diff options
author | Werner Koch <[email protected]> | 2017-11-29 18:29:18 +0000 |
---|---|---|
committer | Werner Koch <[email protected]> | 2017-11-29 18:29:18 +0000 |
commit | 1865c0ba1769b407a3c504f1ab0a4278704a9fc1 (patch) | |
tree | eb98697911bda0270e4aee8de308017642db8979 | |
parent | Import and relicense exechelp* functions from GnuPG. (diff) | |
download | libgpg-error-1865c0ba1769b407a3c504f1ab0a4278704a9fc1.tar.gz libgpg-error-1865c0ba1769b407a3c504f1ab0a4278704a9fc1.zip |
core: Implement the spawn functions.
* src/gpg-error.h.in (GPGRT_SPAWN_NONBLOCK): New const.
(GPGRT_SPAWN_RUN_ASFW): New const.
(GPGRT_SPAWN_DETACHED): New const.
(gpgrt_make_pipe): New function.
(gpgrt_create_pipe): New macro.
(gpgrt_create_inbound_pipe): New macro.
(gpgrt_create_outbound_pipe): New macro.
(gpgrt_spawn_process): New function.
(gpgrt_spawn_process_fd): New function.
(gpgrt_spawn_process_detached): New function.
(gpgrt_wait_process): New function.
(gpgrt_wait_processes): New function.
(gpgrt_kill_process): New function.
(gpgrt_release_process): New function.
* src/gpg-error.def.in, src/gpg-error.vers: Add new functions.
* src/visibility.c, src/visibility.h: Add wrappers for new functions.
* src/spawn-posix.c: Rework to better fit the use in gpgrt. Rename
all public function with a _gpgrt prefix.
* src/spawn-w32.c: Ditto.
* src/gpgrt-int.h: Likewise.
* src/Makefile.am (arch_sources): Add spawn-posix.c and spawn-w32.c.
* src/w32-add.h: Add pid_t typedef as a temporary hack.
* configure.ac: Check for signal.h and getrlimit.
(AC_FUNC_FORK): New.
--
This does build but porting the tests and further changes are
required. Don't assume that the API for the new fucntions is stable.
Signed-off-by: Werner Koch <[email protected]>
-rw-r--r-- | configure.ac | 8 | ||||
-rw-r--r-- | gpgscm/ffi.c | 14 | ||||
-rw-r--r-- | src/Makefile.am | 4 | ||||
-rw-r--r-- | src/gpg-error.def.in | 9 | ||||
-rw-r--r-- | src/gpg-error.h.in | 51 | ||||
-rw-r--r-- | src/gpg-error.vers | 10 | ||||
-rw-r--r-- | src/gpgrt-int.h | 110 | ||||
-rw-r--r-- | src/spawn-posix.c | 393 | ||||
-rw-r--r-- | src/spawn-w32.c | 402 | ||||
-rw-r--r-- | src/visibility.c | 53 | ||||
-rw-r--r-- | src/visibility.h | 19 | ||||
-rw-r--r-- | src/w32-add.h | 4 |
12 files changed, 582 insertions, 495 deletions
diff --git a/configure.ac b/configure.ac index 0d2f4b5..992d1bd 100644 --- a/configure.ac +++ b/configure.ac @@ -164,7 +164,9 @@ AM_GNU_GETTEXT([external]) # Checks for header files. AC_HEADER_STDC -AC_CHECK_HEADERS([stdlib.h locale.h stdint.h sys/select.h sys/time.h]) +AC_CHECK_HEADERS([stdlib.h locale.h stdint.h sys/select.h sys/time.h \ + signal.h]) + AC_FUNC_STRERROR_R case "${host_os}" in solaris*) @@ -177,7 +179,9 @@ AC_MSG_WARN([[Without strerror_r, gpg_strerror_r might not be thread-safe]])) ;; esac -AC_CHECK_FUNCS([flockfile vasprintf mmap rand strlwr stpcpy setenv stat]) +AC_FUNC_FORK +AC_CHECK_FUNCS([flockfile vasprintf mmap rand strlwr stpcpy setenv stat \ + getrlimit ]) # diff --git a/gpgscm/ffi.c b/gpgscm/ffi.c index 2f3e2f7..578c68d 100644 --- a/gpgscm/ffi.c +++ b/gpgscm/ffi.c @@ -788,7 +788,7 @@ do_spawn_process (scheme *sc, pointer args) fprintf (stderr, "\n"); } - err = gnupg_spawn_process (argv[0], (const char **) &argv[1], + err = gpgrt_spawn_process (argv[0], (const char **) &argv[1], NULL, NULL, flags, @@ -840,7 +840,7 @@ do_spawn_process_fd (scheme *sc, pointer args) fprintf (stderr, "\n"); } - err = gnupg_spawn_process_fd (argv[0], (const char **) &argv[1], + err = gpgrt_spawn_process_fd (argv[0], (const char **) &argv[1], infd, outfd, errfd, &pid); xfree (argv); FFI_RETURN_INT (sc, pid); @@ -860,7 +860,7 @@ do_wait_process (scheme *sc, pointer args) FFI_ARG_OR_RETURN (sc, pid_t, pid, number, args); FFI_ARG_OR_RETURN (sc, int, hang, bool, args); FFI_ARGS_DONE_OR_RETURN (sc, args); - err = gnupg_wait_process (name, pid, hang, &retcode); + err = gpgrt_wait_process (name, pid, hang, &retcode); if (err == GPG_ERR_GENERAL) err = 0; /* Let the return code speak for itself. */ @@ -917,7 +917,7 @@ do_wait_processes (scheme *sc, pointer args) FFI_RETURN_ERR (sc, gpg_error_from_syserror ()); } - err = gnupg_wait_processes ((const char **) names, pids, count, hang, + err = gpgrt_wait_processes ((const char **) names, pids, count, hang, retcodes); if (err == GPG_ERR_GENERAL) err = 0; /* Let the return codes speak. */ @@ -944,7 +944,7 @@ do_pipe (scheme *sc, pointer args) FFI_PROLOG (); int filedes[2]; FFI_ARGS_DONE_OR_RETURN (sc, args); - err = gnupg_create_pipe (filedes); + err = gpgrt_create_pipe (filedes); #define IMC(A, B) \ _cons (sc, sc->vptr->mk_integer (sc, (unsigned long) (A)), (B), 1) FFI_RETURN_POINTER (sc, IMC (filedes[0], @@ -958,7 +958,7 @@ do_inbound_pipe (scheme *sc, pointer args) FFI_PROLOG (); int filedes[2]; FFI_ARGS_DONE_OR_RETURN (sc, args); - err = gnupg_create_inbound_pipe (filedes, NULL, 0); + err = gpgrt_create_inbound_pipe (filedes, NULL, 0); #define IMC(A, B) \ _cons (sc, sc->vptr->mk_integer (sc, (unsigned long) (A)), (B), 1) FFI_RETURN_POINTER (sc, IMC (filedes[0], @@ -972,7 +972,7 @@ do_outbound_pipe (scheme *sc, pointer args) FFI_PROLOG (); int filedes[2]; FFI_ARGS_DONE_OR_RETURN (sc, args); - err = gnupg_create_outbound_pipe (filedes, NULL, 0); + err = gpgrt_create_outbound_pipe (filedes, NULL, 0); #define IMC(A, B) \ _cons (sc, sc->vptr->mk_integer (sc, (unsigned long) (A)), (B), 1) FFI_RETURN_POINTER (sc, IMC (filedes[0], diff --git a/src/Makefile.am b/src/Makefile.am index 4db7338..ac13e70 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -114,7 +114,7 @@ CLEANFILES = err-sources.h err-codes.h code-to-errno.h code-from-errno.h \ # if HAVE_W32_SYSTEM arch_sources = w32-gettext.c w32-lock.c w32-lock-obj.h w32-thread.c \ - w32-iconv.c w32-estream.c w32-reg.c + w32-iconv.c w32-estream.c w32-reg.c spawn-w32.c RCCOMPILE = $(RC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ -DLOCALEDIR=\"$(localedir)\" $(AM_CPPFLAGS) $(CPPFLAGS) LTRCCOMPILE = $(LIBTOOL) --mode=compile --tag=RC $(RCCOMPILE) @@ -153,7 +153,7 @@ else # # {{{ Begin Unix part # -arch_sources = posix-lock.c posix-lock-obj.h posix-thread.c +arch_sources = posix-lock.c posix-lock-obj.h posix-thread.c spawn-posix.c gpg_error_res = no_undefined = export_symbols = diff --git a/src/gpg-error.def.in b/src/gpg-error.def.in index 64c75dc..3f26a89 100644 --- a/src/gpg-error.def.in +++ b/src/gpg-error.def.in @@ -197,5 +197,14 @@ EXPORTS gpgrt_chdir @150 gpgrt_getcwd @151 + gpgrt_make_pipe @152 + gpgrt_spawn_process @153 + gpgrt_spawn_process_fd @154 + gpgrt_spawn_process_detached @155 + gpgrt_wait_process @156 + gpgrt_wait_processes @157 + gpgrt_kill_process @158 + gpgrt_release_process @159 + ;; end of file with public symbols for Windows. diff --git a/src/gpg-error.h.in b/src/gpg-error.h.in index 20d196a..991636d 100644 --- a/src/gpg-error.h.in +++ b/src/gpg-error.h.in @@ -1025,6 +1025,57 @@ void _gpgrt_log_assert (const char *expr, const char *file, int line, #endif /*GPGRT_ENABLE_LOG_MACROS*/ + +/* + * Spawn functions + */ + +#define GPGRT_SPAWN_NONBLOCK 16 /* Set the streams to non-blocking. */ +#define GPGRT_SPAWN_RUN_ASFW 64 /* Use AllowSetForegroundWindow on W32. */ +#define GPGRT_SPAWN_DETACHED 128 /* Start the process in the background. */ + +/* Function and convenience macros to create pipes. */ +gpg_err_code_t gpgrt_make_pipe (int filedes[2], estream_t *r_fp, + int direction, int nonblock); +#define gpgrt_create_pipe(a) gpgrt_make_pipe ((a),NULL, 0, 0); +#define gpgrt_create_inbound_pipe(a,b,c) gpgrt_make_pipe ((a), (b), -1,(c)); +#define gpgrt_create_outbound_pipe(a,b,c) gpgrt_make_pipe ((a), (b), 1,(c)); + + +/* Fork and exec PGMNAME. */ +gpg_err_code_t gpgrt_spawn_process (const char *pgmname, const char *argv[], + int *execpt, void (*preexec)(void), + unsigned int flags, + estream_t *r_infp, + estream_t *r_outfp, + estream_t *r_errfp, + pid_t *pid); + +/* Fork and exec PGNNAME and connect the process to the given FDs. */ +gpg_err_code_t gpgrt_spawn_process_fd (const char *pgmname, const char *argv[], + int infd, int outfd, int errfd, + pid_t *pid); + +/* Fork and exec PGMNAME as a detached process. */ +gpg_err_code_t gpgrt_spawn_process_detached (const char *pgmname, + const char *argv[], + const char *envp[] ); + +/* Wait for a single process. */ +gpg_err_code_t gpgrt_wait_process (const char *pgmname, pid_t pid, int hang, + int *r_exitcode); + +/* Wait for a multiple processes. */ +gpg_err_code_t gpgrt_wait_processes (const char **pgmnames, pid_t *pids, + size_t count, int hang, int *r_exitcodes); + +/* Kill the process identified by PID. */ +void gpgrt_kill_process (pid_t pid); + +/* Release process resources identified by PID. */ +void gpgrt_release_process (pid_t pid); + + #ifdef __cplusplus } diff --git a/src/gpg-error.vers b/src/gpg-error.vers index 92184f3..a5f91aa 100644 --- a/src/gpg-error.vers +++ b/src/gpg-error.vers @@ -169,6 +169,16 @@ GPG_ERROR_1.0 { gpgrt_chdir; gpgrt_getcwd; + gpgrt_make_pipe; + gpgrt_spawn_process; + gpgrt_spawn_process_fd; + gpgrt_spawn_process_detached; + gpgrt_wait_process; + gpgrt_wait_processes; + gpgrt_kill_process; + gpgrt_release_process; + + local: *; }; diff --git a/src/gpgrt-int.h b/src/gpgrt-int.h index e144ff1..2413257 100644 --- a/src/gpgrt-int.h +++ b/src/gpgrt-int.h @@ -122,6 +122,7 @@ char *_gpgrt_strconcat_core (const char *s1, va_list arg_ptr); #define xtrymalloc(a) _gpgrt_malloc ((a)) #define xtrycalloc(a,b) _gpgrt_calloc ((a),(b)) #define xtryrealloc(a,b) _gpgrt_realloc ((a),(b)) +#define xtrystrdup(a) _gpgrt_strdup ((a)) @@ -553,6 +554,9 @@ int _gpgrt_logv_internal (int level, int ignore_arg_ptr, /* * Local prototypes for the spawn functions. + * + * We put the docs here because we have separate implementations in + * the files spawn-posix.c and spawn-w32.c */ /* Return the maximum number of currently allowed file descriptors. @@ -574,27 +578,18 @@ int _gpgrt_logv_internal (int level, int ignore_arg_ptr, * been initialized. Returns NULL on error and sets ERRNO accordingly. */ /* int *get_all_open_fds (void); */ +/* Create a pipe. The DIRECTION parameter gives the type of the created pipe: + * DIRECTION < 0 := Inbound pipe: On Windows the write end is inheritable. + * DIRECTION > 0 := Outbound pipe: On Windows the read end is inheritable. + * If R_FP is NULL a standard pipe and no stream is created, DIRECTION + * should then be 0. */ +gpg_err_code_t _gpgrt_make_pipe (int filedes[2], estream_t *r_fp, + int direction, int nonblock); -/* Portable function to create a pipe. Under Windows the write end is - * inheritable. If R_FP is not NULL, an estream is created for the - * write end and stored at R_FP. */ -gpg_error_t gnupg_create_inbound_pipe (int filedes[2], - estream_t *r_fp, int nonblock); - -/* Portable function to create a pipe. Under Windows the read end is - * inheritable. If R_FP is not NULL, an estream is created for the - * write end and stored at R_FP. */ -gpg_error_t gnupg_create_outbound_pipe (int filedes[2], - estream_t *r_fp, int nonblock); - -/* Portable function to create a pipe. Under Windows both ends are - * inheritable. */ -gpg_error_t gnupg_create_pipe (int filedes[2]); - - -#define GNUPG_SPAWN_NONBLOCK 16 -#define GNUPG_SPAWN_RUN_ASFW 64 -#define GNUPG_SPAWN_DETACHED 128 +/* Convenience macros to create a pipe. */ +#define _gpgrt_create_pipe(a) _gpgrt_make_pipe ((a),NULL, 0, 0); +#define _gpgrt_create_inbound_pipe(a,b,c) _gpgrt_make_pipe ((a), (b), -1, (c)); +#define _gpgrt_create_outbound_pipe(a,b,c) _gpgrt_make_pipe ((a), (b), 1, (c)); /* Fork and exec the program PGMNAME. @@ -618,51 +613,60 @@ gpg_error_t gnupg_create_pipe (int filedes[2]); * descriptors, terminated by an entry with the value (-1). These * file descriptors won't be closed before spawning a new program. * - * Returns 0 on success or an error code. Calling gnupg_wait_process - * and gnupg_release_process is required if the function succeeded. + * Returns 0 on success or an error code. Calling gpgrt_wait_process + * and gpgrt_release_process is required if the function succeeded. * * FLAGS is a bit vector: * - * GNUPG_SPAWN_NONBLOCK + * GPGRT_SPAWN_NONBLOCK * If set the two output streams are created in non-blocking * mode and the input stream is switched to non-blocking mode. * This is merely a convenience feature because the caller * could do the same with gpgrt_set_nonblock. Does not yet * work for Windows. * - * GNUPG_SPAWN_DETACHED + * GPGRT_SPAWN_DETACHED * If set the process will be started as a background process. * This flag is only useful under W32 (but not W32CE) systems, * so that no new console is created and pops up a console * window when starting the server. Does not work on W32CE. * - * GNUPG_SPAWN_RUN_ASFW + * GPGRT_SPAWN_RUN_ASFW * On W32 (but not on W32CE) run AllowSetForegroundWindow for * the child. Note that due to unknown problems this actually * allows SetForegroundWindow for all children of this process. */ -gpg_error_t -gnupg_spawn_process (const char *pgmname, const char *argv[], - int *execpt, void (*preexec)(void), unsigned int flags, - estream_t *r_infp, - estream_t *r_outfp, - estream_t *r_errfp, - pid_t *pid); +gpg_err_code_t +_gpgrt_spawn_process (const char *pgmname, const char *argv[], + int *execpt, void (*preexec)(void), unsigned int flags, + estream_t *r_infp, + estream_t *r_outfp, + estream_t *r_errfp, + pid_t *pid); -/* Simplified version of gnupg_spawn_process. This function forks and +/* Simplified version of gpgrt_spawn_process. This function forks and * then execs PGMNAME, while connecting INFD to stdin, OUTFD to stdout * and ERRFD to stderr (any of them may be -1 to connect them to * /dev/null). The arguments for the process are expected in the NULL * terminated array ARGV. The program name itself should not be - * included there. Calling gnupg_wait_process and - * gnupg_release_process is required. Returns 0 on success or an + * included there. Calling gpgrt_wait_process and + * gpgrt_release_process is required. Returns 0 on success or an * error code. */ -gpg_error_t gnupg_spawn_process_fd (const char *pgmname, - const char *argv[], - int infd, int outfd, int errfd, - pid_t *pid); +gpg_err_code_t _gpgrt_spawn_process_fd (const char *pgmname, + const char *argv[], + int infd, int outfd, int errfd, + pid_t *pid); +/* Spawn a new process and immediately detach from it. The name of + * the program to exec is PGMNAME and its arguments are in ARGV (the + * programname is automatically passed as first argument). + * Environment strings in ENVP are set. An error is returned if + * pgmname is not executable; to make this work it is necessary to + * provide an absolute file name. */ +gpg_err_code_t _gpgrt_spawn_process_detached (const char *pgmname, + const char *argv[], + const char *envp[] ); /* If HANG is true, waits for the process identified by PID to exit; * if HANG is false, checks whether the process has terminated. @@ -688,34 +692,22 @@ gpg_error_t gnupg_spawn_process_fd (const char *pgmname, * if the exit code is not required (in that case an error message will * be printed). Note that under Windows PID is not the process id but * the handle of the process. */ -gpg_error_t gnupg_wait_process (const char *pgmname, pid_t pid, int hang, - int *r_exitcode); - -/* Like gnupg_wait_process, but for COUNT processes. */ -gpg_error_t gnupg_wait_processes (const char **pgmnames, pid_t *pids, - size_t count, int hang, int *r_exitcodes); +gpg_err_code_t _gpgrt_wait_process (const char *pgmname, pid_t pid, int hang, + int *r_exitcode); +/* Like _gpgrt_wait_process, but for COUNT processes. */ +gpg_err_code_t _gpgrt_wait_processes (const char **pgmnames, pid_t *pids, + size_t count, int hang, int *r_exitcodes); /* Kill a process; that is send an appropriate signal to the process. - * gnupg_wait_process must be called to actually remove the process + * gpgrt_wait_process must be called to actually remove the process * from the system. An invalid PID is ignored. */ -void gnupg_kill_process (pid_t pid); +void _gpgrt_kill_process (pid_t pid); /* Release the process identified by PID. This function is actually * only required for Windows but it does not harm to always call it. * It is a nop if PID is invalid. */ -void gnupg_release_process (pid_t pid); - - -/* Spawn a new process and immediately detach from it. The name of - * the program to exec is PGMNAME and its arguments are in ARGV (the - * programname is automatically passed as first argument). - * Environment strings in ENVP are set. An error is returned if - * pgmname is not executable; to make this work it is necessary to - * provide an absolute file name. */ -gpg_error_t gnupg_spawn_process_detached (const char *pgmname, - const char *argv[], - const char *envp[] ); +void _gpgrt_release_process (pid_t pid); diff --git a/src/spawn-posix.c b/src/spawn-posix.c index 9e7800f..add012b 100644 --- a/src/spawn-posix.c +++ b/src/spawn-posix.c @@ -39,14 +39,6 @@ #include <unistd.h> #include <fcntl.h> -#ifdef WITHOUT_NPTH /* Give the Makefile a chance to build without Pth. */ -#undef HAVE_NPTH -#undef USE_NPTH -#endif - -#ifdef HAVE_NPTH -#include <npth.h> -#endif #include <sys/wait.h> #ifdef HAVE_GETRLIMIT @@ -63,30 +55,22 @@ # include <dirent.h> #endif /*__linux__ */ -#include "util.h" -#include "i18n.h" -#include "sysutils.h" -#include "exechelp.h" - +#include "gpgrt-int.h" -/* Helper */ -static inline gpg_error_t -my_error_from_syserror (void) -{ - return gpg_err_make (default_errsource, gpg_err_code_from_syserror ()); -} -static inline gpg_error_t -my_error (int errcode) +static void +out_of_core (int line) { - return gpg_err_make (default_errsource, errcode); + _gpgrt_log_fatal ("malloc failed at line %d: %s\n", + line, _gpg_strerror (_gpg_err_code_from_syserror ())); + /*NOTREACHED*/ } /* Return the maximum number of currently allowed open file - descriptors. Only useful on POSIX systems but returns a value on - other systems too. */ -int + * descriptors. Only useful on POSIX systems but returns a value on + * other systems too. */ +static int get_max_fds (void) { int max_fds = -1; @@ -110,6 +94,7 @@ get_max_fds (void) const char *s; int x; + /* FIXME: Check gpgme on how to do this right on Linux. */ dir = opendir ("/proc/self/fd"); if (dir) { @@ -176,10 +161,10 @@ get_max_fds (void) /* Close all file descriptors starting with descriptor FIRST. If - 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. */ -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) { int max_fd = get_max_fds (); @@ -211,16 +196,20 @@ close_all_fds (int first, int *except) close (fd); } - gpg_err_set_errno (0); + _gpg_err_set_errno (0); } /* Returns an array with all currently open file descriptors. The end - of the array is marked by -1. The caller needs to release this - array using the *standard free* and not with xfree. This allow the - use of this function right at startup even before libgcrypt has - been initialized. Returns NULL on error and sets ERRNO - accordingly. */ + * of the array is marked by -1. The caller needs to release this + * array using the *standard free* and not with xfree. This allow the + * use of this function right at startup even before libgcrypt has + * been initialized. Returns NULL on error and sets ERRNO + * accordingly. + * + * FIXME: Needs to be adjusted for use here. + */ +#if 0 int * get_all_open_fds (void) { @@ -263,9 +252,10 @@ get_all_open_fds (void) #endif /*HAVE_STAT*/ return array; } +#endif /*0*/ -/* The exec core used right after the fork. This will never return. */ +/* The exec core used right after the fork. This will never return. */ static void do_exec (const char *pgmname, const char *argv[], int fd_in, int fd_out, int fd_err, @@ -284,12 +274,18 @@ do_exec (const char *pgmname, const char *argv[], if (argv) while (argv[i]) i++; - arg_list = xcalloc (i+2, sizeof *arg_list); + arg_list = xtrycalloc (i+2, sizeof *arg_list); + if (!arg_list) + out_of_core (__LINE__); arg_list[0] = strrchr (pgmname, '/'); if (arg_list[0]) arg_list[0]++; else - arg_list[0] = xstrdup (pgmname); + { + arg_list[0] = xtrystrdup (pgmname); + if (!arg_list[0]) + out_of_core (__LINE__); + } if (argv) for (i=0,j=1; argv[i]; i++, j++) arg_list[j] = (char*)argv[i]; @@ -301,8 +297,8 @@ do_exec (const char *pgmname, const char *argv[], { fds[i] = open ("/dev/null", i? O_WRONLY : O_RDONLY); if (fds[i] == -1) - log_fatal ("failed to open '%s': %s\n", - "/dev/null", strerror (errno)); + _gpgrt_log_fatal ("failed to open '%s': %s\n", + "/dev/null", strerror (errno)); } } @@ -310,8 +306,8 @@ do_exec (const char *pgmname, const char *argv[], for (i=0; i <= 2; i++) { 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)); + _gpgrt_log_fatal ("dup2 std%s failed: %s\n", + i==0?"in":i==1?"out":"err", strerror (errno)); } /* Close all other files. */ @@ -320,19 +316,20 @@ do_exec (const char *pgmname, const char *argv[], if (preexec) preexec (); execv (pgmname, arg_list); - /* No way to print anything, as we have closed all streams. */ + /* No way to print anything, as we have may have closed all streams. */ _exit (127); } -static gpg_error_t +/* Helper for _gpgrt_make_pipe. */ +static gpg_err_code_t do_create_pipe (int filedes[2]) { gpg_error_t err = 0; if (pipe (filedes) == -1) { - err = my_error_from_syserror (); + err = _gpg_err_code_from_syserror (); filedes[0] = filedes[1] = -1; } @@ -340,30 +337,31 @@ do_create_pipe (int filedes[2]) } -static gpg_error_t -create_pipe_and_estream (int filedes[2], estream_t *r_fp, - int outbound, int nonblock) +/* Helper for _gpgrt_make_pipe. */ +static gpg_err_code_t +do_create_pipe_and_estream (int filedes[2], estream_t *r_fp, + int outbound, int nonblock) { - gpg_error_t err; + gpg_err_code_t err; if (pipe (filedes) == -1) { - err = my_error_from_syserror (); - log_error (_("error creating a pipe: %s\n"), gpg_strerror (err)); + err = _gpg_err_code_from_syserror (); + _gpgrt_log_error (_("error creating a pipe: %s\n"), _gpg_strerror (err)); filedes[0] = filedes[1] = -1; *r_fp = NULL; return err; } if (!outbound) - *r_fp = es_fdopen (filedes[0], nonblock? "r,nonblock" : "r"); + *r_fp = _gpgrt_fdopen (filedes[0], nonblock? "r,nonblock" : "r"); else - *r_fp = es_fdopen (filedes[1], nonblock? "w,nonblock" : "w"); + *r_fp = _gpgrt_fdopen (filedes[1], nonblock? "w,nonblock" : "w"); if (!*r_fp) { - err = my_error_from_syserror (); - log_error (_("error creating a stream for a pipe: %s\n"), - gpg_strerror (err)); + err = _gpg_err_code_from_syserror (); + _gpgrt_log_error (_("error creating a stream for a pipe: %s\n"), + _gpg_strerror (err)); close (filedes[0]); close (filedes[1]); filedes[0] = filedes[1] = -1; @@ -373,49 +371,31 @@ create_pipe_and_estream (int filedes[2], estream_t *r_fp, } -/* Portable function to create a pipe. Under Windows the write end is - inheritable. If R_FP is not NULL, an estream is created for the - read end and stored at R_FP. */ -gpg_error_t -gnupg_create_inbound_pipe (int filedes[2], estream_t *r_fp, int nonblock) +/* Create a pipe. The DIRECTION parameter gives the type of the created pipe: + * DIRECTION < 0 := Inbound pipe: On Windows the write end is inheritable. + * DIRECTION > 0 := Outbound pipe: On Windows the read end is inheritable. + * If R_FP is NULL a standard pipe and no stream is created, DIRECTION + * should then be 0. */ +gpg_err_code_t +_gpgrt_make_pipe (int filedes[2], estream_t *r_fp, int direction, + int nonblock) { - if (r_fp) - return create_pipe_and_estream (filedes, r_fp, 0, nonblock); + if (r_fp && direction) + return do_create_pipe_and_estream (filedes, r_fp, + (direction > 0), nonblock); else return do_create_pipe (filedes); } -/* Portable function to create a pipe. Under Windows the read end is - inheritable. If R_FP is not NULL, an estream is created for the - write end and stored at R_FP. */ -gpg_error_t -gnupg_create_outbound_pipe (int filedes[2], estream_t *r_fp, int nonblock) -{ - if (r_fp) - return create_pipe_and_estream (filedes, r_fp, 1, nonblock); - else - return do_create_pipe (filedes); -} - - -/* Portable function to create a pipe. Under Windows both ends are - inheritable. */ -gpg_error_t -gnupg_create_pipe (int filedes[2]) -{ - return do_create_pipe (filedes); -} - - -/* Fork and exec the PGMNAME, see exechelp.h for details. */ -gpg_error_t -gnupg_spawn_process (const char *pgmname, const char *argv[], - int *except, void (*preexec)(void), unsigned int flags, - estream_t *r_infp, - estream_t *r_outfp, - estream_t *r_errfp, - pid_t *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, + estream_t *r_infp, + estream_t *r_outfp, + estream_t *r_errfp, + pid_t *pid) { gpg_error_t err; int inpipe[2] = {-1, -1}; @@ -424,7 +404,7 @@ gnupg_spawn_process (const char *pgmname, const char *argv[], estream_t infp = NULL; estream_t outfp = NULL; estream_t errfp = NULL; - int nonblock = !!(flags & GNUPG_SPAWN_NONBLOCK); + int nonblock = !!(flags & GPGRT_SPAWN_NONBLOCK); if (r_infp) *r_infp = NULL; @@ -436,18 +416,18 @@ gnupg_spawn_process (const char *pgmname, const char *argv[], if (r_infp) { - err = create_pipe_and_estream (inpipe, &infp, 1, nonblock); + err = _gpgrt_create_outbound_pipe (inpipe, &infp, nonblock); if (err) return err; } if (r_outfp) { - err = create_pipe_and_estream (outpipe, &outfp, 0, nonblock); + err = _gpgrt_create_inbound_pipe (outpipe, &outfp, nonblock); if (err) { if (infp) - es_fclose (infp); + _gpgrt_fclose (infp); else if (inpipe[1] != -1) close (inpipe[1]); if (inpipe[0] != -1) @@ -459,18 +439,18 @@ gnupg_spawn_process (const char *pgmname, const char *argv[], if (r_errfp) { - err = create_pipe_and_estream (errpipe, &errfp, 0, nonblock); + err = _gpgrt_create_inbound_pipe (errpipe, &errfp, nonblock); if (err) { if (infp) - es_fclose (infp); + _gpgrt_fclose (infp); else if (inpipe[1] != -1) close (inpipe[1]); if (inpipe[0] != -1) close (inpipe[0]); if (outfp) - es_fclose (outfp); + _gpgrt_fclose (outfp); else if (outpipe[0] != -1) close (outpipe[0]); if (outpipe[1] != -1) @@ -484,25 +464,25 @@ gnupg_spawn_process (const char *pgmname, const char *argv[], *pid = fork (); if (*pid == (pid_t)(-1)) { - err = my_error_from_syserror (); - log_error (_("error forking process: %s\n"), gpg_strerror (err)); + err = _gpg_err_code_from_syserror (); + _gpgrt_log_error (_("error forking process: %s\n"), _gpg_strerror (err)); if (infp) - es_fclose (infp); + _gpgrt_fclose (infp); else if (inpipe[1] != -1) close (inpipe[1]); if (inpipe[0] != -1) close (inpipe[0]); if (outfp) - es_fclose (outfp); + _gpgrt_fclose (outfp); else if (outpipe[0] != -1) close (outpipe[0]); if (outpipe[1] != -1) close (outpipe[1]); if (errfp) - es_fclose (errfp); + _gpgrt_fclose (errfp); else if (errpipe[0] != -1) close (errpipe[0]); if (errpipe[1] != -1) @@ -513,10 +493,11 @@ gnupg_spawn_process (const char *pgmname, const char *argv[], if (!*pid) { /* This is the child. */ - gcry_control (GCRYCTL_TERM_SECMEM); - es_fclose (infp); - es_fclose (outfp); - es_fclose (errfp); + /* 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); /*NOTREACHED*/ @@ -541,32 +522,26 @@ gnupg_spawn_process (const char *pgmname, const char *argv[], } - -/* Simplified version of gnupg_spawn_process. This function forks and - then execs PGMNAME, while connecting INFD to stdin, OUTFD to stdout - and ERRFD to stderr (any of them may be -1 to connect them to - /dev/null). The arguments for the process are expected in the NULL - terminated array ARGV. The program name itself should not be - included there. Calling gnupg_wait_process is required. - - Returns 0 on success or an error code. */ -gpg_error_t -gnupg_spawn_process_fd (const char *pgmname, const char *argv[], - int infd, int outfd, int errfd, pid_t *pid) +/* 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) { gpg_error_t err; *pid = fork (); if (*pid == (pid_t)(-1)) { - err = my_error_from_syserror (); - log_error (_("error forking process: %s\n"), strerror (errno)); + err = _gpg_err_code_from_syserror (); + _gpgrt_log_error (_("error forking process: %s\n"), _gpg_strerror (err)); return err; } if (!*pid) { - gcry_control (GCRYCTL_TERM_SECMEM); + /* FIXME: We need to add a preexec so that a + gcry_control (GCRYCTL_TERM_SECMEM); + can be done. */ /* Run child. */ do_exec (pgmname, argv, infd, outfd, errfd, NULL, NULL); /*NOTREACHED*/ @@ -576,17 +551,17 @@ gnupg_spawn_process_fd (const char *pgmname, const char *argv[], } - - /* Waiting for child processes. - - waitpid(2) may return information about terminated children that we - did not yet request, and there is no portable way to wait for a - specific set of children. - - As a workaround, we store the results of children for later use. - - XXX: This assumes that PIDs are not reused too quickly. */ + * + * waitpid(2) may return information about terminated children that we + * did not yet request, and there is no portable way to wait for a + * specific set of children. + * + * As a workaround, we store the results of children for later use. + * + * XXX: This assumes that PIDs are not reused too quickly. + * FIXME: This is not thread-safe. + */ struct terminated_child { @@ -595,17 +570,17 @@ struct terminated_child struct terminated_child *next; }; -struct terminated_child *terminated_children; +static struct terminated_child *terminated_children; -static gpg_error_t +static gpg_err_code_t store_result (pid_t pid, int exitcode) { struct terminated_child *c; c = xtrymalloc (sizeof *c); if (c == NULL) - return gpg_err_code_from_syserror (); + return _gpg_err_code_from_syserror (); c->pid = pid; c->exitcode = exitcode; @@ -636,9 +611,9 @@ get_result (pid_t pid, int *r_exitcode) } -/* See exechelp.h for a description. */ -gpg_error_t -gnupg_wait_process (const char *pgmname, pid_t pid, int hang, 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) { gpg_err_code_t ec; int i, status; @@ -647,20 +622,16 @@ gnupg_wait_process (const char *pgmname, pid_t pid, int hang, int *r_exitcode) *r_exitcode = -1; if (pid == (pid_t)(-1)) - return gpg_error (GPG_ERR_INV_VALUE); + return GPG_ERR_INV_VALUE; -#ifdef USE_NPTH - i = npth_waitpid (pid, &status, hang? 0:WNOHANG); -#else while ((i=waitpid (pid, &status, hang? 0:WNOHANG)) == (pid_t)(-1) && errno == EINTR); -#endif if (i == (pid_t)(-1)) { - ec = gpg_err_code_from_errno (errno); - log_error (_("waiting for process %d to terminate failed: %s\n"), - (int)pid, strerror (errno)); + ec = _gpg_err_code_from_syserror (); + _gpgrt_log_error (_("waiting for process %d to terminate failed: %s\n"), + (int)pid, _gpg_strerror (ec)); } else if (!i) { @@ -668,21 +639,23 @@ gnupg_wait_process (const char *pgmname, pid_t pid, int hang, int *r_exitcode) } else if (WIFEXITED (status) && WEXITSTATUS (status) == 127) { - log_error (_("error running '%s': probably not installed\n"), pgmname); + /* FIXME: This is GnuPG specific. */ + _gpgrt_log_error (_("error running '%s': probably not installed\n"), + pgmname); ec = GPG_ERR_CONFIGURATION; } else if (WIFEXITED (status) && WEXITSTATUS (status)) { if (!r_exitcode) - log_error (_("error running '%s': exit status %d\n"), pgmname, - WEXITSTATUS (status)); + _gpgrt_log_error (_("error running '%s': exit status %d\n"), pgmname, + WEXITSTATUS (status)); else *r_exitcode = WEXITSTATUS (status); ec = GPG_ERR_GENERAL; } else if (!WIFEXITED (status)) { - log_error (_("error running '%s': terminated\n"), pgmname); + _gpgrt_log_error (_("error running '%s': terminated\n"), pgmname); ec = GPG_ERR_GENERAL; } else @@ -692,23 +665,30 @@ gnupg_wait_process (const char *pgmname, pid_t pid, int hang, int *r_exitcode) ec = 0; } - return gpg_err_make (GPG_ERR_SOURCE_DEFAULT, ec); + return ec; } -/* See exechelp.h for a description. */ -gpg_error_t -gnupg_wait_processes (const char **pgmnames, pid_t *pids, size_t count, - int hang, int *r_exitcodes) + +/* See gpgrt-int.h for a description. + * + * FIXME: What about using a poll like data structure for the pids and + * their exit codes? The whole thing is anyway problematic in a + * threaded processs because waitpid has no association between PIDS + * and threads. + */ +gpg_err_code_t +_gpgrt_wait_processes (const char **pgmnames, pid_t *pids, size_t count, + int hang, int *r_exitcodes) { gpg_err_code_t ec = 0; size_t i, left; int *dummy = NULL; - if (r_exitcodes == NULL) + if (!r_exitcodes) { dummy = r_exitcodes = xtrymalloc (sizeof *r_exitcodes * count); - if (dummy == NULL) - return gpg_err_code_from_syserror (); + if (!dummy) + return _gpg_err_code_from_syserror (); } for (i = 0, left = count; i < count; i++) @@ -716,7 +696,7 @@ gnupg_wait_processes (const char **pgmnames, pid_t *pids, size_t count, int status = -1; if (pids[i] == (pid_t)(-1)) - return my_error (GPG_ERR_INV_VALUE); + return GPG_ERR_INV_VALUE; /* See if there was a previously stored result for this pid. */ if (get_result (pids[i], &status)) @@ -730,18 +710,14 @@ gnupg_wait_processes (const char **pgmnames, pid_t *pids, size_t count, pid_t pid; int status; -#ifdef USE_NPTH - pid = npth_waitpid (-1, &status, hang ? 0 : WNOHANG); -#else while ((pid = waitpid (-1, &status, hang ? 0 : WNOHANG)) == (pid_t)(-1) && errno == EINTR); -#endif if (pid == (pid_t)(-1)) { - ec = gpg_err_code_from_errno (errno); - log_error (_("waiting for processes to terminate failed: %s\n"), - strerror (errno)); + ec = _gpg_err_code_from_syserror (); + _gpgrt_log_error (_("waiting for processes to terminate" + " failed: %s\n"), _gpg_strerror (ec)); break; } else if (!pid) @@ -767,7 +743,7 @@ gnupg_wait_processes (const char **pgmnames, pid_t *pids, size_t count, /* Process PIDS[i] died. */ if (r_exitcodes[i] != (pid_t) -1) { - log_error ("PID %d was reused", pid); + _gpgrt_log_error ("PID %d was reused", pid); ec = GPG_ERR_GENERAL; break; } @@ -784,70 +760,61 @@ gnupg_wait_processes (const char **pgmnames, pid_t *pids, size_t count, if (WIFEXITED (r_exitcodes[i]) && WEXITSTATUS (r_exitcodes[i]) == 127) { - log_error (_("error running '%s': probably not installed\n"), - pgmnames[i]); + _gpgrt_log_error (_("error running '%s': probably not installed\n"), + pgmnames[i]); ec = GPG_ERR_CONFIGURATION; } else if (WIFEXITED (r_exitcodes[i]) && WEXITSTATUS (r_exitcodes[i])) { if (dummy) - log_error (_("error running '%s': exit status %d\n"), - pgmnames[i], WEXITSTATUS (r_exitcodes[i])); + _gpgrt_log_error (_("error running '%s': exit status %d\n"), + pgmnames[i], WEXITSTATUS (r_exitcodes[i])); else r_exitcodes[i] = WEXITSTATUS (r_exitcodes[i]); ec = GPG_ERR_GENERAL; } else if (!WIFEXITED (r_exitcodes[i])) { - log_error (_("error running '%s': terminated\n"), pgmnames[i]); + _gpgrt_log_error (_("error running '%s': terminated\n"), pgmnames[i]); ec = GPG_ERR_GENERAL; } } xfree (dummy); - return gpg_err_make (GPG_ERR_SOURCE_DEFAULT, ec); + return ec; } - -void -gnupg_release_process (pid_t pid) -{ - (void)pid; -} - - -/* Spawn a new process and immediately detach from it. The name of - the program to exec is PGMNAME and its arguments are in ARGV (the - programname is automatically passed as first argument). - Environment strings in ENVP are set. An error is returned if - pgmname is not executable; to make this work it is necessary to - provide an absolute file name. All standard file descriptors are - connected to /dev/null. */ -gpg_error_t -gnupg_spawn_process_detached (const char *pgmname, const char *argv[], - const char *envp[] ) +/* See gpgrt-int.h for a description. FIXME: We should add a prexec + * callback. */ +gpg_err_code_t +_gpgrt_spawn_process_detached (const char *pgmname, const char *argv[], + const char *envp[] ) { + gpg_err_code_t ec; pid_t pid; int i; + /* FIXME: Is this GnuPG specific or should we keep it. */ if (getuid() != geteuid()) - return my_error (GPG_ERR_BUG); + return GPG_ERR_BUG; if (access (pgmname, X_OK)) - return my_error_from_syserror (); + return _gpg_err_code_from_syserror (); pid = fork (); if (pid == (pid_t)(-1)) { - log_error (_("error forking process: %s\n"), strerror (errno)); - return my_error_from_syserror (); + ec = _gpg_err_code_from_syserror (); + _gpgrt_log_error (_("error forking process: %s\n"), _gpg_strerror (ec)); + return ec; } + if (!pid) { pid_t pid2; - gcry_control (GCRYCTL_TERM_SECMEM); + /* gcry_control (GCRYCTL_TERM_SECMEM); */ if (setsid() == -1 || chdir ("/")) _exit (1); @@ -857,31 +824,45 @@ gnupg_spawn_process_detached (const char *pgmname, const char *argv[], if (pid2) _exit (0); /* Let the parent exit immediately. */ - if (envp) - for (i=0; envp[i]; i++) - putenv (xstrdup (envp[i])); + for (i=0; envp && envp[i]; i++) + { + char *p = xtrystrdup (envp[i]); + if (!p) + out_of_core (__LINE__); + putenv (p); + } do_exec (pgmname, argv, -1, -1, -1, NULL, NULL); - /*NOTREACHED*/ } if (waitpid (pid, NULL, 0) == -1) - log_error ("waitpid failed in gnupg_spawn_process_detached: %s", - strerror (errno)); + { + ec = _gpg_err_code_from_syserror (); + _gpgrt_log_error ("waitpid failed in gpgrt_spawn_process_detached: %s", + _gpg_strerror (ec)); + return ec; + } return 0; } /* Kill a process; that is send an appropriate signal to the process. - gnupg_wait_process must be called to actually remove the process + * gnupg_wait_process must be called to actually remove the process from the system. An invalid PID is ignored. */ void -gnupg_kill_process (pid_t pid) +_gpgrt_kill_process (pid_t pid) { if (pid != (pid_t)(-1)) { kill (pid, SIGTERM); } } + + +void +_gpgrt_release_process (pid_t pid) +{ + (void)pid; +} diff --git a/src/spawn-w32.c b/src/spawn-w32.c index 0e4201f..96f8062 100644 --- a/src/spawn-w32.c +++ b/src/spawn-w32.c @@ -37,63 +37,39 @@ #endif #include <unistd.h> #include <fcntl.h> - -#ifdef WITHOUT_NPTH /* Give the Makefile a chance to build without Pth. */ -#undef HAVE_NPTH -#undef USE_NPTH -#endif - -#ifdef HAVE_NPTH -#include <npth.h> -#endif - #ifdef HAVE_STAT # include <sys/stat.h> #endif +#define WIN32_LEAN_AND_MEAN /* We only need the OS core stuff. */ +#include <windows.h> - -#include "util.h" -#include "i18n.h" -#include "sysutils.h" -#include "exechelp.h" +#include "gpgrt-int.h" /* Define to 1 do enable debugging. */ #define DEBUG_W32_SPAWN 0 /* It seems Vista doesn't grok X_OK and so fails access() tests. - Previous versions interpreted X_OK as F_OK anyway, so we'll just - use F_OK directly. */ + * Previous versions interpreted X_OK as F_OK anyway, so we'll just + * use F_OK directly. */ #undef X_OK #define X_OK F_OK /* We assume that a HANDLE can be represented by an int which should - be true for all i386 systems (HANDLE is defined as void *) and - these are the only systems for which Windows is available. Further - we assume that -1 denotes an invalid handle. */ -# define fd_to_handle(a) ((HANDLE)(a)) -# define handle_to_fd(a) ((int)(a)) -# define pid_to_handle(a) ((HANDLE)(a)) -# define handle_to_pid(a) ((int)(a)) - - -/* Helper */ -static inline gpg_error_t -my_error_from_syserror (void) -{ - return gpg_err_make (default_errsource, gpg_err_code_from_syserror ()); -} - -static inline gpg_error_t -my_error (int errcode) -{ - return gpg_err_make (default_errsource, errcode); -} + * be true for all i386 systems (HANDLE is defined as void *) and + * these are the only systems for which Windows is available. Further + * we assume that -1 denotes an invalid handle. + * FIXME: With Windows 64 this is no longer true. + */ +#define fd_to_handle(a) ((HANDLE)(a)) +#define handle_to_fd(a) ((int)(a)) +#define pid_to_handle(a) ((HANDLE)(a)) +#define handle_to_pid(a) ((int)(a)) /* Return the maximum number of currently allowed open file - descriptors. Only useful on POSIX systems but returns a value on - other systems too. */ + * descriptors. Only useful on POSIX systems but returns a value on + * other systems too. */ int get_max_fds (void) { @@ -112,12 +88,12 @@ get_max_fds (void) /* Under Windows this is a dummy function. */ -void -close_all_fds (int first, int *except) -{ - (void)first; - (void)except; -} +/* static void */ +/* close_all_fds (int first, int *except) */ +/* { */ +/* (void)first; */ +/* (void)except; */ +/* } */ /* Returns an array with all currently open file descriptors. The end @@ -129,6 +105,7 @@ close_all_fds (int first, int *except) * invalid fds which is a bit annoying. We actually do not need this * function in real code (close_all_fds is a dummy anyway) but we keep * it for use by t-exechelp.c. */ +#if 0 int * get_all_open_fds (void) { @@ -171,6 +148,7 @@ get_all_open_fds (void) #endif /*HAVE_STAT*/ return array; } +#endif /* Helper function to build_w32_commandline. */ @@ -201,9 +179,10 @@ build_w32_commandline_copy (char *buffer, const char *string) return p; } + /* Build a command line for use with W32's CreateProcess. On success - CMDLINE gets the address of a newly allocated string. */ -static gpg_error_t + * CMDLINE gets the address of a newly allocated string. */ +static gpg_err_code_t build_w32_commandline (const char *pgmname, const char * const *argv, char **cmdline) { @@ -229,7 +208,7 @@ build_w32_commandline (const char *pgmname, const char * const *argv, buf = p = xtrymalloc (n); if (!buf) - return my_error_from_syserror (); + return _gpg_err_code_from_syserror (); p = build_w32_commandline_copy (p, pgmname); for (i=0; argv[i]; i++) @@ -274,7 +253,8 @@ create_inheritable_pipe (HANDLE filedes[2], int flags) return 0; fail: - log_error ("SetHandleInformation failed: %s\n", w32_strerror (-1)); + _gpgrt_log_error ("SetHandleInformation failed: ec=%d\n", + (int)GetLastError ()); CloseHandle (r); CloseHandle (w); return -1; @@ -291,27 +271,35 @@ w32_open_null (int for_write) FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); if (hfile == INVALID_HANDLE_VALUE) - log_debug ("can't open 'nul': %s\n", w32_strerror (-1)); + _gpgrt_log_debug ("can't open 'nul': ec=%d\n", (int)GetLastError ()); return hfile; } -static gpg_error_t -create_pipe_and_estream (int filedes[2], int flags, - estream_t *r_fp, int outbound, int nonblock) +static gpg_err_code_t +do_create_pipe_and_estream (int filedes[2], + estream_t *r_fp, int direction, int nonblock) { - gpg_error_t err = 0; + gpg_err_code_t err = 0; + int flags; HANDLE fds[2]; - es_syshd_t syshd; + gpgrt_syshd_t syshd; + + if (direction < 0) + flags = INHERIT_WRITE; + else if (direction > 0) + flags = INHERIT_READ; + else + flags = INHERIT_BOTH; filedes[0] = filedes[1] = -1; - err = my_error (GPG_ERR_GENERAL); + err = GPG_ERR_GENERAL; if (!create_inheritable_pipe (fds, flags)) { filedes[0] = _open_osfhandle (handle_to_fd (fds[0]), O_RDONLY); if (filedes[0] == -1) { - log_error ("failed to translate osfhandle %p\n", fds[0]); + _gpgrt_log_error ("failed to translate osfhandle %p\n", fds[0]); CloseHandle (fds[1]); } else @@ -319,7 +307,7 @@ create_pipe_and_estream (int filedes[2], int flags, filedes[1] = _open_osfhandle (handle_to_fd (fds[1]), O_APPEND); if (filedes[1] == -1) { - log_error ("failed to translate osfhandle %p\n", fds[1]); + _gpgrt_log_error ("failed to translate osfhandle %p\n", fds[1]); close (filedes[0]); filedes[0] = -1; CloseHandle (fds[1]); @@ -332,21 +320,21 @@ create_pipe_and_estream (int filedes[2], int flags, if (! err && r_fp) { syshd.type = ES_SYSHD_HANDLE; - if (!outbound) + if (direction < 0) { syshd.u.handle = fds[0]; - *r_fp = es_sysopen (&syshd, nonblock? "r,nonblock" : "r"); + *r_fp = _gpgrt_sysopen (&syshd, nonblock? "r,nonblock" : "r"); } else { syshd.u.handle = fds[1]; - *r_fp = es_sysopen (&syshd, nonblock? "w,nonblock" : "w"); + *r_fp = _gpgrt_sysopen (&syshd, nonblock? "w,nonblock" : "w"); } if (!*r_fp) { - err = my_error_from_syserror (); - log_error (_("error creating a stream for a pipe: %s\n"), - gpg_strerror (err)); + err = _gpg_err_code_from_syserror (); + _gpgrt_log_error (_("error creating a stream for a pipe: %s\n"), + _gpg_strerror (err)); close (filedes[0]); close (filedes[1]); filedes[0] = filedes[1] = -1; @@ -357,48 +345,30 @@ create_pipe_and_estream (int filedes[2], int flags, return err; } -/* Portable function to create a pipe. Under Windows the write end is - inheritable. If R_FP is not NULL, an estream is created for the - read end and stored at R_FP. */ -gpg_error_t -gnupg_create_inbound_pipe (int filedes[2], estream_t *r_fp, int nonblock) -{ - return create_pipe_and_estream (filedes, INHERIT_WRITE, - r_fp, 0, nonblock); -} - -/* Portable function to create a pipe. Under Windows the read end is - inheritable. If R_FP is not NULL, an estream is created for the - write end and stored at R_FP. */ -gpg_error_t -gnupg_create_outbound_pipe (int filedes[2], estream_t *r_fp, int nonblock) +/* Create a pipe. The DIRECTION parameter gives the type of the created pipe: + * DIRECTION < 0 := Inbound pipe: On Windows the write end is inheritable. + * DIRECTION > 0 := Outbound pipe: On Windows the read end is inheritable. + * If R_FP is NULL a standard pipe and no stream is created, DIRECTION + * should then be 0. */ +gpg_err_code_t +_gpgrt_make_pipe (int filedes[2], estream_t *r_fp, int direction, int nonblock) { - return create_pipe_and_estream (filedes, INHERIT_READ, - r_fp, 1, nonblock); -} - - -/* Portable function to create a pipe. Under Windows both ends are - inheritable. */ -gpg_error_t -gnupg_create_pipe (int filedes[2]) -{ - return create_pipe_and_estream (filedes, INHERIT_BOTH, - NULL, 0, 0); + if (r_fp && direction) + return do_create_pipe_and_estream (filedes, r_fp, direction, nonblock); + else + return do_create_pipe_and_estream (filedes, NULL, 0, 0); } -/* Fork and exec the PGMNAME, see exechelp.h for details. */ -gpg_error_t -gnupg_spawn_process (const char *pgmname, const char *argv[], - int *except, void (*preexec)(void), unsigned int flags, - estream_t *r_infp, - estream_t *r_outfp, - estream_t *r_errfp, - pid_t *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, + estream_t *r_infp, estream_t *r_outfp, estream_t *r_errfp, + pid_t *pid) { - gpg_error_t err; + gpg_err_code_t err; SECURITY_ATTRIBUTES sec_attr; PROCESS_INFORMATION pi = { @@ -421,8 +391,7 @@ gnupg_spawn_process (const char *pgmname, const char *argv[], INVALID_HANDLE_VALUE}; int i; es_syshd_t syshd; - gpg_err_source_t errsource = default_errsource; - int nonblock = !!(flags & GNUPG_SPAWN_NONBLOCK); + int nonblock = !!(flags & GPGRT_SPAWN_NONBLOCK); (void)except; /* Not yet used. */ @@ -438,19 +407,20 @@ gnupg_spawn_process (const char *pgmname, const char *argv[], { if (create_inheritable_pipe (inpipe, INHERIT_READ)) { - err = gpg_err_make (errsource, GPG_ERR_GENERAL); - log_error (_("error creating a pipe: %s\n"), gpg_strerror (err)); + err = GPG_ERR_GENERAL; + _gpgrt_log_error (_("error creating a pipe: %s\n"), + _gpg_strerror (err)); return err; } syshd.type = ES_SYSHD_HANDLE; syshd.u.handle = inpipe[1]; - infp = es_sysopen (&syshd, nonblock? "w,nonblock" : "w"); + infp = _gpgrt_sysopen (&syshd, nonblock? "w,nonblock" : "w"); if (!infp) { - err = gpg_err_make (errsource, gpg_err_code_from_syserror ()); - log_error (_("error creating a stream for a pipe: %s\n"), - gpg_strerror (err)); + err = _gpg_err_code_from_syserror (); + _gpgrt_log_error (_("error creating a stream for a pipe: %s\n"), + _gpg_strerror (err)); CloseHandle (inpipe[0]); CloseHandle (inpipe[1]); inpipe[0] = inpipe[1] = INVALID_HANDLE_VALUE; @@ -462,24 +432,25 @@ gnupg_spawn_process (const char *pgmname, const char *argv[], { if (create_inheritable_pipe (outpipe, INHERIT_WRITE)) { - err = gpg_err_make (errsource, GPG_ERR_GENERAL); - log_error (_("error creating a pipe: %s\n"), gpg_strerror (err)); + err = GPG_ERR_GENERAL; + _gpgrt_log_error (_("error creating a pipe: %s\n"), + _gpg_strerror (err)); return err; } syshd.type = ES_SYSHD_HANDLE; syshd.u.handle = outpipe[0]; - outfp = es_sysopen (&syshd, nonblock? "r,nonblock" : "r"); + outfp = _gpgrt_sysopen (&syshd, nonblock? "r,nonblock" : "r"); if (!outfp) { - err = gpg_err_make (errsource, gpg_err_code_from_syserror ()); - log_error (_("error creating a stream for a pipe: %s\n"), - gpg_strerror (err)); + err = _gpg_err_code_from_syserror (); + _gpgrt_log_error (_("error creating a stream for a pipe: %s\n"), + _gpg_strerror (err)); CloseHandle (outpipe[0]); CloseHandle (outpipe[1]); outpipe[0] = outpipe[1] = INVALID_HANDLE_VALUE; if (infp) - es_fclose (infp); + _gpgrt_fclose (infp); else if (inpipe[1] != INVALID_HANDLE_VALUE) CloseHandle (inpipe[1]); if (inpipe[0] != INVALID_HANDLE_VALUE) @@ -492,30 +463,31 @@ gnupg_spawn_process (const char *pgmname, const char *argv[], { if (create_inheritable_pipe (errpipe, INHERIT_WRITE)) { - err = gpg_err_make (errsource, GPG_ERR_GENERAL); - log_error (_("error creating a pipe: %s\n"), gpg_strerror (err)); + err = GPG_ERR_GENERAL; + _gpgrt_log_error (_("error creating a pipe: %s\n"), + _gpg_strerror (err)); return err; } syshd.type = ES_SYSHD_HANDLE; syshd.u.handle = errpipe[0]; - errfp = es_sysopen (&syshd, nonblock? "r,nonblock" : "r"); + errfp = _gpgrt_sysopen (&syshd, nonblock? "r,nonblock" : "r"); if (!errfp) { - err = gpg_err_make (errsource, gpg_err_code_from_syserror ()); - log_error (_("error creating a stream for a pipe: %s\n"), - gpg_strerror (err)); + err = _gpg_err_code_from_syserror (); + _gpgrt_log_error (_("error creating a stream for a pipe: %s\n"), + _gpg_strerror (err)); CloseHandle (errpipe[0]); CloseHandle (errpipe[1]); errpipe[0] = errpipe[1] = INVALID_HANDLE_VALUE; if (outfp) - es_fclose (outfp); + _gpgrt_fclose (outfp); else if (outpipe[0] != INVALID_HANDLE_VALUE) CloseHandle (outpipe[0]); if (outpipe[1] != INVALID_HANDLE_VALUE) CloseHandle (outpipe[1]); if (infp) - es_fclose (infp); + _gpgrt_fclose (infp); else if (inpipe[1] != INVALID_HANDLE_VALUE) CloseHandle (inpipe[1]); if (inpipe[0] != INVALID_HANDLE_VALUE) @@ -554,10 +526,11 @@ gnupg_spawn_process (const char *pgmname, const char *argv[], si.hStdError = errpipe[1] == INVALID_HANDLE_VALUE? nullhd[2] : errpipe[1]; cr_flags = (CREATE_DEFAULT_ERROR_MODE - | ((flags & GNUPG_SPAWN_DETACHED)? DETACHED_PROCESS : 0) + | ((flags & GPGRT_SPAWN_DETACHED)? DETACHED_PROCESS : 0) | GetPriorityClass (GetCurrentProcess ()) | CREATE_SUSPENDED); -/* log_debug ("CreateProcess, path='%s' cmdline='%s'\n", pgmname, cmdline); */ + _gpgrt_log_debug ("CreateProcess, path='%s' cmdline='%s'\n", + pgmname, cmdline); if (!CreateProcess (pgmname, /* Program to start. */ cmdline, /* Command line arguments. */ &sec_attr, /* Process security attributes. */ @@ -570,27 +543,27 @@ gnupg_spawn_process (const char *pgmname, const char *argv[], &pi /* Returns process information. */ )) { - log_error ("CreateProcess failed: %s\n", w32_strerror (-1)); + _gpgrt_log_error ("CreateProcess failed: ec=%d\n", (int)GetLastError ()); xfree (cmdline); if (infp) - es_fclose (infp); + _gpgrt_fclose (infp); else if (inpipe[1] != INVALID_HANDLE_VALUE) CloseHandle (outpipe[1]); if (inpipe[0] != INVALID_HANDLE_VALUE) CloseHandle (inpipe[0]); if (outfp) - es_fclose (outfp); + _gpgrt_fclose (outfp); else if (outpipe[0] != INVALID_HANDLE_VALUE) CloseHandle (outpipe[0]); if (outpipe[1] != INVALID_HANDLE_VALUE) CloseHandle (outpipe[1]); if (errfp) - es_fclose (errfp); + _gpgrt_fclose (errfp); else if (errpipe[0] != INVALID_HANDLE_VALUE) CloseHandle (errpipe[0]); if (errpipe[1] != INVALID_HANDLE_VALUE) CloseHandle (errpipe[1]); - return gpg_err_make (errsource, GPG_ERR_GENERAL); + return GPG_ERR_GENERAL; } xfree (cmdline); cmdline = NULL; @@ -608,17 +581,21 @@ gnupg_spawn_process (const char *pgmname, const char *argv[], if (errpipe[1] != INVALID_HANDLE_VALUE) CloseHandle (errpipe[1]); - /* log_debug ("CreateProcess ready: hProcess=%p hThread=%p" */ - /* " dwProcessID=%d dwThreadId=%d\n", */ - /* pi.hProcess, pi.hThread, */ - /* (int) pi.dwProcessId, (int) pi.dwThreadId); */ - /* log_debug (" outfp=%p errfp=%p\n", outfp, errfp); */ + _gpgrt_log_debug ("CreateProcess ready: hProcess=%p hThread=%p" + " dwProcessID=%d dwThreadId=%d\n", + pi.hProcess, pi.hThread, + (int) pi.dwProcessId, (int) pi.dwThreadId); + _gpgrt_log_debug (" outfp=%p errfp=%p\n", outfp, errfp); - /* Fixme: For unknown reasons AllowSetForegroundWindow returns an - invalid argument error if we pass it the correct processID. As a - workaround we use -1 (ASFW_ANY). */ - if ((flags & GNUPG_SPAWN_RUN_ASFW)) - gnupg_allow_set_foregound_window ((pid_t)(-1)/*pi.dwProcessId*/); + if ((flags & GPGRT_SPAWN_RUN_ASFW)) + { + /* Fixme: For unknown reasons AllowSetForegroundWindow returns + * an invalid argument error if we pass it the correct + * processID. As a workaround we use -1 (ASFW_ANY). */ + if (!AllowSetForegroundWindow (ASFW_ANY /*pi.dwProcessId*/)) + _gpgrt_log_info ("AllowSetForegroundWindow() failed: ec=%d\n", + (int)GetLastError ()); + } /* Process has been created suspended; resume it now. */ ResumeThread (pi.hThread); @@ -633,24 +610,15 @@ gnupg_spawn_process (const char *pgmname, const char *argv[], *pid = handle_to_pid (pi.hProcess); return 0; - } - -/* Simplified version of gnupg_spawn_process. This function forks and - then execs PGMNAME, while connecting INFD to stdin, OUTFD to stdout - and ERRFD to stderr (any of them may be -1 to connect them to - /dev/null). The arguments for the process are expected in the NULL - terminated array ARGV. The program name itself should not be - included there. Calling gnupg_wait_process is required. - - Returns 0 on success or an error code. */ -gpg_error_t -gnupg_spawn_process_fd (const char *pgmname, const char *argv[], - int infd, int outfd, int errfd, pid_t *pid) +/* 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) { - gpg_error_t err; + gpg_err_code_t err; SECURITY_ATTRIBUTES sec_attr; PROCESS_INFORMATION pi = { NULL, 0, 0, 0 }; STARTUPINFO si; @@ -682,7 +650,8 @@ gnupg_spawn_process_fd (const char *pgmname, const char *argv[], si.hStdOutput = outfd == -1? stdhd[1] : (void*)_get_osfhandle (outfd); si.hStdError = errfd == -1? stdhd[2] : (void*)_get_osfhandle (errfd); -/* log_debug ("CreateProcess, path='%s' cmdline='%s'\n", pgmname, cmdline); */ + _gpgrt_log_debug ("CreateProcess, path='%s' cmdline='%s'\n", + pgmname, cmdline); if (!CreateProcess (pgmname, /* Program to start. */ cmdline, /* Command line arguments. */ &sec_attr, /* Process security attributes. */ @@ -697,22 +666,25 @@ gnupg_spawn_process_fd (const char *pgmname, const char *argv[], &pi /* Returns process information. */ )) { - log_error ("CreateProcess failed: %s\n", w32_strerror (-1)); - err = my_error (GPG_ERR_GENERAL); + _gpgrt_log_error ("CreateProcess failed: ec=%d\n", (int)GetLastError ()); + err = GPG_ERR_GENERAL; } else err = 0; + xfree (cmdline); + for (i=0; i < 3; i++) if (stdhd[i] != INVALID_HANDLE_VALUE) CloseHandle (stdhd[i]); + if (err) return err; -/* log_debug ("CreateProcess ready: hProcess=%p hThread=%p" */ -/* " dwProcessID=%d dwThreadId=%d\n", */ -/* pi.hProcess, pi.hThread, */ -/* (int) pi.dwProcessId, (int) pi.dwThreadId); */ + _gpgrt_log_debug ("CreateProcess ready: hProcess=%p hThread=%p" + " dwProcessID=%d dwThreadId=%d\n", + pi.hProcess, pi.hThread, + (int) pi.dwProcessId, (int) pi.dwThreadId); /* Process has been created suspended; resume it now. */ ResumeThread (pi.hThread); @@ -724,17 +696,18 @@ gnupg_spawn_process_fd (const char *pgmname, const char *argv[], } -/* See exechelp.h for a description. */ -gpg_error_t -gnupg_wait_process (const char *pgmname, pid_t pid, int hang, 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) { - return gnupg_wait_processes (&pgmname, &pid, 1, hang, r_exitcode); + return _gpgrt_wait_processes (&pgmname, &pid, 1, hang, r_exitcode); } -/* See exechelp.h for a description. */ -gpg_error_t -gnupg_wait_processes (const char **pgmnames, pid_t *pids, size_t count, - int hang, int *r_exitcodes) + +/* See gpgrt-int.h for a description. */ +gpg_err_code_t +_gpgrt_wait_processes (const char **pgmnames, pid_t *pids, size_t count, + int hang, int *r_exitcodes) { gpg_err_code_t ec = 0; size_t i; @@ -743,7 +716,7 @@ gnupg_wait_processes (const char **pgmnames, pid_t *pids, size_t count, procs = xtrycalloc (count, sizeof *procs); if (procs == NULL) - return my_error_from_syserror (); + return _gpg_err_code_from_syserror (); for (i = 0; i < count; i++) { @@ -751,14 +724,11 @@ gnupg_wait_processes (const char **pgmnames, pid_t *pids, size_t count, r_exitcodes[i] = -1; if (pids[i] == (pid_t)(-1)) - return my_error (GPG_ERR_INV_VALUE); + return GPG_ERR_INV_VALUE; procs[i] = fd_to_handle (pids[i]); } - /* FIXME: We should do a pth_waitpid here. However this has not yet - been implemented. A special W32 pth system call would even be - better. */ code = WaitForMultipleObjects (count, procs, TRUE, hang? INFINITE : 0); switch (code) { @@ -767,8 +737,8 @@ gnupg_wait_processes (const char **pgmnames, pid_t *pids, size_t count, goto leave; case WAIT_FAILED: - log_error (_("waiting for processes to terminate failed: %s\n"), - w32_strerror (-1)); + _gpgrt_log_error (_("waiting for processes to terminate failed: ec=%d\n"), + (int)GetLastError ()); ec = GPG_ERR_GENERAL; goto leave; @@ -779,15 +749,16 @@ gnupg_wait_processes (const char **pgmnames, pid_t *pids, size_t count, if (! GetExitCodeProcess (procs[i], &exc)) { - log_error (_("error getting exit code of process %d: %s\n"), - (int) pids[i], w32_strerror (-1) ); + _gpgrt_log_error (_("error getting exit code of process %d:" + " ec=%d\n"), + (int) pids[i], (int)GetLastError ()); ec = GPG_ERR_GENERAL; } else if (exc) { if (!r_exitcodes) - log_error (_("error running '%s': exit status %d\n"), - pgmnames[i], (int)exc); + _gpgrt_log_error (_("error running '%s': exit status %d\n"), + pgmnames[i], (int)exc); else r_exitcodes[i] = (int)exc; ec = GPG_ERR_GENERAL; @@ -801,42 +772,23 @@ gnupg_wait_processes (const char **pgmnames, pid_t *pids, size_t count, break; default: - log_error ("WaitForMultipleObjects returned unexpected " - "code %d\n", code); + _gpgrt_log_debug ("WaitForMultipleObjects returned unexpected code %d\n", + code); ec = GPG_ERR_GENERAL; break; } leave: - return gpg_err_make (GPG_ERR_SOURCE_DEFAULT, ec); -} - - - -void -gnupg_release_process (pid_t pid) -{ - if (pid != (pid_t)INVALID_HANDLE_VALUE) - { - HANDLE process = (HANDLE)pid; - - CloseHandle (process); - } + return ec; } -/* Spawn a new process and immediately detach from it. The name of - the program to exec is PGMNAME and its arguments are in ARGV (the - programname is automatically passed as first argument). - Environment strings in ENVP are set. An error is returned if - pgmname is not executable; to make this work it is necessary to - provide an absolute file name. All standard file descriptors are - connected to /dev/null. */ -gpg_error_t -gnupg_spawn_process_detached (const char *pgmname, const char *argv[], - const char *envp[] ) +/* See gpgrt-int.h for a description. */ +gpg_err_code_t +_gpgrt_spawn_process_detached (const char *pgmname, const char *argv[], + const char *envp[] ) { - gpg_error_t err; + gpg_err_code_t err; SECURITY_ATTRIBUTES sec_attr; PROCESS_INFORMATION pi = { @@ -849,12 +801,11 @@ gnupg_spawn_process_detached (const char *pgmname, const char *argv[], int cr_flags; char *cmdline; - /* We don't use ENVP. */ (void)envp; if (access (pgmname, X_OK)) - return my_error_from_syserror (); + return _gpg_err_code_from_syserror (); /* Prepare security attributes. */ memset (&sec_attr, 0, sizeof sec_attr ); @@ -876,8 +827,8 @@ gnupg_spawn_process_detached (const char *pgmname, const char *argv[], | GetPriorityClass (GetCurrentProcess ()) | CREATE_NEW_PROCESS_GROUP | DETACHED_PROCESS); -/* log_debug ("CreateProcess(detached), path='%s' cmdline='%s'\n", */ -/* pgmname, cmdline); */ + _gpgrt_log_debug ("CreateProcess(detached), path='%s' cmdline='%s'\n", + pgmname, cmdline); if (!CreateProcess (pgmname, /* Program to start. */ cmdline, /* Command line arguments. */ &sec_attr, /* Process security attributes. */ @@ -890,17 +841,18 @@ gnupg_spawn_process_detached (const char *pgmname, const char *argv[], &pi /* Returns process information. */ )) { - log_error ("CreateProcess(detached) failed: %s\n", w32_strerror (-1)); + _gpgrt_log_error ("CreateProcess(detached) failed: ec=%d\n", + (int)GetLastError ()); xfree (cmdline); - return my_error (GPG_ERR_GENERAL); + return GPG_ERR_GENERAL; } xfree (cmdline); cmdline = NULL; -/* log_debug ("CreateProcess(detached) ready: hProcess=%p hThread=%p" */ -/* " dwProcessID=%d dwThreadId=%d\n", */ -/* pi.hProcess, pi.hThread, */ -/* (int) pi.dwProcessId, (int) pi.dwThreadId); */ + _gpgrt_log_debug ("CreateProcess(detached) ready: hProcess=%p hThread=%p" + " dwProcessID=%d dwThreadId=%d\n", + pi.hProcess, pi.hThread, + (int) pi.dwProcessId, (int) pi.dwThreadId); CloseHandle (pi.hThread); CloseHandle (pi.hProcess); @@ -913,7 +865,7 @@ gnupg_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 -gnupg_kill_process (pid_t pid) +_gpgrt_kill_process (pid_t pid) { if (pid != (pid_t) INVALID_HANDLE_VALUE) { @@ -923,3 +875,15 @@ gnupg_kill_process (pid_t pid) TerminateProcess (process, 1); } } + + +void +_gpgrt_release_process (pid_t pid) +{ + if (pid != (pid_t)INVALID_HANDLE_VALUE) + { + HANDLE process = (HANDLE)pid; + + CloseHandle (process); + } +} diff --git a/src/visibility.c b/src/visibility.c index 0f6d159..fb187a5 100644 --- a/src/visibility.c +++ b/src/visibility.c @@ -1008,8 +1008,61 @@ _gpgrt_log_assert (const char *expr, const char *file, #endif } + +gpg_err_code_t +gpgrt_make_pipe (int filedes[2], estream_t *r_fp, int direction, int nonblock) +{ + return _gpgrt_make_pipe (filedes, r_fp, direction, nonblock); +} + +gpg_err_code_t +gpgrt_spawn_process (const char *pgmname, const char *argv[], + int *except, void (*preexec)(void), unsigned int flags, + estream_t *r_infp, estream_t *r_outfp, estream_t *r_errfp, + pid_t *pid) +{ + return _gpgrt_spawn_process (pgmname, argv, except, preexec, flags, + r_infp, r_outfp, r_errfp, pid); +} + +gpg_err_code_t +gpgrt_spawn_process_fd (const char *pgmname, const char *argv[], + int infd, int outfd, int errfd, pid_t *pid) +{ + return _gpgrt_spawn_process_fd (pgmname, argv, infd, outfd, errfd, pid); +} + +gpg_err_code_t +gpgrt_spawn_process_detached (const char *pgmname, const char *argv[], + const char *envp[]) +{ + return _gpgrt_spawn_process_detached (pgmname, argv, envp); +} + +gpg_err_code_t +gpgrt_wait_process (const char *pgmname, pid_t pid, int hang, int *r_exitcode) +{ + return _gpgrt_wait_process (pgmname, pid, hang, r_exitcode); +} +gpg_err_code_t +gpgrt_wait_processes (const char **pgmnames, pid_t *pids, + size_t count, int hang, int *r_exitcodes) +{ + return _gpgrt_wait_processes (pgmnames, pids, count, hang, r_exitcodes); +} +void +gpgrt_kill_process (pid_t pid) +{ + _gpgrt_kill_process (pid); +} + +void +gpgrt_release_process (pid_t pid) +{ + _gpgrt_release_process (pid); +} diff --git a/src/visibility.h b/src/visibility.h index 3209c23..b33744d 100644 --- a/src/visibility.h +++ b/src/visibility.h @@ -188,6 +188,16 @@ MARK_VISIBLE (gpgrt_log_clock) MARK_VISIBLE (gpgrt_log_flush) MARK_VISIBLE (_gpgrt_log_assert) +MARK_VISIBLE (gpgrt_make_pipe) +MARK_VISIBLE (gpgrt_spawn_process) +MARK_VISIBLE (gpgrt_spawn_process_fd) +MARK_VISIBLE (gpgrt_spawn_process_detached) +MARK_VISIBLE (gpgrt_wait_process) +MARK_VISIBLE (gpgrt_wait_processes) +MARK_VISIBLE (gpgrt_kill_process) +MARK_VISIBLE (gpgrt_release_process) + + #undef MARK_VISIBLE #else /*!_GPGRT_INCL_BY_VISIBILITY_C*/ @@ -339,6 +349,15 @@ MARK_VISIBLE (_gpgrt_log_assert) #define gpgrt_log_flush _gpgrt_USE_UNDERSCORED_FUNCTION #define _gpgrt_log_assert _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_make_pipe _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_spawn_process _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_spawn_process_fd _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_spawn_process_detached _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_wait_process _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_wait_processes _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_kill_process _gpgrt_USE_UNDERSCORED_FUNCTION +#define gpgrt_release_process _gpgrt_USE_UNDERSCORED_FUNCTION + /* Windows specific functions. */ #define gpgrt_w32_reg_query_string _gpgrt_USE_UNDERSCORED_FUNCTION diff --git a/src/w32-add.h b/src/w32-add.h index 07e3c7d..6f9f12a 100644 --- a/src/w32-add.h +++ b/src/w32-add.h @@ -3,6 +3,10 @@ ## peculiarity of the script the first used line must not ## start with a hash mark. +/* Fixme: This is a quick hack. We need to check whether the compiler + * actually in use already knows that type. */ +typedef int pid_t; + /* Decide whether to use the format_arg attribute. */ #if _GPG_ERR_GCC_VERSION > 20800 # define _GPG_ERR_ATTR_FORMAT_ARG(a) __attribute__ ((__format_arg__ (a))) |