api work
[oweals/gnunet.git] / src / util / os_priority.c
index 7862d68e9079fe6c567676012c2d1f3b940dfdfd..4e820b8d5cfda1e8efb95d06e35228edb407e762 100644 (file)
@@ -123,9 +123,11 @@ GNUNET_OS_set_process_priority (pid_t proc,
 pid_t
 GNUNET_OS_start_process (const char *filename, ...)
 {
+  va_list ap;
+
+#ifndef MINGW
   pid_t ret;
   char **argv;
-  va_list ap;
   int argc;
 
   ret = fork ();
@@ -149,6 +151,42 @@ GNUNET_OS_start_process (const char *filename, ...)
   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;
+
+  cmdlen = 0;
+  va_start (ap, filename);
+  while (NULL != (arg = va_arg (ap, char *)))
+    cmdlen = cmdlen + strlen (arg) + 3;
+  va_end (ap);
+
+  cmd = idx = GNUNET_malloc (sizeof(char) * cmdlen);
+  va_start (ap, filename);
+  while (NULL != (arg = va_arg (ap, char *)))
+    idx += sprintf (idx, "\"%s\" ", arg);
+  va_end (ap);
+
+  memset (&start, 0, sizeof(start));
+  start.cb = sizeof(start);
+
+  if (!CreateProcess (filename, cmd, NULL, NULL, FALSE, DETACHED_PROCESS, NULL,
+      NULL, &start, &proc))
+  {
+    SetErrnoFromWinError (GetLastError ());
+    GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "fork");
+    return -1;
+  }
+  CloseHandle (proc.hProcess);
+  CloseHandle (proc.hThread);
+
+  GNUNET_free(cmd);
+
+  return proc.dwProcessId;
+#endif
 }
 
 
@@ -164,6 +202,7 @@ GNUNET_OS_start_process (const char *filename, ...)
 pid_t
 GNUNET_OS_start_process_v (const char *filename, char *const argv[])
 {
+#ifndef MINGW
   pid_t ret;
 
   ret = fork ();
@@ -176,11 +215,167 @@ GNUNET_OS_start_process_v (const char *filename, char *const argv[])
   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;
+
+  cmdlen = 0;
+  arg = argv;
+  while (*arg)
+  {
+    cmdlen = cmdlen + strlen (*arg) + 3;
+    arg++;
+  }
+
+  cmd = idx = GNUNET_malloc (sizeof(char) * cmdlen);
+  arg = argv;
+  while (*arg)
+  {
+    idx += sprintf (idx, "\"%s\" ", *arg);
+    arg++;
+  }
+
+  memset (&start, 0, sizeof(start));
+  start.cb = sizeof(start);
+
+  if (!CreateProcess (filename, cmd, NULL, NULL, FALSE, DETACHED_PROCESS, NULL,
+      NULL, &start, &proc))
+  {
+    SetErrnoFromWinError (GetLastError ());
+    GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "fork");
+    return -1;
+  }
+  CloseHandle (proc.hProcess);
+  CloseHandle (proc.hThread);
+
+  GNUNET_free(cmd);
+
+  return proc.dwProcessId;
+#endif
 }
 
+/**
+ * Retrieve the status of a process
+ * @param proc process ID
+ * @param type status type
+ * @param code return code/signal number
+ * @return GNUNET_OK on success, GNUNET_NO if the process is still running, GNUNET_SYSERR otherwise
+ */
+int
+GNUNET_OS_process_status (pid_t proc, enum GNUNET_OS_ProcessStatusType *type,
+    unsigned long *code)
+{
+#ifndef MINGW
+  int status;
+  int ret;
 
+  GNUNET_assert (0 != proc);
+  ret = waitpid (proc, &status, WNOHANG);
+  if (0 == ret) 
+    {
+      *type = GNUNET_OS_PROCESS_RUNNING;
+      *code = 0;
+      return GNUNET_NO;
+    }
+  if (proc != ret)
+    {
+      GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "waitpid");
+      return GNUNET_SYSERR;
+    }
+  if (WIFEXITED (status))
+  {
+    *type = GNUNET_OS_PROCESS_EXITED;
+    *code = WEXITSTATUS (status);
+  }
+  else if (WIFSIGNALED (status))
+  {
+    *type = GNUNET_OS_PROCESS_SIGNALED;
+    *code = WTERMSIG (status);
+  }
+  else if (WIFSTOPPED (status))
+  {
+    *type = GNUNET_OS_PROCESS_SIGNALED;
+    *code = WSTOPSIG (status);
+  }
+  else if (WIFCONTINUED (status))
+  {
+    *type = GNUNET_OS_PROCESS_RUNNING;
+    *code = 0;
+  }
+  else
+  {
+    *type = GNUNET_OS_PROCESS_UNKNOWN;
+    *code = 0;
+  }
+#else
+  HANDLE h;
+  DWORD c;
+
+  h = OpenProcess (PROCESS_QUERY_INFORMATION, FALSE, proc);
+  if (INVALID_HANDLE_VALUE == h)
+  {
+    SetErrnoFromWinError (GetLastError ());
+    GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "OpenProcess");
+    return GNUNET_SYSERR;
+  }
+
+  c = GetExitCodeProcess (proc, &c);
+  if (STILL_ACTIVE == c)
+  {
+    *type = GNUNET_OS_PROCESS_RUNNING;
+    *code = 0;
+    CloseHandle (h);
+    return GNUNET_NO;
+  }
+  *type = GNUNET_OS_PROCESS_EXITED;
+  *code = c;
+  CloseHandle (h);
+#endif
+
+  return GNUNET_OK;
+}
 
+/**
+ * Wait for a process
+ * @param proc process ID to wait for
+ * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
+ */
+int
+GNUNET_OS_process_wait (pid_t proc)
+{
+#ifndef MINGW
+  if (proc != waitpid (proc, NULL, 0))
+    return GNUNET_SYSERR;
+
+  return GNUNET_OK;
+#else
+  HANDLE h;
+  DWORD c;
+  int ret;
 
+  h = OpenProcess (PROCESS_QUERY_INFORMATION, FALSE, proc);
+  if (INVALID_HANDLE_VALUE == h)
+  {
+    SetErrnoFromWinError (GetLastError ());
+    return GNUNET_SYSERR;
+  }
+
+  if (WAIT_OBJECT_0 != WaitForSingleObject (h, INFINITE))
+  {
+    SetErrnoFromWinError (GetLastError ());
+    ret = GNUNET_SYSERR;
+  }
+  else
+    ret = GNUNET_OK;
+
+  CloseHandle (h);
+
+  return ret;
+#endif
+}
 
 
 /* end of os_priority.c */