Use gpgrt's new option parser for gpgc, gpgsm, and gpg-agent.

* g10/gpgv.c: Use new option parser.
* sm/gpgsm.c: Ditto.
* agent/gpg-agent.c: Ditto.
(opts): Add option --no-options.
--

This is the next part of changes.  The latest libgpg-error is required
so that that re-reading options (SIGHUP) works.

GnuPG-bug-id: 4788
Signed-off-by: Werner Koch <wk@gnupg.org>
This commit is contained in:
Werner Koch 2020-02-20 14:59:58 +01:00
parent 0e8f6e2aa9
commit 2c823bd878
No known key found for this signature in database
GPG Key ID: E3FDFF218E45B72B
3 changed files with 210 additions and 242 deletions

View File

@ -1,6 +1,7 @@
/* gpg-agent.c - The GnuPG Agent /* gpg-agent.c - The GnuPG Agent
* Copyright (C) 2000-2007, 2009-2010 Free Software Foundation, Inc. * Copyright (C) 2000-2020 Free Software Foundation, Inc.
* Copyright (C) 2000-2016 Werner Koch * Copyright (C) 2000-2019 Werner Koch
* Copyright (C) 2015-2020 g10 Code GmbH
* *
* This file is part of GnuPG. * This file is part of GnuPG.
* *
@ -16,13 +17,10 @@
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, see <https://www.gnu.org/licenses/>. * along with this program; if not, see <https://www.gnu.org/licenses/>.
* SPDX-License-Identifier: GPL-3.0-or-later
*/ */
#include <config.h> #include <config.h>
/* We don't want to have the macros from gpgrt here until we have
* completely replaced this module by the one from gpgrt. */
#undef GPGRT_ENABLE_ARGPARSE_MACROS
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <stddef.h> #include <stddef.h>
@ -55,7 +53,6 @@
#define GNUPG_COMMON_NEED_AFLOCAL #define GNUPG_COMMON_NEED_AFLOCAL
#include "agent.h" #include "agent.h"
#include <assuan.h> /* Malloc hooks and socket wrappers. */ #include <assuan.h> /* Malloc hooks and socket wrappers. */
#include "../common/argparse.h" /* temporary hack. */
#include "../common/i18n.h" #include "../common/i18n.h"
#include "../common/sysutils.h" #include "../common/sysutils.h"
@ -155,7 +152,7 @@ enum cmd_and_opt_values
#endif #endif
static ARGPARSE_OPTS opts[] = { static gpgrt_opt_t opts[] = {
ARGPARSE_c (aGPGConfList, "gpgconf-list", "@"), ARGPARSE_c (aGPGConfList, "gpgconf-list", "@"),
ARGPARSE_c (aGPGConfTest, "gpgconf-test", "@"), ARGPARSE_c (aGPGConfTest, "gpgconf-test", "@"),
@ -172,7 +169,7 @@ static ARGPARSE_OPTS opts[] = {
ARGPARSE_s_n (oQuiet, "quiet", N_("be somewhat more quiet")), ARGPARSE_s_n (oQuiet, "quiet", N_("be somewhat more quiet")),
ARGPARSE_s_n (oSh, "sh", N_("sh-style command output")), ARGPARSE_s_n (oSh, "sh", N_("sh-style command output")),
ARGPARSE_s_n (oCsh, "csh", N_("csh-style command output")), ARGPARSE_s_n (oCsh, "csh", N_("csh-style command output")),
ARGPARSE_s_s (oOptions, "options", N_("|FILE|read options from FILE")), ARGPARSE_conffile (oOptions, "options", N_("|FILE|read options from FILE")),
ARGPARSE_s_s (oDebug, "debug", "@"), ARGPARSE_s_s (oDebug, "debug", "@"),
ARGPARSE_s_n (oDebugAll, "debug-all", "@"), ARGPARSE_s_n (oDebugAll, "debug-all", "@"),
@ -182,9 +179,8 @@ static ARGPARSE_OPTS opts[] = {
ARGPARSE_s_n (oDebugPinentry, "debug-pinentry", "@"), ARGPARSE_s_n (oDebugPinentry, "debug-pinentry", "@"),
ARGPARSE_s_n (oNoDetach, "no-detach", N_("do not detach from the console")), ARGPARSE_s_n (oNoDetach, "no-detach", N_("do not detach from the console")),
ARGPARSE_s_n (oGrab, "grab", "@"), ARGPARSE_s_n (oGrab, "grab",
/* FIXME: Add the below string for 2.3 */ /* */ N_("let PIN-Entry grab keyboard and mouse")),
/* N_("let PIN-Entry grab keyboard and mouse")), */
ARGPARSE_s_n (oNoGrab, "no-grab", "@"), ARGPARSE_s_n (oNoGrab, "no-grab", "@"),
ARGPARSE_s_s (oLogFile, "log-file", N_("use a log file for the server")), ARGPARSE_s_s (oLogFile, "log-file", N_("use a log file for the server")),
ARGPARSE_s_s (oPinentryProgram, "pinentry-program", ARGPARSE_s_s (oPinentryProgram, "pinentry-program",
@ -268,6 +264,8 @@ static ARGPARSE_OPTS opts[] = {
ARGPARSE_s_i (oListenBacklog, "listen-backlog", "@"), ARGPARSE_s_i (oListenBacklog, "listen-backlog", "@"),
ARGPARSE_noconffile (oNoOptions, "no-options", "@"),
/* Dummy options for backward compatibility. */ /* Dummy options for backward compatibility. */
ARGPARSE_o_s (oWriteEnvFile, "write-env-file", "@"), ARGPARSE_o_s (oWriteEnvFile, "write-env-file", "@"),
ARGPARSE_s_n (oUseStandardSocket, "use-standard-socket", "@"), ARGPARSE_s_n (oUseStandardSocket, "use-standard-socket", "@"),
@ -400,7 +398,9 @@ static char *default_lc_ctype;
static char *default_lc_messages; static char *default_lc_messages;
static char *default_xauthority; static char *default_xauthority;
/* Name of a config file, which will be reread on a HUP if it is not NULL. */ /* Name of a config file which was last read on startup or if missing
* the name of the standard config file. Any value here enabled the
* rereading of the standard config files on SIGHUP. */
static char *config_filename; static char *config_filename;
/* Helper to implement --debug-level */ /* Helper to implement --debug-level */
@ -517,9 +517,11 @@ my_strusage (int level)
switch (level) switch (level)
{ {
case 9: p = "GPL-3.0-or-later"; break;
case 11: p = "@GPG_AGENT@ (@GNUPG@)"; case 11: p = "@GPG_AGENT@ (@GNUPG@)";
break; break;
case 13: p = VERSION; break; case 13: p = VERSION; break;
case 14: p = GNUPG_DEF_COPYRIGHT_LINE; break;
case 17: p = PRINTABLE_OS_NAME; break; case 17: p = PRINTABLE_OS_NAME; break;
/* TRANSLATORS: @EMAIL@ will get replaced by the actual bug /* TRANSLATORS: @EMAIL@ will get replaced by the actual bug
reporting address. This is so that we can change the reporting address. This is so that we can change the
@ -809,7 +811,7 @@ cleanup (void)
PARGS, resets the options to the default. REREAD should be set PARGS, resets the options to the default. REREAD should be set
true if it is not the initial option parsing. */ true if it is not the initial option parsing. */
static int static int
parse_rereadable_options (ARGPARSE_ARGS *pargs, int reread) parse_rereadable_options (gpgrt_argparse_t *pargs, int reread)
{ {
int i; int i;
@ -1007,17 +1009,15 @@ initialize_modules (void)
/* The main entry point. */ /* The main entry point. */
int int
main (int argc, char **argv ) main (int argc, char **argv)
{ {
ARGPARSE_ARGS pargs; gpgrt_argparse_t pargs;
int orig_argc; int orig_argc;
char **orig_argv; char **orig_argv;
FILE *configfp = NULL; char *last_configname = NULL;
char *configname = NULL; const char *configname = NULL;
int debug_argparser = 0;
const char *shell; const char *shell;
unsigned configlineno;
int parse_debug = 0;
int default_config =1;
int pipe_server = 0; int pipe_server = 0;
int is_daemon = 0; int is_daemon = 0;
int nodetach = 0; int nodetach = 0;
@ -1042,7 +1042,7 @@ main (int argc, char **argv )
#endif /*HAVE_SIGPROCMASK*/ #endif /*HAVE_SIGPROCMASK*/
/* Set program name etc. */ /* Set program name etc. */
set_strusage (my_strusage); gpgrt_set_strusage (my_strusage);
gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN); gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN);
/* Please note that we may running SUID(ROOT), so be very CAREFUL /* Please note that we may running SUID(ROOT), so be very CAREFUL
when adding any stuff between here and the call to INIT_SECMEM() when adding any stuff between here and the call to INIT_SECMEM()
@ -1116,80 +1116,68 @@ main (int argc, char **argv )
orig_argv = argv; orig_argv = argv;
pargs.argc = &argc; pargs.argc = &argc;
pargs.argv = &argv; pargs.argv = &argv;
pargs.flags= 1|(1<<6); /* do not remove the args, ignore version */ pargs.flags= (ARGPARSE_FLAG_KEEP | ARGPARSE_FLAG_NOVERSION);
while (arg_parse( &pargs, opts)) while (gpgrt_argparse (NULL, &pargs, opts))
{ {
if (pargs.r_opt == oDebug || pargs.r_opt == oDebugAll) switch (pargs.r_opt)
parse_debug++; {
else if (pargs.r_opt == oOptions) case oDebug:
{ /* yes there is one, so we do not try the default one, but case oDebugAll:
read the option file when it is encountered at the debug_argparser++;
commandline */ break;
default_config = 0;
}
else if (pargs.r_opt == oNoOptions)
default_config = 0; /* --no-options */
else if (pargs.r_opt == oHomedir)
gnupg_set_homedir (pargs.r.ret_str);
else if (pargs.r_opt == oDebugQuickRandom)
{
gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);
}
case oHomedir:
gnupg_set_homedir (pargs.r.ret_str);
break;
case oDebugQuickRandom:
gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);
break;
}
} }
/* Reset the flags. */
pargs.flags &= ~(ARGPARSE_FLAG_KEEP | ARGPARSE_FLAG_NOVERSION);
/* Initialize the secure memory. */ /* Initialize the secure memory. */
gcry_control (GCRYCTL_INIT_SECMEM, SECMEM_BUFFER_SIZE, 0); gcry_control (GCRYCTL_INIT_SECMEM, SECMEM_BUFFER_SIZE, 0);
maybe_setuid = 0; maybe_setuid = 0;
/* /*
Now we are now working under our real uid * Now we are now working under our real uid
*/ */
if (default_config) /* The configuraton directories for use by gpgrt_argparser. */
configname = make_filename (gnupg_homedir (), gpgrt_set_confdir (GPGRT_CONFDIR_SYS, gnupg_sysconfdir ());
GPG_AGENT_NAME EXTSEP_S "conf", NULL); gpgrt_set_confdir (GPGRT_CONFDIR_USER, gnupg_homedir ());
argc = orig_argc; argc = orig_argc;
argv = orig_argv; argv = orig_argv;
pargs.argc = &argc; pargs.argc = &argc;
pargs.argv = &argv; pargs.argv = &argv;
pargs.flags= 1; /* do not remove the args */ /* We are re-using the struct, thus the reset flag. We OR the
next_pass: * flags so that the internal intialized flag won't be cleared. */
if (configname) pargs.flags |= (ARGPARSE_FLAG_RESET
{ | ARGPARSE_FLAG_KEEP
configlineno = 0; | ARGPARSE_FLAG_SYS
configfp = fopen (configname, "r"); | ARGPARSE_FLAG_USER);
if (!configfp)
{
if (default_config)
{
if( parse_debug )
log_info (_("Note: no default option file '%s'\n"),
configname );
/* Save the default conf file name so that
reread_configuration is able to test whether the
config file has been created in the meantime. */
xfree (config_filename);
config_filename = configname;
configname = NULL;
}
else
{
log_error (_("option file '%s': %s\n"),
configname, strerror(errno) );
exit(2);
}
xfree (configname);
configname = NULL;
}
if (parse_debug && configname )
log_info (_("reading options from '%s'\n"), configname );
default_config = 0;
}
while (optfile_parse( configfp, configname, &configlineno, &pargs, opts) ) while (gpgrt_argparser (&pargs, opts, GPG_AGENT_NAME EXTSEP_S "conf"))
{ {
if (pargs.r_opt == ARGPARSE_CONFFILE)
{
if (debug_argparser)
log_info (_("reading options from '%s'\n"),
pargs.r_type? pargs.r.ret_str: "[cmdline]");
if (pargs.r_type)
{
xfree (last_configname);
last_configname = xstrdup (pargs.r.ret_str);
configname = last_configname;
}
else
configname = NULL;
continue;
}
if (parse_rereadable_options (&pargs, 0)) if (parse_rereadable_options (&pargs, 0))
continue; /* Already handled */ continue; /* Already handled */
switch (pargs.r_opt) switch (pargs.r_opt)
@ -1201,18 +1189,8 @@ main (int argc, char **argv )
case oDebugWait: debug_wait = pargs.r.ret_int; break; case oDebugWait: debug_wait = pargs.r.ret_int; break;
case oOptions:
/* config files may not be nested (silently ignore them) */
if (!configfp)
{
xfree(configname);
configname = xstrdup(pargs.r.ret_str);
goto next_pass;
}
break;
case oNoGreeting: /* Dummy option. */ break; case oNoGreeting: /* Dummy option. */ break;
case oNoVerbose: opt.verbose = 0; break; case oNoVerbose: opt.verbose = 0; break;
case oNoOptions: break; /* no-options */
case oHomedir: gnupg_set_homedir (pargs.r.ret_str); break; case oHomedir: gnupg_set_homedir (pargs.r.ret_str); break;
case oNoDetach: nodetach = 1; break; case oNoDetach: nodetach = 1; break;
case oLogFile: logfile = pargs.r.ret_str; break; case oLogFile: logfile = pargs.r.ret_str; break;
@ -1233,7 +1211,7 @@ main (int argc, char **argv )
case oUseStandardSocket: case oUseStandardSocket:
case oNoUseStandardSocket: case oNoUseStandardSocket:
obsolete_option (configname, configlineno, "use-standard-socket"); obsolete_option (configname, pargs.lineno, "use-standard-socket");
break; break;
case oFakedSystemTime: case oFakedSystemTime:
@ -1285,28 +1263,30 @@ main (int argc, char **argv )
break; break;
case oWriteEnvFile: case oWriteEnvFile:
obsolete_option (configname, configlineno, "write-env-file"); obsolete_option (configname, pargs.lineno, "write-env-file");
break; break;
default : pargs.err = configfp? 1:2; break; default:
if (configname)
pargs.err = ARGPARSE_PRINT_WARNING;
else
pargs.err = ARGPARSE_PRINT_ERROR;
break;
} }
} }
if (configfp)
gpgrt_argparse (NULL, &pargs, NULL); /* Release internal state. */
if (!last_configname)
config_filename = gpgrt_fnameconcat (gnupg_homedir (),
GPG_AGENT_NAME EXTSEP_S "conf",
NULL);
else
{ {
fclose( configfp ); config_filename = last_configname;
configfp = NULL; last_configname = NULL;
/* Keep a copy of the name so that it can be read on SIGHUP. */
if (config_filename != configname)
{
xfree (config_filename);
config_filename = configname;
}
configname = NULL;
goto next_pass;
} }
xfree (configname);
configname = NULL;
if (log_get_errorcount(0)) if (log_get_errorcount(0))
exit(2); exit(2);
@ -1402,18 +1382,14 @@ main (int argc, char **argv )
agent_exit (0); agent_exit (0);
else if (gpgconf_list) else if (gpgconf_list)
{ {
char *filename;
char *filename_esc; char *filename_esc;
/* List options and default values in the GPG Conf format. */ /* List options and default values in the GPG Conf format. */
filename = make_filename (gnupg_homedir (), filename_esc = percent_escape (config_filename, NULL);
GPG_AGENT_NAME EXTSEP_S "conf", NULL);
filename_esc = percent_escape (filename, NULL);
es_printf ("%s-%s.conf:%lu:\"%s\n", es_printf ("%s-%s.conf:%lu:\"%s\n",
GPGCONF_NAME, GPG_AGENT_NAME, GPGCONF_NAME, GPG_AGENT_NAME,
GC_OPT_FLAG_DEFAULT, filename_esc); GC_OPT_FLAG_DEFAULT, filename_esc);
xfree (filename);
xfree (filename_esc); xfree (filename_esc);
es_printf ("verbose:%lu:\n" es_printf ("verbose:%lu:\n"
@ -1532,7 +1508,7 @@ main (int argc, char **argv )
log_set_prefix (NULL, 0); log_set_prefix (NULL, 0);
log_info ("%s %s starting in supervised mode.\n", log_info ("%s %s starting in supervised mode.\n",
strusage(11), strusage(13) ); gpgrt_strusage(11), gpgrt_strusage(13) );
/* See below in "regular server mode" on why we remove certain /* See below in "regular server mode" on why we remove certain
* envvars. */ * envvars. */
@ -1812,7 +1788,7 @@ main (int argc, char **argv )
exit (1); exit (1);
} }
log_info ("%s %s started\n", strusage(11), strusage(13) ); log_info ("%s %s started\n", gpgrt_strusage(11), gpgrt_strusage(13) );
handle_connections (fd, fd_extra, fd_browser, fd_ssh); handle_connections (fd, fd_extra, fd_browser, fd_ssh);
assuan_sock_close (fd); assuan_sock_close (fd);
} }
@ -2039,36 +2015,34 @@ agent_copy_startup_env (ctrl_t ctrl)
static void static void
reread_configuration (void) reread_configuration (void)
{ {
ARGPARSE_ARGS pargs; gpgrt_argparse_t pargs;
FILE *fp;
unsigned int configlineno = 0;
int dummy; int dummy;
if (!config_filename) if (!config_filename)
return; /* No config file. */ return; /* No config file. */
fp = fopen (config_filename, "r");
if (!fp)
{
log_info (_("option file '%s': %s\n"),
config_filename, strerror(errno) );
return;
}
parse_rereadable_options (NULL, 1); /* Start from the default values. */ parse_rereadable_options (NULL, 1); /* Start from the default values. */
memset (&pargs, 0, sizeof pargs); memset (&pargs, 0, sizeof pargs);
dummy = 0; dummy = 0;
pargs.argc = &dummy; pargs.argc = &dummy;
pargs.flags = 1; /* do not remove the args */ pargs.flags = (ARGPARSE_FLAG_KEEP
while (optfile_parse (fp, config_filename, &configlineno, &pargs, opts) ) |ARGPARSE_FLAG_SYS
|ARGPARSE_FLAG_USER);
while (gpgrt_argparser (&pargs, opts, GPG_AGENT_NAME EXTSEP_S "conf") )
{ {
if (pargs.r_opt < -1) if (pargs.r_opt == ARGPARSE_CONFFILE)
pargs.err = 1; /* Print a warning. */ {
log_info (_("reading options from '%s'\n"),
pargs.r_type? pargs.r.ret_str: "[cmdline]");
}
else if (pargs.r_opt < -1)
pargs.err = ARGPARSE_PRINT_WARNING;
else /* Try to parse this option - ignore unchangeable ones. */ else /* Try to parse this option - ignore unchangeable ones. */
parse_rereadable_options (&pargs, 1); parse_rereadable_options (&pargs, 1);
} }
fclose (fp); gpgrt_argparse (NULL, &pargs, NULL); /* Release internal state. */
finalize_rereadable_options (); finalize_rereadable_options ();
set_debug (); set_debug ();
} }
@ -2401,7 +2375,7 @@ handle_tick (void)
{ {
shutdown_pending = 2; shutdown_pending = 2;
log_info ("parent process died - shutting down\n"); log_info ("parent process died - shutting down\n");
log_info ("%s %s stopped\n", strusage(11), strusage(13) ); log_info ("%s %s stopped\n", gpgrt_strusage(11), gpgrt_strusage(13));
cleanup (); cleanup ();
agent_exit (0); agent_exit (0);
} }
@ -2499,7 +2473,7 @@ handle_signal (int signo)
if (shutdown_pending > 2) if (shutdown_pending > 2)
{ {
log_info ("shutdown forced\n"); log_info ("shutdown forced\n");
log_info ("%s %s stopped\n", strusage(11), strusage(13) ); log_info ("%s %s stopped\n", gpgrt_strusage(11), gpgrt_strusage(13));
cleanup (); cleanup ();
agent_exit (0); agent_exit (0);
} }
@ -2507,7 +2481,7 @@ handle_signal (int signo)
case SIGINT: case SIGINT:
log_info ("SIGINT received - immediate shutdown\n"); log_info ("SIGINT received - immediate shutdown\n");
log_info( "%s %s stopped\n", strusage(11), strusage(13)); log_info( "%s %s stopped\n", gpgrt_strusage(11), gpgrt_strusage(13));
cleanup (); cleanup ();
agent_exit (0); agent_exit (0);
break; break;
@ -3127,7 +3101,7 @@ handle_connections (gnupg_fd_t listen_fd,
if (home_inotify_fd != -1) if (home_inotify_fd != -1)
close (home_inotify_fd); close (home_inotify_fd);
cleanup (); cleanup ();
log_info (_("%s %s stopped\n"), strusage(11), strusage(13)); log_info (_("%s %s stopped\n"), gpgrt_strusage(11), gpgrt_strusage(13));
npth_attr_destroy (&tattr); npth_attr_destroy (&tattr);
} }

View File

@ -1,6 +1,7 @@
/* gpgv.c - The GnuPG signature verify utility /* gpgv.c - The GnuPG signature verify utility
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2005, 2006, * Copyright (C) 1998-2020 Free Software Foundation, Inc.
* 2008, 2009, 2012 Free Software Foundation, Inc. * Copyright (C) 1997-2019 Werner Koch
* Copyright (C) 2015-2020 g10 Code GmbH
* *
* This file is part of GnuPG. * This file is part of GnuPG.
* *
@ -16,12 +17,10 @@
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, see <https://www.gnu.org/licenses/>. * along with this program; if not, see <https://www.gnu.org/licenses/>.
* SPDX-License-Identifier: GPL-3.0-or-later
*/ */
#include <config.h> #include <config.h>
/* We don't want to have the macros from gpgrt here until we have
* completely replaced this module by the one from gpgrt. */
#undef GPGRT_ENABLE_ARGPARSE_MACROS
#include <errno.h> #include <errno.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
@ -39,7 +38,6 @@
#define INCLUDED_BY_MAIN_MODULE 1 #define INCLUDED_BY_MAIN_MODULE 1
#include "gpg.h" #include "gpg.h"
#include "../common/util.h" #include "../common/util.h"
#include "../common/argparse.h" /* temporary hack. */
#include "packet.h" #include "packet.h"
#include "../common/iobuf.h" #include "../common/iobuf.h"
#include "main.h" #include "main.h"
@ -74,7 +72,7 @@ enum cmd_and_opt_values {
}; };
static ARGPARSE_OPTS opts[] = { static gpgrt_opt_t opts[] = {
ARGPARSE_group (300, N_("@\nOptions:\n ")), ARGPARSE_group (300, N_("@\nOptions:\n ")),
ARGPARSE_s_n (oVerbose, "verbose", N_("verbose")), ARGPARSE_s_n (oVerbose, "verbose", N_("verbose")),
@ -142,9 +140,11 @@ my_strusage( int level )
switch (level) switch (level)
{ {
case 9: p = "GPL-3.0-or-later"; break;
case 11: p = "@GPG@v (GnuPG)"; case 11: p = "@GPG@v (GnuPG)";
break; break;
case 13: p = VERSION; break; case 13: p = VERSION; break;
case 14: p = GNUPG_DEF_COPYRIGHT_LINE; break;
case 17: p = PRINTABLE_OS_NAME; break; case 17: p = PRINTABLE_OS_NAME; break;
case 19: p = _("Please report bugs to <@EMAIL@>.\n"); break; case 19: p = _("Please report bugs to <@EMAIL@>.\n"); break;
@ -172,11 +172,10 @@ my_strusage( int level )
int int
main( int argc, char **argv ) main( int argc, char **argv )
{ {
ARGPARSE_ARGS pargs; gpgrt_argparse_t pargs;
int rc=0; int rc=0;
strlist_t sl; strlist_t sl;
strlist_t nrings = NULL; strlist_t nrings = NULL;
unsigned configlineno;
ctrl_t ctrl; ctrl_t ctrl;
early_system_init (); early_system_init ();
@ -210,11 +209,13 @@ main( int argc, char **argv )
pargs.argc = &argc; pargs.argc = &argc;
pargs.argv = &argv; pargs.argv = &argv;
pargs.flags= 1; /* do not remove the args */ pargs.flags= ARGPARSE_FLAG_KEEP;
while (optfile_parse( NULL, NULL, &configlineno, &pargs, opts)) while (gpgrt_argparser (&pargs, opts, NULL))
{ {
switch (pargs.r_opt) switch (pargs.r_opt)
{ {
case ARGPARSE_CONFFILE: break;
case oQuiet: opt.quiet = 1; break; case oQuiet: opt.quiet = 1; break;
case oVerbose: case oVerbose:
opt.verbose++; opt.verbose++;
@ -254,6 +255,8 @@ main( int argc, char **argv )
} }
} }
gpgrt_argparse (NULL, &pargs, NULL); /* Release internal state. */
if (log_get_errorcount (0)) if (log_get_errorcount (0))
g10_exit(2); g10_exit(2);

View File

@ -1,6 +1,7 @@
/* gpgsm.c - GnuPG for S/MIME /* gpgsm.c - GnuPG for S/MIME
* Copyright (C) 2001-2008, 2010 Free Software Foundation, Inc. * Copyright (C) 2001-2020 Free Software Foundation, Inc.
* Copyright (C) 2001-2008, 2010 Werner Koch * Copyright (C) 2001-2019 Werner Koch
* Copyright (C) 2015-2020 g10 Code GmbH
* *
* This file is part of GnuPG. * This file is part of GnuPG.
* *
@ -16,12 +17,10 @@
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, see <https://www.gnu.org/licenses/>. * along with this program; if not, see <https://www.gnu.org/licenses/>.
* SPDX-License-Identifier: GPL-3.0-or-later
*/ */
#include <config.h> #include <config.h>
/* We don't want to have the macros from gpgrt here until we have
* completely replaced this module by the one from gpgrt. */
#undef GPGRT_ENABLE_ARGPARSE_MACROS
#include <errno.h> #include <errno.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
@ -36,7 +35,6 @@
#include "gpgsm.h" #include "gpgsm.h"
#include <gcrypt.h> #include <gcrypt.h>
#include <assuan.h> /* malloc hooks */ #include <assuan.h> /* malloc hooks */
#include "../common/argparse.h" /* temporary hack. */
#include "passphrase.h" #include "passphrase.h"
#include "../common/shareddefs.h" #include "../common/shareddefs.h"
@ -204,7 +202,7 @@ enum cmd_and_opt_values {
}; };
static ARGPARSE_OPTS opts[] = { static gpgrt_opt_t opts[] = {
ARGPARSE_group (300, N_("@Commands:\n ")), ARGPARSE_group (300, N_("@Commands:\n ")),
@ -343,7 +341,7 @@ static ARGPARSE_OPTS opts[] = {
ARGPARSE_s_s (oKeyServer, "keyserver", ARGPARSE_s_s (oKeyServer, "keyserver",
N_("|SPEC|use this keyserver to lookup keys")), N_("|SPEC|use this keyserver to lookup keys")),
ARGPARSE_s_s (oOptions, "options", N_("|FILE|read options from FILE")), ARGPARSE_conffile (oOptions, "options", N_("|FILE|read options from FILE")),
ARGPARSE_s_s (oDebug, "debug", "@"), ARGPARSE_s_s (oDebug, "debug", "@"),
ARGPARSE_s_s (oDebugLevel, "debug-level", ARGPARSE_s_s (oDebugLevel, "debug-level",
@ -379,7 +377,7 @@ static ARGPARSE_OPTS opts[] = {
ARGPARSE_s_n (oNoArmor, "no-armour", "@"), ARGPARSE_s_n (oNoArmor, "no-armour", "@"),
ARGPARSE_s_n (oNoDefKeyring, "no-default-keyring", "@"), ARGPARSE_s_n (oNoDefKeyring, "no-default-keyring", "@"),
ARGPARSE_s_n (oNoGreeting, "no-greeting", "@"), ARGPARSE_s_n (oNoGreeting, "no-greeting", "@"),
ARGPARSE_s_n (oNoOptions, "no-options", "@"), ARGPARSE_noconffile (oNoOptions, "no-options", "@"),
ARGPARSE_s_s (oHomedir, "homedir", "@"), ARGPARSE_s_s (oHomedir, "homedir", "@"),
ARGPARSE_s_s (oAgentProgram, "agent-program", "@"), ARGPARSE_s_s (oAgentProgram, "agent-program", "@"),
ARGPARSE_s_s (oDisplay, "display", "@"), ARGPARSE_s_s (oDisplay, "display", "@"),
@ -566,9 +564,11 @@ my_strusage( int level )
switch (level) switch (level)
{ {
case 9: p = "GPL-3.0-or-later"; break;
case 11: p = "@GPGSM@ (@GNUPG@)"; case 11: p = "@GPGSM@ (@GNUPG@)";
break; break;
case 13: p = VERSION; break; case 13: p = VERSION; break;
case 14: p = GNUPG_DEF_COPYRIGHT_LINE; break;
case 17: p = PRINTABLE_OS_NAME; break; case 17: p = PRINTABLE_OS_NAME; break;
case 19: p = _("Please report bugs to <@EMAIL@>.\n"); break; case 19: p = _("Please report bugs to <@EMAIL@>.\n"); break;
@ -928,7 +928,7 @@ parse_keyserver_line (char *line,
int int
main ( int argc, char **argv) main ( int argc, char **argv)
{ {
ARGPARSE_ARGS pargs; gpgrt_argparse_t pargs;
int orig_argc; int orig_argc;
char **orig_argv; char **orig_argv;
/* char *username;*/ /* char *username;*/
@ -936,12 +936,12 @@ main ( int argc, char **argv)
strlist_t sl, remusr= NULL, locusr=NULL; strlist_t sl, remusr= NULL, locusr=NULL;
strlist_t nrings=NULL; strlist_t nrings=NULL;
int detached_sig = 0; int detached_sig = 0;
FILE *configfp = NULL; char *last_configname = NULL;
char *configname = NULL; const char *configname = NULL; /* NULL or points to last_configname.
unsigned configlineno; * NULL also indicates that we are
int parse_debug = 0; * processing options from the cmdline. */
int debug_argparser = 0;
int no_more_options = 0; int no_more_options = 0;
int default_config =1;
int default_keyring = 1; int default_keyring = 1;
char *logfile = NULL; char *logfile = NULL;
char *auditlog = NULL; char *auditlog = NULL;
@ -970,7 +970,7 @@ main ( int argc, char **argv)
gnupg_reopen_std (GPGSM_NAME); gnupg_reopen_std (GPGSM_NAME);
/* trap_unaligned ();*/ /* trap_unaligned ();*/
gnupg_rl_initialize (); gnupg_rl_initialize ();
set_strusage (my_strusage); gpgrt_set_strusage (my_strusage);
gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN); gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN);
/* Please note that we may running SUID(ROOT), so be very CAREFUL /* Please note that we may running SUID(ROOT), so be very CAREFUL
@ -1016,29 +1016,35 @@ main ( int argc, char **argv)
orig_argv = argv; orig_argv = argv;
pargs.argc = &argc; pargs.argc = &argc;
pargs.argv = &argv; pargs.argv = &argv;
pargs.flags= 1|(1<<6); /* do not remove the args, ignore version */ pargs.flags= (ARGPARSE_FLAG_KEEP | ARGPARSE_FLAG_NOVERSION);
while (arg_parse( &pargs, opts)) while (gpgrt_argparse (NULL, &pargs, opts))
{ {
if (pargs.r_opt == oDebug || pargs.r_opt == oDebugAll) switch (pargs.r_opt)
parse_debug++;
else if (pargs.r_opt == oOptions)
{ /* yes there is one, so we do not try the default one but
read the config file when it is encountered at the
commandline */
default_config = 0;
}
else if (pargs.r_opt == oNoOptions)
{ {
default_config = 0; /* --no-options */ case oDebug:
opt.no_homedir_creation = 1; case oDebugAll:
} debug_argparser++;
else if (pargs.r_opt == oHomedir) break;
gnupg_set_homedir (pargs.r.ret_str);
else if (pargs.r_opt == aCallProtectTool)
break; /* This break makes sure that --version and --help are
passed to the protect-tool. */
}
case oNoOptions:
/* Set here here because the homedir would otherwise be
* created before main option parsing starts. */
opt.no_homedir_creation = 1;
break;
case oHomedir:
gnupg_set_homedir (pargs.r.ret_str);
break;
case aCallProtectTool:
/* Make sure that --version and --help are passed to the
* protect-tool. */
goto leave_cmdline_parser;
}
}
leave_cmdline_parser:
/* Reset the flags. */
pargs.flags &= ~(ARGPARSE_FLAG_KEEP | ARGPARSE_FLAG_NOVERSION);
/* Initialize the secure memory. */ /* Initialize the secure memory. */
gcry_control (GCRYCTL_INIT_SECMEM, 16384, 0); gcry_control (GCRYCTL_INIT_SECMEM, 16384, 0);
@ -1064,48 +1070,43 @@ main ( int argc, char **argv)
ctrl.status_fd = -1; /* No status output. */ ctrl.status_fd = -1; /* No status output. */
ctrl.autodetect_encoding = 1; ctrl.autodetect_encoding = 1;
/* Set the default option file */
if (default_config )
configname = make_filename (gnupg_homedir (),
GPGSM_NAME EXTSEP_S "conf", NULL);
/* Set the default policy file */ /* Set the default policy file */
opt.policy_file = make_filename (gnupg_homedir (), "policies.txt", NULL); opt.policy_file = make_filename (gnupg_homedir (), "policies.txt", NULL);
/* The configuraton directories for use by gpgrt_argparser. */
gpgrt_set_confdir (GPGRT_CONFDIR_SYS, gnupg_sysconfdir ());
gpgrt_set_confdir (GPGRT_CONFDIR_USER, gnupg_homedir ());
/* We are re-using the struct, thus the reset flag. We OR the
* flags so that the internal intialized flag won't be cleared. */
argc = orig_argc; argc = orig_argc;
argv = orig_argv; argv = orig_argv;
pargs.argc = &argc; pargs.argc = &argc;
pargs.argv = &argv; pargs.argv = &argv;
pargs.flags = 1; /* do not remove the args */ pargs.flags |= (ARGPARSE_FLAG_RESET
| ARGPARSE_FLAG_KEEP
next_pass: | ARGPARSE_FLAG_SYS
if (configname) { | ARGPARSE_FLAG_USER);
configlineno = 0;
configfp = fopen (configname, "r");
if (!configfp)
{
if (default_config)
{
if (parse_debug)
log_info (_("Note: no default option file '%s'\n"), configname);
}
else
{
log_error (_("option file '%s': %s\n"), configname, strerror(errno));
gpgsm_exit(2);
}
xfree(configname);
configname = NULL;
}
if (parse_debug && configname)
log_info (_("reading options from '%s'\n"), configname);
default_config = 0;
}
while (!no_more_options while (!no_more_options
&& optfile_parse (configfp, configname, &configlineno, &pargs, opts)) && gpgrt_argparser (&pargs, opts, GPGSM_NAME EXTSEP_S "conf"))
{ {
switch (pargs.r_opt) switch (pargs.r_opt)
{ {
case ARGPARSE_CONFFILE:
if (debug_argparser)
log_info (_("reading options from '%s'\n"),
pargs.r_type? pargs.r.ret_str: "[cmdline]");
if (pargs.r_type)
{
xfree (last_configname);
last_configname = xstrdup (pargs.r.ret_str);
configname = last_configname;
}
else
configname = NULL;
break;
case aGPGConfList: case aGPGConfList:
case aGPGConfTest: case aGPGConfTest:
set_cmd (&cmd, pargs.r_opt); set_cmd (&cmd, pargs.r_opt);
@ -1351,16 +1352,6 @@ main ( int argc, char **argv)
opt.with_key_screening = 1; opt.with_key_screening = 1;
break; break;
case oOptions:
/* config files may not be nested (silently ignore them) */
if (!configfp)
{
xfree(configname);
configname = xstrdup (pargs.r.ret_str);
goto next_pass;
}
break;
case oNoOptions: opt.no_homedir_creation = 1; break; /* no-options */
case oHomedir: gnupg_set_homedir (pargs.r.ret_str); break; case oHomedir: gnupg_set_homedir (pargs.r.ret_str); break;
case oAgentProgram: opt.agent_program = pargs.r.ret_str; break; case oAgentProgram: opt.agent_program = pargs.r.ret_str; break;
@ -1488,7 +1479,7 @@ main ( int argc, char **argv)
{ {
struct keyserver_spec *keyserver; struct keyserver_spec *keyserver;
keyserver = parse_keyserver_line (pargs.r.ret_str, keyserver = parse_keyserver_line (pargs.r.ret_str,
configname, configlineno); configname, pargs.lineno);
if (! keyserver) if (! keyserver)
log_error (_("could not parse keyserver\n")); log_error (_("could not parse keyserver\n"));
else else
@ -1521,10 +1512,9 @@ main ( int argc, char **argv)
{ "gnupg", CO_GNUPG }, { "gnupg", CO_GNUPG },
{ "de-vs", CO_DE_VS } { "de-vs", CO_DE_VS }
}; };
int compliance = gnupg_parse_compliance_option (pargs.r.ret_str, int compliance = gnupg_parse_compliance_option
compliance_options, (pargs.r.ret_str, compliance_options, DIM (compliance_options),
DIM (compliance_options), opt.quiet);
opt.quiet);
if (compliance < 0) if (compliance < 0)
log_inc_errorcount (); /* Force later termination. */ log_inc_errorcount (); /* Force later termination. */
opt.compliance = compliance; opt.compliance = compliance;
@ -1532,27 +1522,28 @@ main ( int argc, char **argv)
break; break;
default: default:
pargs.err = configfp? ARGPARSE_PRINT_WARNING:ARGPARSE_PRINT_ERROR; if (configname)
pargs.err = ARGPARSE_PRINT_WARNING;
else
{
pargs.err = ARGPARSE_PRINT_ERROR;
/* The argparse function calls a plain exit and thus we
* need to print a status here. */
gpgsm_status_with_error (&ctrl, STATUS_FAILURE, "option-parser",
gpg_error (GPG_ERR_GENERAL));
}
break; break;
} }
} }
if (configfp) gpgrt_argparse (NULL, &pargs, NULL); /* Release internal state. */
{
fclose (configfp);
configfp = NULL;
/* Keep a copy of the config filename. */
opt.config_filename = configname;
configname = NULL;
goto next_pass;
}
xfree (configname);
configname = NULL;
if (!opt.config_filename) if (!last_configname)
opt.config_filename = make_filename (gnupg_homedir (), opt.config_filename = gpgrt_fnameconcat (gnupg_homedir (),
GPGSM_NAME EXTSEP_S "conf", GPGSM_NAME EXTSEP_S "conf",
NULL); NULL);
else
opt.config_filename = last_configname;
if (log_get_errorcount(0)) if (log_get_errorcount(0))
{ {
@ -1574,8 +1565,8 @@ main ( int argc, char **argv)
if (greeting) if (greeting)
{ {
es_fprintf (es_stderr, "%s %s; %s\n", es_fprintf (es_stderr, "%s %s; %s\n",
strusage(11), strusage(13), strusage(14) ); gpgrt_strusage(11), gpgrt_strusage(13), gpgrt_strusage(14) );
es_fprintf (es_stderr, "%s\n", strusage(15) ); es_fprintf (es_stderr, "%s\n", gpgrt_strusage(15) );
} }
# ifdef IS_DEVELOPMENT_VERSION # ifdef IS_DEVELOPMENT_VERSION
if (!opt.batch) if (!opt.batch)