diff options
author | NIIBE Yutaka <[email protected]> | 2024-05-29 06:14:44 +0000 |
---|---|---|
committer | NIIBE Yutaka <[email protected]> | 2024-05-29 06:16:56 +0000 |
commit | 6c05b35977c9d15da45b4fe6c0c870dbbf51657c (patch) | |
tree | eeff919dfe06900b6f8f62b3cf45153ed2d6ab88 | |
parent | Import spawn functions from GnuPG master. (diff) | |
download | libgpg-error-6c05b35977c9d15da45b4fe6c0c870dbbf51657c.tar.gz libgpg-error-6c05b35977c9d15da45b4fe6c0c870dbbf51657c.zip |
Cleaner semantics for _gpgrt_process_spawn without a callback.
* src/gpg-error.h.in (@define:struct_spawn_cb_arg@): Remove.
(gpgrt_spawn_actions_t): New.
(@define:spawn_actions_functions@): New.
* src/gpgrt-int.h (_gpgrt_spawn_actions_new)
(_gpgrt_spawn_actions_release, _gpgrt_spawn_actions_set_envvars)
(_gpgrt_spawn_actions_set_redirect): New.
[HAVE_W32_SYSTEM] (_gpgrt_spawn_actions_set_inherit_handles): New.
[!HAVE_W32_SYSTEM] (_gpgrt_spawn_actions_set_inherit_fds)
(_gpgrt_spawn_actions_set_atfork): New.
(_gpgrt_process_spawn): Use gpgrt_spawn_actions_t.
(_gpgrt_spawn_helper): Remove.
* src/mkheader.c: Emit gpgrt_spawn_actions_* definition.
* src/spawn-posix.c(_gpgrt_spawn_actions_new)
(_gpgrt_spawn_actions_release, _gpgrt_spawn_actions_set_envvars)
(_gpgrt_spawn_actions_set_redirect)
(_gpgrt_spawn_actions_set_inherit_fds)
(_gpgrt_spawn_actions_set_atfork): New.
(spawn_detached, _gpgrt_process_spawn): Use gpgrt_spawn_actions_t.
(_gpgrt_spawn_helper): Remove.
* src/spawn-w32.c: Ditto, with
_gpgrt_spawn_actions_set_inherit_handles, but no
_gpgrt_spawn_actions_set_atfork.
--
GnuPG-bug-id: 6249
Signed-off-by: NIIBE Yutaka <[email protected]>
-rw-r--r-- | src/gpg-error.h.in | 3 | ||||
-rw-r--r-- | src/gpgrt-int.h | 22 | ||||
-rw-r--r-- | src/mkheader.c | 20 | ||||
-rw-r--r-- | src/spawn-posix.c | 130 | ||||
-rw-r--r-- | src/spawn-w32.c | 144 |
5 files changed, 211 insertions, 108 deletions
diff --git a/src/gpg-error.h.in b/src/gpg-error.h.in index 1589015..d38696a 100644 --- a/src/gpg-error.h.in +++ b/src/gpg-error.h.in @@ -1107,7 +1107,8 @@ void _gpgrt_log_assert (const char *expr, const char *file, int line, #define GPGRT_PROCESS_STREAM_NONBLOCK (1 << 16) typedef struct gpgrt_process *gpgrt_process_t; -@define:struct_spawn_cb_arg@ +typedef struct gpgrt_spawn_actions *gpgrt_spawn_actions_t; +@define:spawn_actions_functions@ enum gpgrt_process_requests { diff --git a/src/gpgrt-int.h b/src/gpgrt-int.h index 2cc5f41..2871128 100644 --- a/src/gpgrt-int.h +++ b/src/gpgrt-int.h @@ -684,10 +684,24 @@ gpg_err_code_t _gpgrt_make_pipe (int filedes[2], estream_t *r_fp, * descriptor. * */ +gpg_err_code_t _gpgrt_spawn_actions_new (gpgrt_spawn_actions_t *r_act); +void _gpgrt_spawn_actions_release (gpgrt_spawn_actions_t act); +void _gpgrt_spawn_actions_set_envvars (gpgrt_spawn_actions_t, char **env); +#ifdef HAVE_W32_SYSTEM +void _gpgrt_spawn_actions_set_redirect (gpgrt_spawn_actions_t, + void *, void *, void *); +void _gpgrt_spawn_actions_set_inherit_handles (gpgrt_spawn_actions_t, void **); +#else +void _gpgrt_spawn_actions_set_redirect (gpgrt_spawn_actions_t, int, int, int); +void _gpgrt_spawn_actions_set_inherit_fds (gpgrt_spawn_actions_t, + const int *); +void _gpgrt_spawn_actions_set_atfork (gpgrt_spawn_actions_t, + void (*atfork)(void *), void *arg); +#endif + gpg_err_code_t _gpgrt_process_spawn (const char *pgmname, const char *argv1[], unsigned int flags, - void (*spawn_cb) (struct spawn_cb_arg *), - void *spawn_cb_arg, + gpgrt_spawn_actions_t act, gpgrt_process_t *r_process); gpg_err_code_t _gpgrt_process_terminate (gpgrt_process_t process); @@ -713,8 +727,6 @@ void _gpgrt_process_release (gpgrt_process_t process); gpg_err_code_t _gpgrt_process_wait_list (gpgrt_process_t *process_list, int count, int hang); -void _gpgrt_spawn_helper (struct spawn_cb_arg *sca); - /* If HANG is true, waits for the process identified by PROCESS_ID to * exit; if HANG is false, checks whether the process has terminated. * PGMNAME should be the same as supplied to the spawn function and is @@ -760,7 +772,7 @@ void _gpgrt_kill_process (gpgrt_process_t process_id); void _gpgrt_release_process (gpgrt_process_t process_id); /* Close all file resources (descriptors), except KEEP_FDS. */ -void _gpgrt_close_all_fds (int from, int *keep_fds); +void _gpgrt_close_all_fds (int from, const int *keep_fds); /* diff --git a/src/mkheader.c b/src/mkheader.c index cb4d574..5005bbc 100644 --- a/src/mkheader.c +++ b/src/mkheader.c @@ -573,27 +573,17 @@ write_special (const char *fname, int lnr, const char *tag) else fputs ("int", stdout); } - else if (!strcmp (tag, "define:struct_spawn_cb_arg")) + else if (!strcmp (tag, "define:spawn_actions_functions")) { if (have_w32_system || have_w64_system) { - fputs ("struct spawn_cb_arg;\n", stdout); - fputs ("#ifdef NEED_STRUCT_SPAWN_CB_ARG\n", stdout); - fputs ("struct spawn_cb_arg {\n", stdout); - fputs (" HANDLE hd[3];\n", stdout); - fputs (" HANDLE *inherit_hds;\n", stdout); - fputs (" BOOL allow_foreground_window;\n", stdout); - fputs (" void *arg;\n", stdout); - fputs ("};\n", stdout); - fputs ("#endif /* NEED_STRUCT_SPAWN_CB_ARG */\n", stdout); + fputs ("void gpgrt_spawn_actions_set_redirect (gpgrt_spawn_actions_t, void *, void *, void *);\n", stdout); + fputs ("void gpgrt_spawn_actions_set_inherit_handles (gpgrt_spawn_actions_t, void **);\n", stdout); } else { - fputs ("struct spawn_cb_arg {\n", stdout); - fputs (" int fds[3];\n", stdout); - fputs (" int *except_fds;\n", stdout); - fputs (" void *arg;\n", stdout); - fputs ("};\n", stdout); + fputs ("void gpgrt_spawn_actions_set_redirect (gpgrt_spawn_actions_t, int, int, int);\n", stdout); + fputs ("void gpgrt_spawn_actions_set_inherit_fds (gpgrt_spawn_actions_t, const int *);\n", stdout); } } else if (!strcmp (tag, "include:err-sources")) diff --git a/src/spawn-posix.c b/src/spawn-posix.c index 1c9f7ff..f31b9c5 100644 --- a/src/spawn-posix.c +++ b/src/spawn-posix.c @@ -154,7 +154,7 @@ get_max_fds (void) * which shall not be closed. This list shall be sorted in ascending * order with the end marked by -1. */ void -_gpgrt_close_all_fds (int first, int *except) +_gpgrt_close_all_fds (int first, const int *except) { int max_fd = get_max_fds (); int fd, i, except_start; @@ -287,32 +287,47 @@ posix_open_null (int for_write) return fd; } +struct gpgrt_spawn_actions { + int fd[3]; + const int *except_fds; + char **env; + void (*atfork) (void *); + void *atfork_arg; +}; + static void -my_exec (const char *pgmname, const char *argv[], struct spawn_cb_arg *sca) +my_exec (const char *pgmname, const char *argv[], + gpgrt_spawn_actions_t act) { int i; /* Assign /dev/null to unused FDs. */ for (i = 0; i <= 2; i++) - if (sca->fds[i] == -1) - sca->fds[i] = posix_open_null (i); + if (act->fd[i] == -1) + act->fd[i] = posix_open_null (i); /* Connect the standard files. */ for (i = 0; i <= 2; i++) - if (sca->fds[i] != i) + if (act->fd[i] != i) { - if (dup2 (sca->fds[i], i) == -1) + if (dup2 (act->fd[i], i) == -1) _gpgrt_log_fatal ("dup2 std%s failed: %s\n", i==0?"in":i==1?"out":"err", strerror (errno)); /* - * We don't close sca.fds[i] here, but close them by + * We don't close act->fd[i] here, but close them by * close_all_fds. Note that there may be same one in three of - * sca->fds[i]. + * act->fd[i]. */ } /* Close all other files. */ - _gpgrt_close_all_fds (3, sca->except_fds); + _gpgrt_close_all_fds (3, act->except_fds); + + if (act->env) + environ = act->env; + + if (act->atfork) + act->atfork (act->atfork_arg); execv (pgmname, (char *const *)argv); /* No way to print anything, as we have may have closed all streams. */ @@ -320,24 +335,9 @@ my_exec (const char *pgmname, const char *argv[], struct spawn_cb_arg *sca) } -static void -call_spawn_cb (struct spawn_cb_arg *sca, - int fd_in, int fd_out, int fd_err, - void (*spawn_cb) (struct spawn_cb_arg *), void *spawn_cb_arg) -{ - sca->fds[0] = fd_in; - sca->fds[1] = fd_out; - sca->fds[2] = fd_err; - sca->except_fds = NULL; - sca->arg = spawn_cb_arg; - if (spawn_cb) - (*spawn_cb) (sca); -} - - static gpg_err_code_t spawn_detached (const char *pgmname, const char *argv[], - void (*spawn_cb) (struct spawn_cb_arg *), void *spawn_cb_arg) + gpgrt_spawn_actions_t act) { gpg_err_code_t ec; pid_t pid; @@ -370,7 +370,6 @@ spawn_detached (const char *pgmname, const char *argv[], if (!pid) { pid_t pid2; - struct spawn_cb_arg sca; if (setsid() == -1 || chdir ("/")) _exit (1); @@ -381,9 +380,7 @@ spawn_detached (const char *pgmname, const char *argv[], if (pid2) _exit (0); /* Let the parent exit immediately. */ - call_spawn_cb (&sca, -1, -1, -1, spawn_cb, spawn_cb_arg); - - my_exec (pgmname, argv, &sca); + my_exec (pgmname, argv, act); /*NOTREACHED*/ } @@ -402,11 +399,62 @@ spawn_detached (const char *pgmname, const char *argv[], return 0; } +gpg_err_code_t +_gpgrt_spawn_actions_new (gpgrt_spawn_actions_t *r_act) +{ + gpgrt_spawn_actions_t act; + int i; + + *r_act = NULL; + + act = xtrycalloc (1, sizeof (struct gpgrt_spawn_actions)); + if (act == NULL) + return _gpg_err_code_from_syserror (); + + for (i = 0; i <= 2; i++) + act->fd[i] = -1; + + *r_act = act; + return 0; +} + +void +_gpgrt_spawn_actions_release (gpgrt_spawn_actions_t act) +{ + if (!act) + return; + + xfree (act); +} + +void +_gpgrt_spawn_actions_set_envvars (gpgrt_spawn_actions_t act, char **env) +{ + act->env = env; +} + +void +_gpgrt_spawn_actions_set_atfork (gpgrt_spawn_actions_t act, + void (*atfork)(void *), void *arg) +{ + act->atfork = atfork; + act->atfork_arg = arg; +} + void -_gpgrt_spawn_helper (struct spawn_cb_arg *sca) +_gpgrt_spawn_actions_set_redirect (gpgrt_spawn_actions_t act, + int in, int out, int err) { - int *user_except = sca->arg; - sca->except_fds = user_except; + act->fd[0] = in; + act->fd[1] = out; + act->fd[2] = err; +} + +void +_gpgrt_spawn_actions_set_inherit_fds (gpgrt_spawn_actions_t act, + const int *fds) +{ + act->except_fds = fds; } struct gpgrt_process { @@ -422,9 +470,7 @@ struct gpgrt_process { gpg_err_code_t _gpgrt_process_spawn (const char *pgmname, const char *argv1[], - unsigned int flags, - void (*spawn_cb) (struct spawn_cb_arg *), - void *spawn_cb_arg, + unsigned int flags, gpgrt_spawn_actions_t act, gpgrt_process_t *r_process) { gpg_err_code_t ec; @@ -472,7 +518,7 @@ _gpgrt_process_spawn (const char *pgmname, const char *argv1[], return GPG_ERR_INV_ARG; } - return spawn_detached (pgmname, argv, spawn_cb, spawn_cb_arg); + return spawn_detached (pgmname, argv, act); } process = xtrycalloc (1, sizeof (struct gpgrt_process)); @@ -601,8 +647,6 @@ _gpgrt_process_spawn (const char *pgmname, const char *argv1[], if (!pid) { - struct spawn_cb_arg sca; - if (fd_in[1] >= 0) close (fd_in[1]); if (fd_out[0] >= 0) @@ -610,11 +654,15 @@ _gpgrt_process_spawn (const char *pgmname, const char *argv1[], if (fd_err[0] >= 0) close (fd_err[0]); - call_spawn_cb (&sca, fd_in[0], fd_out[1], fd_err[1], - spawn_cb, spawn_cb_arg); + if (act->fd[0] < 0) + act->fd[0] = fd_in[0]; + if (act->fd[1] < 0) + act->fd[1] = fd_out[1]; + if (act->fd[2] < 0) + act->fd[2] = fd_err[1]; /* Run child. */ - my_exec (pgmname, argv, &sca); + my_exec (pgmname, argv, act); /*NOTREACHED*/ } diff --git a/src/spawn-w32.c b/src/spawn-w32.c index b2eb760..72d5552 100644 --- a/src/spawn-w32.c +++ b/src/spawn-w32.c @@ -301,6 +301,11 @@ _gpgrt_make_pipe (int filedes[2], estream_t *r_fp, int direction, int nonblock) return do_create_pipe_and_estream (filedes, NULL, 0, 0); } +struct gpgrt_spawn_actions { + void *hd[3]; + void **inherit_hds; + char **env; +}; struct gpgrt_process { const char *pgmname; @@ -338,8 +343,7 @@ check_windows_version (void) static gpg_err_code_t -spawn_detached (const char *pgmname, char *cmdline, - void (*spawn_cb) (struct spawn_cb_arg *), void *spawn_cb_arg) +spawn_detached (const char *pgmname, char *cmdline, gpgrt_spawn_actions_t act) { SECURITY_ATTRIBUTES sec_attr; PROCESS_INFORMATION pi = { NULL, 0, 0, 0 }; @@ -349,8 +353,8 @@ spawn_detached (const char *pgmname, char *cmdline, wchar_t *wpgmname = NULL; gpg_err_code_t ec; int ret; - struct spawn_cb_arg sca; BOOL ask_inherit = FALSE; + int i; ec = _gpgrt_access (pgmname, X_OK); if (ec) @@ -361,22 +365,27 @@ spawn_detached (const char *pgmname, char *cmdline, memset (&si, 0, sizeof si); - sca.allow_foreground_window = FALSE; - sca.hd[0] = INVALID_HANDLE_VALUE; - sca.hd[1] = INVALID_HANDLE_VALUE; - sca.hd[2] = INVALID_HANDLE_VALUE; - sca.inherit_hds = NULL; - sca.arg = spawn_cb_arg; - if (spawn_cb) - (*spawn_cb) (&sca); + i = 0; + if (act->hd[0] != INVALID_HANDLE_VALUE) + i++; + if (act->hd[1] != INVALID_HANDLE_VALUE) + i++; + if (act->hd[2] != INVALID_HANDLE_VALUE) + i++; - if (sca.inherit_hds) + if (i != 0 || act->inherit_hds) { SIZE_T attr_list_size = 0; HANDLE hd[16]; - HANDLE *hd_p = sca.inherit_hds; + HANDLE *hd_p = act->inherit_hds; int j = 0; + if (act->hd[0] != INVALID_HANDLE_VALUE) + hd[j++] = act->hd[0]; + if (act->hd[1] != INVALID_HANDLE_VALUE) + hd[j++] = act->hd[1]; + if (act->hd[1] != INVALID_HANDLE_VALUE) + hd[j++] = act->hd[2]; if (hd_p) { while (*hd_p != INVALID_HANDLE_VALUE) @@ -406,7 +415,6 @@ spawn_detached (const char *pgmname, char *cmdline, PROC_THREAD_ATTRIBUTE_HANDLE_LIST, hd, sizeof (HANDLE) * j, NULL, NULL); } - ask_inherit = TRUE; } } @@ -418,8 +426,12 @@ spawn_detached (const char *pgmname, char *cmdline, /* Start the process. */ si.StartupInfo.cb = sizeof (si); - si.StartupInfo.dwFlags = STARTF_USESHOWWINDOW; + si.StartupInfo.dwFlags = ((i > 0 ? STARTF_USESTDHANDLES : 0) + | STARTF_USESHOWWINDOW); si.StartupInfo.wShowWindow = DEBUG_W32_SPAWN? SW_SHOW : SW_MINIMIZE; + si.StartupInfo.hStdInput = act->hd[0]; + si.StartupInfo.hStdOutput = act->hd[1]; + si.StartupInfo.hStdError = act->hd[2]; cr_flags = (CREATE_DEFAULT_ERROR_MODE | GetPriorityClass (GetCurrentProcess ()) @@ -476,18 +488,60 @@ spawn_detached (const char *pgmname, char *cmdline, } +gpg_err_code_t +_gpgrt_spawn_actions_new (gpgrt_spawn_actions_t *r_act) +{ + gpgrt_spawn_actions_t act; + int i; + + *r_act = NULL; + + act = xtrycalloc (1, sizeof (struct gpgrt_spawn_actions)); + if (act == NULL) + return _gpg_err_code_from_syserror (); + + for (i = 0; i <= 2; i++) + act->hd[i] = INVALID_HANDLE_VALUE; + + *r_act = act; + return 0; +} + +void +_gpgrt_spawn_actions_release (gpgrt_spawn_actions_t act) +{ + if (!act) + return; + + xfree (act); +} + +void +_gpgrt_spawn_actions_set_envvars (gpgrt_spawn_actions_t act, char **env) +{ + act->env = env; +} + +void +_gpgrt_spawn_actions_set_redirect (gpgrt_spawn_actions_t act, + void *in, void *out, void *err) +{ + act->hd[0] = in; + act->hd[1] = out; + act->hd[2] = err; +} + void -_gpgrt_spawn_helper (struct spawn_cb_arg *sca) +_gpgrt_spawn_actions_set_inherit_handles (gpgrt_spawn_actions_t act, + void **handles) { - HANDLE *user_except = sca->arg; - sca->inherit_hds = user_except; + act->inherit_hds = handles; } + gpg_err_code_t _gpgrt_process_spawn (const char *pgmname, const char *argv[], - unsigned int flags, - void (*spawn_cb) (struct spawn_cb_arg *), - void *spawn_cb_arg, + unsigned int flags, gpgrt_spawn_actions_t act, gpgrt_process_t *r_process) { gpg_err_code_t ec; @@ -503,9 +557,9 @@ _gpgrt_process_spawn (const char *pgmname, const char *argv[], HANDLE hd_in[2]; HANDLE hd_out[2]; HANDLE hd_err[2]; - struct spawn_cb_arg sca; int i; BOOL ask_inherit = FALSE; + BOOL allow_foreground_window = FALSE; /* Build the command line. */ ec = build_w32_commandline (pgmname, argv, &cmdline); @@ -527,7 +581,7 @@ _gpgrt_process_spawn (const char *pgmname, const char *argv[], return GPG_ERR_INV_ARG; } - return spawn_detached (pgmname, cmdline, spawn_cb, spawn_cb_arg); + return spawn_detached (pgmname, cmdline, act); } if (r_process) @@ -627,36 +681,34 @@ _gpgrt_process_spawn (const char *pgmname, const char *argv[], memset (&si, 0, sizeof si); - sca.allow_foreground_window = FALSE; - sca.hd[0] = hd_in[0]; - sca.hd[1] = hd_out[1]; - sca.hd[2] = hd_err[1]; - sca.inherit_hds = NULL; - sca.arg = spawn_cb_arg; - if (spawn_cb) - (*spawn_cb) (&sca); + if (act->hd[0] == INVALID_HANDLE_VALUE) + act->hd[0] = hd_in[0]; + if (act->hd[1] == INVALID_HANDLE_VALUE) + act->hd[1] = hd_out[1]; + if (act->hd[2] == INVALID_HANDLE_VALUE) + act->hd[2] = hd_err[1]; i = 0; - if (sca.hd[0] != INVALID_HANDLE_VALUE) + if (act->hd[0] != INVALID_HANDLE_VALUE) i++; - if (sca.hd[1] != INVALID_HANDLE_VALUE) + if (act->hd[1] != INVALID_HANDLE_VALUE) i++; - if (sca.hd[2] != INVALID_HANDLE_VALUE) + if (act->hd[2] != INVALID_HANDLE_VALUE) i++; - if (i != 0 || sca.inherit_hds) + if (i != 0 || act->inherit_hds) { SIZE_T attr_list_size = 0; HANDLE hd[16]; - HANDLE *hd_p = sca.inherit_hds; + HANDLE *hd_p = act->inherit_hds; int j = 0; - if (sca.hd[0] != INVALID_HANDLE_VALUE) - hd[j++] = sca.hd[0]; - if (sca.hd[1] != INVALID_HANDLE_VALUE) - hd[j++] = sca.hd[1]; - if (sca.hd[1] != INVALID_HANDLE_VALUE) - hd[j++] = sca.hd[2]; + if (act->hd[0] != INVALID_HANDLE_VALUE) + hd[j++] = act->hd[0]; + if (act->hd[1] != INVALID_HANDLE_VALUE) + hd[j++] = act->hd[1]; + if (act->hd[1] != INVALID_HANDLE_VALUE) + hd[j++] = act->hd[2]; if (hd_p) { while (*hd_p != INVALID_HANDLE_VALUE) @@ -715,9 +767,9 @@ _gpgrt_process_spawn (const char *pgmname, const char *argv[], si.StartupInfo.cb = sizeof (si); si.StartupInfo.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; si.StartupInfo.wShowWindow = DEBUG_W32_SPAWN? SW_SHOW : SW_HIDE; - si.StartupInfo.hStdInput = sca.hd[0]; - si.StartupInfo.hStdOutput = sca.hd[1]; - si.StartupInfo.hStdError = sca.hd[2]; + si.StartupInfo.hStdInput = act->hd[0]; + si.StartupInfo.hStdOutput = act->hd[1]; + si.StartupInfo.hStdError = act->hd[2]; /* log_debug ("CreateProcess, path='%s' cmdline='%s'\n", pgmname, cmdline); */ cr_flags = (CREATE_DEFAULT_ERROR_MODE @@ -790,7 +842,7 @@ _gpgrt_process_spawn (const char *pgmname, const char *argv[], /* pi.hProcess, pi.hThread, */ /* (int) pi.dwProcessId, (int) pi.dwThreadId); */ - if (sca.allow_foreground_window) + if (allow_foreground_window) { /* Fixme: For unknown reasons AllowSetForegroundWindow returns * an invalid argument error if we pass it the correct |