-GArik: fix typo
[oweals/gnunet.git] / src / util / os_priority.c
index de3a5757e04bdf4fc7712147dd95a7d4cc89139f..b1cf2fbff0c1794466c25b6e7174b71d1e685ca1 100644 (file)
@@ -28,6 +28,7 @@
 #include "gnunet_common.h"
 #include "gnunet_os_lib.h"
 #include "gnunet_scheduler_lib.h"
+#include "gnunet_strings_lib.h"
 #include "disk.h"
 
 #define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__)
@@ -304,7 +305,7 @@ extern GNUNET_SIGNAL_Handler w32_sigchld_handler;
  * @param proc pointer to process structure
  */
 static DWORD_WINAPI
-ChildWaitThread (void *arg)
+child_wait_thread (void *arg)
 {
   struct GNUNET_OS_Process *proc = (struct GNUNET_OS_Process *) arg;
 
@@ -533,16 +534,15 @@ CreateCustomEnvTable (char **vars)
  * @param pipe_stdin pipe to use to send input to child process (or NULL)
  * @param pipe_stdout pipe to use to get output from child process (or NULL)
  * @param filename name of the binary
- * @param va NULL-terminated list of arguments to the process
+ * @param argv NULL-terminated array of arguments to the process
  * @return pointer to process structure of the new process, NULL on error
  */
 struct GNUNET_OS_Process *
-GNUNET_OS_start_process_va (struct GNUNET_DISK_PipeHandle *pipe_stdin,
-                            struct GNUNET_DISK_PipeHandle *pipe_stdout,
-                            const char *filename, va_list va)
+GNUNET_OS_start_process_vap (struct GNUNET_DISK_PipeHandle *pipe_stdin,
+                            struct GNUNET_DISK_PipeHandle *pipe_stdout,
+                            const char *filename, 
+                            char *const argv[])
 {
-  va_list ap;
-
 #if ENABLE_WINDOWS_WORKAROUNDS
   char *childpipename = NULL;
   struct GNUNET_DISK_FileHandle *control_pipe = NULL;
@@ -551,8 +551,6 @@ GNUNET_OS_start_process_va (struct GNUNET_DISK_PipeHandle *pipe_stdin,
 
 #ifndef MINGW
   pid_t ret;
-  char **argv;
-  int argc;
   int fd_stdout_write;
   int fd_stdout_read;
   int fd_stdin_read;
@@ -566,20 +564,6 @@ GNUNET_OS_start_process_va (struct GNUNET_DISK_PipeHandle *pipe_stdin,
   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
@@ -618,7 +602,6 @@ GNUNET_OS_start_process_va (struct GNUNET_DISK_PipeHandle *pipe_stdin,
       gnunet_proc->control_pipe = control_pipe;
 #endif
     }
-    GNUNET_free (argv);
 #if ENABLE_WINDOWS_WORKAROUNDS
     GNUNET_free (childpipename);
 #endif
@@ -653,9 +636,9 @@ GNUNET_OS_start_process_va (struct GNUNET_DISK_PipeHandle *pipe_stdin,
   char *arg;
   unsigned int cmdlen;
   char *cmd, *idx;
-  STARTUPINFO start;
+  STARTUPINFOW start;
   PROCESS_INFORMATION proc;
-
+  int argc;
   HANDLE stdin_handle;
   HANDLE stdout_handle;
 
@@ -670,6 +653,7 @@ GNUNET_OS_start_process_va (struct GNUNET_DISK_PipeHandle *pipe_stdin,
   char *libdir;
   char *ptr;
   char *non_const_filename;
+  wchar_t wpath[MAX_PATH + 1], wcmd[32768];
 
   /* Search in prefix dir (hopefully - the directory from which
    * the current module was loaded), bindir and libdir, then in PATH
@@ -719,26 +703,24 @@ GNUNET_OS_start_process_va (struct GNUNET_DISK_PipeHandle *pipe_stdin,
   GNUNET_free (non_const_filename);
 
   cmdlen = 0;
-  va_copy (ap, va);
-  while (NULL != (arg = va_arg (ap, char *)))
+  argc = 0;
+  while (NULL != (arg = argv[argc++]))
   {
     if (cmdlen == 0)
       cmdlen = cmdlen + strlen (path) + 3;
     else
       cmdlen = cmdlen + strlen (arg) + 3;
   }
-  va_end (ap);
 
   cmd = idx = GNUNET_malloc (sizeof (char) * (cmdlen + 1));
-  va_copy (ap, va);
-  while (NULL != (arg = va_arg (ap, char *)))
+  argc = 0;
+  while (NULL != (arg = argv[argc++]))
   {
     if (idx == cmd)
       idx += sprintf (idx, "\"%s\" ", path);
     else
       idx += sprintf (idx, "\"%s\" ", arg);
   }
-  va_end (ap);
 
   memset (&start, 0, sizeof (start));
   start.cb = sizeof (start);
@@ -786,8 +768,10 @@ GNUNET_OS_start_process_va (struct GNUNET_DISK_PipeHandle *pipe_stdin,
   GNUNET_free (our_env[0]);
   GNUNET_free (our_env[1]);
 
-  if (!CreateProcessA
-      (path, cmd, NULL, NULL, TRUE, DETACHED_PROCESS | CREATE_SUSPENDED,
+  if (ERROR_SUCCESS != plibc_conv_to_win_pathwconv(path, wpath)
+      || ERROR_SUCCESS != plibc_conv_to_win_pathwconv(cmd, wcmd)
+      || !CreateProcessW
+      (wpath, wcmd, NULL, NULL, TRUE, DETACHED_PROCESS | CREATE_SUSPENDED,
        env_block, NULL, &start, &proc))
   {
     SetErrnoFromWinError (GetLastError ());
@@ -804,7 +788,7 @@ GNUNET_OS_start_process_va (struct GNUNET_DISK_PipeHandle *pipe_stdin,
   gnunet_proc->handle = proc.hProcess;
   gnunet_proc->control_pipe = control_pipe;
 
-  CreateThread (NULL, 64000, ChildWaitThread, (void *) gnunet_proc, 0, NULL);
+  CreateThread (NULL, 64000, &child_wait_thread, (void *) gnunet_proc, 0, NULL);
 
   ResumeThread (proc.hThread);
   CloseHandle (proc.hThread);
@@ -816,6 +800,46 @@ GNUNET_OS_start_process_va (struct GNUNET_DISK_PipeHandle *pipe_stdin,
 }
 
 
+/**
+ * Start a process.
+ *
+ * @param pipe_stdin pipe to use to send input to child process (or NULL)
+ * @param pipe_stdout pipe to use to get output from child process (or NULL)
+ * @param filename name of the binary
+ * @param va NULL-terminated list of arguments to the process
+ * @return pointer to process structure of the new process, NULL on error
+ */
+struct GNUNET_OS_Process *
+GNUNET_OS_start_process_va (struct GNUNET_DISK_PipeHandle *pipe_stdin,
+                            struct GNUNET_DISK_PipeHandle *pipe_stdout,
+                            const char *filename, va_list va)
+{
+  struct GNUNET_OS_Process *ret;
+  va_list ap;
+  char **argv;
+  int argc;
+
+  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);
+  ret = GNUNET_OS_start_process_vap (pipe_stdin,
+                                    pipe_stdout,
+                                    filename,
+                                    argv);
+  GNUNET_free (argv);
+  return ret;
+}
+
+
+
 /**
  * Start a process.
  *
@@ -973,7 +997,7 @@ GNUNET_OS_start_process_v (const SOCKTYPE *lsocks,
   char **arg, **non_const_argv;
   unsigned int cmdlen;
   char *cmd, *idx;
-  STARTUPINFO start;
+  STARTUPINFOW start;
   PROCESS_INFORMATION proc;
   int argcount = 0;
   struct GNUNET_OS_Process *gnunet_proc = NULL;
@@ -993,6 +1017,7 @@ GNUNET_OS_start_process_v (const SOCKTYPE *lsocks,
   const struct GNUNET_DISK_FileHandle *lsocks_write_fd;
   HANDLE lsocks_read;
   HANDLE lsocks_write;
+  wchar_t wpath[MAX_PATH + 1], wcmd[32768];
 
   int fail;
 
@@ -1108,9 +1133,9 @@ GNUNET_OS_start_process_v (const SOCKTYPE *lsocks,
     GNUNET_free (path);
     return NULL;
   }
-  if (lsocks != NULL)
+  if (lsocks != NULL && lsocks[0] != INVALID_SOCKET)
   {
-    lsocks_pipe = GNUNET_DISK_pipe (GNUNET_YES, GNUNET_YES, GNUNET_NO);
+    lsocks_pipe = GNUNET_DISK_pipe (GNUNET_YES, GNUNET_YES, GNUNET_YES, GNUNET_NO);
 
     if (lsocks_pipe == NULL)
     {
@@ -1136,7 +1161,7 @@ GNUNET_OS_start_process_v (const SOCKTYPE *lsocks,
   GNUNET_asprintf (&our_env[0], "%s=", GNUNET_OS_CONTROL_PIPE);
   GNUNET_asprintf (&our_env[1], "%s", childpipename);
   GNUNET_free (childpipename);
-  if (lsocks == NULL)
+  if (lsocks == NULL || lsocks[0] == INVALID_SOCKET)
     our_env[2] = NULL;
   else
   {
@@ -1151,8 +1176,10 @@ GNUNET_OS_start_process_v (const SOCKTYPE *lsocks,
   GNUNET_free_non_null (our_env[2]);
   GNUNET_free_non_null (our_env[3]);
 
-  if (!CreateProcessA
-      (path, cmd, NULL, NULL, TRUE, DETACHED_PROCESS | CREATE_SUSPENDED,
+  if (ERROR_SUCCESS != plibc_conv_to_win_pathwconv(path, wpath)
+      || ERROR_SUCCESS != plibc_conv_to_win_pathwconv(cmd, wcmd)
+      || !CreateProcessW
+      (wpath, wcmd, NULL, NULL, TRUE, DETACHED_PROCESS | CREATE_SUSPENDED,
        env_block, NULL, &start, &proc))
   {
     SetErrnoFromWinError (GetLastError ());
@@ -1172,13 +1199,13 @@ GNUNET_OS_start_process_v (const SOCKTYPE *lsocks,
   gnunet_proc->handle = proc.hProcess;
   gnunet_proc->control_pipe = control_pipe;
 
-  CreateThread (NULL, 64000, ChildWaitThread, (void *) gnunet_proc, 0, NULL);
+  CreateThread (NULL, 64000, &child_wait_thread, (void *) gnunet_proc, 0, NULL);
 
   ResumeThread (proc.hThread);
   CloseHandle (proc.hThread);
   GNUNET_free (cmd);
 
-  if (lsocks == NULL)
+  if (lsocks == NULL || lsocks[0] == INVALID_SOCKET)
     return gnunet_proc;
 
   GNUNET_DISK_pipe_close_end (lsocks_pipe, GNUNET_DISK_PIPE_END_READ);
@@ -1372,9 +1399,15 @@ GNUNET_OS_process_wait (struct GNUNET_OS_Process *proc)
 
 #ifndef MINGW
   pid_t pid = proc->pid;
+  pid_t ret;
 
-  if (pid != waitpid (pid, NULL, 0))
+  while ( (pid != (ret = waitpid (pid, NULL, 0))) &&
+         (EINTR == errno) ) ;
+  if (pid != ret) 
+  {
+    LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "waitpid");
     return GNUNET_SYSERR;
+  }
   return GNUNET_OK;
 #else
   HANDLE h;
@@ -1555,7 +1588,7 @@ GNUNET_OS_command_run (GNUNET_OS_LineProcessor proc, void *proc_cls,
   struct GNUNET_DISK_PipeHandle *opipe;
   va_list ap;
 
-  opipe = GNUNET_DISK_pipe (GNUNET_YES, GNUNET_NO, GNUNET_YES);
+  opipe = GNUNET_DISK_pipe (GNUNET_YES, GNUNET_YES, GNUNET_NO, GNUNET_YES);
   if (NULL == opipe)
     return NULL;
   va_start (ap, binary);