summaryrefslogtreecommitdiff
path: root/src/spawn-posix.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/spawn-posix.c')
-rw-r--r--src/spawn-posix.c144
1 files changed, 101 insertions, 43 deletions
diff --git a/src/spawn-posix.c b/src/spawn-posix.c
index 54a6a68..8e36ee1 100644
--- a/src/spawn-posix.c
+++ b/src/spawn-posix.c
@@ -163,8 +163,8 @@ get_max_fds (void)
* EXCEPT is not NULL, it is expected to be a list of file descriptors
* which shall not be closed. This list shall be sorted in ascending
* order with the end marked by -1. */
-static void
-close_all_fds (int first, int *except)
+void
+_gpgrt_close_all_fds (int first, int *except)
{
int max_fd = get_max_fds ();
int fd, i, except_start;
@@ -258,16 +258,21 @@ get_all_open_fds (void)
static void
do_exec (const char *pgmname, const char *argv[],
int fd_in, int fd_out, int fd_err,
- int *except, void (*preexec)(void) )
+ int *except, unsigned int flags)
{
char **arg_list;
int i, j;
int fds[3];
+ int nodevnull[3];
fds[0] = fd_in;
fds[1] = fd_out;
fds[2] = fd_err;
+ nodevnull[0] = !!(flags & GPGRT_SPAWN_KEEP_STDIN);
+ nodevnull[1] = !!(flags & GPGRT_SPAWN_KEEP_STDOUT);
+ nodevnull[2] = !!(flags & GPGRT_SPAWN_KEEP_STDERR);
+
/* Create the command line argument array. */
i = 0;
if (argv)
@@ -292,7 +297,9 @@ do_exec (const char *pgmname, const char *argv[],
/* Assign /dev/null to unused FDs. */
for (i=0; i <= 2; i++)
{
- if (fds[i] == -1 )
+ if (nodevnull[i])
+ continue;
+ if (fds[i] == -1)
{
fds[i] = open ("/dev/null", i? O_WRONLY : O_RDONLY);
if (fds[i] == -1)
@@ -304,16 +311,17 @@ do_exec (const char *pgmname, const char *argv[],
/* Connect the standard files. */
for (i=0; i <= 2; i++)
{
+ if (nodevnull[i])
+ continue;
if (fds[i] != i && dup2 (fds[i], i) == -1)
_gpgrt_log_fatal ("dup2 std%s failed: %s\n",
i==0?"in":i==1?"out":"err", strerror (errno));
}
/* Close all other files. */
- close_all_fds (3, except);
+ if (!(flags & GPGRT_SPAWN_INHERIT_FILE))
+ _gpgrt_close_all_fds (3, except);
- if (preexec)
- preexec ();
execv (pgmname, arg_list);
/* No way to print anything, as we have may have closed all streams. */
_exit (127);
@@ -390,15 +398,44 @@ _gpgrt_make_pipe (int filedes[2], estream_t *r_fp, int direction,
return do_create_pipe (filedes);
}
+/*
+ * UNION PROCESS_ID:
+ *
+ * gpgrt_process_t object is an object which represents process handle.
+ * It must be same size as pid_t and must have same bit pattern.
+ */
+union process {
+ gpgrt_process_t process_id;
+ pid_t pid;
+};
+
+static gpgrt_process_t
+convert_from_pid (pid_t pid)
+{
+ union process u;
+
+ u.pid = pid;
+ return u.process_id;
+}
+
+static pid_t
+convert_from_process (gpgrt_process_t process_id)
+{
+ union process u;
+
+ u.process_id = process_id;
+ return u.pid;
+}
+
/* Fork and exec the PGMNAME, see gpgrt-int.h for details. */
gpg_err_code_t
_gpgrt_spawn_process (const char *pgmname, const char *argv[],
- int *except, void (*preexec)(void), unsigned int flags,
+ int *except, unsigned int flags,
estream_t *r_infp,
estream_t *r_outfp,
estream_t *r_errfp,
- pid_t *pid)
+ gpgrt_process_t *r_process_id)
{
gpg_error_t err;
int inpipe[2] = {-1, -1};
@@ -408,6 +445,7 @@ _gpgrt_spawn_process (const char *pgmname, const char *argv[],
estream_t outfp = NULL;
estream_t errfp = NULL;
int nonblock = !!(flags & GPGRT_SPAWN_NONBLOCK);
+ pid_t pid;
if (r_infp)
*r_infp = NULL;
@@ -415,7 +453,7 @@ _gpgrt_spawn_process (const char *pgmname, const char *argv[],
*r_outfp = NULL;
if (r_errfp)
*r_errfp = NULL;
- *pid = (pid_t)(-1); /* Always required. */
+ *r_process_id = convert_from_pid (-1);
if (r_infp)
{
@@ -464,9 +502,9 @@ _gpgrt_spawn_process (const char *pgmname, const char *argv[],
}
_gpgrt_pre_syscall ();
- *pid = fork ();
+ pid = fork ();
_gpgrt_post_syscall ();
- if (*pid == (pid_t)(-1))
+ if (pid == (pid_t)(-1))
{
err = _gpg_err_code_from_syserror ();
_gpgrt_log_error (_("error forking process: %s\n"), _gpg_strerror (err));
@@ -494,16 +532,14 @@ _gpgrt_spawn_process (const char *pgmname, const char *argv[],
return err;
}
- if (!*pid)
+ if (!pid)
{
/* This is the child. */
- /* FIXME: Needs to be done by preexec:
- gcry_control (GCRYCTL_TERM_SECMEM); */
_gpgrt_fclose (infp);
_gpgrt_fclose (outfp);
_gpgrt_fclose (errfp);
do_exec (pgmname, argv, inpipe[0], outpipe[1], errpipe[1],
- except, preexec);
+ except, flags);
/*NOTREACHED*/
}
@@ -522,6 +558,7 @@ _gpgrt_spawn_process (const char *pgmname, const char *argv[],
if (r_errfp)
*r_errfp = errfp;
+ *r_process_id = convert_from_pid (pid);
return 0;
}
@@ -529,30 +566,38 @@ _gpgrt_spawn_process (const char *pgmname, const char *argv[],
/* Fork and exec the PGMNAME using FDs, see gpgrt-int.h for details. */
gpg_err_code_t
_gpgrt_spawn_process_fd (const char *pgmname, const char *argv[],
- int infd, int outfd, int errfd, pid_t *pid)
+ int infd, int outfd, int errfd,
+ int (*spawn_cb) (void *),
+ void *spawn_cb_arg,
+ gpgrt_process_t *r_process_id)
{
gpg_error_t err;
+ int ask_inherit_fds = 0;
+ pid_t pid;
+ *r_process_id = convert_from_pid (-1);
_gpgrt_pre_syscall ();
- *pid = fork ();
+ pid = fork ();
_gpgrt_post_syscall ();
- if (*pid == (pid_t)(-1))
+ if (pid == (pid_t)(-1))
{
err = _gpg_err_code_from_syserror ();
_gpgrt_log_error (_("error forking process: %s\n"), _gpg_strerror (err));
return err;
}
- if (!*pid)
+ if (!pid)
{
- /* FIXME: We need to add a preexec so that a
- gcry_control (GCRYCTL_TERM_SECMEM);
- can be done. */
+ if (spawn_cb)
+ ask_inherit_fds = (*spawn_cb) (spawn_cb_arg);
+
/* Run child. */
- do_exec (pgmname, argv, infd, outfd, errfd, NULL, NULL);
+ do_exec (pgmname, argv, infd, outfd, errfd, NULL,
+ ask_inherit_fds? GPGRT_SPAWN_INHERIT_FILE : 0);
/*NOTREACHED*/
}
+ *r_process_id = convert_from_pid (pid);
return 0;
}
@@ -619,10 +664,14 @@ get_result (pid_t pid, int *r_exitcode)
/* See gpgrt-int.h for a description. */
gpg_err_code_t
-_gpgrt_wait_process (const char *pgmname, pid_t pid, int hang, int *r_exitcode)
+_gpgrt_wait_process (const char *pgmname, gpgrt_process_t process_id, int hang,
+ int *r_exitcode)
{
gpg_err_code_t ec;
int i, status;
+ pid_t pid;
+
+ pid = convert_from_process (process_id);
if (r_exitcode)
*r_exitcode = -1;
@@ -685,12 +734,13 @@ _gpgrt_wait_process (const char *pgmname, pid_t pid, int hang, int *r_exitcode)
* and threads.
*/
gpg_err_code_t
-_gpgrt_wait_processes (const char **pgmnames, pid_t *pids, size_t count,
- int hang, int *r_exitcodes)
+_gpgrt_wait_processes (const char **pgmnames, gpgrt_process_t *process_ids,
+ size_t count, int hang, int *r_exitcodes)
{
gpg_err_code_t ec = 0;
size_t i, left;
int *dummy = NULL;
+ pid_t pid;
if (!r_exitcodes)
{
@@ -703,8 +753,10 @@ _gpgrt_wait_processes (const char **pgmnames, pid_t *pids, size_t count,
{
int status = -1;
+ pid = convert_from_process (process_ids[i]);
+
/* Skip invalid PID. */
- if (pids[i] == (pid_t)(-1))
+ if (pid == (pid_t)(-1))
{
r_exitcodes[i] = -1;
left -= 1;
@@ -712,7 +764,7 @@ _gpgrt_wait_processes (const char **pgmnames, pid_t *pids, size_t count,
}
/* See if there was a previously stored result for this pid. */
- if (get_result (pids[i], &status))
+ if (get_result (pid, &status))
left -= 1;
r_exitcodes[i] = status;
@@ -720,22 +772,22 @@ _gpgrt_wait_processes (const char **pgmnames, pid_t *pids, size_t count,
while (left > 0)
{
- pid_t pid;
+ pid_t pid0;
int status;
_gpgrt_pre_syscall ();
- while ((pid = waitpid (-1, &status, hang ? 0 : WNOHANG)) == (pid_t)(-1)
+ while ((pid0 = waitpid (-1, &status, hang ? 0 : WNOHANG)) == (pid_t)(-1)
&& errno == EINTR);
_gpgrt_post_syscall ();
- if (pid == (pid_t)(-1))
+ if (pid0 == (pid_t)(-1))
{
ec = _gpg_err_code_from_syserror ();
_gpgrt_log_error (_("waiting for processes to terminate"
" failed: %s\n"), _gpg_strerror (ec));
break;
}
- else if (!pid)
+ else if (!pid0)
{
ec = GPG_ERR_TIMEOUT; /* Still running. */
break;
@@ -743,22 +795,25 @@ _gpgrt_wait_processes (const char **pgmnames, pid_t *pids, size_t count,
else
{
for (i = 0; i < count; i++)
- if (pid == pids[i])
- break;
+ {
+ pid = convert_from_process (process_ids[i]);
+ if (pid0 == pid)
+ break;
+ }
if (i == count)
{
/* No match, store this result. */
- ec = store_result (pid, status);
+ ec = store_result (pid0, status);
if (ec)
break;
continue;
}
- /* Process PIDS[i] died. */
+ /* Process PROCESS_PIDS[i] died. */
if (r_exitcodes[i] != (pid_t) -1)
{
- _gpgrt_log_error ("PID %d was reused", (int)pid);
+ _gpgrt_log_error ("PID %d was reused", (int)pid0);
ec = GPG_ERR_GENERAL;
break;
}
@@ -804,7 +859,7 @@ _gpgrt_wait_processes (const char **pgmnames, pid_t *pids, size_t count,
* callback. */
gpg_err_code_t
_gpgrt_spawn_process_detached (const char *pgmname, const char *argv[],
- const char *envp[] )
+ const char *envp[])
{
gpg_err_code_t ec;
pid_t pid;
@@ -849,7 +904,7 @@ _gpgrt_spawn_process_detached (const char *pgmname, const char *argv[],
putenv (p);
}
- do_exec (pgmname, argv, -1, -1, -1, NULL, NULL);
+ do_exec (pgmname, argv, -1, -1, -1, NULL, 0);
/*NOTREACHED*/
}
@@ -873,8 +928,11 @@ _gpgrt_spawn_process_detached (const char *pgmname, const char *argv[],
* gnupg_wait_process must be called to actually remove the process
from the system. An invalid PID is ignored. */
void
-_gpgrt_kill_process (pid_t pid)
+_gpgrt_kill_process (gpgrt_process_t process_id)
{
+ pid_t pid;
+
+ pid = convert_from_process (process_id);
if (pid != (pid_t)(-1))
{
_gpgrt_pre_syscall ();
@@ -885,7 +943,7 @@ _gpgrt_kill_process (pid_t pid)
void
-_gpgrt_release_process (pid_t pid)
+_gpgrt_release_process (gpgrt_process_t process_id)
{
- (void)pid;
+ (void)process_id;
}