diff --git a/doc/tools.texi b/doc/tools.texi index 4fff44fad..c2d874ac8 100644 --- a/doc/tools.texi +++ b/doc/tools.texi @@ -1946,6 +1946,31 @@ This option is reserved and shall not be used. It will eventually be used to encrypt or sign using the CMS protocol; but that is not yet implemented. +@item --batch +@opindex batch +Use batch mode. Never ask but use the default action. This option is +passed directly to @command{gpg}. + +@item --yes +@opindex yes +Assume "yes" on most questions. Often used together with +@option{--batch} to overwrite existing files. This option is passed +directly to @command{gpg}. + +@item --no +@opindex no +Assume "no" on most questions. This option is passed directly to +@command{gpg}. + +@item --require-compliance +@opindex require-compliance +This option is passed directly to @command{gpg}. + +@item --status-fd @var{n} +@opindex status-fd +Write special status strings to the file descriptor @var{n}. +See the file DETAILS in the documentation for a listing of them. + @item --set-filename @var{file} @opindex set-filename diff --git a/tools/gpgtar-create.c b/tools/gpgtar-create.c index a7aae3b3f..f79bc618b 100644 --- a/tools/gpgtar-create.c +++ b/tools/gpgtar-create.c @@ -38,7 +38,8 @@ #endif /*!HAVE_W32_SYSTEM*/ #include "../common/i18n.h" -#include "../common/exectool.h" +#include +#include "../common/exechelp.h" #include "../common/sysutils.h" #include "../common/ccparray.h" #include "../common/membuf.h" @@ -992,8 +993,8 @@ gpgtar_create (char **inpattern, const char *files_from, int null_names, tar_header_t hdr, *start_tail; estream_t files_from_stream = NULL; estream_t outstream = NULL; - estream_t cipher_stream = NULL; int eof_seen = 0; + pid_t pid = (pid_t)(-1); memset (scanctrl, 0, sizeof *scanctrl); scanctrl->flist_tail = &scanctrl->flist; @@ -1146,64 +1147,37 @@ gpgtar_create (char **inpattern, const char *files_from, int null_names, if (files_from_stream && files_from_stream != es_stdin) es_fclose (files_from_stream); - if (opt.outfile) - { - if (!strcmp (opt.outfile, "-")) - outstream = es_stdout; - else - outstream = es_fopen (opt.outfile, "wb,sysopen"); - if (!outstream) - { - err = gpg_error_from_syserror (); - goto leave; - } - } - else - { - outstream = es_stdout; - } - - if (outstream == es_stdout) - es_set_binary (es_stdout); - - if (encrypt || sign) - { - cipher_stream = outstream; - outstream = es_fopenmem (0, "rwb"); - if (! outstream) - { - err = gpg_error_from_syserror (); - goto leave; - } - } - - for (hdr = scanctrl->flist; hdr; hdr = hdr->next) - { - err = write_file (outstream, hdr); - if (err) - goto leave; - } - err = write_eof_mark (outstream); - if (err) - goto leave; - if (encrypt || sign) { strlist_t arg; ccparray_t ccp; const char **argv; - err = es_fseek (outstream, 0, SEEK_SET); - if (err) - goto leave; - /* '--encrypt' may be combined with '--symmetric', but 'encrypt' - is set either way. Clear it if no recipients are specified. - XXX: Fix command handling. */ + * is set either way. Clear it if no recipients are specified. + */ if (opt.symmetric && opt.recipients == NULL) encrypt = 0; ccparray_init (&ccp, 0); + if (opt.batch) + ccparray_put (&ccp, "--batch"); + if (opt.answer_yes) + ccparray_put (&ccp, "--yes"); + if (opt.answer_no) + ccparray_put (&ccp, "--no"); + if (opt.require_compliance) + ccparray_put (&ccp, "--require-compliance"); + if (opt.status_fd != -1) + { + char tmpbuf[40]; + + snprintf (tmpbuf, sizeof tmpbuf, "--status-fd=%d", opt.status_fd); + ccparray_put (&ccp, tmpbuf); + } + + ccparray_put (&ccp, "--output"); + ccparray_put (&ccp, opt.outfile? opt.outfile : "-"); if (encrypt) ccparray_put (&ccp, "--encrypt"); if (sign) @@ -1231,27 +1205,76 @@ gpgtar_create (char **inpattern, const char *files_from, int null_names, goto leave; } - err = gnupg_exec_tool_stream (opt.gpg_program, argv, - outstream, NULL, cipher_stream, NULL, NULL); + err = gnupg_spawn_process (opt.gpg_program, argv, NULL, NULL, + (GNUPG_SPAWN_KEEP_STDOUT + | GNUPG_SPAWN_KEEP_STDERR), + &outstream, NULL, NULL, &pid); xfree (argv); if (err) goto leave; + es_set_binary (outstream); + } + else if (opt.outfile) /* No crypto */ + { + if (!strcmp (opt.outfile, "-")) + outstream = es_stdout; + else + outstream = es_fopen (opt.outfile, "wb,sysopen"); + if (!outstream) + { + err = gpg_error_from_syserror (); + goto leave; + } + if (outstream == es_stdout) + es_set_binary (es_stdout); + + } + else /* Also no crypto. */ + { + outstream = es_stdout; + es_set_binary (outstream); + } + + + for (hdr = scanctrl->flist; hdr; hdr = hdr->next) + { + err = write_file (outstream, hdr); + if (err) + goto leave; + } + err = write_eof_mark (outstream); + if (err) + goto leave; + + + if (pid != (pid_t)(-1)) + { + int exitcode; + + err = es_fclose (outstream); + outstream = NULL; + if (err) + log_error ("error closing pipe: %s\n", gpg_strerror (err)); + else + { + err = gnupg_wait_process (opt.gpg_program, pid, 1, &exitcode); + if (err) + log_error ("running %s failed (exitcode=%d): %s", + opt.gpg_program, exitcode, gpg_strerror (err)); + gnupg_release_process (pid); + pid = (pid_t)(-1); + } } leave: if (!err) { gpg_error_t first_err; - if (outstream != es_stdout) + if (outstream != es_stdout || pid != (pid_t)(-1)) first_err = es_fclose (outstream); else first_err = es_fflush (outstream); outstream = NULL; - if (cipher_stream != es_stdout) - err = es_fclose (cipher_stream); - else - err = es_fflush (cipher_stream); - cipher_stream = NULL; if (! err) err = first_err; } @@ -1261,8 +1284,6 @@ gpgtar_create (char **inpattern, const char *files_from, int null_names, opt.outfile ? opt.outfile : "-", gpg_strerror (err)); if (outstream && outstream != es_stdout) es_fclose (outstream); - if (cipher_stream && cipher_stream != es_stdout) - es_fclose (cipher_stream); if (opt.outfile) gnupg_remove (opt.outfile); } diff --git a/tools/gpgtar-extract.c b/tools/gpgtar-extract.c index 5fad893c5..5f907733b 100644 --- a/tools/gpgtar-extract.c +++ b/tools/gpgtar-extract.c @@ -30,7 +30,8 @@ #include #include "../common/i18n.h" -#include "../common/exectool.h" +#include +#include "../common/exechelp.h" #include "../common/sysutils.h" #include "../common/ccparray.h" #include "gpgtar.h" @@ -316,18 +317,64 @@ gpg_error_t gpgtar_extract (const char *filename, int decrypt) { gpg_error_t err; - estream_t stream; - estream_t cipher_stream = NULL; + estream_t stream = NULL; tar_header_t header = NULL; strlist_t extheader = NULL; const char *dirprefix = NULL; char *dirname = NULL; struct tarinfo_s tarinfo_buffer; tarinfo_t tarinfo = &tarinfo_buffer; + pid_t pid = (pid_t)(-1); memset (&tarinfo_buffer, 0, sizeof tarinfo_buffer); - if (filename) + if (decrypt) + { + strlist_t arg; + ccparray_t ccp; + const char **argv; + + ccparray_init (&ccp, 0); + if (opt.batch) + ccparray_put (&ccp, "--batch"); + if (opt.require_compliance) + ccparray_put (&ccp, "--require-compliance"); + if (opt.status_fd != -1) + { + char tmpbuf[40]; + + snprintf (tmpbuf, sizeof tmpbuf, "--status-fd=%d", opt.status_fd); + ccparray_put (&ccp, tmpbuf); + } + ccparray_put (&ccp, "--output"); + ccparray_put (&ccp, "-"); + ccparray_put (&ccp, "--decrypt"); + for (arg = opt.gpg_arguments; arg; arg = arg->next) + ccparray_put (&ccp, arg->d); + if (filename) + { + ccparray_put (&ccp, "--"); + ccparray_put (&ccp, filename); + } + + ccparray_put (&ccp, NULL); + argv = ccparray_get (&ccp, NULL); + if (!argv) + { + err = gpg_error_from_syserror (); + goto leave; + } + + err = gnupg_spawn_process (opt.gpg_program, argv, NULL, NULL, + ((filename? 0 : GNUPG_SPAWN_KEEP_STDIN) + | GNUPG_SPAWN_KEEP_STDERR), + NULL, &stream, NULL, &pid); + xfree (argv); + if (err) + goto leave; + es_set_binary (stream); + } + else if (filename) { if (!strcmp (filename, "-")) stream = es_stdin; @@ -339,52 +386,16 @@ gpgtar_extract (const char *filename, int decrypt) log_error ("error opening '%s': %s\n", filename, gpg_strerror (err)); return err; } + if (stream == es_stdin) + es_set_binary (es_stdin); } else - stream = es_stdin; - - if (stream == es_stdin) - es_set_binary (es_stdin); - - if (decrypt) { - strlist_t arg; - ccparray_t ccp; - const char **argv; - - cipher_stream = stream; - stream = es_fopenmem (0, "rwb"); - if (! stream) - { - err = gpg_error_from_syserror (); - goto leave; - } - - ccparray_init (&ccp, 0); - - ccparray_put (&ccp, "--decrypt"); - for (arg = opt.gpg_arguments; arg; arg = arg->next) - ccparray_put (&ccp, arg->d); - - ccparray_put (&ccp, NULL); - argv = ccparray_get (&ccp, NULL); - if (!argv) - { - err = gpg_error_from_syserror (); - goto leave; - } - - err = gnupg_exec_tool_stream (opt.gpg_program, argv, - cipher_stream, NULL, stream, NULL, NULL); - xfree (argv); - if (err) - goto leave; - - err = es_fseek (stream, 0, SEEK_SET); - if (err) - goto leave; + stream = es_stdin; + es_set_binary (es_stdin); } + if (opt.directory) dirname = xtrystrdup (opt.directory); else @@ -435,6 +446,25 @@ gpgtar_extract (const char *filename, int decrypt) header = NULL; } + if (pid != (pid_t)(-1)) + { + int exitcode; + + err = es_fclose (stream); + stream = NULL; + if (err) + log_error ("error closing pipe: %s\n", gpg_strerror (err)); + else + { + err = gnupg_wait_process (opt.gpg_program, pid, 1, &exitcode); + if (err) + log_error ("running %s failed (exitcode=%d): %s", + opt.gpg_program, exitcode, gpg_strerror (err)); + gnupg_release_process (pid); + pid = (pid_t)(-1); + } + } + leave: free_strlist (extheader); @@ -442,7 +472,5 @@ gpgtar_extract (const char *filename, int decrypt) xfree (dirname); if (stream != es_stdin) es_fclose (stream); - if (stream != cipher_stream) - es_fclose (cipher_stream); return err; } diff --git a/tools/gpgtar-list.c b/tools/gpgtar-list.c index 413abeed3..9e175437b 100644 --- a/tools/gpgtar-list.c +++ b/tools/gpgtar-list.c @@ -27,8 +27,10 @@ #include #include "../common/i18n.h" +#include #include "gpgtar.h" -#include "../common/exectool.h" +#include "../common/exechelp.h" +#include "../common/sysutils.h" #include "../common/ccparray.h" @@ -453,53 +455,43 @@ gpg_error_t gpgtar_list (const char *filename, int decrypt) { gpg_error_t err; - estream_t stream; - estream_t cipher_stream = NULL; + estream_t stream = NULL; tar_header_t header = NULL; strlist_t extheader = NULL; struct tarinfo_s tarinfo_buffer; tarinfo_t tarinfo = &tarinfo_buffer; + pid_t pid = (pid_t)(-1); memset (&tarinfo_buffer, 0, sizeof tarinfo_buffer); - if (filename) - { - if (!strcmp (filename, "-")) - stream = es_stdin; - else - stream = es_fopen (filename, "rb"); - if (!stream) - { - err = gpg_error_from_syserror (); - log_error ("error opening '%s': %s\n", filename, gpg_strerror (err)); - return err; - } - } - else - stream = es_stdin; - - if (stream == es_stdin) - es_set_binary (es_stdin); - if (decrypt) { strlist_t arg; ccparray_t ccp; const char **argv; - cipher_stream = stream; - stream = es_fopenmem (0, "rwb"); - if (! stream) - { - err = gpg_error_from_syserror (); - goto leave; - } - ccparray_init (&ccp, 0); + if (opt.batch) + ccparray_put (&ccp, "--batch"); + if (opt.require_compliance) + ccparray_put (&ccp, "--require-compliance"); + if (opt.status_fd != -1) + { + char tmpbuf[40]; + snprintf (tmpbuf, sizeof tmpbuf, "--status-fd=%d", opt.status_fd); + ccparray_put (&ccp, tmpbuf); + } + ccparray_put (&ccp, "--output"); + ccparray_put (&ccp, "-"); ccparray_put (&ccp, "--decrypt"); for (arg = opt.gpg_arguments; arg; arg = arg->next) ccparray_put (&ccp, arg->d); + if (filename) + { + ccparray_put (&ccp, "--"); + ccparray_put (&ccp, filename); + } ccparray_put (&ccp, NULL); argv = ccparray_get (&ccp, NULL); @@ -509,15 +501,34 @@ gpgtar_list (const char *filename, int decrypt) goto leave; } - err = gnupg_exec_tool_stream (opt.gpg_program, argv, - cipher_stream, NULL, stream, NULL, NULL); + err = gnupg_spawn_process (opt.gpg_program, argv, NULL, NULL, + ((filename? 0 : GNUPG_SPAWN_KEEP_STDIN) + | GNUPG_SPAWN_KEEP_STDERR), + NULL, &stream, NULL, &pid); xfree (argv); if (err) goto leave; - - err = es_fseek (stream, 0, SEEK_SET); - if (err) - goto leave; + es_set_binary (stream); + } + else if (filename) /* No decryption requested. */ + { + if (!strcmp (filename, "-")) + stream = es_stdin; + else + stream = es_fopen (filename, "rb,sysopen"); + if (!stream) + { + err = gpg_error_from_syserror (); + log_error ("error opening '%s': %s\n", filename, gpg_strerror (err)); + goto leave; + } + if (stream == es_stdin) + es_set_binary (es_stdin); + } + else + { + stream = es_stdin; + es_set_binary (es_stdin); } for (;;) @@ -536,17 +547,34 @@ gpgtar_list (const char *filename, int decrypt) header = NULL; } + if (pid != (pid_t)(-1)) + { + int exitcode; + + err = es_fclose (stream); + stream = NULL; + if (err) + log_error ("error closing pipe: %s\n", gpg_strerror (err)); + else + { + err = gnupg_wait_process (opt.gpg_program, pid, 1, &exitcode); + if (err) + log_error ("running %s failed (exitcode=%d): %s", + opt.gpg_program, exitcode, gpg_strerror (err)); + gnupg_release_process (pid); + pid = (pid_t)(-1); + } + } leave: free_strlist (extheader); xfree (header); if (stream != es_stdin) es_fclose (stream); - if (stream != cipher_stream) - es_fclose (cipher_stream); return err; } + gpg_error_t gpgtar_read_header (estream_t stream, tarinfo_t info, tar_header_t *r_header, strlist_t *r_extheader) diff --git a/tools/gpgtar.c b/tools/gpgtar.c index c15f3dcd0..8131c99a1 100644 --- a/tools/gpgtar.c +++ b/tools/gpgtar.c @@ -76,12 +76,18 @@ enum cmd_and_opt_values oNull, oUtf8Strings, + oBatch, + oAnswerYes, + oAnswerNo, + oStatusFD, + oRequireCompliance, + /* Compatibility with gpg-zip. */ oGpgArgs, oTarArgs, /* Debugging. */ - oDryRun, + oDryRun }; @@ -112,6 +118,12 @@ static ARGPARSE_OPTS opts[] = { ARGPARSE_s_n (oOpenPGP, "openpgp", "@"), ARGPARSE_s_n (oCMS, "cms", "@"), + ARGPARSE_s_n (oBatch, "batch", "@"), + ARGPARSE_s_n (oAnswerYes, "yes", "@"), + ARGPARSE_s_n (oAnswerNo, "no", "@"), + ARGPARSE_s_i (oStatusFD, "status-fd", "@"), + ARGPARSE_s_n (oRequireCompliance, "require-compliance", "@"), + ARGPARSE_group (302, N_("@\nTar options:\n ")), ARGPARSE_s_s (oDirectory, "directory", @@ -372,6 +384,12 @@ parse_arguments (ARGPARSE_ARGS *pargs, ARGPARSE_OPTS *popts) case oOpenPGP: /* Dummy option for now. */ break; case oCMS: /* Dummy option for now. */ break; + case oBatch: opt.batch = 1; break; + case oAnswerYes: opt.answer_yes = 1; break; + case oAnswerNo: opt.answer_no = 1; break; + case oStatusFD: opt.status_fd = pargs->r.ret_int; break; + case oRequireCompliance: opt.require_compliance = 1; break; + case oGpgArgs:; { strlist_t list; @@ -437,9 +455,13 @@ main (int argc, char **argv) /* Make sure that our subsystems are ready. */ i18n_init(); init_common_subsystems (&argc, &argv); + gnupg_init_signals (0, NULL); log_assert (sizeof (struct ustar_raw_header) == 512); + /* Set default options */ + opt.status_fd = -1; + /* Parse the command line. */ pargs.argc = &argc; pargs.argv = &argv; @@ -522,7 +544,7 @@ main (int argc, char **argv) /* Read the next record from STREAM. RECORD is a buffer provided by - the caller and must be at leadt of size RECORDSIZE. The function + the caller and must be at least of size RECORDSIZE. The function return 0 on success and error code on failure; a diagnostic printed as well. Note that there is no need for an EOF indicator because a tarball has an explicit EOF record. */ diff --git a/tools/gpgtar.h b/tools/gpgtar.h index 5e44112ca..b39c1359c 100644 --- a/tools/gpgtar.h +++ b/tools/gpgtar.h @@ -41,6 +41,11 @@ struct int symmetric; const char *filename; const char *directory; + int batch; + int answer_yes; + int answer_no; + int status_fd; + int require_compliance; } opt;