* 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 <unistd.h>
-#include <unistd.h>
#include <fcntl.h>
-#include <sys/time.h>
-#include <sys/wait.h>
#include <sys/types.h>
+
#include <glib.h>
-#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 <unistd.h>
+#endif
+
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+
+#ifdef HAVE_SYS_WAIT_H
+#include <sys/wait.h>
+#endif
+
+#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 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;
}
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)
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,
gint *exit_status,
GError **error)
{
+#ifdef G_OS_WIN32
+#else
pid_t pid;
gchar **argv;
gint argc;
if (WIFEXITED (status) && exit_status) {
*exit_status = WEXITSTATUS (status);
}
-
+#endif
return TRUE;
}
gint *standard_error,
GError **error)
{
+#ifdef G_OS_WIN32
+#else
pid_t pid;
int info_pipe [2];
int in_pipe [2] = { -1, -1 };
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;
}
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);
}
}
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) {
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) {
*standard_output = out_pipe [0];
if (standard_error)
*standard_error = err_pipe [0];
-
+#endif
return TRUE;
}
+