From 0e242278dfaa64ce31a45b72f5fa0806a3dba898 Mon Sep 17 00:00:00 2001 From: Justus Winter Date: Thu, 12 Jan 2017 14:05:15 +0100 Subject: [PATCH] Fix changing options with gpgconf. * src/engine-gpgconf.c (gpgconf_write): Connect a pipe to the child's stderr, and wait for it to be closed as an indication that gpgconf has exited. Also improve error handling. GnuPG-bug-id: 2881 Signed-off-by: Justus Winter --- src/engine-gpgconf.c | 66 ++++++++++++++++++++++++++++++++++++-------- 1 file changed, 54 insertions(+), 12 deletions(-) diff --git a/src/engine-gpgconf.c b/src/engine-gpgconf.c index 01a60eb1..3e463105 100644 --- a/src/engine-gpgconf.c +++ b/src/engine-gpgconf.c @@ -710,8 +710,11 @@ gpgconf_write (void *engine, const char *arg1, char *arg2, gpgme_data_t conf) int buflen = 0; char *argv[7]; int argc = 0; - int rp[2]; - struct spawn_fd_item_s cfd[] = { {-1, 0 /* STDIN_FILENO */}, {-1, -1} }; + int rp[2] = { -1, -1 }; + int errp[2] = { -1, -1 }; + struct spawn_fd_item_s cfd[] = { {-1, 0 /* STDIN_FILENO */}, + {-1, 2 /* STDERR_FILENO */, -1}, + {-1, -1} }; int status; int nwrite; @@ -731,19 +734,31 @@ gpgconf_write (void *engine, const char *arg1, char *arg2, gpgme_data_t conf) assert (argc < DIM (argv)); if (_gpgme_io_pipe (rp, 0) < 0) - return gpg_error_from_syserror (); + { + err = gpg_error_from_syserror (); + goto leave; + } + + if (_gpgme_io_pipe (errp, 1) < 0) + { + err = gpg_error_from_syserror (); + goto leave; + } cfd[0].fd = rp[0]; + cfd[1].fd = errp[1]; status = _gpgme_io_spawn (gpgconf->file_name, argv, IOSPAWN_FLAG_DETACHED, cfd, NULL, NULL, NULL); if (status < 0) { - _gpgme_io_close (rp[0]); - _gpgme_io_close (rp[1]); - return gpg_error_from_syserror (); + err = gpg_error_from_syserror (); + goto leave; } + rp[0] = -1; + errp[1] = -1; + for (;;) { if (buflen == 0) @@ -757,14 +772,29 @@ gpgconf_write (void *engine, const char *arg1, char *arg2, gpgme_data_t conf) if (buflen < 0) { err = gpg_error_from_syserror (); - _gpgme_io_close (rp[1]); - return err; + goto leave; } else if (buflen == 0) { /* All is written. */ _gpgme_io_close (rp[1]); - return 0; + rp[1] = -1; + + for (;;) + { + do + { + buflen = _gpgme_io_read (errp[0], buf, BUFLEN); + } + while (buflen < 0 && errno == EAGAIN); + + if (buflen == 0) + { + err = 0; + goto leave; + } + /* XXX: Do something useful with BUF. */ + } } } @@ -782,12 +812,24 @@ gpgconf_write (void *engine, const char *arg1, char *arg2, gpgme_data_t conf) } else if (nwrite < 0) { - _gpgme_io_close (rp[1]); - return gpg_error_from_syserror (); + err = gpg_error_from_syserror (); + goto leave; } } - return 0; + assert (! "reached"); + + leave: + if (rp[0] != -1) + _gpgme_io_close (rp[0]); + if (rp[1] != -1) + _gpgme_io_close (rp[1]); + if (errp[0] != -1) + _gpgme_io_close (errp[0]); + if (errp[1] != -1) + _gpgme_io_close (errp[1]); + + return err; }