]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
su: (pty) save child status
authorKarel Zak <kzak@redhat.com>
Thu, 7 Sep 2017 10:09:17 +0000 (12:09 +0200)
committerKarel Zak <kzak@redhat.com>
Mon, 18 Sep 2017 09:49:11 +0000 (11:49 +0200)
Signed-off-by: Karel Zak <kzak@redhat.com>
login-utils/su-common.c

index bc96967be60832db03eed1c8c5e4ee8f6d8a2b7d..925cef9839104b33a032b12f0c8c5a4396a8c887 100644 (file)
@@ -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);