2 * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org>
4 * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
13 #ifdef __UCLIBC_HAS_THREADS_NATIVE__
16 #include <bits/libc-lock.h>
17 #include <sysdep-cancel.h>
21 /* TODO: the cancellable version breaks on sparc currently,
22 * need to figure out why still
24 #if !defined __UCLIBC_HAS_THREADS_NATIVE__ || defined __sparc__
25 /* uClinux-2.0 has vfork, but Linux 2.0 doesn't */
26 #include <sys/syscall.h>
31 extern __typeof(system) __libc_system;
32 int __libc_system(const char *command)
35 __sighandler_t save_quit, save_int, save_chld;
40 save_quit = signal(SIGQUIT, SIG_IGN);
41 save_int = signal(SIGINT, SIG_IGN);
42 save_chld = signal(SIGCHLD, SIG_DFL);
44 if ((pid = vfork()) < 0) {
45 signal(SIGQUIT, save_quit);
46 signal(SIGINT, save_int);
47 signal(SIGCHLD, save_chld);
51 signal(SIGQUIT, SIG_DFL);
52 signal(SIGINT, SIG_DFL);
53 signal(SIGCHLD, SIG_DFL);
55 execl("/bin/sh", "sh", "-c", command, (char *) 0);
58 /* Signals are not absolutly guarenteed with vfork */
59 signal(SIGQUIT, SIG_IGN);
60 signal(SIGINT, SIG_IGN);
63 __printf("Waiting for child %d\n", pid);
66 if (wait4(pid, &wait_val, 0, 0) == -1)
69 signal(SIGQUIT, save_quit);
70 signal(SIGINT, save_int);
71 signal(SIGCHLD, save_chld);
75 /* We have to and actually can handle cancelable system(). The big
76 problem: we have to kill the child process if necessary. To do
77 this a cleanup handler has to be registered and is has to be able
78 to find the PID of the child. The main problem is to reliable have
79 the PID when needed. It is not necessary for the parent thread to
80 return. It might still be in the kernel when the cancellation
81 request comes. Therefore we have to use the clone() calls ability
82 to have the kernel write the PID into the user-level variable. */
84 libc_hidden_proto(sigaction)
85 libc_hidden_proto(waitpid)
89 INLINE_SYSCALL (clone2, 6, CLONE_PARENT_SETTID | SIGCHLD, NULL, 0, \
91 #elif defined __sparc__
93 INLINE_CLONE_SYSCALL (CLONE_PARENT_SETTID | SIGCHLD, 0, &pid, NULL, NULL)
94 #elif defined __s390__
96 INLINE_SYSCALL (clone, 3, 0, CLONE_PARENT_SETTID | SIGCHLD, &pid)
99 INLINE_SYSCALL (clone, 3, CLONE_PARENT_SETTID | SIGCHLD, 0, &pid)
102 static void cancel_handler (void *arg);
104 # define CLEANUP_HANDLER \
105 __libc_cleanup_region_start (1, cancel_handler, &pid)
107 # define CLEANUP_RESET \
108 __libc_cleanup_region_end (0)
110 static struct sigaction intr, quit;
111 static int sa_refcntr;
112 __libc_lock_define_initialized (static, lock);
114 # define DO_LOCK() __libc_lock_lock (lock)
115 # define DO_UNLOCK() __libc_lock_unlock (lock)
116 # define INIT_LOCK() ({ __libc_lock_init (lock); sa_refcntr = 0; })
117 # define ADD_REF() sa_refcntr++
118 # define SUB_REF() --sa_refcntr
120 /* Execute LINE as a shell command, returning its status. */
122 do_system (const char *line)
129 sa.sa_handler = SIG_IGN;
131 __sigemptyset (&sa.sa_mask);
136 if (sigaction (SIGINT, &sa, &intr) < 0)
141 if (sigaction (SIGQUIT, &sa, &quit) < 0)
145 goto out_restore_sigint;
150 /* We reuse the bitmap in the 'sa' structure. */
151 __sigaddset (&sa.sa_mask, SIGCHLD);
153 if (sigprocmask (SIG_BLOCK, &sa.sa_mask, &omask) < 0)
160 (void) sigaction (SIGQUIT, &quit, (struct sigaction *) NULL);
162 (void) sigaction (SIGINT, &intr, (struct sigaction *) NULL);
174 if (pid == (pid_t) 0)
177 const char *new_argv[4];
178 new_argv[0] = "/bin/sh";
183 /* Restore the signals. */
184 (void) sigaction (SIGINT, &intr, (struct sigaction *) NULL);
185 (void) sigaction (SIGQUIT, &quit, (struct sigaction *) NULL);
186 (void) sigprocmask (SIG_SETMASK, &omask, (sigset_t *) NULL);
189 /* Exec the shell. */
190 (void) execve ("/bin/sh", (char *const *) new_argv, __environ);
193 else if (pid < (pid_t) 0)
194 /* The fork failed. */
199 /* Note the system() is a cancellation point. But since we call
200 waitpid() which itself is a cancellation point we do not
201 have to do anything here. */
202 if (TEMP_FAILURE_RETRY (waitpid (pid, &status, 0)) != pid)
211 && (sigaction (SIGINT, &intr, (struct sigaction *) NULL)
212 | sigaction (SIGQUIT, &quit, (struct sigaction *) NULL)) != 0)
213 || sigprocmask (SIG_SETMASK, &omask, (sigset_t *) NULL) != 0)
224 __libc_system (const char *line)
227 /* Check that we have a command processor available. It might
228 not be available after a chroot(), for example. */
229 return do_system ("exit 0") == 0;
232 return do_system (line);
234 int oldtype = LIBC_CANCEL_ASYNC ();
236 int result = do_system (line);
238 LIBC_CANCEL_RESET (oldtype);
244 /* The cancellation handler. */
246 cancel_handler (void *arg)
248 pid_t child = *(pid_t *) arg;
250 INTERNAL_SYSCALL_DECL (err);
251 INTERNAL_SYSCALL (kill, err, 2, child, SIGKILL);
253 TEMP_FAILURE_RETRY (waitpid (child, NULL, 0));
259 (void) sigaction (SIGQUIT, &quit, (struct sigaction *) NULL);
260 (void) sigaction (SIGINT, &intr, (struct sigaction *) NULL);
267 weak_alias(__libc_system,system)