diff options
-rw-r--r-- | NEWS | 3 | ||||
-rw-r--r-- | src/argparse.c | 73 | ||||
-rw-r--r-- | src/gpg-error.h.in | 3 | ||||
-rw-r--r-- | tests/etc/t-argparse.conf | 42 | ||||
-rw-r--r-- | tests/t-argparse.c | 5 | ||||
-rw-r--r-- | tests/t-argparse.conf | 3 |
6 files changed, 113 insertions, 16 deletions
@@ -15,6 +15,9 @@ Noteworthy changes in version 1.38 (unreleased) [C28/A28/R_] ARGPARSE_CONFFILE NEW. ARGPARSE_OPT_CONFFILE NEW. ARGPARSE_PERMISSION_ERROR NEW. + ARGPARSE_INVALID_META NEW. + ARGPARSE_UNKNOWN_META NEW. + ARGPARSE_UNEXPECTED_META NEW. ARGPARSE_conffile NEW. ARGPARSE_noconffile NEW. GPGRT_CONFDIR_USER NEW. diff --git a/src/argparse.c b/src/argparse.c index 6f6431d..765c96c 100644 --- a/src/argparse.c +++ b/src/argparse.c @@ -86,6 +86,7 @@ struct _gpgrt_argparse_internal_s int idx; /* Note that this is saved and restored in _gpgrt_argparser. */ int inarg; int stopped; + int insysconfig; /* Processing global config file. */ int explicit_confopt; /* A conffile option has been given. */ char *explicit_conffile; /* Malloced name of an explicit conffile. */ unsigned int opt_flags; /* Current option flags. */ @@ -278,6 +279,7 @@ initialize (gpgrt_argparse_t *arg, gpgrt_opt_t *opts, estream_t fp) arg->internal->last = NULL; arg->internal->inarg = 0; arg->internal->stopped = 0; + arg->internal->insysconfig = 0; arg->internal->explicit_confopt = 0; arg->internal->explicit_conffile = NULL; arg->internal->opt_flags = 0; @@ -393,6 +395,12 @@ initialize (gpgrt_argparse_t *arg, gpgrt_opt_t *opts, estream_t fp) s = _("out of core"); else if ( arg->r_opt == ARGPARSE_NO_CONFFILE ) s = NULL; /* Error has already been printed. */ + else if ( arg->r_opt == ARGPARSE_INVALID_META ) + s = _("invalid meta command"); + else if ( arg->r_opt == ARGPARSE_UNKNOWN_META ) + s = _("unknown meta command"); + else if ( arg->r_opt == ARGPARSE_UNEXPECTED_META ) + s = _("unexpected meta command"); else s = _("invalid option"); if (s) @@ -422,6 +430,12 @@ initialize (gpgrt_argparse_t *arg, gpgrt_opt_t *opts, estream_t fp) _gpgrt_log_error ("%s\n", _("permission error")); else if ( arg->r_opt == ARGPARSE_NO_CONFFILE) ; /* Error has already been printed. */ + else if ( arg->r_opt == ARGPARSE_INVALID_META ) + _gpgrt_log_error ("%s\n", _("invalid meta command")); + else if ( arg->r_opt == ARGPARSE_UNKNOWN_META ) + _gpgrt_log_error ("%s\n", _("unknown meta command")); + else if ( arg->r_opt == ARGPARSE_UNEXPECTED_META ) + _gpgrt_log_error ("%s\n",_("unexpected meta command")); else _gpgrt_log_error (_("invalid option \"%.50s\"\n"), s); } @@ -593,6 +607,10 @@ _gpgrt_argparse (estream_t fp, gpgrt_argparse_t *arg, gpgrt_opt_t *opts_orig) Acopyarg, /* Copy the argument. */ Akeyword_eol, /* Got keyword at end of line. */ Akeyword_spc, /* Got keyword at space. */ + Acopymetacmd, /* Copy a meta command. */ + Askipmetacmd, /* Skip spaces after metacmd. */ + Askipmetacmd2,/* Skip comment after metacmd. */ + Ametacmd, /* Process the metacmd. */ Askipandleave /* Skip the rest of the line and then leave. */ } state; gpgrt_opt_t **opts; @@ -718,6 +736,24 @@ _gpgrt_argparse (estream_t fp, gpgrt_argparse_t *arg, gpgrt_opt_t *opts_orig) goto leave; } } /* (end state Akeyword_eol/Akeyword_spc) */ + else if (state == Ametacmd) + { + gpgrt_assert (*keyword == '['); + trim_spaces (keyword+1); + if (!keyword[1]) + { + arg->r_opt = ARGPARSE_INVALID_META; /* Empty. */ + goto leave; + } + if (!arg->internal->insysconfig) + { + arg->r_opt = ARGPARSE_UNEXPECTED_META; + goto leave; + } + /* _gpgrt_log_debug ("Got meta command '%s'\n", keyword+1); */ + state = Ainit; + i = 0; + } /* Get the next character from the line. */ if (unread_buf_count) @@ -737,6 +773,16 @@ _gpgrt_argparse (estream_t fp, gpgrt_argparse_t *arg, gpgrt_opt_t *opts_orig) state = Akeyword_eol; goto nextstate; } + else if (state == Acopymetacmd) + { + arg->r_opt = ARGPARSE_INVALID_META; /* "]" missing */ + goto leave; + } + else if (state == Askipmetacmd || state == Askipmetacmd2) + { + state = Ametacmd; + goto nextstate; + } else if (state == Awaitarg) { /* No argument found at the end of the line. */ @@ -833,14 +879,30 @@ _gpgrt_argparse (estream_t fp, gpgrt_argparse_t *arg, gpgrt_opt_t *opts_orig) ; /* Skip leading white space. */ else if (state == Ainit && c == '#' ) state = Acomment; /* Start of a comment. */ - else if (state == Acomment) + else if (state == Acomment || state == Askipmetacmd2) ; /* Skip comments. */ + else if (state == Askipmetacmd) + { + if (c == '#') + state = Askipmetacmd2; + else if (!(isascii (c) && isspace(c))) + { + arg->r_opt = ARGPARSE_INVALID_META; + state = Askipandleave; + } + } else if (state == Acopykeyword && isascii (c) && isspace(c)) { keyword[i] = 0; state = Akeyword_spc; goto nextstate; } + else if (state == Acopymetacmd && c == ']') + { + keyword[i] = 0; + state = Askipmetacmd; + goto nextstate; + } else if (state == Awaitarg) { /* Skip leading spaces of the argument. */ @@ -902,10 +964,14 @@ _gpgrt_argparse (estream_t fp, gpgrt_argparse_t *arg, gpgrt_opt_t *opts_orig) arg->r_opt = ARGPARSE_KEYWORD_TOO_LONG; state = Askipandleave; /* Skip rest of line and leave. */ } + else if (!i) + { + state = c == '[' ? Acopymetacmd : Acopykeyword; + keyword[i++] = c; + } else { keyword[i++] = c; - state = Acopykeyword; } } @@ -1173,6 +1239,7 @@ _gpgrt_argparser (gpgrt_argparse_t *arg, gpgrt_opt_t *opts, _gpgrt_log_info (_("reading options from '%s'\n"), arg->internal->confname); arg->internal->state = STATE_read_sys; + arg->internal->insysconfig = 1; arg->r.ret_str = xtrystrdup (arg->internal->confname); if (!arg->r.ret_str) arg->r_opt = ARGPARSE_OUT_OF_CORE; @@ -1237,6 +1304,7 @@ _gpgrt_argparser (gpgrt_argparse_t *arg, gpgrt_opt_t *opts, arg->internal->idx = 0; arg->internal->stopped = 0; arg->internal->inarg = 0; + arg->internal->insysconfig = 0; _gpgrt_fclose (arg->internal->conffp); arg->internal->conffp = _gpgrt_fopen (arg->internal->confname, "r"); if (!arg->internal->conffp) @@ -1280,6 +1348,7 @@ _gpgrt_argparser (gpgrt_argparse_t *arg, gpgrt_opt_t *opts, arg->internal->idx = 0; arg->internal->stopped = 0; arg->internal->inarg = 0; + arg->internal->insysconfig = 0; if (!arg->argc || !arg->argv || !*arg->argv) { /* No or empty argument vector - don't bother to parse things. */ diff --git a/src/gpg-error.h.in b/src/gpg-error.h.in index e353700..165881b 100644 --- a/src/gpg-error.h.in +++ b/src/gpg-error.h.in @@ -1206,6 +1206,9 @@ typedef struct #define ARGPARSE_PERMISSION_ERROR (-13) #define ARGPARSE_NO_CONFFILE (-14) #define ARGPARSE_CONFFILE (-15) +#define ARGPARSE_INVALID_META (-16) +#define ARGPARSE_UNKNOWN_META (-17) +#define ARGPARSE_UNEXPECTED_META (-18) /* Flags for the option descriptor (gpgrt_opt_t)->flags. Note that * a TYPE constant may be or-ed with the OPT constants. */ diff --git a/tests/etc/t-argparse.conf b/tests/etc/t-argparse.conf index 87bff72..0852e71 100644 --- a/tests/etc/t-argparse.conf +++ b/tests/etc/t-argparse.conf @@ -3,33 +3,51 @@ # Options applied to all user's config files #verbose -#[user :staff] -# These option are applied to all users the group staff up until the -# next [user statement] +[group :staff] +# These option are applied to all users of the group staff up until +# the next [group] or [user] statement. -#[+force] +[+force] +# All following option are forced and thus ignored when set in user +# config files. Valid until the next [user] statement. Take care +# that there are often "no-", "disable-", or "enable-" versions of +# options; these should be explictly marked as ignored so that they +# can't be used to override the force attribute. -#[ignore] +[ignore] # The compliance is set immutable for these users verbose +# The next shall raise an error due to the garpage at the end. +#<off>[+ignore] fooo + + +#[+ignore-all] +# All options are ignored. + + +[-ignore] # Comment at line end +# Options wich shall not be ignored. */ #no-verbose -# (parsing does not stop for a group) -#[user wk] -# Options for user wk +[user john ] +# Options for user john -# Change the immutable flag back to mutable. -#[] compliance gnupg +# Change the immutable attribute back to mutable. +[-force] +#compliance gnupg -# Default key for wk +# Default key for user john my-option 42 # Parsing stops for user WK here. -#[user *] +[group * ] +# Options for all group which have no specific group sections above + +[user *] # Options for all users which have no specific user sections above # The default algorithm for new keys is set to this. diff --git a/tests/t-argparse.c b/tests/t-argparse.c index b2b6e51..4719819 100644 --- a/tests/t-argparse.c +++ b/tests/t-argparse.c @@ -88,6 +88,7 @@ main (int argc, char **argv) ) }; int i; const char *srcdir; + int any_warn = 0; gpgrt_set_strusage (my_strusage); srcdir = getenv ("srcdir"); @@ -120,7 +121,7 @@ main (int argc, char **argv) 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_ERROR; break; + default : pargs.err = ARGPARSE_PRINT_WARNING; any_warn = 1; break; } } for (i=0; i < argc; i++ ) @@ -148,5 +149,5 @@ main (int argc, char **argv) (void)fail; (void)die; - return 0; + return !!any_warn; } diff --git a/tests/t-argparse.conf b/tests/t-argparse.conf index 0bbdd3e..e2c96e2 100644 --- a/tests/t-argparse.conf +++ b/tests/t-argparse.conf @@ -3,6 +3,9 @@ # Options applied to all user's config files echo +# The next should be flagged as unexpected meta command. +#<off>[ignore] + my-option 4711 verbose |