mirror of
git://git.gnupg.org/gnupg.git
synced 2025-03-11 22:52:47 +01:00
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@gnupg.org>
This commit is contained in:
parent
44a32455c8
commit
239a4d5391
@ -44,13 +44,17 @@
|
|||||||
#include "exechelp.h"
|
#include "exechelp.h"
|
||||||
#include "sysutils.h"
|
#include "sysutils.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
#include "exectool.h"
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
const char *pgmname;
|
const char *pgmname;
|
||||||
|
exec_tool_status_cb_t status_cb;
|
||||||
|
void *status_cb_value;
|
||||||
int cont;
|
int cont;
|
||||||
int used;
|
size_t used;
|
||||||
char buffer[256];
|
size_t buffer_size;
|
||||||
|
char *buffer;
|
||||||
} read_and_log_buffer_t;
|
} read_and_log_buffer_t;
|
||||||
|
|
||||||
|
|
||||||
@ -83,14 +87,37 @@ read_and_log_stderr (read_and_log_buffer_t *state, es_poll_t *fderr)
|
|||||||
pname++;
|
pname++;
|
||||||
else
|
else
|
||||||
pname = state->pgmname;
|
pname = state->pgmname;
|
||||||
/* If our pgmname plus colon is identical to the start of
|
|
||||||
the output, print only the output. */
|
|
||||||
len = strlen (pname);
|
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)
|
&& !strncmp (state->buffer, pname, len)
|
||||||
&& strlen (state->buffer) > strlen (pname)
|
&& strlen (state->buffer) > strlen (pname)
|
||||||
&& state->buffer[len] == ':' )
|
&& 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
|
else
|
||||||
log_info ("%s%c %s\n",
|
log_info ("%s%c %s\n",
|
||||||
pname, state->cont? '+':':', state->buffer);
|
pname, state->cont? '+':':', state->buffer);
|
||||||
@ -123,10 +150,39 @@ read_and_log_stderr (read_and_log_buffer_t *state, es_poll_t *fderr)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (state->used >= sizeof state->buffer - 1)
|
if (state->used >= state->buffer_size - 1)
|
||||||
{
|
{
|
||||||
read_and_log_stderr (state, NULL);
|
if (state->status_cb)
|
||||||
state->cont = 1;
|
{
|
||||||
|
/* 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;
|
state->buffer[state->used++] = c;
|
||||||
}
|
}
|
||||||
@ -242,7 +298,9 @@ copy_buffer_flush (struct copy_buffer *c, estream_t sink)
|
|||||||
gpg_error_t
|
gpg_error_t
|
||||||
gnupg_exec_tool_stream (const char *pgmname, const char *argv[],
|
gnupg_exec_tool_stream (const char *pgmname, const char *argv[],
|
||||||
estream_t input, estream_t inextra,
|
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;
|
gpg_error_t err;
|
||||||
pid_t pid;
|
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_out);
|
||||||
copy_buffer_init (&cpbuf_extra);
|
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)
|
if (inextra)
|
||||||
{
|
{
|
||||||
err = gnupg_create_outbound_pipe (extrapipe, &extrafp, 1);
|
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",
|
log_error ("error running outbound pipe for extra fp: %s\n",
|
||||||
gpg_strerror (err));
|
gpg_strerror (err));
|
||||||
|
xfree (fderrstate.buffer);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
exceptclose[0] = extrapipe[0]; /* Do not close in child. */
|
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));
|
log_error ("error running '%s': %s\n", pgmname, gpg_strerror (err));
|
||||||
es_fclose (extrafp);
|
es_fclose (extrafp);
|
||||||
|
xfree (fderrstate.buffer);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
fderrstate.pgmname = pgmname;
|
|
||||||
|
|
||||||
fds[0].stream = infp;
|
fds[0].stream = infp;
|
||||||
fds[0].want_write = 1;
|
fds[0].want_write = 1;
|
||||||
if (!input)
|
if (!input)
|
||||||
@ -438,6 +504,7 @@ gnupg_exec_tool_stream (const char *pgmname, const char *argv[],
|
|||||||
copy_buffer_shred (&cpbuf_out);
|
copy_buffer_shred (&cpbuf_out);
|
||||||
if (inextra)
|
if (inextra)
|
||||||
copy_buffer_shred (&cpbuf_extra);
|
copy_buffer_shred (&cpbuf_extra);
|
||||||
|
xfree (fderrstate.buffer);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -488,7 +555,7 @@ gnupg_exec_tool (const char *pgmname, const char *argv[],
|
|||||||
goto leave;
|
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)
|
if (err)
|
||||||
goto leave;
|
goto leave;
|
||||||
|
|
||||||
|
@ -32,6 +32,17 @@
|
|||||||
|
|
||||||
#include <gpg-error.h>
|
#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
|
/* Run the program PGMNAME with the command line arguments given in
|
||||||
the NULL terminates array ARGV. If INPUT_STRING is not NULL it
|
the NULL terminates array ARGV. If INPUT_STRING is not NULL it
|
||||||
will be fed to stdin of the process. stderr is logged using
|
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. */
|
printed, and an error code returned. INEXTRA is reserved. */
|
||||||
gpg_error_t gnupg_exec_tool_stream (const char *pgmname, const char *argv[],
|
gpg_error_t gnupg_exec_tool_stream (const char *pgmname, const char *argv[],
|
||||||
estream_t input, estream_t inextra,
|
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 */
|
#endif /* GNUPG_COMMON_EXECTOOL_H */
|
||||||
|
@ -932,7 +932,7 @@ gpgtar_create (char **inpattern, int encrypt, int sign)
|
|||||||
}
|
}
|
||||||
|
|
||||||
err = gnupg_exec_tool_stream (opt.gpg_program, argv,
|
err = gnupg_exec_tool_stream (opt.gpg_program, argv,
|
||||||
outstream, NULL, cipher_stream);
|
outstream, NULL, cipher_stream, NULL, NULL);
|
||||||
xfree (argv);
|
xfree (argv);
|
||||||
if (err)
|
if (err)
|
||||||
goto leave;
|
goto leave;
|
||||||
|
@ -327,7 +327,7 @@ gpgtar_extract (const char *filename, int decrypt)
|
|||||||
}
|
}
|
||||||
|
|
||||||
err = gnupg_exec_tool_stream (opt.gpg_program, argv,
|
err = gnupg_exec_tool_stream (opt.gpg_program, argv,
|
||||||
cipher_stream, NULL, stream);
|
cipher_stream, NULL, stream, NULL, NULL);
|
||||||
xfree (argv);
|
xfree (argv);
|
||||||
if (err)
|
if (err)
|
||||||
goto leave;
|
goto leave;
|
||||||
|
@ -327,7 +327,7 @@ gpgtar_list (const char *filename, int decrypt)
|
|||||||
}
|
}
|
||||||
|
|
||||||
err = gnupg_exec_tool_stream (opt.gpg_program, argv,
|
err = gnupg_exec_tool_stream (opt.gpg_program, argv,
|
||||||
cipher_stream, NULL, stream);
|
cipher_stream, NULL, stream, NULL, NULL);
|
||||||
xfree (argv);
|
xfree (argv);
|
||||||
if (err)
|
if (err)
|
||||||
goto leave;
|
goto leave;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user