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