Add a third AOT location, alongside ~/.mono/aot-cache and the assembly dir
[mono.git] / eglib / src / gspawn.c
1 /*
2  * Spawning processes.
3  *
4  * Author:
5  *   Gonzalo Paniagua Javier (gonzalo@novell.com
6  *
7  * (C) 2006 Novell, Inc.
8  *
9  * Permission is hereby granted, free of charge, to any person obtaining
10  * a copy of this software and associated documentation files (the
11  * "Software"), to deal in the Software without restriction, including
12  * without limitation the rights to use, copy, modify, merge, publish,
13  * distribute, sublicense, and/or sell copies of the Software, and to
14  * permit persons to whom the Software is furnished to do so, subject to
15  * the following conditions:
16  *
17  * The above copyright notice and this permission notice shall be
18  * included in all copies or substantial portions of the Software.
19  *
20  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27  */
28 #include <config.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <errno.h>
32 #include <fcntl.h>
33 #include <sys/types.h>
34
35 #include <glib.h>
36
37 #ifdef HAVE_UNISTD_H
38 #ifndef __USE_GNU
39 #define __USE_GNU
40 #endif
41 #include <unistd.h>
42 #endif
43
44 #ifdef HAVE_SYS_SELECT_H
45 #include <sys/select.h>
46 #endif
47
48 #ifdef HAVE_SYS_TIME_H
49 #include <sys/time.h>
50 #endif
51
52 #ifdef HAVE_SYS_WAIT_H
53 #include <sys/wait.h>
54 #endif
55
56 #ifdef G_OS_WIN32
57 #include <io.h>
58 #include <winsock2.h>
59 #define open _open
60 #define close _close
61 #define read _read
62 #define write _write
63 /* windows pipe api details: http://msdn2.microsoft.com/en-us/library/edze9h7e(VS.80).aspx */
64 #define pipe(x) _pipe(x, 256, 0)
65 #endif
66
67 #define set_error(msg, ...) do { if (error != NULL) *error = g_error_new (G_LOG_DOMAIN, 1, msg, __VA_ARGS__); } while (0)
68 #define set_error_cond(cond,msg, ...) do { if ((cond) && error != NULL) *error = g_error_new (G_LOG_DOMAIN, 1, msg, __VA_ARGS__); } while (0)
69 #define set_error_status(status,msg, ...) do { if (error != NULL) *error = g_error_new (G_LOG_DOMAIN, status, msg, __VA_ARGS__); } while (0)
70 #define NO_INTR(var,cmd) do { (var) = (cmd); } while ((var) == -1 && errno == EINTR)
71 #define CLOSE_PIPE(p) do { close (p [0]); close (p [1]); } while (0)
72
73 #if defined(__APPLE__) && !defined (__arm__)
74 /* Apple defines this in crt_externs.h but doesn't provide that header for 
75  * arm-apple-darwin9.  We'll manually define the symbol on Apple as it does
76  * in fact exist on all implementations (so far) 
77  */
78 gchar ***_NSGetEnviron();
79 #define environ (*_NSGetEnviron())
80 #elif defined(_MSC_VER)
81 /* MS defines this in stdlib.h */
82 #else
83 extern char **environ;
84 #endif
85
86 #ifndef G_OS_WIN32
87 static int
88 safe_read (int fd, gchar *buffer, gint count, GError **error)
89 {
90         int res;
91
92         NO_INTR (res, read (fd, buffer, count));
93         set_error_cond (res == -1, "%s", "Error reading from pipe.");
94         return res;
95 }
96
97 static int
98 read_pipes (int outfd, gchar **out_str, int errfd, gchar **err_str, GError **error)
99 {
100         fd_set rfds;
101         int res;
102         gboolean out_closed;
103         gboolean err_closed;
104         GString *out = NULL;
105         GString *err = NULL;
106         gchar *buffer = NULL;
107         gint nread;
108
109         out_closed = (outfd < 0);
110         err_closed = (errfd < 0);
111         if (out_str) {
112                 *out_str = NULL;
113                 out = g_string_new ("");
114         }       
115
116         if (err_str) {
117                 *err_str = NULL;
118                 err = g_string_new ("");
119         }       
120
121         do {
122                 if (out_closed && err_closed)
123                         break;
124
125 #ifdef _MSC_VER
126 #pragma warning(push)
127 #pragma warning(disable:4389)
128 #endif
129
130                 FD_ZERO (&rfds);
131                 if (!out_closed && outfd >= 0)
132                         FD_SET (outfd, &rfds);
133                 if (!err_closed && errfd >= 0)
134                         FD_SET (errfd, &rfds);
135
136 #ifdef _MSC_VER
137 #pragma warning(pop)
138 #endif
139
140                 res = select (MAX (outfd, errfd) + 1, &rfds, NULL, NULL, NULL);
141                 if (res > 0) {
142                         if (buffer == NULL)
143                                 buffer = g_malloc (1024);
144                         if (!out_closed && FD_ISSET (outfd, &rfds)) {
145                                 nread = safe_read (outfd, buffer, 1024, error);
146                                 if (nread < 0) {
147                                         close (errfd);
148                                         close (outfd);
149                                         return -1;
150                                 }
151                                 g_string_append_len (out, buffer, nread);
152                                 if (nread <= 0) {
153                                         out_closed = TRUE;
154                                         close (outfd);
155                                 }
156                         }
157
158                         if (!err_closed && FD_ISSET (errfd, &rfds)) {
159                                 nread = safe_read (errfd, buffer, 1024, error);
160                                 if (nread < 0) {
161                                         close (errfd);
162                                         close (outfd);
163                                         return -1;
164                                 }
165                                 g_string_append_len (err, buffer, nread);
166                                 if (nread <= 0) {
167                                         err_closed = TRUE;
168                                         close (errfd);
169                                 }
170                         }
171                 }
172         } while (res > 0 || (res == -1 && errno == EINTR));
173
174         g_free (buffer);
175         if (out_str)
176                 *out_str = g_string_free (out, FALSE);
177
178         if (err_str)
179                 *err_str = g_string_free (err, FALSE);
180
181         return 0;
182 }
183
184 static gboolean
185 create_pipe (int *fds, GError **error)
186 {
187         if (pipe (fds) == -1) {
188                 set_error ("%s", "Error creating pipe.");
189                 return FALSE;
190         }
191         return TRUE;
192 }
193 #endif /* G_OS_WIN32 */
194
195 static int
196 write_all (int fd, const void *vbuf, size_t n)
197 {
198         const char *buf = (const char *) vbuf;
199         size_t nwritten = 0;
200         int w;
201         
202         do {
203                 do {
204                         w = write (fd, buf + nwritten, n - nwritten);
205                 } while (w == -1 && errno == EINTR);
206                 
207                 if (w == -1)
208                         return -1;
209                 
210                 nwritten += w;
211         } while (nwritten < n);
212         
213         return nwritten;
214 }
215
216 gboolean
217 g_spawn_command_line_sync (const gchar *command_line,
218                                 gchar **standard_output,
219                                 gchar **standard_error,
220                                 gint *exit_status,
221                                 GError **error)
222 {
223 #ifdef G_OS_WIN32
224 #else
225         pid_t pid;
226         gchar **argv;
227         gint argc;
228         int stdout_pipe [2] = { -1, -1 };
229         int stderr_pipe [2] = { -1, -1 };
230         int status;
231         int res;
232         
233         if (!g_shell_parse_argv (command_line, &argc, &argv, error))
234                 return FALSE;
235
236         if (standard_output && !create_pipe (stdout_pipe, error))
237                 return FALSE;
238
239         if (standard_error && !create_pipe (stderr_pipe, error)) {
240                 if (standard_output) {
241                         CLOSE_PIPE (stdout_pipe);
242                 }
243                 return FALSE;
244         }
245
246         pid = fork ();
247         if (pid == 0) {
248                 gint i;
249
250                 if (standard_output) {
251                         close (stdout_pipe [0]);
252                         dup2 (stdout_pipe [1], STDOUT_FILENO);
253                 }
254
255                 if (standard_error) {
256                         close (stderr_pipe [0]);
257                         dup2 (stderr_pipe [1], STDERR_FILENO);
258                 }
259                 for (i = getdtablesize () - 1; i >= 3; i--)
260                         close (i);
261
262                 /* G_SPAWN_SEARCH_PATH is always enabled for g_spawn_command_line_sync */
263                 if (!g_path_is_absolute (argv [0])) {
264                         gchar *arg0;
265
266                         arg0 = g_find_program_in_path (argv [0]);
267                         if (arg0 == NULL) {
268                                 exit (1);
269                         }
270                         //g_free (argv [0]);
271                         argv [0] = arg0;
272                 }
273                 execv (argv [0], argv);
274                 exit (1); /* TODO: What now? */
275         }
276
277         g_strfreev (argv);
278         if (standard_output)
279                 close (stdout_pipe [1]);
280
281         if (standard_error)
282                 close (stderr_pipe [1]);
283
284         if (standard_output || standard_error) {
285                 res = read_pipes (stdout_pipe [0], standard_output, stderr_pipe [0], standard_error, error);
286                 if (res) {
287                         waitpid (pid, &status, WNOHANG); /* avoid zombie */
288                         return FALSE;
289                 }
290         }
291
292         NO_INTR (res, waitpid (pid, &status, 0));
293
294         /* TODO: What if error? */
295         if (WIFEXITED (status) && exit_status) {
296                 *exit_status = WEXITSTATUS (status);
297         }
298 #endif
299         return TRUE;
300 }
301
302 /*
303  * This is the only use we have in mono/metadata
304 !g_spawn_async_with_pipes (NULL, (char**)addr_argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, &child_pid, &ch_in, &ch_out, NULL, NULL)
305 */
306 gboolean
307 g_spawn_async_with_pipes (const gchar *working_directory,
308                         gchar **argv,
309                         gchar **envp,
310                         GSpawnFlags flags,
311                         GSpawnChildSetupFunc child_setup,
312                         gpointer user_data,
313                         GPid *child_pid,
314                         gint *standard_input,
315                         gint *standard_output,
316                         gint *standard_error,
317                         GError **error)
318 {
319 #ifdef G_OS_WIN32
320 #else
321         pid_t pid;
322         int info_pipe [2];
323         int in_pipe [2] = { -1, -1 };
324         int out_pipe [2] = { -1, -1 };
325         int err_pipe [2] = { -1, -1 };
326         int status;
327
328         g_return_val_if_fail (argv != NULL, FALSE); /* Only mandatory arg */
329
330         if (!create_pipe (info_pipe, error))
331                 return FALSE;
332
333         if (standard_output && !create_pipe (out_pipe, error)) {
334                 CLOSE_PIPE (info_pipe);
335                 return FALSE;
336         }
337
338         if (standard_error && !create_pipe (err_pipe, error)) {
339                 CLOSE_PIPE (info_pipe);
340                 CLOSE_PIPE (out_pipe);
341                 return FALSE;
342         }
343
344         if (standard_input && !create_pipe (in_pipe, error)) {
345                 CLOSE_PIPE (info_pipe);
346                 CLOSE_PIPE (out_pipe);
347                 CLOSE_PIPE (err_pipe);
348                 return FALSE;
349         }
350
351         pid = fork ();
352         if (pid == -1) {
353                 CLOSE_PIPE (info_pipe);
354                 CLOSE_PIPE (out_pipe);
355                 CLOSE_PIPE (err_pipe);
356                 CLOSE_PIPE (in_pipe);
357                 set_error ("%s", "Error in fork ()");
358                 return FALSE;
359         }
360
361         if (pid == 0) {
362                 /* No zombie left behind */
363                 if ((flags & G_SPAWN_DO_NOT_REAP_CHILD) == 0) {
364                         pid = fork ();
365                 }
366
367                 if (pid != 0) {
368                         exit (pid == -1 ? 1 : 0);
369                 }  else {
370                         gint i;
371                         int fd;
372                         gchar *arg0;
373                         gchar **actual_args;
374                         gint unused;
375
376                         close (info_pipe [0]);
377                         close (in_pipe [1]);
378                         close (out_pipe [0]);
379                         close (err_pipe [0]);
380
381                         /* when exec* succeeds, we want to close this fd, which will return
382                          * a 0 read on the parent. We're not supposed to keep it open forever.
383                          * If exec fails, we still can write the error to it before closing.
384                          */
385                         fcntl (info_pipe [1], F_SETFD, FD_CLOEXEC);
386
387                         if ((flags & G_SPAWN_DO_NOT_REAP_CHILD) == 0) {
388                                 pid = getpid ();
389                                 NO_INTR (unused, write_all (info_pipe [1], &pid, sizeof (pid_t)));
390                         }
391
392                         if (working_directory && chdir (working_directory) == -1) {
393                                 int err = errno;
394                                 NO_INTR (unused, write_all (info_pipe [1], &err, sizeof (int)));
395                                 exit (0);
396                         }
397
398                         if (standard_output) {
399                                 dup2 (out_pipe [1], STDOUT_FILENO);
400                         } else if ((flags & G_SPAWN_STDOUT_TO_DEV_NULL) != 0) {
401                                 fd = open ("/dev/null", O_WRONLY);
402                                 dup2 (fd, STDOUT_FILENO);
403                         }
404
405                         if (standard_error) {
406                                 dup2 (err_pipe [1], STDERR_FILENO);
407                         } else if ((flags & G_SPAWN_STDERR_TO_DEV_NULL) != 0) {
408                                 fd = open ("/dev/null", O_WRONLY);
409                                 dup2 (fd, STDERR_FILENO);
410                         }
411
412                         if (standard_input) {
413                                 dup2 (in_pipe [0], STDIN_FILENO);
414                         } else if ((flags & G_SPAWN_CHILD_INHERITS_STDIN) == 0) {
415                                 fd = open ("/dev/null", O_RDONLY);
416                                 dup2 (fd, STDIN_FILENO);
417                         }
418
419                         if ((flags & G_SPAWN_LEAVE_DESCRIPTORS_OPEN) != 0) {
420                                 for (i = getdtablesize () - 1; i >= 3; i--)
421                                         close (i);
422                         }
423
424                         actual_args = ((flags & G_SPAWN_FILE_AND_ARGV_ZERO) == 0) ? argv : argv + 1;
425                         if (envp == NULL)
426                                 envp = environ;
427
428                         if (child_setup)
429                                 child_setup (user_data);
430
431                         arg0 = argv [0];
432                         if (!g_path_is_absolute (arg0) || (flags & G_SPAWN_SEARCH_PATH) != 0) {
433                                 arg0 = g_find_program_in_path (argv [0]);
434                                 if (arg0 == NULL) {
435                                         int err = ENOENT;
436                                         write_all (info_pipe [1], &err, sizeof (int));
437                                         exit (0);
438                                 }
439                         }
440
441                         execve (arg0, actual_args, envp);
442                         write_all (info_pipe [1], &errno, sizeof (int));
443                         exit (0);
444                 }
445         } else if ((flags & G_SPAWN_DO_NOT_REAP_CHILD) == 0) {
446                 int w;
447                 /* Wait for the first child if two are created */
448                 NO_INTR (w, waitpid (pid, &status, 0));
449                 if (status == 1 || w == -1) {
450                         CLOSE_PIPE (info_pipe);
451                         CLOSE_PIPE (out_pipe);
452                         CLOSE_PIPE (err_pipe);
453                         CLOSE_PIPE (in_pipe);
454                         set_error ("Error in fork (): %d", status);
455                         return FALSE;
456                 }
457         }
458         close (info_pipe [1]);
459         close (in_pipe [0]);
460         close (out_pipe [1]);
461         close (err_pipe [1]);
462
463         if ((flags & G_SPAWN_DO_NOT_REAP_CHILD) == 0) {
464                 int x;
465                 NO_INTR (x, read (info_pipe [0], &pid, sizeof (pid_t))); /* if we read < sizeof (pid_t)... */
466         }
467
468         if (child_pid) {
469                 *child_pid = pid;
470         }
471
472         if (read (info_pipe [0], &status, sizeof (int)) != 0) {
473                 close (info_pipe [0]);
474                 close (in_pipe [0]);
475                 close (out_pipe [1]);
476                 close (err_pipe [1]);
477                 set_error_status (status, "Error in exec (%d -> %s)", status, strerror (status));
478                 return FALSE;
479         }
480
481         close (info_pipe [0]);
482         if (standard_input)
483                 *standard_input = in_pipe [1];
484         if (standard_output)
485                 *standard_output = out_pipe [0];
486         if (standard_error)
487                 *standard_error = err_pipe [0];
488 #endif
489         return TRUE;
490 }
491
492