diff --git a/common/Makefile.am b/common/Makefile.am index 9e0f10917..094ebe6e2 100644 --- a/common/Makefile.am +++ b/common/Makefile.am @@ -1,229 +1,228 @@ # Makefile for common gnupg modules # Copyright (C) 2001, 2003, 2007, 2010 Free Software Foundation, Inc. # # This file is part of GnuPG. # # GnuPG is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. # # GnuPG is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, see . ## Process this file with automake to produce Makefile.in EXTRA_DIST = mkstrtable.awk exaudit.awk exstatus.awk ChangeLog-2011 \ audit-events.h status-codes.h ChangeLog.jnlib \ ChangeLog-2011.include w32info-rc.h.in gnupg.ico \ all-tests.scm noinst_LIBRARIES = libcommon.a libcommonpth.a libgpgrl.a if !HAVE_W32CE_SYSTEM noinst_LIBRARIES += libsimple-pwquery.a endif noinst_PROGRAMS = $(module_tests) $(module_maint_tests) TESTS = $(module_tests) BUILT_SOURCES = audit-events.h status-codes.h MAINTAINERCLEANFILES = audit-events.h status-codes.h AM_CPPFLAGS = AM_CFLAGS = $(LIBGCRYPT_CFLAGS) $(LIBASSUAN_CFLAGS) $(KSBA_CFLAGS) include $(top_srcdir)/am/cmacros.am common_sources = \ common-defs.h \ util.h utilproto.h fwddecl.h i18n.c i18n.h \ types.h host2net.h dynload.h w32help.h \ mapstrings.c stringhelp.c stringhelp.h \ strlist.c strlist.h \ utf8conv.c utf8conv.h \ - argparse.c argparse.h \ logging.h \ dotlock.c dotlock.h \ mischelp.c mischelp.h \ status.c status.h\ shareddefs.h \ openpgpdefs.h \ gc-opt-flags.h \ keyserver.h \ sexp-parse.h \ tlv.c tlv.h \ init.c init.h \ sexputil.c \ sysutils.c sysutils.h \ homedir.c \ gettime.c gettime.h \ yesno.c \ b64enc.c b64dec.c zb32.c zb32.h \ convert.c \ percent.c \ mbox-util.c mbox-util.h \ miscellaneous.c \ xasprintf.c \ xreadline.c \ membuf.c membuf.h \ ccparray.c ccparray.h \ iobuf.c iobuf.h \ ttyio.c ttyio.h \ asshelp.c asshelp2.c asshelp.h \ exechelp.h \ signal.c \ audit.c audit.h \ localename.c \ session-env.c session-env.h \ userids.c userids.h \ openpgp-oid.c openpgp-s2k.c \ ssh-utils.c ssh-utils.h \ agent-opt.c \ helpfile.c \ mkdir_p.c mkdir_p.h \ strlist.c strlist.h \ exectool.c exectool.h \ server-help.c server-help.h \ name-value.c name-value.h \ recsel.c recsel.h \ ksba-io-support.c ksba-io-support.h \ compliance.c compliance.h \ pkscreening.c pkscreening.h if HAVE_W32_SYSTEM common_sources += w32-reg.c endif # To make the code easier to read we have split home some code into # separate source files. if HAVE_W32_SYSTEM if HAVE_W32CE_SYSTEM common_sources += exechelp-w32ce.c else common_sources += exechelp-w32.c endif else common_sources += exechelp-posix.c endif # Sources only useful without NPTH. without_npth_sources = \ get-passphrase.c get-passphrase.h # Sources only useful with NPTH. with_npth_sources = \ call-gpg.c call-gpg.h libcommon_a_SOURCES = $(common_sources) $(without_npth_sources) libcommon_a_CFLAGS = $(AM_CFLAGS) $(LIBASSUAN_CFLAGS) -DWITHOUT_NPTH=1 libcommonpth_a_SOURCES = $(common_sources) $(with_npth_sources) libcommonpth_a_CFLAGS = $(AM_CFLAGS) $(LIBASSUAN_CFLAGS) $(NPTH_CFLAGS) if !HAVE_W32CE_SYSTEM libsimple_pwquery_a_SOURCES = \ simple-pwquery.c simple-pwquery.h asshelp.c asshelp.h libsimple_pwquery_a_CFLAGS = $(AM_CFLAGS) $(LIBASSUAN_CFLAGS) endif libgpgrl_a_SOURCES = \ gpgrlhelp.c if MAINTAINER_MODE # Note: Due to the dependency on Makefile, the file will always be # rebuilt, so we allow this only in maintainer mode. # Create the audit-events.h include file from audit.h # Note: We create the target file in the source directory because it # is a distributed built source. If we would not do that we may end # up with two files and then it is not clear which version of the # files will be picked up. audit-events.h: Makefile.am mkstrtable.awk exaudit.awk audit.h $(AWK) -f $(srcdir)/exaudit.awk $(srcdir)/audit.h \ | $(AWK) -f $(srcdir)/mkstrtable.awk -v textidx=3 -v nogettext=1 \ -v pkg_namespace=eventstr_ > $(srcdir)/audit-events.h # Create the status-codes.h include file from status.h status-codes.h: Makefile.am mkstrtable.awk exstatus.awk status.h $(AWK) -f $(srcdir)/exstatus.awk $(srcdir)/status.h \ | $(AWK) -f $(srcdir)/mkstrtable.awk -v textidx=3 -v nogettext=1 \ -v pkg_namespace=statusstr_ > $(srcdir)/status-codes.h endif # # Module tests # module_tests = t-stringhelp t-timestuff \ t-convert t-percent t-gettime t-sysutils t-sexputil \ t-session-env t-openpgp-oid t-ssh-utils \ t-mapstrings t-zb32 t-mbox-util t-iobuf t-strlist \ t-name-value t-ccparray t-recsel if !HAVE_W32CE_SYSTEM module_tests += t-exechelp t-exectool endif if HAVE_W32_SYSTEM module_tests += t-w32-reg endif if MAINTAINER_MODE module_maint_tests = t-helpfile t-b64 else module_maint_tests = endif t_extra_src = t-support.h t_common_cflags = $(KSBA_CFLAGS) $(LIBGCRYPT_CFLAGS) \ $(LIBASSUAN_CFLAGS) $(GPG_ERROR_CFLAGS) $(INCICONV) t_common_ldadd = libcommon.a \ $(LIBGCRYPT_LIBS) $(LIBASSUAN_LIBS) $(GPG_ERROR_LIBS) \ $(LIBINTL) $(LIBICONV) # Common tests t_stringhelp_SOURCES = t-stringhelp.c $(t_extra_src) t_stringhelp_LDADD = $(t_common_ldadd) t_timestuff_SOURCES = t-timestuff.c $(t_extra_src) t_timestuff_LDADD = $(t_common_ldadd) t_convert_LDADD = $(t_common_ldadd) t_percent_LDADD = $(t_common_ldadd) t_gettime_LDADD = $(t_common_ldadd) t_sysutils_LDADD = $(t_common_ldadd) t_helpfile_LDADD = $(t_common_ldadd) t_sexputil_LDADD = $(t_common_ldadd) t_b64_LDADD = $(t_common_ldadd) t_exechelp_LDADD = $(t_common_ldadd) t_exectool_LDADD = $(t_common_ldadd) t_session_env_LDADD = $(t_common_ldadd) t_openpgp_oid_LDADD = $(t_common_ldadd) t_ssh_utils_LDADD = $(t_common_ldadd) t_mapstrings_LDADD = $(t_common_ldadd) t_zb32_SOURCES = t-zb32.c $(t_extra_src) t_zb32_LDADD = $(t_common_ldadd) t_mbox_util_LDADD = $(t_common_ldadd) t_iobuf_LDADD = $(t_common_ldadd) t_strlist_LDADD = $(t_common_ldadd) t_name_value_LDADD = $(t_common_ldadd) t_ccparray_LDADD = $(t_common_ldadd) t_recsel_LDADD = $(t_common_ldadd) # System specific test if HAVE_W32_SYSTEM t_w32_reg_SOURCES = t-w32-reg.c $(t_extra_src) t_w32_reg_LDADD = $(t_common_ldadd) endif # All programs should depend on the created libs. $(PROGRAMS) : libcommon.a libcommonpth.a diff --git a/common/argparse.c b/common/argparse.c deleted file mode 100644 index b30499bcc..000000000 --- a/common/argparse.c +++ /dev/null @@ -1,1663 +0,0 @@ -/* argparse.c - Argument Parser for option handling - * Copyright (C) 1997-2001, 2006-2008, 2013-2017 Werner Koch - * Copyright (C) 1998-2001, 2006-2008, 2012 Free Software Foundation, Inc. - * Copyright (C) 2015-2017 g10 Code GmbH - * - * This file is part of GnuPG. - * - * This file is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * This file is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, see . - * SPDX-License-Identifier: LGPL-2.1+ - */ - -/* This file may be used as part of GnuPG or standalone. A GnuPG - build is detected by the presence of the macro GNUPG_MAJOR_VERSION. - Some feature are only available in the GnuPG build mode. - */ - -#ifdef HAVE_CONFIG_H -#include -#endif -/* 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 -#include -#include -#include -#include -#include -#include - -#ifdef GNUPG_MAJOR_VERSION -# include "util.h" -# include "common-defs.h" -# include "i18n.h" -# include "mischelp.h" -# include "stringhelp.h" -# include "logging.h" -# include "utf8conv.h" -#endif /*GNUPG_MAJOR_VERSION*/ - -#include "argparse.h" - -/* GnuPG uses GPLv3+ but a standalone version of this defaults to - GPLv2+ because that is the license of this file. Change this if - you include it in a program which uses GPLv3. If you don't want to - set a copyright string for your usage() you may also hardcode it - here. */ -#ifndef GNUPG_MAJOR_VERSION - -# define ARGPARSE_GPL_VERSION 2 -# define ARGPARSE_CRIGHT_STR "Copyright (C) YEAR NAME" - -#else /* Used by GnuPG */ - -# define ARGPARSE_GPL_VERSION 3 -# define ARGPARSE_CRIGHT_STR "Copyright (C) 2018 Free Software Foundation, Inc." - -#endif /*GNUPG_MAJOR_VERSION*/ - -/* Replacements for standalone builds. */ -#ifndef GNUPG_MAJOR_VERSION -# ifndef _ -# define _(a) (a) -# endif -# ifndef DIM -# define DIM(v) (sizeof(v)/sizeof((v)[0])) -# endif -# define xtrymalloc(a) malloc ((a)) -# define xtryrealloc(a,b) realloc ((a), (b)) -# define xtrystrdup(a) strdup ((a)) -# define xfree(a) free ((a)) -# define log_error my_log_error -# define log_bug my_log_bug -# define trim_spaces(a) my_trim_spaces ((a)) -# define map_static_macro_string(a) (a) -#endif /*!GNUPG_MAJOR_VERSION*/ - - -#define ARGPARSE_STR(v) #v -#define ARGPARSE_STR2(v) ARGPARSE_STR(v) - - -/* Replacements for standalone builds. */ -#ifndef GNUPG_MAJOR_VERSION -static void -my_log_error (const char *fmt, ...) -{ - va_list arg_ptr ; - - va_start (arg_ptr, fmt); - fprintf (stderr, "%s: ", strusage (11)); - vfprintf (stderr, fmt, arg_ptr); - va_end (arg_ptr); -} - -static void -my_log_bug (const char *fmt, ...) -{ - va_list arg_ptr ; - - va_start (arg_ptr, fmt); - fprintf (stderr, "%s: Ohhhh jeeee: ", strusage (11)); - vfprintf (stderr, fmt, arg_ptr); - va_end (arg_ptr); - abort (); -} - -/* Return true if the native charset is utf-8. */ -static int -is_native_utf8 (void) -{ - return 1; -} - -static char * -my_trim_spaces (char *str) -{ - char *string, *p, *mark; - - string = str; - /* Find first non space character. */ - for (p=string; *p && isspace (*(unsigned char*)p) ; p++) - ; - /* Move characters. */ - for ((mark = NULL); (*string = *p); string++, p++) - if (isspace (*(unsigned char*)p)) - { - if (!mark) - mark = string; - } - else - mark = NULL; - if (mark) - *mark = '\0' ; /* Remove trailing spaces. */ - - return str ; -} - -#endif /*!GNUPG_MAJOR_VERSION*/ - - - -/********************************* - * @Summary arg_parse - * #include "argparse.h" - * - * typedef struct { - * char *argc; pointer to argc (value subject to change) - * char ***argv; pointer to argv (value subject to change) - * unsigned flags; Global flags (DO NOT CHANGE) - * int err; print error about last option - * 1 = warning, 2 = abort - * int r_opt; return option - * int r_type; type of return value (0 = no argument found) - * union { - * int ret_int; - * long ret_long - * ulong ret_ulong; - * char *ret_str; - * } r; Return values - * struct { - * int idx; - * const char *last; - * void *aliases; - * } internal; DO NOT CHANGE - * } ARGPARSE_ARGS; - * - * typedef struct { - * int short_opt; - * const char *long_opt; - * unsigned flags; - * } ARGPARSE_OPTS; - * - * int arg_parse( ARGPARSE_ARGS *arg, ARGPARSE_OPTS *opts ); - * - * @Description - * This is my replacement for getopt(). See the example for a typical usage. - * Global flags are: - * Bit 0 : Do not remove options form argv - * Bit 1 : Do not stop at last option but return other args - * with r_opt set to -1. - * Bit 2 : Assume options and real args are mixed. - * Bit 3 : Do not use -- to stop option processing. - * Bit 4 : Do not skip the first arg. - * Bit 5 : allow usage of long option with only one dash - * Bit 6 : ignore --version - * all other bits must be set to zero, this value is modified by the - * function, so assume this is write only. - * Local flags (for each option): - * Bit 2-0 : 0 = does not take an argument - * 1 = takes int argument - * 2 = takes string argument - * 3 = takes long argument - * 4 = takes ulong argument - * Bit 3 : argument is optional (r_type will the be set to 0) - * Bit 4 : allow 0x etc. prefixed values. - * Bit 6 : Ignore this option - * Bit 7 : This is a command and not an option - * You stop the option processing by setting opts to NULL, the function will - * then return 0. - * @Return Value - * Returns the args.r_opt or 0 if ready - * r_opt may be -2/-7 to indicate an unknown option/command. - * @See Also - * ArgExpand - * @Notes - * You do not need to process the options 'h', '--help' or '--version' - * because this function includes standard help processing; but if you - * specify '-h', '--help' or '--version' you have to do it yourself. - * The option '--' stops argument processing; if bit 1 is set the function - * continues to return normal arguments. - * To process float args or unsigned args you must use a string args and do - * the conversion yourself. - * @Example - * - * ARGPARSE_OPTS opts[] = { - * { 'v', "verbose", 0 }, - * { 'd', "debug", 0 }, - * { 'o', "output", 2 }, - * { 'c', "cross-ref", 2|8 }, - * { 'm', "my-option", 1|8 }, - * { 300, "ignored-long-option, ARGPARSE_OP_IGNORE}, - * { 500, "have-no-short-option-for-this-long-option", 0 }, - * {0} }; - * ARGPARSE_ARGS pargs = { &argc, &argv, 0 } - * - * while( ArgParse( &pargs, &opts) ) { - * switch( pargs.r_opt ) { - * case 'v': opt.verbose++; break; - * case 'd': opt.debug++; break; - * case 'o': opt.outfile = pargs.r.ret_str; break; - * case 'c': opt.crf = pargs.r_type? pargs.r.ret_str:"a.crf"; break; - * case 'm': opt.myopt = pargs.r_type? pargs.r.ret_int : 1; break; - * case 500: opt.a_long_one++; break - * default : pargs.err = 1; break; -- force warning output -- - * } - * } - * if( argc > 1 ) - * log_fatal( "Too many args"); - * - */ - -typedef struct alias_def_s *ALIAS_DEF; -struct alias_def_s { - ALIAS_DEF next; - char *name; /* malloced buffer with name, \0, value */ - const char *value; /* ptr into name */ -}; - - -/* Object to store the names for the --ignore-invalid-option option. - This is a simple linked list. */ -typedef struct iio_item_def_s *IIO_ITEM_DEF; -struct iio_item_def_s -{ - IIO_ITEM_DEF next; - char name[1]; /* String with the long option name. */ -}; - -static const char *(*strusage_handler)( int ) = NULL; -static int (*custom_outfnc) (int, const char *); - -static int set_opt_arg(ARGPARSE_ARGS *arg, unsigned flags, char *s); -static void show_help(ARGPARSE_OPTS *opts, unsigned flags); -static void show_version(void); -static int writestrings (int is_error, const char *string, ...) -#if __GNUC__ >= 4 - __attribute__ ((sentinel(0))) -#endif - ; - - -void -argparse_register_outfnc (int (*fnc)(int, const char *)) -{ - custom_outfnc = fnc; -} - - -/* Write STRING and all following const char * arguments either to - stdout or, if IS_ERROR is set, to stderr. The list of strings must - be terminated by a NULL. */ -static int -writestrings (int is_error, const char *string, ...) -{ - va_list arg_ptr; - const char *s; - int count = 0; - - if (string) - { - s = string; - va_start (arg_ptr, string); - do - { - if (custom_outfnc) - custom_outfnc (is_error? 2:1, s); - else - fputs (s, is_error? stderr : stdout); - count += strlen (s); - } - while ((s = va_arg (arg_ptr, const char *))); - va_end (arg_ptr); - } - return count; -} - - -static void -flushstrings (int is_error) -{ - if (custom_outfnc) - custom_outfnc (is_error? 2:1, NULL); - else - fflush (is_error? stderr : stdout); -} - - -static void -initialize( ARGPARSE_ARGS *arg, const char *filename, unsigned *lineno ) -{ - if( !(arg->flags & (1<<15)) ) - { - /* Initialize this instance. */ - arg->internal.idx = 0; - arg->internal.last = NULL; - arg->internal.inarg = 0; - arg->internal.stopped = 0; - arg->internal.aliases = NULL; - arg->internal.cur_alias = NULL; - arg->internal.iio_list = NULL; - arg->err = 0; - arg->flags |= 1<<15; /* Mark as initialized. */ - if ( *arg->argc < 0 ) - log_bug ("invalid argument for arg_parse\n"); - } - - - if (arg->err) - { - /* Last option was erroneous. */ - const char *s; - - if (filename) - { - if ( arg->r_opt == ARGPARSE_UNEXPECTED_ARG ) - s = _("argument not expected"); - else if ( arg->r_opt == ARGPARSE_READ_ERROR ) - s = _("read error"); - else if ( arg->r_opt == ARGPARSE_KEYWORD_TOO_LONG ) - s = _("keyword too long"); - else if ( arg->r_opt == ARGPARSE_MISSING_ARG ) - s = _("missing argument"); - else if ( arg->r_opt == ARGPARSE_INVALID_ARG ) - s = _("invalid argument"); - else if ( arg->r_opt == ARGPARSE_INVALID_COMMAND ) - s = _("invalid command"); - else if ( arg->r_opt == ARGPARSE_INVALID_ALIAS ) - s = _("invalid alias definition"); - else if ( arg->r_opt == ARGPARSE_OUT_OF_CORE ) - s = _("out of core"); - else - s = _("invalid option"); - log_error ("%s:%u: %s\n", filename, *lineno, s); - } - else - { - s = arg->internal.last? arg->internal.last:"[??]"; - - if ( arg->r_opt == ARGPARSE_MISSING_ARG ) - log_error (_("missing argument for option \"%.50s\"\n"), s); - else if ( arg->r_opt == ARGPARSE_INVALID_ARG ) - log_error (_("invalid argument for option \"%.50s\"\n"), s); - else if ( arg->r_opt == ARGPARSE_UNEXPECTED_ARG ) - log_error (_("option \"%.50s\" does not expect an argument\n"), s); - else if ( arg->r_opt == ARGPARSE_INVALID_COMMAND ) - log_error (_("invalid command \"%.50s\"\n"), s); - else if ( arg->r_opt == ARGPARSE_AMBIGUOUS_OPTION ) - log_error (_("option \"%.50s\" is ambiguous\n"), s); - else if ( arg->r_opt == ARGPARSE_AMBIGUOUS_COMMAND ) - log_error (_("command \"%.50s\" is ambiguous\n"),s ); - else if ( arg->r_opt == ARGPARSE_OUT_OF_CORE ) - log_error ("%s\n", _("out of core\n")); - else - log_error (_("invalid option \"%.50s\"\n"), s); - } - if (arg->err != ARGPARSE_PRINT_WARNING) - exit (2); - arg->err = 0; - } - - /* Zero out the return value union. */ - arg->r.ret_str = NULL; - arg->r.ret_long = 0; -} - - -static void -store_alias( ARGPARSE_ARGS *arg, char *name, char *value ) -{ - /* TODO: replace this dummy function with a rea one - * and fix the problems IRIX has with (ALIAS_DEV)arg.. - * used as lvalue - */ - (void)arg; - (void)name; - (void)value; -#if 0 - ALIAS_DEF a = xmalloc( sizeof *a ); - a->name = name; - a->value = value; - a->next = (ALIAS_DEF)arg->internal.aliases; - (ALIAS_DEF)arg->internal.aliases = a; -#endif -} - - -/* Return true if KEYWORD is in the ignore-invalid-option list. */ -static int -ignore_invalid_option_p (ARGPARSE_ARGS *arg, const char *keyword) -{ - IIO_ITEM_DEF item = arg->internal.iio_list; - - for (; item; item = item->next) - if (!strcmp (item->name, keyword)) - return 1; - return 0; -} - - -/* Add the keywords up to the next LF to the list of to be ignored - options. After returning FP will either be at EOF or the next - character read will be the first of a new line. The function - returns 0 on success or true on malloc failure. */ -static int -ignore_invalid_option_add (ARGPARSE_ARGS *arg, FILE *fp) -{ - IIO_ITEM_DEF item; - int c; - char name[100]; - int namelen = 0; - int ready = 0; - enum { skipWS, collectNAME, skipNAME, addNAME} state = skipWS; - - while (!ready) - { - c = getc (fp); - if (c == '\n') - ready = 1; - else if (c == EOF) - { - c = '\n'; - ready = 1; - } - again: - switch (state) - { - case skipWS: - if (!isascii (c) || !isspace(c)) - { - namelen = 0; - state = collectNAME; - goto again; - } - break; - - case collectNAME: - if (isspace (c)) - { - state = addNAME; - goto again; - } - else if (namelen < DIM(name)-1) - name[namelen++] = c; - else /* Too long. */ - state = skipNAME; - break; - - case skipNAME: - if (isspace (c)) - { - state = skipWS; - goto again; - } - break; - - case addNAME: - name[namelen] = 0; - if (!ignore_invalid_option_p (arg, name)) - { - item = xtrymalloc (sizeof *item + namelen); - if (!item) - return 1; - strcpy (item->name, name); - item->next = (IIO_ITEM_DEF)arg->internal.iio_list; - arg->internal.iio_list = item; - } - state = skipWS; - goto again; - } - } - return 0; -} - - -/* Clear the entire ignore-invalid-option list. */ -static void -ignore_invalid_option_clear (ARGPARSE_ARGS *arg) -{ - IIO_ITEM_DEF item, tmpitem; - - for (item = arg->internal.iio_list; item; item = tmpitem) - { - tmpitem = item->next; - xfree (item); - } - arg->internal.iio_list = NULL; -} - - - -/**************** - * Get options from a file. - * Lines starting with '#' are comment lines. - * Syntax is simply a keyword and the argument. - * Valid keywords are all keywords from the long_opt list without - * the leading dashes. The special keywords "help", "warranty" and "version" - * are not valid here. - * The special keyword "alias" may be used to store alias definitions, - * which are later expanded like long options. - * The option - * ignore-invalid-option OPTIONNAMEs - * is recognized and updates a list of option which should be ignored if they - * are not defined. - * Caller must free returned strings. - * If called with FP set to NULL command line args are parse instead. - * - * Q: Should we allow the syntax - * keyword = value - * and accept for boolean options a value of 1/0, yes/no or true/false? - * Note: Abbreviation of options is here not allowed. - */ -int -optfile_parse (FILE *fp, const char *filename, unsigned *lineno, - ARGPARSE_ARGS *arg, ARGPARSE_OPTS *opts) -{ - int state, i, c; - int idx=0; - char keyword[100]; - char *buffer = NULL; - size_t buflen = 0; - int in_alias=0; - int unread_buf[3]; /* We use an int so that we can store EOF. */ - int unread_buf_count = 0; - - if (!fp) /* Divert to arg_parse() in this case. */ - return arg_parse (arg, opts); - - initialize (arg, filename, lineno); - - /* If the LINENO is zero we assume that we are at the start of a - * file and we skip over a possible Byte Order Mark. */ - if (!*lineno) - { - unread_buf[0] = getc (fp); - unread_buf[1] = getc (fp); - unread_buf[2] = getc (fp); - if (unread_buf[0] != 0xef - || unread_buf[1] != 0xbb - || unread_buf[2] != 0xbf) - unread_buf_count = 3; - } - - /* Find the next keyword. */ - state = i = 0; - for (;;) - { - if (unread_buf_count) - c = unread_buf[3 - unread_buf_count--]; - else - c = getc (fp); - if (c == '\n' || c== EOF ) - { - if ( c != EOF ) - ++*lineno; - if (state == -1) - break; - else if (state == 2) - { - keyword[i] = 0; - for (i=0; opts[i].short_opt; i++ ) - { - if (opts[i].long_opt && !strcmp (opts[i].long_opt, keyword)) - break; - } - idx = i; - arg->r_opt = opts[idx].short_opt; - if ((opts[idx].flags & ARGPARSE_OPT_IGNORE)) - { - state = i = 0; - continue; - } - else if (!opts[idx].short_opt ) - { - if (!strcmp (keyword, "ignore-invalid-option")) - { - /* No argument - ignore this meta option. */ - state = i = 0; - continue; - } - else if (ignore_invalid_option_p (arg, keyword)) - { - /* This invalid option is in the iio list. */ - state = i = 0; - continue; - } - arg->r_opt = ((opts[idx].flags & ARGPARSE_OPT_COMMAND) - ? ARGPARSE_INVALID_COMMAND - : ARGPARSE_INVALID_OPTION); - } - else if (!(opts[idx].flags & ARGPARSE_TYPE_MASK)) - arg->r_type = 0; /* Does not take an arg. */ - else if ((opts[idx].flags & ARGPARSE_OPT_OPTIONAL) ) - arg->r_type = 0; /* Arg is optional. */ - else - arg->r_opt = ARGPARSE_MISSING_ARG; - - break; - } - else if (state == 3) - { - /* No argument found. */ - if (in_alias) - arg->r_opt = ARGPARSE_MISSING_ARG; - else if (!(opts[idx].flags & ARGPARSE_TYPE_MASK)) - arg->r_type = 0; /* Does not take an arg. */ - else if ((opts[idx].flags & ARGPARSE_OPT_OPTIONAL)) - arg->r_type = 0; /* No optional argument. */ - else - arg->r_opt = ARGPARSE_MISSING_ARG; - - break; - } - else if (state == 4) - { - /* Has an argument. */ - if (in_alias) - { - if (!buffer) - arg->r_opt = ARGPARSE_UNEXPECTED_ARG; - else - { - char *p; - - buffer[i] = 0; - p = strpbrk (buffer, " \t"); - if (p) - { - *p++ = 0; - trim_spaces (p); - } - if (!p || !*p) - { - xfree (buffer); - arg->r_opt = ARGPARSE_INVALID_ALIAS; - } - else - { - store_alias (arg, buffer, p); - } - } - } - else if (!(opts[idx].flags & ARGPARSE_TYPE_MASK)) - arg->r_opt = ARGPARSE_UNEXPECTED_ARG; - else - { - char *p; - - if (!buffer) - { - keyword[i] = 0; - buffer = xtrystrdup (keyword); - if (!buffer) - arg->r_opt = ARGPARSE_OUT_OF_CORE; - } - else - buffer[i] = 0; - - if (buffer) - { - trim_spaces (buffer); - p = buffer; - if (*p == '"') - { - /* Remove quotes. */ - p++; - if (*p && p[strlen(p)-1] == '\"' ) - p[strlen(p)-1] = 0; - } - if (!set_opt_arg (arg, opts[idx].flags, p)) - xfree (buffer); - else - gpgrt_annotate_leaked_object (buffer); - } - } - break; - } - else if (c == EOF) - { - ignore_invalid_option_clear (arg); - if (ferror (fp)) - arg->r_opt = ARGPARSE_READ_ERROR; - else - arg->r_opt = 0; /* EOF. */ - break; - } - state = 0; - i = 0; - } - else if (state == -1) - ; /* Skip. */ - else if (state == 0 && isascii (c) && isspace(c)) - ; /* Skip leading white space. */ - else if (state == 0 && c == '#' ) - state = 1; /* Start of a comment. */ - else if (state == 1) - ; /* Skip comments. */ - else if (state == 2 && isascii (c) && isspace(c)) - { - /* Check keyword. */ - keyword[i] = 0; - for (i=0; opts[i].short_opt; i++ ) - if (opts[i].long_opt && !strcmp (opts[i].long_opt, keyword)) - break; - idx = i; - arg->r_opt = opts[idx].short_opt; - if ((opts[idx].flags & ARGPARSE_OPT_IGNORE)) - { - state = 1; /* Process like a comment. */ - } - else if (!opts[idx].short_opt) - { - if (!strcmp (keyword, "alias")) - { - in_alias = 1; - state = 3; - } - else if (!strcmp (keyword, "ignore-invalid-option")) - { - if (ignore_invalid_option_add (arg, fp)) - { - arg->r_opt = ARGPARSE_OUT_OF_CORE; - break; - } - state = i = 0; - ++*lineno; - } - else if (ignore_invalid_option_p (arg, keyword)) - state = 1; /* Process like a comment. */ - else - { - arg->r_opt = ((opts[idx].flags & ARGPARSE_OPT_COMMAND) - ? ARGPARSE_INVALID_COMMAND - : ARGPARSE_INVALID_OPTION); - state = -1; /* Skip rest of line and leave. */ - } - } - else - state = 3; - } - else if (state == 3) - { - /* Skip leading spaces of the argument. */ - if (!isascii (c) || !isspace(c)) - { - i = 0; - keyword[i++] = c; - state = 4; - } - } - else if (state == 4) - { - /* Collect the argument. */ - if (buffer) - { - if (i < buflen-1) - buffer[i++] = c; - else - { - char *tmp; - size_t tmplen = buflen + 50; - - tmp = xtryrealloc (buffer, tmplen); - if (tmp) - { - buflen = tmplen; - buffer = tmp; - buffer[i++] = c; - } - else - { - xfree (buffer); - arg->r_opt = ARGPARSE_OUT_OF_CORE; - break; - } - } - } - else if (i < DIM(keyword)-1) - keyword[i++] = c; - else - { - size_t tmplen = DIM(keyword) + 50; - buffer = xtrymalloc (tmplen); - if (buffer) - { - buflen = tmplen; - memcpy(buffer, keyword, i); - buffer[i++] = c; - } - else - { - arg->r_opt = ARGPARSE_OUT_OF_CORE; - break; - } - } - } - else if (i >= DIM(keyword)-1) - { - arg->r_opt = ARGPARSE_KEYWORD_TOO_LONG; - state = -1; /* Skip rest of line and leave. */ - } - else - { - keyword[i++] = c; - state = 2; - } - } - - return arg->r_opt; -} - - - -static int -find_long_option( ARGPARSE_ARGS *arg, - ARGPARSE_OPTS *opts, const char *keyword ) -{ - int i; - size_t n; - - (void)arg; - - /* Would be better if we can do a binary search, but it is not - possible to reorder our option table because we would mess - up our help strings - What we can do is: Build a nice option - lookup table when this function is first invoked */ - if( !*keyword ) - return -1; - for(i=0; opts[i].short_opt; i++ ) - if( opts[i].long_opt && !strcmp( opts[i].long_opt, keyword) ) - return i; -#if 0 - { - ALIAS_DEF a; - /* see whether it is an alias */ - for( a = args->internal.aliases; a; a = a->next ) { - if( !strcmp( a->name, keyword) ) { - /* todo: must parse the alias here */ - args->internal.cur_alias = a; - return -3; /* alias available */ - } - } - } -#endif - /* not found, see whether it is an abbreviation */ - /* aliases may not be abbreviated */ - n = strlen( keyword ); - for(i=0; opts[i].short_opt; i++ ) { - if( opts[i].long_opt && !strncmp( opts[i].long_opt, keyword, n ) ) { - int j; - for(j=i+1; opts[j].short_opt; j++ ) { - if( opts[j].long_opt - && !strncmp( opts[j].long_opt, keyword, n ) - && !(opts[j].short_opt == opts[i].short_opt - && opts[j].flags == opts[i].flags ) ) - return -2; /* abbreviation is ambiguous */ - } - return i; - } - } - return -1; /* Not found. */ -} - -int -arg_parse( ARGPARSE_ARGS *arg, ARGPARSE_OPTS *opts) -{ - int idx; - int argc; - char **argv; - char *s, *s2; - int i; - - /* Fill in missing standard options: help, version, warranty and - * dump-options. */ - ARGPARSE_OPTS help_opt - = ARGPARSE_s_n (ARGPARSE_SHORTOPT_HELP, "help", "@"); - ARGPARSE_OPTS version_opt - = ARGPARSE_s_n (ARGPARSE_SHORTOPT_VERSION, "version", "@"); - ARGPARSE_OPTS warranty_opt - = ARGPARSE_s_n (ARGPARSE_SHORTOPT_WARRANTY, "warranty", "@"); - ARGPARSE_OPTS dump_options_opt - = ARGPARSE_s_n(ARGPARSE_SHORTOPT_DUMP_OPTIONS, "dump-options", "@"); - int seen_help = 0; - int seen_version = 0; - int seen_warranty = 0; - int seen_dump_options = 0; - - i = 0; - while (opts[i].short_opt) - { - if (opts[i].long_opt) - { - if (!strcmp(opts[i].long_opt, help_opt.long_opt)) - seen_help = 1; - else if (!strcmp(opts[i].long_opt, version_opt.long_opt)) - seen_version = 1; - else if (!strcmp(opts[i].long_opt, warranty_opt.long_opt)) - seen_warranty = 1; - else if (!strcmp(opts[i].long_opt, dump_options_opt.long_opt)) - seen_dump_options = 1; - } - i++; - } - if (! seen_help) - opts[i++] = help_opt; - if (! seen_version) - opts[i++] = version_opt; - if (! seen_warranty) - opts[i++] = warranty_opt; - if (! seen_dump_options) - opts[i++] = dump_options_opt; - - initialize( arg, NULL, NULL ); - argc = *arg->argc; - argv = *arg->argv; - idx = arg->internal.idx; - - if (!idx && argc && !(arg->flags & ARGPARSE_FLAG_ARG0)) - { - /* Skip the first argument. */ - argc--; argv++; idx++; - } - - next_one: - if (!argc) - { - /* No more args. */ - arg->r_opt = 0; - goto leave; /* Ready. */ - } - - s = *argv; - arg->internal.last = s; - - if (arg->internal.stopped && (arg->flags & ARGPARSE_FLAG_ALL)) - { - arg->r_opt = ARGPARSE_IS_ARG; /* Not an option but an argument. */ - arg->r_type = 2; - arg->r.ret_str = s; - argc--; argv++; idx++; /* set to next one */ - } - else if( arg->internal.stopped ) - { - arg->r_opt = 0; - goto leave; /* Ready. */ - } - else if ( *s == '-' && s[1] == '-' ) - { - /* Long option. */ - char *argpos; - - arg->internal.inarg = 0; - if (!s[2] && !(arg->flags & ARGPARSE_FLAG_NOSTOP)) - { - /* Stop option processing. */ - arg->internal.stopped = 1; - arg->flags |= ARGPARSE_FLAG_STOP_SEEN; - argc--; argv++; idx++; - goto next_one; - } - - argpos = strchr( s+2, '=' ); - if ( argpos ) - *argpos = 0; - i = find_long_option ( arg, opts, s+2 ); - if ( argpos ) - *argpos = '='; - - if (i > 0 && opts[i].short_opt == ARGPARSE_SHORTOPT_HELP) - show_help (opts, arg->flags); - else if (i > 0 && opts[i].short_opt == ARGPARSE_SHORTOPT_VERSION) - { - if (!(arg->flags & ARGPARSE_FLAG_NOVERSION)) - { - show_version (); - exit(0); - } - } - else if (i > 0 && opts[i].short_opt == ARGPARSE_SHORTOPT_WARRANTY) - { - writestrings (0, strusage (16), "\n", NULL); - exit (0); - } - else if (i > 0 && opts[i].short_opt == ARGPARSE_SHORTOPT_DUMP_OPTIONS) - { - for (i=0; opts[i].short_opt; i++ ) - { - if (opts[i].long_opt && !(opts[i].flags & ARGPARSE_OPT_IGNORE)) - writestrings (0, "--", opts[i].long_opt, "\n", NULL); - } - exit (0); - } - - if ( i == -2 ) - arg->r_opt = ARGPARSE_AMBIGUOUS_OPTION; - else if ( i == -1 ) - { - arg->r_opt = ARGPARSE_INVALID_OPTION; - arg->r.ret_str = s+2; - } - else - arg->r_opt = opts[i].short_opt; - if ( i < 0 ) - ; - else if ( (opts[i].flags & ARGPARSE_TYPE_MASK) ) - { - if ( argpos ) - { - s2 = argpos+1; - if ( !*s2 ) - s2 = NULL; - } - else - s2 = argv[1]; - if ( !s2 && (opts[i].flags & ARGPARSE_OPT_OPTIONAL) ) - { - arg->r_type = ARGPARSE_TYPE_NONE; /* Argument is optional. */ - } - else if ( !s2 ) - { - arg->r_opt = ARGPARSE_MISSING_ARG; - } - else if ( !argpos && *s2 == '-' - && (opts[i].flags & ARGPARSE_OPT_OPTIONAL) ) - { - /* The argument is optional and the next seems to be an - option. We do not check this possible option but - assume no argument */ - arg->r_type = ARGPARSE_TYPE_NONE; - } - else - { - set_opt_arg (arg, opts[i].flags, s2); - if ( !argpos ) - { - argc--; argv++; idx++; /* Skip one. */ - } - } - } - else - { - /* Does not take an argument. */ - if ( argpos ) - arg->r_type = ARGPARSE_UNEXPECTED_ARG; - else - arg->r_type = 0; - } - argc--; argv++; idx++; /* Set to next one. */ - } - else if ( (*s == '-' && s[1]) || arg->internal.inarg ) - { - /* Short option. */ - int dash_kludge = 0; - - i = 0; - if ( !arg->internal.inarg ) - { - arg->internal.inarg++; - if ( (arg->flags & ARGPARSE_FLAG_ONEDASH) ) - { - for (i=0; opts[i].short_opt; i++ ) - if ( opts[i].long_opt && !strcmp (opts[i].long_opt, s+1)) - { - dash_kludge = 1; - break; - } - } - } - s += arg->internal.inarg; - - if (!dash_kludge ) - { - for (i=0; opts[i].short_opt; i++ ) - if ( opts[i].short_opt == *s ) - break; - } - - if ( !opts[i].short_opt && ( *s == 'h' || *s == '?' ) ) - show_help (opts, arg->flags); - - arg->r_opt = opts[i].short_opt; - if (!opts[i].short_opt ) - { - arg->r_opt = (opts[i].flags & ARGPARSE_OPT_COMMAND)? - ARGPARSE_INVALID_COMMAND:ARGPARSE_INVALID_OPTION; - arg->internal.inarg++; /* Point to the next arg. */ - arg->r.ret_str = s; - } - else if ( (opts[i].flags & ARGPARSE_TYPE_MASK) ) - { - if ( s[1] && !dash_kludge ) - { - s2 = s+1; - set_opt_arg (arg, opts[i].flags, s2); - } - else - { - s2 = argv[1]; - if ( !s2 && (opts[i].flags & ARGPARSE_OPT_OPTIONAL) ) - { - arg->r_type = ARGPARSE_TYPE_NONE; - } - else if ( !s2 ) - { - arg->r_opt = ARGPARSE_MISSING_ARG; - } - else if ( *s2 == '-' && s2[1] - && (opts[i].flags & ARGPARSE_OPT_OPTIONAL) ) - { - /* The argument is optional and the next seems to - be an option. We do not check this possible - option but assume no argument. */ - arg->r_type = ARGPARSE_TYPE_NONE; - } - else - { - set_opt_arg (arg, opts[i].flags, s2); - argc--; argv++; idx++; /* Skip one. */ - } - } - s = "x"; /* This is so that !s[1] yields false. */ - } - else - { - /* Does not take an argument. */ - arg->r_type = ARGPARSE_TYPE_NONE; - arg->internal.inarg++; /* Point to the next arg. */ - } - if ( !s[1] || dash_kludge ) - { - /* No more concatenated short options. */ - arg->internal.inarg = 0; - argc--; argv++; idx++; - } - } - else if ( arg->flags & ARGPARSE_FLAG_MIXED ) - { - arg->r_opt = ARGPARSE_IS_ARG; - arg->r_type = 2; - arg->r.ret_str = s; - argc--; argv++; idx++; /* Set to next one. */ - } - else - { - arg->internal.stopped = 1; /* Stop option processing. */ - goto next_one; - } - - leave: - *arg->argc = argc; - *arg->argv = argv; - arg->internal.idx = idx; - return arg->r_opt; -} - - -/* Returns: -1 on error, 0 for an integer type and 1 for a non integer - type argument. */ -static int -set_opt_arg (ARGPARSE_ARGS *arg, unsigned flags, char *s) -{ - int base = (flags & ARGPARSE_OPT_PREFIX)? 0 : 10; - long l; - - switch ( (arg->r_type = (flags & ARGPARSE_TYPE_MASK)) ) - { - case ARGPARSE_TYPE_LONG: - case ARGPARSE_TYPE_INT: - errno = 0; - l = strtol (s, NULL, base); - if ((l == LONG_MIN || l == LONG_MAX) && errno == ERANGE) - { - arg->r_opt = ARGPARSE_INVALID_ARG; - return -1; - } - if (arg->r_type == ARGPARSE_TYPE_LONG) - arg->r.ret_long = l; - else if ( (l < 0 && l < INT_MIN) || l > INT_MAX ) - { - arg->r_opt = ARGPARSE_INVALID_ARG; - return -1; - } - else - arg->r.ret_int = (int)l; - return 0; - - case ARGPARSE_TYPE_ULONG: - while (isascii (*s) && isspace(*s)) - s++; - if (*s == '-') - { - arg->r.ret_ulong = 0; - arg->r_opt = ARGPARSE_INVALID_ARG; - return -1; - } - errno = 0; - arg->r.ret_ulong = strtoul (s, NULL, base); - if (arg->r.ret_ulong == ULONG_MAX && errno == ERANGE) - { - arg->r_opt = ARGPARSE_INVALID_ARG; - return -1; - } - return 0; - - case ARGPARSE_TYPE_STRING: - default: - arg->r.ret_str = s; - return 1; - } -} - - -static size_t -long_opt_strlen( ARGPARSE_OPTS *o ) -{ - size_t n = strlen (o->long_opt); - - if ( o->description && *o->description == '|' ) - { - const char *s; - int is_utf8 = is_native_utf8 (); - - s=o->description+1; - if ( *s != '=' ) - n++; - /* For a (mostly) correct length calculation we exclude - continuation bytes (10xxxxxx) if we are on a native utf8 - terminal. */ - for (; *s && *s != '|'; s++ ) - if ( is_utf8 && (*s&0xc0) != 0x80 ) - n++; - } - return n; -} - - -/**************** - * Print formatted help. The description string has some special - * meanings: - * - A description string which is "@" suppresses help output for - * this option - * - a description,ine which starts with a '@' and is followed by - * any other characters is printed as is; this may be used for examples - * and such. - * - A description which starts with a '|' outputs the string between this - * bar and the next one as arguments of the long option. - */ -static void -show_help (ARGPARSE_OPTS *opts, unsigned int flags) -{ - const char *s; - char tmp[2]; - - show_version (); - writestrings (0, "\n", NULL); - s = strusage (42); - if (s && *s == '1') - { - s = strusage (40); - writestrings (1, s, NULL); - if (*s && s[strlen(s)] != '\n') - writestrings (1, "\n", NULL); - } - s = strusage(41); - writestrings (0, s, "\n", NULL); - if ( opts[0].description ) - { - /* Auto format the option description. */ - int i,j, indent; - - /* Get max. length of long options. */ - for (i=indent=0; opts[i].short_opt; i++ ) - { - if ( opts[i].long_opt ) - if ( !opts[i].description || *opts[i].description != '@' ) - if ( (j=long_opt_strlen(opts+i)) > indent && j < 35 ) - indent = j; - } - - /* Example: " -v, --verbose Viele Sachen ausgeben" */ - indent += 10; - if ( *opts[0].description != '@' ) - writestrings (0, "Options:", "\n", NULL); - for (i=0; opts[i].short_opt; i++ ) - { - s = map_static_macro_string (_( opts[i].description )); - if ( s && *s== '@' && !s[1] ) /* Hide this line. */ - continue; - if ( s && *s == '@' ) /* Unindented comment only line. */ - { - for (s++; *s; s++ ) - { - if ( *s == '\n' ) - { - if( s[1] ) - writestrings (0, "\n", NULL); - } - else - { - tmp[0] = *s; - tmp[1] = 0; - writestrings (0, tmp, NULL); - } - } - writestrings (0, "\n", NULL); - continue; - } - - j = 3; - if ( opts[i].short_opt < 256 ) - { - tmp[0] = opts[i].short_opt; - tmp[1] = 0; - writestrings (0, " -", tmp, NULL ); - if ( !opts[i].long_opt ) - { - if (s && *s == '|' ) - { - writestrings (0, " ", NULL); j++; - for (s++ ; *s && *s != '|'; s++, j++ ) - { - tmp[0] = *s; - tmp[1] = 0; - writestrings (0, tmp, NULL); - } - if ( *s ) - s++; - } - } - } - else - writestrings (0, " ", NULL); - if ( opts[i].long_opt ) - { - tmp[0] = opts[i].short_opt < 256?',':' '; - tmp[1] = 0; - j += writestrings (0, tmp, " --", opts[i].long_opt, NULL); - if (s && *s == '|' ) - { - if ( *++s != '=' ) - { - writestrings (0, " ", NULL); - j++; - } - for ( ; *s && *s != '|'; s++, j++ ) - { - tmp[0] = *s; - tmp[1] = 0; - writestrings (0, tmp, NULL); - } - if ( *s ) - s++; - } - writestrings (0, " ", NULL); - j += 3; - } - for (;j < indent; j++ ) - writestrings (0, " ", NULL); - if ( s ) - { - if ( *s && j > indent ) - { - writestrings (0, "\n", NULL); - for (j=0;j < indent; j++ ) - writestrings (0, " ", NULL); - } - for (; *s; s++ ) - { - if ( *s == '\n' ) - { - if ( s[1] ) - { - writestrings (0, "\n", NULL); - for (j=0; j < indent; j++ ) - writestrings (0, " ", NULL); - } - } - else - { - tmp[0] = *s; - tmp[1] = 0; - writestrings (0, tmp, NULL); - } - } - } - writestrings (0, "\n", NULL); - } - if ( (flags & ARGPARSE_FLAG_ONEDASH) ) - writestrings (0, "\n(A single dash may be used " - "instead of the double ones)\n", NULL); - } - if ( (s=strusage(19)) ) - { - writestrings (0, "\n", NULL); - writestrings (0, s, NULL); - } - flushstrings (0); - exit(0); -} - -static void -show_version () -{ - const char *s; - int i; - - /* Version line. */ - writestrings (0, strusage (11), NULL); - if ((s=strusage (12))) - writestrings (0, " (", s, ")", NULL); - writestrings (0, " ", strusage (13), "\n", NULL); - /* Additional version lines. */ - for (i=20; i < 30; i++) - if ((s=strusage (i))) - writestrings (0, s, "\n", NULL); - /* Copyright string. */ - if ((s=strusage (14))) - writestrings (0, s, "\n", NULL); - /* Licence string. */ - if( (s=strusage (10)) ) - writestrings (0, s, "\n", NULL); - /* Copying conditions. */ - if ( (s=strusage(15)) ) - writestrings (0, s, NULL); - /* Thanks. */ - if ((s=strusage(18))) - writestrings (0, s, NULL); - /* Additional program info. */ - for (i=30; i < 40; i++ ) - if ( (s=strusage (i)) ) - writestrings (0, s, NULL); - flushstrings (0); -} - - -void -usage (int level) -{ - const char *p; - - if (!level) - { - writestrings (1, strusage(11), " ", strusage(13), "; ", - strusage (14), "\n", NULL); - flushstrings (1); - } - else if (level == 1) - { - p = strusage (40); - writestrings (1, p, NULL); - if (*p && p[strlen(p)] != '\n') - writestrings (1, "\n", NULL); - exit (2); - } - else if (level == 2) - { - p = strusage (42); - if (p && *p == '1') - { - p = strusage (40); - writestrings (1, p, NULL); - if (*p && p[strlen(p)] != '\n') - writestrings (1, "\n", NULL); - } - writestrings (0, strusage(41), "\n", NULL); - exit (0); - } -} - -/* Level - * 0: Print copyright string to stderr - * 1: Print a short usage hint to stderr and terminate - * 2: Print a long usage hint to stdout and terminate - * 10: Return license info string - * 11: Return the name of the program - * 12: Return optional name of package which includes this program. - * 13: version string - * 14: copyright string - * 15: Short copying conditions (with LFs) - * 16: Long copying conditions (with LFs) - * 17: Optional printable OS name - * 18: Optional thanks list (with LFs) - * 19: Bug report info - *20..29: Additional lib version strings. - *30..39: Additional program info (with LFs) - * 40: short usage note (with LF) - * 41: long usage note (with LF) - * 42: Flag string: - * First char is '1': - * The short usage notes needs to be printed - * before the long usage note. - */ -const char * -strusage( int level ) -{ - const char *p = strusage_handler? strusage_handler(level) : NULL; - - if ( p ) - return map_static_macro_string (p); - - switch ( level ) - { - - case 10: -#if ARGPARSE_GPL_VERSION == 3 - p = ("License GPLv3+: GNU GPL version 3 or later " - ""); -#else - p = ("License GPLv2+: GNU GPL version 2 or later " - ""); -#endif - break; - case 11: p = "foo"; break; - case 13: p = "0.0"; break; - case 14: p = ARGPARSE_CRIGHT_STR; break; - case 15: p = -"This is free software: you are free to change and redistribute it.\n" -"There is NO WARRANTY, to the extent permitted by law.\n"; - break; - case 16: p = -"This is free software; you can redistribute it and/or modify\n" -"it under the terms of the GNU General Public License as published by\n" -"the Free Software Foundation; either version " -ARGPARSE_STR2(ARGPARSE_GPL_VERSION) -" of the License, or\n" -"(at your option) any later version.\n\n" -"It is distributed in the hope that it will be useful,\n" -"but WITHOUT ANY WARRANTY; without even the implied warranty of\n" -"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" -"GNU General Public License for more details.\n\n" -"You should have received a copy of the GNU General Public License\n" -"along with this software. If not, see .\n"; - break; - case 40: /* short and long usage */ - case 41: p = ""; break; - } - - return p; -} - - -/* Set the usage handler. This function is basically a constructor. */ -void -set_strusage ( const char *(*f)( int ) ) -{ - strusage_handler = f; -} - - -#ifdef TEST -static struct { - int verbose; - int debug; - char *outfile; - char *crf; - int myopt; - int echo; - int a_long_one; -} opt; - -int -main(int argc, char **argv) -{ - ARGPARSE_OPTS opts[] = { - ARGPARSE_x('v', "verbose", NONE, 0, "Laut sein"), - ARGPARSE_s_n('e', "echo" , ("Zeile ausgeben, damit wir sehen, " - "was wir eingegeben haben")), - ARGPARSE_s_n('d', "debug", "Debug\nfalls mal etwas\nschief geht"), - ARGPARSE_s_s('o', "output", 0 ), - ARGPARSE_o_s('c', "cross-ref", "cross-reference erzeugen\n" ), - /* Note that on a non-utf8 terminal the ß might garble the output. */ - ARGPARSE_s_n('s', "street","|Straße|set the name of the street to Straße"), - ARGPARSE_o_i('m', "my-option", 0), - ARGPARSE_s_n(500, "a-long-option", 0 ), - ARGPARSE_end() - }; - ARGPARSE_ARGS pargs = { &argc, &argv, (ARGPARSE_FLAG_ALL - | ARGPARSE_FLAG_MIXED - | ARGPARSE_FLAG_ONEDASH) }; - int i; - - while (arg_parse (&pargs, opts)) - { - switch (pargs.r_opt) - { - case ARGPARSE_IS_ARG : - printf ("arg='%s'\n", pargs.r.ret_str); - break; - case 'v': opt.verbose++; break; - case 'e': opt.echo++; break; - case 'd': opt.debug++; break; - case 'o': opt.outfile = pargs.r.ret_str; break; - case 'c': opt.crf = pargs.r_type? pargs.r.ret_str:"a.crf"; break; - case 'm': opt.myopt = pargs.r_type? pargs.r.ret_int : 1; break; - case 500: opt.a_long_one++; break; - default : pargs.err = ARGPARSE_PRINT_WARNING; break; - } - } - for (i=0; i < argc; i++ ) - printf ("%3d -> (%s)\n", i, argv[i] ); - puts ("Options:"); - if (opt.verbose) - printf (" verbose=%d\n", opt.verbose ); - if (opt.debug) - printf (" debug=%d\n", opt.debug ); - if (opt.outfile) - printf (" outfile='%s'\n", opt.outfile ); - if (opt.crf) - printf (" crffile='%s'\n", opt.crf ); - if (opt.myopt) - printf (" myopt=%d\n", opt.myopt ); - if (opt.a_long_one) - printf (" a-long-one=%d\n", opt.a_long_one ); - if (opt.echo) - printf (" echo=%d\n", opt.echo ); - - return 0; -} -#endif /*TEST*/ - -/**** bottom of file ****/ diff --git a/common/argparse.h b/common/argparse.h deleted file mode 100644 index 4167d667a..000000000 --- a/common/argparse.h +++ /dev/null @@ -1,207 +0,0 @@ -/* argparse.h - Argument parser for option handling. - * Copyright (C) 1997-2001, 2006-2008, 2013-2017 Werner Koch - * Copyright (C) 1998-2001, 2006-2008, 2012 Free Software Foundation, Inc. - * Copyright (C) 2015-2017 g10 Code GmbH - * - * This file is part of GnuPG. - * - * This file is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * This file is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, see . - * SPDX-License-Identifier: LGPL-2.1+ - */ - -#ifndef GNUPG_COMMON_ARGPARSE_H -#define GNUPG_COMMON_ARGPARSE_H - -#include - -typedef struct -{ - int *argc; /* Pointer to ARGC (value subject to change). */ - char ***argv; /* Pointer to ARGV (value subject to change). */ - unsigned int flags; /* Global flags. May be set prior to calling the - parser. The parser may change the value. */ - int err; /* Print error description for last option. - Either 0, ARGPARSE_PRINT_WARNING or - ARGPARSE_PRINT_ERROR. */ - - int r_opt; /* Returns option code. */ - int r_type; /* Returns type of option value. */ - union { - int ret_int; - long ret_long; - unsigned long ret_ulong; - char *ret_str; - } r; /* Return values */ - - struct { - int idx; - int inarg; - int stopped; - const char *last; - void *aliases; - const void *cur_alias; - void *iio_list; - } internal; /* Private - do not change. */ -} ARGPARSE_ARGS; - -typedef struct -{ - int short_opt; - const char *long_opt; - unsigned int flags; - const char *description; /* Optional option description. */ -} ARGPARSE_OPTS; - -/* Short options. */ -#define ARGPARSE_SHORTOPT_HELP 32768 -#define ARGPARSE_SHORTOPT_VERSION 32769 -#define ARGPARSE_SHORTOPT_WARRANTY 32770 -#define ARGPARSE_SHORTOPT_DUMP_OPTIONS 32771 - - -/* Global flags (ARGPARSE_ARGS). */ -#define ARGPARSE_FLAG_KEEP 1 /* Do not remove options form argv. */ -#define ARGPARSE_FLAG_ALL 2 /* Do not stop at last option but return - remaining args with R_OPT set to -1. */ -#define ARGPARSE_FLAG_MIXED 4 /* Assume options and args are mixed. */ -#define ARGPARSE_FLAG_NOSTOP 8 /* Do not stop processing at "--". */ -#define ARGPARSE_FLAG_ARG0 16 /* Do not skip the first arg. */ -#define ARGPARSE_FLAG_ONEDASH 32 /* Allow long options with one dash. */ -#define ARGPARSE_FLAG_NOVERSION 64 /* No output for "--version". */ - -#define ARGPARSE_FLAG_STOP_SEEN 256 /* Set to true if a "--" has been seen. */ - -/* Flags for each option (ARGPARSE_OPTS). The type code may be - ORed with the OPT flags. */ -#define ARGPARSE_TYPE_NONE 0 /* Does not take an argument. */ -#define ARGPARSE_TYPE_INT 1 /* Takes an int argument. */ -#define ARGPARSE_TYPE_STRING 2 /* Takes a string argument. */ -#define ARGPARSE_TYPE_LONG 3 /* Takes a long argument. */ -#define ARGPARSE_TYPE_ULONG 4 /* Takes an unsigned long argument. */ -#define ARGPARSE_OPT_OPTIONAL (1<<3) /* Argument is optional. */ -#define ARGPARSE_OPT_PREFIX (1<<4) /* Allow 0x etc. prefixed values. */ -#define ARGPARSE_OPT_IGNORE (1<<6) /* Ignore command or option. */ -#define ARGPARSE_OPT_COMMAND (1<<7) /* The argument is a command. */ - -#define ARGPARSE_TYPE_MASK 7 /* Mask for the type values (internal). */ - -/* A set of macros to make option definitions easier to read. */ -#define ARGPARSE_x(s,l,t,f,d) \ - { (s), (l), ARGPARSE_TYPE_ ## t | (f), (d) } - -#define ARGPARSE_s(s,l,t,d) \ - { (s), (l), ARGPARSE_TYPE_ ## t, (d) } -#define ARGPARSE_s_n(s,l,d) \ - { (s), (l), ARGPARSE_TYPE_NONE, (d) } -#define ARGPARSE_s_i(s,l,d) \ - { (s), (l), ARGPARSE_TYPE_INT, (d) } -#define ARGPARSE_s_s(s,l,d) \ - { (s), (l), ARGPARSE_TYPE_STRING, (d) } -#define ARGPARSE_s_l(s,l,d) \ - { (s), (l), ARGPARSE_TYPE_LONG, (d) } -#define ARGPARSE_s_u(s,l,d) \ - { (s), (l), ARGPARSE_TYPE_ULONG, (d) } - -#define ARGPARSE_o(s,l,t,d) \ - { (s), (l), (ARGPARSE_TYPE_ ## t | ARGPARSE_OPT_OPTIONAL), (d) } -#define ARGPARSE_o_n(s,l,d) \ - { (s), (l), (ARGPARSE_TYPE_NONE | ARGPARSE_OPT_OPTIONAL), (d) } -#define ARGPARSE_o_i(s,l,d) \ - { (s), (l), (ARGPARSE_TYPE_INT | ARGPARSE_OPT_OPTIONAL), (d) } -#define ARGPARSE_o_s(s,l,d) \ - { (s), (l), (ARGPARSE_TYPE_STRING | ARGPARSE_OPT_OPTIONAL), (d) } -#define ARGPARSE_o_l(s,l,d) \ - { (s), (l), (ARGPARSE_TYPE_LONG | ARGPARSE_OPT_OPTIONAL), (d) } -#define ARGPARSE_o_u(s,l,d) \ - { (s), (l), (ARGPARSE_TYPE_ULONG | ARGPARSE_OPT_OPTIONAL), (d) } - -#define ARGPARSE_p(s,l,t,d) \ - { (s), (l), (ARGPARSE_TYPE_ ## t | ARGPARSE_OPT_PREFIX), (d) } -#define ARGPARSE_p_n(s,l,d) \ - { (s), (l), (ARGPARSE_TYPE_NONE | ARGPARSE_OPT_PREFIX), (d) } -#define ARGPARSE_p_i(s,l,d) \ - { (s), (l), (ARGPARSE_TYPE_INT | ARGPARSE_OPT_PREFIX), (d) } -#define ARGPARSE_p_s(s,l,d) \ - { (s), (l), (ARGPARSE_TYPE_STRING | ARGPARSE_OPT_PREFIX), (d) } -#define ARGPARSE_p_l(s,l,d) \ - { (s), (l), (ARGPARSE_TYPE_LONG | ARGPARSE_OPT_PREFIX), (d) } -#define ARGPARSE_p_u(s,l,d) \ - { (s), (l), (ARGPARSE_TYPE_ULONG | ARGPARSE_OPT_PREFIX), (d) } - -#define ARGPARSE_op(s,l,t,d) \ - { (s), (l), (ARGPARSE_TYPE_ ## t \ - | ARGPARSE_OPT_OPTIONAL | ARGPARSE_OPT_PREFIX), (d) } -#define ARGPARSE_op_n(s,l,d) \ - { (s), (l), (ARGPARSE_TYPE_NONE \ - | ARGPARSE_OPT_OPTIONAL | ARGPARSE_OPT_PREFIX), (d) } -#define ARGPARSE_op_i(s,l,d) \ - { (s), (l), (ARGPARSE_TYPE_INT \ - | ARGPARSE_OPT_OPTIONAL | ARGPARSE_OPT_PREFIX), (d) } -#define ARGPARSE_op_s(s,l,d) \ - { (s), (l), (ARGPARSE_TYPE_STRING \ - | ARGPARSE_OPT_OPTIONAL | ARGPARSE_OPT_PREFIX), (d) } -#define ARGPARSE_op_l(s,l,d) \ - { (s), (l), (ARGPARSE_TYPE_LONG \ - | ARGPARSE_OPT_OPTIONAL | ARGPARSE_OPT_PREFIX), (d) } -#define ARGPARSE_op_u(s,l,d) \ - { (s), (l), (ARGPARSE_TYPE_ULONG \ - | ARGPARSE_OPT_OPTIONAL | ARGPARSE_OPT_PREFIX), (d) } - -#define ARGPARSE_c(s,l,d) \ - { (s), (l), (ARGPARSE_TYPE_NONE | ARGPARSE_OPT_COMMAND), (d) } - -#define ARGPARSE_ignore(s,l) \ - { (s), (l), (ARGPARSE_OPT_IGNORE), "@" } - -#define ARGPARSE_group(s,d) \ - { (s), NULL, 0, (d) } - -/* Placeholder options for help, version, warranty and dump-options. See arg_parse(). */ -#define ARGPARSE_end() \ - { 0, NULL, 0, NULL }, \ - { 0, NULL, 0, NULL }, \ - { 0, NULL, 0, NULL }, \ - { 0, NULL, 0, NULL }, \ - { 0, NULL, 0, NULL } - - -/* Other constants. */ -#define ARGPARSE_PRINT_WARNING 1 -#define ARGPARSE_PRINT_ERROR 2 - - -/* Error values. */ -#define ARGPARSE_IS_ARG (-1) -#define ARGPARSE_INVALID_OPTION (-2) -#define ARGPARSE_MISSING_ARG (-3) -#define ARGPARSE_KEYWORD_TOO_LONG (-4) -#define ARGPARSE_READ_ERROR (-5) -#define ARGPARSE_UNEXPECTED_ARG (-6) -#define ARGPARSE_INVALID_COMMAND (-7) -#define ARGPARSE_AMBIGUOUS_OPTION (-8) -#define ARGPARSE_AMBIGUOUS_COMMAND (-9) -#define ARGPARSE_INVALID_ALIAS (-10) -#define ARGPARSE_OUT_OF_CORE (-11) -#define ARGPARSE_INVALID_ARG (-12) - - -int arg_parse (ARGPARSE_ARGS *arg, ARGPARSE_OPTS *opts); -int optfile_parse (FILE *fp, const char *filename, unsigned *lineno, - ARGPARSE_ARGS *arg, ARGPARSE_OPTS *opts); -void usage (int level); -const char *strusage (int level); -void set_strusage (const char *(*f)( int )); -void argparse_register_outfnc (int (*fnc)(int, const char *)); - -#endif /*GNUPG_COMMON_ARGPARSE_H*/ diff --git a/common/init.c b/common/init.c index f62c5cd58..073c5cd8a 100644 --- a/common/init.c +++ b/common/init.c @@ -1,293 +1,292 @@ /* init.c - Various initializations * Copyright (C) 2007 Free Software Foundation, Inc. * * This file is part of GnuPG. * * This file is free software; you can redistribute it and/or modify * it under the terms of either * * - the GNU Lesser General Public License as published by the Free * Software Foundation; either version 3 of the License, or (at * your option) any later version. * * or * * - the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at * your option) any later version. * * or both in parallel, as here. * * This file is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . */ #include #ifdef HAVE_W32_SYSTEM # ifdef HAVE_WINSOCK2_H # include # endif # include #endif #ifdef HAVE_W32CE_SYSTEM # include /* For _assuan_w32ce_finish_pipe. */ #endif #include #include "util.h" #include "i18n.h" /* This object is used to register memory cleanup functions. Technically they are not needed but they can avoid frequent questions about un-released memory. Note that we use the system malloc and not any wrappers. */ struct mem_cleanup_item_s; typedef struct mem_cleanup_item_s *mem_cleanup_item_t; struct mem_cleanup_item_s { mem_cleanup_item_t next; void (*func) (void); }; static mem_cleanup_item_t mem_cleanup_list; /* The default error source of the application. This is different from GPG_ERR_SOURCE_DEFAULT in that it does not depend on the source file and thus is usable in code shared by applications. Note that we need to initialize it because otherwise some linkers (OS X at least) won't find the symbol when linking the t-*.c files. */ gpg_err_source_t default_errsource = 0; #ifdef HAVE_W32CE_SYSTEM static void parse_std_file_handles (int *argcp, char ***argvp); static void sleep_on_exit (void) { /* The sshd on CE swallows some of the command output. Sleeping a while usually helps. */ Sleep (400); } #endif /*HAVE_W32CE_SYSTEM*/ static void run_mem_cleanup (void) { mem_cleanup_item_t next; while (mem_cleanup_list) { next = mem_cleanup_list->next; mem_cleanup_list->func (); free (mem_cleanup_list); mem_cleanup_list = next; } } void register_mem_cleanup_func (void (*func)(void)) { mem_cleanup_item_t item; for (item = mem_cleanup_list; item; item = item->next) if (item->func == func) return; /* Function has already been registered. */ item = malloc (sizeof *item); if (item) { item->func = func; item->next = mem_cleanup_list; mem_cleanup_list = item; } } /* If STRING is not NULL write string to es_stdout or es_stderr. MODE must be 1 or 2. If STRING is NULL flush the respective stream. */ static int writestring_via_estream (int mode, const char *string) { if (mode == 1 || mode == 2) { if (string) return es_fputs (string, mode == 1? es_stdout : es_stderr); else return es_fflush (mode == 1? es_stdout : es_stderr); } else return -1; } /* This function should be the first called after main. */ void early_system_init (void) { } /* This function is to be used early at program startup to make sure that some subsystems are initialized. This is in particular important for W32 to initialize the sockets so that our socket emulation code used directly as well as in libassuan may be used. It should best be called before any I/O is done so that setup required for logging is ready. ARGCP and ARGVP are the addresses of the parameters given to main. This function may modify them. This function should be called only via the macro init_common_subsystems. CAUTION: This might be called while running suid(root). */ void _init_common_subsystems (gpg_err_source_t errsource, int *argcp, char ***argvp) { /* Store the error source in a global variable. */ default_errsource = errsource; atexit (run_mem_cleanup); /* Try to auto set the character set. */ set_native_charset (NULL); #ifdef HAVE_W32_SYSTEM /* For W32 we need to initialize the socket layer. This is because we use recv and send in libassuan as well as at some other places. */ { WSADATA wsadat; WSAStartup (0x202, &wsadat); } #endif #ifdef HAVE_W32CE_SYSTEM /* Register the sleep exit function before the estream init so that the sleep will be called after the estream registered atexit function which flushes the left open estream streams and in particular es_stdout. */ atexit (sleep_on_exit); #endif if (!gcry_check_version (NEED_LIBGCRYPT_VERSION)) { log_fatal (_("%s is too old (need %s, have %s)\n"), "libgcrypt", NEED_LIBGCRYPT_VERSION, gcry_check_version (NULL)); } /* Initialize the Estream library. */ gpgrt_init (); gpgrt_set_alloc_func (gcry_realloc); /* Special hack for Windows CE: We extract some options from arg to setup the standard handles. */ #ifdef HAVE_W32CE_SYSTEM parse_std_file_handles (argcp, argvp); #else (void)argcp; (void)argvp; #endif /* Access the standard estreams as early as possible. If we don't do this the original stdio streams may have been closed when _es_get_std_stream is first use and in turn it would connect to the bit bucket. */ { int i; for (i=0; i < 3; i++) (void)_gpgrt_get_std_stream (i); } /* --version et al shall use estream as well. */ - argparse_register_outfnc (writestring_via_estream); /* legacy. */ gpgrt_set_usage_outfnc (writestring_via_estream); /* Register our string mapper with gpgrt. */ gpgrt_set_fixed_string_mapper (map_static_macro_string); /* Logging shall use the standard socket directory as fallback. */ log_set_socket_dir_cb (gnupg_socketdir); } /* WindowsCE uses a very strange way of handling the standard streams. There is a function SetStdioPath to associate a standard stream with a file or a device but what we really want is to use pipes as standard streams. Despite that we implement pipes using a device, we would have some limitations on the number of open pipes due to the 3 character limit of device file name. Thus we don't take this path. Another option would be to install a file system driver with support for pipes; this would allow us to get rid of the device name length limitation. However, with GnuPG we can get away be redefining the standard streams and passing the handles to be used on the command line. This has also the advantage that it makes creating a process much easier and does not require the SetStdioPath set and restore game. The caller needs to pass the rendezvous ids using up to three options: -&S0= -&S1= -&S2= They are all optional but they must be the first arguments on the command line. Parsing stops as soon as an invalid option is found. These rendezvous ids are then used to finish the pipe creation.*/ #ifdef HAVE_W32CE_SYSTEM static void parse_std_file_handles (int *argcp, char ***argvp) { int argc = *argcp; char **argv = *argvp; const char *s; assuan_fd_t fd; int i; int fixup = 0; if (!argc) return; for (argc--, argv++; argc; argc--, argv++) { s = *argv; if (*s == '-' && s[1] == '&' && s[2] == 'S' && (s[3] == '0' || s[3] == '1' || s[3] == '2') && s[4] == '=' && (strchr ("-01234567890", s[5]) || !strcmp (s+5, "null"))) { if (s[5] == 'n') fd = ASSUAN_INVALID_FD; else fd = _assuan_w32ce_finish_pipe (atoi (s+5), s[3] != '0'); _es_set_std_fd (s[3] - '0', (int)fd); fixup++; } else break; } if (fixup) { argc = *argcp; argc -= fixup; *argcp = argc; argv = *argvp; for (i=1; i < argc; i++) argv[i] = argv[i + fixup]; for (; i < argc + fixup; i++) argv[i] = NULL; } } #endif /*HAVE_W32CE_SYSTEM*/ diff --git a/po/POTFILES.in b/po/POTFILES.in index e35a7938d..0f12f53fb 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -1,133 +1,132 @@ # List of files with translatable strings agent/call-pinentry.c agent/command-ssh.c agent/divert-scd.c agent/genkey.c agent/gpg-agent.c agent/preset-passphrase.c agent/protect-tool.c agent/trustlist.c agent/findkey.c agent/pksign.c agent/cvt-openpgp.c common/exechelp-posix.c common/exechelp-w32.c common/exechelp-w32ce.c common/simple-pwquery.c common/sysutils.c common/yesno.c common/miscellaneous.c common/asshelp.c common/audit.c common/helpfile.c common/gettime.c common/ksba-io-support.c -common/argparse.c common/utf8conv.c common/dotlock.c common/init.c g10/armor.c g10/build-packet.c g10/call-agent.c g10/card-util.c g10/dearmor.c g10/decrypt.c g10/delkey.c g10/encrypt.c g10/decrypt-data.c g10/exec.c g10/export.c g10/getkey.c g10/gpg.c g10/gpgv.c g10/helptext.c g10/import.c g10/keydb.c g10/keyedit.c g10/keygen.c g10/keyid.c g10/keylist.c g10/keyring.c g10/keyserver.c g10/mainproc.c g10/misc.c g10/openfile.c g10/parse-packet.c g10/passphrase.c g10/photoid.c g10/pkclist.c g10/plaintext.c g10/pubkey-enc.c g10/revoke.c g10/seskey.c g10/sig-check.c g10/sign.c g10/skclist.c g10/tdbdump.c g10/tdbio.c g10/textfilter.c g10/tofu.c g10/trustdb.c g10/trust.c g10/verify.c g10/cipher-cfb.c g10/cipher-aead.c kbx/kbxutil.c scd/app-nks.c scd/app-openpgp.c scd/app-dinsig.c scd/scdaemon.c sm/call-agent.c sm/call-dirmngr.c sm/certchain.c sm/certcheck.c sm/certdump.c sm/certlist.c sm/certreqgen.c sm/certreqgen-ui.c sm/decrypt.c sm/delete.c sm/encrypt.c sm/export.c sm/gpgsm.c sm/import.c sm/keydb.c sm/keylist.c sm/misc.c sm/qualified.c sm/sign.c sm/verify.c dirmngr/certcache.c dirmngr/crlcache.c dirmngr/crlfetch.c dirmngr/dirmngr-client.c dirmngr/dirmngr.c dirmngr/dirmngr_ldap.c dirmngr/http.c dirmngr/ldap-wrapper.c dirmngr/ldap.c dirmngr/ldapserver.c dirmngr/misc.c dirmngr/ocsp.c dirmngr/server.c dirmngr/validate.c tools/gpg-connect-agent.c tools/gpgconf-comp.c tools/gpgconf.c tools/no-libgcrypt.c tools/symcryptrun.c tools/gpg-check-pattern.c tools/gpg-card.c tools/card-misc.c tools/card-keys.c tools/card-yubikey.c tools/card-call-scd.c diff --git a/tests/gpgscm/main.c b/tests/gpgscm/main.c index dc176c302..bd579c43f 100644 --- a/tests/gpgscm/main.c +++ b/tests/gpgscm/main.c @@ -1,363 +1,360 @@ /* TinyScheme-based test driver. * * Copyright (C) 2016 g10 code GmbH * * This file is part of GnuPG. * * GnuPG is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * GnuPG is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . + * SPDX-License-Identifier: GPL-3.0-or-later */ #include -/* 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 #include #include #include #include #include #include #include #include #include #include #include #if HAVE_MMAP #include #endif #include "private.h" #include "scheme.h" #include "scheme-private.h" #include "ffi.h" #include "../common/i18n.h" -#include "../../common/argparse.h" #include "../../common/init.h" #include "../../common/logging.h" #include "../../common/strlist.h" #include "../../common/sysutils.h" #include "../../common/util.h" -#include "../common/argparse.h" /* temporary hack. */ /* The TinyScheme banner. Unfortunately, it isn't in the header file. */ #define ts_banner "TinyScheme 1.41" int verbose; /* Constants to identify the commands and options. */ enum cmd_and_opt_values { aNull = 0, oVerbose = 'v', }; /* The list of commands and options. */ -static ARGPARSE_OPTS opts[] = +static gpgrt_opt_t opts[] = { ARGPARSE_s_n (oVerbose, "verbose", N_("verbose")), ARGPARSE_end (), }; char *scmpath = ""; size_t scmpath_len = 0; /* Command line parsing. */ static void -parse_arguments (ARGPARSE_ARGS *pargs, ARGPARSE_OPTS *popts) +parse_arguments (gpgrt_argparse_t *pargs, gpgrt_opt_t *popts) { - int no_more_options = 0; - - while (!no_more_options && optfile_parse (NULL, NULL, NULL, pargs, popts)) + while (gpgrt_argparse (NULL, pargs, popts)) { switch (pargs->r_opt) { case oVerbose: verbose++; break; default: - pargs->err = 2; + pargs->err = ARGPARSE_PRINT_ERROR; break; } } } /* Print usage information and provide strings for help. */ static const char * my_strusage( int level ) { const char *p; switch (level) { + case 9: p = "GPL-3.0-or-later"; break; case 11: p = "gpgscm (@GNUPG@)"; break; case 13: p = VERSION; break; + case 14: p = GNUPG_DEF_COPYRIGHT_LINE; break; case 17: p = PRINTABLE_OS_NAME; break; case 19: p = _("Please report bugs to <@EMAIL@>.\n"); break; case 1: case 40: p = _("Usage: gpgscm [options] [file] (-h for help)"); break; case 41: p = _("Syntax: gpgscm [options] [file]\n" "Execute the given Scheme program, or spawn interactive shell.\n"); break; default: p = NULL; break; } return p; } static int path_absolute_p (const char *p) { #if _WIN32 return ((strlen (p) > 2 && p[1] == ':' && (p[2] == '\\' || p[2] == '/')) || p[0] == '\\' || p[0] == '/'); #else return p[0] == '/'; #endif } /* Load the Scheme program from FILE_NAME. If FILE_NAME is not an absolute path, and LOOKUP_IN_PATH is given, then it is qualified with the values in scmpath until the file is found. */ static gpg_error_t load (scheme *sc, char *file_name, int lookup_in_cwd, int lookup_in_path) { gpg_error_t err = 0; size_t n; const char *directory; char *qualified_name = file_name; int use_path; FILE *h = NULL; use_path = lookup_in_path && ! (path_absolute_p (file_name) || scmpath_len == 0); if (path_absolute_p (file_name) || lookup_in_cwd || scmpath_len == 0) { h = fopen (file_name, "r"); if (! h) err = gpg_error_from_syserror (); } if (h == NULL && use_path) for (directory = scmpath, n = scmpath_len; n; directory += strlen (directory) + 1, n--) { if (asprintf (&qualified_name, "%s/%s", directory, file_name) < 0) return gpg_error_from_syserror (); h = fopen (qualified_name, "r"); if (h) { err = 0; break; } if (n > 1) { free (qualified_name); continue; /* Try again! */ } err = gpg_error_from_syserror (); } if (h == NULL) { /* Failed and no more elements in scmpath to try. */ fprintf (stderr, "Could not read %s: %s.\n", qualified_name, gpg_strerror (err)); if (lookup_in_path) fprintf (stderr, "Consider using GPGSCM_PATH to specify the location " "of the Scheme library.\n"); goto leave; } if (verbose > 2) fprintf (stderr, "Loading %s...\n", qualified_name); #if HAVE_MMAP /* Always try to mmap the file. This allows the pages to be shared * between processes. If anything fails, we fall back to using * buffered streams. */ if (1) { struct stat st; void *map; size_t len; int fd = fileno (h); if (fd < 0) goto fallback; if (fstat (fd, &st)) goto fallback; len = (size_t) st.st_size; if ((off_t) len != st.st_size) goto fallback; /* Truncated. */ map = mmap (NULL, len, PROT_READ, MAP_SHARED, fd, 0); if (map == MAP_FAILED) goto fallback; scheme_load_memory (sc, map, len, qualified_name); munmap (map, len); } else fallback: #endif scheme_load_named_file (sc, h, qualified_name); fclose (h); if (sc->retcode && sc->nesting) { fprintf (stderr, "%s: Unbalanced parenthesis\n", qualified_name); err = gpg_error (GPG_ERR_GENERAL); } leave: if (file_name != qualified_name) free (qualified_name); return err; } int main (int argc, char **argv) { int retcode; gpg_error_t err; char *argv0; - ARGPARSE_ARGS pargs; + gpgrt_argparse_t pargs; scheme *sc; char *p; #if _WIN32 char pathsep = ';'; #else char pathsep = ':'; #endif char *script = NULL; /* Save argv[0] so that we can re-exec. */ argv0 = argv[0]; /* Parse path. */ if (getenv ("GPGSCM_PATH")) scmpath = getenv ("GPGSCM_PATH"); p = scmpath = strdup (scmpath); if (p == NULL) return 2; if (*p) scmpath_len++; for (; *p; p++) if (*p == pathsep) *p = 0, scmpath_len++; - set_strusage (my_strusage); + gpgrt_set_strusage (my_strusage); log_set_prefix ("gpgscm", GPGRT_LOG_WITH_PREFIX); /* Make sure that our subsystems are ready. */ i18n_init (); init_common_subsystems (&argc, &argv); if (!gcry_check_version (NEED_LIBGCRYPT_VERSION)) { fputs ("libgcrypt version mismatch\n", stderr); exit (2); } /* Parse the command line. */ pargs.argc = &argc; pargs.argv = &argv; pargs.flags = 0; parse_arguments (&pargs, opts); + gpgrt_argparse (NULL, &pargs, NULL); if (log_get_errorcount (0)) exit (2); sc = scheme_init_new_custom_alloc (gcry_malloc, gcry_free); if (! sc) { fprintf (stderr, "Could not initialize TinyScheme!\n"); return 2; } scheme_set_input_port_file (sc, stdin); scheme_set_output_port_file (sc, stderr); if (argc) { script = argv[0]; argc--, argv++; } err = load (sc, "init.scm", 0, 1); if (! err) err = load (sc, "ffi.scm", 0, 1); if (! err) err = ffi_init (sc, argv0, script ? script : "interactive", argc, (const char **) argv); if (! err) err = load (sc, "lib.scm", 0, 1); if (! err) err = load (sc, "repl.scm", 0, 1); if (! err) err = load (sc, "xml.scm", 0, 1); if (! err) err = load (sc, "tests.scm", 0, 1); if (! err) err = load (sc, "gnupg.scm", 0, 1); if (err) { fprintf (stderr, "Error initializing gpgscm: %s.\n", gpg_strerror (err)); exit (2); } if (script == NULL) { /* Interactive shell. */ fprintf (stderr, "gpgscm/"ts_banner".\n"); scheme_load_string (sc, "(interactive-repl)"); } else { err = load (sc, script, 1, 1); if (err) log_fatal ("%s: %s", script, gpg_strerror (err)); } retcode = sc->retcode; scheme_load_string (sc, "(*run-atexit-handlers*)"); scheme_deinit (sc); xfree (sc); return retcode; }