aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWerner Koch <[email protected]>2017-11-29 18:29:18 +0000
committerWerner Koch <[email protected]>2017-11-29 18:29:18 +0000
commit1865c0ba1769b407a3c504f1ab0a4278704a9fc1 (patch)
treeeb98697911bda0270e4aee8de308017642db8979
parentImport and relicense exechelp* functions from GnuPG. (diff)
downloadlibgpg-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.ac8
-rw-r--r--gpgscm/ffi.c14
-rw-r--r--src/Makefile.am4
-rw-r--r--src/gpg-error.def.in9
-rw-r--r--src/gpg-error.h.in51
-rw-r--r--src/gpg-error.vers10
-rw-r--r--src/gpgrt-int.h110
-rw-r--r--src/spawn-posix.c393
-rw-r--r--src/spawn-w32.c402
-rw-r--r--src/visibility.c53
-rw-r--r--src/visibility.h19
-rw-r--r--src/w32-add.h4
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)))