From 83811e3f1f0c615b2b63bafdb49a35a0fc198088 Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Mon, 28 Sep 2015 18:10:21 +0200 Subject: common: Change calling convention for gnupg_spawn_process. * common/exechelp.h (GNUPG_SPAWN_NONBLOCK): New. (GNUPG_SPAWN_RUN_ASFW, GNUPG_SPAWN_DETACHED): Macro to replace the numbers. * common/exechelp.h (gnupg_spawn_process): Change function to not take an optional stream for stdin but to return one. * common/exechelp-posix.c (gnupg_spawn_process): Implement change. (create_pipe_and_estream): Add args outbound and nonblock. * common/exechelp-w32.c (gnupg_spawn_process): Implement change. -- In 2.1 this function is only used at one place and the stdin parameter is not used. Thus this change is trivial for the callers but along with estream's new es_poll it is overall simpler to use. Note that the Windows version has not been tested. Signed-off-by: Werner Koch --- common/exechelp-posix.c | 62 +++++++++++++++++++++++++++++++++++++------------ 1 file changed, 47 insertions(+), 15 deletions(-) (limited to 'common/exechelp-posix.c') 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) -- cgit v1.2.3