summaryrefslogtreecommitdiffstats
path: root/login-utils/su-common.c
diff options
context:
space:
mode:
authorOndrej Oprala2013-05-17 10:50:58 +0200
committerKarel Zak2013-06-07 12:00:01 +0200
commit8960f3ae5f4d72be88ee76e50417785e836b35e8 (patch)
tree8c79fb3c392fc66112ab879b38ccfd73cc1f2d5b /login-utils/su-common.c
parentdocs: improve grammar and consistency of comments in login.c (diff)
downloadkernel-qcow2-util-linux-8960f3ae5f4d72be88ee76e50417785e836b35e8.tar.gz
kernel-qcow2-util-linux-8960f3ae5f4d72be88ee76e50417785e836b35e8.tar.xz
kernel-qcow2-util-linux-8960f3ae5f4d72be88ee76e50417785e836b35e8.zip
su: fix exit status if terminated by signal
[kzak@redhat.com: - add comment] Signed-off-by: Ondrej Oprala <ooprala@redhat.com> Signed-off-by: Karel Zak <kzak@redhat.com>
Diffstat (limited to 'login-utils/su-common.c')
-rw-r--r--login-utils/su-common.c56
1 files changed, 41 insertions, 15 deletions
diff --git a/login-utils/su-common.c b/login-utils/su-common.c
index 8b08df16c..6df176382 100644
--- a/login-utils/su-common.c
+++ b/login-utils/su-common.c
@@ -232,9 +232,9 @@ cleanup_pam (int retcode)
/* Signal handler for parent process. */
static void
-su_catch_sig (int sig __attribute__((__unused__)))
+su_catch_sig (int sig)
{
- caught_signal = true;
+ caught_signal = sig;
}
/* Export env variables declared by PAM modules. */
@@ -258,6 +258,7 @@ create_watching_parent (void)
{
pid_t child;
sigset_t ourset;
+ struct sigaction oldact[3];
int status = 0;
int retval;
@@ -312,13 +313,13 @@ create_watching_parent (void)
}
if (!caught_signal && (sigaddset(&ourset, SIGTERM)
|| sigaddset(&ourset, SIGALRM)
- || sigaction(SIGTERM, &action, NULL)
+ || sigaction(SIGTERM, &action, &oldact[0])
|| sigprocmask(SIG_UNBLOCK, &ourset, NULL))) {
warn (_("cannot set signal handler"));
caught_signal = true;
}
- if (!caught_signal && !same_session && (sigaction(SIGINT, &action, NULL)
- || sigaction(SIGQUIT, &action, NULL)))
+ if (!caught_signal && !same_session && (sigaction(SIGINT, &action, &oldact[1])
+ || sigaction(SIGQUIT, &action, &oldact[2])))
{
warn (_("cannot set signal handler"));
caught_signal = true;
@@ -341,17 +342,21 @@ create_watching_parent (void)
break;
}
if (pid != (pid_t)-1)
- if (WIFSIGNALED (status))
- {
- status = WTERMSIG (status) + 128;
- if (WCOREDUMP (status))
- fprintf (stderr, _("%s (core dumped)\n"),
- strsignal (WTERMSIG (status)));
- }
- else
- status = WEXITSTATUS (status);
+ {
+ if (WIFSIGNALED (status))
+ {
+ status = WTERMSIG (status) + 128;
+ if (WCOREDUMP (status))
+ fprintf (stderr, _("%s (core dumped)\n"),
+ strsignal (WTERMSIG (status)));
+ }
+ else
+ status = WEXITSTATUS (status);
+ }
+ else if (caught_signal)
+ status = caught_signal + 128;
else
- status = 1;
+ status = 1;
}
else
status = 1;
@@ -369,6 +374,27 @@ create_watching_parent (void)
sleep (2);
kill (child, SIGKILL);
fprintf (stderr, _(" ...killed.\n"));
+
+ /* Let's terminate itself with the received signal.
+ *
+ * It seems that shells use WIFSIGNALED() rather than our exit status
+ * value to detect situations when is necessary to cleanup (reset)
+ * terminal settings (kzak -- Jun 2013).
+ */
+ switch (caught_signal) {
+ case SIGTERM:
+ sigaction(SIGTERM, &oldact[0], NULL);
+ break;
+ case SIGINT:
+ sigaction(SIGINT, &oldact[1], NULL);
+ break;
+ case SIGQUIT:
+ sigaction(SIGQUIT, &oldact[2], NULL);
+ break;
+ default:
+ break;
+ }
+ kill(0, caught_signal);
}
exit (status);
}