diff options
author | NIIBE Yutaka <[email protected]> | 2025-07-17 02:01:25 +0000 |
---|---|---|
committer | NIIBE Yutaka <[email protected]> | 2025-07-17 02:01:25 +0000 |
commit | 15b8bc7495dbaba2e4855cd3a0b1dcbd4ea03ae2 (patch) | |
tree | bf5dbdd7991a381e147123f277bb242f92667141 | |
parent | build: Require libgpg-error 1.56 or newer. (diff) | |
download | gnupg-gniibe/synch-spawn.tar.gz gnupg-gniibe/synch-spawn.zip |
w32: Synchronous spawning gpg-agent/dirmngr/keyboxd.gniibe/synch-spawn
* common/asshelp.h [HAVE_W32_SYSTEM] (w32_ack_to_frontend): New.
* common/asshelp.c [HAVE_W32_SYSTEM] (start_new_service): Use
GPGRT_PROCESS_STDOUT_PIPE flag, and read from the pipe to wait.
(w32_ack_to_frontend): New.
* agent/gpg-agent.c [HAVE_W32_SYSTEM] (main): Add
w32_ack_to_frontend.
* dirmngr/dirmngr.c [HAVE_W32_SYSTEM] (main): Likewise.
* kbx/keyboxd.c [HAVE_W32_SYSTEM] (main): Likewise.
--
GnuPG-bug-id: 7720
Signed-off-by: NIIBE Yutaka <[email protected]>
-rw-r--r-- | agent/gpg-agent.c | 3 | ||||
-rw-r--r-- | common/asshelp.c | 75 | ||||
-rw-r--r-- | common/asshelp.h | 5 | ||||
-rw-r--r-- | dirmngr/dirmngr.c | 1 | ||||
-rw-r--r-- | kbx/keyboxd.c | 1 |
5 files changed, 84 insertions, 1 deletions
diff --git a/agent/gpg-agent.c b/agent/gpg-agent.c index ae1295977..9d214e703 100644 --- a/agent/gpg-agent.c +++ b/agent/gpg-agent.c @@ -1855,6 +1855,9 @@ main (int argc, char **argv) } log_info ("%s %s started\n", gpgrt_strusage(11), gpgrt_strusage(13) ); +#ifdef HAVE_W32_SYSTEM + w32_ack_to_frontend (); +#endif handle_connections (fd, fd_extra, fd_browser, fd_ssh, reliable_homedir_inotify); assuan_sock_close (fd); diff --git a/common/asshelp.c b/common/asshelp.c index 0152d1243..a45f05714 100644 --- a/common/asshelp.c +++ b/common/asshelp.c @@ -536,8 +536,46 @@ start_new_service (assuan_context_t *r_ctx, && assuan_socket_connect (ctx, sockname, 0, connect_flags)) { #ifdef HAVE_W32_SYSTEM + gpgrt_process_t proc; + err = gpgrt_process_spawn (program? program : program_name, argv, - GPGRT_PROCESS_DETACHED, NULL, NULL); + (GPGRT_PROCESS_DETACHED + |GPGRT_PROCESS_STDOUT_PIPE + |GPGRT_PROCESS_STDERR_KEEP), + NULL, &proc); + if (!err) + { + int pipe_in; + err = gpgrt_process_get_fds (proc, 0, NULL, &pipe_in, NULL); + if (!err) + { + char buf[256]; + int r; + + /* We wait until the child process says it's ready + to serve, by reading from the pipe. */ + r = read (pipe_in, buf, sizeof buf); + close (pipe_in); + /* Older versions of Windows (< Vista), it cannot + * support spawing with pipe I/O for + * GPGRT_PROCESS_DETACHED flag (since inheriting + * specific HANDLEs are not supported). In this + * case, read from child process fails. + */ + if (r < 0) + { + if (verbose) + log_info ("read from child process failed: %s\n", + strerror (errno)); +/* NOTE: Remove following line when we can assume newer Windows. */ +#define SUPPORT_OLDER_WINDOWS 1 +#if !defined(SUPPORT_OLDER_WINDOWS) + err = gpg_error (GPG_ERR_SERVER_FAILED); +#endif + } + } + gpgrt_process_release (proc); + } #else /*!W32*/ err = gpgrt_process_spawn (program? program : program_name, argv, 0, NULL, NULL); @@ -757,3 +795,38 @@ warn_server_version_mismatch (assuan_context_t ctx, xfree (serverversion); return err; } + + +#ifdef HAVE_W32_SYSTEM +#include <fcntl.h> + +/* + * At the start of service (gpg-agent/dirmngr/keyboxd), after the + * preparation of socket, send "OK" (or "ERR 1") to the frontend + * (gpg/gpgsm). + */ +void +w32_ack_to_frontend (void) +{ + int null_fd = open ("NUL", O_RDWR); + + /* For the case of older Windows (< Vista), stdin/stdout/stder is + * invalid handle and write to stdout may fail. We ignore this + * error. */ + if (null_fd < 0) + { + perror ("open failed"); + /* Reply "General Error". */ + write (1, "ERR 1\n", 6); + } + else + { + /* Reply, it's OK. */ + write (1, "OK\n", 3); + if (dup2 (null_fd, 1) < 0) + perror ("dup2 failed"); + dup2 (null_fd, 2); + close (null_fd); + } +} +#endif diff --git a/common/asshelp.h b/common/asshelp.h index cde6e226f..936a3964e 100644 --- a/common/asshelp.h +++ b/common/asshelp.h @@ -106,6 +106,11 @@ gpg_error_t warn_server_version_mismatch (assuan_context_t ctx, void *status_func_ctrl, int print_hints); +#ifdef HAVE_W32_SYSTEM +/* Say hello to the frontend. */ +void w32_ack_to_frontend (void); +#endif + /*-- asshelp2.c --*/ diff --git a/dirmngr/dirmngr.c b/dirmngr/dirmngr.c index d418d09e2..dc7e233f2 100644 --- a/dirmngr/dirmngr.c +++ b/dirmngr/dirmngr.c @@ -1526,6 +1526,7 @@ main (int argc, char **argv) pid = getpid (); es_printf ("set %s=%s;%lu;1\n", DIRMNGR_INFO_NAME, socket_name, (ulong) pid); + w32_ack_to_frontend (); #else pid = fork(); if (pid == (pid_t)-1) diff --git a/kbx/keyboxd.c b/kbx/keyboxd.c index 197f01c74..4eff1cc45 100644 --- a/kbx/keyboxd.c +++ b/kbx/keyboxd.c @@ -734,6 +734,7 @@ main (int argc, char **argv ) (void)nodetach; initialize_modules (); + w32_ack_to_frontend (); #else /*!HAVE_W32_SYSTEM*/ |