From 0336e5d1a7b9d46e06c838e6a98aecfcc9542882 Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Fri, 6 Apr 2018 17:32:08 +0200 Subject: [PATCH] gpg: Emit FAILURE stati now in almost all cases. * g10/cpr.c (write_status_failure): Make it print only once. * g10/gpg.c (wrong_args): Bump error counter. (g10_exit): Print a FAILURE status if we ever did a log_error etc. (main): Use log_error instead of log_fatal at one place. Print a FAILURE status for a bad option. Ditto for certain exit points so that we can see different error locations. -- This makes it easier to detect errors by tools which have no way to get the exit code (e.g. due to double forking). GnuPG-bug-id: 3872 Signed-off-by: Werner Koch --- g10/cpr.c | 6 +++++- g10/gpg.c | 56 +++++++++++++++++++++++++++++++++++++++++++++++------- sm/gpgsm.c | 14 +++++++++++--- 3 files changed, 65 insertions(+), 11 deletions(-) diff --git a/g10/cpr.c b/g10/cpr.c index a7fd1aaba..435442636 100644 --- a/g10/cpr.c +++ b/g10/cpr.c @@ -245,9 +245,13 @@ write_status_errcode (const char *where, int errcode) void write_status_failure (const char *where, gpg_error_t err) { + static int any_failure_printed; + if (!statusfp || !status_currently_allowed (STATUS_FAILURE)) return; /* Not enabled or allowed. */ - + if (any_failure_printed) + return; + any_failure_printed = 1; es_fprintf (statusfp, "[GNUPG:] %s %s %u\n", get_status_string (STATUS_FAILURE), where, err); if (es_fflush (statusfp) && opt.exit_on_status_write_error) diff --git a/g10/gpg.c b/g10/gpg.c index bfff7a567..2c93a8380 100644 --- a/g10/gpg.c +++ b/g10/gpg.c @@ -1166,6 +1166,7 @@ static void wrong_args( const char *text) { es_fprintf (es_stderr, _("usage: %s [options] %s\n"), GPG_NAME, text); + log_inc_errorcount (); g10_exit(2); } @@ -3107,7 +3108,7 @@ main (int argc, char **argv) case oCommandFD: opt.command_fd = translate_sys2libc_fd_int (pargs.r.ret_int, 0); if (! gnupg_fd_valid (opt.command_fd)) - log_fatal ("command-fd is invalid: %s\n", strerror (errno)); + log_error ("command-fd is invalid: %s\n", strerror (errno)); break; case oCommandFile: opt.command_fd = open_info_file (pargs.r.ret_str, 0, 1); @@ -3563,7 +3564,16 @@ main (int argc, char **argv) case oNoop: break; default: - pargs.err = configfp? ARGPARSE_PRINT_WARNING:ARGPARSE_PRINT_ERROR; + if (configfp) + pargs.err = ARGPARSE_PRINT_WARNING; + else + { + pargs.err = ARGPARSE_PRINT_ERROR; + /* The argparse fucntion calls a plain exit and thus + * we need to print a status here. */ + write_status_failure ("option-parser", + gpg_error(GPG_ERR_GENERAL)); + } break; } } @@ -3582,7 +3592,10 @@ main (int argc, char **argv) } xfree(configname); configname = NULL; if (log_get_errorcount (0)) - g10_exit(2); + { + write_status_failure ("option-parser", gpg_error(GPG_ERR_GENERAL)); + g10_exit(2); + } /* The command --gpgconf-list is pretty simple and may be called directly after the option parsing. */ @@ -3603,7 +3616,10 @@ main (int argc, char **argv) "--print-pks-records", "--export-options export-pka"); if (log_get_errorcount (0)) - g10_exit(2); + { + write_status_failure ("option-checking", gpg_error(GPG_ERR_GENERAL)); + g10_exit(2); + } if( nogreeting ) @@ -3704,6 +3720,7 @@ main (int argc, char **argv) { log_info(_("will not run with insecure memory due to %s\n"), "--require-secmem"); + write_status_failure ("option-checking", gpg_error(GPG_ERR_GENERAL)); g10_exit(2); } @@ -3844,7 +3861,11 @@ main (int argc, char **argv) } if( log_get_errorcount(0) ) - g10_exit(2); + { + write_status_failure ("option-postprocessing", + gpg_error(GPG_ERR_GENERAL)); + g10_exit (2); + } if(opt.compress_level==0) opt.compress_algo=COMPRESS_ALGO_NONE; @@ -3945,7 +3966,10 @@ main (int argc, char **argv) /* Fail hard. */ if (log_get_errorcount (0)) + { + write_status_failure ("option-checking", gpg_error(GPG_ERR_GENERAL)); g10_exit (2); + } /* Set the random seed file. */ if( use_random_seed ) { @@ -4929,7 +4953,10 @@ main (int argc, char **argv) hd = keydb_new (); if (! hd) - g10_exit (1); + { + write_status_failure ("tofu-driver", gpg_error(GPG_ERR_GENERAL)); + g10_exit (1); + } tofu_begin_batch_update (ctrl); @@ -4943,6 +4970,7 @@ main (int argc, char **argv) { log_error (_("error parsing key specification '%s': %s\n"), argv[i], gpg_strerror (rc)); + write_status_failure ("tofu-driver", rc); g10_exit (1); } @@ -4956,6 +4984,8 @@ main (int argc, char **argv) log_error (_("'%s' does not appear to be a valid" " key ID, fingerprint or keygrip\n"), argv[i]); + write_status_failure ("tofu-driver", + gpg_error(GPG_ERR_GENERAL)); g10_exit (1); } @@ -4966,6 +4996,7 @@ main (int argc, char **argv) the string. */ log_error ("keydb_search_reset failed: %s\n", gpg_strerror (rc)); + write_status_failure ("tofu-driver", rc); g10_exit (1); } @@ -4974,6 +5005,7 @@ main (int argc, char **argv) { log_error (_("key \"%s\" not found: %s\n"), argv[i], gpg_strerror (rc)); + write_status_failure ("tofu-driver", rc); g10_exit (1); } @@ -4982,12 +5014,16 @@ main (int argc, char **argv) { log_error (_("error reading keyblock: %s\n"), gpg_strerror (rc)); + write_status_failure ("tofu-driver", rc); g10_exit (1); } merge_keys_and_selfsig (ctrl, kb); if (tofu_set_policy (ctrl, kb, policy)) - g10_exit (1); + { + write_status_failure ("tofu-driver", rc); + g10_exit (1); + } release_kbnode (kb); } @@ -5069,6 +5105,12 @@ emergency_cleanup (void) void g10_exit( int rc ) { + /* If we had an error but not printed an error message, do it now. + * Note that write_status_failure will never print a second failure + * status line. */ + if (log_get_errorcount (0)) + write_status_failure ("gpg-exit", gpg_error (GPG_ERR_GENERAL)); + gcry_control (GCRYCTL_UPDATE_RANDOM_SEED_FILE); if (DBG_CLOCK) log_clock ("stop"); diff --git a/sm/gpgsm.c b/sm/gpgsm.c index b81e3b6e8..da1783df2 100644 --- a/sm/gpgsm.c +++ b/sm/gpgsm.c @@ -1464,7 +1464,7 @@ main ( int argc, char **argv) DIM (compliance_options), opt.quiet); if (compliance < 0) - gpgsm_exit (1); + log_inc_errorcount (); /* Force later termination. */ opt.compliance = compliance; } break; @@ -1493,7 +1493,11 @@ main ( int argc, char **argv) NULL); if (log_get_errorcount(0)) - gpgsm_exit(2); + { + gpgsm_status_with_error (&ctrl, STATUS_FAILURE, + "option-parser", gpg_error (GPG_ERR_GENERAL)); + gpgsm_exit(2); + } if (pwfd != -1) /* Read the passphrase now. */ read_passphrase_from_fd (pwfd); @@ -1660,7 +1664,11 @@ main ( int argc, char **argv) gnupg_compliance_option_string (opt.compliance)); if (log_get_errorcount(0)) - gpgsm_exit(2); + { + gpgsm_status_with_error (&ctrl, STATUS_FAILURE, "option-postprocessing", + gpg_error (GPG_ERR_GENERAL)); + gpgsm_exit (2); + } /* Set the random seed file. */ if (use_random_seed)