aboutsummaryrefslogtreecommitdiffstats
path: root/common/exechelp-posix.c
diff options
context:
space:
mode:
Diffstat (limited to 'common/exechelp-posix.c')
-rw-r--r--common/exechelp-posix.c62
1 files changed, 47 insertions, 15 deletions
diff --git a/common/exechelp-posix.c b/common/exechelp-posix.c
index 8a2b3b9c2..2bf2592e0 100644
--- a/common/exechelp-posix.c
+++ b/common/exechelp-posix.c
@@ -313,6 +313,7 @@ gnupg_create_outbound_pipe (int filedes[2])
static gpg_error_t
create_pipe_and_estream (int filedes[2], estream_t *r_fp,
+ int outbound, int nonblock,
gpg_err_source_t errsource)
{
gpg_error_t err;
@@ -326,7 +327,10 @@ create_pipe_and_estream (int filedes[2], estream_t *r_fp,
return err;
}
- *r_fp = es_fdopen (filedes[0], "r");
+ if (outbound)
+ *r_fp = es_fdopen (filedes[0], nonblock? "r,nonblock" : "r");
+ else
+ *r_fp = es_fdopen (filedes[1], nonblock? "w,nonblock" : "w");
if (!*r_fp)
{
err = gpg_err_make (errsource, gpg_err_code_from_syserror ());
@@ -347,53 +351,70 @@ gpg_error_t
gnupg_spawn_process (const char *pgmname, const char *argv[],
gpg_err_source_t errsource,
void (*preexec)(void), unsigned int flags,
- estream_t infp,
+ estream_t *r_infp,
estream_t *r_outfp,
estream_t *r_errfp,
pid_t *pid)
{
gpg_error_t err;
- int infd = -1;
+ int inpipe[2] = {-1, -1};
int outpipe[2] = {-1, -1};
int errpipe[2] = {-1, -1};
+ estream_t infp = NULL;
estream_t outfp = NULL;
estream_t errfp = NULL;
+ int nonblock = !!(flags & GNUPG_SPAWN_NONBLOCK);
- (void)flags; /* Currently not used. */
-
+ if (r_infp)
+ *r_infp = NULL;
if (r_outfp)
*r_outfp = NULL;
if (r_errfp)
*r_errfp = NULL;
*pid = (pid_t)(-1); /* Always required. */
- if (infp)
+ if (r_infp)
{
- es_fflush (infp);
- es_rewind (infp);
- infd = es_fileno (infp);
- if (infd == -1)
- return gpg_err_make (errsource, GPG_ERR_INV_VALUE);
+ err = create_pipe_and_estream (inpipe, &infp, 0, nonblock, errsource);
+ if (err)
+ return err;
}
if (r_outfp)
{
- err = create_pipe_and_estream (outpipe, &outfp, errsource);
+ err = create_pipe_and_estream (outpipe, &outfp, 1, nonblock, errsource);
if (err)
- return err;
+ {
+ if (infp)
+ es_fclose (infp);
+ else if (inpipe[1] != -1)
+ close (inpipe[1]);
+ if (inpipe[0] != -1)
+ close (inpipe[0]);
+
+ return err;
+ }
}
if (r_errfp)
{
- err = create_pipe_and_estream (errpipe, &errfp, errsource);
+ err = create_pipe_and_estream (errpipe, &errfp, 1, nonblock, errsource);
if (err)
{
+ if (infp)
+ es_fclose (infp);
+ else if (inpipe[1] != -1)
+ close (inpipe[1]);
+ if (inpipe[0] != -1)
+ close (inpipe[0]);
+
if (outfp)
es_fclose (outfp);
else if (outpipe[0] != -1)
close (outpipe[0]);
if (outpipe[1] != -1)
close (outpipe[1]);
+
return err;
}
}
@@ -405,6 +426,13 @@ gnupg_spawn_process (const char *pgmname, const char *argv[],
err = gpg_err_make (errsource, gpg_err_code_from_syserror ());
log_error (_("error forking process: %s\n"), gpg_strerror (err));
+ if (infp)
+ es_fclose (infp);
+ else if (inpipe[1] != -1)
+ close (inpipe[1]);
+ if (inpipe[0] != -1)
+ close (inpipe[0]);
+
if (outfp)
es_fclose (outfp);
else if (outpipe[0] != -1)
@@ -427,16 +455,20 @@ gnupg_spawn_process (const char *pgmname, const char *argv[],
gcry_control (GCRYCTL_TERM_SECMEM);
es_fclose (outfp);
es_fclose (errfp);
- do_exec (pgmname, argv, infd, outpipe[1], errpipe[1], preexec);
+ do_exec (pgmname, argv, inpipe[0], outpipe[1], errpipe[1], preexec);
/*NOTREACHED*/
}
/* This is the parent. */
+ if (inpipe[0] != -1)
+ close (inpipe[0]);
if (outpipe[1] != -1)
close (outpipe[1]);
if (errpipe[1] != -1)
close (errpipe[1]);
+ if (r_infp)
+ *r_infp = infp;
if (r_outfp)
*r_outfp = outfp;
if (r_errfp)