summaryrefslogtreecommitdiffstats
path: root/common
diff options
context:
space:
mode:
authorWerner Koch <wk@gnupg.org>2010-08-20 14:18:38 +0200
committerWerner Koch <wk@gnupg.org>2010-08-20 14:18:38 +0200
commit15330f36a72a98db06e7e3e8ea2204645a5c470b (patch)
tree53a98514afe9a0f654fffdc0d2cf966ced285d06 /common
parentPrepare for gpg-error change (diff)
downloadgnupg2-15330f36a72a98db06e7e3e8ea2204645a5c470b.tar.xz
gnupg2-15330f36a72a98db06e7e3e8ea2204645a5c470b.zip
Reworked the posix and w32 exechelpers.
Diffstat (limited to 'common')
-rw-r--r--common/ChangeLog28
-rw-r--r--common/estream.c471
-rw-r--r--common/estream.h29
-rw-r--r--common/exechelp-posix.c140
-rw-r--r--common/exechelp-w32.c221
-rw-r--r--common/exechelp-w32ce.c14
-rw-r--r--common/exechelp.h39
7 files changed, 776 insertions, 166 deletions
diff --git a/common/ChangeLog b/common/ChangeLog
index f53a19293..1fdd7de5d 100644
--- a/common/ChangeLog
+++ b/common/ChangeLog
@@ -1,3 +1,31 @@
+2010-08-20 Werner Koch <wk@g10code.com>
+
+ * exechelp-w32.c (create_inheritable_pipe): Change arg to HANDLE.
+
+ * estream.h (es_sysopen_t): New.
+ * estream.c (es_func_w32_create, es_func_w32_read)
+ (es_func_w32_write, es_func_w32_seek, es_func_w32_destroy)
+ (estream_functions_w32, estream_cookie_fd): New. Only for W32.
+ (es_sysopen, es_sysopen_nc): New.
+ (do_w32open, do_sysopen): New.
+ (es_syshd, es_syshd_unlocked): New.
+ (struct estream_internal): Replace filed FD by SYSHD.
+ (es_initialize): Clear SYSHD_VALID.
+ (map_w32_to_errno): New.
+ (es_get_fd): Remove.
+ (es_fileno_unlocked): Re-implement using es_syshd.
+ (es_initialize, es_create): Replace arg FD by SYSHD.
+ (es_fopen, es_mopen, es_fopenmem, do_fdopen, do_fpopen)
+ (es_tmpfile): Use SYSHD instead of FD.
+ (es_destroy): Rename to do_close.
+
+2010-08-19 Werner Koch <wk@g10code.com>
+
+ * exechelp-posix.c (create_pipe_and_estream): New.
+ (gnupg_spawn_process): Rework this function and its calling
+ convention; it is not used anyway.
+ * exechelp-w32.c (gnupg_spawn_process): Ditto.
+
2010-08-18 Werner Koch <wk@g10code.com>
* logging.c (writen): Add arg IS_SOCKET.
diff --git a/common/estream.c b/common/estream.c
index ea5d4d00f..00f40d24d 100644
--- a/common/estream.c
+++ b/common/estream.c
@@ -126,9 +126,9 @@ int _setmode (int handle, int mode);
#endif
#ifdef HAVE_W32_SYSTEM
-# define IS_INVALID_FD(a) ((void*)(a) == (void*)(-1))
+# define IS_INVALID_FD(a) ((void*)(a) == (void*)(-1)) /* ?? FIXME. */
#else
-# define IS_INVALID_FD(a) ((a) == -1)
+# define IS_INVALID_FD(a) ((a) == -1)
#endif
@@ -197,6 +197,7 @@ dummy_mutex_call_int (estream_mutex_t mutex)
# define ESTREAM_SYS_YIELD() do { } while (0)
#endif
+
/* Misc definitions. */
#define ES_DEFAULT_OPEN_MODE (S_IRUSR | S_IWUSR)
@@ -218,7 +219,7 @@ struct estream_internal
es_cookie_seek_function_t func_seek;
es_cookie_close_function_t func_close;
int strategy;
- int fd; /* Value to return by es_fileno(). */
+ es_syshd_t syshd; /* A copy of the sytem handle. */
struct
{
unsigned int err: 1;
@@ -317,7 +318,39 @@ mem_free (void *p)
free (p);
}
+#ifdef HAVE_W32_SYSTEM
+static int
+map_w32_to_errno (DWORD w32_err)
+{
+ switch (w32_err)
+ {
+ case 0:
+ return 0;
+
+ case ERROR_FILE_NOT_FOUND:
+ return ENOENT;
+
+ case ERROR_PATH_NOT_FOUND:
+ return ENOENT;
+
+ case ERROR_ACCESS_DENIED:
+ return EPERM;
+ case ERROR_INVALID_HANDLE:
+ case ERROR_INVALID_BLOCK:
+ return EINVAL;
+
+ case ERROR_NOT_ENOUGH_MEMORY:
+ return ENOMEM;
+
+ case ERROR_NO_DATA:
+ return EPIPE;
+
+ default:
+ return EIO;
+ }
+}
+#endif /*HAVE_W32_SYSTEM*/
/*
* List manipulation.
@@ -744,7 +777,7 @@ static es_cookie_io_functions_t estream_functions_mem =
-/* Implementation of fd I/O. */
+/* Implementation of file descriptor based I/O. */
/* Cookie for fd objects. */
typedef struct estream_cookie_fd
@@ -887,6 +920,217 @@ static es_cookie_io_functions_t estream_functions_fd =
+#ifdef HAVE_W32_SYSTEM
+/* Implementation of W32 handle based I/O. */
+
+/* Cookie for fd objects. */
+typedef struct estream_cookie_w32
+{
+ HANDLE hd; /* The handle we are using for actual output. */
+ int no_close; /* If set we won't close the handle. */
+} *estream_cookie_w32_t;
+
+
+/* Create function for w32 handle objects. */
+static int
+es_func_w32_create (void **cookie, HANDLE hd,
+ unsigned int modeflags, int no_close)
+{
+ estream_cookie_w32_t w32_cookie;
+ int err;
+
+ w32_cookie = mem_alloc (sizeof (*w32_cookie));
+ if (!w32_cookie)
+ err = -1;
+ else
+ {
+ /* CR/LF translations are not supported when using the bare W32
+ API. If that is really required we need to implemented that
+ in the upper layer. */
+ (void)modeflags;
+
+ w32_cookie->hd = hd;
+ w32_cookie->no_close = no_close;
+ *cookie = w32_cookie;
+ err = 0;
+ }
+
+ return err;
+}
+
+/* Read function for W32 handle objects. */
+static ssize_t
+es_func_w32_read (void *cookie, void *buffer, size_t size)
+{
+ estream_cookie_w32_t w32_cookie = cookie;
+ ssize_t bytes_read;
+
+ if (w32_cookie->hd == INVALID_HANDLE_VALUE)
+ {
+ ESTREAM_SYS_YIELD ();
+ bytes_read = 0;
+ }
+ else
+ {
+ do
+ {
+#ifdef HAVE_PTH
+ /* Note: Our pth_read actually uses HANDLE! */
+ bytes_read = pth_read ((int)w32_cookie->hd, buffer, size);
+#else
+ DWORD nread, ec;
+
+ if (!ReadFile (w32_cookie->hd, buffer, size, &nread, NULL))
+ {
+ ec = GetLastError ();
+ if (ec == ERROR_BROKEN_PIPE)
+ bytes_read = 0; /* Like our pth_read we handle this as EOF. */
+ else
+ {
+ _set_errno (map_w32_to_errno (ec));
+ log_debug ("estream: ReadFile returned %d\n",
+ (int)GetLastError ());
+ bytes_read = -1;
+ }
+ }
+ else
+ bytes_read = (int)nread;
+#endif
+ }
+ while (bytes_read == -1 && errno == EINTR);
+ }
+
+ return bytes_read;
+}
+
+/* Write function for W32 handle objects. */
+static ssize_t
+es_func_w32_write (void *cookie, const void *buffer, size_t size)
+{
+ estream_cookie_w32_t w32_cookie = cookie;
+ ssize_t bytes_written;
+
+ if (w32_cookie->hd == INVALID_HANDLE_VALUE)
+ {
+ ESTREAM_SYS_YIELD ();
+ bytes_written = size; /* Yeah: Success writing to the bit bucket. */
+ }
+ else
+ {
+ do
+ {
+#ifdef HAVE_PTH
+ /* Note: Our pth_write actually uses HANDLE! */
+ bytes_written = pth_write ((int)w32_cookie->hd, buffer, size);
+#else
+ DWORD nwritten;
+
+ if (!WriteFile (w32_cookie->hd, buffer, size, &nwritten, NULL))
+ {
+ _set_errno (map_w32_to_errno (GetLastError ()));
+ bytes_written = -1;
+ }
+ else
+ bytes_written = (int)nwritten;
+#endif
+ }
+ while (bytes_written == -1 && errno == EINTR);
+ }
+
+ return bytes_written;
+}
+
+/* Seek function for W32 handle objects. */
+static int
+es_func_w32_seek (void *cookie, off_t *offset, int whence)
+{
+ estream_cookie_w32_t w32_cookie = cookie;
+ DWORD method;
+ LARGE_INTEGER distance, newoff;
+
+ if (w32_cookie->hd == INVALID_HANDLE_VALUE)
+ {
+ _set_errno (ESPIPE);
+ return -1;
+ }
+
+ if (whence == SEEK_SET)
+ {
+ method = FILE_BEGIN;
+ distance.QuadPart = (unsigned long long)(*offset);
+ }
+ else if (whence == SEEK_CUR)
+ {
+ method = FILE_CURRENT;
+ distance.QuadPart = (long long)(*offset);
+ }
+ else if (whence == SEEK_END)
+ {
+ method = FILE_END;
+ distance.QuadPart = (long long)(*offset);
+ }
+ else
+ {
+ _set_errno (EINVAL);
+ return -1;
+ }
+#ifdef HAVE_W32CE_SYSTEM
+# warning need to use SetFilePointer
+#else
+ if (!SetFilePointerEx (w32_cookie->hd, distance, &newoff, method))
+ {
+ _set_errno (map_w32_to_errno (GetLastError ()));
+ return -1;
+ }
+#endif
+ *offset = (unsigned long long)newoff.QuadPart;
+ return 0;
+}
+
+/* Destroy function for W32 handle objects. */
+static int
+es_func_w32_destroy (void *cookie)
+{
+ estream_cookie_w32_t w32_cookie = cookie;
+ int err;
+
+ if (w32_cookie)
+ {
+ if (w32_cookie->hd == INVALID_HANDLE_VALUE)
+ err = 0;
+ else if (w32_cookie->no_close)
+ err = 0;
+ else
+ {
+ if (!CloseHandle (w32_cookie->hd))
+ {
+ _set_errno (map_w32_to_errno (GetLastError ()));
+ err = -1;
+ }
+ else
+ err = 0;
+ }
+ mem_free (w32_cookie);
+ }
+ else
+ err = 0;
+
+ return err;
+}
+
+
+static es_cookie_io_functions_t estream_functions_w32 =
+ {
+ es_func_w32_read,
+ es_func_w32_write,
+ es_func_w32_seek,
+ es_func_w32_destroy
+ };
+#endif /*HAVE_W32_SYSTEM*/
+
+
+
+
/* Implementation of FILE* I/O. */
/* Cookie for fp objects. */
@@ -1049,7 +1293,7 @@ static es_cookie_io_functions_t estream_functions_fp =
/* Implementation of file I/O. */
-/* Create function for file objects. */
+/* Create function for fd objects. */
static int
es_func_file_create (void **cookie, int *filedes,
const char *path, unsigned int modeflags)
@@ -1269,7 +1513,8 @@ es_empty (estream_t stream)
/* Initialize STREAM. */
static void
es_initialize (estream_t stream,
- void *cookie, int fd, es_cookie_io_functions_t functions,
+ void *cookie, es_syshd_t *syshd,
+ es_cookie_io_functions_t functions,
unsigned int modeflags)
{
stream->intern->cookie = cookie;
@@ -1280,7 +1525,7 @@ es_initialize (estream_t stream,
stream->intern->func_seek = functions.func_seek;
stream->intern->func_close = functions.func_close;
stream->intern->strategy = _IOFBF;
- stream->intern->fd = fd;
+ stream->intern->syshd = *syshd;
stream->intern->print_ntotal = 0;
stream->intern->indicators.err = 0;
stream->intern->indicators.eof = 0;
@@ -1329,7 +1574,7 @@ es_deinitialize (estream_t stream)
/* Create a new stream object, initialize it. */
static int
-es_create (estream_t *stream, void *cookie, int fd,
+es_create (estream_t *stream, void *cookie, es_syshd_t *syshd,
es_cookie_io_functions_t functions, unsigned int modeflags,
int with_locked_list)
{
@@ -1361,7 +1606,7 @@ es_create (estream_t *stream, void *cookie, int fd,
stream_new->intern = stream_internal_new;
ESTREAM_MUTEX_INITIALIZE (stream_new->intern->lock);
- es_initialize (stream_new, cookie, fd, functions, modeflags);
+ es_initialize (stream_new, cookie, syshd, functions, modeflags);
err = es_list_add (stream_new, with_locked_list);
if (err)
@@ -1385,9 +1630,9 @@ es_create (estream_t *stream, void *cookie, int fd,
/* Deinitialize a stream object and destroy it. */
static int
-es_destroy (estream_t stream, int with_locked_list)
+do_close (estream_t stream, int with_locked_list)
{
- int err = 0;
+ int err;
if (stream)
{
@@ -1396,6 +1641,8 @@ es_destroy (estream_t stream, int with_locked_list)
mem_free (stream->intern);
mem_free (stream);
}
+ else
+ err = 0;
return err;
}
@@ -1897,6 +2144,7 @@ doreadline (estream_t ES__RESTRICT stream, size_t max_length,
unsigned char *data;
size_t data_len;
int err;
+ es_syshd_t syshd;
line_new = NULL;
line_stream = NULL;
@@ -1910,7 +2158,8 @@ doreadline (estream_t ES__RESTRICT stream, size_t max_length,
if (err)
goto out;
- err = es_create (&line_stream, line_stream_cookie, -1,
+ memset (&syshd, 0, sizeof syshd);
+ err = es_create (&line_stream, line_stream_cookie, &syshd,
estream_functions_mem, O_RDWR, 0);
if (err)
goto out;
@@ -1996,7 +2245,7 @@ doreadline (estream_t ES__RESTRICT stream, size_t max_length,
out:
if (line_stream)
- es_destroy (line_stream, 0);
+ do_close (line_stream, 0);
else if (line_stream_cookie)
es_func_mem_destroy (line_stream_cookie);
@@ -2152,12 +2401,6 @@ es_opaque_ctrl (estream_t ES__RESTRICT stream, void *ES__RESTRICT opaque_new,
}
-static int
-es_get_fd (estream_t stream)
-{
- return stream->intern->fd;
-}
-
/* API. */
@@ -2172,6 +2415,8 @@ es_init (void)
return err;
}
+
+
estream_t
es_fopen (const char *ES__RESTRICT path, const char *ES__RESTRICT mode)
{
@@ -2181,6 +2426,7 @@ es_fopen (const char *ES__RESTRICT path, const char *ES__RESTRICT mode)
void *cookie;
int err;
int fd;
+ es_syshd_t syshd;
stream = NULL;
cookie = NULL;
@@ -2193,9 +2439,12 @@ es_fopen (const char *ES__RESTRICT path, const char *ES__RESTRICT mode)
err = es_func_file_create (&cookie, &fd, path, modeflags);
if (err)
goto out;
+
+ syshd.type = ES_SYSHD_FD;
+ syshd.u.fd = fd;
create_called = 1;
- err = es_create (&stream, cookie, fd, estream_functions_fd, modeflags, 0);
+ err = es_create (&stream, cookie, &syshd, estream_functions_fd, modeflags, 0);
if (err)
goto out;
@@ -2211,6 +2460,7 @@ es_fopen (const char *ES__RESTRICT path, const char *ES__RESTRICT mode)
}
+
estream_t
es_mopen (unsigned char *ES__RESTRICT data, size_t data_n, size_t data_len,
unsigned int grow,
@@ -2222,6 +2472,7 @@ es_mopen (unsigned char *ES__RESTRICT data, size_t data_n, size_t data_len,
estream_t stream;
void *cookie;
int err;
+ es_syshd_t syshd;
cookie = 0;
stream = NULL;
@@ -2237,8 +2488,10 @@ es_mopen (unsigned char *ES__RESTRICT data, size_t data_n, size_t data_len,
if (err)
goto out;
+ memset (&syshd, 0, sizeof syshd);
create_called = 1;
- err = es_create (&stream, cookie, -1, estream_functions_mem, modeflags, 0);
+ err = es_create (&stream, cookie, &syshd,
+ estream_functions_mem, modeflags, 0);
out:
@@ -2249,12 +2502,14 @@ es_mopen (unsigned char *ES__RESTRICT data, size_t data_n, size_t data_len,
}
+
estream_t
es_fopenmem (size_t memlimit, const char *ES__RESTRICT mode)
{
unsigned int modeflags;
estream_t stream = NULL;
void *cookie = NULL;
+ es_syshd_t syshd;
/* Memory streams are always read/write. We use MODE only to get
the append flag. */
@@ -2269,14 +2524,15 @@ es_fopenmem (size_t memlimit, const char *ES__RESTRICT mode)
memlimit))
return NULL;
- if (es_create (&stream, cookie, -1, estream_functions_mem, modeflags, 0))
+ memset (&syshd, 0, sizeof syshd);
+ if (es_create (&stream, cookie, &syshd, estream_functions_mem, modeflags, 0))
(*estream_functions_mem.func_close) (cookie);
return stream;
}
-
+
estream_t
es_fopencookie (void *ES__RESTRICT cookie,
const char *ES__RESTRICT mode,
@@ -2285,6 +2541,7 @@ es_fopencookie (void *ES__RESTRICT cookie,
unsigned int modeflags;
estream_t stream;
int err;
+ es_syshd_t syshd;
stream = NULL;
modeflags = 0;
@@ -2293,16 +2550,17 @@ es_fopencookie (void *ES__RESTRICT cookie,
if (err)
goto out;
- err = es_create (&stream, cookie, -1, functions, modeflags, 0);
+ memset (&syshd, 0, sizeof syshd);
+ err = es_create (&stream, cookie, &syshd, functions, modeflags, 0);
if (err)
goto out;
out:
-
return stream;
}
+
estream_t
do_fdopen (int filedes, const char *mode, int no_close, int with_locked_list)
{
@@ -2311,6 +2569,7 @@ do_fdopen (int filedes, const char *mode, int no_close, int with_locked_list)
estream_t stream;
void *cookie;
int err;
+ es_syshd_t syshd;
stream = NULL;
cookie = NULL;
@@ -2324,12 +2583,13 @@ do_fdopen (int filedes, const char *mode, int no_close, int with_locked_list)
if (err)
goto out;
+ syshd.type = ES_SYSHD_FD;
+ syshd.u.fd = filedes;
create_called = 1;
- err = es_create (&stream, cookie, filedes, estream_functions_fd,
+ err = es_create (&stream, cookie, &syshd, estream_functions_fd,
modeflags, with_locked_list);
out:
-
if (err && create_called)
(*estream_functions_fd.func_close) (cookie);
@@ -2350,6 +2610,7 @@ es_fdopen_nc (int filedes, const char *mode)
}
+
estream_t
do_fpopen (FILE *fp, const char *mode, int no_close, int with_locked_list)
{
@@ -2358,6 +2619,7 @@ do_fpopen (FILE *fp, const char *mode, int no_close, int with_locked_list)
estream_t stream;
void *cookie;
int err;
+ es_syshd_t syshd;
stream = NULL;
cookie = NULL;
@@ -2372,9 +2634,11 @@ do_fpopen (FILE *fp, const char *mode, int no_close, int with_locked_list)
err = es_func_fp_create (&cookie, fp, modeflags, no_close);
if (err)
goto out;
-
+
+ syshd.type = ES_SYSHD_FD;
+ syshd.u.fd = fp? fileno (fp): -1;
create_called = 1;
- err = es_create (&stream, cookie, fp? fileno (fp):-1, estream_functions_fp,
+ err = es_create (&stream, cookie, &syshd, estream_functions_fp,
modeflags, with_locked_list);
out:
@@ -2409,6 +2673,87 @@ es_fpopen_nc (FILE *fp, const char *mode)
}
+
+#ifdef HAVE_W32_SYSTEM
+estream_t
+do_w32open (HANDLE hd, const char *mode,
+ int no_close, int with_locked_list)
+{
+ unsigned int modeflags;
+ int create_called = 0;
+ estream_t stream = NULL;
+ void *cookie = NULL;
+ int err;
+ es_syshd_t syshd;
+
+ err = es_convert_mode (mode, &modeflags);
+ if (err)
+ goto leave;
+
+ err = es_func_w32_create (&cookie, hd, modeflags, no_close);
+ if (err)
+ goto leave;
+
+ syshd.type = ES_SYSHD_HANDLE;
+ syshd.u.handle = hd;
+ create_called = 1;
+ err = es_create (&stream, cookie, &syshd, estream_functions_w32,
+ modeflags, with_locked_list);
+
+ leave:
+ if (err && create_called)
+ (*estream_functions_w32.func_close) (cookie);
+
+ return stream;
+}
+#endif /*HAVE_W32_SYSTEM*/
+
+static estream_t
+do_sysopen (es_syshd_t *syshd, const char *mode, int no_close)
+{
+ estream_t stream;
+
+ switch (syshd->type)
+ {
+ case ES_SYSHD_FD:
+ case ES_SYSHD_SOCK:
+ stream = do_fdopen (syshd->u.fd, mode, no_close, 0);
+ break;
+
+#ifdef HAVE_W32_SYSTEM
+ case ES_SYSHD_HANDLE:
+ stream = do_w32open (syshd->u.handle, mode, no_close, 0);
+ break;
+#endif
+
+ /* FIXME: Support RVIDs under Wince? */
+
+ default:
+ _set_errno (EINVAL);
+ stream = NULL;
+ }
+ return stream;
+}
+
+/* On POSIX systems this function is an alias for es_fdopen. Under
+ Windows it uses the bare W32 API and thus a HANDLE instead of a
+ file descriptor. */
+estream_t
+es_sysopen (es_syshd_t *syshd, const char *mode)
+{
+ return do_sysopen (syshd, mode, 0);
+}
+
+/* Same as es_sysopen but the handle/fd will not be closed by
+ es_fclose. */
+estream_t
+es_sysopen_nc (es_syshd_t *syshd, const char *mode)
+{
+ return do_sysopen (syshd, mode, 1);
+}
+
+
+
/* Set custom standard descriptors to be used for stdin, stdout and
stderr. This function needs to be called before any of the
standard streams are accessed. */
@@ -2500,6 +2845,7 @@ es_freopen (const char *ES__RESTRICT path, const char *ES__RESTRICT mode,
int create_called;
void *cookie;
int fd;
+ es_syshd_t syshd;
cookie = NULL;
create_called = 0;
@@ -2516,8 +2862,10 @@ es_freopen (const char *ES__RESTRICT path, const char *ES__RESTRICT mode,
if (err)
goto leave;
+ syshd.type = ES_SYSHD_FD;
+ syshd.u.fd = fd;
create_called = 1;
- es_initialize (stream, cookie, fd, estream_functions_fd, modeflags);
+ es_initialize (stream, cookie, &syshd, estream_functions_fd, modeflags);
leave:
@@ -2526,7 +2874,7 @@ es_freopen (const char *ES__RESTRICT path, const char *ES__RESTRICT mode,
if (create_called)
es_func_fd_destroy (cookie);
- es_destroy (stream, 0);
+ do_close (stream, 0);
stream = NULL;
}
else
@@ -2541,7 +2889,7 @@ es_freopen (const char *ES__RESTRICT path, const char *ES__RESTRICT mode,
/* FIXME? We don't support re-opening at the moment. */
_set_errno (EINVAL);
es_deinitialize (stream);
- es_destroy (stream, 0);
+ do_close (stream, 0);
stream = NULL;
}
@@ -2554,15 +2902,47 @@ es_fclose (estream_t stream)
{
int err;
- err = es_destroy (stream, 0);
+ err = do_close (stream, 0);
return err;
}
+
int
es_fileno_unlocked (estream_t stream)
{
- return es_get_fd (stream);
+ es_syshd_t syshd;
+
+ if (es_syshd (stream, &syshd))
+ return -1;
+ switch (syshd.type)
+ {
+ case ES_SYSHD_FD: return syshd.u.fd;
+ case ES_SYSHD_SOCK: return syshd.u.sock;
+ default:
+ _set_errno (EINVAL);
+ return -1;
+ }
+}
+
+
+/* Return the handle of a stream which has been opened by es_sysopen.
+ The caller needs to pass a structure which will be filled with the
+ sys handle. Return 0 on success or true on error and sets errno.
+ This is the unlocked version. */
+int
+es_syshd_unlocked (estream_t stream, es_syshd_t *syshd)
+{
+ if (!stream || !syshd || stream->intern->syshd.type == ES_SYSHD_NONE)
+ {
+ if (syshd)
+ syshd->type = ES_SYSHD_NONE;
+ _set_errno (EINVAL);
+ return -1;
+ }
+
+ *syshd = stream->intern->syshd;
+ return 0;
}
@@ -2600,6 +2980,23 @@ es_fileno (estream_t stream)
}
+/* Return the handle of a stream which has been opened by es_sysopen.
+ The caller needs to pass a structure which will be filled with the
+ sys handle. Return 0 on success or true on error and sets errno.
+ This is the unlocked version. */
+int
+es_syshd (estream_t stream, es_syshd_t *syshd)
+{
+ int ret;
+
+ ESTREAM_LOCK (stream);
+ ret = es_syshd_unlocked (stream, syshd);
+ ESTREAM_UNLOCK (stream);
+
+ return ret;
+}
+
+
int
es_feof_unlocked (estream_t stream)
{
@@ -3371,6 +3768,7 @@ es_tmpfile (void)
void *cookie;
int err;
int fd;
+ es_syshd_t syshd;
create_called = 0;
stream = NULL;
@@ -3388,11 +3786,12 @@ es_tmpfile (void)
if (err)
goto out;
+ syshd.type = ES_SYSHD_FD;
+ syshd.u.fd = fd;
create_called = 1;
- err = es_create (&stream, cookie, fd, estream_functions_fd, modeflags, 0);
+ err = es_create (&stream, cookie, &syshd, estream_functions_fd, modeflags, 0);
out:
-
if (err)
{
if (create_called)
diff --git a/common/estream.h b/common/estream.h
index 34ff5ce77..c5dc19c07 100644
--- a/common/estream.h
+++ b/common/estream.h
@@ -78,6 +78,8 @@
#define es_fopenmem _ESTREAM_PREFIX(es_fopenmem)
#define es_fdopen _ESTREAM_PREFIX(es_fdopen)
#define es_fdopen_nc _ESTREAM_PREFIX(es_fdopen_nc)
+#define es_sysopen _ESTREAM_PREFIX(es_sysopen)
+#define es_sysopen_nc _ESTREAM_PREFIX(es_sysopen_nc)
#define es_fpopen _ESTREAM_PREFIX(es_fpopen)
#define es_fpopen_nc _ESTREAM_PREFIX(es_fpopen_nc)
#define _es_set_std_fd _ESTREAM_PREFIX(_es_set_std_fd)
@@ -211,6 +213,29 @@ typedef struct es_cookie_io_functions
es_cookie_close_function_t func_close;
} es_cookie_io_functions_t;
+
+enum es_syshd_types
+ {
+ ES_SYSHD_NONE, /* No system handle available. */
+ ES_SYSHD_FD, /* A file descriptor as returned by open(). */
+ ES_SYSHD_SOCK, /* A socket as returned by socket(). */
+ ES_SYSHD_RVID, /* A rendevous id (see libassuan's gpgcedev.c). */
+ ES_SYSHD_HANDLE /* A HANDLE object (Windows). */
+ };
+
+typedef struct
+{
+ enum es_syshd_types type;
+ union {
+ int fd;
+ int sock;
+ int rvid;
+ void *handle;
+ } u;
+} es_syshd_t;
+
+
+
#ifndef _ESTREAM_GCC_A_PRINTF
#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 5 )
@@ -245,6 +270,8 @@ estream_t es_mopen (unsigned char *ES__RESTRICT data,
estream_t es_fopenmem (size_t memlimit, const char *ES__RESTRICT mode);
estream_t es_fdopen (int filedes, const char *mode);
estream_t es_fdopen_nc (int filedes, const char *mode);
+estream_t es_sysopen (es_syshd_t *syshd, const char *mode);
+estream_t es_sysopen_nc (es_syshd_t *syshd, const char *mode);
estream_t es_fpopen (FILE *fp, const char *mode);
estream_t es_fpopen_nc (FILE *fp, const char *mode);
estream_t es_freopen (const char *ES__RESTRICT path,
@@ -256,6 +283,8 @@ estream_t es_fopencookie (void *ES__RESTRICT cookie,
int es_fclose (estream_t stream);
int es_fileno (estream_t stream);
int es_fileno_unlocked (estream_t stream);
+int es_syshd (estream_t stream, es_syshd_t *syshd);
+int es_syshd_unlocked (estream_t stream, es_syshd_t *syshd);
void _es_set_std_fd (int no, int fd);
estream_t _es_get_std_stream (int fd);
diff --git a/common/exechelp-posix.c b/common/exechelp-posix.c
index 5a8e0289c..6ffc562ca 100644
--- a/common/exechelp-posix.c
+++ b/common/exechelp-posix.c
@@ -299,45 +299,95 @@ gnupg_create_outbound_pipe (int filedes[2])
}
+
+static gpg_error_t
+create_pipe_and_estream (int filedes[2], estream_t *r_fp,
+ gpg_err_source_t errsource)
+{
+ gpg_error_t err;
+
+ if (pipe (filedes) == -1)
+ {
+ err = gpg_err_make (errsource, gpg_err_code_from_syserror ());
+ log_error (_("error creating a pipe: %s\n"), gpg_strerror (err));
+ filedes[0] = filedes[1] = -1;
+ *r_fp = NULL;
+ return err;
+ }
+
+ *r_fp = es_fdopen (filedes[0], "r");
+ if (!*r_fp)
+ {
+ err = gpg_err_make (errsource, gpg_err_code_from_syserror ());
+ 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;
+ return err;
+ }
+ return 0;
+}
+
+
+
/* Fork and exec the PGMNAME, see exechelp.h for details. */
gpg_error_t
gnupg_spawn_process (const char *pgmname, const char *argv[],
- estream_t infile, estream_t outfile,
+ gpg_err_source_t errsource,
void (*preexec)(void), unsigned int flags,
- estream_t *statusfile, pid_t *pid)
+ estream_t infp,
+ estream_t *r_outfp,
+ estream_t *r_errfp,
+ pid_t *pid)
{
gpg_error_t err;
- int fd, fdout, rp[2];
+ int infd = -1;
+ int outpipe[2] = {-1, -1};
+ int errpipe[2] = {-1, -1};
+ estream_t outfp = NULL;
+ estream_t errfp = NULL;
(void)flags; /* Currently not used. */
- *statusfile = NULL;
- *pid = (pid_t)(-1);
+ if (r_outfp)
+ *r_outfp = NULL;
+ if (r_errfp)
+ *r_errfp = NULL;
+ *pid = (pid_t)(-1); /* Always required. */
- if (infile)
+ if (infp)
{
- es_fflush (infile);
- es_rewind (infile);
- fd = es_fileno (infile);
+ es_fflush (infp);
+ es_rewind (infp);
+ infd = es_fileno (infp);
+ if (infd == -1)
+ return gpg_err_make (errsource, GPG_ERR_INV_VALUE);
}
- else
- fd = -1;
- if (outfile)
- fdout = es_fileno (outfile);
- else
- fdout = -1;
-
- if ((infile && fd == -1) || (outfile && fdout == -1))
- log_fatal ("no file descriptor for file passed to gnupg_spawn_process\n");
+ if (r_outfp)
+ {
+ err = create_pipe_and_estream (outpipe, &outfp, errsource);
+ if (err)
+ return err;
+ }
- if (pipe (rp) == -1)
+ if (r_errfp)
{
- err = gpg_error_from_syserror ();
- log_error (_("error creating a pipe: %s\n"), strerror (errno));
- return err;
+ err = create_pipe_and_estream (errpipe, &errfp, errsource);
+ if (err)
+ {
+ if (outfp)
+ es_fclose (outfp);
+ else if (outpipe[0] != -1)
+ close (outpipe[0]);
+ if (outpipe[1] != -1)
+ close (outpipe[1]);
+ return err;
+ }
}
+
#ifdef USE_GNU_PTH
*pid = pth_fork? pth_fork () : fork ();
#else
@@ -345,33 +395,45 @@ gnupg_spawn_process (const char *pgmname, const char *argv[],
#endif
if (*pid == (pid_t)(-1))
{
- err = gpg_error_from_syserror ();
- log_error (_("error forking process: %s\n"), strerror (errno));
- close (rp[0]);
- close (rp[1]);
+ err = gpg_err_make (errsource, gpg_err_code_from_syserror ());
+ log_error (_("error forking process: %s\n"), gpg_strerror (err));
+
+ if (outfp)
+ es_fclose (outfp);
+ else if (outpipe[0] != -1)
+ close (outpipe[0]);
+ if (outpipe[1] != -1)
+ close (outpipe[1]);
+
+ if (errfp)
+ es_fclose (errfp);
+ else if (errpipe[0] != -1)
+ close (errpipe[0]);
+ if (errpipe[1] != -1)
+ close (errpipe[1]);
return err;
}
if (!*pid)
{
+ /* This is the child. */
gcry_control (GCRYCTL_TERM_SECMEM);
- /* Run child. */
- do_exec (pgmname, argv, fd, fdout, rp[1], preexec);
+ es_fclose (outfp);
+ es_fclose (errfp);
+ do_exec (pgmname, argv, infd, outpipe[1], errpipe[1], preexec);
/*NOTREACHED*/
}
- /* Parent. */
- close (rp[1]);
+ /* This is the parent. */
+ if (outpipe[1] != -1)
+ close (outpipe[1]);
+ if (errpipe[1] != -1)
+ close (errpipe[1]);
- *statusfile = es_fdopen (rp[0], "r");
- if (!*statusfile)
- {
- err = gpg_error_from_syserror ();
- log_error (_("can't fdopen pipe for reading: %s\n"), strerror (errno));
- kill (*pid, SIGTERM);
- *pid = (pid_t)(-1);
- return err;
- }
+ if (r_outfp)
+ *r_outfp = outfp;
+ if (r_errfp)
+ *r_errfp = errfp;
return 0;
}
diff --git a/common/exechelp-w32.c b/common/exechelp-w32.c
index 297f6f854..13f600716 100644
--- a/common/exechelp-w32.c
+++ b/common/exechelp-w32.c
@@ -257,7 +257,7 @@ build_w32_commandline (const char *pgmname, const char * const *argv,
/* Create pipe where one end is inheritable: With an INHERIT_IDX of 0
the read end is inheritable, with 1 the write end is inheritable. */
static int
-create_inheritable_pipe (int filedes[2], int inherit_idx)
+create_inheritable_pipe (HANDLE filedes[2], int inherit_idx)
{
HANDLE r, w, h;
SECURITY_ATTRIBUTES sec_attr;
@@ -290,8 +290,8 @@ create_inheritable_pipe (int filedes[2], int inherit_idx)
r = h;
}
- filedes[0] = handle_to_fd (r);
- filedes[1] = handle_to_fd (w);
+ filedes[0] = r;
+ filedes[1] = w;
return 0;
}
@@ -315,27 +315,27 @@ static gpg_error_t
do_create_pipe (int filedes[2], int inherit_idx)
{
gpg_error_t err = 0;
- int fds[2];
+ HANDLE fds[2];
filedes[0] = filedes[1] = -1;
err = gpg_error (GPG_ERR_GENERAL);
if (!create_inheritable_pipe (fds, inherit_idx))
{
- filedes[0] = _open_osfhandle (fds[0], 0);
+ filedes[0] = _open_osfhandle (handle_to_fd (fds[0]), 0);
if (filedes[0] == -1)
{
- log_error ("failed to translate osfhandle %p\n", (void*)fds[0]);
- CloseHandle (fd_to_handle (fds[1]));
+ log_error ("failed to translate osfhandle %p\n", fds[0]);
+ CloseHandle (fds[1]);
}
else
{
- filedes[1] = _open_osfhandle (fds[1], 1);
+ filedes[1] = _open_osfhandle (handle_to_fd (fds[1]), 1);
if (filedes[1] == -1)
{
- log_error ("failed to translate osfhandle %p\n", (void*)fds[1]);
+ log_error ("failed to translate osfhandle %p\n", fds[1]);
close (filedes[0]);
filedes[0] = -1;
- CloseHandle (fd_to_handle (fds[1]));
+ CloseHandle (fds[1]);
}
else
err = 0;
@@ -365,9 +365,12 @@ gnupg_create_outbound_pipe (int filedes[2])
/* Fork and exec the PGMNAME, see exechelp.h for details. */
gpg_error_t
gnupg_spawn_process (const char *pgmname, const char *argv[],
- estream_t infile, estream_t outfile,
+ gpg_err_source_t errsource,
void (*preexec)(void), unsigned int flags,
- estream_t *statusfile, pid_t *pid)
+ estream_t infp,
+ estream_t *r_outfp,
+ estream_t *r_errfp,
+ pid_t *pid)
{
gpg_error_t err;
SECURITY_ATTRIBUTES sec_attr;
@@ -381,32 +384,103 @@ gnupg_spawn_process (const char *pgmname, const char *argv[],
STARTUPINFO si;
int cr_flags;
char *cmdline;
- int fd, fdout, rp[2];
- HANDLE nullhd[2];
+ HANDLE inhandle = INVALID_HANDLE_VALUE;
+ HANDLE outpipe[2] = {INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE};
+ HANDLE errpipe[2] = {INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE};
+ estream_t outfp = NULL;
+ estream_t errfp = NULL;
+ HANDLE nullhd[3] = {INVALID_HANDLE_VALUE,
+ INVALID_HANDLE_VALUE,
+ INVALID_HANDLE_VALUE};
int i;
+ es_syshd_t syshd;
- (void)preexec;
-
- /* Setup return values. */
- *statusfile = NULL;
- *pid = (pid_t)(-1);
+ if (r_outfp)
+ *r_outfp = NULL;
+ if (r_errfp)
+ *r_errfp = NULL;
+ *pid = (pid_t)(-1); /* Always required. */
- if (infile)
+ if (infp)
{
- es_fflush (infile);
- es_rewind (infile);
- fd = _get_osfhandle (es_fileno (infile));
+ es_fflush (infp);
+ es_rewind (infp);
+ es_syshd (infp, &syshd);
+ switch (syshd.type)
+ {
+ case ES_SYSHD_FD:
+ inhandle = (HANDLE)_get_osfhandle (syshd.u.fd);
+ break;
+ case ES_SYSHD_SOCK:
+ inhandle = (HANDLE)_get_osfhandle (syshd.u.sock);
+ break;
+ case ES_SYSHD_HANDLE:
+ inhandle = syshd.u.handle;
+ break;
+ default:
+ inhandle = INVALID_HANDLE_VALUE;
+ break;
+ }
+ if (inhandle == INVALID_HANDLE_VALUE)
+ return gpg_err_make (errsource, GPG_ERR_INV_VALUE);
+ /* FIXME: In case we can't get a system handle (e.g. due to
+ es_fopencookie we should create a piper and a feeder
+ thread. */
}
- else
- fd = -1;
- if (outfile)
- fdout = _get_osfhandle (es_fileno (outfile));
- else
- fdout = -1;
+ if (r_outfp)
+ {
+ if (create_inheritable_pipe (outpipe, 1))
+ {
+ err = gpg_err_make (errsource, GPG_ERR_GENERAL);
+ log_error (_("error creating a pipe: %s\n"), gpg_strerror (err));
+ return err;
+ }
- if ( (infile && fd == -1) || (outfile && fdout == -1))
- log_fatal ("no file descriptor for file passed to gnupg_spawn_process\n");
+ syshd.type = ES_SYSHD_HANDLE;
+ syshd.u.handle = outpipe[0];
+ outfp = es_sysopen (&syshd, "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));
+ CloseHandle (outpipe[0]);
+ CloseHandle (outpipe[1]);
+ outpipe[0] = outpipe[1] = INVALID_HANDLE_VALUE;
+ return err;
+ }
+ }
+
+ if (r_errfp)
+ {
+ if (create_inheritable_pipe (errpipe, 1))
+ {
+ err = gpg_err_make (errsource, GPG_ERR_GENERAL);
+ 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, "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));
+ CloseHandle (errpipe[0]);
+ CloseHandle (errpipe[1]);
+ errpipe[0] = errpipe[1] = INVALID_HANDLE_VALUE;
+ if (outfp)
+ es_fclose (outfp);
+ else if (outpipe[0] != INVALID_HANDLE_VALUE)
+ CloseHandle (outpipe[0]);
+ if (outpipe[1] != INVALID_HANDLE_VALUE)
+ CloseHandle (outpipe[1]);
+ return err;
+ }
+ }
/* Prepare security attributes. */
memset (&sec_attr, 0, sizeof sec_attr );
@@ -418,27 +492,24 @@ gnupg_spawn_process (const char *pgmname, const char *argv[],
if (err)
return err;
- /* Create a pipe. */
- if (create_inheritable_pipe (rp, 1))
- {
- err = gpg_error (GPG_ERR_GENERAL);
- log_error (_("error creating a pipe: %s\n"), gpg_strerror (err));
- xfree (cmdline);
- return err;
- }
-
- nullhd[0] = fd == -1? w32_open_null (0) : INVALID_HANDLE_VALUE;
- nullhd[1] = fdout == -1? w32_open_null (1) : INVALID_HANDLE_VALUE;
+ if (inhandle != INVALID_HANDLE_VALUE)
+ nullhd[0] = w32_open_null (0);
+ if (outpipe[1] != INVALID_HANDLE_VALUE)
+ nullhd[1] = w32_open_null (0);
+ if (errpipe[1] != INVALID_HANDLE_VALUE)
+ nullhd[2] = w32_open_null (0);
/* Start the process. Note that we can't run the PREEXEC function
- because this would change our own environment. */
+ because this might change our own environment. */
+ (void)preexec;
+
memset (&si, 0, sizeof si);
si.cb = sizeof (si);
si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
si.wShowWindow = DEBUG_W32_SPAWN? SW_SHOW : SW_MINIMIZE;
- si.hStdInput = fd == -1? nullhd[0] : fd_to_handle (fd);
- si.hStdOutput = fdout == -1? nullhd[1] : fd_to_handle (fdout);
- si.hStdError = fd_to_handle (rp[1]);
+ si.hStdInput = inhandle == INVALID_HANDLE_VALUE? nullhd[0] : inhandle;
+ si.hStdOutput = outpipe[1] == INVALID_HANDLE_VALUE? nullhd[1] : outpipe[1];
+ si.hStdError = errpipe[1] == INVALID_HANDLE_VALUE? nullhd[2] : errpipe[1];
cr_flags = (CREATE_DEFAULT_ERROR_MODE
| ((flags & 128)? DETACHED_PROCESS : 0)
@@ -459,9 +530,19 @@ gnupg_spawn_process (const char *pgmname, const char *argv[],
{
log_error ("CreateProcess failed: %s\n", w32_strerror (-1));
xfree (cmdline);
- CloseHandle (fd_to_handle (rp[0]));
- CloseHandle (fd_to_handle (rp[1]));
- return gpg_error (GPG_ERR_GENERAL);
+ if (outfp)
+ es_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);
+ 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);
}
xfree (cmdline);
cmdline = NULL;
@@ -471,17 +552,21 @@ gnupg_spawn_process (const char *pgmname, const char *argv[],
if (nullhd[i] != INVALID_HANDLE_VALUE)
CloseHandle (nullhd[i]);
- /* Close the other end of the pipe. */
- CloseHandle (fd_to_handle (rp[1]));
-
-/* log_debug ("CreateProcess ready: hProcess=%p hThread=%p" */
-/* " dwProcessID=%d dwThreadId=%d\n", */
-/* pi.hProcess, pi.hThread, */
-/* (int) pi.dwProcessId, (int) pi.dwThreadId); */
+ /* Close the inherited ends of the pipes. */
+ if (outpipe[1] != INVALID_HANDLE_VALUE)
+ CloseHandle (outpipe[1]);
+ 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); */
+
/* Fixme: For unknown reasons AllowSetForegroundWindow returns an
- invalid argument error if we pass the correct processID to
- it. As a workaround we use -1 (ASFW_ANY). */
+ invalid argument error if we pass it the correct processID. As a
+ workaround we use -1 (ASFW_ANY). */
if ( (flags & 64) )
gnupg_allow_set_foregound_window ((pid_t)(-1)/*pi.dwProcessId*/);
@@ -489,22 +574,10 @@ gnupg_spawn_process (const char *pgmname, const char *argv[],
ResumeThread (pi.hThread);
CloseHandle (pi.hThread);
- {
- int x;
-
- x = _open_osfhandle (rp[0], 0);
- if (x == -1)
- log_error ("failed to translate osfhandle %p\n", (void*)rp[0] );
- else
- *statusfile = es_fdopen (x, "r");
- }
- if (!*statusfile)
- {
- err = gpg_error_from_syserror ();
- log_error (_("can't fdopen pipe for reading: %s\n"), gpg_strerror (err));
- CloseHandle (pi.hProcess);
- return err;
- }
+ if (r_outfp)
+ *r_outfp = outfp;
+ if (r_errfp)
+ *r_errfp = errfp;
*pid = handle_to_pid (pi.hProcess);
return 0;
diff --git a/common/exechelp-w32ce.c b/common/exechelp-w32ce.c
index 5a84c9f1d..f49a442d9 100644
--- a/common/exechelp-w32ce.c
+++ b/common/exechelp-w32ce.c
@@ -83,7 +83,7 @@ struct feeder_thread_parms
};
-/* The thread started by start_feeded. */
+/* The thread started by start_feede3. */
static void *
feeder_thread (void *arg)
{
@@ -485,10 +485,14 @@ create_process (const char *pgmname, const char *cmdline,
/* Fork and exec the PGMNAME, see exechelp.h for details. */
gpg_error_t
gnupg_spawn_process (const char *pgmname, const char *argv[],
- estream_t infile, estream_t outfile,
+ gpg_err_source_t errsource,
void (*preexec)(void), unsigned int flags,
- estream_t *statusfile, pid_t *pid)
+ estream_t infp,
+ estream_t *r_outfp,
+ estream_t *r_errfp,
+ pid_t *pid)
{
+#if 0
gpg_error_t err;
PROCESS_INFORMATION pi = {NULL };
char *cmdline;
@@ -598,7 +602,9 @@ gnupg_spawn_process (const char *pgmname, const char *argv[],
*pid = handle_to_pid (pi.hProcess);
return 0;
-
+#else
+ return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
+#endif
}
diff --git a/common/exechelp.h b/common/exechelp.h
index 3a5b9e2b8..e6a0ee5e1 100644
--- a/common/exechelp.h
+++ b/common/exechelp.h
@@ -52,15 +52,24 @@ gpg_error_t gnupg_create_inbound_pipe (int filedes[2]);
gpg_error_t gnupg_create_outbound_pipe (int filedes[2]);
-/* Fork and exec the PGMNAME, connect the file descriptor of INFILE to
- stdin, write the output to OUTFILE. INFILE or PUTFILE may be NULL
- to connect thenm to /dev/null. Returns a new stream in STATUSFILE
- for stderr and the pid of the process in PID. The arguments for the
- process are expected in the NULL terminated array ARGV. The
- program name itself should not be included there. If PREEXEC is
- not NULL, that function will be called right before the exec.
- Calling gnupg_wait_process and gnupg_release_process is required.
- Returns 0 on success or an error code.
+/* Fork and exec the PGMNAME. If INFP is NULL connect /dev/null to
+ stdin of the new process; if it is not NULL connect the file
+ descriptor retrieved from INFP to stdin. If R_OUTFP is NULL
+ connect stdout of the new process to /dev/null; if it is not NULL
+ store the address of a pointer to a new estream there. If R_ERRFP
+ is NULL connect stderr of the new process to /dev/null; if it is
+ not NULL store the address of a pointer to a new estream there. On
+ success the pid of the new process is stored at PID. On error -1
+ is stored at PID and if R_OUTFP or R_ERRFP are not NULL, NULL is
+ stored there.
+
+ The arguments for the process are expected in the NULL terminated
+ array ARGV. The program name itself should not be included there.
+ If PREEXEC is not NULL, the given function will be called right
+ before the exec.
+
+ Returns 0 on success or an error code. Calling gnupg_wait_process
+ and gnupg_release_process is required if the function succeeded.
FLAGS is a bit vector:
@@ -74,10 +83,14 @@ gpg_error_t gnupg_create_outbound_pipe (int filedes[2]);
allows SetForegroundWindow for all childs of this process.
*/
-gpg_error_t gnupg_spawn_process (const char *pgmname, const char *argv[],
- estream_t infile, estream_t outfile,
- void (*preexec)(void), unsigned int flags,
- estream_t *statusfile, pid_t *pid);
+gpg_error_t
+gnupg_spawn_process (const char *pgmname, const char *argv[],
+ gpg_err_source_t errsource,
+ void (*preexec)(void), unsigned int flags,
+ estream_t infp,
+ estream_t *r_outfp,
+ estream_t *r_errfp,
+ pid_t *pid);
/* Simplified version of gnupg_spawn_process. This function forks and