2.9
[glibc/nacl-glibc.git] / sysdeps / posix / system.c
blobe78195ef822342d7afcc7784f8a72e7c0f0366f9
1 /* Copyright (C) 1991-2000,2002,2003,2005,2007 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
4 The GNU C Library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the License, or (at your option) any later version.
9 The GNU C Library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Lesser General Public License for more details.
14 You should have received a copy of the GNU Lesser General Public
15 License along with the GNU C Library; if not, write to the Free
16 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
17 02111-1307 USA. */
19 #include <errno.h>
20 #include <signal.h>
21 #include <stddef.h>
22 #include <stdlib.h>
23 #include <unistd.h>
24 #include <sys/types.h>
25 #include <sys/wait.h>
26 #include <bits/libc-lock.h>
27 #include <sysdep-cancel.h>
30 #define SHELL_PATH "/bin/sh" /* Path of the shell. */
31 #define SHELL_NAME "sh" /* Name to give it. */
34 #ifdef _LIBC_REENTRANT
35 static struct sigaction intr, quit;
36 static int sa_refcntr;
37 __libc_lock_define_initialized (static, lock);
39 # define DO_LOCK() __libc_lock_lock (lock)
40 # define DO_UNLOCK() __libc_lock_unlock (lock)
41 # define INIT_LOCK() ({ __libc_lock_init (lock); sa_refcntr = 0; })
42 # define ADD_REF() sa_refcntr++
43 # define SUB_REF() --sa_refcntr
44 #else
45 # define DO_LOCK()
46 # define DO_UNLOCK()
47 # define INIT_LOCK()
48 # define ADD_REF() 0
49 # define SUB_REF() 0
50 #endif
53 /* Execute LINE as a shell command, returning its status. */
54 static int
55 do_system (const char *line)
57 int status, save;
58 pid_t pid;
59 struct sigaction sa;
60 #ifndef _LIBC_REENTRANT
61 struct sigaction intr, quit;
62 #endif
63 sigset_t omask;
65 sa.sa_handler = SIG_IGN;
66 sa.sa_flags = 0;
67 __sigemptyset (&sa.sa_mask);
69 DO_LOCK ();
70 if (ADD_REF () == 0)
72 if (__sigaction (SIGINT, &sa, &intr) < 0)
74 SUB_REF ();
75 goto out;
77 if (__sigaction (SIGQUIT, &sa, &quit) < 0)
79 save = errno;
80 SUB_REF ();
81 goto out_restore_sigint;
84 DO_UNLOCK ();
86 /* We reuse the bitmap in the 'sa' structure. */
87 __sigaddset (&sa.sa_mask, SIGCHLD);
88 save = errno;
89 if (__sigprocmask (SIG_BLOCK, &sa.sa_mask, &omask) < 0)
91 #ifndef _LIBC
92 if (errno == ENOSYS)
93 __set_errno (save);
94 else
95 #endif
97 DO_LOCK ();
98 if (SUB_REF () == 0)
100 save = errno;
101 (void) __sigaction (SIGQUIT, &quit, (struct sigaction *) NULL);
102 out_restore_sigint:
103 (void) __sigaction (SIGINT, &intr, (struct sigaction *) NULL);
104 __set_errno (save);
106 out:
107 DO_UNLOCK ();
108 return -1;
112 #ifdef CLEANUP_HANDLER
113 CLEANUP_HANDLER;
114 #endif
116 #ifdef FORK
117 pid = FORK ();
118 #else
119 pid = __fork ();
120 #endif
121 if (pid == (pid_t) 0)
123 /* Child side. */
124 const char *new_argv[4];
125 new_argv[0] = SHELL_NAME;
126 new_argv[1] = "-c";
127 new_argv[2] = line;
128 new_argv[3] = NULL;
130 /* Restore the signals. */
131 (void) __sigaction (SIGINT, &intr, (struct sigaction *) NULL);
132 (void) __sigaction (SIGQUIT, &quit, (struct sigaction *) NULL);
133 (void) __sigprocmask (SIG_SETMASK, &omask, (sigset_t *) NULL);
134 INIT_LOCK ();
136 /* Exec the shell. */
137 (void) __execve (SHELL_PATH, (char *const *) new_argv, __environ);
138 _exit (127);
140 else if (pid < (pid_t) 0)
141 /* The fork failed. */
142 status = -1;
143 else
144 /* Parent side. */
146 /* Note the system() is a cancellation point. But since we call
147 waitpid() which itself is a cancellation point we do not
148 have to do anything here. */
149 if (TEMP_FAILURE_RETRY (__waitpid (pid, &status, 0)) != pid)
150 status = -1;
153 #ifdef CLEANUP_HANDLER
154 CLEANUP_RESET;
155 #endif
157 save = errno;
158 DO_LOCK ();
159 if ((SUB_REF () == 0
160 && (__sigaction (SIGINT, &intr, (struct sigaction *) NULL)
161 | __sigaction (SIGQUIT, &quit, (struct sigaction *) NULL)) != 0)
162 || __sigprocmask (SIG_SETMASK, &omask, (sigset_t *) NULL) != 0)
164 #ifndef _LIBC
165 /* glibc cannot be used on systems without waitpid. */
166 if (errno == ENOSYS)
167 __set_errno (save);
168 else
169 #endif
170 status = -1;
172 DO_UNLOCK ();
174 return status;
178 __libc_system (const char *line)
180 if (line == NULL)
181 /* Check that we have a command processor available. It might
182 not be available after a chroot(), for example. */
183 return do_system ("exit 0") == 0;
185 if (SINGLE_THREAD_P)
186 return do_system (line);
188 int oldtype = LIBC_CANCEL_ASYNC ();
190 int result = do_system (line);
192 LIBC_CANCEL_RESET (oldtype);
194 return result;
196 weak_alias (__libc_system, system)