-fix time assertion introduce in last patch
[oweals/gnunet.git] / src / util / os_priority.c
index 1466ce0599805728b6d1d9fcc288bcb89dfa07b7..d3310abb175463c9e58fb3deca0651de37fa90f5 100644 (file)
@@ -107,7 +107,7 @@ parent_control_handler (void *cls,
   GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
                                  control_pipe, &parent_control_handler,
                                  control_pipe);
-  raise ((int) sig);
+  GNUNET_SIGNAL_raise ((int) sig);
 }
 
 
@@ -503,6 +503,7 @@ start_process (int pipe_control,
                enum GNUNET_OS_InheritStdioFlags std_inheritance,
               struct GNUNET_DISK_PipeHandle *pipe_stdin,
               struct GNUNET_DISK_PipeHandle *pipe_stdout,
+              struct GNUNET_DISK_PipeHandle *pipe_stderr,
               const SOCKTYPE *lsocks,
               const char *filename,
               char *const argv[])
@@ -523,6 +524,8 @@ start_process (int pipe_control,
   unsigned int ls;
   int fd_stdout_write;
   int fd_stdout_read;
+  int fd_stderr_write;
+  int fd_stderr_read;
   int fd_stdin_read;
   int fd_stdin_write;
 
@@ -560,6 +563,17 @@ start_process (int pipe_control,
     childpipe_write = NULL;
     childpipe_read_fd = -1;
   }
+  if (NULL != pipe_stdin)
+  {
+    GNUNET_assert (GNUNET_OK ==
+                  GNUNET_DISK_internal_file_handle_ (GNUNET_DISK_pipe_handle
+                                                     (pipe_stdin, GNUNET_DISK_PIPE_END_READ),
+                                                     &fd_stdin_read, sizeof (int)));
+    GNUNET_assert (GNUNET_OK ==
+                  GNUNET_DISK_internal_file_handle_ (GNUNET_DISK_pipe_handle
+                                                     (pipe_stdin, GNUNET_DISK_PIPE_END_WRITE),
+                                                     &fd_stdin_write, sizeof (int)));
+  }
   if (NULL != pipe_stdout)
   {
     GNUNET_assert (GNUNET_OK ==
@@ -572,16 +586,18 @@ start_process (int pipe_control,
                                                      (pipe_stdout, GNUNET_DISK_PIPE_END_READ),
                                                      &fd_stdout_read, sizeof (int)));
   }
-  if (NULL != pipe_stdin)
+  if (NULL != pipe_stderr)
   {
     GNUNET_assert (GNUNET_OK ==
-                  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_stderr,
+                                                       GNUNET_DISK_PIPE_END_READ),
+                                                      &fd_stderr_read, sizeof (int)));
     GNUNET_assert (GNUNET_OK ==
-                  GNUNET_DISK_internal_file_handle_ (GNUNET_DISK_pipe_handle
-                                                     (pipe_stdin, GNUNET_DISK_PIPE_END_WRITE),
-                                                     &fd_stdin_write, sizeof (int)));
+                   GNUNET_DISK_internal_file_handle_ (GNUNET_DISK_pipe_handle
+                                                      (pipe_stderr,
+                                                       GNUNET_DISK_PIPE_END_WRITE),
+                                                      &fd_stderr_write, sizeof (int)));
   }
   lscp = NULL;
   ls = 0;
@@ -659,7 +675,14 @@ start_process (int pipe_control,
     GNUNET_break (0 == close (1));
     open_dev_null (1, O_WRONLY);
   }
-  if (0 == (std_inheritance & GNUNET_OS_INHERIT_STD_ERR))
+  if (NULL != pipe_stderr)
+  {
+    GNUNET_break (0 == close (fd_stderr_read));
+    if (-1 == dup2 (fd_stderr_write, 2))
+      LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "dup2");
+    GNUNET_break (0 == close (fd_stderr_write));
+  }
+  else if (0 == (std_inheritance & GNUNET_OS_INHERIT_STD_ERR))
   {
     GNUNET_break (0 == close (2));
     open_dev_null (2, O_WRONLY);
@@ -753,6 +776,7 @@ start_process (int pipe_control,
   DWORD stdif, stdof, stdef;
   BOOL bresult;
   DWORD error_code;
+  DWORD create_no_window;
 
   if (GNUNET_SYSERR == GNUNET_OS_check_helper_binary (filename, GNUNET_NO, NULL))
     return NULL; /* not executable */
@@ -1051,8 +1075,17 @@ start_process (int pipe_control,
     return NULL;
   }
 
+  create_no_window = 0;
+  {
+    HANDLE console_input = CreateFile ("CONIN$", GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
+    if (INVALID_HANDLE_VALUE == console_input)
+      create_no_window = CREATE_NO_WINDOW;
+    else
+      CloseHandle (console_input);
+  }
+
   bresult = CreateProcessW (wpath, wcmd, NULL, NULL, GNUNET_YES,
-       CREATE_NO_WINDOW | CREATE_SUSPENDED, env_block, NULL, &start, &proc);
+       create_no_window | CREATE_SUSPENDED, env_block, NULL, &start, &proc);
   error_code = GetLastError ();
 
   if ((NULL == pipe_stdin) && (stdih))
@@ -1089,7 +1122,7 @@ start_process (int pipe_control,
     return NULL;
   }
 
-  gnunet_proc = GNUNET_malloc (sizeof (struct GNUNET_OS_Process));
+  gnunet_proc = GNUNET_new (struct GNUNET_OS_Process);
   gnunet_proc->pid = proc.dwProcessId;
   gnunet_proc->handle = proc.hProcess;
   gnunet_proc->control_pipe = childpipe_write;
@@ -1192,8 +1225,6 @@ start_process (int pipe_control,
 }
 
 
-
-
 /**
  * Start a process.
  *
@@ -1201,6 +1232,7 @@ start_process (int pipe_control,
  * @param std_inheritance a set of GNUNET_OS_INHERIT_STD_* flags
  * @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 pipe_stderr pipe to use to get output from child process (or NULL)
  * @param filename name of the binary
  * @param argv NULL-terminated array of arguments to the process
  * @return pointer to process structure of the new process, NULL on error
@@ -1210,6 +1242,7 @@ GNUNET_OS_start_process_vap (int pipe_control,
                              enum GNUNET_OS_InheritStdioFlags std_inheritance,
                             struct GNUNET_DISK_PipeHandle *pipe_stdin,
                             struct GNUNET_DISK_PipeHandle *pipe_stdout,
+                             struct GNUNET_DISK_PipeHandle *pipe_stderr,
                             const char *filename,
                             char *const argv[])
 {
@@ -1217,6 +1250,7 @@ GNUNET_OS_start_process_vap (int pipe_control,
                         std_inheritance,
                        pipe_stdin,
                        pipe_stdout,
+                        pipe_stderr,
                        NULL,
                        filename,
                        argv);
@@ -1230,6 +1264,7 @@ GNUNET_OS_start_process_vap (int pipe_control,
  * @param std_inheritance a set of GNUNET_OS_INHERIT_STD_* flags
  * @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 pipe_stderr 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
@@ -1239,6 +1274,7 @@ GNUNET_OS_start_process_va (int pipe_control,
                             enum GNUNET_OS_InheritStdioFlags std_inheritance,
                            struct GNUNET_DISK_PipeHandle *pipe_stdin,
                             struct GNUNET_DISK_PipeHandle *pipe_stdout,
+                            struct GNUNET_DISK_PipeHandle *pipe_stderr,
                             const char *filename, va_list va)
 {
   struct GNUNET_OS_Process *ret;
@@ -1261,6 +1297,7 @@ GNUNET_OS_start_process_va (int pipe_control,
                                      std_inheritance,
                                     pipe_stdin,
                                     pipe_stdout,
+                                     pipe_stderr,
                                     filename,
                                     argv);
   GNUNET_free (argv);
@@ -1284,14 +1321,20 @@ GNUNET_OS_start_process (int pipe_control,
                          enum GNUNET_OS_InheritStdioFlags std_inheritance,
                         struct GNUNET_DISK_PipeHandle *pipe_stdin,
                          struct GNUNET_DISK_PipeHandle *pipe_stdout,
+                         struct GNUNET_DISK_PipeHandle *pipe_stderr,
                          const char *filename, ...)
 {
   struct GNUNET_OS_Process *ret;
   va_list ap;
 
   va_start (ap, filename);
-  ret = GNUNET_OS_start_process_va (pipe_control, std_inheritance, pipe_stdin,
-                                   pipe_stdout, filename, ap);
+  ret = GNUNET_OS_start_process_va (pipe_control,
+                                    std_inheritance,
+                                    pipe_stdin,
+                                   pipe_stdout,
+                                    pipe_stderr,
+                                    filename,
+                                    ap);
   va_end (ap);
   return ret;
 }
@@ -1322,12 +1365,150 @@ GNUNET_OS_start_process_v (int pipe_control,
                         std_inheritance,
                        NULL,
                        NULL,
+                        NULL,
                        lsocks,
                        filename,
                        argv);
 }
 
 
+/**
+ * Start a process.  This function is similar to the GNUNET_OS_start_process_*
+ * except that the filename and arguments can have whole strings which contain
+ * the arguments.  These arguments are to be separated by spaces and are parsed
+ * in the order they appear.  Arguments containing spaces can be used by
+ * quoting them with @em ".
+ *
+ * @param pipe_control should a pipe be used to send signals to the child?
+ * @param std_inheritance a set of GNUNET_OS_INHERIT_STD_* flags
+ * @param lsocks array of listen sockets to dup systemd-style (or NULL);
+ *         must be NULL on platforms where dup is not supported
+ * @param filename name of the binary.  It is valid to have the arguments
+ *         in this string when they are separated by spaces.
+ * @param ... more arguments.  Should be of type `char *`.  It is valid
+ *         to have the arguments in these strings when they are separated by
+ *         spaces.  The last argument MUST be NULL.
+ * @return pointer to process structure of the new process, NULL on error
+ */
+struct GNUNET_OS_Process *
+GNUNET_OS_start_process_s (int pipe_control,
+                           unsigned int std_inheritance,
+                           const SOCKTYPE * lsocks,
+                           const char *filename, ...)
+{
+  va_list ap;
+  char **argv;
+  unsigned int argv_size;
+  const char *arg;
+  const char *rpos;
+  char *pos;
+  char *cp;
+  const char *last;
+  struct GNUNET_OS_Process *proc;
+  char *binary_path;
+  int quote_on;
+  unsigned int i;
+  size_t len;
+
+  argv_size = 1;
+  va_start (ap, filename);
+  arg = filename;
+  last = NULL;
+  do
+  {
+    rpos = arg;
+    quote_on = 0;
+    while ('\0' != *rpos)
+    {
+      if ('"' == *rpos)
+      {
+       if (1 == quote_on)
+         quote_on = 0;
+       else
+         quote_on = 1;
+      }
+      if ( (' ' == *rpos) && (0 == quote_on) )
+      {
+       if (NULL != last)
+         argv_size++;
+       last = NULL;
+       rpos++;
+       while (' ' == *rpos)
+         rpos++;
+      }
+      if ( (NULL == last) && ('\0' != *rpos) ) // FIXME: == or !=?
+       last = rpos;
+      if ('\0' != *rpos)
+       rpos++;
+    }
+    if (NULL != last)
+      argv_size++;
+  }
+  while (NULL != (arg = (va_arg (ap, const char*))));
+  va_end (ap);
+
+  argv = GNUNET_malloc (argv_size * sizeof (char *));
+  argv_size = 0;
+  va_start (ap, filename);
+  arg = filename;
+  last = NULL;
+  do
+  {
+    cp = GNUNET_strdup (arg);
+    quote_on = 0;
+    pos = cp;
+    while ('\0' != *pos)
+    {
+      if ('"' == *pos)
+      {
+       if (1 == quote_on)
+         quote_on = 0;
+       else
+         quote_on = 1;
+      }
+      if ( (' ' == *pos) && (0 == quote_on) )
+      {
+       *pos = '\0';
+       if (NULL != last)
+         argv[argv_size++] = GNUNET_strdup (last);
+       last = NULL;
+       pos++;
+       while (' ' == *pos)
+         pos++;
+      }
+      if ( (NULL == last) && ('\0' != *pos)) // FIXME: == or !=?
+       last = pos;
+      if ('\0' != *pos)
+       pos++;
+    }
+    if (NULL != last)
+      argv[argv_size++] = GNUNET_strdup (last);
+    last = NULL;
+    GNUNET_free (cp);
+  }
+  while (NULL != (arg = (va_arg (ap, const char*))));
+  va_end (ap);
+  argv[argv_size] = NULL;
+
+  for(i = 0; i < argv_size; i++)
+  {
+    len = strlen (argv[i]);
+    if ( (argv[i][0] == '"') && (argv[i][len-1] == '"'))
+    {
+      memmove (&argv[i][0], &argv[i][1], len - 2);
+      argv[i][len-2] = '\0';
+    }
+  }
+  binary_path = argv[0];
+  proc = GNUNET_OS_start_process_v (pipe_control, std_inheritance, lsocks,
+                                   binary_path, argv);
+  while (argv_size > 0)
+    GNUNET_free (argv[--argv_size]);
+  GNUNET_free (argv);
+  return proc;
+}
+
+
 /**
  * Retrieve the status of a process, waiting on him if dead.
  * Nonblocking version.
@@ -1629,7 +1810,7 @@ GNUNET_OS_command_run (GNUNET_OS_LineProcessor proc, void *proc_cls,
     return NULL;
   va_start (ap, binary);
   /* redirect stdout, don't inherit stderr/stdin */
-  eip = GNUNET_OS_start_process_va (GNUNET_NO, 0, NULL, opipe, binary, ap);
+  eip = GNUNET_OS_start_process_va (GNUNET_NO, 0, NULL, opipe, NULL, binary, ap);
   va_end (ap);
   if (NULL == eip)
   {
@@ -1637,7 +1818,7 @@ GNUNET_OS_command_run (GNUNET_OS_LineProcessor proc, void *proc_cls,
     return NULL;
   }
   GNUNET_DISK_pipe_close_end (opipe, GNUNET_DISK_PIPE_END_WRITE);
-  cmd = GNUNET_malloc (sizeof (struct GNUNET_OS_CommandHandle));
+  cmd = GNUNET_new (struct GNUNET_OS_CommandHandle);
   cmd->timeout = GNUNET_TIME_relative_to_absolute (timeout);
   cmd->eip = eip;
   cmd->opipe = opipe;