diff --git a/lib/libc/stdlib/system.c b/lib/libc/stdlib/system.c index b552a63fd904..64a544714564 100644 --- a/lib/libc/stdlib/system.c +++ b/lib/libc/stdlib/system.c @@ -39,6 +39,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -56,37 +57,36 @@ __system(const char *command) if (!command) /* just checking... */ return(1); - /* - * Ignore SIGINT and SIGQUIT, block SIGCHLD. Remember to save - * existing signal dispositions. - */ - ign.sa_handler = SIG_IGN; - (void)sigemptyset(&ign.sa_mask); - ign.sa_flags = 0; - (void)_sigaction(SIGINT, &ign, &intact); - (void)_sigaction(SIGQUIT, &ign, &quitact); (void)sigemptyset(&newsigblock); (void)sigaddset(&newsigblock, SIGCHLD); (void)_sigprocmask(SIG_BLOCK, &newsigblock, &oldsigblock); - switch(pid = fork()) { + switch(pid = vfork()) { case -1: /* error */ - break; + (void)_sigprocmask(SIG_SETMASK, &oldsigblock, NULL); + return (-1); case 0: /* child */ /* * Restore original signal dispositions and exec the command. */ - (void)_sigaction(SIGINT, &intact, NULL); - (void)_sigaction(SIGQUIT, &quitact, NULL); (void)_sigprocmask(SIG_SETMASK, &oldsigblock, NULL); execl(_PATH_BSHELL, "sh", "-c", command, (char *)NULL); _exit(127); - default: /* parent */ - savedpid = pid; - do { - pid = _wait4(savedpid, &pstat, 0, (struct rusage *)0); - } while (pid == -1 && errno == EINTR); - break; } + /* + * If we are running means that the child has either completed + * its execve, or has failed. + * Block SIGINT/QUIT because sh -c handles it and wait for + * it to clean up. + */ + memset(&ign, 0, sizeof(ign)); + ign.sa_handler = SIG_IGN; + (void)sigemptyset(&ign.sa_mask); + (void)_sigaction(SIGINT, &ign, &intact); + (void)_sigaction(SIGQUIT, &ign, &quitact); + savedpid = pid; + do { + pid = _wait4(savedpid, &pstat, 0, (struct rusage *)0); + } while (pid == -1 && errno == EINTR); (void)_sigaction(SIGINT, &intact, NULL); (void)_sigaction(SIGQUIT, &quitact, NULL); (void)_sigprocmask(SIG_SETMASK, &oldsigblock, NULL);