summaryrefslogtreecommitdiffstats
path: root/common
diff options
context:
space:
mode:
authorWerner Koch <wk@gnupg.org>2007-06-20 13:16:42 +0200
committerWerner Koch <wk@gnupg.org>2007-06-20 13:16:42 +0200
commit09cc0ee7bebcdde9f5a40e827a9e29f9ae7fdf11 (patch)
tree7b5d692846eeed89f8c419814b791188488290fe /common
parentMade percent_escape more general. (diff)
downloadgnupg2-09cc0ee7bebcdde9f5a40e827a9e29f9ae7fdf11.tar.xz
gnupg2-09cc0ee7bebcdde9f5a40e827a9e29f9ae7fdf11.zip
[w32] gpg-agent is now started automagically by gpgsm.
Diffstat (limited to 'common')
-rw-r--r--common/ChangeLog11
-rw-r--r--common/exechelp.c135
-rw-r--r--common/sysutils.c55
-rw-r--r--common/sysutils.h4
4 files changed, 174 insertions, 31 deletions
diff --git a/common/ChangeLog b/common/ChangeLog
index f0381229e..3f8fa41c4 100644
--- a/common/ChangeLog
+++ b/common/ChangeLog
@@ -1,3 +1,14 @@
+2007-06-20 Werner Koch <wk@g10code.com>
+
+ * sysutils.c (gnupg_sleep): New.
+ * sysutils.h [W32]: Remove _sleep wrapper. Changed all callers to
+ use gnupg_sleep.
+
+ * exechelp.c (build_w32_commandline_copy): New.
+ (build_w32_commandline): Factored some code out to new function
+ and correctly process a PGMNAME with spaces.
+ (gnupg_spawn_process_detached) [W32]: Implement.
+
2007-06-14 Werner Koch <wk@g10code.com>
* simple-pwquery.h (MAP_SPWQ_ERROR_IMPL): New.
diff --git a/common/exechelp.c b/common/exechelp.c
index b4700c5cd..d0be84047 100644
--- a/common/exechelp.c
+++ b/common/exechelp.c
@@ -80,17 +80,51 @@
#ifdef HAVE_W32_SYSTEM
+/* Helper function to build_w32_commandline. */
+static char *
+build_w32_commandline_copy (char *buffer, const char *string)
+{
+ char *p = buffer;
+ const char *s;
+
+ if (!*string) /* Empty string. */
+ p = stpcpy (p, "\"\"");
+ else if (strpbrk (string, " \t\n\v\f\""))
+ {
+ /* Need top do some kind of quoting. */
+ p = stpcpy (p, "\"");
+ for (s=string; *s; s++)
+ {
+ *p++ = *s;
+ if (*s == '\"')
+ *p++ = *s;
+ }
+ *p++ = '\"';
+ *p = 0;
+ }
+ else
+ p = stpcpy (p, string);
+
+ return p;
+}
+
/* Build a command line for use with W32's CreateProcess. On success
CMDLINE gets the address of a newly allocated string. */
static gpg_error_t
-build_w32_commandline (const char *pgmname, const char **argv, char **cmdline)
+build_w32_commandline (const char *pgmname, const char * const *argv,
+ char **cmdline)
{
int i, n;
const char *s;
char *buf, *p;
*cmdline = NULL;
- n = strlen (pgmname);
+ n = 0;
+ s = pgmname;
+ n += strlen (s) + 1 + 2; /* (1 space, 2 quoting */
+ for (; *s; s++)
+ if (*s == '\"')
+ n++; /* Need to double inner quotes. */
for (i=0; (s=argv[i]); i++)
{
n += strlen (s) + 1 + 2; /* (1 space, 2 quoting */
@@ -104,26 +138,11 @@ build_w32_commandline (const char *pgmname, const char **argv, char **cmdline)
if (!buf)
return gpg_error_from_syserror ();
- /* fixme: PGMNAME may not contain spaces etc. */
- p = stpcpy (p, pgmname);
+ p = build_w32_commandline_copy (p, pgmname);
for (i=0; argv[i]; i++)
{
- if (!*argv[i]) /* Empty string. */
- p = stpcpy (p, " \"\"");
- else if (strpbrk (argv[i], " \t\n\v\f\""))
- {
- p = stpcpy (p, " \"");
- for (s=argv[i]; *s; s++)
- {
- *p++ = *s;
- if (*s == '\"')
- *p++ = *s;
- }
- *p++ = '\"';
- *p = 0;
- }
- else
- p = stpcpy (stpcpy (p, " "), argv[i]);
+ *p++ = ' ';
+ p = build_w32_commandline_copy (p, argv[i]);
}
*cmdline= buf;
@@ -330,7 +349,7 @@ gnupg_spawn_process (const char *pgmname, const char *argv[],
pi.hProcess, pi.hThread,
(int) pi.dwProcessId, (int) pi.dwThreadId);
- /* Process ha been created suspended; resume it now. */
+ /* Process has been created suspended; resume it now. */
ResumeThread (pi.hThread);
CloseHandle (pi.hThread);
@@ -525,7 +544,79 @@ gnupg_spawn_process_detached (const char *pgmname, const char *argv[],
const char *envp[] )
{
#ifdef HAVE_W32_SYSTEM
- return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
+ gpg_error_t err;
+ 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;
+ char *cmdline;
+
+
+ /* FIXME: We don't make use of ENVP yet. It is currently only used
+ to pass the GPG_AGENT_INFO variable to gpg-agent. As the default
+ on windows is to use a standard socket, this does not really
+ matter. */
+
+
+ if (access (pgmname, X_OK))
+ return gpg_error_from_syserror ();
+
+ /* Prepare security attributes. */
+ memset (&sec_attr, 0, sizeof sec_attr );
+ sec_attr.nLength = sizeof sec_attr;
+ sec_attr.bInheritHandle = FALSE;
+
+ /* Build the command line. */
+ err = build_w32_commandline (pgmname, argv, &cmdline);
+ if (err)
+ return err;
+
+ /* Start the process. */
+ 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);
+ log_debug ("CreateProcess(detached), path=`%s' cmdline=`%s'\n",
+ pgmname, cmdline);
+ if (!CreateProcess (pgmname, /* Program to start. */
+ cmdline, /* 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. */
+ ))
+ {
+ log_error ("CreateProcess(detached) failed: %s\n", w32_strerror (-1));
+ xfree (cmdline);
+ return gpg_error (GPG_ERR_GENERAL);
+ }
+ xfree (cmdline);
+ cmdline = NULL;
+
+ log_debug ("CreateProcess(detached) ready: hProcess=%p hThread=%p"
+ " dwProcessID=%d dwThreadId=%d\n",
+ pi.hProcess, pi.hThread,
+ (int) pi.dwProcessId, (int) pi.dwThreadId);
+
+ CloseHandle (pi.hThread);
+
+ return 0;
+
#else
pid_t pid;
int i;
diff --git a/common/sysutils.c b/common/sysutils.c
index d044f222b..ff1fe1ba4 100644
--- a/common/sysutils.c
+++ b/common/sysutils.c
@@ -20,23 +20,36 @@
*/
#include <config.h>
+
+#ifdef WITHOUT_GNU_PTH /* Give the Makefile a chance to build without Pth. */
+# undef HAVE_PTH
+# undef USE_GNU_PTH
+#endif
+
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#ifdef HAVE_STAT
-#include <sys/stat.h>
+# include <sys/stat.h>
#endif
#if defined(__linux__) && defined(__alpha__) && __GLIBC__ < 2
- #include <asm/sysinfo.h>
- #include <asm/unistd.h>
+# include <asm/sysinfo.h>
+# include <asm/unistd.h>
#endif
#ifdef HAVE_SETRLIMIT
- #include <time.h>
- #include <sys/time.h>
- #include <sys/resource.h>
+# include <time.h>
+# include <sys/time.h>
+# include <sys/resource.h>
+#endif
+#ifdef HAVE_W32_SYSTEM
+# include <windows.h>
+#endif
+#ifdef HAVE_PTH
+# include <pth.h>
#endif
+
#include "util.h"
#include "i18n.h"
@@ -229,3 +242,33 @@ check_permissions(const char *path,int extension,int checkonly)
return 0;
}
#endif
+
+
+/* Wrapper around the usual sleep fucntion. This one won't wake up
+ before the sleep time has really elapsed. When build with Pth it
+ merely calls pth_sleep and thus suspends only the current
+ thread. */
+void
+gnupg_sleep (unsigned int seconds)
+{
+#ifdef HAVE_PTH
+ /* With Pth we force a regular sleep for seconds == 0 so that also
+ the process will give up its timeslot. */
+ if (!seconds)
+ {
+# ifdef HAVE_W32_SYSTEM
+ Sleep (0);
+# else
+ sleep (0);
+# endif
+ }
+ pth_sleep (seconds);
+#else
+ /* Fixme: make sure that a sleep won't wake up to early. */
+# ifdef HAVE_W32_SYSTEM
+ Sleep (seconds*1000);
+# else
+ sleep (seconds);
+# endif
+#endif
+}
diff --git a/common/sysutils.h b/common/sysutils.h
index 712991599..0e295f5d1 100644
--- a/common/sysutils.h
+++ b/common/sysutils.h
@@ -27,11 +27,9 @@ int disable_core_dumps (void);
int enable_core_dumps (void);
const unsigned char *get_session_marker (size_t *rlen);
int check_permissions (const char *path,int extension,int checkonly);
+void gnupg_sleep (unsigned int seconds);
#ifdef HAVE_W32_SYSTEM
-/* Windows declares sleep as obsolete, but provides a definition for
- _sleep but non for the still existing sleep. */
-#define sleep(a) _sleep ((a))
#include "../jnlib/w32help.h"