[Pkg-gnupg-commit] [gnupg2] 37/102: common: Add a status callback to gnupg_exec_tool_stream.
Daniel Kahn Gillmor
dkg at fifthhorseman.net
Fri Jun 17 00:14:52 UTC 2016
This is an automated email from the git hooks/post-receive script.
dkg pushed a commit to branch experimental
in repository gnupg2.
commit 239a4d53916b47b5b0f0167a9b2c7a8915bb9c52
Author: Werner Koch <wk at gnupg.org>
Date: Sat May 28 00:07:09 2016 +0200
common: Add a status callback to gnupg_exec_tool_stream.
* common/exectool.h (exec_tool_status_cb_t): New.
* common/exectool.c: Include missing exectool.h.
(read_and_log_buffer_t): Replace array by pointer.
(gnupg_exec_tool_stream): Add args 'status_cb' and 'status_cb_value'.
Change all callers to pass NULL for them. Malloc buffer for
FDERRSTATE.
(read_and_log_stderr): Implement status_fd feature.
Signed-off-by: Werner Koch <wk at gnupg.org>
---
common/exectool.c | 93 +++++++++++++++++++++++++++++++++++++++++++-------
common/exectool.h | 15 +++++++-
tools/gpgtar-create.c | 2 +-
tools/gpgtar-extract.c | 2 +-
tools/gpgtar-list.c | 2 +-
5 files changed, 97 insertions(+), 17 deletions(-)
diff --git a/common/exectool.c b/common/exectool.c
index 953c34a..897450e 100644
--- a/common/exectool.c
+++ b/common/exectool.c
@@ -44,13 +44,17 @@
#include "exechelp.h"
#include "sysutils.h"
#include "util.h"
+#include "exectool.h"
typedef struct
{
const char *pgmname;
+ exec_tool_status_cb_t status_cb;
+ void *status_cb_value;
int cont;
- int used;
- char buffer[256];
+ size_t used;
+ size_t buffer_size;
+ char *buffer;
} read_and_log_buffer_t;
@@ -83,14 +87,37 @@ read_and_log_stderr (read_and_log_buffer_t *state, es_poll_t *fderr)
pname++;
else
pname = state->pgmname;
- /* If our pgmname plus colon is identical to the start of
- the output, print only the output. */
len = strlen (pname);
- if (!state->cont
+
+ if (state->status_cb
+ && !strncmp (state->buffer, "[GNUPG:] ", 9)
+ && state->buffer[9] >= 'A' && state->buffer[9] <= 'Z')
+ {
+ char *rest;
+
+ rest = strchr (state->buffer + 9, ' ');
+ if (!rest)
+ {
+ /* Set REST to an empty string. */
+ rest = state->buffer + strlen (state->buffer);
+ }
+ else
+ {
+ *rest++ = 0;
+ trim_spaces (rest);
+ }
+ state->status_cb (state->status_cb_value,
+ state->buffer + 9, rest);
+ }
+ else if (!state->cont
&& !strncmp (state->buffer, pname, len)
&& strlen (state->buffer) > strlen (pname)
&& state->buffer[len] == ':' )
- log_info ("%s\n", state->buffer);
+ {
+ /* PGMNAME plus colon is identical to the start of
+ the output: print only the output. */
+ log_info ("%s\n", state->buffer);
+ }
else
log_info ("%s%c %s\n",
pname, state->cont? '+':':', state->buffer);
@@ -123,10 +150,39 @@ read_and_log_stderr (read_and_log_buffer_t *state, es_poll_t *fderr)
}
else
{
- if (state->used >= sizeof state->buffer - 1)
+ if (state->used >= state->buffer_size - 1)
{
- read_and_log_stderr (state, NULL);
- state->cont = 1;
+ if (state->status_cb)
+ {
+ /* A status callback requires that we have a full
+ * line. Thus we need to enlarget the buffer in
+ * this case. */
+ char *newbuffer;
+ size_t newsize = state->buffer_size + 256;
+
+ newbuffer = xtrymalloc (newsize);
+ if (!newbuffer)
+ {
+ log_error ("error allocating memory for status cb: %s\n",
+ gpg_strerror (my_error_from_syserror ()));
+ /* We better disable the status CB in this case. */
+ state->status_cb = NULL;
+ read_and_log_stderr (state, NULL);
+ state->cont = 1;
+ }
+ else
+ {
+ memcpy (newbuffer, state->buffer, state->used);
+ xfree (state->buffer);
+ state->buffer = newbuffer;
+ state->buffer_size = newsize;
+ }
+ }
+ else
+ {
+ read_and_log_stderr (state, NULL);
+ state->cont = 1;
+ }
}
state->buffer[state->used++] = c;
}
@@ -242,7 +298,9 @@ copy_buffer_flush (struct copy_buffer *c, estream_t sink)
gpg_error_t
gnupg_exec_tool_stream (const char *pgmname, const char *argv[],
estream_t input, estream_t inextra,
- estream_t output)
+ estream_t output,
+ exec_tool_status_cb_t status_cb,
+ void *status_cb_value)
{
gpg_error_t err;
pid_t pid;
@@ -265,6 +323,14 @@ gnupg_exec_tool_stream (const char *pgmname, const char *argv[],
copy_buffer_init (&cpbuf_out);
copy_buffer_init (&cpbuf_extra);
+ fderrstate.pgmname = pgmname;
+ fderrstate.status_cb = status_cb;
+ fderrstate.status_cb_value = status_cb_value;
+ fderrstate.buffer_size = 256;
+ fderrstate.buffer = xtrymalloc (fderrstate.buffer_size);
+ if (!fderrstate.buffer)
+ return my_error_from_syserror ();
+
if (inextra)
{
err = gnupg_create_outbound_pipe (extrapipe, &extrafp, 1);
@@ -272,6 +338,7 @@ gnupg_exec_tool_stream (const char *pgmname, const char *argv[],
{
log_error ("error running outbound pipe for extra fp: %s\n",
gpg_strerror (err));
+ xfree (fderrstate.buffer);
return err;
}
exceptclose[0] = extrapipe[0]; /* Do not close in child. */
@@ -303,11 +370,10 @@ gnupg_exec_tool_stream (const char *pgmname, const char *argv[],
{
log_error ("error running '%s': %s\n", pgmname, gpg_strerror (err));
es_fclose (extrafp);
+ xfree (fderrstate.buffer);
return err;
}
- fderrstate.pgmname = pgmname;
-
fds[0].stream = infp;
fds[0].want_write = 1;
if (!input)
@@ -438,6 +504,7 @@ gnupg_exec_tool_stream (const char *pgmname, const char *argv[],
copy_buffer_shred (&cpbuf_out);
if (inextra)
copy_buffer_shred (&cpbuf_extra);
+ xfree (fderrstate.buffer);
return err;
}
@@ -488,7 +555,7 @@ gnupg_exec_tool (const char *pgmname, const char *argv[],
goto leave;
}
- err = gnupg_exec_tool_stream (pgmname, argv, input, NULL, output);
+ err = gnupg_exec_tool_stream (pgmname, argv, input, NULL, output, NULL, NULL);
if (err)
goto leave;
diff --git a/common/exectool.h b/common/exectool.h
index 21bc177..94091fd 100644
--- a/common/exectool.h
+++ b/common/exectool.h
@@ -32,6 +32,17 @@
#include <gpg-error.h>
+/* This callback can be used to process --status-fd outputs of GnuPG
+ * tools. OPAQUE can be used to communicate between the caller of the
+ * function and the callback. KEYWORD is the status keyword (see
+ * doc/DETAILS); it is never NULL. ARGS are the arguments of the
+ * status line and will also never be NULL; the caller may modify this
+ * string. */
+typedef void (*exec_tool_status_cb_t) (void *opaque,
+ const char *keyword,
+ char *args);
+
+
/* Run the program PGMNAME with the command line arguments given in
the NULL terminates array ARGV. If INPUT_STRING is not NULL it
will be fed to stdin of the process. stderr is logged using
@@ -51,6 +62,8 @@ gpg_error_t gnupg_exec_tool (const char *pgmname, const char *argv[],
printed, and an error code returned. INEXTRA is reserved. */
gpg_error_t gnupg_exec_tool_stream (const char *pgmname, const char *argv[],
estream_t input, estream_t inextra,
- estream_t output);
+ estream_t output,
+ exec_tool_status_cb_t status_cb,
+ void *status_cb_value);
#endif /* GNUPG_COMMON_EXECTOOL_H */
diff --git a/tools/gpgtar-create.c b/tools/gpgtar-create.c
index d615fd3..6adc1f5 100644
--- a/tools/gpgtar-create.c
+++ b/tools/gpgtar-create.c
@@ -932,7 +932,7 @@ gpgtar_create (char **inpattern, int encrypt, int sign)
}
err = gnupg_exec_tool_stream (opt.gpg_program, argv,
- outstream, NULL, cipher_stream);
+ outstream, NULL, cipher_stream, NULL, NULL);
xfree (argv);
if (err)
goto leave;
diff --git a/tools/gpgtar-extract.c b/tools/gpgtar-extract.c
index c4bf440..866215b 100644
--- a/tools/gpgtar-extract.c
+++ b/tools/gpgtar-extract.c
@@ -327,7 +327,7 @@ gpgtar_extract (const char *filename, int decrypt)
}
err = gnupg_exec_tool_stream (opt.gpg_program, argv,
- cipher_stream, NULL, stream);
+ cipher_stream, NULL, stream, NULL, NULL);
xfree (argv);
if (err)
goto leave;
diff --git a/tools/gpgtar-list.c b/tools/gpgtar-list.c
index a3f85ac..1d59d9c 100644
--- a/tools/gpgtar-list.c
+++ b/tools/gpgtar-list.c
@@ -327,7 +327,7 @@ gpgtar_list (const char *filename, int decrypt)
}
err = gnupg_exec_tool_stream (opt.gpg_program, argv,
- cipher_stream, NULL, stream);
+ cipher_stream, NULL, stream, NULL, NULL);
xfree (argv);
if (err)
goto leave;
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-gnupg/gnupg2.git
More information about the Pkg-gnupg-commit
mailing list