summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorjraynard <jraynard@FreeBSD.org>1996-06-05 00:08:54 +0000
committerjraynard <jraynard@FreeBSD.org>1996-06-05 00:08:54 +0000
commitf12d02958af4923cccf62583718f39baa06fa941 (patch)
tree10283a97de8afbdc5464824310abeebd04f2f5f2 /lib
parent01b73f855a2b4735f46664d4ccf4d1319aad3e54 (diff)
downloadFreeBSD-src-f12d02958af4923cccf62583718f39baa06fa941.zip
FreeBSD-src-f12d02958af4923cccf62583718f39baa06fa941.tar.gz
Submitted by: (based on code in "Advanced Programming in the Unix Environment"
by W.Richard Ste vens. EINTR handling suggested by bde@freebsd.org). Code cleanup: 1. Add missing return type. 2. Replace 'union wait' by int. 3. Use Posix-style signal handling instead of signal(). 4. Use fork() instead of deprecated vfork(). 5. Block signals before fork()'ing, instead of after. 6. Return -1 if fork() fails, instead of 0. 7. Add EINTR handling for waitpid() call. Also add claim of Posix conformance to man page.
Diffstat (limited to 'lib')
-rw-r--r--lib/libc/stdlib/system.33
-rw-r--r--lib/libc/stdlib/system.c51
2 files changed, 36 insertions, 18 deletions
diff --git a/lib/libc/stdlib/system.3 b/lib/libc/stdlib/system.3
index 44aaf0c..9b82e7b 100644
--- a/lib/libc/stdlib/system.3
+++ b/lib/libc/stdlib/system.3
@@ -91,3 +91,6 @@ The
function
conforms to
.St -ansiC .
+and is expected to be
+.St -p1003.2
+compatible.
diff --git a/lib/libc/stdlib/system.c b/lib/libc/stdlib/system.c
index c438f17..3bae36a 100644
--- a/lib/libc/stdlib/system.c
+++ b/lib/libc/stdlib/system.c
@@ -42,35 +42,50 @@ static char sccsid[] = "@(#)system.c 8.1 (Berkeley) 6/4/93";
#include <stddef.h>
#include <unistd.h>
#include <paths.h>
+#include <errno.h>
-system(command)
+int system(command)
const char *command;
{
- union wait pstat;
pid_t pid;
- int omask;
- sig_t intsave, quitsave;
+ int pstat;
+ struct sigaction ign, intact, quitact;
+ sigset_t newsigblock, oldsigblock;
if (!command) /* just checking... */
return(1);
- omask = sigblock(sigmask(SIGCHLD));
- switch(pid = vfork()) {
+ /*
+ * 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);
+ sigprocmask(SIG_BLOCK, &newsigblock, &oldsigblock);
+ switch(pid = fork()) {
case -1: /* error */
- (void)sigsetmask(omask);
- pstat.w_status = 0;
- pstat.w_retcode = 127;
- return(pstat.w_status);
+ break;
case 0: /* child */
- (void)sigsetmask(omask);
+ /*
+ * 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 */
+ do {
+ pid = waitpid(pid, &pstat, 0);
+ } while (pid == -1 && errno == EINTR);
+ break;
}
- intsave = signal(SIGINT, SIG_IGN);
- quitsave = signal(SIGQUIT, SIG_IGN);
- pid = waitpid(pid, (int *)&pstat, 0);
- (void)sigsetmask(omask);
- (void)signal(SIGINT, intsave);
- (void)signal(SIGQUIT, quitsave);
- return(pid == -1 ? -1 : pstat.w_status);
+ (void)sigaction(SIGINT, &intact, NULL);
+ (void)sigaction(SIGQUIT, &quitact, NULL);
+ (void)sigprocmask(SIG_SETMASK, &oldsigblock, NULL);
+ return(pid == -1 ? -1 : pstat);
}
OpenPOWER on IntegriCloud