(CFLAGS-tst-align.c): Add -mpreferred-stack-boundary=4.
[glibc.git] / sysdeps / posix / system.c
blob85483133146b6a175551c57fda4f57d5641388b9
1 /* Copyright (C) 1991-2000, 2002, 2003 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 #ifndef HAVE_GNU_LD
31 #define __environ environ
32 #endif
34 #define SHELL_PATH "/bin/sh" /* Path of the shell. */
35 #define SHELL_NAME "sh" /* Name to give it. */
38 #ifdef _LIBC_REENTRANT
39 static struct sigaction intr, quit;
40 static int sa_refcntr;
41 __libc_lock_define_initialized (static, lock);
43 # define DO_LOCK() __libc_lock_lock (lock)
44 # define DO_UNLOCK() __libc_lock_unlock (lock)
45 # define INIT_LOCK() ({ __libc_lock_init (lock); sa_refcntr = 0; })
46 # define ADD_REF() sa_refcntr++
47 # define SUB_REF() --sa_refcntr
48 #else
49 # define DO_LOCK()
50 # define DO_UNLOCK()
51 # define INIT_LOCK()
52 # define ADD_REF() 0
53 # define SUB_REF() 0
54 #endif
57 /* Execute LINE as a shell command, returning its status. */
58 static int
59 do_system (const char *line)
61 int status, save;
62 pid_t pid;
63 struct sigaction sa;
64 #ifndef _LIBC_REENTRANT
65 struct sigaction intr, quit;
66 #endif
67 sigset_t omask;
69 sa.sa_handler = SIG_IGN;
70 sa.sa_flags = 0;
71 __sigemptyset (&sa.sa_mask);
73 DO_LOCK ();
74 if (ADD_REF () == 0)
76 if (__sigaction (SIGINT, &sa, &intr) < 0)
78 SUB_REF ();
79 goto out;
81 if (__sigaction (SIGQUIT, &sa, &quit) < 0)
83 save = errno;
84 SUB_REF ();
85 goto out_restore_sigint;
88 DO_UNLOCK ();
90 /* We reuse the bitmap in the 'sa' structure. */
91 __sigaddset (&sa.sa_mask, SIGCHLD);
92 save = errno;
93 if (__sigprocmask (SIG_BLOCK, &sa.sa_mask, &omask) < 0)
95 #ifndef _LIBC
96 if (errno == ENOSYS)
97 __set_errno (save);
98 else
99 #endif
101 DO_LOCK ();
102 if (SUB_REF () == 0)
104 save = errno;
105 (void) __sigaction (SIGQUIT, &quit, (struct sigaction *) NULL);
106 out_restore_sigint:
107 (void) __sigaction (SIGINT, &intr, (struct sigaction *) NULL);
108 __set_errno (save);
110 out:
111 DO_UNLOCK ();
112 return -1;
116 #ifdef CLEANUP_HANDLER
117 CLEANUP_HANDLER;
118 #endif
120 #ifdef FORK
121 pid = FORK ();
122 #else
123 pid = __fork ();
124 #endif
125 if (pid == (pid_t) 0)
127 /* Child side. */
128 const char *new_argv[4];
129 new_argv[0] = SHELL_NAME;
130 new_argv[1] = "-c";
131 new_argv[2] = line;
132 new_argv[3] = NULL;
134 /* Restore the signals. */
135 (void) __sigaction (SIGINT, &intr, (struct sigaction *) NULL);
136 (void) __sigaction (SIGQUIT, &quit, (struct sigaction *) NULL);
137 (void) __sigprocmask (SIG_SETMASK, &omask, (sigset_t *) NULL);
138 INIT_LOCK ();
140 /* Exec the shell. */
141 (void) __execve (SHELL_PATH, (char *const *) new_argv, __environ);
142 _exit (127);
144 else if (pid < (pid_t) 0)
145 /* The fork failed. */
146 status = -1;
147 else
148 /* Parent side. */
150 #ifdef NO_WAITPID
151 pid_t child;
154 child = __wait (&status);
155 if (child <= -1 && errno != EINTR)
157 status = -1;
158 break;
160 /* Note that pid cannot be <= -1 and therefore the loop continues
161 when __wait returned with EINTR. */
163 while (child != pid);
164 #else
165 /* Note the system() is a cancellation point. But since we call
166 waitpid() which itself is a cancellation point we do not
167 have to do anything here. */
168 if (TEMP_FAILURE_RETRY (__waitpid (pid, &status, 0)) != pid)
169 status = -1;
170 #endif
173 #ifdef CLEANUP_HANDLER
174 CLEANUP_RESET;
175 #endif
177 save = errno;
178 DO_LOCK ();
179 if ((SUB_REF () == 0
180 && (__sigaction (SIGINT, &intr, (struct sigaction *) NULL)
181 | __sigaction (SIGQUIT, &quit, (struct sigaction *) NULL)) != 0)
182 || __sigprocmask (SIG_SETMASK, &omask, (sigset_t *) NULL) != 0)
184 #ifndef _LIBC
185 /* glibc cannot be used on systems without waitpid. */
186 if (errno == ENOSYS)
187 __set_errno (save);
188 else
189 #endif
190 status = -1;
192 DO_UNLOCK ();
194 return status;
198 __libc_system (const char *line)
200 if (line == NULL)
201 /* Check that we have a command processor available. It might
202 not be available after a chroot(), for example. */
203 return do_system ("exit 0") == 0;
205 if (SINGLE_THREAD_P)
206 return do_system (line);
208 int oldtype = LIBC_CANCEL_ASYNC ();
210 int result = do_system (line);
212 LIBC_CANCEL_RESET (oldtype);
214 return result;
216 weak_alias (__libc_system, system)