123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263 |
- #include <stdio.h>
- #include <string.h>
- #include <stddef.h>
- #include <signal.h>
- #include <unistd.h>
- #include <sys/wait.h>
- #include <stdlib.h>
- #include <paths.h>
- #ifdef __UCLIBC_HAS_THREADS_NATIVE__
- #include <sched.h>
- #include <errno.h>
- #include <bits/libc-lock.h>
- #include <sysdep-cancel.h>
- #endif
- extern __typeof(system) __libc_system;
- #if !defined __UCLIBC_HAS_THREADS_NATIVE__
- #include <sys/syscall.h>
- int __libc_system(const char *command)
- {
- int wait_val, pid;
- struct sigaction sa, save_quit, save_int;
- sigset_t save_mask;
- if (command == 0)
- return 1;
- memset(&sa, 0, sizeof(sa));
- sa.sa_handler = SIG_IGN;
-
-
- sigaction(SIGQUIT, &sa, &save_quit);
- sigaction(SIGINT, &sa, &save_int);
- __sigaddset(&sa.sa_mask, SIGCHLD);
- sigprocmask(SIG_BLOCK, &sa.sa_mask, &save_mask);
- if ((pid = vfork()) < 0) {
- wait_val = -1;
- goto out;
- }
- if (pid == 0) {
- sigaction(SIGQUIT, &save_quit, NULL);
- sigaction(SIGINT, &save_int, NULL);
- sigprocmask(SIG_SETMASK, &save_mask, NULL);
- execl(_PATH_BSHELL, "sh", "-c", command, (char *) 0);
- _exit(127);
- }
- #if 0
- __printf("Waiting for child %d\n", pid);
- #endif
- if (__wait4_nocancel(pid, &wait_val, 0, 0) == -1)
- wait_val = -1;
- out:
- sigaction(SIGQUIT, &save_quit, NULL);
- sigaction(SIGINT, &save_int, NULL);
- sigprocmask(SIG_SETMASK, &save_mask, NULL);
- return wait_val;
- }
- #else
- libc_hidden_proto(sigaction)
- libc_hidden_proto(waitpid)
- #if defined __ia64__
- # define FORK() \
- INLINE_SYSCALL (clone2, 6, CLONE_PARENT_SETTID | SIGCHLD, NULL, 0, \
- &pid, NULL, NULL)
- #elif defined __sparc__
- # define FORK() \
- INLINE_CLONE_SYSCALL (CLONE_PARENT_SETTID | SIGCHLD, 0, &pid, NULL, NULL)
- #else
- # define FORK() \
- INLINE_SYSCALL (clone, 3, CLONE_PARENT_SETTID | SIGCHLD, 0, &pid)
- #endif
- static void cancel_handler (void *arg);
- # define CLEANUP_HANDLER \
- __libc_cleanup_region_start (1, cancel_handler, &pid)
- # define CLEANUP_RESET \
- __libc_cleanup_region_end (0)
- static struct sigaction intr, quit;
- static int sa_refcntr;
- __libc_lock_define_initialized (static, lock);
- # define DO_LOCK() __libc_lock_lock (lock)
- # define DO_UNLOCK() __libc_lock_unlock (lock)
- # define INIT_LOCK() ({ __libc_lock_init (lock); sa_refcntr = 0; })
- # define ADD_REF() sa_refcntr++
- # define SUB_REF() --sa_refcntr
- static int
- do_system (const char *line)
- {
- int status, save;
- pid_t pid;
- struct sigaction sa;
- sigset_t omask;
- memset(&sa, 0, sizeof(sa));
- sa.sa_handler = SIG_IGN;
-
-
- DO_LOCK ();
- if (ADD_REF () == 0)
- {
- if (sigaction (SIGINT, &sa, &intr) < 0)
- {
- SUB_REF ();
- goto out;
- }
- if (sigaction (SIGQUIT, &sa, &quit) < 0)
- {
- save = errno;
- SUB_REF ();
- goto out_restore_sigint;
- }
- }
- DO_UNLOCK ();
-
- __sigaddset (&sa.sa_mask, SIGCHLD);
- save = errno;
- if (sigprocmask (SIG_BLOCK, &sa.sa_mask, &omask) < 0)
- {
- {
- DO_LOCK ();
- if (SUB_REF () == 0)
- {
- save = errno;
- (void) sigaction (SIGQUIT, &quit, (struct sigaction *) NULL);
- out_restore_sigint:
- (void) sigaction (SIGINT, &intr, (struct sigaction *) NULL);
- __set_errno (save);
- }
- out:
- DO_UNLOCK ();
- return -1;
- }
- }
- CLEANUP_HANDLER;
- pid = FORK ();
- if (pid == (pid_t) 0)
- {
-
- const char *new_argv[4];
- new_argv[0] = _PATH_BSHELL;
- new_argv[1] = "-c";
- new_argv[2] = line;
- new_argv[3] = NULL;
-
- (void) sigaction (SIGINT, &intr, (struct sigaction *) NULL);
- (void) sigaction (SIGQUIT, &quit, (struct sigaction *) NULL);
- (void) sigprocmask (SIG_SETMASK, &omask, (sigset_t *) NULL);
- INIT_LOCK ();
-
- (void) execve (_PATH_BSHELL, (char *const *) new_argv, __environ);
- _exit (127);
- }
- else if (pid < (pid_t) 0)
-
- status = -1;
- else
-
- {
-
- if (TEMP_FAILURE_RETRY (waitpid (pid, &status, 0)) != pid)
- status = -1;
- }
- CLEANUP_RESET;
- save = errno;
- DO_LOCK ();
- if ((SUB_REF () == 0
- && (sigaction (SIGINT, &intr, (struct sigaction *) NULL)
- | sigaction (SIGQUIT, &quit, (struct sigaction *) NULL)) != 0)
- || sigprocmask (SIG_SETMASK, &omask, (sigset_t *) NULL) != 0)
- {
- status = -1;
- }
- DO_UNLOCK ();
- return status;
- }
- int
- __libc_system (const char *line)
- {
- if (line == NULL)
-
- return do_system ("exit 0") == 0;
- if (SINGLE_THREAD_P)
- return do_system (line);
- int oldtype = LIBC_CANCEL_ASYNC ();
- int result = do_system (line);
- LIBC_CANCEL_RESET (oldtype);
- return result;
- }
- static void
- cancel_handler (void *arg)
- {
- pid_t child = *(pid_t *) arg;
- INTERNAL_SYSCALL_DECL (err);
- INTERNAL_SYSCALL (kill, err, 2, child, SIGKILL);
- TEMP_FAILURE_RETRY (waitpid (child, NULL, 0));
- DO_LOCK ();
- if (SUB_REF () == 0)
- {
- (void) sigaction (SIGQUIT, &quit, (struct sigaction *) NULL);
- (void) sigaction (SIGINT, &intr, (struct sigaction *) NULL);
- }
- DO_UNLOCK ();
- }
- #endif
- #ifdef IS_IN_libc
- weak_alias(__libc_system,system)
- #endif
|