diff options
author | Ondrej Oprala | 2013-05-17 10:50:58 +0200 |
---|---|---|
committer | Karel Zak | 2013-06-07 12:00:01 +0200 |
commit | 8960f3ae5f4d72be88ee76e50417785e836b35e8 (patch) | |
tree | 8c79fb3c392fc66112ab879b38ccfd73cc1f2d5b /login-utils | |
parent | docs: improve grammar and consistency of comments in login.c (diff) | |
download | kernel-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')
-rw-r--r-- | login-utils/su-common.c | 56 | ||||
-rw-r--r-- | login-utils/su.1 | 9 |
2 files changed, 50 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); } diff --git a/login-utils/su.1 b/login-utils/su.1 index eab1a6f7f..e48a4f34c 100644 --- a/login-utils/su.1 +++ b/login-utils/su.1 @@ -135,6 +135,15 @@ Display help text and exit. .TP \fB\-\-version\fR Display version information and exit. +.SH SIGNALS +Upon receiving either +.BR SIGINT , +.BR SIGQUIT +or +.BR SIGTERM , +.BR su +terminates it's child and afterwards terminates itself with +the received signal. .SH CONFIG FILES .B su reads the |