Extra files to distribute in sysdeps/posix.
[glibc/history.git] / sysdeps / posix / system.c
blobf63dde4dae4bea009e2cb78f35b16547361fa780
1 /* Copyright (C) 1991-2000, 2002, 2003, 2005 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 #ifdef NO_WAITPID
147 pid_t child;
150 child = __wait (&status);
151 if (child <= -1 && errno != EINTR)
153 status = -1;
154 break;
156 /* Note that pid cannot be <= -1 and therefore the loop continues
157 when __wait returned with EINTR. */
159 while (child != pid);
160 #else
161 /* Note the system() is a cancellation point. But since we call
162 waitpid() which itself is a cancellation point we do not
163 have to do anything here. */
164 if (TEMP_FAILURE_RETRY (__waitpid (pid, &status, 0)) != pid)
165 status = -1;
166 #endif
169 #ifdef CLEANUP_HANDLER
170 CLEANUP_RESET;
171 #endif
173 save = errno;
174 DO_LOCK ();
175 if ((SUB_REF () == 0
176 && (__sigaction (SIGINT, &intr, (struct sigaction *) NULL)
177 | __sigaction (SIGQUIT, &quit, (struct sigaction *) NULL)) != 0)
178 || __sigprocmask (SIG_SETMASK, &omask, (sigset_t *) NULL) != 0)
180 #ifndef _LIBC
181 /* glibc cannot be used on systems without waitpid. */
182 if (errno == ENOSYS)
183 __set_errno (save);
184 else
185 #endif
186 status = -1;
188 DO_UNLOCK ();
190 return status;
194 __libc_system (const char *line)
196 if (line == NULL)
197 /* Check that we have a command processor available. It might
198 not be available after a chroot(), for example. */
199 return do_system ("exit 0") == 0;
201 if (SINGLE_THREAD_P)
202 return do_system (line);
204 int oldtype = LIBC_CANCEL_ASYNC ();
206 int result = do_system (line);
208 LIBC_CANCEL_RESET (oldtype);
210 return result;
212 weak_alias (__libc_system, system)