This source file includes following definitions.
- nonintr_close
- nonintr_open
- execute
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 #include <config.h>
20
21
22 #include "execute.h"
23
24 #include <errno.h>
25 #include <fcntl.h>
26 #include <stdbool.h>
27 #include <stdlib.h>
28 #include <signal.h>
29 #include <unistd.h>
30
31 #include <sys/types.h>
32 #include <sys/wait.h>
33
34 #include "canonicalize.h"
35 #include "error.h"
36 #include "fatal-signal.h"
37 #include "filename.h"
38 #include "findprog.h"
39 #include "wait-process.h"
40 #include "xalloc.h"
41 #include "gettext.h"
42
43 #define _(str) gettext (str)
44
45
46
47
48
49
50
51
52
53 #ifndef EXECUTE_IMPL_AVOID_POSIX_SPAWN
54 # define EXECUTE_IMPL_AVOID_POSIX_SPAWN 0
55 #endif
56
57
58 #if (defined _WIN32 && !defined __CYGWIN__) && EXECUTE_IMPL_AVOID_POSIX_SPAWN
59
60
61 # if GNULIB_MSVC_NOTHROW
62 # include "msvc-nothrow.h"
63 # else
64 # include <io.h>
65 # endif
66 # include <process.h>
67 # include "windows-spawn.h"
68
69 #else
70
71
72 # include <spawn.h>
73
74 #endif
75
76
77 #if defined EINTR && (defined _WIN32 && !defined __CYGWIN__) && EXECUTE_IMPL_AVOID_POSIX_SPAWN
78
79
80
81
82
83 static int
84 nonintr_close (int fd)
85 {
86 int retval;
87
88 do
89 retval = close (fd);
90 while (retval < 0 && errno == EINTR);
91
92 return retval;
93 }
94 #undef close
95 #define close nonintr_close
96
97 static int
98 nonintr_open (const char *pathname, int oflag, mode_t mode)
99 {
100 int retval;
101
102 do
103 retval = open (pathname, oflag, mode);
104 while (retval < 0 && errno == EINTR);
105
106 return retval;
107 }
108 #undef open
109 #define open nonintr_open
110
111 #endif
112
113
114 int
115 execute (const char *progname,
116 const char *prog_path, const char * const *prog_argv,
117 const char *directory,
118 bool ignore_sigpipe,
119 bool null_stdin, bool null_stdout, bool null_stderr,
120 bool slave_process, bool exit_on_error,
121 int *termsigp)
122 {
123 int saved_errno;
124 char *prog_path_to_free = NULL;
125
126 if (directory != NULL)
127 {
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142 if (! IS_ABSOLUTE_FILE_NAME (prog_path))
143 {
144 const char *resolved_prog =
145 find_in_given_path (prog_path, getenv ("PATH"), NULL, false);
146 if (resolved_prog == NULL)
147 goto fail_with_errno;
148 if (resolved_prog != prog_path)
149 prog_path_to_free = (char *) resolved_prog;
150 prog_path = resolved_prog;
151
152 if (! IS_ABSOLUTE_FILE_NAME (prog_path))
153 {
154 char *absolute_prog =
155 canonicalize_filename_mode (prog_path,
156 CAN_MISSING | CAN_NOLINKS);
157 if (absolute_prog == NULL)
158 {
159 free (prog_path_to_free);
160 goto fail_with_errno;
161 }
162 free (prog_path_to_free);
163 prog_path_to_free = absolute_prog;
164 prog_path = absolute_prog;
165
166 if (! IS_ABSOLUTE_FILE_NAME (prog_path))
167 abort ();
168 }
169 }
170 }
171
172 #if (defined _WIN32 && !defined __CYGWIN__) && EXECUTE_IMPL_AVOID_POSIX_SPAWN
173
174
175
176 char *argv_mem_to_free;
177
178 const char **argv = prepare_spawn (prog_argv, &argv_mem_to_free);
179 if (argv == NULL)
180 xalloc_die ();
181
182 int exitcode = -1;
183
184
185 int nullinfd = -1;
186 int nulloutfd = -1;
187 if ((!null_stdin
188 || (nullinfd = open ("NUL", O_RDONLY, 0)) >= 0)
189 && (!(null_stdout || null_stderr)
190 || (nulloutfd = open ("NUL", O_RDWR, 0)) >= 0))
191
192
193
194
195
196
197
198 {
199 HANDLE stdin_handle =
200 (HANDLE) _get_osfhandle (null_stdin ? nullinfd : STDIN_FILENO);
201 HANDLE stdout_handle =
202 (HANDLE) _get_osfhandle (null_stdout ? nulloutfd : STDOUT_FILENO);
203 HANDLE stderr_handle =
204 (HANDLE) _get_osfhandle (null_stderr ? nulloutfd : STDERR_FILENO);
205
206 exitcode = spawnpvech (P_WAIT, prog_path, argv + 1,
207 (const char * const *) environ, directory,
208 stdin_handle, stdout_handle, stderr_handle);
209 # if 0
210 if (exitcode == -1 && errno == ENOEXEC)
211 {
212
213
214
215 argv[1] = prog_path;
216 exitcode = spawnpvech (P_WAIT, argv[0], argv,
217 (const char * const *) environ, directory,
218 stdin_handle, stdout_handle, stderr_handle);
219 }
220 # endif
221 }
222 if (exitcode == -1)
223 saved_errno = errno;
224 if (nulloutfd >= 0)
225 close (nulloutfd);
226 if (nullinfd >= 0)
227 close (nullinfd);
228 free (argv);
229 free (argv_mem_to_free);
230 free (prog_path_to_free);
231
232
233
234 if (termsigp != NULL)
235 *termsigp = 0;
236
237 if (exitcode == -1)
238 goto fail_with_saved_errno;
239
240 if (WIFSIGNALED (exitcode))
241 {
242 if (termsigp != NULL)
243 *termsigp = WTERMSIG (exitcode);
244 saved_errno = 0;
245 goto fail_with_saved_errno;
246 }
247
248 return exitcode;
249
250 #else
251
252
253
254
255
256
257
258 sigset_t blocked_signals;
259 posix_spawn_file_actions_t actions;
260 bool actions_allocated;
261 posix_spawnattr_t attrs;
262 bool attrs_allocated;
263 int err;
264 pid_t child;
265
266 if (slave_process)
267 {
268 sigprocmask (SIG_SETMASK, NULL, &blocked_signals);
269 block_fatal_signals ();
270 }
271 actions_allocated = false;
272 attrs_allocated = false;
273 if ((err = posix_spawn_file_actions_init (&actions)) != 0
274 || (actions_allocated = true,
275 (null_stdin
276 && (err = posix_spawn_file_actions_addopen (&actions,
277 STDIN_FILENO,
278 "/dev/null", O_RDONLY,
279 0))
280 != 0)
281 || (null_stdout
282 && (err = posix_spawn_file_actions_addopen (&actions,
283 STDOUT_FILENO,
284 "/dev/null", O_RDWR,
285 0))
286 != 0)
287 || (null_stderr
288 && (err = posix_spawn_file_actions_addopen (&actions,
289 STDERR_FILENO,
290 "/dev/null", O_RDWR,
291 0))
292 != 0)
293 || (directory != NULL
294 && (err = posix_spawn_file_actions_addchdir (&actions,
295 directory)))
296 # if !(defined _WIN32 && !defined __CYGWIN__)
297 || (slave_process
298 && ((err = posix_spawnattr_init (&attrs)) != 0
299 || (attrs_allocated = true,
300 (err = posix_spawnattr_setsigmask (&attrs,
301 &blocked_signals))
302 != 0
303 || (err = posix_spawnattr_setflags (&attrs,
304 POSIX_SPAWN_SETSIGMASK))
305 != 0)))
306 # endif
307 || (err = (directory != NULL
308 ? posix_spawn (&child, prog_path, &actions,
309 attrs_allocated ? &attrs : NULL,
310 (char * const *) prog_argv, environ)
311 : posix_spawnp (&child, prog_path, &actions,
312 attrs_allocated ? &attrs : NULL,
313 (char * const *) prog_argv, environ)))
314 != 0))
315 {
316 if (actions_allocated)
317 posix_spawn_file_actions_destroy (&actions);
318 if (attrs_allocated)
319 posix_spawnattr_destroy (&attrs);
320 if (slave_process)
321 unblock_fatal_signals ();
322 free (prog_path_to_free);
323 if (termsigp != NULL)
324 *termsigp = 0;
325 saved_errno = err;
326 goto fail_with_saved_errno;
327 }
328 posix_spawn_file_actions_destroy (&actions);
329 if (attrs_allocated)
330 posix_spawnattr_destroy (&attrs);
331 if (slave_process)
332 {
333 register_slave_subprocess (child);
334 unblock_fatal_signals ();
335 }
336 free (prog_path_to_free);
337
338 return wait_subprocess (child, progname, ignore_sigpipe, null_stderr,
339 slave_process, exit_on_error, termsigp);
340
341 #endif
342
343 fail_with_errno:
344 saved_errno = errno;
345 fail_with_saved_errno:
346 if (exit_on_error || !null_stderr)
347 error (exit_on_error ? EXIT_FAILURE : 0, saved_errno,
348 _("%s subprocess failed"), progname);
349 return 127;
350 }