Extract the SGEN debugging code into a separate file.
[mono.git] / eglib / src / gspawn.c
index d5f81336b7c0792c71b8acd431dd33eab9c17cc1..4f4e5bef5391cf94e8a601125637c70fcab13371 100644 (file)
  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  */
+#include <config.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <sys/types.h>
-#ifdef _MSC_VER
-#include <winsock2.h>
-#else
+
+#include <glib.h>
+
+#ifdef HAVE_UNISTD_H
+#ifndef __USE_GNU
+#define __USE_GNU
+#endif
 #include <unistd.h>
+#endif
+
+#ifdef HAVE_SYS_TIME_H
 #include <sys/time.h>
+#endif
+
+#ifdef HAVE_SYS_WAIT_H
 #include <sys/wait.h>
 #endif
-#include <glib.h>
+
+#ifdef G_OS_WIN32
+#include <io.h>
+#include <winsock2.h>
+#define open _open
+#define close _close
+#define read _read
+#define write _write
+/* windows pipe api details: http://msdn2.microsoft.com/en-us/library/edze9h7e(VS.80).aspx */
+#define pipe(x) _pipe(x, 256, 0)
+#endif
 
 #define set_error(msg, ...) do { if (error != NULL) *error = g_error_new (G_LOG_DOMAIN, 1, msg, __VA_ARGS__); } while (0)
 #define set_error_cond(cond,msg, ...) do { if ((cond) && error != NULL) *error = g_error_new (G_LOG_DOMAIN, 1, msg, __VA_ARGS__); } while (0)
 #define NO_INTR(var,cmd) do { (var) = (cmd); } while ((var) == -1 && errno == EINTR)
 #define CLOSE_PIPE(p) do { close (p [0]); close (p [1]); } while (0)
 
+#if defined(__APPLE__) && !defined (__arm__)
+/* Apple defines this in crt_externs.h but doesn't provide that header for 
+ * arm-apple-darwin9.  We'll manually define the symbol on Apple as it does
+ * in fact exist on all implementations (so far) 
+ */
+gchar ***_NSGetEnviron();
+#define environ (*_NSGetEnviron())
+#elif defined(_MSC_VER)
+/* MS defines this in stdlib.h */
+#else
+extern char **environ;
+#endif
+
+#ifndef G_OS_WIN32
 static int
 safe_read (int fd, gchar *buffer, gint count, GError **error)
 {
@@ -83,12 +118,21 @@ read_pipes (int outfd, gchar **out_str, int errfd, gchar **err_str, GError **err
                if (out_closed && err_closed)
                        break;
 
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable:4389)
+#endif
+
                FD_ZERO (&rfds);
                if (!out_closed && outfd >= 0)
                        FD_SET (outfd, &rfds);
                if (!err_closed && errfd >= 0)
                        FD_SET (errfd, &rfds);
 
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
+
                res = select (MAX (outfd, errfd) + 1, &rfds, NULL, NULL, NULL);
                if (res > 0) {
                        if (buffer == NULL)
@@ -142,6 +186,28 @@ create_pipe (int *fds, GError **error)
        }
        return TRUE;
 }
+#endif /* G_OS_WIN32 */
+
+static int
+write_all (int fd, const void *vbuf, size_t n)
+{
+       const char *buf = (const char *) vbuf;
+       size_t nwritten = 0;
+       int w;
+       
+       do {
+               do {
+                       w = write (fd, buf + nwritten, n - nwritten);
+               } while (w == -1 && errno == EINTR);
+               
+               if (w == -1)
+                       return -1;
+               
+               nwritten += w;
+       } while (nwritten < n);
+       
+       return nwritten;
+}
 
 gboolean
 g_spawn_command_line_sync (const gchar *command_line,
@@ -150,6 +216,8 @@ g_spawn_command_line_sync (const gchar *command_line,
                                gint *exit_status,
                                GError **error)
 {
+#ifdef G_OS_WIN32
+#else
        pid_t pid;
        gchar **argv;
        gint argc;
@@ -223,7 +291,7 @@ g_spawn_command_line_sync (const gchar *command_line,
        if (WIFEXITED (status) && exit_status) {
                *exit_status = WEXITSTATUS (status);
        }
-
+#endif
        return TRUE;
 }
 
@@ -244,6 +312,8 @@ g_spawn_async_with_pipes (const gchar *working_directory,
                        gint *standard_error,
                        GError **error)
 {
+#ifdef G_OS_WIN32
+#else
        pid_t pid;
        int info_pipe [2];
        int in_pipe [2] = { -1, -1 };
@@ -312,12 +382,12 @@ g_spawn_async_with_pipes (const gchar *working_directory,
 
                        if ((flags & G_SPAWN_DO_NOT_REAP_CHILD) == 0) {
                                pid = getpid ();
-                               NO_INTR (unused, write (info_pipe [1], &pid, sizeof (pid_t)));
+                               NO_INTR (unused, write_all (info_pipe [1], &pid, sizeof (pid_t)));
                        }
 
                        if (working_directory && chdir (working_directory) == -1) {
                                int err = errno;
-                               NO_INTR (unused, write (info_pipe [1], &err, sizeof (int)));
+                               NO_INTR (unused, write_all (info_pipe [1], &err, sizeof (int)));
                                exit (0);
                        }
 
@@ -336,10 +406,10 @@ g_spawn_async_with_pipes (const gchar *working_directory,
                        }
 
                        if (standard_input) {
-                               dup2 (in_pipe [0], STDERR_FILENO);
+                               dup2 (in_pipe [0], STDIN_FILENO);
                        } else if ((flags & G_SPAWN_CHILD_INHERITS_STDIN) == 0) {
                                fd = open ("/dev/null", O_RDONLY);
-                               dup2 (fd, STDERR_FILENO);
+                               dup2 (fd, STDIN_FILENO);
                        }
 
                        if ((flags & G_SPAWN_LEAVE_DESCRIPTORS_OPEN) != 0) {
@@ -359,13 +429,13 @@ g_spawn_async_with_pipes (const gchar *working_directory,
                                arg0 = g_find_program_in_path (argv [0]);
                                if (arg0 == NULL) {
                                        int err = ENOENT;
-                                       write (info_pipe [1], &err, sizeof (int));
+                                       write_all (info_pipe [1], &err, sizeof (int));
                                        exit (0);
                                }
                        }
 
                        execve (arg0, actual_args, envp);
-                       write (info_pipe [1], &errno, sizeof (int));
+                       write_all (info_pipe [1], &errno, sizeof (int));
                        exit (0);
                }
        } else if ((flags & G_SPAWN_DO_NOT_REAP_CHILD) == 0) {
@@ -411,7 +481,8 @@ g_spawn_async_with_pipes (const gchar *working_directory,
                *standard_output = out_pipe [0];
        if (standard_error)
                *standard_error = err_pipe [0];
-
+#endif
        return TRUE;
 }
 
+