-#if ENABLE_WINDOWS_WORKAROUNDS
- struct GNUNET_DISK_FileHandle *control_pipe = NULL;
- char *childpipename = NULL;
-#endif
-
-#ifndef MINGW
- pid_t ret;
- char lpid[16];
- char fds[16];
- struct GNUNET_OS_Process *gnunet_proc = NULL;
- int i;
- int j;
- int k;
- int tgt;
- int flags;
- int *lscp;
- unsigned int ls;
-
-#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
-
- lscp = NULL;
- ls = 0;
- if (lsocks != NULL)
- {
- i = 0;
- while (-1 != (k = lsocks[i++]))
- GNUNET_array_append (lscp, ls, k);
- GNUNET_array_append (lscp, ls, -1);
- }
-#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 */
- 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_array_grow (lscp, ls, 0);
-#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 (lscp != NULL)
- {
- /* read systemd documentation... */
- GNUNET_snprintf (lpid, sizeof (lpid), "%u", getpid());
- setenv ("LISTEN_PID", lpid, 1);
- i = 0;
- tgt = 3;
- while (-1 != lscp[i])
- {
- j = i + 1;
- while (-1 != lscp[j])
- {
- if (lscp[j] == tgt)
- {
- /* dup away */
- k = dup (lscp[j]);
- GNUNET_assert (-1 != k);
- GNUNET_assert (0 == close (lscp[j]));
- lscp[j] = k;
- break;
- }
- j++;
- }
- if (lscp[i] != tgt)
- {
- /* Bury any existing FD, no matter what; they should all be closed
- on exec anyway and the important onces have been dup'ed away */
- (void) close (tgt);
- GNUNET_assert (-1 != dup2 (lscp[i], tgt));
- }
- /* unset close-on-exec flag */
- flags = fcntl (tgt, F_GETFD);
- GNUNET_assert (flags >= 0);
- flags &= ~FD_CLOEXEC;
- fflush (stderr);
- (void) fcntl (tgt, F_SETFD, flags);
- tgt++;
- i++;
- }
- GNUNET_snprintf (fds, sizeof (fds), "%u", i);
- setenv ("LISTEN_FDS", fds, 1);
- }
- GNUNET_array_grow (lscp, ls, 0);
- execvp (filename, argv);
- GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "execvp", filename);
- _exit (1);
-#else
- char **arg, **non_const_argv;
- unsigned int cmdlen;
- char *cmd, *idx;
- STARTUPINFO start;
- PROCESS_INFORMATION proc;
- int argcount = 0;
- struct GNUNET_OS_Process *gnunet_proc = NULL;
-
- 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;
-
- GNUNET_assert (lsocks == NULL);
-
- /* 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);