diff options
author | H. Peter Anvin <hpa@zytor.com> | 2003-02-28 05:18:55 +0000 |
---|---|---|
committer | H. Peter Anvin <hpa@zytor.com> | 2003-02-28 05:18:55 +0000 |
commit | 1c6bf555158e0a3ea31401d1164b717b4f1f2445 (patch) | |
tree | 64fba8abd660d170072ffce28bbfe897a2b2cbbc | |
parent | 0ff2032c6186ac00f1f63f30f88643c48d46bbd8 (diff) | |
download | klibc-1c6bf555158e0a3ea31401d1164b717b4f1f2445.tar.gz |
Add system()klibc-0.78
-rw-r--r-- | klibc/Makefile | 2 | ||||
-rw-r--r-- | klibc/system.c | 61 |
2 files changed, 62 insertions, 1 deletions
diff --git a/klibc/Makefile b/klibc/Makefile index 7fad8499b8337..f5143e28e7a49 100644 --- a/klibc/Makefile +++ b/klibc/Makefile @@ -17,7 +17,7 @@ LIBOBJS = vsnprintf.o snprintf.o vsprintf.o sprintf.o \ strtoimax.o strtoumax.o \ globals.o exitc.o atexit.o onexit.o \ execl.o execle.o execv.o execvpe.o execvp.o execlp.o execlpe.o \ - fork.o wait.o wait3.o waitpid.o setpgrp.o \ + fork.o wait.o wait3.o waitpid.o system.o setpgrp.o \ printf.o vprintf.o fprintf.o vfprintf.o perror.o \ fopen.o fread.o fread2.o fgetc.o fgets.o \ fwrite.o fwrite2.o fputc.o fputs.o puts.o \ diff --git a/klibc/system.c b/klibc/system.c new file mode 100644 index 0000000000000..643bf5e1ccd3b --- /dev/null +++ b/klibc/system.c @@ -0,0 +1,61 @@ +/* + * system.c + * + * The system() function. If this turns out to actually be *used*, + * we may want to try to detect the very simple cases (no shell magic) + * and handle them internally, instead of requiring that /bin/sh be + * present. + */ + +#include <errno.h> +#include <stdlib.h> +#include <unistd.h> +#include <signal.h> +#include <sys/wait.h> + +int system(const char *string) +{ + pid_t pid; + struct sigaction ignore, old_int, old_quit; + sigset_t masked, oldmask; + static const char *argv[] = { "/bin/sh", "-c", NULL, NULL }; + int status; + + /* Block SIGCHLD and ignore SIGINT and SIGQUIT */ + /* Do this before the fork() to avoid races */ + + ignore.sa_handler = SIG_IGN; + sigemptyset(&ignore.sa_mask); + ignore.sa_flags = 0; + sigaction(SIGINT, &ignore, &old_int); + sigaction(SIGQUIT, &ignore, &old_quit); + + sigemptyset(&masked); + sigaddset(&masked, SIGCHLD); + sigprocmask(SIG_BLOCK, &masked, &oldmask); + + pid = fork(); + + if ( pid < 0 ) + return -1; + else if ( pid == 0 ) { + sigaction(SIGINT, &old_int, NULL); + sigaction(SIGQUIT, &old_quit, NULL); + sigprocmask(SIG_SETMASK, &oldmask, NULL); + + argv[2] = string; + + execve(argv[0], (char * const *)argv, (char * const *)environ); + _exit(127); + } + + /* else... */ + + waitpid(pid, &status, 0); + + sigaction(SIGINT, &old_int, NULL); + sigaction(SIGQUIT, &old_quit, NULL); + sigprocmask(SIG_SETMASK, &oldmask, NULL); + + return status; +} |