aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNIIBE Yutaka <[email protected]>2025-07-17 02:01:25 +0000
committerNIIBE Yutaka <[email protected]>2025-07-17 02:01:25 +0000
commit15b8bc7495dbaba2e4855cd3a0b1dcbd4ea03ae2 (patch)
treebf5dbdd7991a381e147123f277bb242f92667141
parentbuild: Require libgpg-error 1.56 or newer. (diff)
downloadgnupg-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.c3
-rw-r--r--common/asshelp.c75
-rw-r--r--common/asshelp.h5
-rw-r--r--dirmngr/dirmngr.c1
-rw-r--r--kbx/keyboxd.c1
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*/