aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2003-02-28 05:18:55 +0000
committerH. Peter Anvin <hpa@zytor.com>2003-02-28 05:18:55 +0000
commit1c6bf555158e0a3ea31401d1164b717b4f1f2445 (patch)
tree64fba8abd660d170072ffce28bbfe897a2b2cbbc
parent0ff2032c6186ac00f1f63f30f88643c48d46bbd8 (diff)
downloadklibc-1c6bf555158e0a3ea31401d1164b717b4f1f2445.tar.gz
Add system()klibc-0.78
-rw-r--r--klibc/Makefile2
-rw-r--r--klibc/system.c61
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;
+}