1 /* 2 * Copyright 2004-2011, Ingo Weinhold, ingo_weinhold@gmx.de. 3 * Distributed under the terms of the MIT License. 4 */ 5 6 #include <image.h> 7 8 #include <errno.h> 9 #include <pthread.h> 10 #include <stdlib.h> 11 #include <string.h> 12 #include <sys/wait.h> 13 #include <unistd.h> 14 15 #include <errno_private.h> 16 #include <syscall_utils.h> 17 18 19 extern "C" int 20 system(const char *command) 21 { 22 if (!command) 23 return 1; 24 25 const char *argv[] = { "/bin/sh", "-c", command, NULL }; 26 int argc = 3; 27 28 thread_id thread = load_image(argc, argv, (const char **)environ); 29 if (thread < 0) 30 RETURN_AND_SET_ERRNO_TEST_CANCEL(thread); 31 32 // block SIGCHLD ... 33 sigset_t mask, oldMask; 34 sigemptyset(&mask); 35 sigaddset(&mask, SIGCHLD); 36 sigprocmask(SIG_BLOCK, &mask, &oldMask); 37 38 // and ignore SIGINT and SIGQUIT while waiting for completion 39 struct sigaction intSave, quitSave, sa; 40 memset(&sa, 0, sizeof(sa)); 41 sigemptyset(&sa.sa_mask); 42 sa.sa_handler = SIG_IGN; 43 sigaction(SIGINT, &sa, &intSave); 44 sigaction(SIGQUIT, &sa, &quitSave); 45 46 resume_thread(thread); 47 48 int exitStatus; 49 pid_t result; 50 while ((result = waitpid(thread, &exitStatus, 0)) < 0 51 && errno == B_INTERRUPTED) { 52 // waitpid() was interrupted by a signal, retry... 53 } 54 55 // unblock and reset signal handlers 56 sigprocmask(SIG_SETMASK, &oldMask, NULL); 57 sigaction(SIGINT, &intSave, NULL); 58 sigaction(SIGQUIT, &quitSave, NULL); 59 60 if (result < 0) 61 return -1; 62 63 return exitStatus; 64 } 65