source: trunk/third/glib2/glib/gspawn.c @ 20721

Revision 20721, 46.7 KB checked in by ghudson, 20 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r20720, which included commits to RCS files with non-trunk default branches.
Line 
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
34#ifdef HAVE_SYS_SELECT_H
35#include <sys/select.h>
36#endif /* HAVE_SYS_SELECT_H */
37
38#include "glib.h"
39
40#include "glibintl.h"
41
42/* With solaris threads, fork() duplicates all threads, which
43 * a) could cause unexpected side-effects, and b) is expensive.
44 * Once we remove support for solaris threads, the FORK1 #define
45 * should be removedl
46 */
47#ifdef G_THREADS_IMPL_SOLARIS
48#define FORK1() fork1()
49#else
50#define FORK1() fork()
51#endif
52
53static gint g_execute (const gchar  *file,
54                       gchar **argv,
55                       gchar **envp,
56                       gboolean search_path);
57
58static gboolean make_pipe            (gint                  p[2],
59                                      GError              **error);
60static gboolean fork_exec_with_pipes (gboolean              intermediate_child,
61                                      const gchar          *working_directory,
62                                      gchar               **argv,
63                                      gchar               **envp,
64                                      gboolean              close_descriptors,
65                                      gboolean              search_path,
66                                      gboolean              stdout_to_null,
67                                      gboolean              stderr_to_null,
68                                      gboolean              child_inherits_stdin,
69                                      gboolean              file_and_argv_zero,
70                                      GSpawnChildSetupFunc  child_setup,
71                                      gpointer              user_data,
72                                      GPid                 *child_pid,
73                                      gint                 *standard_input,
74                                      gint                 *standard_output,
75                                      gint                 *standard_error,
76                                      GError              **error);
77
78GQuark
79g_spawn_error_quark (void)
80{
81  static GQuark quark = 0;
82  if (quark == 0)
83    quark = g_quark_from_static_string ("g-exec-error-quark");
84  return quark;
85}
86
87/**
88 * g_spawn_async:
89 * @working_directory: child's current working directory, or %NULL to inherit parent's
90 * @argv: child's argument vector
91 * @envp: child's environment, or %NULL to inherit parent's
92 * @flags: flags from #GSpawnFlags
93 * @child_setup: function to run in the child just before exec()
94 * @user_data: user data for @child_setup
95 * @child_pid: return location for child process ID, or %NULL
96 * @error: return location for error
97 *
98 * See g_spawn_async_with_pipes() for a full description; this function
99 * simply calls the g_spawn_async_with_pipes() without any pipes.
100 *
101 * Return value: %TRUE on success, %FALSE if error is set
102 **/
103gboolean
104g_spawn_async (const gchar          *working_directory,
105               gchar               **argv,
106               gchar               **envp,
107               GSpawnFlags           flags,
108               GSpawnChildSetupFunc  child_setup,
109               gpointer              user_data,
110               GPid                 *child_pid,
111               GError              **error)
112{
113  g_return_val_if_fail (argv != NULL, FALSE);
114 
115  return g_spawn_async_with_pipes (working_directory,
116                                   argv, envp,
117                                   flags,
118                                   child_setup,
119                                   user_data,
120                                   child_pid,
121                                   NULL, NULL, NULL,
122                                   error);
123}
124
125/* Avoids a danger in threaded situations (calling close()
126 * on a file descriptor twice, and another thread has
127 * re-opened it since the first close)
128 */
129static gint
130close_and_invalidate (gint *fd)
131{
132  gint ret;
133
134  if (*fd < 0)
135    return -1;
136  else
137    {
138      ret = close (*fd);
139      *fd = -1;
140    }
141
142  return ret;
143}
144
145typedef enum
146{
147  READ_FAILED = 0, /* FALSE */
148  READ_OK,
149  READ_EOF
150} ReadResult;
151
152static ReadResult
153read_data (GString *str,
154           gint     fd,
155           GError **error)
156{
157  gssize bytes;       
158  gchar buf[4096];   
159
160 again:
161 
162  bytes = read (fd, buf, 4096);
163
164  if (bytes == 0)
165    return READ_EOF;
166  else if (bytes > 0)
167    {
168      g_string_append_len (str, buf, bytes);
169      return READ_OK;
170    }
171  else if (bytes < 0 && errno == EINTR)
172    goto again;
173  else if (bytes < 0)
174    {
175      g_set_error (error,
176                   G_SPAWN_ERROR,
177                   G_SPAWN_ERROR_READ,
178                   _("Failed to read data from child process (%s)"),
179                   g_strerror (errno));
180     
181      return READ_FAILED;
182    }
183  else
184    return READ_OK;
185}
186
187/**
188 * g_spawn_sync:
189 * @working_directory: child's current working directory, or %NULL to inherit parent's
190 * @argv: child's argument vector
191 * @envp: child's environment, or %NULL to inherit parent's
192 * @flags: flags from #GSpawnFlags
193 * @child_setup: function to run in the child just before exec()
194 * @user_data: user data for @child_setup
195 * @standard_output: return location for child output
196 * @standard_error: return location for child error messages
197 * @exit_status: child exit status, as returned by waitpid()
198 * @error: return location for error
199 *
200 * Executes a child synchronously (waits for the child to exit before returning).
201 * All output from the child is stored in @standard_output and @standard_error,
202 * if those parameters are non-%NULL. If @exit_status is non-%NULL, the exit
203 * status of the child is stored there as it would be returned by
204 * waitpid(); standard UNIX macros such as WIFEXITED() and WEXITSTATUS()
205 * must be used to evaluate the exit status. If an error occurs, no data is
206 * returned in @standard_output, @standard_error, or @exit_status.
207 *
208 * This function calls g_spawn_async_with_pipes() internally; see that function
209 * for full details on the other parameters.
210 *
211 * Return value: %TRUE on success, %FALSE if an error was set.
212 **/
213gboolean
214g_spawn_sync (const gchar          *working_directory,
215              gchar               **argv,
216              gchar               **envp,
217              GSpawnFlags           flags,
218              GSpawnChildSetupFunc  child_setup,
219              gpointer              user_data,
220              gchar               **standard_output,
221              gchar               **standard_error,
222              gint                 *exit_status,
223              GError              **error)     
224{
225  gint outpipe = -1;
226  gint errpipe = -1;
227  GPid pid;
228  fd_set fds;
229  gint ret;
230  GString *outstr = NULL;
231  GString *errstr = NULL;
232  gboolean failed;
233  gint status;
234 
235  g_return_val_if_fail (argv != NULL, FALSE);
236  g_return_val_if_fail (!(flags & G_SPAWN_DO_NOT_REAP_CHILD), FALSE);
237  g_return_val_if_fail (standard_output == NULL ||
238                        !(flags & G_SPAWN_STDOUT_TO_DEV_NULL), FALSE);
239  g_return_val_if_fail (standard_error == NULL ||
240                        !(flags & G_SPAWN_STDERR_TO_DEV_NULL), FALSE);
241 
242  /* Just to ensure segfaults if callers try to use
243   * these when an error is reported.
244   */
245  if (standard_output)
246    *standard_output = NULL;
247
248  if (standard_error)
249    *standard_error = NULL;
250 
251  if (!fork_exec_with_pipes (FALSE,
252                             working_directory,
253                             argv,
254                             envp,
255                             !(flags & G_SPAWN_LEAVE_DESCRIPTORS_OPEN),
256                             (flags & G_SPAWN_SEARCH_PATH) != 0,
257                             (flags & G_SPAWN_STDOUT_TO_DEV_NULL) != 0,
258                             (flags & G_SPAWN_STDERR_TO_DEV_NULL) != 0,
259                             (flags & G_SPAWN_CHILD_INHERITS_STDIN) != 0,
260                             (flags & G_SPAWN_FILE_AND_ARGV_ZERO) != 0,
261                             child_setup,
262                             user_data,
263                             &pid,
264                             NULL,
265                             standard_output ? &outpipe : NULL,
266                             standard_error ? &errpipe : NULL,
267                             error))
268    return FALSE;
269
270  /* Read data from child. */
271 
272  failed = FALSE;
273
274  if (outpipe >= 0)
275    {
276      outstr = g_string_new (NULL);
277    }
278     
279  if (errpipe >= 0)
280    {
281      errstr = g_string_new (NULL);
282    }
283
284  /* Read data until we get EOF on both pipes. */
285  while (!failed &&
286         (outpipe >= 0 ||
287          errpipe >= 0))
288    {
289      ret = 0;
290         
291      FD_ZERO (&fds);
292      if (outpipe >= 0)
293        FD_SET (outpipe, &fds);
294      if (errpipe >= 0)
295        FD_SET (errpipe, &fds);
296         
297      ret = select (MAX (outpipe, errpipe) + 1,
298                    &fds,
299                    NULL, NULL,
300                    NULL /* no timeout */);
301
302      if (ret < 0 && errno != EINTR)
303        {
304          failed = TRUE;
305
306          g_set_error (error,
307                       G_SPAWN_ERROR,
308                       G_SPAWN_ERROR_READ,
309                       _("Unexpected error in select() reading data from a child process (%s)"),
310                       g_strerror (errno));
311             
312          break;
313        }
314
315      if (outpipe >= 0 && FD_ISSET (outpipe, &fds))
316        {
317          switch (read_data (outstr, outpipe, error))
318            {
319            case READ_FAILED:
320              failed = TRUE;
321              break;
322            case READ_EOF:
323              close_and_invalidate (&outpipe);
324              outpipe = -1;
325              break;
326            default:
327              break;
328            }
329
330          if (failed)
331            break;
332        }
333
334      if (errpipe >= 0 && FD_ISSET (errpipe, &fds))
335        {
336          switch (read_data (errstr, errpipe, error))
337            {
338            case READ_FAILED:
339              failed = TRUE;
340              break;
341            case READ_EOF:
342              close_and_invalidate (&errpipe);
343              errpipe = -1;
344              break;
345            default:
346              break;
347            }
348
349          if (failed)
350            break;
351        }
352    }
353
354  /* These should only be open still if we had an error.  */
355 
356  if (outpipe >= 0)
357    close_and_invalidate (&outpipe);
358  if (errpipe >= 0)
359    close_and_invalidate (&errpipe);
360 
361  /* Wait for child to exit, even if we have
362   * an error pending.
363   */
364 again:
365     
366  ret = waitpid (pid, &status, 0);
367
368  if (ret < 0)
369    {
370      if (errno == EINTR)
371        goto again;
372      else if (errno == ECHILD)
373        {
374          if (exit_status)
375            {
376              g_warning ("In call to g_spawn_sync(), exit status of a child process was requested but SIGCHLD action was set to SIG_IGN and ECHILD was received by waitpid(), so exit status can't be returned. This is a bug in the program calling g_spawn_sync(); either don't request the exit status, or don't set the SIGCHLD action.");
377            }
378          else
379            {
380              /* We don't need the exit status. */
381            }
382        }
383      else
384        {
385          if (!failed) /* avoid error pileups */
386            {
387              failed = TRUE;
388                 
389              g_set_error (error,
390                           G_SPAWN_ERROR,
391                           G_SPAWN_ERROR_READ,
392                           _("Unexpected error in waitpid() (%s)"),
393                           g_strerror (errno));
394            }
395        }
396    }
397 
398  if (failed)
399    {
400      if (outstr)
401        g_string_free (outstr, TRUE);
402      if (errstr)
403        g_string_free (errstr, TRUE);
404
405      return FALSE;
406    }
407  else
408    {
409      if (exit_status)
410        *exit_status = status;
411     
412      if (standard_output)       
413        *standard_output = g_string_free (outstr, FALSE);
414
415      if (standard_error)
416        *standard_error = g_string_free (errstr, FALSE);
417
418      return TRUE;
419    }
420}
421
422/**
423 * g_spawn_async_with_pipes:
424 * @working_directory: child's current working directory, or %NULL to inherit parent's
425 * @argv: child's argument vector
426 * @envp: child's environment, or %NULL to inherit parent's
427 * @flags: flags from #GSpawnFlags
428 * @child_setup: function to run in the child just before exec()
429 * @user_data: user data for @child_setup
430 * @child_pid: return location for child process ID, or %NULL
431 * @standard_input: return location for file descriptor to write to child's stdin, or %NULL
432 * @standard_output: return location for file descriptor to read child's stdout, or %NULL
433 * @standard_error: return location for file descriptor to read child's stderr, or %NULL
434 * @error: return location for error
435 *
436 * Executes a child program asynchronously (your program will not
437 * block waiting for the child to exit). The child program is
438 * specified by the only argument that must be provided, @argv. @argv
439 * should be a %NULL-terminated array of strings, to be passed as the
440 * argument vector for the child. The first string in @argv is of
441 * course the name of the program to execute. By default, the name of
442 * the program must be a full path; the <envar>PATH</envar> shell variable
443 * will only be searched if you pass the %G_SPAWN_SEARCH_PATH flag.
444 *
445 * On Windows, the low-level child process creation API
446 * (CreateProcess())doesn't use argument vectors,
447 * but a command line. The C runtime library's
448 * <function>spawn*()</function> family of functions (which
449 * g_spawn_async_with_pipes() eventually calls) paste the argument
450 * vector elements into a command line, and the C runtime startup code
451 * does a corresponding recostruction of an argument vector from the
452 * command line, to be passed to main(). Complications arise when you have
453 * argument vector elements that contain spaces of double quotes. The
454 * <function>spawn*()</function> functions don't do any quoting or
455 * escaping, but on the other hand the startup code does do unquoting
456 * and unescaping in order to enable receiving arguments with embedded
457 * spaces or double quotes. To work around this asymmetry,
458 * g_spawn_async_with_pipes() will do quoting and escaping on argument
459 * vector elements that need it before calling the C runtime
460 * spawn() function.
461 *
462 * @envp is a %NULL-terminated array of strings, where each string
463 * has the form <literal>KEY=VALUE</literal>. This will become
464 * the child's environment. If @envp is %NULL, the child inherits its
465 * parent's environment.
466 *
467 * @flags should be the bitwise OR of any flags you want to affect the
468 * function's behavior. On Unix, the %G_SPAWN_DO_NOT_REAP_CHILD means
469 * that the child will not be automatically reaped; you must call
470 * waitpid() or handle %SIGCHLD yourself, or the
471 * child will become a zombie. On Windows, the flag means that a
472 * handle to the child will be returned @child_pid. You must call
473 * CloseHandle() on it eventually (or exit the
474 * process), or the child processs will continue to take up some table
475 * space even after its death. Quite similar to zombies on Unix,
476 * actually.
477 *
478 * %G_SPAWN_LEAVE_DESCRIPTORS_OPEN means that the parent's open file
479 * descriptors will be inherited by the child; otherwise all
480 * descriptors except stdin/stdout/stderr will be closed before
481 * calling exec() in the child. %G_SPAWN_SEARCH_PATH
482 * means that <literal>argv[0]</literal> need not be an absolute path, it
483 * will be looked for in the user's <envar>PATH</envar>.
484 * %G_SPAWN_STDOUT_TO_DEV_NULL means that the child's standard output will
485 * be discarded, instead of going to the same location as the parent's
486 * standard output. If you use this flag, @standard_output must be %NULL.
487 * %G_SPAWN_STDERR_TO_DEV_NULL means that the child's standard error
488 * will be discarded, instead of going to the same location as the parent's
489 * standard error. If you use this flag, @standard_error must be %NULL.
490 * %G_SPAWN_CHILD_INHERITS_STDIN means that the child will inherit the parent's
491 * standard input (by default, the child's standard input is attached to
492 * /dev/null). If you use this flag, @standard_input must be %NULL.
493 * %G_SPAWN_FILE_AND_ARGV_ZERO means that the first element of @argv is
494 * the file to execute, while the remaining elements are the
495 * actual argument vector to pass to the file. Normally
496 * g_spawn_async_with_pipes() uses @argv[0] as the file to execute, and
497 * passes all of @argv to the child.
498 *
499 * @child_setup and @user_data are a function and user data. On POSIX
500 * platforms, the function is called in the child after GLib has
501 * performed all the setup it plans to perform (including creating
502 * pipes, closing file descriptors, etc.) but before calling
503 * exec(). That is, @child_setup is called just
504 * before calling exec() in the child. Obviously
505 * actions taken in this function will only affect the child, not the
506 * parent. On Windows, there is no separate fork() and exec()
507 * functionality. Child processes are created and run right away with
508 * one API call, CreateProcess(). @child_setup is
509 * called in the parent process just before creating the child
510 * process. You should carefully consider what you do in @child_setup
511 * if you intend your software to be portable to Windows.
512 *
513 * If non-%NULL, @child_pid will on Unix be filled with the child's
514 * process ID. You can use the process ID to send signals to the
515 * child, or to waitpid() if you specified the
516 * %G_SPAWN_DO_NOT_REAP_CHILD flag. On Windows, @child_pid will be
517 * filled with a handle to the child process only if you specified the
518 * %G_SPAWN_DO_NOT_REAP_CHILD flag. You can then access the child
519 * process using the Win32 API, for example wait for its termination
520 * with the <function>WaitFor*()</function> functions, or examine its
521 * exit code with GetExitCodeProcess(). You should close the handle
522 * with CloseHandle() when you no longer need it.
523 *
524 * If non-%NULL, the @standard_input, @standard_output, @standard_error
525 * locations will be filled with file descriptors for writing to the child's
526 * standard input or reading from its standard output or standard error.
527 * The caller of g_spawn_async_with_pipes() must close these file descriptors
528 * when they are no longer in use. If these parameters are %NULL, the corresponding
529 * pipe won't be created.
530 *
531 * If @standard_input is NULL, the child's standard input is attached to /dev/null
532 * unless %G_SPAWN_CHILD_INHERITS_STDIN is set.
533 *
534 * If @standard_error is NULL, the child's standard error goes to the same location
535 * as the parent's standard error unless %G_SPAWN_STDERR_TO_DEV_NULL is set.
536 *
537 * If @standard_output is NULL, the child's standard output goes to the same location
538 * as the parent's standard output unless %G_SPAWN_STDOUT_TO_DEV_NULL is set.
539 *
540 * @error can be %NULL to ignore errors, or non-%NULL to report errors.
541 * If an error is set, the function returns %FALSE. Errors
542 * are reported even if they occur in the child (for example if the
543 * executable in <literal>argv[0]</literal> is not found). Typically
544 * the <literal>message</literal> field of returned errors should be displayed
545 * to users. Possible errors are those from the #G_SPAWN_ERROR domain.
546 *
547 * If an error occurs, @child_pid, @standard_input, @standard_output,
548 * and @standard_error will not be filled with valid values.
549 *
550 * If @child_pid is not %NULL and an error does not occur then the returned
551 * pid must be closed using g_spawn_close_pid().
552 *
553 * Return value: %TRUE on success, %FALSE if an error was set
554 **/
555gboolean
556g_spawn_async_with_pipes (const gchar          *working_directory,
557                          gchar               **argv,
558                          gchar               **envp,
559                          GSpawnFlags           flags,
560                          GSpawnChildSetupFunc  child_setup,
561                          gpointer              user_data,
562                          GPid                 *child_pid,
563                          gint                 *standard_input,
564                          gint                 *standard_output,
565                          gint                 *standard_error,
566                          GError              **error)
567{
568  g_return_val_if_fail (argv != NULL, FALSE);
569  g_return_val_if_fail (standard_output == NULL ||
570                        !(flags & G_SPAWN_STDOUT_TO_DEV_NULL), FALSE);
571  g_return_val_if_fail (standard_error == NULL ||
572                        !(flags & G_SPAWN_STDERR_TO_DEV_NULL), FALSE);
573  /* can't inherit stdin if we have an input pipe. */
574  g_return_val_if_fail (standard_input == NULL ||
575                        !(flags & G_SPAWN_CHILD_INHERITS_STDIN), FALSE);
576 
577  return fork_exec_with_pipes (!(flags & G_SPAWN_DO_NOT_REAP_CHILD),
578                               working_directory,
579                               argv,
580                               envp,
581                               !(flags & G_SPAWN_LEAVE_DESCRIPTORS_OPEN),
582                               (flags & G_SPAWN_SEARCH_PATH) != 0,
583                               (flags & G_SPAWN_STDOUT_TO_DEV_NULL) != 0,
584                               (flags & G_SPAWN_STDERR_TO_DEV_NULL) != 0,
585                               (flags & G_SPAWN_CHILD_INHERITS_STDIN) != 0,
586                               (flags & G_SPAWN_FILE_AND_ARGV_ZERO) != 0,
587                               child_setup,
588                               user_data,
589                               child_pid,
590                               standard_input,
591                               standard_output,
592                               standard_error,
593                               error);
594}
595
596/**
597 * g_spawn_command_line_sync:
598 * @command_line: a command line
599 * @standard_output: return location for child output
600 * @standard_error: return location for child errors
601 * @exit_status: return location for child exit status
602 * @error: return location for errors
603 *
604 * A simple version of g_spawn_sync() with little-used parameters
605 * removed, taking a command line instead of an argument vector.  See
606 * g_spawn_sync() for full details. @command_line will be parsed by
607 * g_shell_parse_argv(). Unlike g_spawn_sync(), the %G_SPAWN_SEARCH_PATH flag
608 * is enabled. Note that %G_SPAWN_SEARCH_PATH can have security
609 * implications, so consider using g_spawn_sync() directly if
610 * appropriate. Possible errors are those from g_spawn_sync() and those
611 * from g_shell_parse_argv().
612 *
613 * On Windows, please note the implications of g_shell_parse_argv()
614 * parsing @command_line. Space is a separator, and backslashes are
615 * special. Thus you cannot simply pass a @command_line containing
616 * canonical Windows paths, like "c:\\program files\\app\\app.exe", as
617 * the backslashes will be eaten, and the space will act as a
618 * separator. You need to enclose such paths with single quotes, like
619 * "'c:\\program files\\app\\app.exe' 'e:\\folder\\argument.txt'".
620 *
621 * Return value: %TRUE on success, %FALSE if an error was set
622 **/
623gboolean
624g_spawn_command_line_sync (const gchar  *command_line,
625                           gchar       **standard_output,
626                           gchar       **standard_error,
627                           gint         *exit_status,
628                           GError      **error)
629{
630  gboolean retval;
631  gchar **argv = 0;
632
633  g_return_val_if_fail (command_line != NULL, FALSE);
634 
635  if (!g_shell_parse_argv (command_line,
636                           NULL, &argv,
637                           error))
638    return FALSE;
639 
640  retval = g_spawn_sync (NULL,
641                         argv,
642                         NULL,
643                         G_SPAWN_SEARCH_PATH,
644                         NULL,
645                         NULL,
646                         standard_output,
647                         standard_error,
648                         exit_status,
649                         error);
650  g_strfreev (argv);
651
652  return retval;
653}
654
655/**
656 * g_spawn_command_line_async:
657 * @command_line: a command line
658 * @error: return location for errors
659 *
660 * A simple version of g_spawn_async() that parses a command line with
661 * g_shell_parse_argv() and passes it to g_spawn_async(). Runs a
662 * command line in the background. Unlike g_spawn_async(), the
663 * %G_SPAWN_SEARCH_PATH flag is enabled, other flags are not. Note
664 * that %G_SPAWN_SEARCH_PATH can have security implications, so
665 * consider using g_spawn_async() directly if appropriate. Possible
666 * errors are those from g_shell_parse_argv() and g_spawn_async().
667 *
668 * The same concerns on Windows apply as for g_spawn_command_line_sync().
669 *
670 * Return value: %TRUE on success, %FALSE if error is set.
671 **/
672gboolean
673g_spawn_command_line_async (const gchar *command_line,
674                            GError     **error)
675{
676  gboolean retval;
677  gchar **argv = 0;
678
679  g_return_val_if_fail (command_line != NULL, FALSE);
680
681  if (!g_shell_parse_argv (command_line,
682                           NULL, &argv,
683                           error))
684    return FALSE;
685 
686  retval = g_spawn_async (NULL,
687                          argv,
688                          NULL,
689                          G_SPAWN_SEARCH_PATH,
690                          NULL,
691                          NULL,
692                          NULL,
693                          error);
694  g_strfreev (argv);
695
696  return retval;
697}
698
699static gint
700exec_err_to_g_error (gint en)
701{
702  switch (en)
703    {
704#ifdef EACCES
705    case EACCES:
706      return G_SPAWN_ERROR_ACCES;
707      break;
708#endif
709
710#ifdef EPERM
711    case EPERM:
712      return G_SPAWN_ERROR_PERM;
713      break;
714#endif
715
716#ifdef E2BIG
717    case E2BIG:
718      return G_SPAWN_ERROR_2BIG;
719      break;
720#endif
721
722#ifdef ENOEXEC
723    case ENOEXEC:
724      return G_SPAWN_ERROR_NOEXEC;
725      break;
726#endif
727
728#ifdef ENAMETOOLONG
729    case ENAMETOOLONG:
730      return G_SPAWN_ERROR_NAMETOOLONG;
731      break;
732#endif
733
734#ifdef ENOENT
735    case ENOENT:
736      return G_SPAWN_ERROR_NOENT;
737      break;
738#endif
739
740#ifdef ENOMEM
741    case ENOMEM:
742      return G_SPAWN_ERROR_NOMEM;
743      break;
744#endif
745
746#ifdef ENOTDIR
747    case ENOTDIR:
748      return G_SPAWN_ERROR_NOTDIR;
749      break;
750#endif
751
752#ifdef ELOOP
753    case ELOOP:
754      return G_SPAWN_ERROR_LOOP;
755      break;
756#endif
757     
758#ifdef ETXTBUSY
759    case ETXTBUSY:
760      return G_SPAWN_ERROR_TXTBUSY;
761      break;
762#endif
763
764#ifdef EIO
765    case EIO:
766      return G_SPAWN_ERROR_IO;
767      break;
768#endif
769
770#ifdef ENFILE
771    case ENFILE:
772      return G_SPAWN_ERROR_NFILE;
773      break;
774#endif
775
776#ifdef EMFILE
777    case EMFILE:
778      return G_SPAWN_ERROR_MFILE;
779      break;
780#endif
781
782#ifdef EINVAL
783    case EINVAL:
784      return G_SPAWN_ERROR_INVAL;
785      break;
786#endif
787
788#ifdef EISDIR
789    case EISDIR:
790      return G_SPAWN_ERROR_ISDIR;
791      break;
792#endif
793
794#ifdef ELIBBAD
795    case ELIBBAD:
796      return G_SPAWN_ERROR_LIBBAD;
797      break;
798#endif
799     
800    default:
801      return G_SPAWN_ERROR_FAILED;
802      break;
803    }
804}
805
806static gssize
807write_all (gint fd, gconstpointer vbuf, gsize to_write)
808{
809  gchar *buf = (gchar *) vbuf;
810 
811  while (to_write > 0)
812    {
813      gssize count = write (fd, buf, to_write);
814      if (count < 0)
815        {
816          if (errno != EINTR)
817            return FALSE;
818        }
819      else
820        {
821          to_write -= count;
822          buf += count;
823        }
824    }
825 
826  return TRUE;
827}
828
829static void
830write_err_and_exit (gint fd, gint msg)
831{
832  gint en = errno;
833 
834  write_all (fd, &msg, sizeof(msg));
835  write_all (fd, &en, sizeof(en));
836 
837  _exit (1);
838}
839
840static void
841set_cloexec (gint fd)
842{
843  fcntl (fd, F_SETFD, FD_CLOEXEC);
844}
845
846static gint
847sane_dup2 (gint fd1, gint fd2)
848{
849  gint ret;
850
851 retry:
852  ret = dup2 (fd1, fd2);
853  if (ret < 0 && errno == EINTR)
854    goto retry;
855
856  return ret;
857}
858
859enum
860{
861  CHILD_CHDIR_FAILED,
862  CHILD_EXEC_FAILED,
863  CHILD_DUP2_FAILED,
864  CHILD_FORK_FAILED
865};
866
867static void
868do_exec (gint                  child_err_report_fd,
869         gint                  stdin_fd,
870         gint                  stdout_fd,
871         gint                  stderr_fd,
872         const gchar          *working_directory,
873         gchar               **argv,
874         gchar               **envp,
875         gboolean              close_descriptors,
876         gboolean              search_path,
877         gboolean              stdout_to_null,
878         gboolean              stderr_to_null,
879         gboolean              child_inherits_stdin,
880         gboolean              file_and_argv_zero,
881         GSpawnChildSetupFunc  child_setup,
882         gpointer              user_data)
883{
884  if (working_directory && chdir (working_directory) < 0)
885    write_err_and_exit (child_err_report_fd,
886                        CHILD_CHDIR_FAILED);
887
888  /* Close all file descriptors but stdin stdout and stderr as
889   * soon as we exec. Note that this includes
890   * child_err_report_fd, which keeps the parent from blocking
891   * forever on the other end of that pipe.
892   */
893  if (close_descriptors)
894    {
895      gint open_max;
896      gint i;
897     
898      open_max = sysconf (_SC_OPEN_MAX);
899      for (i = 3; i < open_max; i++)
900        set_cloexec (i);
901    }
902  else
903    {
904      /* We need to do child_err_report_fd anyway */
905      set_cloexec (child_err_report_fd);
906    }
907 
908  /* Redirect pipes as required */
909 
910  if (stdin_fd >= 0)
911    {
912      /* dup2 can't actually fail here I don't think */
913         
914      if (sane_dup2 (stdin_fd, 0) < 0)
915        write_err_and_exit (child_err_report_fd,
916                            CHILD_DUP2_FAILED);
917
918      /* ignore this if it doesn't work */
919      close_and_invalidate (&stdin_fd);
920    }
921  else if (!child_inherits_stdin)
922    {
923      /* Keep process from blocking on a read of stdin */
924      gint read_null = open ("/dev/null", O_RDONLY);
925      sane_dup2 (read_null, 0);
926      close_and_invalidate (&read_null);
927    }
928
929  if (stdout_fd >= 0)
930    {
931      /* dup2 can't actually fail here I don't think */
932         
933      if (sane_dup2 (stdout_fd, 1) < 0)
934        write_err_and_exit (child_err_report_fd,
935                            CHILD_DUP2_FAILED);
936
937      /* ignore this if it doesn't work */
938      close_and_invalidate (&stdout_fd);
939    }
940  else if (stdout_to_null)
941    {
942      gint write_null = open ("/dev/null", O_WRONLY);
943      sane_dup2 (write_null, 1);
944      close_and_invalidate (&write_null);
945    }
946
947  if (stderr_fd >= 0)
948    {
949      /* dup2 can't actually fail here I don't think */
950         
951      if (sane_dup2 (stderr_fd, 2) < 0)
952        write_err_and_exit (child_err_report_fd,
953                            CHILD_DUP2_FAILED);
954
955      /* ignore this if it doesn't work */
956      close_and_invalidate (&stderr_fd);
957    }
958  else if (stderr_to_null)
959    {
960      gint write_null = open ("/dev/null", O_WRONLY);
961      sane_dup2 (write_null, 2);
962      close_and_invalidate (&write_null);
963    }
964 
965  /* Call user function just before we exec */
966  if (child_setup)
967    {
968      (* child_setup) (user_data);
969    }
970
971  g_execute (argv[0],
972             file_and_argv_zero ? argv + 1 : argv,
973             envp, search_path);
974
975  /* Exec failed */
976  write_err_and_exit (child_err_report_fd,
977                      CHILD_EXEC_FAILED);
978}
979
980static gboolean
981read_ints (int      fd,
982           gint*    buf,
983           gint     n_ints_in_buf,   
984           gint    *n_ints_read,     
985           GError **error)
986{
987  gsize bytes = 0;   
988 
989  while (TRUE)
990    {
991      gssize chunk;   
992
993      if (bytes >= sizeof(gint)*2)
994        break; /* give up, who knows what happened, should not be
995                * possible.
996                */
997         
998    again:
999      chunk = read (fd,
1000                    ((gchar*)buf) + bytes,
1001                    sizeof(gint) * n_ints_in_buf - bytes);
1002      if (chunk < 0 && errno == EINTR)
1003        goto again;
1004         
1005      if (chunk < 0)
1006        {
1007          /* Some weird shit happened, bail out */
1008             
1009          g_set_error (error,
1010                       G_SPAWN_ERROR,
1011                       G_SPAWN_ERROR_FAILED,
1012                       _("Failed to read from child pipe (%s)"),
1013                       g_strerror (errno));
1014
1015          return FALSE;
1016        }
1017      else if (chunk == 0)
1018        break; /* EOF */
1019      else /* chunk > 0 */
1020        bytes += chunk;
1021    }
1022
1023  *n_ints_read = (gint)(bytes / sizeof(gint));
1024
1025  return TRUE;
1026}
1027
1028static gboolean
1029fork_exec_with_pipes (gboolean              intermediate_child,
1030                      const gchar          *working_directory,
1031                      gchar               **argv,
1032                      gchar               **envp,
1033                      gboolean              close_descriptors,
1034                      gboolean              search_path,
1035                      gboolean              stdout_to_null,
1036                      gboolean              stderr_to_null,
1037                      gboolean              child_inherits_stdin,
1038                      gboolean              file_and_argv_zero,
1039                      GSpawnChildSetupFunc  child_setup,
1040                      gpointer              user_data,
1041                      GPid                 *child_pid,
1042                      gint                 *standard_input,
1043                      gint                 *standard_output,
1044                      gint                 *standard_error,
1045                      GError              **error)     
1046{
1047  GPid pid = -1;
1048  gint stdin_pipe[2] = { -1, -1 };
1049  gint stdout_pipe[2] = { -1, -1 };
1050  gint stderr_pipe[2] = { -1, -1 };
1051  gint child_err_report_pipe[2] = { -1, -1 };
1052  gint child_pid_report_pipe[2] = { -1, -1 };
1053  gint status;
1054 
1055  if (!make_pipe (child_err_report_pipe, error))
1056    return FALSE;
1057
1058  if (intermediate_child && !make_pipe (child_pid_report_pipe, error))
1059    goto cleanup_and_fail;
1060 
1061  if (standard_input && !make_pipe (stdin_pipe, error))
1062    goto cleanup_and_fail;
1063 
1064  if (standard_output && !make_pipe (stdout_pipe, error))
1065    goto cleanup_and_fail;
1066
1067  if (standard_error && !make_pipe (stderr_pipe, error))
1068    goto cleanup_and_fail;
1069
1070  pid = FORK1 ();
1071
1072  if (pid < 0)
1073    {     
1074      g_set_error (error,
1075                   G_SPAWN_ERROR,
1076                   G_SPAWN_ERROR_FORK,
1077                   _("Failed to fork (%s)"),
1078                   g_strerror (errno));
1079
1080      goto cleanup_and_fail;
1081    }
1082  else if (pid == 0)
1083    {
1084      /* Immediate child. This may or may not be the child that
1085       * actually execs the new process.
1086       */
1087     
1088      /* Be sure we crash if the parent exits
1089       * and we write to the err_report_pipe
1090       */
1091      signal (SIGPIPE, SIG_DFL);
1092
1093      /* Close the parent's end of the pipes;
1094       * not needed in the close_descriptors case,
1095       * though
1096       */
1097      close_and_invalidate (&child_err_report_pipe[0]);
1098      close_and_invalidate (&child_pid_report_pipe[0]);
1099      close_and_invalidate (&stdin_pipe[1]);
1100      close_and_invalidate (&stdout_pipe[0]);
1101      close_and_invalidate (&stderr_pipe[0]);
1102     
1103      if (intermediate_child)
1104        {
1105          /* We need to fork an intermediate child that launches the
1106           * final child. The purpose of the intermediate child
1107           * is to exit, so we can waitpid() it immediately.
1108           * Then the grandchild will not become a zombie.
1109           */
1110          GPid grandchild_pid;
1111
1112          grandchild_pid = FORK1 ();
1113
1114          if (grandchild_pid < 0)
1115            {
1116              /* report -1 as child PID */
1117              write_all (child_pid_report_pipe[1], &grandchild_pid,
1118                         sizeof(grandchild_pid));
1119             
1120              write_err_and_exit (child_err_report_pipe[1],
1121                                  CHILD_FORK_FAILED);             
1122            }
1123          else if (grandchild_pid == 0)
1124            {
1125              do_exec (child_err_report_pipe[1],
1126                       stdin_pipe[0],
1127                       stdout_pipe[1],
1128                       stderr_pipe[1],
1129                       working_directory,
1130                       argv,
1131                       envp,
1132                       close_descriptors,
1133                       search_path,
1134                       stdout_to_null,
1135                       stderr_to_null,
1136                       child_inherits_stdin,
1137                       file_and_argv_zero,
1138                       child_setup,
1139                       user_data);
1140            }
1141          else
1142            {
1143              write_all (child_pid_report_pipe[1], &grandchild_pid, sizeof(grandchild_pid));
1144              close_and_invalidate (&child_pid_report_pipe[1]);
1145             
1146              _exit (0);
1147            }
1148        }
1149      else
1150        {
1151          /* Just run the child.
1152           */
1153
1154          do_exec (child_err_report_pipe[1],
1155                   stdin_pipe[0],
1156                   stdout_pipe[1],
1157                   stderr_pipe[1],
1158                   working_directory,
1159                   argv,
1160                   envp,
1161                   close_descriptors,
1162                   search_path,
1163                   stdout_to_null,
1164                   stderr_to_null,
1165                   child_inherits_stdin,
1166                   file_and_argv_zero,
1167                   child_setup,
1168                   user_data);
1169        }
1170    }
1171  else
1172    {
1173      /* Parent */
1174     
1175      gint buf[2];
1176      gint n_ints = 0;   
1177
1178      /* Close the uncared-about ends of the pipes */
1179      close_and_invalidate (&child_err_report_pipe[1]);
1180      close_and_invalidate (&child_pid_report_pipe[1]);
1181      close_and_invalidate (&stdin_pipe[0]);
1182      close_and_invalidate (&stdout_pipe[1]);
1183      close_and_invalidate (&stderr_pipe[1]);
1184
1185      /* If we had an intermediate child, reap it */
1186      if (intermediate_child)
1187        {
1188        wait_again:
1189          if (waitpid (pid, &status, 0) < 0)
1190            {
1191              if (errno == EINTR)
1192                goto wait_again;
1193              else if (errno == ECHILD)
1194                ; /* do nothing, child already reaped */
1195              else
1196                g_warning ("waitpid() should not fail in "
1197                           "'fork_exec_with_pipes'");
1198            }
1199        }
1200     
1201
1202      if (!read_ints (child_err_report_pipe[0],
1203                      buf, 2, &n_ints,
1204                      error))
1205        goto cleanup_and_fail;
1206       
1207      if (n_ints >= 2)
1208        {
1209          /* Error from the child. */
1210
1211          switch (buf[0])
1212            {
1213            case CHILD_CHDIR_FAILED:
1214              g_set_error (error,
1215                           G_SPAWN_ERROR,
1216                           G_SPAWN_ERROR_CHDIR,
1217                           _("Failed to change to directory '%s' (%s)"),
1218                           working_directory,
1219                           g_strerror (buf[1]));
1220
1221              break;
1222             
1223            case CHILD_EXEC_FAILED:
1224              g_set_error (error,
1225                           G_SPAWN_ERROR,
1226                           exec_err_to_g_error (buf[1]),
1227                           _("Failed to execute child process \"%s\" (%s)"),
1228                           argv[0],
1229                           g_strerror (buf[1]));
1230
1231              break;
1232             
1233            case CHILD_DUP2_FAILED:
1234              g_set_error (error,
1235                           G_SPAWN_ERROR,
1236                           G_SPAWN_ERROR_FAILED,
1237                           _("Failed to redirect output or input of child process (%s)"),
1238                           g_strerror (buf[1]));
1239
1240              break;
1241
1242            case CHILD_FORK_FAILED:
1243              g_set_error (error,
1244                           G_SPAWN_ERROR,
1245                           G_SPAWN_ERROR_FORK,
1246                           _("Failed to fork child process (%s)"),
1247                           g_strerror (buf[1]));
1248              break;
1249             
1250            default:
1251              g_set_error (error,
1252                           G_SPAWN_ERROR,
1253                           G_SPAWN_ERROR_FAILED,
1254                           _("Unknown error executing child process \"%s\""),
1255                           argv[0]);
1256              break;
1257            }
1258
1259          goto cleanup_and_fail;
1260        }
1261
1262      /* Get child pid from intermediate child pipe. */
1263      if (intermediate_child)
1264        {
1265          n_ints = 0;
1266         
1267          if (!read_ints (child_pid_report_pipe[0],
1268                          buf, 1, &n_ints, error))
1269            goto cleanup_and_fail;
1270
1271          if (n_ints < 1)
1272            {
1273              g_set_error (error,
1274                           G_SPAWN_ERROR,
1275                           G_SPAWN_ERROR_FAILED,
1276                           _("Failed to read enough data from child pid pipe (%s)"),
1277                           g_strerror (errno));
1278              goto cleanup_and_fail;
1279            }
1280          else
1281            {
1282              /* we have the child pid */
1283              pid = buf[0];
1284            }
1285        }
1286     
1287      /* Success against all odds! return the information */
1288      close_and_invalidate (&child_err_report_pipe[0]);
1289      close_and_invalidate (&child_pid_report_pipe[0]);
1290 
1291      if (child_pid)
1292        *child_pid = pid;
1293
1294      if (standard_input)
1295        *standard_input = stdin_pipe[1];
1296      if (standard_output)
1297        *standard_output = stdout_pipe[0];
1298      if (standard_error)
1299        *standard_error = stderr_pipe[0];
1300     
1301      return TRUE;
1302    }
1303
1304 cleanup_and_fail:
1305
1306  /* There was an error from the Child, reap the child to avoid it being
1307     a zombie.
1308   */
1309
1310  if (pid > 0)
1311  {
1312    wait_failed:
1313     if (waitpid (pid, NULL, 0) < 0)
1314       {
1315          if (errno == EINTR)
1316            goto wait_failed;
1317          else if (errno == ECHILD)
1318            ; /* do nothing, child already reaped */
1319          else
1320            g_warning ("waitpid() should not fail in "
1321                       "'fork_exec_with_pipes'");
1322       }
1323   }
1324
1325  close_and_invalidate (&child_err_report_pipe[0]);
1326  close_and_invalidate (&child_err_report_pipe[1]);
1327  close_and_invalidate (&child_pid_report_pipe[0]);
1328  close_and_invalidate (&child_pid_report_pipe[1]);
1329  close_and_invalidate (&stdin_pipe[0]);
1330  close_and_invalidate (&stdin_pipe[1]);
1331  close_and_invalidate (&stdout_pipe[0]);
1332  close_and_invalidate (&stdout_pipe[1]);
1333  close_and_invalidate (&stderr_pipe[0]);
1334  close_and_invalidate (&stderr_pipe[1]);
1335
1336  return FALSE;
1337}
1338
1339static gboolean
1340make_pipe (gint     p[2],
1341           GError **error)
1342{
1343  if (pipe (p) < 0)
1344    {
1345      g_set_error (error,
1346                   G_SPAWN_ERROR,
1347                   G_SPAWN_ERROR_FAILED,
1348                   _("Failed to create pipe for communicating with child process (%s)"),
1349                   g_strerror (errno));
1350      return FALSE;
1351    }
1352  else
1353    return TRUE;
1354}
1355
1356/* Based on execvp from GNU C Library */
1357
1358static void
1359script_execute (const gchar *file,
1360                gchar      **argv,
1361                gchar      **envp,
1362                gboolean     search_path)
1363{
1364  /* Count the arguments.  */
1365  int argc = 0;
1366  while (argv[argc])
1367    ++argc;
1368 
1369  /* Construct an argument list for the shell.  */
1370  {
1371    gchar **new_argv;
1372
1373    new_argv = g_new0 (gchar*, argc + 2); /* /bin/sh and NULL */
1374   
1375    new_argv[0] = (char *) "/bin/sh";
1376    new_argv[1] = (char *) file;
1377    while (argc > 0)
1378      {
1379        new_argv[argc + 1] = argv[argc];
1380        --argc;
1381      }
1382
1383    /* Execute the shell. */
1384    if (envp)
1385      execve (new_argv[0], new_argv, envp);
1386    else
1387      execv (new_argv[0], new_argv);
1388   
1389    g_free (new_argv);
1390  }
1391}
1392
1393static gchar*
1394my_strchrnul (const gchar *str, gchar c)
1395{
1396  gchar *p = (gchar*) str;
1397  while (*p && (*p != c))
1398    ++p;
1399
1400  return p;
1401}
1402
1403static gint
1404g_execute (const gchar *file,
1405           gchar      **argv,
1406           gchar      **envp,
1407           gboolean     search_path)
1408{
1409  if (*file == '\0')
1410    {
1411      /* We check the simple case first. */
1412      errno = ENOENT;
1413      return -1;
1414    }
1415
1416  if (!search_path || strchr (file, '/') != NULL)
1417    {
1418      /* Don't search when it contains a slash. */
1419      if (envp)
1420        execve (file, argv, envp);
1421      else
1422        execv (file, argv);
1423     
1424      if (errno == ENOEXEC)
1425        script_execute (file, argv, envp, FALSE);
1426    }
1427  else
1428    {
1429      gboolean got_eacces = 0;
1430      const gchar *path, *p;
1431      gchar *name, *freeme;
1432      size_t len;
1433      size_t pathlen;
1434
1435      path = g_getenv ("PATH");
1436      if (path == NULL)
1437        {
1438          /* There is no `PATH' in the environment.  The default
1439           * search path in libc is the current directory followed by
1440           * the path `confstr' returns for `_CS_PATH'.
1441           */
1442
1443          /* In GLib we put . last, for security, and don't use the
1444           * unportable confstr(); UNIX98 does not actually specify
1445           * what to search if PATH is unset. POSIX may, dunno.
1446           */
1447         
1448          path = "/bin:/usr/bin:.";
1449        }
1450
1451      len = strlen (file) + 1;
1452      pathlen = strlen (path);
1453      freeme = name = g_malloc (pathlen + len + 1);
1454     
1455      /* Copy the file name at the top, including '\0'  */
1456      memcpy (name + pathlen + 1, file, len);
1457      name = name + pathlen;
1458      /* And add the slash before the filename  */
1459      *name = '/';
1460
1461      p = path;
1462      do
1463        {
1464          char *startp;
1465
1466          path = p;
1467          p = my_strchrnul (path, ':');
1468
1469          if (p == path)
1470            /* Two adjacent colons, or a colon at the beginning or the end
1471             * of `PATH' means to search the current directory.
1472             */
1473            startp = name + 1;
1474          else
1475            startp = memcpy (name - (p - path), path, p - path);
1476
1477          /* Try to execute this name.  If it works, execv will not return.  */
1478          if (envp)
1479            execve (startp, argv, envp);
1480          else
1481            execv (startp, argv);
1482         
1483          if (errno == ENOEXEC)
1484            script_execute (startp, argv, envp, search_path);
1485
1486          switch (errno)
1487            {
1488            case EACCES:
1489              /* Record the we got a `Permission denied' error.  If we end
1490               * up finding no executable we can use, we want to diagnose
1491               * that we did find one but were denied access.
1492               */
1493              got_eacces = TRUE;
1494
1495              /* FALL THRU */
1496             
1497            case ENOENT:
1498#ifdef ESTALE
1499            case ESTALE:
1500#endif
1501#ifdef ENOTDIR
1502            case ENOTDIR:
1503#endif
1504              /* Those errors indicate the file is missing or not executable
1505               * by us, in which case we want to just try the next path
1506               * directory.
1507               */
1508              break;
1509
1510            default:
1511              /* Some other error means we found an executable file, but
1512               * something went wrong executing it; return the error to our
1513               * caller.
1514               */
1515              g_free (freeme);
1516              return -1;
1517            }
1518        }
1519      while (*p++ != '\0');
1520
1521      /* We tried every element and none of them worked.  */
1522      if (got_eacces)
1523        /* At least one failure was due to permissions, so report that
1524         * error.
1525         */
1526        errno = EACCES;
1527
1528      g_free (freeme);
1529    }
1530
1531  /* Return the error from the last attempt (probably ENOENT).  */
1532  return -1;
1533}
1534
1535/**
1536 * g_spawn_close_pid:
1537 * @pid: The process identifier to close
1538 *
1539 * On some platforms, notably WIN32, the #GPid type represents a resource
1540 * which must be closed to prevent resource leaking. g_spawn_close_pid()
1541 * is provided for this purpose. It should be used on all platforms, even
1542 * though it doesn't do anything under UNIX.
1543 **/
1544void
1545g_spawn_close_pid (GPid pid)
1546{
1547}
Note: See TracBrowser for help on using the repository browser.