X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=eglib%2Fsrc%2Fgspawn.c;h=4f4e5bef5391cf94e8a601125637c70fcab13371;hb=21c71df8d35236aff833b1f280e35f4732be3a67;hp=65a41de11270cd22e8406dcaee415ddc7ae1ea06;hpb=e51a9b6ba1a93bc981639a706c93bee413099fd6;p=mono.git diff --git a/eglib/src/gspawn.c b/eglib/src/gspawn.c index 65a41de1127..4f4e5bef539 100644 --- a/eglib/src/gspawn.c +++ b/eglib/src/gspawn.c @@ -25,31 +25,68 @@ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#define _GNU_SOURCE +#include #include #include #include -#include -#include #include -#include -#include #include + #include -#define set_error(msg...) do { if (error != NULL) *error = g_error_new (G_LOG_DOMAIN, 1, msg); } while (0) -#define set_error_cond(cond,msg...) do { if ((cond) && error != NULL) *error = g_error_new (G_LOG_DOMAIN, 1, msg); } while (0) -#define set_error_status(status,msg...) do { if (error != NULL) *error = g_error_new (G_LOG_DOMAIN, status, msg); } while (0) +#ifdef HAVE_UNISTD_H +#ifndef __USE_GNU +#define __USE_GNU +#endif +#include +#endif + +#ifdef HAVE_SYS_TIME_H +#include +#endif + +#ifdef HAVE_SYS_WAIT_H +#include +#endif + +#ifdef G_OS_WIN32 +#include +#include +#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 set_error_status(status,msg, ...) do { if (error != NULL) *error = g_error_new (G_LOG_DOMAIN, status, 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) { int res; NO_INTR (res, read (fd, buffer, count)); - set_error_cond (res == -1, "Error reading from pipe."); + set_error_cond (res == -1, "%s", "Error reading from pipe."); return res; } @@ -81,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) @@ -135,11 +181,33 @@ static gboolean create_pipe (int *fds, GError **error) { if (pipe (fds) == -1) { - set_error ("Error creating pipe."); + set_error ("%s", "Error creating pipe."); return FALSE; } 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, @@ -148,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; @@ -185,6 +255,17 @@ g_spawn_command_line_sync (const gchar *command_line, for (i = getdtablesize () - 1; i >= 3; i--) close (i); + /* G_SPAWN_SEARCH_PATH is always enabled for g_spawn_command_line_sync */ + if (!g_path_is_absolute (argv [0])) { + gchar *arg0; + + arg0 = g_find_program_in_path (argv [0]); + if (arg0 == NULL) { + exit (1); + } + //g_free (argv [0]); + argv [0] = arg0; + } execv (argv [0], argv); exit (1); /* TODO: What now? */ } @@ -210,7 +291,7 @@ g_spawn_command_line_sync (const gchar *command_line, if (WIFEXITED (status) && exit_status) { *exit_status = WEXITSTATUS (status); } - +#endif return TRUE; } @@ -231,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 }; @@ -267,7 +350,7 @@ g_spawn_async_with_pipes (const gchar *working_directory, CLOSE_PIPE (out_pipe); CLOSE_PIPE (err_pipe); CLOSE_PIPE (in_pipe); - set_error ("Error in fork ()"); + set_error ("%s", "Error in fork ()"); return FALSE; } @@ -299,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); } @@ -323,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) { @@ -346,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) { @@ -398,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; } +