diff --git a/NEWS b/NEWS index 78e64b0d2..6f39200d8 100644 --- a/NEWS +++ b/NEWS @@ -23,6 +23,12 @@ Noteworthy changes in version 2.1.x (under development) * Support for Windows CE. + * If the agent's --use-standard-socket option is active, all tools + try to start and daemonize the agent on the fly. In the past this + was only supported on W32; on non-W32 systems the new configure + option --use-standard-socket may now be used to use this feature by + default. + Noteworthy changes in version 2.0.13 (2009-09-04) ------------------------------------------------- diff --git a/agent/gpg-agent.c b/agent/gpg-agent.c index 89027b541..6d96b5223 100644 --- a/agent/gpg-agent.c +++ b/agent/gpg-agent.c @@ -99,7 +99,6 @@ enum cmd_and_opt_values oEnablePassphraseHistory, oUseStandardSocket, oNoUseStandardSocket, - oStandardSocketP, oFakedSystemTime, oIgnoreCacheForSigning, @@ -631,9 +630,8 @@ main (int argc, char **argv ) /* Set default options. */ parse_rereadable_options (NULL, 0); /* Reset them to default values. */ -#ifdef HAVE_W32_SYSTEM - use_standard_socket = 1; /* Under Windows we always use a standard - socket. */ +#ifdef USE_STANDARD_SOCKET + use_standard_socket = 1; #endif shell = getenv ("SHELL"); @@ -863,7 +861,11 @@ main (int argc, char **argv ) } if (gpgconf_list == 3) - agent_exit (!use_standard_socket); + { + if (use_standard_socket && !opt.quiet) + log_info ("configured to use the standard socket\n"); + agent_exit (!use_standard_socket); + } else if (gpgconf_list == 2) agent_exit (0); else if (gpgconf_list) diff --git a/common/ChangeLog b/common/ChangeLog index 14ca0ef71..76d5298bb 100644 --- a/common/ChangeLog +++ b/common/ChangeLog @@ -1,3 +1,15 @@ +2010-05-04 Werner Koch + + * estream.c (_es_get_std_stream): Re-use registered standard fds. + (IS_INVALID_FD, ESTREAM_SYS_YIELD): New. + (es_func_fd_read, es_func_fd_write, es_func_fd_seek) + (es_func_fd_destroy): Implement a dummy stream. + + * exechelp-w32ce.c (build_w32_commandline): Add args FD0_ISNULL + and FD1_ISNULL. Remove arg PGMNAME. Change callers. + (gnupg_spawn_process_detached): Implement. + (gnupg_spawn_process_fd): Implement one special case for now. + 2010-05-03 Werner Koch * asshelp.c (lock_agent_spawning, unlock_agent_spawning): New. @@ -18,7 +30,7 @@ 2010-04-20 Werner Koch * estream.c (es_deinit): New. - (es_init_do): Intll atexit handler to flush all streams. + (es_init_do): Install atexit handler to flush all streams. * Makefile.am (common_sources): Add gettime.h. diff --git a/common/estream.c b/common/estream.c index 47ff94ff2..3a17910f7 100644 --- a/common/estream.c +++ b/common/estream.c @@ -125,6 +125,12 @@ int _setmode (int handle, int mode); # define _set_errno(a) do { errno = (a); } while (0) #endif +#ifdef HAVE_W32_SYSTEM +# define IS_INVALID_FD(a) ((void*)(a) == (void*)(-1)) +#else +# define IS_INVALID_FD(a) ((a) == -1) +#endif + /* Generally used types. */ @@ -184,9 +190,11 @@ dummy_mutex_call_int (estream_mutex_t mutex) #ifdef HAVE_PTH # define ESTREAM_SYS_READ es_pth_read # define ESTREAM_SYS_WRITE es_pth_write +# define ESTREAM_SYS_YIELD() pth_yield (NULL) #else # define ESTREAM_SYS_READ read # define ESTREAM_SYS_WRITE write +# define ESTREAM_SYS_YIELD() do { } while (0) #endif /* Misc definitions. */ @@ -777,10 +785,18 @@ es_func_fd_read (void *cookie, void *buffer, size_t size) { estream_cookie_fd_t file_cookie = cookie; ssize_t bytes_read; - - do - bytes_read = ESTREAM_SYS_READ (file_cookie->fd, buffer, size); - while (bytes_read == -1 && errno == EINTR); + + if (IS_INVALID_FD (file_cookie->fd)) + { + ESTREAM_SYS_YIELD (); + bytes_read = 0; + } + else + { + do + bytes_read = ESTREAM_SYS_READ (file_cookie->fd, buffer, size); + while (bytes_read == -1 && errno == EINTR); + } return bytes_read; } @@ -788,14 +804,21 @@ es_func_fd_read (void *cookie, void *buffer, size_t size) /* Write function for fd objects. */ static ssize_t es_func_fd_write (void *cookie, const void *buffer, size_t size) - { estream_cookie_fd_t file_cookie = cookie; ssize_t bytes_written; - do - bytes_written = ESTREAM_SYS_WRITE (file_cookie->fd, buffer, size); - while (bytes_written == -1 && errno == EINTR); + if (IS_INVALID_FD (file_cookie->fd)) + { + ESTREAM_SYS_YIELD (); + bytes_written = size; /* Yeah: Success writing to the bit bucket. */ + } + else + { + do + bytes_written = ESTREAM_SYS_WRITE (file_cookie->fd, buffer, size); + while (bytes_written == -1 && errno == EINTR); + } return bytes_written; } @@ -808,13 +831,21 @@ es_func_fd_seek (void *cookie, off_t *offset, int whence) off_t offset_new; int err; - offset_new = lseek (file_cookie->fd, *offset, whence); - if (offset_new == -1) - err = -1; + if (IS_INVALID_FD (file_cookie->fd)) + { + _set_errno (ESPIPE); + err = -1; + } else { - *offset = offset_new; - err = 0; + offset_new = lseek (file_cookie->fd, *offset, whence); + if (offset_new == -1) + err = -1; + else + { + *offset = offset_new; + err = 0; + } } return err; @@ -829,7 +860,10 @@ es_func_fd_destroy (void *cookie) if (fd_cookie) { - err = fd_cookie->no_close? 0 : close (fd_cookie->fd); + if (IS_INVALID_FD (fd_cookie->fd)) + err = 0; + else + err = fd_cookie->no_close? 0 : close (fd_cookie->fd); mem_free (fd_cookie); } else @@ -2405,19 +2439,21 @@ _es_get_std_stream (int fd) stream = do_fdopen (custom_std_fds[1], "a", 1, 1); else if (custom_std_fds_valid[2]) stream = do_fdopen (custom_std_fds[1], "a", 1, 1); - } - if (!stream) - { - /* Standard stream not yet created - do it now. */ - if (!fd) - stream = do_fpopen (stdin, "r", 1, 1); - else if (fd == 1) - stream = do_fpopen (stdout, "a", 1, 1); - else - stream = do_fpopen (stderr, "a", 1, 1); - - if (!stream) /* Fallback: Create a bit bucket. */ + + if (!stream) { + /* Second try is to use the standard C streams. */ + if (!fd) + stream = do_fpopen (stdin, "r", 1, 1); + else if (fd == 1) + stream = do_fpopen (stdout, "a", 1, 1); + else + stream = do_fpopen (stderr, "a", 1, 1); + } + + if (!stream) + { + /* Last try: Create a bit bucket. */ stream = do_fpopen (NULL, fd? "a":"r", 0, 1); if (!stream) { @@ -2426,6 +2462,7 @@ _es_get_std_stream (int fd) abort(); } } + stream->intern->is_stdstream = 1; stream->intern->stdstream_fd = fd; if (fd == 2) diff --git a/common/exechelp-w32ce.c b/common/exechelp-w32ce.c index ac7602d04..809641c3e 100644 --- a/common/exechelp-w32ce.c +++ b/common/exechelp-w32ce.c @@ -334,8 +334,10 @@ copy_quoted (char *p, const char *string) /* Build a command line for use with W32's CreateProcess. On success CMDLINE gets the address of a newly allocated string. */ static int -build_w32_commandline (const char *pgmname, const char * const *argv, - int fd0, int fd1, int fd2, int fd2_isnull, +build_w32_commandline (const char * const *argv, + int fd0, int fd0_isnull, + int fd1, int fd1_isnull, + int fd2, int fd2_isnull, char **cmdline) { int i, n; @@ -347,12 +349,18 @@ build_w32_commandline (const char *pgmname, const char * const *argv, *p = 0; if (fd0) { - snprintf (p, 25, "-&S0=%d ", fd0); + if (fd0_isnull) + strcpy (p, "-&S0=null "); + else + snprintf (p, 25, "-&S0=%d ", fd0); p += strlen (p); } if (fd1) { - snprintf (p, 25, "-&S1=%d ", fd1); + if (fd1_isnull) + strcpy (p, "-&S1=null "); + else + snprintf (p, 25, "-&S1=%d ", fd1); p += strlen (p); } if (fd2) @@ -366,7 +374,6 @@ build_w32_commandline (const char *pgmname, const char * const *argv, *cmdline = NULL; n = strlen (fdbuf); - n += strlen (pgmname) + 1 + 2; /* (1 space, 2 quoting) */ for (i=0; (s = argv[i]); i++) { n += strlen (s) + 1 + 2; /* (1 space, 2 quoting) */ @@ -381,7 +388,6 @@ build_w32_commandline (const char *pgmname, const char * const *argv, return -1; p = stpcpy (p, fdbuf); - p = copy_quoted (p, pgmname); for (i = 0; argv[i]; i++) { *p++ = ' '; @@ -540,8 +546,11 @@ gnupg_spawn_process (const char *pgmname, const char *argv[], } /* Build the command line. */ - err = build_w32_commandline (pgmname, argv, inpipe[0], outpipe[1], errpipe[1], - 0, &cmdline); + err = build_w32_commandline (argv, + inpipe[0], 0, + outpipe[1], 0, + errpipe[1], 0, + &cmdline); if (err) { CloseHandle (fd_to_handle (errpipe[0])); @@ -601,68 +610,42 @@ gpg_error_t gnupg_spawn_process_fd (const char *pgmname, const char *argv[], int infd, int outfd, int errfd, pid_t *pid) { - return gpg_error (GPG_ERR_NOT_IMPLEMENTED); -#if 0 gpg_error_t err; - PROCESS_INFORMATION pi = { NULL, 0, 0, 0 }; - STARTUPINFO si; + PROCESS_INFORMATION pi = {NULL}; char *cmdline; - int i; - HANDLE stdhd[3]; /* Setup return values. */ *pid = (pid_t)(-1); + if (infd != -1 || outfd != -1 || errfd != -1) + return gpg_error (GPG_ERR_NOT_SUPPORTED); + /* Build the command line. */ - err = build_w32_commandline (pgmname, argv, &cmdline); + err = build_w32_commandline (argv, -1, 1, -1, 1, -1, 1, &cmdline); if (err) return err; - /* si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; */ - /* stdhd[0] = infd == -1? w32_open_null (0) : INVALID_HANDLE_VALUE; */ - /* stdhd[1] = outfd == -1? w32_open_null (1) : INVALID_HANDLE_VALUE; */ - /* stdhd[2] = errfd == -1? w32_open_null (1) : INVALID_HANDLE_VALUE; */ - /* si.hStdInput = infd == -1? stdhd[0] : (void*)_get_osfhandle (infd); */ - /* si.hStdOutput = outfd == -1? stdhd[1] : (void*)_get_osfhandle (outfd); */ - /* si.hStdError = errfd == -1? stdhd[2] : (void*)_get_osfhandle (errfd); */ - -/* log_debug ("CreateProcess, path=`%s' cmdline=`%s'\n", pgmname, cmdline); */ - if (!CreateProcess (pgmname, /* Program to start. */ - cmdline, /* Command line arguments. */ - NULL, /* Process security attributes. */ - NULL, /* Thread security attributes. */ - FALSE, /* Inherit handles. */ - CREATE_SUSPENDED, - NULL, /* Environment. */ - NULL, /* Use current drive/directory. */ - NULL, /* Startup information. */ - &pi /* Returns process information. */ - )) + log_debug ("CreateProcess, path=`%s' cmdline=`%s'\n", pgmname, cmdline); + if (!create_process (pgmname, cmdline, &pi)) { - log_error ("CreateProcess failed: %s\n", w32_strerror (-1)); - err = gpg_error (GPG_ERR_GENERAL); + log_error ("CreateProcess(fd) failed: %s\n", w32_strerror (-1)); + xfree (cmdline); + return gpg_error (GPG_ERR_GENERAL); } - else - err = 0; xfree (cmdline); - for (i=0; i < 3; i++) - if (stdhd[i] != INVALID_HANDLE_VALUE) - CloseHandle (stdhd[i]); - if (err) - return err; - -/* log_debug ("CreateProcess ready: hProcess=%p hThread=%p" */ -/* " dwProcessID=%d dwThreadId=%d\n", */ -/* pi.hProcess, pi.hThread, */ -/* (int) pi.dwProcessId, (int) pi.dwThreadId); */ + cmdline = NULL; + log_debug ("CreateProcess(fd) ready: hProcess=%p hThread=%p" + " dwProcessID=%d dwThreadId=%d\n", + pi.hProcess, pi.hThread, + (int) pi.dwProcessId, (int) pi.dwThreadId); + /* Process has been created suspended; resume it now. */ ResumeThread (pi.hThread); CloseHandle (pi.hThread); *pid = handle_to_pid (pi.hProcess); return 0; -#endif } /* Wait for the process identified by PID to terminate. PGMNAME should @@ -743,42 +726,20 @@ gpg_error_t gnupg_spawn_process_detached (const char *pgmname, const char *argv[], const char *envp[] ) { - return gpg_error (GPG_ERR_NOT_IMPLEMENTED); -#if 0 gpg_error_t err; - PROCESS_INFORMATION pi = - { - NULL, /* Returns process handle. */ - 0, /* Returns primary thread handle. */ - 0, /* Returns pid. */ - 0 /* Returns tid. */ - }; - STARTUPINFO si; char *cmdline; + PROCESS_INFORMATION pi = {NULL }; (void)envp; - - if (access (pgmname, X_OK)) - return gpg_error_from_syserror (); - + /* Build the command line. */ - err = build_w32_commandline (pgmname, argv, &cmdline); + err = build_w32_commandline (argv, -1, 1, -1, 1, -1, 1, &cmdline); if (err) return err; -/* log_debug ("CreateProcess(detached), path=`%s' cmdline=`%s'\n", */ -/* pgmname, cmdline); */ - if (!CreateProcess (pgmname, /* Program to start. */ - cmdline, /* Command line arguments. */ - NULL, /* Process security attributes. */ - NULL, /* Thread security attributes. */ - FALSE, /* Inherit handles. */ - 0, /* Creation flags. */ - NULL, /* Environment. */ - NULL, /* Use current drive/directory. */ - NULL, /* Startup information. */ - &pi /* Returns process information. */ - )) + /* Note: There is no detached flag under CE. */ + log_debug ("CreateProcess, path=`%s' cmdline=`%s'\n", pgmname, cmdline); + if (!create_process (pgmname, cmdline, &pi)) { log_error ("CreateProcess(detached) failed: %s\n", w32_strerror (-1)); xfree (cmdline); @@ -787,17 +748,19 @@ gnupg_spawn_process_detached (const char *pgmname, const char *argv[], 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); */ - + log_debug ("CreateProcess(detached) ready: hProcess=%p hThread=%p" + " dwProcessID=%d dwThreadId=%d\n", + pi.hProcess, pi.hThread, + (int) pi.dwProcessId, (int) pi.dwThreadId); + + /* Process has been created suspended; resume it now. */ + ResumeThread (pi.hThread); CloseHandle (pi.hThread); return 0; -#endif } + /* Kill a process; that is send an appropriate signal to the process. gnupg_wait_process must be called to actually remove the process from the system. An invalid PID is ignored. */ diff --git a/configure.ac b/configure.ac index 280e40880..22d6383ac 100644 --- a/configure.ac +++ b/configure.ac @@ -1584,12 +1584,13 @@ echo " Smartcard: $build_scdaemon $build_scdaemon_extra G13: $build_g13 - Protect tool: $show_gnupg_protect_tool_pgm Default agent: $show_gnupg_agent_pgm Default pinentry: $show_gnupg_pinentry_pgm Default scdaemon: $show_gnupg_scdaemon_pgm Default dirmngr: $show_gnupg_dirmngr_pgm + + Use standard socket: $use_standard_socket " if test x"$use_regex" != xyes ; then echo "