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 /src/spawn-posix.c | |
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]>
Diffstat (limited to 'src/spawn-posix.c')
-rw-r--r-- | src/spawn-posix.c | 130 |
1 files changed, 89 insertions, 41 deletions
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*/ } |