diff --git a/common/exechelp-posix.c b/common/exechelp-posix.c index 77182cb9d..b4d10bf65 100644 --- a/common/exechelp-posix.c +++ b/common/exechelp-posix.c @@ -277,16 +277,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, void (*preexec)(void), 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 & GNUPG_SPAWN_KEEP_STDIN); + nodevnull[1] = !!(flags & GNUPG_SPAWN_KEEP_STDOUT); + nodevnull[2] = !!(flags & GNUPG_SPAWN_KEEP_STDERR); + /* Create the command line argument array. */ i = 0; if (argv) @@ -305,7 +310,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) @@ -317,6 +324,8 @@ 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) log_fatal ("dup2 std%s failed: %s\n", i==0?"in":i==1?"out":"err", strerror (errno)); @@ -535,7 +544,7 @@ gnupg_spawn_process (const char *pgmname, const char *argv[], es_fclose (outfp); es_fclose (errfp); do_exec (pgmname, argv, inpipe[0], outpipe[1], errpipe[1], - except, preexec); + except, preexec, flags); /*NOTREACHED*/ } @@ -585,7 +594,7 @@ gnupg_spawn_process_fd (const char *pgmname, const char *argv[], { gcry_control (GCRYCTL_TERM_SECMEM); /* Run child. */ - do_exec (pgmname, argv, infd, outfd, errfd, NULL, NULL); + do_exec (pgmname, argv, infd, outfd, errfd, NULL, NULL, 0); /*NOTREACHED*/ } @@ -884,7 +893,7 @@ gnupg_spawn_process_detached (const char *pgmname, const char *argv[], for (i=0; envp[i]; i++) putenv (xstrdup (envp[i])); - do_exec (pgmname, argv, -1, -1, -1, NULL, NULL); + do_exec (pgmname, argv, -1, -1, -1, NULL, NULL, 0); /*NOTREACHED*/ } diff --git a/common/exechelp-w32.c b/common/exechelp-w32.c index dee96f5b4..9529c57a0 100644 --- a/common/exechelp-w32.c +++ b/common/exechelp-w32.c @@ -556,11 +556,14 @@ gnupg_spawn_process (const char *pgmname, const char *argv[], return err; if (inpipe[0] == INVALID_HANDLE_VALUE) - nullhd[0] = w32_open_null (0); + nullhd[0] = ((flags & GNUPG_SPAWN_KEEP_STDIN)? + GetStdHandle (STD_INPUT_HANDLE) : w32_open_null (0)); if (outpipe[1] == INVALID_HANDLE_VALUE) - nullhd[1] = w32_open_null (1); + nullhd[1] = ((flags & GNUPG_SPAWN_KEEP_STDOUT)? + GetStdHandle (STD_OUTPUT_HANDLE) : w32_open_null (1)); if (errpipe[1] == INVALID_HANDLE_VALUE) - nullhd[2] = w32_open_null (1); + nullhd[2] = ((flags & GNUPG_SPAWN_KEEP_STDOUT)? + GetStdHandle (STD_ERROR_HANDLE) : w32_open_null (1)); /* Start the process. Note that we can't run the PREEXEC function because this might change our own environment. */ diff --git a/common/exechelp.h b/common/exechelp.h index d50e378e7..735ea4728 100644 --- a/common/exechelp.h +++ b/common/exechelp.h @@ -76,7 +76,9 @@ void gnupg_close_pipe (int fd); #define GNUPG_SPAWN_NONBLOCK 16 #define GNUPG_SPAWN_RUN_ASFW 64 #define GNUPG_SPAWN_DETACHED 128 - +#define GNUPG_SPAWN_KEEP_STDIN 256 +#define GNUPG_SPAWN_KEEP_STDOUT 512 +#define GNUPG_SPAWN_KEEP_STDERR 1024 /* Fork and exec the program PGMNAME. @@ -122,6 +124,12 @@ void gnupg_close_pipe (int fd); the child. Note that due to unknown problems this actually allows SetForegroundWindow for all children of this process. + GNUPG_SPAWN_KEEP_STDIN + GNUPG_SPAWN_KEEP_STDOUT + GNUPG_SPAWN_KEEP_STDERR + Do not assign /dev/null to a non-required standard file + descriptor. + */ gpg_error_t gnupg_spawn_process (const char *pgmname, const char *argv[],