Add process spawning code from gpgex
authorAndre Heinecke <aheinecke@intevation.de>
Fri, 27 Nov 2015 15:15:47 +0000 (16:15 +0100)
committerAndre Heinecke <aheinecke@intevation.de>
Fri, 27 Nov 2015 15:15:47 +0000 (16:15 +0100)
* src/common.c, src/common.h (gpgol_spawn_detached): New.
* src/exechelp.h, src/exechelp.c: New.
* src/Makefile.am: Add exechelp files.

--
While the spawning in gpgol_spawn_detached was quite similar
it makes sense to move that out in it's own source file and
use the same mutex that gpgex uses.

src/Makefile.am
src/common.c
src/common.h
src/exechelp.c [new file with mode: 0644]
src/exechelp.h [new file with mode: 0644]

index cc0aea8..6e02fb4 100644 (file)
@@ -84,7 +84,8 @@ gpgol_SOURCES = \
        mail.h mail.cpp \
        rfc2047parse.h rfc2047parse.c \
        mlang-charset.cpp mlang-charset.h \
-       gmime-table-private.h
+       gmime-table-private.h \
+       exechelp.c exechelp.h
 
 
 #treeview_SOURCES = treeview.c
index fd53592..bf1c9e9 100644 (file)
@@ -965,57 +965,6 @@ generate_boundary (char *buffer)
 }
 
 
-/* Fork and exec the program given in CMDLINE with /dev/null as
-   stdin, stdout and stderr.  Returns 0 on success.  */
-int
-gpgol_spawn_detached (const char *cmdline)
-{
-  int rc;
-  SECURITY_ATTRIBUTES sec_attr;
-  PROCESS_INFORMATION pi = { NULL, 0, 0, 0 };
-  STARTUPINFO si;
-  int cr_flags;
-  char *cmdline_copy;
-
-  memset (&sec_attr, 0, sizeof sec_attr);
-  sec_attr.nLength = sizeof sec_attr;
-  
-  memset (&si, 0, sizeof si);
-  si.cb = sizeof (si);
-  si.dwFlags = STARTF_USESHOWWINDOW;
-  si.wShowWindow = SW_SHOW;
-
-  cr_flags = (CREATE_DEFAULT_ERROR_MODE
-              | GetPriorityClass (GetCurrentProcess ())
-             | CREATE_NEW_PROCESS_GROUP
-              | DETACHED_PROCESS); 
-
-  cmdline_copy = xstrdup (cmdline);
-  rc = CreateProcess (NULL,          /* No appliactionname, use CMDLINE.  */
-                      cmdline_copy,  /* Command line arguments.  */
-                      &sec_attr,     /* Process security attributes.  */
-                      &sec_attr,     /* Thread security attributes.  */
-                      FALSE,          /* Inherit handles.  */
-                      cr_flags,      /* Creation flags.  */
-                      NULL,          /* Environment.  */
-                      NULL,          /* Use current drive/directory.  */
-                      &si,           /* Startup information. */
-                      &pi            /* Returns process information.  */
-                      );
-  xfree (cmdline_copy);
-  if (!rc)
-    {
-      log_error_w32 (-1, "%s:%s: CreateProcess failed", SRCNAME, __func__);
-      return -1;
-    }
-
-  CloseHandle (pi.hThread); 
-  CloseHandle (pi.hProcess);
-  return 0;
-}
-
-
-
 /* Percent-escape the string STR by replacing colons with '%3a'.  If
    EXTRA is not NULL all characters in it are also escaped. */
 char *
index 1d46515..379a55c 100644 (file)
@@ -202,8 +202,6 @@ wchar_t *get_pretty_attachment_name (wchar_t *path, protocol_t protocol,
 #define BOUNDARYSIZE 20
 char *generate_boundary (char *buffer);
 
-int gpgol_spawn_detached (const char *cmdline);
-
 /*-- recipient-dialog.c --*/
 unsigned int recipient_dialog_box (gpgme_key_t **ret_rset);
 unsigned int recipient_dialog_box2 (gpgme_key_t *fnd, char **unknown,
diff --git a/src/exechelp.c b/src/exechelp.c
new file mode 100644 (file)
index 0000000..5d2a5bf
--- /dev/null
@@ -0,0 +1,145 @@
+/* exechelp.c - fork and exec helpers
+ * Copyright (C) 2004, 2007, 2014 g10 Code GmbH
+ * Copyright (C) 2015 Intevation GmbH
+ *
+ * This file is part of GpgOL.
+ *
+ * GpgOL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * GpgOL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <windows.h>
+
+#include <gpg-error.h>
+
+#include "common.h"
+#include "exechelp.h"
+
+/* Define to 1 do enable debugging.  */
+#define DEBUG_W32_SPAWN 0
+
+
+\f
+
+/* Lock a spawning process.  The caller needs to provide the address
+   of a variable to store the lock information and the name or the
+   process.  */
+gpg_error_t
+gpgol_lock_spawning (lock_spawn_t *lock)
+{
+  int waitrc;
+  int timeout = 5;
+
+  *lock = CreateMutexW (NULL, FALSE, L"spawn_gnupg_uiserver_sentinel");
+  if (!*lock)
+    {
+      log_error ("failed to create the spawn mutex: rc=%ld", GetLastError ());
+      return gpg_error (GPG_ERR_GENERAL);
+    }
+
+ retry:
+  waitrc = WaitForSingleObject (*lock, 1000);
+  if (waitrc == WAIT_OBJECT_0)
+    return 0;
+
+  if (waitrc == WAIT_TIMEOUT && timeout)
+    {
+      timeout--;
+      goto retry;
+    }
+  if (waitrc == WAIT_TIMEOUT)
+    log_error ("error waiting for the spawn mutex: timeout");
+  else
+    log_error ("error waiting for the spawn mutex: (code=%d) rc=%ld",
+                waitrc, GetLastError ());
+  return gpg_error (GPG_ERR_GENERAL);
+}
+
+
+/* Unlock the spawning process.  */
+void
+gpgol_unlock_spawning (lock_spawn_t *lock)
+{
+  if (*lock)
+    {
+      if (!ReleaseMutex (*lock))
+        log_error ("failed to release the spawn mutex: rc=%ld", GetLastError());
+      CloseHandle (*lock);
+      *lock = NULL;
+    }
+}
+
+
+/* Fork and exec the program with /dev/null as stdin, stdout and
+   stderr.  Returns 0 on success or an error code.  */
+gpg_error_t
+gpgol_spawn_detached (const char *cmdline)
+{
+  SECURITY_ATTRIBUTES sec_attr;
+  PROCESS_INFORMATION pi =
+    {
+      NULL,      /* Returns process handle.  */
+      0,         /* Returns primary thread handle.  */
+      0,         /* Returns pid.  */
+      0          /* Returns tid.  */
+    };
+  STARTUPINFO si;
+  int cr_flags;
+
+  log_debug ("gpgol_spawn_detached cmdline=%s", cmdline);
+
+  /* Prepare security attributes.  */
+  memset (&sec_attr, 0, sizeof sec_attr);
+  sec_attr.nLength = sizeof sec_attr;
+  sec_attr.bInheritHandle = FALSE;
+
+  /* Start the process.  Note that we can't run the PREEXEC function
+     because this would change our own environment. */
+  memset (&si, 0, sizeof si);
+  si.cb = sizeof (si);
+  si.dwFlags = STARTF_USESHOWWINDOW;
+  si.wShowWindow = DEBUG_W32_SPAWN ? SW_SHOW : SW_MINIMIZE;
+
+  cr_flags = (CREATE_DEFAULT_ERROR_MODE
+              | GetPriorityClass (GetCurrentProcess ())
+              | CREATE_NEW_PROCESS_GROUP
+              | DETACHED_PROCESS);
+
+  if (!CreateProcess (NULL,          /* pgmname; Program to start.  */
+                      (char *) cmdline, /* Command line arguments.  */
+                      &sec_attr,     /* Process security attributes.  */
+                      &sec_attr,     /* Thread security attributes.  */
+                      TRUE,          /* Inherit handles.  */
+                      cr_flags,      /* Creation flags.  */
+                      NULL,          /* Environment.  */
+                      NULL,          /* Use current drive/directory.  */
+                      &si,           /* Startup information. */
+                      &pi            /* Returns process information.  */
+                      ))
+    {
+      log_error ("CreateProcess failed: %ld\n", GetLastError ());
+      return gpg_error (GPG_ERR_GENERAL);
+    }
+
+  /* Process has been created suspended; resume it now. */
+  CloseHandle (pi.hThread);
+  CloseHandle (pi.hProcess);
+
+  return 0;
+}
diff --git a/src/exechelp.h b/src/exechelp.h
new file mode 100644 (file)
index 0000000..5f4c9f4
--- /dev/null
@@ -0,0 +1,50 @@
+/* exechelp.h - fork and exec helpers
+ * Copyright (C) 2004, 2007 g10 Code GmbH
+ * Copyright (C) 2015 Intevation GmbH
+ *
+ * This file is part of GpgOL.
+ *
+ * GpgOL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * GpgOL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#ifndef GPGOL_EXECHELP_H
+#define GPGOL_EXECHELP_H
+
+#include <gpg-error.h>
+
+#ifdef __cplusplus
+extern "C" {
+#if 0
+}
+#endif
+#endif
+
+#define lock_spawn_t HANDLE
+
+gpg_error_t gpgol_lock_spawning (lock_spawn_t *lock);
+void gpgol_unlock_spawning (lock_spawn_t *lock);
+
+/* Fork and exec CMDLINE with /dev/null as stdin, stdout and stderr.
+   Returns 0 on success or an error code.  */
+gpg_error_t gpgol_spawn_detached (const char *cmdline);
+
+#ifdef __cplusplus
+#if 0
+{
+#endif
+}
+#endif
+
+#endif /* GPGOL_EXECHELP_H */