+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
* 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
</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>
* 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];
/* 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.
*
if (killed) {
closelog ();
- exit (killed);
+ exit (128+killed);
}
}
}
#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)
{
exit (1);
}
/* parent only */
+ pid_child = child;
sigfillset (&ourset);
if (sigprocmask (SIG_BLOCK, &ourset, NULL) != 0) {
(void) fprintf (stderr, "%s: signal malfunction\n", Prog);
}
if (caught) {
- fprintf (stderr, "\nSession terminated, killing shell...");
+ (void) fputs ("\n", stderr);
+ (void) fputs (_("Session terminated, terminating shell..."),
+ stderr);
kill (child, SIGTERM);
}
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)