Add braces to silence gcc -Wall.
[platform/upstream/glib.git] / glib / gspawn-win32-helper.c
1 /* gspawn-win32-helper.c - Helper program for process launching on Win32.
2  *
3  *  Copyright 2000 Red Hat, Inc.
4  *  Copyright 2000 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 #undef G_LOG_DOMAIN
23 #include "glib.h"
24 #define GSPAWN_HELPER
25 #include "gspawn-win32.c"       /* For shared definitions */
26
27 static void
28 write_err_and_exit (gint fd,
29                     gint msg)
30 {
31   gint en = errno;
32   
33   write (fd, &msg, sizeof(msg));
34   write (fd, &en, sizeof(en));
35   
36   _exit (1);
37 }
38
39 #ifdef __GNUC__
40 #  ifndef _stdcall
41 #    define _stdcall  __attribute__((stdcall))
42 #  endif
43 #endif
44
45 /* We build gspawn-win32-helper.exe as a Windows GUI application
46  * to avoid any temporarily flashing console windows in case
47  * the gspawn function is invoked by a GUI program. Thus, no main()
48  * but a WinMain(). We do, however, still use argc and argv tucked
49  * away in the global __argc and __argv by the C runtime startup code.
50  */
51
52 int _stdcall
53 WinMain (struct HINSTANCE__ *hInstance,
54          struct HINSTANCE__ *hPrevInstance,
55          char               *lpszCmdLine,
56          int                 nCmdShow)
57 {
58   int child_err_report_fd;
59   int i;
60   int fd;
61   int mode;
62   GString *debugstring;
63
64   SETUP_DEBUG();
65
66   if (debug)
67     {
68       debugstring = g_string_new ("");
69
70       g_string_append (debugstring,
71                        g_strdup_printf ("g-spawn-win32-helper: "
72                                         "argc = %d, argv: ",
73                                         __argc));
74       for (i = 0; i < __argc; i++)
75         {
76           if (i > 0)
77             g_string_append (debugstring, " ");
78           g_string_append (debugstring, __argv[i]);
79         }
80       
81       MessageBox (NULL, debugstring->str, "gspawn-win32-helper", 0);
82     }
83
84   g_assert (__argc >= ARG_COUNT);
85
86   /* argv[ARG_CHILD_ERR_REPORT] is the file descriptor onto which
87    * write error messages.
88    */
89   child_err_report_fd = atoi (__argv[ARG_CHILD_ERR_REPORT]);
90
91   /* argv[ARG_STDIN..ARG_STDERR] are the file descriptors that should
92    * be dup2'd to stdin, stdout and stderr, '-' if the corresponding
93    * std* should be let alone, and 'z' if it should be connected to
94    * the bit bucket NUL:.
95    */
96   if (__argv[ARG_STDIN][0] == '-')
97     ; /* Nothing */
98   else if (__argv[ARG_STDIN][0] == 'z')
99     {
100       fd = open ("NUL:", O_RDONLY);
101       if (fd != 0)
102         {
103           dup2 (fd, 0);
104           close (fd);
105         }
106     }
107   else
108     {
109       fd = atoi (__argv[ARG_STDIN]);
110       if (fd != 0)
111         {
112           dup2 (fd, 0);
113           close (fd);
114         }
115     }
116
117   if (__argv[ARG_STDOUT][0] == '-')
118     ; /* Nothing */
119   else if (__argv[ARG_STDOUT][0] == 'z')
120     {
121       fd = open ("NUL:", O_WRONLY);
122       if (fd != 1)
123         {
124           dup2 (fd, 1);
125           close (fd);
126         }
127     }
128   else
129     {
130       fd = atoi (__argv[ARG_STDOUT]);
131       if (fd != 1)
132         {
133           dup2 (fd, 1);
134           close (fd);
135         }
136     }
137
138   if (__argv[ARG_STDERR][0] == '-')
139     ; /* Nothing */
140   else if (__argv[ARG_STDERR][0] == 'z')
141     {
142       fd = open ("NUL:", O_WRONLY);
143       if (fd != 2)
144         {
145           dup2 (fd, 2);
146           close (fd);
147         }
148     }
149   else
150     {
151       fd = atoi (__argv[ARG_STDERR]);
152       if (fd != 2)
153         {
154           dup2 (fd, 2);
155           close (fd);
156         }
157     }
158
159   /* __argv[ARG_WORKING_DIRECTORY] is the directory in which to run the
160    * process.  If "-", don't change directory.
161    */
162   if (__argv[ARG_WORKING_DIRECTORY][0] == '-' &&
163       __argv[ARG_WORKING_DIRECTORY][1] == 0)
164     ; /* Nothing */
165   else if (chdir (__argv[ARG_WORKING_DIRECTORY]) < 0)
166     write_err_and_exit (child_err_report_fd,
167                         CHILD_CHDIR_FAILED);
168
169   /* __argv[ARG_CLOSE_DESCRIPTORS] is "y" if file descriptors from 3
170    *  upwards should be closed
171    */
172
173   if (__argv[ARG_CLOSE_DESCRIPTORS][0] == 'y')
174     for (i = 3; i < 1000; i++)  /* FIXME real limit? */
175       if (i != child_err_report_fd)
176         close (i);
177
178   /* __argv[ARG_WAIT] is "w" to wait for the program to exit */
179
180   if (__argv[ARG_WAIT][0] == 'w')
181     mode = P_WAIT;
182   else
183     mode = P_NOWAIT;
184
185   /* __argv[ARG_USE_PATH] is "y" to use PATH, otherwise not */
186
187   /* __argv[ARG_PROGRAM] is program file to run,
188    * __argv[ARG_PROGRAM+1]... is its __argv.
189    */
190
191   if (debug)
192     {
193       debugstring = g_string_new ("");
194       g_string_append (debugstring,
195                        g_strdup_printf ("calling %s on program %s, __argv: ",
196                                         (__argv[ARG_USE_PATH][0] == 'y' ?
197                                          "spawnvp" : "spawnv"),
198                                         __argv[ARG_PROGRAM]));
199       i = ARG_PROGRAM+1;
200       while (__argv[i])
201         g_string_append (debugstring, __argv[i++]);
202       MessageBox (NULL, debugstring->str, "gspawn-win32-helper", 0);
203     }
204
205   if (__argv[ARG_USE_PATH][0] == 'y')
206     {
207       if (spawnvp (mode, __argv[ARG_PROGRAM], __argv+ARG_PROGRAM) < 0)
208         write_err_and_exit (child_err_report_fd, CHILD_SPAWN_FAILED);
209     }
210   else
211     {
212       if (spawnv (mode, __argv[ARG_PROGRAM], __argv+ARG_PROGRAM) < 0)
213         write_err_and_exit (child_err_report_fd, CHILD_SPAWN_FAILED);
214     }
215
216   return 0;
217 }
218