From 09cc0ee7bebcdde9f5a40e827a9e29f9ae7fdf11 Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Wed, 20 Jun 2007 11:16:42 +0000 Subject: [w32] gpg-agent is now started automagically by gpgsm. --- common/ChangeLog | 11 +++++ common/exechelp.c | 135 +++++++++++++++++++++++++++++++++++++++++++++--------- common/sysutils.c | 55 +++++++++++++++++++--- common/sysutils.h | 4 +- 4 files changed, 174 insertions(+), 31 deletions(-) (limited to 'common') 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 + + * 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 * 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 + +#ifdef WITHOUT_GNU_PTH /* Give the Makefile a chance to build without Pth. */ +# undef HAVE_PTH +# undef USE_GNU_PTH +#endif + #include #include #include #include #include #ifdef HAVE_STAT -#include +# include #endif #if defined(__linux__) && defined(__alpha__) && __GLIBC__ < 2 - #include - #include +# include +# include #endif #ifdef HAVE_SETRLIMIT - #include - #include - #include +# include +# include +# include +#endif +#ifdef HAVE_W32_SYSTEM +# include +#endif +#ifdef HAVE_PTH +# include #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" -- cgit v1.2.3