Imported Upstream version 2.74.3
[platform/upstream/glib.git] / glib / gspawn-win32.c
1 /* gspawn-win32.c - Process launching on Win32
2  *
3  *  Copyright 2000 Red Hat, Inc.
4  *  Copyright 2003 Tor Lillqvist
5  *
6  * SPDX-License-Identifier: LGPL-2.1-or-later
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public License
19  * along with this library; if not, see <http://www.gnu.org/licenses/>.
20  */
21
22 /*
23  * Implementation details on Win32.
24  *
25  * - There is no way to set the no-inherit flag for
26  *   a "file descriptor" in the MS C runtime. The flag is there,
27  *   and the dospawn() function uses it, but unfortunately
28  *   this flag can only be set when opening the file.
29  * - As there is no fork(), we cannot reliably change directory
30  *   before starting the child process. (There might be several threads
31  *   running, and the current directory is common for all threads.)
32  *
33  * Thus, we must in many cases use a helper program to handle closing
34  * of (inherited) file descriptors and changing of directory. The
35  * helper process is also needed if the standard input, standard
36  * output, or standard error of the process to be run are supposed to
37  * be redirected somewhere.
38  *
39  * The structure of the source code in this file is a mess, I know.
40  */
41
42 /* Define this to get some logging all the time */
43 /* #define G_SPAWN_WIN32_DEBUG */
44
45 #include "config.h"
46
47 #include "glib-init.h"
48 #include "glib-private.h"
49 #include "glib.h"
50 #include "glibintl.h"
51 #include "gprintfint.h"
52 #include "gspawn-private.h"
53 #include "gthread.h"
54
55 #include <string.h>
56 #include <stdlib.h>
57 #include <stdio.h>
58
59 #include <windows.h>
60 #include <errno.h>
61 #include <fcntl.h>
62 #include <io.h>
63 #include <process.h>
64 #include <direct.h>
65 #include <wchar.h>
66
67 #ifdef _MSC_VER
68 #include <vcruntime.h> /* for _UCRT */
69 #endif
70
71 #ifndef GSPAWN_HELPER
72 #ifdef G_SPAWN_WIN32_DEBUG
73   static int debug = 1;
74   #define SETUP_DEBUG() /* empty */
75 #else
76   static int debug = -1;
77   #define SETUP_DEBUG()                                 \
78     G_STMT_START                                        \
79       {                                                 \
80         if (debug == -1)                                \
81           {                                             \
82             if (g_getenv ("G_SPAWN_WIN32_DEBUG") != NULL)       \
83               debug = 1;                                \
84             else                                        \
85               debug = 0;                                \
86           }                                             \
87       }                                                 \
88     G_STMT_END
89 #endif
90 #endif
91
92 enum
93 {
94   CHILD_NO_ERROR,
95   CHILD_CHDIR_FAILED,
96   CHILD_SPAWN_FAILED,
97   CHILD_SPAWN_NOENT,
98   CHILD_DUP_FAILED,
99 };
100
101 enum {
102   ARG_CHILD_ERR_REPORT = 1,
103   ARG_HELPER_SYNC,
104   ARG_STDIN,
105   ARG_STDOUT,
106   ARG_STDERR,
107   ARG_WORKING_DIRECTORY,
108   ARG_CLOSE_DESCRIPTORS,
109   ARG_USE_PATH,
110   ARG_WAIT,
111   ARG_FDS,
112   ARG_PROGRAM,
113   ARG_COUNT = ARG_PROGRAM
114 };
115
116 #ifndef GSPAWN_HELPER
117
118 #ifdef _WIN64
119 #define HELPER_PROCESS "gspawn-win64-helper"
120 #else
121 #define HELPER_PROCESS "gspawn-win32-helper"
122 #endif
123
124 #ifndef _UCRT
125
126 /* The wspawn*e functions are thread-safe only in the Universal
127  * CRT (UCRT). If we are linking against the MSVCRT.dll or the
128  * pre-2015 MSVC runtime (MSVCRXXX.dll), then we have to use a
129  * mutex.
130  */
131
132 static GMutex safe_wspawn_e_mutex;
133
134 static intptr_t
135 safe_wspawnve (int _Mode,
136                const wchar_t *_Filename,
137                const wchar_t *const *_ArgList,
138                const wchar_t *const *_Env)
139 {
140   intptr_t ret_val = -1;
141
142   g_mutex_lock (&safe_wspawn_e_mutex);
143   ret_val = _wspawnve (_Mode, _Filename, _ArgList, _Env);
144   g_mutex_unlock (&safe_wspawn_e_mutex);
145
146   return ret_val;
147 }
148
149 static intptr_t
150 safe_wspawnvpe (int _Mode,
151                 const wchar_t *_Filename,
152                 const wchar_t *const *_ArgList,
153                 const wchar_t *const *_Env)
154 {
155   intptr_t ret_val = -1;
156
157   g_mutex_lock (&safe_wspawn_e_mutex);
158   ret_val = _wspawnvpe (_Mode, _Filename, _ArgList, _Env);
159   g_mutex_unlock (&safe_wspawn_e_mutex);
160
161   return ret_val;
162 }
163
164 #else
165
166 #define safe_wspawnve _spawnve
167 #define safe_wspawnvpe _wspawnvpe
168
169 #endif /* _UCRT */
170
171 /* This logic has a copy for wchar_t in gspawn-win32-helper.c, protect_wargv() */
172 static gchar *
173 protect_argv_string (const gchar *string)
174 {
175   const gchar *p = string;
176   gchar *retval, *q;
177   gint len = 0;
178   gint pre_bslash = 0;
179   gboolean need_dblquotes = FALSE;
180   while (*p)
181     {
182       if (*p == ' ' || *p == '\t')
183         need_dblquotes = TRUE;
184       /* estimate max len, assuming that all escapable characters will be escaped */
185       if (*p == '"' || *p == '\\')
186         len += 2;
187       else
188         len += 1;
189       p++;
190     }
191   
192   q = retval = g_malloc (len + need_dblquotes*2 + 1);
193   p = string;
194
195   if (need_dblquotes)
196     *q++ = '"';
197   /* Only quotes and backslashes preceding quotes are escaped:
198    * see "Parsing C Command-Line Arguments" at
199    * https://docs.microsoft.com/en-us/cpp/c-language/parsing-c-command-line-arguments
200    */
201   while (*p)
202     {
203       if (*p == '"')
204         {
205           /* Add backslash for escaping quote itself */
206           *q++ = '\\';
207           /* Add backslash for every preceding backslash for escaping it */
208           for (;pre_bslash > 0; --pre_bslash)
209             *q++ = '\\';
210         }
211
212       /* Count length of continuous sequence of preceding backslashes. */
213       if (*p == '\\')
214         ++pre_bslash;
215       else
216         pre_bslash = 0;
217
218       *q++ = *p;
219       p++;
220     }
221   
222   if (need_dblquotes)
223     {
224       /* Add backslash for every preceding backslash for escaping it,
225        * do NOT escape quote itself.
226        */
227       for (;pre_bslash > 0; --pre_bslash)
228         *q++ = '\\';
229       *q++ = '"';
230     }
231   *q++ = '\0';
232
233   return retval;
234 }
235
236 static gint
237 protect_argv (const gchar * const   *argv,
238               gchar               ***new_argv)
239 {
240   gint i;
241   gint argc = 0;
242   
243   while (argv[argc])
244     ++argc;
245   *new_argv = g_new (gchar *, argc+1);
246
247   /* Quote each argv element if necessary, so that it will get
248    * reconstructed correctly in the C runtime startup code.  Note that
249    * the unquoting algorithm in the C runtime is really weird, and
250    * rather different than what Unix shells do. See stdargv.c in the C
251    * runtime sources (in the Platform SDK, in src/crt).
252    *
253    * Note that a new_argv[0] constructed by this function should
254    * *not* be passed as the filename argument to a spawn* or exec*
255    * family function. That argument should be the real file name
256    * without any quoting.
257    */
258   for (i = 0; i < argc; i++)
259     (*new_argv)[i] = protect_argv_string (argv[i]);
260
261   (*new_argv)[argc] = NULL;
262
263   return argc;
264 }
265
266 G_DEFINE_QUARK (g-exec-error-quark, g_spawn_error)
267 G_DEFINE_QUARK (g-spawn-exit-error-quark, g_spawn_exit_error)
268
269 gboolean
270 g_spawn_async (const gchar          *working_directory,
271                gchar               **argv,
272                gchar               **envp,
273                GSpawnFlags           flags,
274                GSpawnChildSetupFunc  child_setup,
275                gpointer              user_data,
276                GPid                 *child_pid,
277                GError              **error)
278 {
279   g_return_val_if_fail (argv != NULL && argv[0] != NULL, FALSE);
280   
281   return g_spawn_async_with_pipes (working_directory,
282                                    argv, envp,
283                                    flags,
284                                    child_setup,
285                                    user_data,
286                                    child_pid,
287                                    NULL, NULL, NULL,
288                                    error);
289 }
290
291 /* Avoids a danger in threaded situations (calling close()
292  * on a file descriptor twice, and another thread has
293  * re-opened it since the first close)
294  */
295 static void
296 close_and_invalidate (gint *fd)
297 {
298   if (*fd < 0)
299     return;
300
301   close (*fd);
302   *fd = -1;
303 }
304
305 typedef enum
306 {
307   READ_FAILED = 0, /* FALSE */
308   READ_OK,
309   READ_EOF
310 } ReadResult;
311
312 static ReadResult
313 read_data (GString     *str,
314            GIOChannel  *iochannel,
315            GError     **error)
316 {
317   GIOStatus giostatus;
318   gsize bytes;
319   gchar buf[4096];
320
321  again:
322   
323   giostatus = g_io_channel_read_chars (iochannel, buf, sizeof (buf), &bytes, NULL);
324
325   if (bytes == 0)
326     return READ_EOF;
327   else if (bytes > 0)
328     {
329       g_string_append_len (str, buf, bytes);
330       return READ_OK;
331     }
332   else if (giostatus == G_IO_STATUS_AGAIN)
333     goto again;
334   else if (giostatus == G_IO_STATUS_ERROR)
335     {
336       g_set_error_literal (error, G_SPAWN_ERROR, G_SPAWN_ERROR_READ,
337                            _("Failed to read data from child process"));
338       
339       return READ_FAILED;
340     }
341   else
342     return READ_OK;
343 }
344
345 static gboolean
346 make_pipe (gint     p[2],
347            GError **error)
348 {
349   if (_pipe (p, 4096, _O_BINARY) < 0)
350     {
351       int errsv = errno;
352
353       g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED,
354                    _("Failed to create pipe for communicating with child process (%s)"),
355                    g_strerror (errsv));
356       return FALSE;
357     }
358   else
359     return TRUE;
360 }
361
362 /* The helper process writes a status report back to us, through a
363  * pipe, consisting of two ints.
364  */
365 static gboolean
366 read_helper_report (int      fd,
367                     gintptr  report[2],
368                     GError **error)
369 {
370   gsize bytes = 0;
371   
372   while (bytes < sizeof(gintptr)*2)
373     {
374       gint chunk;
375       int errsv;
376
377       if (debug)
378         g_print ("%s:read_helper_report: read %" G_GSIZE_FORMAT "...\n",
379                  __FILE__,
380                  sizeof(gintptr)*2 - bytes);
381
382       chunk = read (fd, ((gchar*)report) + bytes,
383                     sizeof(gintptr)*2 - bytes);
384       errsv = errno;
385
386       if (debug)
387         g_print ("...got %d bytes\n", chunk);
388           
389       if (chunk < 0)
390         {
391           /* Some weird shit happened, bail out */
392           g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED,
393                        _("Failed to read from child pipe (%s)"),
394                        g_strerror (errsv));
395
396           return FALSE;
397         }
398       else if (chunk == 0)
399         {
400           g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED,
401                        _("Failed to read from child pipe (%s)"),
402                        "EOF");
403           break; /* EOF */
404         }
405       else
406         bytes += chunk;
407     }
408
409   if (bytes < sizeof(gintptr)*2)
410     return FALSE;
411
412   return TRUE;
413 }
414
415 static void
416 set_child_error (gintptr      report[2],
417                  const gchar *working_directory,
418                  GError     **error)
419 {
420   switch (report[0])
421     {
422     case CHILD_CHDIR_FAILED:
423       g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_CHDIR,
424                    _("Failed to change to directory “%s” (%s)"),
425                    working_directory,
426                    g_strerror (report[1]));
427       break;
428     case CHILD_SPAWN_FAILED:
429       g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED,
430                    _("Failed to execute child process (%s)"),
431                    g_strerror (report[1]));
432       break;
433     case CHILD_SPAWN_NOENT:
434       g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_NOENT,
435                    _("Failed to execute child process (%s)"),
436                    g_strerror (report[1]));
437       break;
438     case CHILD_DUP_FAILED:
439       g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED,
440                    _("Failed to dup() in child process (%s)"),
441                    g_strerror (report[1]));
442       break;
443     default:
444       g_assert_not_reached ();
445     }
446 }
447
448 static gboolean
449 utf8_charv_to_wcharv (const gchar * const   *utf8_charv,
450                       wchar_t             ***wcharv,
451                       int                   *error_index,
452                       GError               **error)
453 {
454   wchar_t **retval = NULL;
455
456   *wcharv = NULL;
457   if (utf8_charv != NULL)
458     {
459       int n = 0, i;
460
461       while (utf8_charv[n])
462         n++;
463       retval = g_new (wchar_t *, n + 1);
464
465       for (i = 0; i < n; i++)
466         {
467           retval[i] = g_utf8_to_utf16 (utf8_charv[i], -1, NULL, NULL, error);
468           if (retval[i] == NULL)
469             {
470               if (error_index)
471                 *error_index = i;
472               while (i)
473                 g_free (retval[--i]);
474               g_free (retval);
475               return FALSE;
476             }
477         }
478             
479       retval[n] = NULL;
480     }
481   *wcharv = retval;
482   return TRUE;
483 }
484
485 static gboolean
486 do_spawn_directly (gint                 *exit_status,
487                    gboolean              do_return_handle,
488                    GSpawnFlags           flags,
489                    const gchar * const  *argv,
490                    const gchar * const  *envp,
491                    const gchar * const  *protected_argv,
492                    GPid                 *child_pid,
493                    GError              **error)
494 {
495   const int mode = (exit_status == NULL) ? P_NOWAIT : P_WAIT;
496   const gchar * const *new_argv;
497   gintptr rc = -1;
498   int errsv;
499   GError *conv_error = NULL;
500   gint conv_error_index;
501   wchar_t *wargv0, **wargv, **wenvp;
502
503   g_assert (argv != NULL && argv[0] != NULL);
504
505   new_argv = (flags & G_SPAWN_FILE_AND_ARGV_ZERO) ? protected_argv + 1 : protected_argv;
506       
507   wargv0 = g_utf8_to_utf16 (argv[0], -1, NULL, NULL, &conv_error);
508   if (wargv0 == NULL)
509     {
510       g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED,
511                    _("Invalid program name: %s"),
512                    conv_error->message);
513       g_error_free (conv_error);
514       
515       return FALSE;
516     }
517   
518   if (!utf8_charv_to_wcharv (new_argv, &wargv, &conv_error_index, &conv_error))
519     {
520       g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED,
521                    _("Invalid string in argument vector at %d: %s"),
522                    conv_error_index, conv_error->message);
523       g_error_free (conv_error);
524       g_free (wargv0);
525
526       return FALSE;
527     }
528
529   if (!utf8_charv_to_wcharv (envp, &wenvp, NULL, &conv_error))
530     {
531       g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED,
532                    _("Invalid string in environment: %s"),
533                    conv_error->message);
534       g_error_free (conv_error);
535       g_free (wargv0);
536       g_strfreev ((gchar **) wargv);
537
538       return FALSE;
539     }
540
541   if (flags & G_SPAWN_SEARCH_PATH)
542     if (wenvp != NULL)
543       rc = safe_wspawnvpe (mode, wargv0, (const wchar_t **) wargv, (const wchar_t **) wenvp);
544     else
545       rc = _wspawnvp (mode, wargv0, (const wchar_t **) wargv);
546   else
547     if (wenvp != NULL)
548       rc = safe_wspawnve (mode, wargv0, (const wchar_t **) wargv, (const wchar_t **) wenvp);
549     else
550       rc = _wspawnv (mode, wargv0, (const wchar_t **) wargv);
551
552   errsv = errno;
553
554   g_free (wargv0);
555   g_strfreev ((gchar **) wargv);
556   g_strfreev ((gchar **) wenvp);
557
558   if (rc == -1 && errsv != 0)
559     {
560       g_set_error (error, G_SPAWN_ERROR, _g_spawn_exec_err_to_g_error (errsv),
561                    _("Failed to execute child process (%s)"),
562                    g_strerror (errsv));
563       return FALSE;
564     }
565
566   if (exit_status == NULL)
567     {
568       if (child_pid && do_return_handle)
569         *child_pid = (GPid) rc;
570       else
571         {
572           CloseHandle ((HANDLE) rc);
573           if (child_pid)
574             *child_pid = 0;
575         }
576     }
577   else
578     *exit_status = rc;
579
580   return TRUE;
581 }
582
583 static gboolean
584 might_be_console_process (void)
585 {
586   // we should always fail to attach ourself to a console (because we're
587   // either already attached, or we do not have a console)
588   gboolean attached_to_self = AttachConsole (GetCurrentProcessId ());
589   g_return_val_if_fail (!attached_to_self, TRUE);
590
591   switch (GetLastError ())
592     {
593     // current process is already attached to a console
594     case ERROR_ACCESS_DENIED:
595       return TRUE;
596     // current process does not have a console
597     case ERROR_INVALID_HANDLE:
598       return FALSE;
599     // we should not get ERROR_INVALID_PARAMETER
600     }
601
602   g_return_val_if_reached (FALSE);
603 }
604
605 static gboolean
606 fork_exec (gint                  *exit_status,
607            gboolean               do_return_handle,
608            const gchar           *working_directory,
609            const gchar * const   *argv,
610            const gchar * const   *envp,
611            GSpawnFlags            flags,
612            GSpawnChildSetupFunc   child_setup,
613            gpointer               user_data,
614            GPid                  *child_pid,
615            gint                  *stdin_pipe_out,
616            gint                  *stdout_pipe_out,
617            gint                  *stderr_pipe_out,
618            gint                   stdin_fd,
619            gint                   stdout_fd,
620            gint                   stderr_fd,
621            const gint            *source_fds,
622            const gint            *target_fds,
623            gsize                  n_fds,
624            gint                  *err_report,
625            GError               **error)
626 {
627   char **protected_argv;
628   char args[ARG_COUNT][10];
629   char **new_argv;
630   int i;
631   gintptr rc = -1;
632   int errsv;
633   int argc;
634   int child_err_report_pipe[2] = { -1, -1 };
635   int helper_sync_pipe[2] = { -1, -1 };
636   gintptr helper_report[2];
637   static gboolean warned_about_child_setup = FALSE;
638   GError *conv_error = NULL;
639   gint conv_error_index;
640   gchar *helper_process;
641   wchar_t *whelper, **wargv, **wenvp;
642   int stdin_pipe[2] = { -1, -1 };
643   int stdout_pipe[2] = { -1, -1 };
644   int stderr_pipe[2] = { -1, -1 };
645
646   g_assert (argv != NULL && argv[0] != NULL);
647   g_assert (stdin_pipe_out == NULL || stdin_fd < 0);
648   g_assert (stdout_pipe_out == NULL || stdout_fd < 0);
649   g_assert (stderr_pipe_out == NULL || stderr_fd < 0);
650
651   if (child_setup && !warned_about_child_setup)
652     {
653       warned_about_child_setup = TRUE;
654       g_warning ("passing a child setup function to the g_spawn functions is pointless on Windows and it is ignored");
655     }
656
657   if (stdin_pipe_out != NULL)
658     {
659       if (!make_pipe (stdin_pipe, error))
660         goto cleanup_and_fail;
661       stdin_fd = stdin_pipe[0];
662     }
663
664   if (stdout_pipe_out != NULL)
665     {
666       if (!make_pipe (stdout_pipe, error))
667         goto cleanup_and_fail;
668       stdout_fd = stdout_pipe[1];
669     }
670
671   if (stderr_pipe_out != NULL)
672     {
673       if (!make_pipe (stderr_pipe, error))
674         goto cleanup_and_fail;
675       stderr_fd = stderr_pipe[1];
676     }
677
678   argc = protect_argv (argv, &protected_argv);
679
680   /*
681    * FIXME: Workaround broken spawnvpe functions that SEGV when "=X:="
682    * environment variables are missing. Calling chdir() will set the magic
683    * environment variable again.
684    */
685   _chdir (".");
686
687   if (stdin_fd == -1 && stdout_fd == -1 && stderr_fd == -1 &&
688       (flags & G_SPAWN_CHILD_INHERITS_STDIN) &&
689       !(flags & G_SPAWN_STDOUT_TO_DEV_NULL) &&
690       !(flags & G_SPAWN_STDERR_TO_DEV_NULL) &&
691       (working_directory == NULL || !*working_directory) &&
692       (flags & G_SPAWN_LEAVE_DESCRIPTORS_OPEN) &&
693       n_fds == 0)
694     {
695       /* We can do without the helper process */
696       gboolean retval =
697         do_spawn_directly (exit_status, do_return_handle, flags,
698                            argv, envp, (const gchar * const *) protected_argv,
699                            child_pid, error);
700       g_strfreev (protected_argv);
701       return retval;
702     }
703
704   if (!make_pipe (child_err_report_pipe, error))
705     goto cleanup_and_fail;
706   
707   if (!make_pipe (helper_sync_pipe, error))
708     goto cleanup_and_fail;
709   
710   new_argv = g_new (char *, argc + 1 + ARG_COUNT);
711   if (might_be_console_process ())
712     helper_process = HELPER_PROCESS "-console.exe";
713   else
714     helper_process = HELPER_PROCESS ".exe";
715
716   helper_process = g_win32_find_helper_executable_path (helper_process, glib_dll);
717   new_argv[0] = protect_argv_string (helper_process);
718
719   _g_sprintf (args[ARG_CHILD_ERR_REPORT], "%d", child_err_report_pipe[1]);
720   new_argv[ARG_CHILD_ERR_REPORT] = args[ARG_CHILD_ERR_REPORT];
721   
722   /* Make the read end of the child error report pipe
723    * noninherited. Otherwise it will needlessly be inherited by the
724    * helper process, and the started actual user process. As such that
725    * shouldn't harm, but it is unnecessary.
726    */
727   child_err_report_pipe[0] = g_win32_reopen_noninherited (
728     child_err_report_pipe[0], _O_RDONLY, error);
729   if (child_err_report_pipe[0] == -1)
730       goto cleanup_and_fail;
731
732   if (flags & G_SPAWN_FILE_AND_ARGV_ZERO)
733     {
734       /* Overload ARG_CHILD_ERR_REPORT to also encode the
735        * G_SPAWN_FILE_AND_ARGV_ZERO functionality.
736        */
737       strcat (args[ARG_CHILD_ERR_REPORT], "#");
738     }
739   
740   _g_sprintf (args[ARG_HELPER_SYNC], "%d", helper_sync_pipe[0]);
741   new_argv[ARG_HELPER_SYNC] = args[ARG_HELPER_SYNC];
742   
743   /* Make the write end of the sync pipe noninherited. Otherwise the
744    * helper process will inherit it, and thus if this process happens
745    * to crash before writing the sync byte to the pipe, the helper
746    * process won't read but won't get any EOF either, as it has the
747    * write end open itself.
748    */
749   helper_sync_pipe[1] = g_win32_reopen_noninherited (
750     helper_sync_pipe[1], _O_WRONLY, error);
751   if (helper_sync_pipe[1] == -1)
752       goto cleanup_and_fail;
753
754   if (stdin_fd != -1)
755     {
756       _g_sprintf (args[ARG_STDIN], "%d", stdin_fd);
757       new_argv[ARG_STDIN] = args[ARG_STDIN];
758     }
759   else if (flags & G_SPAWN_CHILD_INHERITS_STDIN)
760     {
761       /* Let stdin be alone */
762       new_argv[ARG_STDIN] = "-";
763     }
764   else
765     {
766       /* Keep process from blocking on a read of stdin */
767       new_argv[ARG_STDIN] = "z";
768     }
769   
770   if (stdout_fd != -1)
771     {
772       _g_sprintf (args[ARG_STDOUT], "%d", stdout_fd);
773       new_argv[ARG_STDOUT] = args[ARG_STDOUT];
774     }
775   else if (flags & G_SPAWN_STDOUT_TO_DEV_NULL)
776     {
777       new_argv[ARG_STDOUT] = "z";
778     }
779   else
780     {
781       new_argv[ARG_STDOUT] = "-";
782     }
783   
784   if (stderr_fd != -1)
785     {
786       _g_sprintf (args[ARG_STDERR], "%d", stderr_fd);
787       new_argv[ARG_STDERR] = args[ARG_STDERR];
788     }
789   else if (flags & G_SPAWN_STDERR_TO_DEV_NULL)
790     {
791       new_argv[ARG_STDERR] = "z";
792     }
793   else
794     {
795       new_argv[ARG_STDERR] = "-";
796     }
797   
798   if (working_directory && *working_directory)
799     new_argv[ARG_WORKING_DIRECTORY] = protect_argv_string (working_directory);
800   else
801     new_argv[ARG_WORKING_DIRECTORY] = g_strdup ("-");
802   
803   if (!(flags & G_SPAWN_LEAVE_DESCRIPTORS_OPEN))
804     new_argv[ARG_CLOSE_DESCRIPTORS] = "y";
805   else
806     new_argv[ARG_CLOSE_DESCRIPTORS] = "-";
807
808   if (flags & G_SPAWN_SEARCH_PATH)
809     new_argv[ARG_USE_PATH] = "y";
810   else
811     new_argv[ARG_USE_PATH] = "-";
812
813   if (exit_status == NULL)
814     new_argv[ARG_WAIT] = "-";
815   else
816     new_argv[ARG_WAIT] = "w";
817
818   if (n_fds == 0)
819     new_argv[ARG_FDS] = g_strdup ("-");
820   else
821     {
822       GString *fds = g_string_new ("");
823       gsize n;
824
825       for (n = 0; n < n_fds; n++)
826         g_string_append_printf (fds, "%d:%d,", source_fds[n], target_fds[n]);
827
828       /* remove the trailing , */
829       g_string_truncate (fds, fds->len - 1);
830       new_argv[ARG_FDS] = g_string_free (fds, FALSE);
831     }
832
833   for (i = 0; i <= argc; i++)
834     new_argv[ARG_PROGRAM + i] = protected_argv[i];
835
836   SETUP_DEBUG();
837
838   if (debug)
839     {
840       g_print ("calling %s with argv:\n", helper_process);
841       for (i = 0; i < argc + 1 + ARG_COUNT; i++)
842         g_print ("argv[%d]: %s\n", i, (new_argv[i] ? new_argv[i] : "NULL"));
843     }
844
845   if (!utf8_charv_to_wcharv ((const gchar * const *) new_argv, &wargv, &conv_error_index, &conv_error))
846     {
847       if (conv_error_index == ARG_WORKING_DIRECTORY)
848         g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_CHDIR,
849                      _("Invalid working directory: %s"),
850                      conv_error->message);
851       else
852         g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED,
853                      _("Invalid string in argument vector at %d: %s"),
854                      conv_error_index - ARG_PROGRAM, conv_error->message);
855       g_error_free (conv_error);
856       g_strfreev (protected_argv);
857       g_free (new_argv[0]);
858       g_free (new_argv[ARG_WORKING_DIRECTORY]);
859       g_free (new_argv[ARG_FDS]);
860       g_free (new_argv);
861       g_free (helper_process);
862
863       goto cleanup_and_fail;
864     }
865
866   if (!utf8_charv_to_wcharv (envp, &wenvp, NULL, &conv_error))
867     {
868       g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED,
869                    _("Invalid string in environment: %s"),
870                    conv_error->message);
871       g_error_free (conv_error);
872       g_strfreev (protected_argv);
873       g_free (new_argv[0]);
874       g_free (new_argv[ARG_WORKING_DIRECTORY]);
875       g_free (new_argv[ARG_FDS]);
876       g_free (new_argv);
877       g_free (helper_process);
878       g_strfreev ((gchar **) wargv);
879  
880       goto cleanup_and_fail;
881     }
882
883   whelper = g_utf8_to_utf16 (helper_process, -1, NULL, NULL, NULL);
884   g_free (helper_process);
885
886   if (wenvp != NULL)
887     rc = safe_wspawnvpe (P_NOWAIT, whelper, (const wchar_t **) wargv, (const wchar_t **) wenvp);
888   else
889     rc = _wspawnvp (P_NOWAIT, whelper, (const wchar_t **) wargv);
890
891   errsv = errno;
892
893   g_free (whelper);
894   g_strfreev ((gchar **) wargv);
895   g_strfreev ((gchar **) wenvp);
896
897   /* Close the other process's ends of the pipes in this process,
898    * otherwise the reader will never get EOF.
899    */
900   close_and_invalidate (&child_err_report_pipe[1]);
901   close_and_invalidate (&helper_sync_pipe[0]);
902
903   g_strfreev (protected_argv);
904
905   g_free (new_argv[0]);
906   g_free (new_argv[ARG_WORKING_DIRECTORY]);
907   g_free (new_argv[ARG_FDS]);
908   g_free (new_argv);
909
910   /* Check if gspawn-win32-helper couldn't be run */
911   if (rc == -1 && errsv != 0)
912     {
913       g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED,
914                    _("Failed to execute helper program (%s)"),
915                    g_strerror (errsv));
916       goto cleanup_and_fail;
917     }
918
919   if (exit_status != NULL)
920     {
921       /* Synchronous case. Pass helper's report pipe back to caller,
922        * which takes care of reading it after the grandchild has
923        * finished.
924        */
925       g_assert (err_report != NULL);
926       *err_report = child_err_report_pipe[0];
927       write (helper_sync_pipe[1], " ", 1);
928       close_and_invalidate (&helper_sync_pipe[1]);
929     }
930   else
931     {
932       /* Asynchronous case. We read the helper's report right away. */
933       if (!read_helper_report (child_err_report_pipe[0], helper_report, error))
934         goto cleanup_and_fail;
935         
936       close_and_invalidate (&child_err_report_pipe[0]);
937
938       switch (helper_report[0])
939         {
940         case CHILD_NO_ERROR:
941           if (child_pid && do_return_handle)
942             {
943               /* rc is our HANDLE for gspawn-win32-helper. It has
944                * told us the HANDLE of its child. Duplicate that into
945                * a HANDLE valid in this process.
946                */
947               if (!DuplicateHandle ((HANDLE) rc, (HANDLE) helper_report[1],
948                                     GetCurrentProcess (), (LPHANDLE) child_pid,
949                                     0, TRUE, DUPLICATE_SAME_ACCESS))
950                 {
951                   char *emsg = g_win32_error_message (GetLastError ());
952                   g_print ("%s\n", emsg);
953                   g_free (emsg);
954                   *child_pid = 0;
955                 }
956             }
957           else if (child_pid)
958             *child_pid = 0;
959           write (helper_sync_pipe[1], " ", 1);
960           close_and_invalidate (&helper_sync_pipe[1]);
961           break;
962           
963         default:
964           write (helper_sync_pipe[1], " ", 1);
965           close_and_invalidate (&helper_sync_pipe[1]);
966           set_child_error (helper_report, working_directory, error);
967           goto cleanup_and_fail;
968         }
969     }
970
971   /* Success against all odds! return the information */
972       
973   if (rc != -1)
974     CloseHandle ((HANDLE) rc);
975
976   /* Close the other process's ends of the pipes in this process,
977    * otherwise the reader will never get EOF.
978    */
979   close_and_invalidate (&stdin_pipe[0]);
980   close_and_invalidate (&stdout_pipe[1]);
981   close_and_invalidate (&stderr_pipe[1]);
982
983   if (stdin_pipe_out != NULL)
984     *stdin_pipe_out = stdin_pipe[1];
985   if (stdout_pipe_out != NULL)
986     *stdout_pipe_out = stdout_pipe[0];
987   if (stderr_pipe_out != NULL)
988     *stderr_pipe_out = stderr_pipe[0];
989
990   return TRUE;
991
992  cleanup_and_fail:
993
994   if (rc != -1)
995     CloseHandle ((HANDLE) rc);
996   if (child_err_report_pipe[0] != -1)
997     close (child_err_report_pipe[0]);
998   if (child_err_report_pipe[1] != -1)
999     close (child_err_report_pipe[1]);
1000   if (helper_sync_pipe[0] != -1)
1001     close (helper_sync_pipe[0]);
1002   if (helper_sync_pipe[1] != -1)
1003     close (helper_sync_pipe[1]);
1004
1005   if (stdin_pipe[0] != -1)
1006     close (stdin_pipe[0]);
1007   if (stdin_pipe[1] != -1)
1008     close (stdin_pipe[1]);
1009   if (stdout_pipe[0] != -1)
1010     close (stdout_pipe[0]);
1011   if (stdout_pipe[1] != -1)
1012     close (stdout_pipe[1]);
1013   if (stderr_pipe[0] != -1)
1014     close (stderr_pipe[0]);
1015   if (stderr_pipe[1] != -1)
1016     close (stderr_pipe[1]);
1017
1018   return FALSE;
1019 }
1020
1021 gboolean
1022 g_spawn_sync (const gchar          *working_directory,
1023               gchar               **argv,
1024               gchar               **envp,
1025               GSpawnFlags           flags,
1026               GSpawnChildSetupFunc  child_setup,
1027               gpointer              user_data,
1028               gchar               **standard_output,
1029               gchar               **standard_error,
1030               gint                 *wait_status,
1031               GError              **error)
1032 {
1033   gint outpipe = -1;
1034   gint errpipe = -1;
1035   gint reportpipe = -1;
1036   GIOChannel *outchannel = NULL;
1037   GIOChannel *errchannel = NULL;
1038   GPollFD outfd = { -1, 0, 0 }, errfd = { -1, 0, 0 };
1039   GPollFD fds[2];
1040   gint nfds;
1041   gint outindex = -1;
1042   gint errindex = -1;
1043   gint ret;
1044   GString *outstr = NULL;
1045   GString *errstr = NULL;
1046   gboolean failed;
1047   gint status;
1048   
1049   g_return_val_if_fail (argv != NULL && argv[0] != NULL, FALSE);
1050   g_return_val_if_fail (!(flags & G_SPAWN_DO_NOT_REAP_CHILD), FALSE);
1051   g_return_val_if_fail (standard_output == NULL ||
1052                         !(flags & G_SPAWN_STDOUT_TO_DEV_NULL), FALSE);
1053   g_return_val_if_fail (standard_error == NULL ||
1054                         !(flags & G_SPAWN_STDERR_TO_DEV_NULL), FALSE);
1055   
1056   /* Just to ensure segfaults if callers try to use
1057    * these when an error is reported.
1058    */
1059   if (standard_output)
1060     *standard_output = NULL;
1061
1062   if (standard_error)
1063     *standard_error = NULL;
1064
1065   if (!fork_exec (&status,
1066                   FALSE,
1067                   working_directory,
1068                   (const gchar * const *) argv,
1069                   (const gchar * const *) envp,
1070                   flags,
1071                   child_setup,
1072                   user_data,
1073                   NULL,
1074                   NULL,
1075                   standard_output ? &outpipe : NULL,
1076                   standard_error ? &errpipe : NULL,
1077                   -1,
1078                   -1,
1079                   -1,
1080                   NULL, NULL, 0,
1081                   &reportpipe,
1082                   error))
1083     return FALSE;
1084
1085   /* Read data from child. */
1086   
1087   failed = FALSE;
1088
1089   if (outpipe >= 0)
1090     {
1091       outstr = g_string_new (NULL);
1092       outchannel = g_io_channel_win32_new_fd (outpipe);
1093       g_io_channel_set_encoding (outchannel, NULL, NULL);
1094       g_io_channel_set_buffered (outchannel, FALSE);
1095       g_io_channel_win32_make_pollfd (outchannel,
1096                                       G_IO_IN | G_IO_ERR | G_IO_HUP,
1097                                       &outfd);
1098       if (debug)
1099         g_print ("outfd=%p\n", (HANDLE) outfd.fd);
1100     }
1101       
1102   if (errpipe >= 0)
1103     {
1104       errstr = g_string_new (NULL);
1105       errchannel = g_io_channel_win32_new_fd (errpipe);
1106       g_io_channel_set_encoding (errchannel, NULL, NULL);
1107       g_io_channel_set_buffered (errchannel, FALSE);
1108       g_io_channel_win32_make_pollfd (errchannel,
1109                                       G_IO_IN | G_IO_ERR | G_IO_HUP,
1110                                       &errfd);
1111       if (debug)
1112         g_print ("errfd=%p\n", (HANDLE) errfd.fd);
1113     }
1114
1115   /* Read data until we get EOF on all pipes. */
1116   while (!failed && (outpipe >= 0 || errpipe >= 0))
1117     {
1118       nfds = 0;
1119       if (outpipe >= 0)
1120         {
1121           fds[nfds] = outfd;
1122           outindex = nfds;
1123           nfds++;
1124         }
1125       if (errpipe >= 0)
1126         {
1127           fds[nfds] = errfd;
1128           errindex = nfds;
1129           nfds++;
1130         }
1131
1132       if (debug)
1133         g_print ("g_spawn_sync: calling g_io_channel_win32_poll, nfds=%d\n",
1134                  nfds);
1135
1136       ret = g_io_channel_win32_poll (fds, nfds, -1);
1137
1138       if (ret < 0)
1139         {
1140           failed = TRUE;
1141
1142           g_set_error_literal (error, G_SPAWN_ERROR, G_SPAWN_ERROR_READ,
1143                                _("Unexpected error in g_io_channel_win32_poll() reading data from a child process"));
1144           
1145           break;
1146         }
1147
1148       if (outpipe >= 0 && (fds[outindex].revents & G_IO_IN))
1149         {
1150           switch (read_data (outstr, outchannel, error))
1151             {
1152             case READ_FAILED:
1153               if (debug)
1154                 g_print ("g_spawn_sync: outchannel: READ_FAILED\n");
1155               failed = TRUE;
1156               break;
1157             case READ_EOF:
1158               if (debug)
1159                 g_print ("g_spawn_sync: outchannel: READ_EOF\n");
1160               g_io_channel_unref (outchannel);
1161               outchannel = NULL;
1162               close_and_invalidate (&outpipe);
1163               break;
1164             default:
1165               if (debug)
1166                 g_print ("g_spawn_sync: outchannel: OK\n");
1167               break;
1168             }
1169
1170           if (failed)
1171             break;
1172         }
1173
1174       if (errpipe >= 0 && (fds[errindex].revents & G_IO_IN))
1175         {
1176           switch (read_data (errstr, errchannel, error))
1177             {
1178             case READ_FAILED:
1179               if (debug)
1180                 g_print ("g_spawn_sync: errchannel: READ_FAILED\n");
1181               failed = TRUE;
1182               break;
1183             case READ_EOF:
1184               if (debug)
1185                 g_print ("g_spawn_sync: errchannel: READ_EOF\n");
1186               g_io_channel_unref (errchannel);
1187               errchannel = NULL;
1188               close_and_invalidate (&errpipe);
1189               break;
1190             default:
1191               if (debug)
1192                 g_print ("g_spawn_sync: errchannel: OK\n");
1193               break;
1194             }
1195
1196           if (failed)
1197             break;
1198         }
1199     }
1200
1201   if (reportpipe == -1)
1202     {
1203       /* No helper process, exit status of actual spawned process
1204        * already available.
1205        */
1206       if (wait_status)
1207         *wait_status = status;
1208     }
1209   else
1210     {
1211       /* Helper process was involved. Read its report now after the
1212        * grandchild has finished.
1213        */
1214       gintptr helper_report[2];
1215
1216       if (!read_helper_report (reportpipe, helper_report, error))
1217         failed = TRUE;
1218       else
1219         {
1220           switch (helper_report[0])
1221             {
1222             case CHILD_NO_ERROR:
1223               if (wait_status)
1224                 *wait_status = helper_report[1];
1225               break;
1226             default:
1227               set_child_error (helper_report, working_directory, error);
1228               failed = TRUE;
1229               break;
1230             }
1231         }
1232       close_and_invalidate (&reportpipe);
1233     }
1234
1235
1236   /* These should only be open still if we had an error.  */
1237   
1238   if (outchannel != NULL)
1239     g_io_channel_unref (outchannel);
1240   if (errchannel != NULL)
1241     g_io_channel_unref (errchannel);
1242   if (outpipe >= 0)
1243     close_and_invalidate (&outpipe);
1244   if (errpipe >= 0)
1245     close_and_invalidate (&errpipe);
1246   
1247   if (failed)
1248     {
1249       if (outstr)
1250         g_string_free (outstr, TRUE);
1251       if (errstr)
1252         g_string_free (errstr, TRUE);
1253
1254       return FALSE;
1255     }
1256   else
1257     {
1258       if (standard_output)        
1259         *standard_output = g_string_free (outstr, FALSE);
1260
1261       if (standard_error)
1262         *standard_error = g_string_free (errstr, FALSE);
1263
1264       return TRUE;
1265     }
1266 }
1267
1268 gboolean
1269 g_spawn_async_with_pipes (const gchar          *working_directory,
1270                           gchar               **argv,
1271                           gchar               **envp,
1272                           GSpawnFlags           flags,
1273                           GSpawnChildSetupFunc  child_setup,
1274                           gpointer              user_data,
1275                           GPid                 *child_pid,
1276                           gint                 *standard_input,
1277                           gint                 *standard_output,
1278                           gint                 *standard_error,
1279                           GError              **error)
1280 {
1281   g_return_val_if_fail (argv != NULL && argv[0] != NULL, FALSE);
1282   g_return_val_if_fail (standard_output == NULL ||
1283                         !(flags & G_SPAWN_STDOUT_TO_DEV_NULL), FALSE);
1284   g_return_val_if_fail (standard_error == NULL ||
1285                         !(flags & G_SPAWN_STDERR_TO_DEV_NULL), FALSE);
1286   /* can't inherit stdin if we have an input pipe. */
1287   g_return_val_if_fail (standard_input == NULL ||
1288                         !(flags & G_SPAWN_CHILD_INHERITS_STDIN), FALSE);
1289
1290   return fork_exec (NULL,
1291                     (flags & G_SPAWN_DO_NOT_REAP_CHILD),
1292                     working_directory,
1293                     (const gchar * const *) argv,
1294                     (const gchar * const *) envp,
1295                     flags,
1296                     child_setup,
1297                     user_data,
1298                     child_pid,
1299                     standard_input,
1300                     standard_output,
1301                     standard_error,
1302                     -1,
1303                     -1,
1304                     -1,
1305                     NULL, NULL, 0,
1306                     NULL,
1307                     error);
1308 }
1309
1310 gboolean
1311 g_spawn_async_with_fds (const gchar          *working_directory,
1312                         gchar               **argv,
1313                         gchar               **envp,
1314                         GSpawnFlags           flags,
1315                         GSpawnChildSetupFunc  child_setup,
1316                         gpointer              user_data,
1317                         GPid                 *child_pid,
1318                         gint                  stdin_fd,
1319                         gint                  stdout_fd,
1320                         gint                  stderr_fd,
1321                         GError              **error)
1322 {
1323   g_return_val_if_fail (argv != NULL && argv[0] != NULL, FALSE);
1324   g_return_val_if_fail (stdin_fd == -1 ||
1325                         !(flags & G_SPAWN_STDOUT_TO_DEV_NULL), FALSE);
1326   g_return_val_if_fail (stderr_fd == -1 ||
1327                         !(flags & G_SPAWN_STDERR_TO_DEV_NULL), FALSE);
1328   /* can't inherit stdin if we have an input pipe. */
1329   g_return_val_if_fail (stdin_fd == -1 ||
1330                         !(flags & G_SPAWN_CHILD_INHERITS_STDIN), FALSE);
1331
1332   return fork_exec (NULL,
1333                     (flags & G_SPAWN_DO_NOT_REAP_CHILD),
1334                     working_directory,
1335                     (const gchar * const *) argv,
1336                     (const gchar * const *) envp,
1337                     flags,
1338                     child_setup,
1339                     user_data,
1340                     child_pid,
1341                     NULL,
1342                     NULL,
1343                     NULL,
1344                     stdin_fd,
1345                     stdout_fd,
1346                     stderr_fd,
1347                     NULL, NULL, 0,
1348                     NULL,
1349                     error);
1350
1351 }
1352
1353 gboolean
1354 g_spawn_async_with_pipes_and_fds (const gchar           *working_directory,
1355                                   const gchar * const   *argv,
1356                                   const gchar * const   *envp,
1357                                   GSpawnFlags            flags,
1358                                   GSpawnChildSetupFunc   child_setup,
1359                                   gpointer               user_data,
1360                                   gint                   stdin_fd,
1361                                   gint                   stdout_fd,
1362                                   gint                   stderr_fd,
1363                                   const gint            *source_fds,
1364                                   const gint            *target_fds,
1365                                   gsize                  n_fds,
1366                                   GPid                  *child_pid_out,
1367                                   gint                  *stdin_pipe_out,
1368                                   gint                  *stdout_pipe_out,
1369                                   gint                  *stderr_pipe_out,
1370                                   GError               **error)
1371 {
1372   g_return_val_if_fail (argv != NULL && argv[0] != NULL, FALSE);
1373   g_return_val_if_fail (stdout_pipe_out == NULL ||
1374                         !(flags & G_SPAWN_STDOUT_TO_DEV_NULL), FALSE);
1375   g_return_val_if_fail (stderr_pipe_out == NULL ||
1376                         !(flags & G_SPAWN_STDERR_TO_DEV_NULL), FALSE);
1377   /* can't inherit stdin if we have an input pipe. */
1378   g_return_val_if_fail (stdin_pipe_out == NULL ||
1379                         !(flags & G_SPAWN_CHILD_INHERITS_STDIN), FALSE);
1380   /* can’t use pipes and stdin/stdout/stderr FDs */
1381   g_return_val_if_fail (stdin_pipe_out == NULL || stdin_fd < 0, FALSE);
1382   g_return_val_if_fail (stdout_pipe_out == NULL || stdout_fd < 0, FALSE);
1383   g_return_val_if_fail (stderr_pipe_out == NULL || stderr_fd < 0, FALSE);
1384
1385   return fork_exec (NULL,
1386                     (flags & G_SPAWN_DO_NOT_REAP_CHILD),
1387                     working_directory,
1388                     argv,
1389                     envp,
1390                     flags,
1391                     child_setup,
1392                     user_data,
1393                     child_pid_out,
1394                     stdin_pipe_out,
1395                     stdout_pipe_out,
1396                     stderr_pipe_out,
1397                     stdin_fd,
1398                     stdout_fd,
1399                     stderr_fd,
1400                     source_fds,
1401                     target_fds,
1402                     n_fds,
1403                     NULL,
1404                     error);
1405 }
1406
1407 gboolean
1408 g_spawn_command_line_sync (const gchar  *command_line,
1409                            gchar       **standard_output,
1410                            gchar       **standard_error,
1411                            gint         *wait_status,
1412                            GError      **error)
1413 {
1414   gboolean retval;
1415   gchar **argv = 0;
1416
1417   g_return_val_if_fail (command_line != NULL, FALSE);
1418   
1419   /* This will return a runtime error if @command_line is the empty string. */
1420   if (!g_shell_parse_argv (command_line,
1421                            NULL, &argv,
1422                            error))
1423     return FALSE;
1424   
1425   retval = g_spawn_sync (NULL,
1426                          argv,
1427                          NULL,
1428                          G_SPAWN_SEARCH_PATH,
1429                          NULL,
1430                          NULL,
1431                          standard_output,
1432                          standard_error,
1433                          wait_status,
1434                          error);
1435   g_strfreev (argv);
1436
1437   return retval;
1438 }
1439
1440 gboolean
1441 g_spawn_command_line_async (const gchar *command_line,
1442                             GError     **error)
1443 {
1444   gboolean retval;
1445   gchar **argv = 0;
1446
1447   g_return_val_if_fail (command_line != NULL, FALSE);
1448
1449   /* This will return a runtime error if @command_line is the empty string. */
1450   if (!g_shell_parse_argv (command_line,
1451                            NULL, &argv,
1452                            error))
1453     return FALSE;
1454   
1455   retval = g_spawn_async (NULL,
1456                           argv,
1457                           NULL,
1458                           G_SPAWN_SEARCH_PATH,
1459                           NULL,
1460                           NULL,
1461                           NULL,
1462                           error);
1463   g_strfreev (argv);
1464
1465   return retval;
1466 }
1467
1468 void
1469 g_spawn_close_pid (GPid pid)
1470 {
1471   /* CRT functions such as _wspawn* return (HANDLE)-1
1472    * on failure, so check also for that value. */
1473   if (pid != NULL && pid != (HANDLE) -1)
1474     CloseHandle (pid);
1475 }
1476
1477 gboolean
1478 g_spawn_check_wait_status (gint      wait_status,
1479                            GError  **error)
1480 {
1481   gboolean ret = FALSE;
1482
1483   if (wait_status != 0)
1484     {
1485       /* On Windows, the wait status is just the exit status: the
1486        * difference between the two that exists on Unix is not relevant */
1487       g_set_error (error, G_SPAWN_EXIT_ERROR, wait_status,
1488                    _("Child process exited with code %ld"),
1489                    (long) wait_status);
1490       goto out;
1491     }
1492
1493   ret = TRUE;
1494  out:
1495   return ret;
1496 }
1497
1498 gboolean
1499 g_spawn_check_exit_status (gint      wait_status,
1500                            GError  **error)
1501 {
1502   return g_spawn_check_wait_status (wait_status, error);
1503 }
1504
1505 #ifdef G_OS_WIN32
1506
1507 /* Binary compatibility versions. Not for newly compiled code. */
1508
1509 _GLIB_EXTERN gboolean g_spawn_async_utf8              (const gchar           *working_directory,
1510                                                        gchar                **argv,
1511                                                        gchar                **envp,
1512                                                        GSpawnFlags            flags,
1513                                                        GSpawnChildSetupFunc   child_setup,
1514                                                        gpointer               user_data,
1515                                                        GPid                  *child_pid,
1516                                                        GError               **error);
1517 _GLIB_EXTERN gboolean g_spawn_async_with_pipes_utf8   (const gchar           *working_directory,
1518                                                        gchar                **argv,
1519                                                        gchar                **envp,
1520                                                        GSpawnFlags            flags,
1521                                                        GSpawnChildSetupFunc   child_setup,
1522                                                        gpointer               user_data,
1523                                                        GPid                  *child_pid,
1524                                                        gint                  *standard_input,
1525                                                        gint                  *standard_output,
1526                                                        gint                  *standard_error,
1527                                                        GError               **error);
1528 _GLIB_EXTERN gboolean g_spawn_sync_utf8               (const gchar           *working_directory,
1529                                                        gchar                **argv,
1530                                                        gchar                **envp,
1531                                                        GSpawnFlags            flags,
1532                                                        GSpawnChildSetupFunc   child_setup,
1533                                                        gpointer               user_data,
1534                                                        gchar                **standard_output,
1535                                                        gchar                **standard_error,
1536                                                        gint                  *wait_status,
1537                                                        GError               **error);
1538 _GLIB_EXTERN gboolean g_spawn_command_line_sync_utf8  (const gchar           *command_line,
1539                                                        gchar                **standard_output,
1540                                                        gchar                **standard_error,
1541                                                        gint                  *wait_status,
1542                                                        GError               **error);
1543 _GLIB_EXTERN gboolean g_spawn_command_line_async_utf8 (const gchar           *command_line,
1544                                                        GError               **error);
1545
1546 gboolean
1547 g_spawn_async_utf8 (const gchar          *working_directory,
1548                     gchar               **argv,
1549                     gchar               **envp,
1550                     GSpawnFlags           flags,
1551                     GSpawnChildSetupFunc  child_setup,
1552                     gpointer              user_data,
1553                     GPid                 *child_pid,
1554                     GError              **error)
1555 {
1556   return g_spawn_async (working_directory,
1557                         argv,
1558                         envp,
1559                         flags,
1560                         child_setup,
1561                         user_data,
1562                         child_pid,
1563                         error);
1564 }
1565
1566 gboolean
1567 g_spawn_async_with_pipes_utf8 (const gchar          *working_directory,
1568                                gchar               **argv,
1569                                gchar               **envp,
1570                                GSpawnFlags           flags,
1571                                GSpawnChildSetupFunc  child_setup,
1572                                gpointer              user_data,
1573                                GPid                 *child_pid,
1574                                gint                 *standard_input,
1575                                gint                 *standard_output,
1576                                gint                 *standard_error,
1577                                GError              **error)
1578 {
1579   return g_spawn_async_with_pipes (working_directory,
1580                                    argv,
1581                                    envp,
1582                                    flags,
1583                                    child_setup,
1584                                    user_data,
1585                                    child_pid,
1586                                    standard_input,
1587                                    standard_output,
1588                                    standard_error,
1589                                    error);
1590 }
1591
1592 gboolean
1593 g_spawn_sync_utf8 (const gchar          *working_directory,
1594                    gchar               **argv,
1595                    gchar               **envp,
1596                    GSpawnFlags           flags,
1597                    GSpawnChildSetupFunc  child_setup,
1598                    gpointer              user_data,
1599                    gchar               **standard_output,
1600                    gchar               **standard_error,
1601                    gint                 *wait_status,
1602                    GError              **error)
1603 {
1604   return g_spawn_sync (working_directory,
1605                        argv,
1606                        envp,
1607                        flags,
1608                        child_setup,
1609                        user_data,
1610                        standard_output,
1611                        standard_error,
1612                        wait_status,
1613                        error);
1614 }
1615
1616 gboolean
1617 g_spawn_command_line_sync_utf8 (const gchar  *command_line,
1618                                 gchar       **standard_output,
1619                                 gchar       **standard_error,
1620                                 gint         *wait_status,
1621                                 GError      **error)
1622 {
1623   return g_spawn_command_line_sync (command_line,
1624                                     standard_output,
1625                                     standard_error,
1626                                     wait_status,
1627                                     error);
1628 }
1629
1630 gboolean
1631 g_spawn_command_line_async_utf8 (const gchar *command_line,
1632                                  GError     **error)
1633 {
1634   return g_spawn_command_line_async (command_line, error);
1635 }
1636
1637 #endif /* G_OS_WIN32 */
1638
1639 #endif /* !GSPAWN_HELPER */