- va_list ap;
-
-#if ENABLE_WINDOWS_WORKAROUNDS
- char *childpipename = NULL;
- struct GNUNET_DISK_FileHandle *control_pipe = NULL;
-#endif
- struct GNUNET_OS_Process *gnunet_proc = NULL;
-
-#ifndef MINGW
- pid_t ret;
- char **argv;
- int argc;
- int fd_stdout_write;
- int fd_stdout_read;
- int fd_stdin_read;
- int fd_stdin_write;
-
-#if ENABLE_WINDOWS_WORKAROUNDS
- control_pipe =
- GNUNET_DISK_npipe_create (&childpipename, GNUNET_DISK_OPEN_WRITE,
- GNUNET_DISK_PERM_USER_READ |
- GNUNET_DISK_PERM_USER_WRITE);
- if (control_pipe == NULL)
- return NULL;
-#endif
-
- argc = 0;
- va_copy (ap, va);
- while (NULL != va_arg (ap, char *))
- argc++;
-
- va_end (ap);
- argv = GNUNET_malloc (sizeof (char *) * (argc + 1));
- argc = 0;
- va_copy (ap, va);
- while (NULL != (argv[argc] = va_arg (ap, char *)))
- argc++;
-
- va_end (ap);
- if (pipe_stdout != NULL)
- {
- GNUNET_DISK_internal_file_handle_ (GNUNET_DISK_pipe_handle
- (pipe_stdout,
- GNUNET_DISK_PIPE_END_WRITE),
- &fd_stdout_write, sizeof (int));
- GNUNET_DISK_internal_file_handle_ (GNUNET_DISK_pipe_handle
- (pipe_stdout, GNUNET_DISK_PIPE_END_READ),
- &fd_stdout_read, sizeof (int));
- }
- if (pipe_stdin != NULL)
- {
- GNUNET_DISK_internal_file_handle_ (GNUNET_DISK_pipe_handle
- (pipe_stdin, GNUNET_DISK_PIPE_END_READ),
- &fd_stdin_read, sizeof (int));
- GNUNET_DISK_internal_file_handle_ (GNUNET_DISK_pipe_handle
- (pipe_stdin, GNUNET_DISK_PIPE_END_WRITE),
- &fd_stdin_write, sizeof (int));
- }
-
-#if HAVE_WORKING_VFORK
- ret = vfork ();
-#else
- ret = fork ();
-#endif
- if (ret != 0)
- {
- if (ret == -1)
- {
- GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "fork");
-#if ENABLE_WINDOWS_WORKAROUNDS
- GNUNET_DISK_npipe_close (control_pipe);
-#endif
- }
- else
- {
-
-#if HAVE_WORKING_VFORK
- /* let's hope vfork actually works; for some extreme cases (including
- * a testcase) we need 'execvp' to have run before we return, since
- * we may send a signal to the process next and we don't want it
- * to be caught by OUR signal handler (but either by the default
- * handler or the actual handler as installed by the process itself). */
-#else
- /* let's give the child process a chance to run execvp, 1s should
- * be plenty in practice */
- if (pipe_stdout != NULL)
- GNUNET_DISK_pipe_close_end (pipe_stdout, GNUNET_DISK_PIPE_END_WRITE);
- if (pipe_stdin != NULL)
- GNUNET_DISK_pipe_close_end (pipe_stdin, GNUNET_DISK_PIPE_END_READ);
- sleep (1);
-#endif
- gnunet_proc = GNUNET_malloc (sizeof (struct GNUNET_OS_Process));
- gnunet_proc->pid = ret;
-#if ENABLE_WINDOWS_WORKAROUNDS
- gnunet_proc->control_pipe = control_pipe;
-#endif
- }
- GNUNET_free (argv);
-#if ENABLE_WINDOWS_WORKAROUNDS
- GNUNET_free (childpipename);
-#endif
- return gnunet_proc;
- }
-
-#if ENABLE_WINDOWS_WORKAROUNDS
- setenv (GNUNET_OS_CONTROL_PIPE, childpipename, 1);
- GNUNET_free (childpipename);
-#endif
-
- if (pipe_stdout != NULL)
- {
- GNUNET_break (0 == close (fd_stdout_read));
- if (-1 == dup2 (fd_stdout_write, 1))
- GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "dup2");
- GNUNET_break (0 == close (fd_stdout_write));
- }
-
- if (pipe_stdin != NULL)
- {
-
- GNUNET_break (0 == close (fd_stdin_write));
- if (-1 == dup2 (fd_stdin_read, 0))
- GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "dup2");
- GNUNET_break (0 == close (fd_stdin_read));
- }
- execvp (filename, argv);
- GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "execvp", filename);
- _exit (1);
-#else
- char *arg;
- unsigned int cmdlen;
- char *cmd, *idx;
- STARTUPINFO start;
- PROCESS_INFORMATION proc;
-
- HANDLE stdin_handle;
- HANDLE stdout_handle;
-
- char path[MAX_PATH + 1];
-
- char *our_env[3] = { NULL, NULL, NULL };
- char *env_block = NULL;
- char *pathbuf;
- DWORD pathbuf_len, alloc_len;
- char *self_prefix;
- char *bindir;
- char *libdir;
- char *ptr;
- char *non_const_filename;
-
- /* Search in prefix dir (hopefully - the directory from which
- * the current module was loaded), bindir and libdir, then in PATH
- */
- self_prefix = GNUNET_OS_installation_get_path (GNUNET_OS_IPK_SELF_PREFIX);
- bindir = GNUNET_OS_installation_get_path (GNUNET_OS_IPK_BINDIR);
- libdir = GNUNET_OS_installation_get_path (GNUNET_OS_IPK_LIBDIR);
-
- pathbuf_len = GetEnvironmentVariableA ("PATH", (char *) &pathbuf, 0);
-
- alloc_len =
- pathbuf_len + 1 + strlen (self_prefix) + 1 + strlen (bindir) + 1 +
- strlen (libdir);
-
- pathbuf = GNUNET_malloc (alloc_len * sizeof (char));
-
- ptr = pathbuf;
- ptr += sprintf (pathbuf, "%s;%s;%s;", self_prefix, bindir, libdir);
- GNUNET_free (self_prefix);
- GNUNET_free (bindir);
- GNUNET_free (libdir);
-
- alloc_len = GetEnvironmentVariableA ("PATH", ptr, pathbuf_len);
- GNUNET_assert (alloc_len == (pathbuf_len - 1));
-
- cmdlen = strlen (filename);
- if (cmdlen < 5 || strcmp (&filename[cmdlen - 4], ".exe") != 0)
- GNUNET_asprintf (&non_const_filename, "%s.exe", filename);
- else
- GNUNET_asprintf (&non_const_filename, "%s", filename);
-
- /* Check that this is the full path. If it isn't, search. */
- if (non_const_filename[1] == ':')
- snprintf (path, sizeof (path) / sizeof (char), "%s", non_const_filename);
- else if (!SearchPathA
- (pathbuf, non_const_filename, NULL, sizeof (path) / sizeof (char),
- path, NULL))
- {
- SetErrnoFromWinError (GetLastError ());
- GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "SearchPath",
- non_const_filename);
- GNUNET_free (non_const_filename);
- GNUNET_free (pathbuf);
- return NULL;
- }
- GNUNET_free (pathbuf);
- GNUNET_free (non_const_filename);
-
- cmdlen = 0;
- va_copy (ap, va);
- while (NULL != (arg = va_arg (ap, char *)))
- {
- if (cmdlen == 0)
- cmdlen = cmdlen + strlen (path) + 3;
- else
- cmdlen = cmdlen + strlen (arg) + 3;
- }
- va_end (ap);