mirror of
git://git.gnupg.org/gnupg.git
synced 2024-12-22 10:19:57 +01:00
Reworked the posix and w32 exechelpers.
This commit is contained in:
parent
be9c4748d0
commit
15330f36a7
@ -1,3 +1,7 @@
|
|||||||
|
2010-08-19 Werner Koch <wk@g10code.com>
|
||||||
|
|
||||||
|
* configure.ac (AH_BOTTOM): Define GPG_ERR_ENABLE_ERRNO_MACROS.
|
||||||
|
|
||||||
2010-08-09 Werner Koch <wk@g10code.com>
|
2010-08-09 Werner Koch <wk@g10code.com>
|
||||||
|
|
||||||
* configure.ac (inet_pton): Check for it.
|
* configure.ac (inet_pton): Check for it.
|
||||||
|
2
NEWS
2
NEWS
@ -35,6 +35,8 @@ Noteworthy changes in version 2.1.x (under development)
|
|||||||
|
|
||||||
* Given sufficient permissions Dirmngr is started automagically.
|
* Given sufficient permissions Dirmngr is started automagically.
|
||||||
|
|
||||||
|
* Fixed output of "gpgconf --check-options".
|
||||||
|
|
||||||
|
|
||||||
Noteworthy changes in version 2.0.13 (2009-09-04)
|
Noteworthy changes in version 2.0.13 (2009-09-04)
|
||||||
-------------------------------------------------
|
-------------------------------------------------
|
||||||
|
2
README
2
README
@ -16,7 +16,7 @@ INTRODUCTION
|
|||||||
GnuPG is GNU's tool for secure communication and data storage. It can
|
GnuPG is GNU's tool for secure communication and data storage. It can
|
||||||
be used to encrypt data and to create digital signatures. It includes
|
be used to encrypt data and to create digital signatures. It includes
|
||||||
an advanced key management facility and is compliant with the proposed
|
an advanced key management facility and is compliant with the proposed
|
||||||
OpenPGP Internet standard as described in RFC2440 and the S/MIME
|
OpenPGP Internet standard as described in RFC4880 and the S/MIME
|
||||||
standard as described by several RFCs.
|
standard as described by several RFCs.
|
||||||
|
|
||||||
GnuPG is distributed under the terms of the GNU General Public
|
GnuPG is distributed under the terms of the GNU General Public
|
||||||
|
@ -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>
|
2010-08-18 Werner Koch <wk@g10code.com>
|
||||||
|
|
||||||
* logging.c (writen): Add arg IS_SOCKET.
|
* logging.c (writen): Add arg IS_SOCKET.
|
||||||
|
471
common/estream.c
471
common/estream.c
@ -126,9 +126,9 @@ int _setmode (int handle, int mode);
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_W32_SYSTEM
|
#ifdef HAVE_W32_SYSTEM
|
||||||
# define IS_INVALID_FD(a) ((void*)(a) == (void*)(-1))
|
# define IS_INVALID_FD(a) ((void*)(a) == (void*)(-1)) /* ?? FIXME. */
|
||||||
#else
|
#else
|
||||||
# define IS_INVALID_FD(a) ((a) == -1)
|
# define IS_INVALID_FD(a) ((a) == -1)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
@ -197,6 +197,7 @@ dummy_mutex_call_int (estream_mutex_t mutex)
|
|||||||
# define ESTREAM_SYS_YIELD() do { } while (0)
|
# define ESTREAM_SYS_YIELD() do { } while (0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/* Misc definitions. */
|
/* Misc definitions. */
|
||||||
|
|
||||||
#define ES_DEFAULT_OPEN_MODE (S_IRUSR | S_IWUSR)
|
#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_seek_function_t func_seek;
|
||||||
es_cookie_close_function_t func_close;
|
es_cookie_close_function_t func_close;
|
||||||
int strategy;
|
int strategy;
|
||||||
int fd; /* Value to return by es_fileno(). */
|
es_syshd_t syshd; /* A copy of the sytem handle. */
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
unsigned int err: 1;
|
unsigned int err: 1;
|
||||||
@ -317,7 +318,39 @@ mem_free (void *p)
|
|||||||
free (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.
|
* 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. */
|
/* Cookie for fd objects. */
|
||||||
typedef struct estream_cookie_fd
|
typedef struct estream_cookie_fd
|
||||||
@ -886,6 +919,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. */
|
/* Implementation of FILE* I/O. */
|
||||||
|
|
||||||
@ -1049,7 +1293,7 @@ static es_cookie_io_functions_t estream_functions_fp =
|
|||||||
|
|
||||||
/* Implementation of file I/O. */
|
/* Implementation of file I/O. */
|
||||||
|
|
||||||
/* Create function for file objects. */
|
/* Create function for fd objects. */
|
||||||
static int
|
static int
|
||||||
es_func_file_create (void **cookie, int *filedes,
|
es_func_file_create (void **cookie, int *filedes,
|
||||||
const char *path, unsigned int modeflags)
|
const char *path, unsigned int modeflags)
|
||||||
@ -1269,7 +1513,8 @@ es_empty (estream_t stream)
|
|||||||
/* Initialize STREAM. */
|
/* Initialize STREAM. */
|
||||||
static void
|
static void
|
||||||
es_initialize (estream_t stream,
|
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)
|
unsigned int modeflags)
|
||||||
{
|
{
|
||||||
stream->intern->cookie = cookie;
|
stream->intern->cookie = cookie;
|
||||||
@ -1280,7 +1525,7 @@ es_initialize (estream_t stream,
|
|||||||
stream->intern->func_seek = functions.func_seek;
|
stream->intern->func_seek = functions.func_seek;
|
||||||
stream->intern->func_close = functions.func_close;
|
stream->intern->func_close = functions.func_close;
|
||||||
stream->intern->strategy = _IOFBF;
|
stream->intern->strategy = _IOFBF;
|
||||||
stream->intern->fd = fd;
|
stream->intern->syshd = *syshd;
|
||||||
stream->intern->print_ntotal = 0;
|
stream->intern->print_ntotal = 0;
|
||||||
stream->intern->indicators.err = 0;
|
stream->intern->indicators.err = 0;
|
||||||
stream->intern->indicators.eof = 0;
|
stream->intern->indicators.eof = 0;
|
||||||
@ -1329,7 +1574,7 @@ es_deinitialize (estream_t stream)
|
|||||||
|
|
||||||
/* Create a new stream object, initialize it. */
|
/* Create a new stream object, initialize it. */
|
||||||
static int
|
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,
|
es_cookie_io_functions_t functions, unsigned int modeflags,
|
||||||
int with_locked_list)
|
int with_locked_list)
|
||||||
{
|
{
|
||||||
@ -1361,7 +1606,7 @@ es_create (estream_t *stream, void *cookie, int fd,
|
|||||||
stream_new->intern = stream_internal_new;
|
stream_new->intern = stream_internal_new;
|
||||||
|
|
||||||
ESTREAM_MUTEX_INITIALIZE (stream_new->intern->lock);
|
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);
|
err = es_list_add (stream_new, with_locked_list);
|
||||||
if (err)
|
if (err)
|
||||||
@ -1385,9 +1630,9 @@ es_create (estream_t *stream, void *cookie, int fd,
|
|||||||
|
|
||||||
/* Deinitialize a stream object and destroy it. */
|
/* Deinitialize a stream object and destroy it. */
|
||||||
static int
|
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)
|
if (stream)
|
||||||
{
|
{
|
||||||
@ -1396,6 +1641,8 @@ es_destroy (estream_t stream, int with_locked_list)
|
|||||||
mem_free (stream->intern);
|
mem_free (stream->intern);
|
||||||
mem_free (stream);
|
mem_free (stream);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
err = 0;
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@ -1897,6 +2144,7 @@ doreadline (estream_t ES__RESTRICT stream, size_t max_length,
|
|||||||
unsigned char *data;
|
unsigned char *data;
|
||||||
size_t data_len;
|
size_t data_len;
|
||||||
int err;
|
int err;
|
||||||
|
es_syshd_t syshd;
|
||||||
|
|
||||||
line_new = NULL;
|
line_new = NULL;
|
||||||
line_stream = NULL;
|
line_stream = NULL;
|
||||||
@ -1910,7 +2158,8 @@ doreadline (estream_t ES__RESTRICT stream, size_t max_length,
|
|||||||
if (err)
|
if (err)
|
||||||
goto out;
|
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);
|
estream_functions_mem, O_RDWR, 0);
|
||||||
if (err)
|
if (err)
|
||||||
goto out;
|
goto out;
|
||||||
@ -1996,7 +2245,7 @@ doreadline (estream_t ES__RESTRICT stream, size_t max_length,
|
|||||||
out:
|
out:
|
||||||
|
|
||||||
if (line_stream)
|
if (line_stream)
|
||||||
es_destroy (line_stream, 0);
|
do_close (line_stream, 0);
|
||||||
else if (line_stream_cookie)
|
else if (line_stream_cookie)
|
||||||
es_func_mem_destroy (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. */
|
/* API. */
|
||||||
@ -2172,6 +2415,8 @@ es_init (void)
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
estream_t
|
estream_t
|
||||||
es_fopen (const char *ES__RESTRICT path, const char *ES__RESTRICT mode)
|
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;
|
void *cookie;
|
||||||
int err;
|
int err;
|
||||||
int fd;
|
int fd;
|
||||||
|
es_syshd_t syshd;
|
||||||
|
|
||||||
stream = NULL;
|
stream = NULL;
|
||||||
cookie = 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);
|
err = es_func_file_create (&cookie, &fd, path, modeflags);
|
||||||
if (err)
|
if (err)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
syshd.type = ES_SYSHD_FD;
|
||||||
|
syshd.u.fd = fd;
|
||||||
|
|
||||||
create_called = 1;
|
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)
|
if (err)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
@ -2211,6 +2460,7 @@ es_fopen (const char *ES__RESTRICT path, const char *ES__RESTRICT mode)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
estream_t
|
estream_t
|
||||||
es_mopen (unsigned char *ES__RESTRICT data, size_t data_n, size_t data_len,
|
es_mopen (unsigned char *ES__RESTRICT data, size_t data_n, size_t data_len,
|
||||||
unsigned int grow,
|
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;
|
estream_t stream;
|
||||||
void *cookie;
|
void *cookie;
|
||||||
int err;
|
int err;
|
||||||
|
es_syshd_t syshd;
|
||||||
|
|
||||||
cookie = 0;
|
cookie = 0;
|
||||||
stream = NULL;
|
stream = NULL;
|
||||||
@ -2237,8 +2488,10 @@ es_mopen (unsigned char *ES__RESTRICT data, size_t data_n, size_t data_len,
|
|||||||
if (err)
|
if (err)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
memset (&syshd, 0, sizeof syshd);
|
||||||
create_called = 1;
|
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:
|
out:
|
||||||
|
|
||||||
@ -2249,12 +2502,14 @@ es_mopen (unsigned char *ES__RESTRICT data, size_t data_n, size_t data_len,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
estream_t
|
estream_t
|
||||||
es_fopenmem (size_t memlimit, const char *ES__RESTRICT mode)
|
es_fopenmem (size_t memlimit, const char *ES__RESTRICT mode)
|
||||||
{
|
{
|
||||||
unsigned int modeflags;
|
unsigned int modeflags;
|
||||||
estream_t stream = NULL;
|
estream_t stream = NULL;
|
||||||
void *cookie = NULL;
|
void *cookie = NULL;
|
||||||
|
es_syshd_t syshd;
|
||||||
|
|
||||||
/* Memory streams are always read/write. We use MODE only to get
|
/* Memory streams are always read/write. We use MODE only to get
|
||||||
the append flag. */
|
the append flag. */
|
||||||
@ -2269,14 +2524,15 @@ es_fopenmem (size_t memlimit, const char *ES__RESTRICT mode)
|
|||||||
memlimit))
|
memlimit))
|
||||||
return NULL;
|
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);
|
(*estream_functions_mem.func_close) (cookie);
|
||||||
|
|
||||||
return stream;
|
return stream;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
estream_t
|
estream_t
|
||||||
es_fopencookie (void *ES__RESTRICT cookie,
|
es_fopencookie (void *ES__RESTRICT cookie,
|
||||||
const char *ES__RESTRICT mode,
|
const char *ES__RESTRICT mode,
|
||||||
@ -2285,6 +2541,7 @@ es_fopencookie (void *ES__RESTRICT cookie,
|
|||||||
unsigned int modeflags;
|
unsigned int modeflags;
|
||||||
estream_t stream;
|
estream_t stream;
|
||||||
int err;
|
int err;
|
||||||
|
es_syshd_t syshd;
|
||||||
|
|
||||||
stream = NULL;
|
stream = NULL;
|
||||||
modeflags = 0;
|
modeflags = 0;
|
||||||
@ -2293,16 +2550,17 @@ es_fopencookie (void *ES__RESTRICT cookie,
|
|||||||
if (err)
|
if (err)
|
||||||
goto out;
|
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)
|
if (err)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
out:
|
out:
|
||||||
|
|
||||||
return stream;
|
return stream;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
estream_t
|
estream_t
|
||||||
do_fdopen (int filedes, const char *mode, int no_close, int with_locked_list)
|
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;
|
estream_t stream;
|
||||||
void *cookie;
|
void *cookie;
|
||||||
int err;
|
int err;
|
||||||
|
es_syshd_t syshd;
|
||||||
|
|
||||||
stream = NULL;
|
stream = NULL;
|
||||||
cookie = NULL;
|
cookie = NULL;
|
||||||
@ -2324,12 +2583,13 @@ do_fdopen (int filedes, const char *mode, int no_close, int with_locked_list)
|
|||||||
if (err)
|
if (err)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
syshd.type = ES_SYSHD_FD;
|
||||||
|
syshd.u.fd = filedes;
|
||||||
create_called = 1;
|
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);
|
modeflags, with_locked_list);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
|
|
||||||
if (err && create_called)
|
if (err && create_called)
|
||||||
(*estream_functions_fd.func_close) (cookie);
|
(*estream_functions_fd.func_close) (cookie);
|
||||||
|
|
||||||
@ -2350,6 +2610,7 @@ es_fdopen_nc (int filedes, const char *mode)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
estream_t
|
estream_t
|
||||||
do_fpopen (FILE *fp, const char *mode, int no_close, int with_locked_list)
|
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;
|
estream_t stream;
|
||||||
void *cookie;
|
void *cookie;
|
||||||
int err;
|
int err;
|
||||||
|
es_syshd_t syshd;
|
||||||
|
|
||||||
stream = NULL;
|
stream = NULL;
|
||||||
cookie = 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);
|
err = es_func_fp_create (&cookie, fp, modeflags, no_close);
|
||||||
if (err)
|
if (err)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
syshd.type = ES_SYSHD_FD;
|
||||||
|
syshd.u.fd = fp? fileno (fp): -1;
|
||||||
create_called = 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);
|
modeflags, with_locked_list);
|
||||||
|
|
||||||
out:
|
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
|
/* Set custom standard descriptors to be used for stdin, stdout and
|
||||||
stderr. This function needs to be called before any of the
|
stderr. This function needs to be called before any of the
|
||||||
standard streams are accessed. */
|
standard streams are accessed. */
|
||||||
@ -2500,6 +2845,7 @@ es_freopen (const char *ES__RESTRICT path, const char *ES__RESTRICT mode,
|
|||||||
int create_called;
|
int create_called;
|
||||||
void *cookie;
|
void *cookie;
|
||||||
int fd;
|
int fd;
|
||||||
|
es_syshd_t syshd;
|
||||||
|
|
||||||
cookie = NULL;
|
cookie = NULL;
|
||||||
create_called = 0;
|
create_called = 0;
|
||||||
@ -2516,8 +2862,10 @@ es_freopen (const char *ES__RESTRICT path, const char *ES__RESTRICT mode,
|
|||||||
if (err)
|
if (err)
|
||||||
goto leave;
|
goto leave;
|
||||||
|
|
||||||
|
syshd.type = ES_SYSHD_FD;
|
||||||
|
syshd.u.fd = fd;
|
||||||
create_called = 1;
|
create_called = 1;
|
||||||
es_initialize (stream, cookie, fd, estream_functions_fd, modeflags);
|
es_initialize (stream, cookie, &syshd, estream_functions_fd, modeflags);
|
||||||
|
|
||||||
leave:
|
leave:
|
||||||
|
|
||||||
@ -2526,7 +2874,7 @@ es_freopen (const char *ES__RESTRICT path, const char *ES__RESTRICT mode,
|
|||||||
if (create_called)
|
if (create_called)
|
||||||
es_func_fd_destroy (cookie);
|
es_func_fd_destroy (cookie);
|
||||||
|
|
||||||
es_destroy (stream, 0);
|
do_close (stream, 0);
|
||||||
stream = NULL;
|
stream = NULL;
|
||||||
}
|
}
|
||||||
else
|
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. */
|
/* FIXME? We don't support re-opening at the moment. */
|
||||||
_set_errno (EINVAL);
|
_set_errno (EINVAL);
|
||||||
es_deinitialize (stream);
|
es_deinitialize (stream);
|
||||||
es_destroy (stream, 0);
|
do_close (stream, 0);
|
||||||
stream = NULL;
|
stream = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2554,15 +2902,47 @@ es_fclose (estream_t stream)
|
|||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
err = es_destroy (stream, 0);
|
err = do_close (stream, 0);
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
es_fileno_unlocked (estream_t stream)
|
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
|
int
|
||||||
es_feof_unlocked (estream_t stream)
|
es_feof_unlocked (estream_t stream)
|
||||||
{
|
{
|
||||||
@ -3371,6 +3768,7 @@ es_tmpfile (void)
|
|||||||
void *cookie;
|
void *cookie;
|
||||||
int err;
|
int err;
|
||||||
int fd;
|
int fd;
|
||||||
|
es_syshd_t syshd;
|
||||||
|
|
||||||
create_called = 0;
|
create_called = 0;
|
||||||
stream = NULL;
|
stream = NULL;
|
||||||
@ -3388,11 +3786,12 @@ es_tmpfile (void)
|
|||||||
if (err)
|
if (err)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
syshd.type = ES_SYSHD_FD;
|
||||||
|
syshd.u.fd = fd;
|
||||||
create_called = 1;
|
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:
|
out:
|
||||||
|
|
||||||
if (err)
|
if (err)
|
||||||
{
|
{
|
||||||
if (create_called)
|
if (create_called)
|
||||||
|
@ -78,6 +78,8 @@
|
|||||||
#define es_fopenmem _ESTREAM_PREFIX(es_fopenmem)
|
#define es_fopenmem _ESTREAM_PREFIX(es_fopenmem)
|
||||||
#define es_fdopen _ESTREAM_PREFIX(es_fdopen)
|
#define es_fdopen _ESTREAM_PREFIX(es_fdopen)
|
||||||
#define es_fdopen_nc _ESTREAM_PREFIX(es_fdopen_nc)
|
#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 _ESTREAM_PREFIX(es_fpopen)
|
||||||
#define es_fpopen_nc _ESTREAM_PREFIX(es_fpopen_nc)
|
#define es_fpopen_nc _ESTREAM_PREFIX(es_fpopen_nc)
|
||||||
#define _es_set_std_fd _ESTREAM_PREFIX(_es_set_std_fd)
|
#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_close_function_t func_close;
|
||||||
} es_cookie_io_functions_t;
|
} 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
|
#ifndef _ESTREAM_GCC_A_PRINTF
|
||||||
#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 5 )
|
#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_fopenmem (size_t memlimit, const char *ES__RESTRICT mode);
|
||||||
estream_t es_fdopen (int filedes, const char *mode);
|
estream_t es_fdopen (int filedes, const char *mode);
|
||||||
estream_t es_fdopen_nc (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 (FILE *fp, const char *mode);
|
||||||
estream_t es_fpopen_nc (FILE *fp, const char *mode);
|
estream_t es_fpopen_nc (FILE *fp, const char *mode);
|
||||||
estream_t es_freopen (const char *ES__RESTRICT path,
|
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_fclose (estream_t stream);
|
||||||
int es_fileno (estream_t stream);
|
int es_fileno (estream_t stream);
|
||||||
int es_fileno_unlocked (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);
|
void _es_set_std_fd (int no, int fd);
|
||||||
estream_t _es_get_std_stream (int fd);
|
estream_t _es_get_std_stream (int fd);
|
||||||
|
@ -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. */
|
/* Fork and exec the PGMNAME, see exechelp.h for details. */
|
||||||
gpg_error_t
|
gpg_error_t
|
||||||
gnupg_spawn_process (const char *pgmname, const char *argv[],
|
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,
|
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;
|
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. */
|
(void)flags; /* Currently not used. */
|
||||||
|
|
||||||
*statusfile = NULL;
|
if (r_outfp)
|
||||||
*pid = (pid_t)(-1);
|
*r_outfp = NULL;
|
||||||
|
if (r_errfp)
|
||||||
|
*r_errfp = NULL;
|
||||||
|
*pid = (pid_t)(-1); /* Always required. */
|
||||||
|
|
||||||
if (infile)
|
if (infp)
|
||||||
{
|
{
|
||||||
es_fflush (infile);
|
es_fflush (infp);
|
||||||
es_rewind (infile);
|
es_rewind (infp);
|
||||||
fd = es_fileno (infile);
|
infd = es_fileno (infp);
|
||||||
|
if (infd == -1)
|
||||||
|
return gpg_err_make (errsource, GPG_ERR_INV_VALUE);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
fd = -1;
|
|
||||||
|
|
||||||
if (outfile)
|
if (r_outfp)
|
||||||
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 (pipe (rp) == -1)
|
|
||||||
{
|
{
|
||||||
err = gpg_error_from_syserror ();
|
err = create_pipe_and_estream (outpipe, &outfp, errsource);
|
||||||
log_error (_("error creating a pipe: %s\n"), strerror (errno));
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (r_errfp)
|
||||||
|
{
|
||||||
|
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
|
#ifdef USE_GNU_PTH
|
||||||
*pid = pth_fork? pth_fork () : fork ();
|
*pid = pth_fork? pth_fork () : fork ();
|
||||||
#else
|
#else
|
||||||
@ -345,33 +395,45 @@ gnupg_spawn_process (const char *pgmname, const char *argv[],
|
|||||||
#endif
|
#endif
|
||||||
if (*pid == (pid_t)(-1))
|
if (*pid == (pid_t)(-1))
|
||||||
{
|
{
|
||||||
err = gpg_error_from_syserror ();
|
err = gpg_err_make (errsource, gpg_err_code_from_syserror ());
|
||||||
log_error (_("error forking process: %s\n"), strerror (errno));
|
log_error (_("error forking process: %s\n"), gpg_strerror (err));
|
||||||
close (rp[0]);
|
|
||||||
close (rp[1]);
|
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;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!*pid)
|
if (!*pid)
|
||||||
{
|
{
|
||||||
|
/* This is the child. */
|
||||||
gcry_control (GCRYCTL_TERM_SECMEM);
|
gcry_control (GCRYCTL_TERM_SECMEM);
|
||||||
/* Run child. */
|
es_fclose (outfp);
|
||||||
do_exec (pgmname, argv, fd, fdout, rp[1], preexec);
|
es_fclose (errfp);
|
||||||
|
do_exec (pgmname, argv, infd, outpipe[1], errpipe[1], preexec);
|
||||||
/*NOTREACHED*/
|
/*NOTREACHED*/
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Parent. */
|
/* This is the parent. */
|
||||||
close (rp[1]);
|
if (outpipe[1] != -1)
|
||||||
|
close (outpipe[1]);
|
||||||
|
if (errpipe[1] != -1)
|
||||||
|
close (errpipe[1]);
|
||||||
|
|
||||||
*statusfile = es_fdopen (rp[0], "r");
|
if (r_outfp)
|
||||||
if (!*statusfile)
|
*r_outfp = outfp;
|
||||||
{
|
if (r_errfp)
|
||||||
err = gpg_error_from_syserror ();
|
*r_errfp = errfp;
|
||||||
log_error (_("can't fdopen pipe for reading: %s\n"), strerror (errno));
|
|
||||||
kill (*pid, SIGTERM);
|
|
||||||
*pid = (pid_t)(-1);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -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
|
/* 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. */
|
the read end is inheritable, with 1 the write end is inheritable. */
|
||||||
static int
|
static int
|
||||||
create_inheritable_pipe (int filedes[2], int inherit_idx)
|
create_inheritable_pipe (HANDLE filedes[2], int inherit_idx)
|
||||||
{
|
{
|
||||||
HANDLE r, w, h;
|
HANDLE r, w, h;
|
||||||
SECURITY_ATTRIBUTES sec_attr;
|
SECURITY_ATTRIBUTES sec_attr;
|
||||||
@ -290,8 +290,8 @@ create_inheritable_pipe (int filedes[2], int inherit_idx)
|
|||||||
r = h;
|
r = h;
|
||||||
}
|
}
|
||||||
|
|
||||||
filedes[0] = handle_to_fd (r);
|
filedes[0] = r;
|
||||||
filedes[1] = handle_to_fd (w);
|
filedes[1] = w;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -315,27 +315,27 @@ static gpg_error_t
|
|||||||
do_create_pipe (int filedes[2], int inherit_idx)
|
do_create_pipe (int filedes[2], int inherit_idx)
|
||||||
{
|
{
|
||||||
gpg_error_t err = 0;
|
gpg_error_t err = 0;
|
||||||
int fds[2];
|
HANDLE fds[2];
|
||||||
|
|
||||||
filedes[0] = filedes[1] = -1;
|
filedes[0] = filedes[1] = -1;
|
||||||
err = gpg_error (GPG_ERR_GENERAL);
|
err = gpg_error (GPG_ERR_GENERAL);
|
||||||
if (!create_inheritable_pipe (fds, inherit_idx))
|
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)
|
if (filedes[0] == -1)
|
||||||
{
|
{
|
||||||
log_error ("failed to translate osfhandle %p\n", (void*)fds[0]);
|
log_error ("failed to translate osfhandle %p\n", fds[0]);
|
||||||
CloseHandle (fd_to_handle (fds[1]));
|
CloseHandle (fds[1]);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
filedes[1] = _open_osfhandle (fds[1], 1);
|
filedes[1] = _open_osfhandle (handle_to_fd (fds[1]), 1);
|
||||||
if (filedes[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]);
|
close (filedes[0]);
|
||||||
filedes[0] = -1;
|
filedes[0] = -1;
|
||||||
CloseHandle (fd_to_handle (fds[1]));
|
CloseHandle (fds[1]);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
err = 0;
|
err = 0;
|
||||||
@ -365,9 +365,12 @@ gnupg_create_outbound_pipe (int filedes[2])
|
|||||||
/* Fork and exec the PGMNAME, see exechelp.h for details. */
|
/* Fork and exec the PGMNAME, see exechelp.h for details. */
|
||||||
gpg_error_t
|
gpg_error_t
|
||||||
gnupg_spawn_process (const char *pgmname, const char *argv[],
|
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,
|
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;
|
gpg_error_t err;
|
||||||
SECURITY_ATTRIBUTES sec_attr;
|
SECURITY_ATTRIBUTES sec_attr;
|
||||||
@ -381,32 +384,103 @@ gnupg_spawn_process (const char *pgmname, const char *argv[],
|
|||||||
STARTUPINFO si;
|
STARTUPINFO si;
|
||||||
int cr_flags;
|
int cr_flags;
|
||||||
char *cmdline;
|
char *cmdline;
|
||||||
int fd, fdout, rp[2];
|
HANDLE inhandle = INVALID_HANDLE_VALUE;
|
||||||
HANDLE nullhd[2];
|
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;
|
int i;
|
||||||
|
es_syshd_t syshd;
|
||||||
|
|
||||||
(void)preexec;
|
if (r_outfp)
|
||||||
|
*r_outfp = NULL;
|
||||||
/* Setup return values. */
|
if (r_errfp)
|
||||||
*statusfile = NULL;
|
*r_errfp = NULL;
|
||||||
*pid = (pid_t)(-1);
|
*pid = (pid_t)(-1); /* Always required. */
|
||||||
|
|
||||||
if (infile)
|
if (infp)
|
||||||
{
|
{
|
||||||
es_fflush (infile);
|
es_fflush (infp);
|
||||||
es_rewind (infile);
|
es_rewind (infp);
|
||||||
fd = _get_osfhandle (es_fileno (infile));
|
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)
|
if (r_outfp)
|
||||||
fdout = _get_osfhandle (es_fileno (outfile));
|
{
|
||||||
else
|
if (create_inheritable_pipe (outpipe, 1))
|
||||||
fdout = -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))
|
syshd.type = ES_SYSHD_HANDLE;
|
||||||
log_fatal ("no file descriptor for file passed to gnupg_spawn_process\n");
|
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. */
|
/* Prepare security attributes. */
|
||||||
memset (&sec_attr, 0, sizeof sec_attr );
|
memset (&sec_attr, 0, sizeof sec_attr );
|
||||||
@ -418,27 +492,24 @@ gnupg_spawn_process (const char *pgmname, const char *argv[],
|
|||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
/* Create a pipe. */
|
if (inhandle != INVALID_HANDLE_VALUE)
|
||||||
if (create_inheritable_pipe (rp, 1))
|
nullhd[0] = w32_open_null (0);
|
||||||
{
|
if (outpipe[1] != INVALID_HANDLE_VALUE)
|
||||||
err = gpg_error (GPG_ERR_GENERAL);
|
nullhd[1] = w32_open_null (0);
|
||||||
log_error (_("error creating a pipe: %s\n"), gpg_strerror (err));
|
if (errpipe[1] != INVALID_HANDLE_VALUE)
|
||||||
xfree (cmdline);
|
nullhd[2] = w32_open_null (0);
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
nullhd[0] = fd == -1? w32_open_null (0) : INVALID_HANDLE_VALUE;
|
|
||||||
nullhd[1] = fdout == -1? w32_open_null (1) : INVALID_HANDLE_VALUE;
|
|
||||||
|
|
||||||
/* Start the process. Note that we can't run the PREEXEC function
|
/* 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);
|
memset (&si, 0, sizeof si);
|
||||||
si.cb = sizeof (si);
|
si.cb = sizeof (si);
|
||||||
si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
|
si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
|
||||||
si.wShowWindow = DEBUG_W32_SPAWN? SW_SHOW : SW_MINIMIZE;
|
si.wShowWindow = DEBUG_W32_SPAWN? SW_SHOW : SW_MINIMIZE;
|
||||||
si.hStdInput = fd == -1? nullhd[0] : fd_to_handle (fd);
|
si.hStdInput = inhandle == INVALID_HANDLE_VALUE? nullhd[0] : inhandle;
|
||||||
si.hStdOutput = fdout == -1? nullhd[1] : fd_to_handle (fdout);
|
si.hStdOutput = outpipe[1] == INVALID_HANDLE_VALUE? nullhd[1] : outpipe[1];
|
||||||
si.hStdError = fd_to_handle (rp[1]);
|
si.hStdError = errpipe[1] == INVALID_HANDLE_VALUE? nullhd[2] : errpipe[1];
|
||||||
|
|
||||||
cr_flags = (CREATE_DEFAULT_ERROR_MODE
|
cr_flags = (CREATE_DEFAULT_ERROR_MODE
|
||||||
| ((flags & 128)? DETACHED_PROCESS : 0)
|
| ((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));
|
log_error ("CreateProcess failed: %s\n", w32_strerror (-1));
|
||||||
xfree (cmdline);
|
xfree (cmdline);
|
||||||
CloseHandle (fd_to_handle (rp[0]));
|
if (outfp)
|
||||||
CloseHandle (fd_to_handle (rp[1]));
|
es_fclose (outfp);
|
||||||
return gpg_error (GPG_ERR_GENERAL);
|
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);
|
xfree (cmdline);
|
||||||
cmdline = NULL;
|
cmdline = NULL;
|
||||||
@ -471,17 +552,21 @@ gnupg_spawn_process (const char *pgmname, const char *argv[],
|
|||||||
if (nullhd[i] != INVALID_HANDLE_VALUE)
|
if (nullhd[i] != INVALID_HANDLE_VALUE)
|
||||||
CloseHandle (nullhd[i]);
|
CloseHandle (nullhd[i]);
|
||||||
|
|
||||||
/* Close the other end of the pipe. */
|
/* Close the inherited ends of the pipes. */
|
||||||
CloseHandle (fd_to_handle (rp[1]));
|
if (outpipe[1] != INVALID_HANDLE_VALUE)
|
||||||
|
CloseHandle (outpipe[1]);
|
||||||
/* log_debug ("CreateProcess ready: hProcess=%p hThread=%p" */
|
if (errpipe[1] != INVALID_HANDLE_VALUE)
|
||||||
/* " dwProcessID=%d dwThreadId=%d\n", */
|
CloseHandle (errpipe[1]);
|
||||||
/* pi.hProcess, pi.hThread, */
|
|
||||||
/* (int) pi.dwProcessId, (int) pi.dwThreadId); */
|
|
||||||
|
|
||||||
|
/* 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
|
/* Fixme: For unknown reasons AllowSetForegroundWindow returns an
|
||||||
invalid argument error if we pass the correct processID to
|
invalid argument error if we pass it the correct processID. As a
|
||||||
it. As a workaround we use -1 (ASFW_ANY). */
|
workaround we use -1 (ASFW_ANY). */
|
||||||
if ( (flags & 64) )
|
if ( (flags & 64) )
|
||||||
gnupg_allow_set_foregound_window ((pid_t)(-1)/*pi.dwProcessId*/);
|
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);
|
ResumeThread (pi.hThread);
|
||||||
CloseHandle (pi.hThread);
|
CloseHandle (pi.hThread);
|
||||||
|
|
||||||
{
|
if (r_outfp)
|
||||||
int x;
|
*r_outfp = outfp;
|
||||||
|
if (r_errfp)
|
||||||
x = _open_osfhandle (rp[0], 0);
|
*r_errfp = errfp;
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
*pid = handle_to_pid (pi.hProcess);
|
*pid = handle_to_pid (pi.hProcess);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -83,7 +83,7 @@ struct feeder_thread_parms
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/* The thread started by start_feeded. */
|
/* The thread started by start_feede3. */
|
||||||
static void *
|
static void *
|
||||||
feeder_thread (void *arg)
|
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. */
|
/* Fork and exec the PGMNAME, see exechelp.h for details. */
|
||||||
gpg_error_t
|
gpg_error_t
|
||||||
gnupg_spawn_process (const char *pgmname, const char *argv[],
|
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,
|
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;
|
gpg_error_t err;
|
||||||
PROCESS_INFORMATION pi = {NULL };
|
PROCESS_INFORMATION pi = {NULL };
|
||||||
char *cmdline;
|
char *cmdline;
|
||||||
@ -598,7 +602,9 @@ gnupg_spawn_process (const char *pgmname, const char *argv[],
|
|||||||
|
|
||||||
*pid = handle_to_pid (pi.hProcess);
|
*pid = handle_to_pid (pi.hProcess);
|
||||||
return 0;
|
return 0;
|
||||||
|
#else
|
||||||
|
return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -52,15 +52,24 @@ gpg_error_t gnupg_create_inbound_pipe (int filedes[2]);
|
|||||||
gpg_error_t gnupg_create_outbound_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
|
/* Fork and exec the PGMNAME. If INFP is NULL connect /dev/null to
|
||||||
stdin, write the output to OUTFILE. INFILE or PUTFILE may be NULL
|
stdin of the new process; if it is not NULL connect the file
|
||||||
to connect thenm to /dev/null. Returns a new stream in STATUSFILE
|
descriptor retrieved from INFP to stdin. If R_OUTFP is NULL
|
||||||
for stderr and the pid of the process in PID. The arguments for the
|
connect stdout of the new process to /dev/null; if it is not NULL
|
||||||
process are expected in the NULL terminated array ARGV. The
|
store the address of a pointer to a new estream there. If R_ERRFP
|
||||||
program name itself should not be included there. If PREEXEC is
|
is NULL connect stderr of the new process to /dev/null; if it is
|
||||||
not NULL, that function will be called right before the exec.
|
not NULL store the address of a pointer to a new estream there. On
|
||||||
Calling gnupg_wait_process and gnupg_release_process is required.
|
success the pid of the new process is stored at PID. On error -1
|
||||||
Returns 0 on success or an error code.
|
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:
|
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.
|
allows SetForegroundWindow for all childs of this process.
|
||||||
|
|
||||||
*/
|
*/
|
||||||
gpg_error_t gnupg_spawn_process (const char *pgmname, const char *argv[],
|
gpg_error_t
|
||||||
estream_t infile, estream_t outfile,
|
gnupg_spawn_process (const char *pgmname, const char *argv[],
|
||||||
void (*preexec)(void), unsigned int flags,
|
gpg_err_source_t errsource,
|
||||||
estream_t *statusfile, pid_t *pid);
|
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
|
/* Simplified version of gnupg_spawn_process. This function forks and
|
||||||
|
@ -1,5 +1,16 @@
|
|||||||
|
2010-08-20 Werner Koch <wk@g10code.com>
|
||||||
|
|
||||||
|
* gpgconf-comp.c (collect_error_output): Remove extra CRs.
|
||||||
|
|
||||||
2010-08-19 Werner Koch <wk@g10code.com>
|
2010-08-19 Werner Koch <wk@g10code.com>
|
||||||
|
|
||||||
|
* gpgconf.c (main): Fix --check-options.
|
||||||
|
|
||||||
|
* gpgconf-comp.c (gc_component_check_options): Replace
|
||||||
|
gnupg_spawn_process_fd by gnupg_spawn_process.
|
||||||
|
(retrieve_options_from_program): Ditto.
|
||||||
|
(collect_error_output): Change to use estream.
|
||||||
|
|
||||||
* gpgconf-comp.c: Add new backend and component for PINENTRY.
|
* gpgconf-comp.c: Add new backend and component for PINENTRY.
|
||||||
(gc_component_check_options): Use --version to test the pinentry.
|
(gc_component_check_options): Use --version to test the pinentry.
|
||||||
(gc_component_retrieve_options, gc_component_change_options):
|
(gc_component_retrieve_options, gc_component_change_options):
|
||||||
|
@ -1363,14 +1363,12 @@ all_digits_p (const char *p, size_t len)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Collect all error lines from file descriptor FD. Only lines
|
/* Collect all error lines from stream FP. Only lines prefixed with
|
||||||
prefixed with TAG are considered. Close that file descriptor
|
TAG are considered. Returns a list of error line items (which may
|
||||||
then. Returns a list of error line items (which may be empty).
|
be empty). There is no error return. */
|
||||||
There is no error return. */
|
|
||||||
static error_line_t
|
static error_line_t
|
||||||
collect_error_output (int fd, const char *tag)
|
collect_error_output (estream_t fp, const char *tag)
|
||||||
{
|
{
|
||||||
FILE *fp;
|
|
||||||
char buffer[1024];
|
char buffer[1024];
|
||||||
char *p, *p2, *p3;
|
char *p, *p2, *p3;
|
||||||
int c, cont_line;
|
int c, cont_line;
|
||||||
@ -1378,15 +1376,11 @@ collect_error_output (int fd, const char *tag)
|
|||||||
error_line_t eitem, errlines, *errlines_tail;
|
error_line_t eitem, errlines, *errlines_tail;
|
||||||
size_t taglen = strlen (tag);
|
size_t taglen = strlen (tag);
|
||||||
|
|
||||||
fp = fdopen (fd, "r");
|
|
||||||
if (!fp)
|
|
||||||
gc_error (1, errno, "can't fdopen pipe for reading");
|
|
||||||
|
|
||||||
errlines = NULL;
|
errlines = NULL;
|
||||||
errlines_tail = &errlines;
|
errlines_tail = &errlines;
|
||||||
pos = 0;
|
pos = 0;
|
||||||
cont_line = 0;
|
cont_line = 0;
|
||||||
while ((c=getc (fp)) != EOF)
|
while ((c=es_getc (fp)) != EOF)
|
||||||
{
|
{
|
||||||
buffer[pos++] = c;
|
buffer[pos++] = c;
|
||||||
if (pos >= sizeof buffer - 5 || c == '\n')
|
if (pos >= sizeof buffer - 5 || c == '\n')
|
||||||
@ -1401,6 +1395,7 @@ collect_error_output (int fd, const char *tag)
|
|||||||
p = buffer + taglen + 1;
|
p = buffer + taglen + 1;
|
||||||
while (*p == ' ' || *p == '\t')
|
while (*p == ' ' || *p == '\t')
|
||||||
p++;
|
p++;
|
||||||
|
trim_trailing_spaces (p); /* Get rid of extra CRs. */
|
||||||
if (!*p)
|
if (!*p)
|
||||||
; /* Empty lines are ignored. */
|
; /* Empty lines are ignored. */
|
||||||
else if ( (p2 = strchr (p, ':')) && (p3 = strchr (p2+1, ':'))
|
else if ( (p2 = strchr (p, ':')) && (p3 = strchr (p2+1, ':'))
|
||||||
@ -1445,8 +1440,6 @@ collect_error_output (int fd, const char *tag)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* We ignore error lines not terminated by a LF. */
|
/* We ignore error lines not terminated by a LF. */
|
||||||
|
|
||||||
fclose (fp);
|
|
||||||
return errlines;
|
return errlines;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1466,14 +1459,9 @@ gc_component_check_options (int component, estream_t out, const char *conf_file)
|
|||||||
int i;
|
int i;
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
int exitcode;
|
int exitcode;
|
||||||
int filedes[2];
|
estream_t errfp;
|
||||||
error_line_t errlines;
|
error_line_t errlines;
|
||||||
|
|
||||||
/* We use a temporary file to collect the error output. It would be
|
|
||||||
better to use a pipe here but as of now we have no suitable
|
|
||||||
fucntion to create a portable pipe outside of exechelp. Thus it
|
|
||||||
is easier to use the tempfile approach. */
|
|
||||||
|
|
||||||
for (backend = 0; backend < GC_BACKEND_NR; backend++)
|
for (backend = 0; backend < GC_BACKEND_NR; backend++)
|
||||||
backend_seen[backend] = 0;
|
backend_seen[backend] = 0;
|
||||||
|
|
||||||
@ -1510,23 +1498,15 @@ gc_component_check_options (int component, estream_t out, const char *conf_file)
|
|||||||
argv[i++] = "--gpgconf-test";
|
argv[i++] = "--gpgconf-test";
|
||||||
argv[i++] = NULL;
|
argv[i++] = NULL;
|
||||||
|
|
||||||
err = gnupg_create_inbound_pipe (filedes);
|
|
||||||
if (err)
|
|
||||||
gc_error (1, 0, _("error creating a pipe: %s\n"),
|
|
||||||
gpg_strerror (err));
|
|
||||||
|
|
||||||
result = 0;
|
result = 0;
|
||||||
errlines = NULL;
|
errlines = NULL;
|
||||||
if (gnupg_spawn_process_fd (pgmname, argv, -1, -1, filedes[1], &pid))
|
err = gnupg_spawn_process (pgmname, argv, GPG_ERR_SOURCE_DEFAULT, NULL, 0,
|
||||||
{
|
NULL, NULL, &errfp, &pid);
|
||||||
close (filedes[0]);
|
if (err)
|
||||||
close (filedes[1]);
|
result |= 1; /* Program could not be run. */
|
||||||
result |= 1; /* Program could not be run. */
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
close (filedes[1]);
|
errlines = collect_error_output (errfp,
|
||||||
errlines = collect_error_output (filedes[0],
|
|
||||||
gc_component[component].name);
|
gc_component[component].name);
|
||||||
if (gnupg_wait_process (pgmname, pid, 1, &exitcode))
|
if (gnupg_wait_process (pgmname, pid, 1, &exitcode))
|
||||||
{
|
{
|
||||||
@ -1536,6 +1516,7 @@ gc_component_check_options (int component, estream_t out, const char *conf_file)
|
|||||||
result |= 2; /* Program returned an error. */
|
result |= 2; /* Program returned an error. */
|
||||||
}
|
}
|
||||||
gnupg_release_process (pid);
|
gnupg_release_process (pid);
|
||||||
|
es_fclose (errfp);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If the program could not be run, we can't tell whether
|
/* If the program could not be run, we can't tell whether
|
||||||
@ -1839,41 +1820,32 @@ static void
|
|||||||
retrieve_options_from_program (gc_component_t component, gc_backend_t backend)
|
retrieve_options_from_program (gc_component_t component, gc_backend_t backend)
|
||||||
{
|
{
|
||||||
gpg_error_t err;
|
gpg_error_t err;
|
||||||
int filedes[2];
|
|
||||||
const char *pgmname;
|
const char *pgmname;
|
||||||
const char *argv[2];
|
const char *argv[2];
|
||||||
|
estream_t outfp;
|
||||||
int exitcode;
|
int exitcode;
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
char *line = NULL;
|
char *line = NULL;
|
||||||
size_t line_len = 0;
|
size_t line_len = 0;
|
||||||
ssize_t length;
|
ssize_t length;
|
||||||
FILE *config;
|
estream_t config;
|
||||||
char *config_filename;
|
char *config_filename;
|
||||||
|
|
||||||
err = gnupg_create_inbound_pipe (filedes);
|
|
||||||
if (err)
|
|
||||||
gc_error (1, 0, _("error creating a pipe: %s\n"), gpg_strerror (err));
|
|
||||||
|
|
||||||
pgmname = (gc_backend[backend].module_name
|
pgmname = (gc_backend[backend].module_name
|
||||||
? gnupg_module_name (gc_backend[backend].module_name)
|
? gnupg_module_name (gc_backend[backend].module_name)
|
||||||
: gc_backend[backend].program );
|
: gc_backend[backend].program );
|
||||||
argv[0] = "--gpgconf-list";
|
argv[0] = "--gpgconf-list";
|
||||||
argv[1] = NULL;
|
argv[1] = NULL;
|
||||||
|
|
||||||
err = gnupg_spawn_process_fd (pgmname, argv, -1, filedes[1], -1, &pid);
|
err = gnupg_spawn_process (pgmname, argv, GPG_ERR_SOURCE_DEFAULT, NULL, 0,
|
||||||
|
NULL, &outfp, NULL, &pid);
|
||||||
if (err)
|
if (err)
|
||||||
{
|
{
|
||||||
close (filedes[0]);
|
|
||||||
close (filedes[1]);
|
|
||||||
gc_error (1, 0, "could not gather active options from `%s': %s",
|
gc_error (1, 0, "could not gather active options from `%s': %s",
|
||||||
pgmname, gpg_strerror (err));
|
pgmname, gpg_strerror (err));
|
||||||
}
|
}
|
||||||
close (filedes[1]);
|
|
||||||
config = fdopen (filedes[0], "r");
|
|
||||||
if (!config)
|
|
||||||
gc_error (1, errno, "can't fdopen pipe for reading");
|
|
||||||
|
|
||||||
while ((length = read_line (config, &line, &line_len, NULL)) > 0)
|
while ((length = es_read_line (outfp, &line, &line_len, NULL)) > 0)
|
||||||
{
|
{
|
||||||
gc_option_t *option;
|
gc_option_t *option;
|
||||||
char *linep;
|
char *linep;
|
||||||
@ -1942,9 +1914,9 @@ retrieve_options_from_program (gc_component_t component, gc_backend_t backend)
|
|||||||
option->default_value = xstrdup (default_value);
|
option->default_value = xstrdup (default_value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (length < 0 || ferror (config))
|
if (length < 0 || es_ferror (outfp))
|
||||||
gc_error (1, errno, "error reading from %s",pgmname);
|
gc_error (1, errno, "error reading from %s", pgmname);
|
||||||
if (fclose (config) && ferror (config))
|
if (es_fclose (outfp) && es_ferror (outfp))
|
||||||
gc_error (1, errno, "error closing %s", pgmname);
|
gc_error (1, errno, "error closing %s", pgmname);
|
||||||
|
|
||||||
err = gnupg_wait_process (pgmname, pid, 1, &exitcode);
|
err = gnupg_wait_process (pgmname, pid, 1, &exitcode);
|
||||||
@ -1957,13 +1929,13 @@ retrieve_options_from_program (gc_component_t component, gc_backend_t backend)
|
|||||||
/* At this point, we can parse the configuration file. */
|
/* At this point, we can parse the configuration file. */
|
||||||
config_filename = get_config_filename (component, backend);
|
config_filename = get_config_filename (component, backend);
|
||||||
|
|
||||||
config = fopen (config_filename, "r");
|
config = es_fopen (config_filename, "r");
|
||||||
if (!config)
|
if (!config)
|
||||||
gc_error (0, errno, "warning: can not open config file %s",
|
gc_error (0, errno, "warning: can not open config file %s",
|
||||||
config_filename);
|
config_filename);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
while ((length = read_line (config, &line, &line_len, NULL)) > 0)
|
while ((length = es_read_line (config, &line, &line_len, NULL)) > 0)
|
||||||
{
|
{
|
||||||
char *name;
|
char *name;
|
||||||
char *value;
|
char *value;
|
||||||
@ -2044,9 +2016,9 @@ retrieve_options_from_program (gc_component_t component, gc_backend_t backend)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (length < 0 || ferror (config))
|
if (length < 0 || es_ferror (config))
|
||||||
gc_error (1, errno, "error reading from %s", config_filename);
|
gc_error (1, errno, "error reading from %s", config_filename);
|
||||||
if (fclose (config) && ferror (config))
|
if (es_fclose (config) && es_ferror (config))
|
||||||
gc_error (1, errno, "error closing %s", config_filename);
|
gc_error (1, errno, "error closing %s", config_filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -226,15 +226,18 @@ main (int argc, char **argv)
|
|||||||
es_putc ('\n', es_stderr);
|
es_putc ('\n', es_stderr);
|
||||||
exit (1);
|
exit (1);
|
||||||
}
|
}
|
||||||
gc_component_retrieve_options (idx);
|
if (cmd == aCheckOptions)
|
||||||
if (gc_process_gpgconf_conf (NULL, 1, 0, NULL))
|
|
||||||
exit (1);
|
|
||||||
if (cmd == aListOptions)
|
|
||||||
gc_component_list_options (idx, get_outfp (&outfp));
|
|
||||||
else if (cmd == aChangeOptions)
|
|
||||||
gc_component_change_options (idx, es_stdin, get_outfp (&outfp));
|
|
||||||
else
|
|
||||||
gc_component_check_options (idx, get_outfp (&outfp), NULL);
|
gc_component_check_options (idx, get_outfp (&outfp), NULL);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
gc_component_retrieve_options (idx);
|
||||||
|
if (gc_process_gpgconf_conf (NULL, 1, 0, NULL))
|
||||||
|
exit (1);
|
||||||
|
if (cmd == aListOptions)
|
||||||
|
gc_component_list_options (idx, get_outfp (&outfp));
|
||||||
|
else if (cmd == aChangeOptions)
|
||||||
|
gc_component_change_options (idx, es_stdin, get_outfp (&outfp));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user