]> granicus.if.org Git - shadow/commitdiff
* NEWS, src/su.c: When su receives a signal, wait for the child to
authornekral-guest <nekral-guest@5a98b0ae-9ef6-0310-add3-de5d479b70d7>
Tue, 8 Sep 2009 20:39:15 +0000 (20:39 +0000)
committernekral-guest <nekral-guest@5a98b0ae-9ef6-0310-add3-de5d479b70d7>
Tue, 8 Sep 2009 20:39:15 +0000 (20:39 +0000)
terminate (after sending a SIGTERM), and kill it only if it did
not terminate by itself. No delay will be enforced if the child
cooperates. See http://bugs.gentoo.org/282094
* NEWS, man/su.1.xml: Document su's exit values.

ChangeLog
NEWS
man/su.1.xml
src/su.c

index 7bbc7a4b4e448513d80edf34387e139d9e5f0fdb..027c8b05f3b33fbc56ee0bb2496b42a4a3f6e9e9 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2009-09-08  Nicolas François  <nicolas.francois@centraliens.net>
+
+       * NEWS, src/su.c: When su receives a signal, wait for the child to
+       terminate (after sending a SIGTERM), and kill it only if it did
+       not terminate by itself. No delay will be enforced if the child
+       cooperates. See http://bugs.gentoo.org/282094
+       * NEWS, man/su.1.xml: Document su's exit values.
+
 2009-09-08  Nicolas François  <nicolas.francois@centraliens.net>
 
        * src/useradd.c: The default value for the CREATE_MAIL_SPOOL
diff --git a/NEWS b/NEWS
index 8451ad778153abd8eeff4df2fe49ce9d041bd7ce..dcc0ee289c748ba68d561475513421ae2398ae88 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -6,6 +6,12 @@ shadow-4.1.4.2 -> shadow-4.1.4.3                                               UNRELEASED
   * report usage error to stderr, but report usage help to stdout (and return
     zero) when explicitly requested (e.g. with --help).
 
+- su
+  * Document the su exit values.
+  * When su receives a signal, wait for the child to terminate (after
+    sending a SIGTERM), and kill it only if it did not terminate by itself.
+    No delay will be enforced if the child cooperates.
+
 shadow-4.1.4.1 -> shadow-4.1.4.2                                               2009-07-24
 
 - general
index d965705faa95538d490eefe21e6fca36ef052c16..fc0afed06fbb38d1b9bef87dbbbd4e1abd0634e4 100644 (file)
     </variablelist>
   </refsect1>
 
+  <refsect1 id='exit_values'>
+    <title>EXIT VALUES</title>
+    <para>
+      On success, <command>su</command> returns the exit value of the
+      command it executed.
+    </para>
+    <para>
+      If this command was terminated by a signal, <command>su</command>
+      returns the number of this signal plus 128.
+    </para>
+    <para>
+      If su has to kill the command (because it was asked to terminate,
+      and the command did not terminate in time), <command>su</command>
+      returns 255.
+    </para>
+    <para>
+      Some exit values from <command>su</command> are independent from the
+      executed command:
+      <variablelist>
+       <varlistentry>
+         <term><replaceable>0</replaceable></term>
+         <listitem>
+           <para>success (<option>--help</option> only)</para>
+         </listitem>
+       </varlistentry>
+       <varlistentry>
+         <term><replaceable>1</replaceable></term>
+         <listitem>
+           <para>System or authentication failure</para>
+         </listitem>
+       </varlistentry>
+       <varlistentry>
+         <term><replaceable>126</replaceable></term>
+         <listitem>
+           <para>The requested command was not found</para>
+         </listitem>
+       </varlistentry>
+       <varlistentry>
+         <term><replaceable>127</replaceable></term>
+         <listitem>
+           <para>The requested command could not be executed</para>
+         </listitem>
+       </varlistentry>
+      </variablelist>
+    </para>
+  </refsect1>
+
   <refsect1 id='see_also'>
     <title>SEE ALSO</title>
     <para><citerefentry>
index 716cbf637761dc37f7e9bc9fdbf3707e47d3d6be..072c51d1b76459e4294972b11b156fef0e4de7a9 100644 (file)
--- a/src/su.c
+++ b/src/su.c
@@ -78,6 +78,8 @@
  * Global variables
  */
 char *Prog;
+/* PID of the child, in case it needs to be killed */
+static pid_t pid_child = 0;
 
 /* not needed by sulog.c anymore */
 static char name[BUFSIZ];
@@ -103,11 +105,16 @@ extern size_t newenvc;
 
 /* local function prototypes */
 
+static void execve_shell (const char *shellstr,
+                          char *args[],
+                          char *const envp[]);
+static RETSIGTYPE kill_child (int s);
 #ifndef USE_PAM
-
 static RETSIGTYPE die (int);
 static int iswheel (const char *);
+#endif                         /* !USE_PAM */
 
+#ifndef USE_PAM
 /*
  * die - set or reset termio modes.
  *
@@ -126,7 +133,7 @@ static RETSIGTYPE die (int killed)
 
        if (killed) {
                closelog ();
-               exit (killed);
+               exit (128+killed);
        }
 }
 
@@ -143,6 +150,18 @@ static int iswheel (const char *username)
 }
 #endif                         /* !USE_PAM */
 
+static RETSIGTYPE kill_child (int unused(s))
+{
+       if (0 != pid_child) {
+               (void) kill (pid_child, SIGKILL);
+               (void) fputs (_(" ...killed.\n"), stderr);
+       } else {
+               (void) fputs (_(" ...waiting for child to terminate.\n"),
+                             stderr);
+       }
+       exit (255);
+}
+
 /* borrowed from GNU sh-utils' "su.c" */
 static bool restricted_shell (const char *shellstr)
 {
@@ -252,6 +271,7 @@ static void run_shell (const char *shellstr, char *args[], bool doshell,
                exit (1);
        }
        /* parent only */
+       pid_child = child;
        sigfillset (&ourset);
        if (sigprocmask (SIG_BLOCK, &ourset, NULL) != 0) {
                (void) fprintf (stderr, "%s: signal malfunction\n", Prog);
@@ -293,7 +313,9 @@ static void run_shell (const char *shellstr, char *args[], bool doshell,
        }
 
        if (caught) {
-               fprintf (stderr, "\nSession terminated, killing shell...");
+               (void) fputs ("\n", stderr);
+               (void) fputs (_("Session terminated, terminating shell..."),
+                             stderr);
                kill (child, SIGTERM);
        }
 
@@ -309,10 +331,11 @@ static void run_shell (const char *shellstr, char *args[], bool doshell,
        ret = pam_end (pamh, PAM_SUCCESS);
 
        if (caught) {
-               sleep (2);
-               kill (child, SIGKILL);
-               fprintf (stderr, " ...killed.\n");
-               exit (-1);
+               (void) signal (SIGALRM, kill_child);
+               (void) alarm (2);
+
+               (void) wait (&status);
+               (void) fputs (_(" ...terminated.\n"), stderr);
        }
 
        exit ((0 != WIFEXITED (status)) ? WEXITSTATUS (status)