summaryrefslogtreecommitdiffstats
path: root/login-utils/su-common.c
diff options
context:
space:
mode:
authorKarel Zak2017-09-07 12:09:17 +0200
committerKarel Zak2017-09-18 11:49:11 +0200
commit13ee2f4d78fd6866cc82b6e237f178752fe60371 (patch)
tree8e090bc56bbc17b55c71646051d8214935100eff /login-utils/su-common.c
parentsu: (pty) simplify stdin usage in poll() (diff)
downloadkernel-qcow2-util-linux-13ee2f4d78fd6866cc82b6e237f178752fe60371.tar.gz
kernel-qcow2-util-linux-13ee2f4d78fd6866cc82b6e237f178752fe60371.tar.xz
kernel-qcow2-util-linux-13ee2f4d78fd6866cc82b6e237f178752fe60371.zip
su: (pty) save child status
Signed-off-by: Karel Zak <kzak@redhat.com>
Diffstat (limited to 'login-utils/su-common.c')
-rw-r--r--login-utils/su-common.c13
1 files changed, 12 insertions, 1 deletions
diff --git a/login-utils/su-common.c b/login-utils/su-common.c
index bc96967be..925cef983 100644
--- a/login-utils/su-common.c
+++ b/login-utils/su-common.c
@@ -133,6 +133,7 @@ struct su_context {
char *old_user; /* orginal user */
pid_t child; /* fork() baby */
+ int childstatus; /* wait() status */
struct sigaction oldact[SIGNALS_IDX_COUNT]; /* original sigactions indexed by SIG*_IDX */
@@ -182,11 +183,18 @@ static void init_tty(struct su_context *su)
get_terminal_name(NULL, &su->tty_name, &su->tty_number);
}
+/*
+ * Note, this function has to be possible call more than once. If the child is
+ * already dead than it returns saved result from the previous call.
+ */
static int wait_for_child(struct su_context *su)
{
pid_t pid = (pid_t) -1;;
int status = 0;
+ if (su->child == (pid_t) -1)
+ return su->childstatus;
+
if (su->child != (pid_t) -1) {
DBG(SIG, ul_debug("waiting for child [%d]...", su->child));
for (;;) {
@@ -212,12 +220,13 @@ static int wait_for_child(struct su_context *su)
DBG(SIG, ul_debug("child %d is dead", su->child));
su->child = (pid_t) -1; /* Don't use the PID anymore! */
+ su->childstatus = status;
} else if (caught_signal)
status = caught_signal + 128;
else
status = 1;
- DBG(SIG, ul_debug("status=%d", status));
+ DBG(SIG, ul_debug("child status=%d", status));
return status;
}
@@ -845,6 +854,8 @@ static void create_watching_parent(struct su_context *su)
else
status = 1;
+ DBG(SIG, ul_debug("final child status=%d", status));
+
if (caught_signal && su->child != (pid_t)-1) {
fprintf(stderr, _("\nSession terminated, killing shell..."));
kill(su->child, SIGTERM);