Loop the waitpid() on EINTR, and save and restore the disposition of
authorguenther <guenther@openbsd.org>
Fri, 23 Oct 2015 04:44:41 +0000 (04:44 +0000)
committerguenther <guenther@openbsd.org>
Fri, 23 Oct 2015 04:44:41 +0000 (04:44 +0000)
SIGINT and SIGQUIT with sigaction() instead of signal() so that all bits
are preserved.

ok deraadt@ millert@

lib/libc/stdlib/system.c

index 3ad0bcd..de32d43 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: system.c,v 1.10 2015/09/14 08:51:07 guenther Exp $ */
+/*     $OpenBSD: system.c,v 1.11 2015/10/23 04:44:41 guenther Exp $ */
 /*
  * Copyright (c) 1988 The Regents of the University of California.
  * All rights reserved.
@@ -30,6 +30,7 @@
 
 #include <sys/types.h>
 #include <sys/wait.h>
+#include <errno.h>
 #include <signal.h>
 #include <stdlib.h>
 #include <unistd.h>
@@ -40,8 +41,8 @@ extern char **environ;
 int
 system(const char *command)
 {
-       pid_t pid;
-       sig_t intsave, quitsave;
+       pid_t pid, cpid;
+       struct sigaction intsave, quitsave;
        sigset_t mask, omask;
        int pstat;
        char *argp[] = {"sh", "-c", NULL, NULL};
@@ -54,7 +55,7 @@ system(const char *command)
        sigemptyset(&mask);
        sigaddset(&mask, SIGCHLD);
        sigprocmask(SIG_BLOCK, &mask, &omask);
-       switch (pid = vfork()) {
+       switch (cpid = vfork()) {
        case -1:                        /* error */
                sigprocmask(SIG_SETMASK, &omask, NULL);
                return(-1);
@@ -64,12 +65,14 @@ system(const char *command)
                _exit(127);
        }
 
-       intsave = signal(SIGINT, SIG_IGN);
-       quitsave = signal(SIGQUIT, SIG_IGN);
-       pid = waitpid(pid, &pstat, 0);
+       sigaction(SIGINT, NULL, &intsave);
+       sigaction(SIGQUIT, NULL, &quitsave);
+       do {
+               pid = waitpid(cpid, &pstat, 0);
+       } while (pid == -1 && errno == EINTR);
        sigprocmask(SIG_SETMASK, &omask, NULL);
-       (void)signal(SIGINT, intsave);
-       (void)signal(SIGQUIT, quitsave);
+       sigaction(SIGINT, &intsave, NULL);
+       sigaction(SIGQUIT, &quitsave, NULL);
        return (pid == -1 ? -1 : pstat);
 }
 DEF_STRONG(system);