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