nexmon – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | /* gspawn.c - Process launching |
2 | * |
||
3 | * Copyright 2000 Red Hat, Inc. |
||
4 | * g_execvpe implementation based on GNU libc execvp: |
||
5 | * Copyright 1991, 92, 95, 96, 97, 98, 99 Free Software Foundation, Inc. |
||
6 | * |
||
7 | * GLib is free software; you can redistribute it and/or |
||
8 | * modify it under the terms of the GNU Lesser General Public License as |
||
9 | * published by the Free Software Foundation; either version 2 of the |
||
10 | * License, or (at your option) any later version. |
||
11 | * |
||
12 | * GLib is distributed in the hope that it will be useful, |
||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||
15 | * Lesser General Public License for more details. |
||
16 | * |
||
17 | * You should have received a copy of the GNU Lesser General Public |
||
18 | * License along with GLib; see the file COPYING.LIB. If not, write |
||
19 | * to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
||
20 | * Boston, MA 02111-1307, USA. |
||
21 | */ |
||
22 | |||
23 | #include "config.h" |
||
24 | |||
25 | #include <sys/time.h> |
||
26 | #include <sys/types.h> |
||
27 | #include <sys/wait.h> |
||
28 | #include <unistd.h> |
||
29 | #include <errno.h> |
||
30 | #include <fcntl.h> |
||
31 | #include <signal.h> |
||
32 | #include <string.h> |
||
33 | #include <stdlib.h> /* for fdwalk */ |
||
34 | #include <dirent.h> |
||
35 | |||
36 | #ifdef HAVE_SYS_SELECT_H |
||
37 | #include <sys/select.h> |
||
38 | #endif /* HAVE_SYS_SELECT_H */ |
||
39 | |||
40 | #ifdef HAVE_SYS_RESOURCE_H |
||
41 | #include <sys/resource.h> |
||
42 | #endif /* HAVE_SYS_RESOURCE_H */ |
||
43 | |||
44 | #include "gspawn.h" |
||
45 | #include "gthread.h" |
||
46 | #include "glib/gstdio.h" |
||
47 | |||
48 | #include "genviron.h" |
||
49 | #include "gmem.h" |
||
50 | #include "gshell.h" |
||
51 | #include "gstring.h" |
||
52 | #include "gstrfuncs.h" |
||
53 | #include "gtestutils.h" |
||
54 | #include "gutils.h" |
||
55 | #include "glibintl.h" |
||
56 | #include "glib-unix.h" |
||
57 | |||
58 | /** |
||
59 | * SECTION:spawn |
||
60 | * @Short_description: process launching |
||
61 | * @Title: Spawning Processes |
||
62 | * |
||
63 | * GLib supports spawning of processes with an API that is more |
||
64 | * convenient than the bare UNIX fork() and exec(). |
||
65 | * |
||
66 | * The g_spawn family of functions has synchronous (g_spawn_sync()) |
||
67 | * and asynchronous variants (g_spawn_async(), g_spawn_async_with_pipes()), |
||
68 | * as well as convenience variants that take a complete shell-like |
||
69 | * commandline (g_spawn_command_line_sync(), g_spawn_command_line_async()). |
||
70 | * |
||
71 | * See #GSubprocess in GIO for a higher-level API that provides |
||
72 | * stream interfaces for communication with child processes. |
||
73 | */ |
||
74 | |||
75 | |||
76 | |||
77 | static gint g_execute (const gchar *file, |
||
78 | gchar **argv, |
||
79 | gchar **envp, |
||
80 | gboolean search_path, |
||
81 | gboolean search_path_from_envp); |
||
82 | |||
83 | static gboolean fork_exec_with_pipes (gboolean intermediate_child, |
||
84 | const gchar *working_directory, |
||
85 | gchar **argv, |
||
86 | gchar **envp, |
||
87 | gboolean close_descriptors, |
||
88 | gboolean search_path, |
||
89 | gboolean search_path_from_envp, |
||
90 | gboolean stdout_to_null, |
||
91 | gboolean stderr_to_null, |
||
92 | gboolean child_inherits_stdin, |
||
93 | gboolean file_and_argv_zero, |
||
94 | gboolean cloexec_pipes, |
||
95 | GSpawnChildSetupFunc child_setup, |
||
96 | gpointer user_data, |
||
97 | GPid *child_pid, |
||
98 | gint *standard_input, |
||
99 | gint *standard_output, |
||
100 | gint *standard_error, |
||
101 | GError **error); |
||
102 | |||
103 | G_DEFINE_QUARK (g-exec-error-quark, g_spawn_error) |
||
104 | G_DEFINE_QUARK (g-spawn-exit-error-quark, g_spawn_exit_error) |
||
105 | |||
106 | /** |
||
107 | * g_spawn_async: |
||
108 | * @working_directory: (allow-none): child's current working directory, or %NULL to inherit parent's |
||
109 | * @argv: (array zero-terminated=1): child's argument vector |
||
110 | * @envp: (array zero-terminated=1) (allow-none): child's environment, or %NULL to inherit parent's |
||
111 | * @flags: flags from #GSpawnFlags |
||
112 | * @child_setup: (scope async) (allow-none): function to run in the child just before exec() |
||
113 | * @user_data: (closure): user data for @child_setup |
||
114 | * @child_pid: (out) (allow-none): return location for child process reference, or %NULL |
||
115 | * @error: return location for error |
||
116 | * |
||
117 | * See g_spawn_async_with_pipes() for a full description; this function |
||
118 | * simply calls the g_spawn_async_with_pipes() without any pipes. |
||
119 | * |
||
120 | * You should call g_spawn_close_pid() on the returned child process |
||
121 | * reference when you don't need it any more. |
||
122 | * |
||
123 | * If you are writing a GTK+ application, and the program you are |
||
124 | * spawning is a graphical application, too, then you may want to |
||
125 | * use gdk_spawn_on_screen() instead to ensure that the spawned program |
||
126 | * opens its windows on the right screen. |
||
127 | * |
||
128 | * Note that the returned @child_pid on Windows is a handle to the child |
||
129 | * process and not its identifier. Process handles and process identifiers |
||
130 | * are different concepts on Windows. |
||
131 | * |
||
132 | * Returns: %TRUE on success, %FALSE if error is set |
||
133 | **/ |
||
134 | gboolean |
||
135 | g_spawn_async (const gchar *working_directory, |
||
136 | gchar **argv, |
||
137 | gchar **envp, |
||
138 | GSpawnFlags flags, |
||
139 | GSpawnChildSetupFunc child_setup, |
||
140 | gpointer user_data, |
||
141 | GPid *child_pid, |
||
142 | GError **error) |
||
143 | { |
||
144 | g_return_val_if_fail (argv != NULL, FALSE); |
||
145 | |||
146 | return g_spawn_async_with_pipes (working_directory, |
||
147 | argv, envp, |
||
148 | flags, |
||
149 | child_setup, |
||
150 | user_data, |
||
151 | child_pid, |
||
152 | NULL, NULL, NULL, |
||
153 | error); |
||
154 | } |
||
155 | |||
156 | /* Avoids a danger in threaded situations (calling close() |
||
157 | * on a file descriptor twice, and another thread has |
||
158 | * re-opened it since the first close) |
||
159 | */ |
||
160 | static void |
||
161 | close_and_invalidate (gint *fd) |
||
162 | { |
||
163 | if (*fd < 0) |
||
164 | return; |
||
165 | else |
||
166 | { |
||
167 | (void) g_close (*fd, NULL); |
||
168 | *fd = -1; |
||
169 | } |
||
170 | } |
||
171 | |||
172 | /* Some versions of OS X define READ_OK in public headers */ |
||
173 | #undef READ_OK |
||
174 | |||
175 | typedef enum |
||
176 | { |
||
177 | READ_FAILED = 0, /* FALSE */ |
||
178 | READ_OK, |
||
179 | READ_EOF |
||
180 | } ReadResult; |
||
181 | |||
182 | static ReadResult |
||
183 | read_data (GString *str, |
||
184 | gint fd, |
||
185 | GError **error) |
||
186 | { |
||
187 | gssize bytes; |
||
188 | gchar buf[4096]; |
||
189 | |||
190 | again: |
||
191 | bytes = read (fd, buf, 4096); |
||
192 | |||
193 | if (bytes == 0) |
||
194 | return READ_EOF; |
||
195 | else if (bytes > 0) |
||
196 | { |
||
197 | g_string_append_len (str, buf, bytes); |
||
198 | return READ_OK; |
||
199 | } |
||
200 | else if (errno == EINTR) |
||
201 | goto again; |
||
202 | else |
||
203 | { |
||
204 | int errsv = errno; |
||
205 | |||
206 | g_set_error (error, |
||
207 | G_SPAWN_ERROR, |
||
208 | G_SPAWN_ERROR_READ, |
||
209 | _("Failed to read data from child process (%s)"), |
||
210 | g_strerror (errsv)); |
||
211 | |||
212 | return READ_FAILED; |
||
213 | } |
||
214 | } |
||
215 | |||
216 | /** |
||
217 | * g_spawn_sync: |
||
218 | * @working_directory: (allow-none): child's current working directory, or %NULL to inherit parent's |
||
219 | * @argv: (array zero-terminated=1): child's argument vector |
||
220 | * @envp: (array zero-terminated=1) (allow-none): child's environment, or %NULL to inherit parent's |
||
221 | * @flags: flags from #GSpawnFlags |
||
222 | * @child_setup: (scope async) (allow-none): function to run in the child just before exec() |
||
223 | * @user_data: (closure): user data for @child_setup |
||
224 | * @standard_output: (out) (array zero-terminated=1) (element-type guint8) (allow-none): return location for child output, or %NULL |
||
225 | * @standard_error: (out) (array zero-terminated=1) (element-type guint8) (allow-none): return location for child error messages, or %NULL |
||
226 | * @exit_status: (out) (allow-none): return location for child exit status, as returned by waitpid(), or %NULL |
||
227 | * @error: return location for error, or %NULL |
||
228 | * |
||
229 | * Executes a child synchronously (waits for the child to exit before returning). |
||
230 | * All output from the child is stored in @standard_output and @standard_error, |
||
231 | * if those parameters are non-%NULL. Note that you must set the |
||
232 | * %G_SPAWN_STDOUT_TO_DEV_NULL and %G_SPAWN_STDERR_TO_DEV_NULL flags when |
||
233 | * passing %NULL for @standard_output and @standard_error. |
||
234 | * |
||
235 | * If @exit_status is non-%NULL, the platform-specific exit status of |
||
236 | * the child is stored there; see the documentation of |
||
237 | * g_spawn_check_exit_status() for how to use and interpret this. |
||
238 | * Note that it is invalid to pass %G_SPAWN_DO_NOT_REAP_CHILD in |
||
239 | * @flags. |
||
240 | * |
||
241 | * If an error occurs, no data is returned in @standard_output, |
||
242 | * @standard_error, or @exit_status. |
||
243 | * |
||
244 | * This function calls g_spawn_async_with_pipes() internally; see that |
||
245 | * function for full details on the other parameters and details on |
||
246 | * how these functions work on Windows. |
||
247 | * |
||
248 | * Returns: %TRUE on success, %FALSE if an error was set |
||
249 | */ |
||
250 | gboolean |
||
251 | g_spawn_sync (const gchar *working_directory, |
||
252 | gchar **argv, |
||
253 | gchar **envp, |
||
254 | GSpawnFlags flags, |
||
255 | GSpawnChildSetupFunc child_setup, |
||
256 | gpointer user_data, |
||
257 | gchar **standard_output, |
||
258 | gchar **standard_error, |
||
259 | gint *exit_status, |
||
260 | GError **error) |
||
261 | { |
||
262 | gint outpipe = -1; |
||
263 | gint errpipe = -1; |
||
264 | GPid pid; |
||
265 | fd_set fds; |
||
266 | gint ret; |
||
267 | GString *outstr = NULL; |
||
268 | GString *errstr = NULL; |
||
269 | gboolean failed; |
||
270 | gint status; |
||
271 | |||
272 | g_return_val_if_fail (argv != NULL, FALSE); |
||
273 | g_return_val_if_fail (!(flags & G_SPAWN_DO_NOT_REAP_CHILD), FALSE); |
||
274 | g_return_val_if_fail (standard_output == NULL || |
||
275 | !(flags & G_SPAWN_STDOUT_TO_DEV_NULL), FALSE); |
||
276 | g_return_val_if_fail (standard_error == NULL || |
||
277 | !(flags & G_SPAWN_STDERR_TO_DEV_NULL), FALSE); |
||
278 | |||
279 | /* Just to ensure segfaults if callers try to use |
||
280 | * these when an error is reported. |
||
281 | */ |
||
282 | if (standard_output) |
||
283 | *standard_output = NULL; |
||
284 | |||
285 | if (standard_error) |
||
286 | *standard_error = NULL; |
||
287 | |||
288 | if (!fork_exec_with_pipes (FALSE, |
||
289 | working_directory, |
||
290 | argv, |
||
291 | envp, |
||
292 | !(flags & G_SPAWN_LEAVE_DESCRIPTORS_OPEN), |
||
293 | (flags & G_SPAWN_SEARCH_PATH) != 0, |
||
294 | (flags & G_SPAWN_SEARCH_PATH_FROM_ENVP) != 0, |
||
295 | (flags & G_SPAWN_STDOUT_TO_DEV_NULL) != 0, |
||
296 | (flags & G_SPAWN_STDERR_TO_DEV_NULL) != 0, |
||
297 | (flags & G_SPAWN_CHILD_INHERITS_STDIN) != 0, |
||
298 | (flags & G_SPAWN_FILE_AND_ARGV_ZERO) != 0, |
||
299 | (flags & G_SPAWN_CLOEXEC_PIPES) != 0, |
||
300 | child_setup, |
||
301 | user_data, |
||
302 | &pid, |
||
303 | NULL, |
||
304 | standard_output ? &outpipe : NULL, |
||
305 | standard_error ? &errpipe : NULL, |
||
306 | error)) |
||
307 | return FALSE; |
||
308 | |||
309 | /* Read data from child. */ |
||
310 | |||
311 | failed = FALSE; |
||
312 | |||
313 | if (outpipe >= 0) |
||
314 | { |
||
315 | outstr = g_string_new (NULL); |
||
316 | } |
||
317 | |||
318 | if (errpipe >= 0) |
||
319 | { |
||
320 | errstr = g_string_new (NULL); |
||
321 | } |
||
322 | |||
323 | /* Read data until we get EOF on both pipes. */ |
||
324 | while (!failed && |
||
325 | (outpipe >= 0 || |
||
326 | errpipe >= 0)) |
||
327 | { |
||
328 | ret = 0; |
||
329 | |||
330 | FD_ZERO (&fds); |
||
331 | if (outpipe >= 0) |
||
332 | FD_SET (outpipe, &fds); |
||
333 | if (errpipe >= 0) |
||
334 | FD_SET (errpipe, &fds); |
||
335 | |||
336 | ret = select (MAX (outpipe, errpipe) + 1, |
||
337 | &fds, |
||
338 | NULL, NULL, |
||
339 | NULL /* no timeout */); |
||
340 | |||
341 | if (ret < 0) |
||
342 | { |
||
343 | int errsv = errno; |
||
344 | |||
345 | if (errno == EINTR) |
||
346 | continue; |
||
347 | |||
348 | failed = TRUE; |
||
349 | |||
350 | g_set_error (error, |
||
351 | G_SPAWN_ERROR, |
||
352 | G_SPAWN_ERROR_READ, |
||
353 | _("Unexpected error in select() reading data from a child process (%s)"), |
||
354 | g_strerror (errsv)); |
||
355 | |||
356 | break; |
||
357 | } |
||
358 | |||
359 | if (outpipe >= 0 && FD_ISSET (outpipe, &fds)) |
||
360 | { |
||
361 | switch (read_data (outstr, outpipe, error)) |
||
362 | { |
||
363 | case READ_FAILED: |
||
364 | failed = TRUE; |
||
365 | break; |
||
366 | case READ_EOF: |
||
367 | close_and_invalidate (&outpipe); |
||
368 | outpipe = -1; |
||
369 | break; |
||
370 | default: |
||
371 | break; |
||
372 | } |
||
373 | |||
374 | if (failed) |
||
375 | break; |
||
376 | } |
||
377 | |||
378 | if (errpipe >= 0 && FD_ISSET (errpipe, &fds)) |
||
379 | { |
||
380 | switch (read_data (errstr, errpipe, error)) |
||
381 | { |
||
382 | case READ_FAILED: |
||
383 | failed = TRUE; |
||
384 | break; |
||
385 | case READ_EOF: |
||
386 | close_and_invalidate (&errpipe); |
||
387 | errpipe = -1; |
||
388 | break; |
||
389 | default: |
||
390 | break; |
||
391 | } |
||
392 | |||
393 | if (failed) |
||
394 | break; |
||
395 | } |
||
396 | } |
||
397 | |||
398 | /* These should only be open still if we had an error. */ |
||
399 | |||
400 | if (outpipe >= 0) |
||
401 | close_and_invalidate (&outpipe); |
||
402 | if (errpipe >= 0) |
||
403 | close_and_invalidate (&errpipe); |
||
404 | |||
405 | /* Wait for child to exit, even if we have |
||
406 | * an error pending. |
||
407 | */ |
||
408 | again: |
||
409 | |||
410 | ret = waitpid (pid, &status, 0); |
||
411 | |||
412 | if (ret < 0) |
||
413 | { |
||
414 | if (errno == EINTR) |
||
415 | goto again; |
||
416 | else if (errno == ECHILD) |
||
417 | { |
||
418 | if (exit_status) |
||
419 | { |
||
420 | g_warning ("In call to g_spawn_sync(), exit status of a child process was requested but ECHILD was received by waitpid(). Most likely the process is ignoring SIGCHLD, or some other thread is invoking waitpid() with a nonpositive first argument; either behavior can break applications that use g_spawn_sync either directly or indirectly."); |
||
421 | } |
||
422 | else |
||
423 | { |
||
424 | /* We don't need the exit status. */ |
||
425 | } |
||
426 | } |
||
427 | else |
||
428 | { |
||
429 | if (!failed) /* avoid error pileups */ |
||
430 | { |
||
431 | int errsv = errno; |
||
432 | |||
433 | failed = TRUE; |
||
434 | |||
435 | g_set_error (error, |
||
436 | G_SPAWN_ERROR, |
||
437 | G_SPAWN_ERROR_READ, |
||
438 | _("Unexpected error in waitpid() (%s)"), |
||
439 | g_strerror (errsv)); |
||
440 | } |
||
441 | } |
||
442 | } |
||
443 | |||
444 | if (failed) |
||
445 | { |
||
446 | if (outstr) |
||
447 | g_string_free (outstr, TRUE); |
||
448 | if (errstr) |
||
449 | g_string_free (errstr, TRUE); |
||
450 | |||
451 | return FALSE; |
||
452 | } |
||
453 | else |
||
454 | { |
||
455 | if (exit_status) |
||
456 | *exit_status = status; |
||
457 | |||
458 | if (standard_output) |
||
459 | *standard_output = g_string_free (outstr, FALSE); |
||
460 | |||
461 | if (standard_error) |
||
462 | *standard_error = g_string_free (errstr, FALSE); |
||
463 | |||
464 | return TRUE; |
||
465 | } |
||
466 | } |
||
467 | |||
468 | /** |
||
469 | * g_spawn_async_with_pipes: |
||
470 | * @working_directory: (allow-none): child's current working directory, or %NULL to inherit parent's, in the GLib file name encoding |
||
471 | * @argv: (array zero-terminated=1): child's argument vector, in the GLib file name encoding |
||
472 | * @envp: (array zero-terminated=1) (allow-none): child's environment, or %NULL to inherit parent's, in the GLib file name encoding |
||
473 | * @flags: flags from #GSpawnFlags |
||
474 | * @child_setup: (scope async) (allow-none): function to run in the child just before exec() |
||
475 | * @user_data: (closure): user data for @child_setup |
||
476 | * @child_pid: (out) (allow-none): return location for child process ID, or %NULL |
||
477 | * @standard_input: (out) (allow-none): return location for file descriptor to write to child's stdin, or %NULL |
||
478 | * @standard_output: (out) (allow-none): return location for file descriptor to read child's stdout, or %NULL |
||
479 | * @standard_error: (out) (allow-none): return location for file descriptor to read child's stderr, or %NULL |
||
480 | * @error: return location for error |
||
481 | * |
||
482 | * Executes a child program asynchronously (your program will not |
||
483 | * block waiting for the child to exit). The child program is |
||
484 | * specified by the only argument that must be provided, @argv. |
||
485 | * @argv should be a %NULL-terminated array of strings, to be passed |
||
486 | * as the argument vector for the child. The first string in @argv |
||
487 | * is of course the name of the program to execute. By default, the |
||
488 | * name of the program must be a full path. If @flags contains the |
||
489 | * %G_SPAWN_SEARCH_PATH flag, the `PATH` environment variable is |
||
490 | * used to search for the executable. If @flags contains the |
||
491 | * %G_SPAWN_SEARCH_PATH_FROM_ENVP flag, the `PATH` variable from |
||
492 | * @envp is used to search for the executable. If both the |
||
493 | * %G_SPAWN_SEARCH_PATH and %G_SPAWN_SEARCH_PATH_FROM_ENVP flags |
||
494 | * are set, the `PATH` variable from @envp takes precedence over |
||
495 | * the environment variable. |
||
496 | * |
||
497 | * If the program name is not a full path and %G_SPAWN_SEARCH_PATH flag is not |
||
498 | * used, then the program will be run from the current directory (or |
||
499 | * @working_directory, if specified); this might be unexpected or even |
||
500 | * dangerous in some cases when the current directory is world-writable. |
||
501 | * |
||
502 | * On Windows, note that all the string or string vector arguments to |
||
503 | * this function and the other g_spawn*() functions are in UTF-8, the |
||
504 | * GLib file name encoding. Unicode characters that are not part of |
||
505 | * the system codepage passed in these arguments will be correctly |
||
506 | * available in the spawned program only if it uses wide character API |
||
507 | * to retrieve its command line. For C programs built with Microsoft's |
||
508 | * tools it is enough to make the program have a wmain() instead of |
||
509 | * main(). wmain() has a wide character argument vector as parameter. |
||
510 | * |
||
511 | * At least currently, mingw doesn't support wmain(), so if you use |
||
512 | * mingw to develop the spawned program, it should call |
||
513 | * g_win32_get_command_line() to get arguments in UTF-8. |
||
514 | * |
||
515 | * On Windows the low-level child process creation API CreateProcess() |
||
516 | * doesn't use argument vectors, but a command line. The C runtime |
||
517 | * library's spawn*() family of functions (which g_spawn_async_with_pipes() |
||
518 | * eventually calls) paste the argument vector elements together into |
||
519 | * a command line, and the C runtime startup code does a corresponding |
||
520 | * reconstruction of an argument vector from the command line, to be |
||
521 | * passed to main(). Complications arise when you have argument vector |
||
522 | * elements that contain spaces of double quotes. The spawn*() functions |
||
523 | * don't do any quoting or escaping, but on the other hand the startup |
||
524 | * code does do unquoting and unescaping in order to enable receiving |
||
525 | * arguments with embedded spaces or double quotes. To work around this |
||
526 | * asymmetry, g_spawn_async_with_pipes() will do quoting and escaping on |
||
527 | * argument vector elements that need it before calling the C runtime |
||
528 | * spawn() function. |
||
529 | * |
||
530 | * The returned @child_pid on Windows is a handle to the child |
||
531 | * process, not its identifier. Process handles and process |
||
532 | * identifiers are different concepts on Windows. |
||
533 | * |
||
534 | * @envp is a %NULL-terminated array of strings, where each string |
||
535 | * has the form `KEY=VALUE`. This will become the child's environment. |
||
536 | * If @envp is %NULL, the child inherits its parent's environment. |
||
537 | * |
||
538 | * @flags should be the bitwise OR of any flags you want to affect the |
||
539 | * function's behaviour. The %G_SPAWN_DO_NOT_REAP_CHILD means that the |
||
540 | * child will not automatically be reaped; you must use a child watch to |
||
541 | * be notified about the death of the child process. Eventually you must |
||
542 | * call g_spawn_close_pid() on the @child_pid, in order to free |
||
543 | * resources which may be associated with the child process. (On Unix, |
||
544 | * using a child watch is equivalent to calling waitpid() or handling |
||
545 | * the %SIGCHLD signal manually. On Windows, calling g_spawn_close_pid() |
||
546 | * is equivalent to calling CloseHandle() on the process handle returned |
||
547 | * in @child_pid). See g_child_watch_add(). |
||
548 | * |
||
549 | * %G_SPAWN_LEAVE_DESCRIPTORS_OPEN means that the parent's open file |
||
550 | * descriptors will be inherited by the child; otherwise all descriptors |
||
551 | * except stdin/stdout/stderr will be closed before calling exec() in |
||
552 | * the child. %G_SPAWN_SEARCH_PATH means that @argv[0] need not be an |
||
553 | * absolute path, it will be looked for in the `PATH` environment |
||
554 | * variable. %G_SPAWN_SEARCH_PATH_FROM_ENVP means need not be an |
||
555 | * absolute path, it will be looked for in the `PATH` variable from |
||
556 | * @envp. If both %G_SPAWN_SEARCH_PATH and %G_SPAWN_SEARCH_PATH_FROM_ENVP |
||
557 | * are used, the value from @envp takes precedence over the environment. |
||
558 | * %G_SPAWN_STDOUT_TO_DEV_NULL means that the child's standard output |
||
559 | * will be discarded, instead of going to the same location as the parent's |
||
560 | * standard output. If you use this flag, @standard_output must be %NULL. |
||
561 | * %G_SPAWN_STDERR_TO_DEV_NULL means that the child's standard error |
||
562 | * will be discarded, instead of going to the same location as the parent's |
||
563 | * standard error. If you use this flag, @standard_error must be %NULL. |
||
564 | * %G_SPAWN_CHILD_INHERITS_STDIN means that the child will inherit the parent's |
||
565 | * standard input (by default, the child's standard input is attached to |
||
566 | * /dev/null). If you use this flag, @standard_input must be %NULL. |
||
567 | * %G_SPAWN_FILE_AND_ARGV_ZERO means that the first element of @argv is |
||
568 | * the file to execute, while the remaining elements are the actual |
||
569 | * argument vector to pass to the file. Normally g_spawn_async_with_pipes() |
||
570 | * uses @argv[0] as the file to execute, and passes all of @argv to the child. |
||
571 | * |
||
572 | * @child_setup and @user_data are a function and user data. On POSIX |
||
573 | * platforms, the function is called in the child after GLib has |
||
574 | * performed all the setup it plans to perform (including creating |
||
575 | * pipes, closing file descriptors, etc.) but before calling exec(). |
||
576 | * That is, @child_setup is called just before calling exec() in the |
||
577 | * child. Obviously actions taken in this function will only affect |
||
578 | * the child, not the parent. |
||
579 | * |
||
580 | * On Windows, there is no separate fork() and exec() functionality. |
||
581 | * Child processes are created and run with a single API call, |
||
582 | * CreateProcess(). There is no sensible thing @child_setup |
||
583 | * could be used for on Windows so it is ignored and not called. |
||
584 | * |
||
585 | * If non-%NULL, @child_pid will on Unix be filled with the child's |
||
586 | * process ID. You can use the process ID to send signals to the child, |
||
587 | * or to use g_child_watch_add() (or waitpid()) if you specified the |
||
588 | * %G_SPAWN_DO_NOT_REAP_CHILD flag. On Windows, @child_pid will be |
||
589 | * filled with a handle to the child process only if you specified the |
||
590 | * %G_SPAWN_DO_NOT_REAP_CHILD flag. You can then access the child |
||
591 | * process using the Win32 API, for example wait for its termination |
||
592 | * with the WaitFor*() functions, or examine its exit code with |
||
593 | * GetExitCodeProcess(). You should close the handle with CloseHandle() |
||
594 | * or g_spawn_close_pid() when you no longer need it. |
||
595 | * |
||
596 | * If non-%NULL, the @standard_input, @standard_output, @standard_error |
||
597 | * locations will be filled with file descriptors for writing to the child's |
||
598 | * standard input or reading from its standard output or standard error. |
||
599 | * The caller of g_spawn_async_with_pipes() must close these file descriptors |
||
600 | * when they are no longer in use. If these parameters are %NULL, the |
||
601 | * corresponding pipe won't be created. |
||
602 | * |
||
603 | * If @standard_input is NULL, the child's standard input is attached to |
||
604 | * /dev/null unless %G_SPAWN_CHILD_INHERITS_STDIN is set. |
||
605 | * |
||
606 | * If @standard_error is NULL, the child's standard error goes to the same |
||
607 | * location as the parent's standard error unless %G_SPAWN_STDERR_TO_DEV_NULL |
||
608 | * is set. |
||
609 | * |
||
610 | * If @standard_output is NULL, the child's standard output goes to the same |
||
611 | * location as the parent's standard output unless %G_SPAWN_STDOUT_TO_DEV_NULL |
||
612 | * is set. |
||
613 | * |
||
614 | * @error can be %NULL to ignore errors, or non-%NULL to report errors. |
||
615 | * If an error is set, the function returns %FALSE. Errors are reported |
||
616 | * even if they occur in the child (for example if the executable in |
||
617 | * @argv[0] is not found). Typically the `message` field of returned |
||
618 | * errors should be displayed to users. Possible errors are those from |
||
619 | * the #G_SPAWN_ERROR domain. |
||
620 | * |
||
621 | * If an error occurs, @child_pid, @standard_input, @standard_output, |
||
622 | * and @standard_error will not be filled with valid values. |
||
623 | * |
||
624 | * If @child_pid is not %NULL and an error does not occur then the returned |
||
625 | * process reference must be closed using g_spawn_close_pid(). |
||
626 | * |
||
627 | * If you are writing a GTK+ application, and the program you |
||
628 | * are spawning is a graphical application, too, then you may |
||
629 | * want to use gdk_spawn_on_screen_with_pipes() instead to ensure that |
||
630 | * the spawned program opens its windows on the right screen. |
||
631 | * |
||
632 | * Returns: %TRUE on success, %FALSE if an error was set |
||
633 | */ |
||
634 | gboolean |
||
635 | g_spawn_async_with_pipes (const gchar *working_directory, |
||
636 | gchar **argv, |
||
637 | gchar **envp, |
||
638 | GSpawnFlags flags, |
||
639 | GSpawnChildSetupFunc child_setup, |
||
640 | gpointer user_data, |
||
641 | GPid *child_pid, |
||
642 | gint *standard_input, |
||
643 | gint *standard_output, |
||
644 | gint *standard_error, |
||
645 | GError **error) |
||
646 | { |
||
647 | g_return_val_if_fail (argv != NULL, FALSE); |
||
648 | g_return_val_if_fail (standard_output == NULL || |
||
649 | !(flags & G_SPAWN_STDOUT_TO_DEV_NULL), FALSE); |
||
650 | g_return_val_if_fail (standard_error == NULL || |
||
651 | !(flags & G_SPAWN_STDERR_TO_DEV_NULL), FALSE); |
||
652 | /* can't inherit stdin if we have an input pipe. */ |
||
653 | g_return_val_if_fail (standard_input == NULL || |
||
654 | !(flags & G_SPAWN_CHILD_INHERITS_STDIN), FALSE); |
||
655 | |||
656 | return fork_exec_with_pipes (!(flags & G_SPAWN_DO_NOT_REAP_CHILD), |
||
657 | working_directory, |
||
658 | argv, |
||
659 | envp, |
||
660 | !(flags & G_SPAWN_LEAVE_DESCRIPTORS_OPEN), |
||
661 | (flags & G_SPAWN_SEARCH_PATH) != 0, |
||
662 | (flags & G_SPAWN_SEARCH_PATH_FROM_ENVP) != 0, |
||
663 | (flags & G_SPAWN_STDOUT_TO_DEV_NULL) != 0, |
||
664 | (flags & G_SPAWN_STDERR_TO_DEV_NULL) != 0, |
||
665 | (flags & G_SPAWN_CHILD_INHERITS_STDIN) != 0, |
||
666 | (flags & G_SPAWN_FILE_AND_ARGV_ZERO) != 0, |
||
667 | (flags & G_SPAWN_CLOEXEC_PIPES) != 0, |
||
668 | child_setup, |
||
669 | user_data, |
||
670 | child_pid, |
||
671 | standard_input, |
||
672 | standard_output, |
||
673 | standard_error, |
||
674 | error); |
||
675 | } |
||
676 | |||
677 | /** |
||
678 | * g_spawn_command_line_sync: |
||
679 | * @command_line: a command line |
||
680 | * @standard_output: (out) (array zero-terminated=1) (element-type guint8) (allow-none): return location for child output |
||
681 | * @standard_error: (out) (array zero-terminated=1) (element-type guint8) (allow-none): return location for child errors |
||
682 | * @exit_status: (out) (allow-none): return location for child exit status, as returned by waitpid() |
||
683 | * @error: return location for errors |
||
684 | * |
||
685 | * A simple version of g_spawn_sync() with little-used parameters |
||
686 | * removed, taking a command line instead of an argument vector. See |
||
687 | * g_spawn_sync() for full details. @command_line will be parsed by |
||
688 | * g_shell_parse_argv(). Unlike g_spawn_sync(), the %G_SPAWN_SEARCH_PATH flag |
||
689 | * is enabled. Note that %G_SPAWN_SEARCH_PATH can have security |
||
690 | * implications, so consider using g_spawn_sync() directly if |
||
691 | * appropriate. Possible errors are those from g_spawn_sync() and those |
||
692 | * from g_shell_parse_argv(). |
||
693 | * |
||
694 | * If @exit_status is non-%NULL, the platform-specific exit status of |
||
695 | * the child is stored there; see the documentation of |
||
696 | * g_spawn_check_exit_status() for how to use and interpret this. |
||
697 | * |
||
698 | * On Windows, please note the implications of g_shell_parse_argv() |
||
699 | * parsing @command_line. Parsing is done according to Unix shell rules, not |
||
700 | * Windows command interpreter rules. |
||
701 | * Space is a separator, and backslashes are |
||
702 | * special. Thus you cannot simply pass a @command_line containing |
||
703 | * canonical Windows paths, like "c:\\program files\\app\\app.exe", as |
||
704 | * the backslashes will be eaten, and the space will act as a |
||
705 | * separator. You need to enclose such paths with single quotes, like |
||
706 | * "'c:\\program files\\app\\app.exe' 'e:\\folder\\argument.txt'". |
||
707 | * |
||
708 | * Returns: %TRUE on success, %FALSE if an error was set |
||
709 | **/ |
||
710 | gboolean |
||
711 | g_spawn_command_line_sync (const gchar *command_line, |
||
712 | gchar **standard_output, |
||
713 | gchar **standard_error, |
||
714 | gint *exit_status, |
||
715 | GError **error) |
||
716 | { |
||
717 | gboolean retval; |
||
718 | gchar **argv = NULL; |
||
719 | |||
720 | g_return_val_if_fail (command_line != NULL, FALSE); |
||
721 | |||
722 | if (!g_shell_parse_argv (command_line, |
||
723 | NULL, &argv, |
||
724 | error)) |
||
725 | return FALSE; |
||
726 | |||
727 | retval = g_spawn_sync (NULL, |
||
728 | argv, |
||
729 | NULL, |
||
730 | G_SPAWN_SEARCH_PATH, |
||
731 | NULL, |
||
732 | NULL, |
||
733 | standard_output, |
||
734 | standard_error, |
||
735 | exit_status, |
||
736 | error); |
||
737 | g_strfreev (argv); |
||
738 | |||
739 | return retval; |
||
740 | } |
||
741 | |||
742 | /** |
||
743 | * g_spawn_command_line_async: |
||
744 | * @command_line: a command line |
||
745 | * @error: return location for errors |
||
746 | * |
||
747 | * A simple version of g_spawn_async() that parses a command line with |
||
748 | * g_shell_parse_argv() and passes it to g_spawn_async(). Runs a |
||
749 | * command line in the background. Unlike g_spawn_async(), the |
||
750 | * %G_SPAWN_SEARCH_PATH flag is enabled, other flags are not. Note |
||
751 | * that %G_SPAWN_SEARCH_PATH can have security implications, so |
||
752 | * consider using g_spawn_async() directly if appropriate. Possible |
||
753 | * errors are those from g_shell_parse_argv() and g_spawn_async(). |
||
754 | * |
||
755 | * The same concerns on Windows apply as for g_spawn_command_line_sync(). |
||
756 | * |
||
757 | * Returns: %TRUE on success, %FALSE if error is set |
||
758 | **/ |
||
759 | gboolean |
||
760 | g_spawn_command_line_async (const gchar *command_line, |
||
761 | GError **error) |
||
762 | { |
||
763 | gboolean retval; |
||
764 | gchar **argv = NULL; |
||
765 | |||
766 | g_return_val_if_fail (command_line != NULL, FALSE); |
||
767 | |||
768 | if (!g_shell_parse_argv (command_line, |
||
769 | NULL, &argv, |
||
770 | error)) |
||
771 | return FALSE; |
||
772 | |||
773 | retval = g_spawn_async (NULL, |
||
774 | argv, |
||
775 | NULL, |
||
776 | G_SPAWN_SEARCH_PATH, |
||
777 | NULL, |
||
778 | NULL, |
||
779 | NULL, |
||
780 | error); |
||
781 | g_strfreev (argv); |
||
782 | |||
783 | return retval; |
||
784 | } |
||
785 | |||
786 | /** |
||
787 | * g_spawn_check_exit_status: |
||
788 | * @exit_status: An exit code as returned from g_spawn_sync() |
||
789 | * @error: a #GError |
||
790 | * |
||
791 | * Set @error if @exit_status indicates the child exited abnormally |
||
792 | * (e.g. with a nonzero exit code, or via a fatal signal). |
||
793 | * |
||
794 | * The g_spawn_sync() and g_child_watch_add() family of APIs return an |
||
795 | * exit status for subprocesses encoded in a platform-specific way. |
||
796 | * On Unix, this is guaranteed to be in the same format waitpid() returns, |
||
797 | * and on Windows it is guaranteed to be the result of GetExitCodeProcess(). |
||
798 | * |
||
799 | * Prior to the introduction of this function in GLib 2.34, interpreting |
||
800 | * @exit_status required use of platform-specific APIs, which is problematic |
||
801 | * for software using GLib as a cross-platform layer. |
||
802 | * |
||
803 | * Additionally, many programs simply want to determine whether or not |
||
804 | * the child exited successfully, and either propagate a #GError or |
||
805 | * print a message to standard error. In that common case, this function |
||
806 | * can be used. Note that the error message in @error will contain |
||
807 | * human-readable information about the exit status. |
||
808 | * |
||
809 | * The @domain and @code of @error have special semantics in the case |
||
810 | * where the process has an "exit code", as opposed to being killed by |
||
811 | * a signal. On Unix, this happens if WIFEXITED() would be true of |
||
812 | * @exit_status. On Windows, it is always the case. |
||
813 | * |
||
814 | * The special semantics are that the actual exit code will be the |
||
815 | * code set in @error, and the domain will be %G_SPAWN_EXIT_ERROR. |
||
816 | * This allows you to differentiate between different exit codes. |
||
817 | * |
||
818 | * If the process was terminated by some means other than an exit |
||
819 | * status, the domain will be %G_SPAWN_ERROR, and the code will be |
||
820 | * %G_SPAWN_ERROR_FAILED. |
||
821 | * |
||
822 | * This function just offers convenience; you can of course also check |
||
823 | * the available platform via a macro such as %G_OS_UNIX, and use |
||
824 | * WIFEXITED() and WEXITSTATUS() on @exit_status directly. Do not attempt |
||
825 | * to scan or parse the error message string; it may be translated and/or |
||
826 | * change in future versions of GLib. |
||
827 | * |
||
828 | * Returns: %TRUE if child exited successfully, %FALSE otherwise (and |
||
829 | * @error will be set) |
||
830 | * |
||
831 | * Since: 2.34 |
||
832 | */ |
||
833 | gboolean |
||
834 | g_spawn_check_exit_status (gint exit_status, |
||
835 | GError **error) |
||
836 | { |
||
837 | gboolean ret = FALSE; |
||
838 | |||
839 | if (WIFEXITED (exit_status)) |
||
840 | { |
||
841 | if (WEXITSTATUS (exit_status) != 0) |
||
842 | { |
||
843 | g_set_error (error, G_SPAWN_EXIT_ERROR, WEXITSTATUS (exit_status), |
||
844 | _("Child process exited with code %ld"), |
||
845 | (long) WEXITSTATUS (exit_status)); |
||
846 | goto out; |
||
847 | } |
||
848 | } |
||
849 | else if (WIFSIGNALED (exit_status)) |
||
850 | { |
||
851 | g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED, |
||
852 | _("Child process killed by signal %ld"), |
||
853 | (long) WTERMSIG (exit_status)); |
||
854 | goto out; |
||
855 | } |
||
856 | else if (WIFSTOPPED (exit_status)) |
||
857 | { |
||
858 | g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED, |
||
859 | _("Child process stopped by signal %ld"), |
||
860 | (long) WSTOPSIG (exit_status)); |
||
861 | goto out; |
||
862 | } |
||
863 | else |
||
864 | { |
||
865 | g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED, |
||
866 | _("Child process exited abnormally")); |
||
867 | goto out; |
||
868 | } |
||
869 | |||
870 | ret = TRUE; |
||
871 | out: |
||
872 | return ret; |
||
873 | } |
||
874 | |||
875 | static gint |
||
876 | exec_err_to_g_error (gint en) |
||
877 | { |
||
878 | switch (en) |
||
879 | { |
||
880 | #ifdef EACCES |
||
881 | case EACCES: |
||
882 | return G_SPAWN_ERROR_ACCES; |
||
883 | break; |
||
884 | #endif |
||
885 | |||
886 | #ifdef EPERM |
||
887 | case EPERM: |
||
888 | return G_SPAWN_ERROR_PERM; |
||
889 | break; |
||
890 | #endif |
||
891 | |||
892 | #ifdef E2BIG |
||
893 | case E2BIG: |
||
894 | return G_SPAWN_ERROR_TOO_BIG; |
||
895 | break; |
||
896 | #endif |
||
897 | |||
898 | #ifdef ENOEXEC |
||
899 | case ENOEXEC: |
||
900 | return G_SPAWN_ERROR_NOEXEC; |
||
901 | break; |
||
902 | #endif |
||
903 | |||
904 | #ifdef ENAMETOOLONG |
||
905 | case ENAMETOOLONG: |
||
906 | return G_SPAWN_ERROR_NAMETOOLONG; |
||
907 | break; |
||
908 | #endif |
||
909 | |||
910 | #ifdef ENOENT |
||
911 | case ENOENT: |
||
912 | return G_SPAWN_ERROR_NOENT; |
||
913 | break; |
||
914 | #endif |
||
915 | |||
916 | #ifdef ENOMEM |
||
917 | case ENOMEM: |
||
918 | return G_SPAWN_ERROR_NOMEM; |
||
919 | break; |
||
920 | #endif |
||
921 | |||
922 | #ifdef ENOTDIR |
||
923 | case ENOTDIR: |
||
924 | return G_SPAWN_ERROR_NOTDIR; |
||
925 | break; |
||
926 | #endif |
||
927 | |||
928 | #ifdef ELOOP |
||
929 | case ELOOP: |
||
930 | return G_SPAWN_ERROR_LOOP; |
||
931 | break; |
||
932 | #endif |
||
933 | |||
934 | #ifdef ETXTBUSY |
||
935 | case ETXTBUSY: |
||
936 | return G_SPAWN_ERROR_TXTBUSY; |
||
937 | break; |
||
938 | #endif |
||
939 | |||
940 | #ifdef EIO |
||
941 | case EIO: |
||
942 | return G_SPAWN_ERROR_IO; |
||
943 | break; |
||
944 | #endif |
||
945 | |||
946 | #ifdef ENFILE |
||
947 | case ENFILE: |
||
948 | return G_SPAWN_ERROR_NFILE; |
||
949 | break; |
||
950 | #endif |
||
951 | |||
952 | #ifdef EMFILE |
||
953 | case EMFILE: |
||
954 | return G_SPAWN_ERROR_MFILE; |
||
955 | break; |
||
956 | #endif |
||
957 | |||
958 | #ifdef EINVAL |
||
959 | case EINVAL: |
||
960 | return G_SPAWN_ERROR_INVAL; |
||
961 | break; |
||
962 | #endif |
||
963 | |||
964 | #ifdef EISDIR |
||
965 | case EISDIR: |
||
966 | return G_SPAWN_ERROR_ISDIR; |
||
967 | break; |
||
968 | #endif |
||
969 | |||
970 | #ifdef ELIBBAD |
||
971 | case ELIBBAD: |
||
972 | return G_SPAWN_ERROR_LIBBAD; |
||
973 | break; |
||
974 | #endif |
||
975 | |||
976 | default: |
||
977 | return G_SPAWN_ERROR_FAILED; |
||
978 | break; |
||
979 | } |
||
980 | } |
||
981 | |||
982 | static gssize |
||
983 | write_all (gint fd, gconstpointer vbuf, gsize to_write) |
||
984 | { |
||
985 | gchar *buf = (gchar *) vbuf; |
||
986 | |||
987 | while (to_write > 0) |
||
988 | { |
||
989 | gssize count = write (fd, buf, to_write); |
||
990 | if (count < 0) |
||
991 | { |
||
992 | if (errno != EINTR) |
||
993 | return FALSE; |
||
994 | } |
||
995 | else |
||
996 | { |
||
997 | to_write -= count; |
||
998 | buf += count; |
||
999 | } |
||
1000 | } |
||
1001 | |||
1002 | return TRUE; |
||
1003 | } |
||
1004 | |||
1005 | G_GNUC_NORETURN |
||
1006 | static void |
||
1007 | write_err_and_exit (gint fd, gint msg) |
||
1008 | { |
||
1009 | gint en = errno; |
||
1010 | |||
1011 | write_all (fd, &msg, sizeof(msg)); |
||
1012 | write_all (fd, &en, sizeof(en)); |
||
1013 | |||
1014 | _exit (1); |
||
1015 | } |
||
1016 | |||
1017 | static int |
||
1018 | set_cloexec (void *data, gint fd) |
||
1019 | { |
||
1020 | if (fd >= GPOINTER_TO_INT (data)) |
||
1021 | fcntl (fd, F_SETFD, FD_CLOEXEC); |
||
1022 | |||
1023 | return 0; |
||
1024 | } |
||
1025 | |||
1026 | #ifndef HAVE_FDWALK |
||
1027 | static int |
||
1028 | fdwalk (int (*cb)(void *data, int fd), void *data) |
||
1029 | { |
||
1030 | gint open_max; |
||
1031 | gint fd; |
||
1032 | gint res = 0; |
||
1033 | |||
1034 | #ifdef HAVE_SYS_RESOURCE_H |
||
1035 | struct rlimit rl; |
||
1036 | #endif |
||
1037 | |||
1038 | #ifdef __linux__ |
||
1039 | DIR *d; |
||
1040 | |||
1041 | if ((d = opendir("/proc/self/fd"))) { |
||
1042 | struct dirent *de; |
||
1043 | |||
1044 | while ((de = readdir(d))) { |
||
1045 | glong l; |
||
1046 | gchar *e = NULL; |
||
1047 | |||
1048 | if (de->d_name[0] == '.') |
||
1049 | continue; |
||
1050 | |||
1051 | errno = 0; |
||
1052 | l = strtol(de->d_name, &e, 10); |
||
1053 | if (errno != 0 || !e || *e) |
||
1054 | continue; |
||
1055 | |||
1056 | fd = (gint) l; |
||
1057 | |||
1058 | if ((glong) fd != l) |
||
1059 | continue; |
||
1060 | |||
1061 | if (fd == dirfd(d)) |
||
1062 | continue; |
||
1063 | |||
1064 | if ((res = cb (data, fd)) != 0) |
||
1065 | break; |
||
1066 | } |
||
1067 | |||
1068 | closedir(d); |
||
1069 | return res; |
||
1070 | } |
||
1071 | |||
1072 | /* If /proc is not mounted or not accessible we fall back to the old |
||
1073 | * rlimit trick */ |
||
1074 | |||
1075 | #endif |
||
1076 | |||
1077 | #ifdef HAVE_SYS_RESOURCE_H |
||
1078 | |||
1079 | if (getrlimit(RLIMIT_NOFILE, &rl) == 0 && rl.rlim_max != RLIM_INFINITY) |
||
1080 | open_max = rl.rlim_max; |
||
1081 | else |
||
1082 | #endif |
||
1083 | open_max = sysconf (_SC_OPEN_MAX); |
||
1084 | |||
1085 | for (fd = 0; fd < open_max; fd++) |
||
1086 | if ((res = cb (data, fd)) != 0) |
||
1087 | break; |
||
1088 | |||
1089 | return res; |
||
1090 | } |
||
1091 | #endif |
||
1092 | |||
1093 | static gint |
||
1094 | sane_dup2 (gint fd1, gint fd2) |
||
1095 | { |
||
1096 | gint ret; |
||
1097 | |||
1098 | retry: |
||
1099 | ret = dup2 (fd1, fd2); |
||
1100 | if (ret < 0 && errno == EINTR) |
||
1101 | goto retry; |
||
1102 | |||
1103 | return ret; |
||
1104 | } |
||
1105 | |||
1106 | static gint |
||
1107 | sane_open (const char *path, gint mode) |
||
1108 | { |
||
1109 | gint ret; |
||
1110 | |||
1111 | retry: |
||
1112 | ret = open (path, mode); |
||
1113 | if (ret < 0 && errno == EINTR) |
||
1114 | goto retry; |
||
1115 | |||
1116 | return ret; |
||
1117 | } |
||
1118 | |||
1119 | enum |
||
1120 | { |
||
1121 | CHILD_CHDIR_FAILED, |
||
1122 | CHILD_EXEC_FAILED, |
||
1123 | CHILD_DUP2_FAILED, |
||
1124 | CHILD_FORK_FAILED |
||
1125 | }; |
||
1126 | |||
1127 | static void |
||
1128 | do_exec (gint child_err_report_fd, |
||
1129 | gint stdin_fd, |
||
1130 | gint stdout_fd, |
||
1131 | gint stderr_fd, |
||
1132 | const gchar *working_directory, |
||
1133 | gchar **argv, |
||
1134 | gchar **envp, |
||
1135 | gboolean close_descriptors, |
||
1136 | gboolean search_path, |
||
1137 | gboolean search_path_from_envp, |
||
1138 | gboolean stdout_to_null, |
||
1139 | gboolean stderr_to_null, |
||
1140 | gboolean child_inherits_stdin, |
||
1141 | gboolean file_and_argv_zero, |
||
1142 | GSpawnChildSetupFunc child_setup, |
||
1143 | gpointer user_data) |
||
1144 | { |
||
1145 | if (working_directory && chdir (working_directory) < 0) |
||
1146 | write_err_and_exit (child_err_report_fd, |
||
1147 | CHILD_CHDIR_FAILED); |
||
1148 | |||
1149 | /* Close all file descriptors but stdin stdout and stderr as |
||
1150 | * soon as we exec. Note that this includes |
||
1151 | * child_err_report_fd, which keeps the parent from blocking |
||
1152 | * forever on the other end of that pipe. |
||
1153 | */ |
||
1154 | if (close_descriptors) |
||
1155 | { |
||
1156 | fdwalk (set_cloexec, GINT_TO_POINTER(3)); |
||
1157 | } |
||
1158 | else |
||
1159 | { |
||
1160 | /* We need to do child_err_report_fd anyway */ |
||
1161 | set_cloexec (GINT_TO_POINTER(0), child_err_report_fd); |
||
1162 | } |
||
1163 | |||
1164 | /* Redirect pipes as required */ |
||
1165 | |||
1166 | if (stdin_fd >= 0) |
||
1167 | { |
||
1168 | /* dup2 can't actually fail here I don't think */ |
||
1169 | |||
1170 | if (sane_dup2 (stdin_fd, 0) < 0) |
||
1171 | write_err_and_exit (child_err_report_fd, |
||
1172 | CHILD_DUP2_FAILED); |
||
1173 | |||
1174 | /* ignore this if it doesn't work */ |
||
1175 | close_and_invalidate (&stdin_fd); |
||
1176 | } |
||
1177 | else if (!child_inherits_stdin) |
||
1178 | { |
||
1179 | /* Keep process from blocking on a read of stdin */ |
||
1180 | gint read_null = open ("/dev/null", O_RDONLY); |
||
1181 | g_assert (read_null != -1); |
||
1182 | sane_dup2 (read_null, 0); |
||
1183 | close_and_invalidate (&read_null); |
||
1184 | } |
||
1185 | |||
1186 | if (stdout_fd >= 0) |
||
1187 | { |
||
1188 | /* dup2 can't actually fail here I don't think */ |
||
1189 | |||
1190 | if (sane_dup2 (stdout_fd, 1) < 0) |
||
1191 | write_err_and_exit (child_err_report_fd, |
||
1192 | CHILD_DUP2_FAILED); |
||
1193 | |||
1194 | /* ignore this if it doesn't work */ |
||
1195 | close_and_invalidate (&stdout_fd); |
||
1196 | } |
||
1197 | else if (stdout_to_null) |
||
1198 | { |
||
1199 | gint write_null = sane_open ("/dev/null", O_WRONLY); |
||
1200 | g_assert (write_null != -1); |
||
1201 | sane_dup2 (write_null, 1); |
||
1202 | close_and_invalidate (&write_null); |
||
1203 | } |
||
1204 | |||
1205 | if (stderr_fd >= 0) |
||
1206 | { |
||
1207 | /* dup2 can't actually fail here I don't think */ |
||
1208 | |||
1209 | if (sane_dup2 (stderr_fd, 2) < 0) |
||
1210 | write_err_and_exit (child_err_report_fd, |
||
1211 | CHILD_DUP2_FAILED); |
||
1212 | |||
1213 | /* ignore this if it doesn't work */ |
||
1214 | close_and_invalidate (&stderr_fd); |
||
1215 | } |
||
1216 | else if (stderr_to_null) |
||
1217 | { |
||
1218 | gint write_null = sane_open ("/dev/null", O_WRONLY); |
||
1219 | sane_dup2 (write_null, 2); |
||
1220 | close_and_invalidate (&write_null); |
||
1221 | } |
||
1222 | |||
1223 | /* Call user function just before we exec */ |
||
1224 | if (child_setup) |
||
1225 | { |
||
1226 | (* child_setup) (user_data); |
||
1227 | } |
||
1228 | |||
1229 | g_execute (argv[0], |
||
1230 | file_and_argv_zero ? argv + 1 : argv, |
||
1231 | envp, search_path, search_path_from_envp); |
||
1232 | |||
1233 | /* Exec failed */ |
||
1234 | write_err_and_exit (child_err_report_fd, |
||
1235 | CHILD_EXEC_FAILED); |
||
1236 | } |
||
1237 | |||
1238 | static gboolean |
||
1239 | read_ints (int fd, |
||
1240 | gint* buf, |
||
1241 | gint n_ints_in_buf, |
||
1242 | gint *n_ints_read, |
||
1243 | GError **error) |
||
1244 | { |
||
1245 | gsize bytes = 0; |
||
1246 | |||
1247 | while (TRUE) |
||
1248 | { |
||
1249 | gssize chunk; |
||
1250 | |||
1251 | if (bytes >= sizeof(gint)*2) |
||
1252 | break; /* give up, who knows what happened, should not be |
||
1253 | * possible. |
||
1254 | */ |
||
1255 | |||
1256 | again: |
||
1257 | chunk = read (fd, |
||
1258 | ((gchar*)buf) + bytes, |
||
1259 | sizeof(gint) * n_ints_in_buf - bytes); |
||
1260 | if (chunk < 0 && errno == EINTR) |
||
1261 | goto again; |
||
1262 | |||
1263 | if (chunk < 0) |
||
1264 | { |
||
1265 | int errsv = errno; |
||
1266 | |||
1267 | /* Some weird shit happened, bail out */ |
||
1268 | g_set_error (error, |
||
1269 | G_SPAWN_ERROR, |
||
1270 | G_SPAWN_ERROR_FAILED, |
||
1271 | _("Failed to read from child pipe (%s)"), |
||
1272 | g_strerror (errsv)); |
||
1273 | |||
1274 | return FALSE; |
||
1275 | } |
||
1276 | else if (chunk == 0) |
||
1277 | break; /* EOF */ |
||
1278 | else /* chunk > 0 */ |
||
1279 | bytes += chunk; |
||
1280 | } |
||
1281 | |||
1282 | *n_ints_read = (gint)(bytes / sizeof(gint)); |
||
1283 | |||
1284 | return TRUE; |
||
1285 | } |
||
1286 | |||
1287 | static gboolean |
||
1288 | fork_exec_with_pipes (gboolean intermediate_child, |
||
1289 | const gchar *working_directory, |
||
1290 | gchar **argv, |
||
1291 | gchar **envp, |
||
1292 | gboolean close_descriptors, |
||
1293 | gboolean search_path, |
||
1294 | gboolean search_path_from_envp, |
||
1295 | gboolean stdout_to_null, |
||
1296 | gboolean stderr_to_null, |
||
1297 | gboolean child_inherits_stdin, |
||
1298 | gboolean file_and_argv_zero, |
||
1299 | gboolean cloexec_pipes, |
||
1300 | GSpawnChildSetupFunc child_setup, |
||
1301 | gpointer user_data, |
||
1302 | GPid *child_pid, |
||
1303 | gint *standard_input, |
||
1304 | gint *standard_output, |
||
1305 | gint *standard_error, |
||
1306 | GError **error) |
||
1307 | { |
||
1308 | GPid pid = -1; |
||
1309 | gint stdin_pipe[2] = { -1, -1 }; |
||
1310 | gint stdout_pipe[2] = { -1, -1 }; |
||
1311 | gint stderr_pipe[2] = { -1, -1 }; |
||
1312 | gint child_err_report_pipe[2] = { -1, -1 }; |
||
1313 | gint child_pid_report_pipe[2] = { -1, -1 }; |
||
1314 | guint pipe_flags = cloexec_pipes ? FD_CLOEXEC : 0; |
||
1315 | gint status; |
||
1316 | |||
1317 | if (!g_unix_open_pipe (child_err_report_pipe, pipe_flags, error)) |
||
1318 | return FALSE; |
||
1319 | |||
1320 | if (intermediate_child && !g_unix_open_pipe (child_pid_report_pipe, pipe_flags, error)) |
||
1321 | goto cleanup_and_fail; |
||
1322 | |||
1323 | if (standard_input && !g_unix_open_pipe (stdin_pipe, pipe_flags, error)) |
||
1324 | goto cleanup_and_fail; |
||
1325 | |||
1326 | if (standard_output && !g_unix_open_pipe (stdout_pipe, pipe_flags, error)) |
||
1327 | goto cleanup_and_fail; |
||
1328 | |||
1329 | if (standard_error && !g_unix_open_pipe (stderr_pipe, FD_CLOEXEC, error)) |
||
1330 | goto cleanup_and_fail; |
||
1331 | |||
1332 | pid = fork (); |
||
1333 | |||
1334 | if (pid < 0) |
||
1335 | { |
||
1336 | int errsv = errno; |
||
1337 | |||
1338 | g_set_error (error, |
||
1339 | G_SPAWN_ERROR, |
||
1340 | G_SPAWN_ERROR_FORK, |
||
1341 | _("Failed to fork (%s)"), |
||
1342 | g_strerror (errsv)); |
||
1343 | |||
1344 | goto cleanup_and_fail; |
||
1345 | } |
||
1346 | else if (pid == 0) |
||
1347 | { |
||
1348 | /* Immediate child. This may or may not be the child that |
||
1349 | * actually execs the new process. |
||
1350 | */ |
||
1351 | |||
1352 | /* Reset some signal handlers that we may use */ |
||
1353 | signal (SIGCHLD, SIG_DFL); |
||
1354 | signal (SIGINT, SIG_DFL); |
||
1355 | signal (SIGTERM, SIG_DFL); |
||
1356 | signal (SIGHUP, SIG_DFL); |
||
1357 | |||
1358 | /* Be sure we crash if the parent exits |
||
1359 | * and we write to the err_report_pipe |
||
1360 | */ |
||
1361 | signal (SIGPIPE, SIG_DFL); |
||
1362 | |||
1363 | /* Close the parent's end of the pipes; |
||
1364 | * not needed in the close_descriptors case, |
||
1365 | * though |
||
1366 | */ |
||
1367 | close_and_invalidate (&child_err_report_pipe[0]); |
||
1368 | close_and_invalidate (&child_pid_report_pipe[0]); |
||
1369 | close_and_invalidate (&stdin_pipe[1]); |
||
1370 | close_and_invalidate (&stdout_pipe[0]); |
||
1371 | close_and_invalidate (&stderr_pipe[0]); |
||
1372 | |||
1373 | if (intermediate_child) |
||
1374 | { |
||
1375 | /* We need to fork an intermediate child that launches the |
||
1376 | * final child. The purpose of the intermediate child |
||
1377 | * is to exit, so we can waitpid() it immediately. |
||
1378 | * Then the grandchild will not become a zombie. |
||
1379 | */ |
||
1380 | GPid grandchild_pid; |
||
1381 | |||
1382 | grandchild_pid = fork (); |
||
1383 | |||
1384 | if (grandchild_pid < 0) |
||
1385 | { |
||
1386 | /* report -1 as child PID */ |
||
1387 | write_all (child_pid_report_pipe[1], &grandchild_pid, |
||
1388 | sizeof(grandchild_pid)); |
||
1389 | |||
1390 | write_err_and_exit (child_err_report_pipe[1], |
||
1391 | CHILD_FORK_FAILED); |
||
1392 | } |
||
1393 | else if (grandchild_pid == 0) |
||
1394 | { |
||
1395 | close_and_invalidate (&child_pid_report_pipe[1]); |
||
1396 | do_exec (child_err_report_pipe[1], |
||
1397 | stdin_pipe[0], |
||
1398 | stdout_pipe[1], |
||
1399 | stderr_pipe[1], |
||
1400 | working_directory, |
||
1401 | argv, |
||
1402 | envp, |
||
1403 | close_descriptors, |
||
1404 | search_path, |
||
1405 | search_path_from_envp, |
||
1406 | stdout_to_null, |
||
1407 | stderr_to_null, |
||
1408 | child_inherits_stdin, |
||
1409 | file_and_argv_zero, |
||
1410 | child_setup, |
||
1411 | user_data); |
||
1412 | } |
||
1413 | else |
||
1414 | { |
||
1415 | write_all (child_pid_report_pipe[1], &grandchild_pid, sizeof(grandchild_pid)); |
||
1416 | close_and_invalidate (&child_pid_report_pipe[1]); |
||
1417 | |||
1418 | _exit (0); |
||
1419 | } |
||
1420 | } |
||
1421 | else |
||
1422 | { |
||
1423 | /* Just run the child. |
||
1424 | */ |
||
1425 | |||
1426 | do_exec (child_err_report_pipe[1], |
||
1427 | stdin_pipe[0], |
||
1428 | stdout_pipe[1], |
||
1429 | stderr_pipe[1], |
||
1430 | working_directory, |
||
1431 | argv, |
||
1432 | envp, |
||
1433 | close_descriptors, |
||
1434 | search_path, |
||
1435 | search_path_from_envp, |
||
1436 | stdout_to_null, |
||
1437 | stderr_to_null, |
||
1438 | child_inherits_stdin, |
||
1439 | file_and_argv_zero, |
||
1440 | child_setup, |
||
1441 | user_data); |
||
1442 | } |
||
1443 | } |
||
1444 | else |
||
1445 | { |
||
1446 | /* Parent */ |
||
1447 | |||
1448 | gint buf[2]; |
||
1449 | gint n_ints = 0; |
||
1450 | |||
1451 | /* Close the uncared-about ends of the pipes */ |
||
1452 | close_and_invalidate (&child_err_report_pipe[1]); |
||
1453 | close_and_invalidate (&child_pid_report_pipe[1]); |
||
1454 | close_and_invalidate (&stdin_pipe[0]); |
||
1455 | close_and_invalidate (&stdout_pipe[1]); |
||
1456 | close_and_invalidate (&stderr_pipe[1]); |
||
1457 | |||
1458 | /* If we had an intermediate child, reap it */ |
||
1459 | if (intermediate_child) |
||
1460 | { |
||
1461 | wait_again: |
||
1462 | if (waitpid (pid, &status, 0) < 0) |
||
1463 | { |
||
1464 | if (errno == EINTR) |
||
1465 | goto wait_again; |
||
1466 | else if (errno == ECHILD) |
||
1467 | ; /* do nothing, child already reaped */ |
||
1468 | else |
||
1469 | g_warning ("waitpid() should not fail in " |
||
1470 | "'fork_exec_with_pipes'"); |
||
1471 | } |
||
1472 | } |
||
1473 | |||
1474 | |||
1475 | if (!read_ints (child_err_report_pipe[0], |
||
1476 | buf, 2, &n_ints, |
||
1477 | error)) |
||
1478 | goto cleanup_and_fail; |
||
1479 | |||
1480 | if (n_ints >= 2) |
||
1481 | { |
||
1482 | /* Error from the child. */ |
||
1483 | |||
1484 | switch (buf[0]) |
||
1485 | { |
||
1486 | case CHILD_CHDIR_FAILED: |
||
1487 | g_set_error (error, |
||
1488 | G_SPAWN_ERROR, |
||
1489 | G_SPAWN_ERROR_CHDIR, |
||
1490 | _("Failed to change to directory '%s' (%s)"), |
||
1491 | working_directory, |
||
1492 | g_strerror (buf[1])); |
||
1493 | |||
1494 | break; |
||
1495 | |||
1496 | case CHILD_EXEC_FAILED: |
||
1497 | g_set_error (error, |
||
1498 | G_SPAWN_ERROR, |
||
1499 | exec_err_to_g_error (buf[1]), |
||
1500 | _("Failed to execute child process \"%s\" (%s)"), |
||
1501 | argv[0], |
||
1502 | g_strerror (buf[1])); |
||
1503 | |||
1504 | break; |
||
1505 | |||
1506 | case CHILD_DUP2_FAILED: |
||
1507 | g_set_error (error, |
||
1508 | G_SPAWN_ERROR, |
||
1509 | G_SPAWN_ERROR_FAILED, |
||
1510 | _("Failed to redirect output or input of child process (%s)"), |
||
1511 | g_strerror (buf[1])); |
||
1512 | |||
1513 | break; |
||
1514 | |||
1515 | case CHILD_FORK_FAILED: |
||
1516 | g_set_error (error, |
||
1517 | G_SPAWN_ERROR, |
||
1518 | G_SPAWN_ERROR_FORK, |
||
1519 | _("Failed to fork child process (%s)"), |
||
1520 | g_strerror (buf[1])); |
||
1521 | break; |
||
1522 | |||
1523 | default: |
||
1524 | g_set_error (error, |
||
1525 | G_SPAWN_ERROR, |
||
1526 | G_SPAWN_ERROR_FAILED, |
||
1527 | _("Unknown error executing child process \"%s\""), |
||
1528 | argv[0]); |
||
1529 | break; |
||
1530 | } |
||
1531 | |||
1532 | goto cleanup_and_fail; |
||
1533 | } |
||
1534 | |||
1535 | /* Get child pid from intermediate child pipe. */ |
||
1536 | if (intermediate_child) |
||
1537 | { |
||
1538 | n_ints = 0; |
||
1539 | |||
1540 | if (!read_ints (child_pid_report_pipe[0], |
||
1541 | buf, 1, &n_ints, error)) |
||
1542 | goto cleanup_and_fail; |
||
1543 | |||
1544 | if (n_ints < 1) |
||
1545 | { |
||
1546 | int errsv = errno; |
||
1547 | |||
1548 | g_set_error (error, |
||
1549 | G_SPAWN_ERROR, |
||
1550 | G_SPAWN_ERROR_FAILED, |
||
1551 | _("Failed to read enough data from child pid pipe (%s)"), |
||
1552 | g_strerror (errsv)); |
||
1553 | goto cleanup_and_fail; |
||
1554 | } |
||
1555 | else |
||
1556 | { |
||
1557 | /* we have the child pid */ |
||
1558 | pid = buf[0]; |
||
1559 | } |
||
1560 | } |
||
1561 | |||
1562 | /* Success against all odds! return the information */ |
||
1563 | close_and_invalidate (&child_err_report_pipe[0]); |
||
1564 | close_and_invalidate (&child_pid_report_pipe[0]); |
||
1565 | |||
1566 | if (child_pid) |
||
1567 | *child_pid = pid; |
||
1568 | |||
1569 | if (standard_input) |
||
1570 | *standard_input = stdin_pipe[1]; |
||
1571 | if (standard_output) |
||
1572 | *standard_output = stdout_pipe[0]; |
||
1573 | if (standard_error) |
||
1574 | *standard_error = stderr_pipe[0]; |
||
1575 | |||
1576 | return TRUE; |
||
1577 | } |
||
1578 | |||
1579 | cleanup_and_fail: |
||
1580 | |||
1581 | /* There was an error from the Child, reap the child to avoid it being |
||
1582 | a zombie. |
||
1583 | */ |
||
1584 | |||
1585 | if (pid > 0) |
||
1586 | { |
||
1587 | wait_failed: |
||
1588 | if (waitpid (pid, NULL, 0) < 0) |
||
1589 | { |
||
1590 | if (errno == EINTR) |
||
1591 | goto wait_failed; |
||
1592 | else if (errno == ECHILD) |
||
1593 | ; /* do nothing, child already reaped */ |
||
1594 | else |
||
1595 | g_warning ("waitpid() should not fail in " |
||
1596 | "'fork_exec_with_pipes'"); |
||
1597 | } |
||
1598 | } |
||
1599 | |||
1600 | close_and_invalidate (&child_err_report_pipe[0]); |
||
1601 | close_and_invalidate (&child_err_report_pipe[1]); |
||
1602 | close_and_invalidate (&child_pid_report_pipe[0]); |
||
1603 | close_and_invalidate (&child_pid_report_pipe[1]); |
||
1604 | close_and_invalidate (&stdin_pipe[0]); |
||
1605 | close_and_invalidate (&stdin_pipe[1]); |
||
1606 | close_and_invalidate (&stdout_pipe[0]); |
||
1607 | close_and_invalidate (&stdout_pipe[1]); |
||
1608 | close_and_invalidate (&stderr_pipe[0]); |
||
1609 | close_and_invalidate (&stderr_pipe[1]); |
||
1610 | |||
1611 | return FALSE; |
||
1612 | } |
||
1613 | |||
1614 | /* Based on execvp from GNU C Library */ |
||
1615 | |||
1616 | static void |
||
1617 | script_execute (const gchar *file, |
||
1618 | gchar **argv, |
||
1619 | gchar **envp) |
||
1620 | { |
||
1621 | /* Count the arguments. */ |
||
1622 | int argc = 0; |
||
1623 | while (argv[argc]) |
||
1624 | ++argc; |
||
1625 | |||
1626 | /* Construct an argument list for the shell. */ |
||
1627 | { |
||
1628 | gchar **new_argv; |
||
1629 | |||
1630 | new_argv = g_new0 (gchar*, argc + 2); /* /bin/sh and NULL */ |
||
1631 | |||
1632 | new_argv[0] = (char *) "/bin/sh"; |
||
1633 | new_argv[1] = (char *) file; |
||
1634 | while (argc > 0) |
||
1635 | { |
||
1636 | new_argv[argc + 1] = argv[argc]; |
||
1637 | --argc; |
||
1638 | } |
||
1639 | |||
1640 | /* Execute the shell. */ |
||
1641 | if (envp) |
||
1642 | execve (new_argv[0], new_argv, envp); |
||
1643 | else |
||
1644 | execv (new_argv[0], new_argv); |
||
1645 | |||
1646 | g_free (new_argv); |
||
1647 | } |
||
1648 | } |
||
1649 | |||
1650 | static gchar* |
||
1651 | my_strchrnul (const gchar *str, gchar c) |
||
1652 | { |
||
1653 | gchar *p = (gchar*) str; |
||
1654 | while (*p && (*p != c)) |
||
1655 | ++p; |
||
1656 | |||
1657 | return p; |
||
1658 | } |
||
1659 | |||
1660 | static gint |
||
1661 | g_execute (const gchar *file, |
||
1662 | gchar **argv, |
||
1663 | gchar **envp, |
||
1664 | gboolean search_path, |
||
1665 | gboolean search_path_from_envp) |
||
1666 | { |
||
1667 | if (*file == '\0') |
||
1668 | { |
||
1669 | /* We check the simple case first. */ |
||
1670 | errno = ENOENT; |
||
1671 | return -1; |
||
1672 | } |
||
1673 | |||
1674 | if (!(search_path || search_path_from_envp) || strchr (file, '/') != NULL) |
||
1675 | { |
||
1676 | /* Don't search when it contains a slash. */ |
||
1677 | if (envp) |
||
1678 | execve (file, argv, envp); |
||
1679 | else |
||
1680 | execv (file, argv); |
||
1681 | |||
1682 | if (errno == ENOEXEC) |
||
1683 | script_execute (file, argv, envp); |
||
1684 | } |
||
1685 | else |
||
1686 | { |
||
1687 | gboolean got_eacces = 0; |
||
1688 | const gchar *path, *p; |
||
1689 | gchar *name, *freeme; |
||
1690 | gsize len; |
||
1691 | gsize pathlen; |
||
1692 | |||
1693 | path = NULL; |
||
1694 | if (search_path_from_envp) |
||
1695 | path = g_environ_getenv (envp, "PATH"); |
||
1696 | if (search_path && path == NULL) |
||
1697 | path = g_getenv ("PATH"); |
||
1698 | |||
1699 | if (path == NULL) |
||
1700 | { |
||
1701 | /* There is no 'PATH' in the environment. The default |
||
1702 | * search path in libc is the current directory followed by |
||
1703 | * the path 'confstr' returns for '_CS_PATH'. |
||
1704 | */ |
||
1705 | |||
1706 | /* In GLib we put . last, for security, and don't use the |
||
1707 | * unportable confstr(); UNIX98 does not actually specify |
||
1708 | * what to search if PATH is unset. POSIX may, dunno. |
||
1709 | */ |
||
1710 | |||
1711 | path = "/bin:/usr/bin:."; |
||
1712 | } |
||
1713 | |||
1714 | len = strlen (file) + 1; |
||
1715 | pathlen = strlen (path); |
||
1716 | freeme = name = g_malloc (pathlen + len + 1); |
||
1717 | |||
1718 | /* Copy the file name at the top, including '\0' */ |
||
1719 | memcpy (name + pathlen + 1, file, len); |
||
1720 | name = name + pathlen; |
||
1721 | /* And add the slash before the filename */ |
||
1722 | *name = '/'; |
||
1723 | |||
1724 | p = path; |
||
1725 | do |
||
1726 | { |
||
1727 | char *startp; |
||
1728 | |||
1729 | path = p; |
||
1730 | p = my_strchrnul (path, ':'); |
||
1731 | |||
1732 | if (p == path) |
||
1733 | /* Two adjacent colons, or a colon at the beginning or the end |
||
1734 | * of 'PATH' means to search the current directory. |
||
1735 | */ |
||
1736 | startp = name + 1; |
||
1737 | else |
||
1738 | startp = memcpy (name - (p - path), path, p - path); |
||
1739 | |||
1740 | /* Try to execute this name. If it works, execv will not return. */ |
||
1741 | if (envp) |
||
1742 | execve (startp, argv, envp); |
||
1743 | else |
||
1744 | execv (startp, argv); |
||
1745 | |||
1746 | if (errno == ENOEXEC) |
||
1747 | script_execute (startp, argv, envp); |
||
1748 | |||
1749 | switch (errno) |
||
1750 | { |
||
1751 | case EACCES: |
||
1752 | /* Record the we got a 'Permission denied' error. If we end |
||
1753 | * up finding no executable we can use, we want to diagnose |
||
1754 | * that we did find one but were denied access. |
||
1755 | */ |
||
1756 | got_eacces = TRUE; |
||
1757 | |||
1758 | /* FALL THRU */ |
||
1759 | |||
1760 | case ENOENT: |
||
1761 | #ifdef ESTALE |
||
1762 | case ESTALE: |
||
1763 | #endif |
||
1764 | #ifdef ENOTDIR |
||
1765 | case ENOTDIR: |
||
1766 | #endif |
||
1767 | /* Those errors indicate the file is missing or not executable |
||
1768 | * by us, in which case we want to just try the next path |
||
1769 | * directory. |
||
1770 | */ |
||
1771 | break; |
||
1772 | |||
1773 | case ENODEV: |
||
1774 | case ETIMEDOUT: |
||
1775 | /* Some strange filesystems like AFS return even |
||
1776 | * stranger error numbers. They cannot reasonably mean anything |
||
1777 | * else so ignore those, too. |
||
1778 | */ |
||
1779 | break; |
||
1780 | |||
1781 | default: |
||
1782 | /* Some other error means we found an executable file, but |
||
1783 | * something went wrong executing it; return the error to our |
||
1784 | * caller. |
||
1785 | */ |
||
1786 | g_free (freeme); |
||
1787 | return -1; |
||
1788 | } |
||
1789 | } |
||
1790 | while (*p++ != '\0'); |
||
1791 | |||
1792 | /* We tried every element and none of them worked. */ |
||
1793 | if (got_eacces) |
||
1794 | /* At least one failure was due to permissions, so report that |
||
1795 | * error. |
||
1796 | */ |
||
1797 | errno = EACCES; |
||
1798 | |||
1799 | g_free (freeme); |
||
1800 | } |
||
1801 | |||
1802 | /* Return the error from the last attempt (probably ENOENT). */ |
||
1803 | return -1; |
||
1804 | } |
||
1805 | |||
1806 | /** |
||
1807 | * g_spawn_close_pid: |
||
1808 | * @pid: The process reference to close |
||
1809 | * |
||
1810 | * On some platforms, notably Windows, the #GPid type represents a resource |
||
1811 | * which must be closed to prevent resource leaking. g_spawn_close_pid() |
||
1812 | * is provided for this purpose. It should be used on all platforms, even |
||
1813 | * though it doesn't do anything under UNIX. |
||
1814 | **/ |
||
1815 | void |
||
1816 | g_spawn_close_pid (GPid pid) |
||
1817 | { |
||
1818 | } |