diff options
Diffstat (limited to 'src/argparse.c')
-rw-r--r-- | src/argparse.c | 155 |
1 files changed, 113 insertions, 42 deletions
diff --git a/src/argparse.c b/src/argparse.c index 2399c43..bd44aef 100644 --- a/src/argparse.c +++ b/src/argparse.c @@ -117,14 +117,17 @@ struct _gpgrt_argparse_internal_s unsigned int in_sysconf:1; /* Processing global config file. */ unsigned int mark_forced:1; /* Mark options as forced. */ unsigned int mark_ignore:1; /* Mark options as to be ignored. */ - unsigned int explicit_ignore:1; /* Option has explicitly been set - * to ignore or unignore. */ + unsigned int explicit_ignore:1; /* Option has explicitly been set */ + /* to be ignored or un-ignoref. */ + unsigned int command_seen:1; /* A command option has been seen. */ unsigned int ignore_all_seen:1; /* [ignore-all] has been seen. */ unsigned int user_seen:1; /* A [user] has been seen. */ unsigned int user_wildcard:1; /* A [user *] has been seen. */ unsigned int user_any_active:1; /* Any user section was active. */ unsigned int user_active:1; /* User section active. */ unsigned int expand:1; /* Expand vars in option values. */ + unsigned int explicit_cmd_mode:1;/* Command mode set via config. */ + unsigned int cmd_mode:1; /* Command mode according to config. */ unsigned int explicit_confopt:1; /* A conffile option has been given. */ char *explicit_conffile; /* Malloced name of an explicit * conffile. */ @@ -336,6 +339,9 @@ initialize (gpgrt_argparse_t *arg, gpgrt_opt_t *opts, estream_t fp) arg->internal->inarg = 0; arg->internal->stopped = 0; arg->internal->in_sysconf = 0; + arg->internal->command_seen = 0; + arg->internal->explicit_cmd_mode = 0; + arg->internal->cmd_mode = 0; arg->internal->user_seen = 0; arg->internal->user_wildcard = 0; arg->internal->user_any_active = 0; @@ -425,7 +431,7 @@ initialize (gpgrt_argparse_t *arg, gpgrt_opt_t *opts, estream_t fp) if (!seen_help) { arg->internal->opts[i].short_opt = ARGPARSE_SHORTOPT_HELP; - arg->internal->opts[i].flags = ARGPARSE_TYPE_NONE; + arg->internal->opts[i].flags = ARGPARSE_OPT_COMMAND; arg->internal->opts[i].long_opt = "help"; arg->internal->opts[i].description = "@"; arg->internal->opts[i].ordinal = i; @@ -434,7 +440,7 @@ initialize (gpgrt_argparse_t *arg, gpgrt_opt_t *opts, estream_t fp) if (!seen_version) { arg->internal->opts[i].short_opt = ARGPARSE_SHORTOPT_VERSION; - arg->internal->opts[i].flags = ARGPARSE_TYPE_NONE; + arg->internal->opts[i].flags = ARGPARSE_OPT_COMMAND; arg->internal->opts[i].long_opt = "version"; arg->internal->opts[i].description = "@"; arg->internal->opts[i].ordinal = i; @@ -444,7 +450,7 @@ initialize (gpgrt_argparse_t *arg, gpgrt_opt_t *opts, estream_t fp) if (!seen_warranty) { arg->internal->opts[i].short_opt = ARGPARSE_SHORTOPT_WARRANTY; - arg->internal->opts[i].flags = ARGPARSE_TYPE_NONE; + arg->internal->opts[i].flags = ARGPARSE_OPT_COMMAND; arg->internal->opts[i].long_opt = "warranty"; arg->internal->opts[i].description = "@"; arg->internal->opts[i].ordinal = i; @@ -454,7 +460,7 @@ initialize (gpgrt_argparse_t *arg, gpgrt_opt_t *opts, estream_t fp) if (!seen_dump_option_table) { arg->internal->opts[i].short_opt = ARGPARSE_SHORTOPT_DUMP_OPTTBL; - arg->internal->opts[i].flags = ARGPARSE_TYPE_NONE; + arg->internal->opts[i].flags = ARGPARSE_OPT_COMMAND; arg->internal->opts[i].long_opt = "dump-option-table"; arg->internal->opts[i].description = "@"; arg->internal->opts[i].ordinal = i; @@ -464,7 +470,7 @@ initialize (gpgrt_argparse_t *arg, gpgrt_opt_t *opts, estream_t fp) if (!seen_dump_options) { arg->internal->opts[i].short_opt = ARGPARSE_SHORTOPT_DUMP_OPTIONS; - arg->internal->opts[i].flags = ARGPARSE_TYPE_NONE; + arg->internal->opts[i].flags = ARGPARSE_OPT_COMMAND; arg->internal->opts[i].long_opt = "dump-options"; arg->internal->opts[i].description = "@"; arg->internal->opts[i].ordinal = i; @@ -1369,6 +1375,21 @@ handle_meta_verbose (gpgrt_argparse_t *arg, unsigned int alternate, char *args) return 0; } +/* Implementation of the "command-mode" command. ARG is the context. If + * ALTERNATE is true the command mode is disabled. ARGS is not used. */ +static int +handle_meta_command (gpgrt_argparse_t *arg, unsigned int alternate, char *args) +{ + (void)args; + + arg->internal->explicit_cmd_mode = 1; + if (alternate) + arg->internal->cmd_mode = 0; + else + arg->internal->cmd_mode = 1; + return 0; +} + /* Implementation of the "expand" command. ARG is the context. If * ALTERNATE is true expand is reset. ARGS is not used. */ @@ -1422,6 +1443,9 @@ handle_metacmd (gpgrt_argparse_t *arg, char *keyword) { "verbose", 0, 0, 1, 1, handle_meta_verbose }, { "+verbose", 0, 0, 1, 1, handle_meta_verbose }, { "-verbose", 1, 0, 1, 1, handle_meta_verbose }, + { "command-mode", 0,0, 1, 0, handle_meta_command }, + { "+command-mode",0,0, 1, 0, handle_meta_command }, + { "-command-mode",1,0, 1, 0, handle_meta_command }, { "echo", 0, 1, 1, 1, handle_meta_echo }, { "-echo", 1, 1, 1, 1, handle_meta_echo }, { "info", 0, 1, 1, 0, handle_meta_echo }, @@ -2479,9 +2503,10 @@ _gpgrt_argparser (gpgrt_argparse_t *arg, gpgrt_opt_t *opts, /* Given the list of options in ARG and a keyword, return the index of * the long option matching KEYWORD. On error -1 is returned for not - * found or -2 for ambigious keyword. */ + * found or -2 for ambiguous keyword. If ONLY_COMMANDS is set only + * options marked as commands are considere. */ static int -find_long_option (gpgrt_argparse_t *arg, const char *keyword) +find_long_option (gpgrt_argparse_t *arg, const char *keyword, int only_commands) { int i; size_t n; @@ -2495,9 +2520,24 @@ find_long_option (gpgrt_argparse_t *arg, const char *keyword) * done. */ if (!*keyword) return -1; - for (i=0; i < nopts; i++ ) - if (opts[i].long_opt && !strcmp (opts[i].long_opt, keyword)) - return i; + if (only_commands) + { + /* Note that we consider only options which have just the + * command flag set and ignore all option which falsely have + * other bits set. */ + for (i=0; i < nopts; i++ ) + if (opts[i].flags == ARGPARSE_OPT_COMMAND + && opts[i].long_opt && !strcmp (opts[i].long_opt, keyword)) + return i; + return -1; /* Not found (no abbreviations in this mode). */ + } + else + { + for (i=0; i < nopts; i++ ) + if (opts[i].long_opt && !strcmp (opts[i].long_opt, keyword)) + return i; + } + #if 0 { ALIAS_DEF a; @@ -2536,6 +2576,48 @@ find_long_option (gpgrt_argparse_t *arg, const char *keyword) } +/* Handle special commands like "help" and "version". All of these + * commands call exit and thus this function does not return if such a + * command was found at IDX. */ +static void +handle_special_commands (gpgrt_argparse_t *arg, int idx) +{ + int i = idx; + opttable_t *opts = arg->internal->opts; + unsigned int nopts = arg->internal->nopts; + + if (i >= 0 && opts[i].short_opt == ARGPARSE_SHORTOPT_HELP) + { + show_help (opts, nopts, arg->flags); + my_exit (arg, 0); + } + else if (i >= 0 && opts[i].short_opt == ARGPARSE_SHORTOPT_VERSION) + { + if (!(arg->flags & ARGPARSE_FLAG_NOVERSION)) + { + show_version (); + my_exit (arg, 0); + } + } + else if (i >= 0 && opts[i].short_opt == ARGPARSE_SHORTOPT_WARRANTY) + { + writestrings (0, _gpgrt_strusage (16), "\n", NULL); + my_exit (arg, 0); + } + else if (i >= 0 && opts[i].short_opt == ARGPARSE_SHORTOPT_DUMP_OPTTBL) + dump_option_table (arg); + else if (i >= 0 && opts[i].short_opt == ARGPARSE_SHORTOPT_DUMP_OPTIONS) + { + for (i=0; i < nopts; i++ ) + { + if (opts[i].long_opt && !(opts[i].flags & ARGPARSE_OPT_IGNORE)) + writestrings (0, "--", opts[i].long_opt, "\n", NULL); + } + my_exit (arg, 0); + } +} + + /* The option parser for command line options. */ static int arg_parse (gpgrt_argparse_t *arg, gpgrt_opt_t *opts_orig, int no_init) @@ -2606,39 +2688,11 @@ arg_parse (gpgrt_argparse_t *arg, gpgrt_opt_t *opts_orig, int no_init) argpos = strchr( s+2, '=' ); if ( argpos ) *argpos = 0; - i = find_long_option (arg, s+2); + i = find_long_option (arg, s+2, 0); if ( argpos ) *argpos = '='; - if (i > 0 && opts[i].short_opt == ARGPARSE_SHORTOPT_HELP) - { - show_help (opts, nopts, arg->flags); - my_exit (arg, 0); - } - else if (i > 0 && opts[i].short_opt == ARGPARSE_SHORTOPT_VERSION) - { - if (!(arg->flags & ARGPARSE_FLAG_NOVERSION)) - { - show_version (); - my_exit (arg, 0); - } - } - else if (i > 0 && opts[i].short_opt == ARGPARSE_SHORTOPT_WARRANTY) - { - writestrings (0, _gpgrt_strusage (16), "\n", NULL); - my_exit (arg, 0); - } - else if (i > 0 && opts[i].short_opt == ARGPARSE_SHORTOPT_DUMP_OPTTBL) - dump_option_table (arg); - else if (i > 0 && opts[i].short_opt == ARGPARSE_SHORTOPT_DUMP_OPTIONS) - { - for (i=0; i < nopts; i++ ) - { - if (opts[i].long_opt && !(opts[i].flags & ARGPARSE_OPT_IGNORE)) - writestrings (0, "--", opts[i].long_opt, "\n", NULL); - } - my_exit (arg, 0); - } + handle_special_commands (arg, i); if ( i == -2 ) arg->r_opt = ARGPARSE_AMBIGUOUS_OPTION; @@ -2650,6 +2704,9 @@ arg_parse (gpgrt_argparse_t *arg, gpgrt_opt_t *opts_orig, int no_init) else arg->r_opt = opts[i].short_opt; + if (i >= 0 && (opts[i].flags & ARGPARSE_OPT_COMMAND)) + arg->internal->command_seen = 1; + if ( i < 0 ) ; else if ( (opts[i].flags & ARGPARSE_TYPE_MASK) ) @@ -2793,6 +2850,20 @@ arg_parse (gpgrt_argparse_t *arg, gpgrt_opt_t *opts_orig, int no_init) argc--; argv++; idx++; } } + else if (!arg->internal->command_seen + && ((!arg->internal->explicit_cmd_mode + && arg->flags & ARGPARSE_FLAG_COMMAND) + || (arg->internal->explicit_cmd_mode + && arg->internal->cmd_mode)) + && (i = find_long_option (arg, s, 1)) >= 0) + { + handle_special_commands (arg, i); + arg->internal->opt_flags = opts[i].flags; + arg->internal->command_seen = 1; + arg->r_opt = opts[i].short_opt; + arg->r_type = ARGPARSE_TYPE_NONE; + argc--; argv++; idx++; /* Set to next one. */ + } else if ( arg->flags & ARGPARSE_FLAG_MIXED ) { arg->r_opt = ARGPARSE_IS_ARG; |