From 064f04e7e2b1316f7c3de1ac7dd1fc4d4e108dd5 Mon Sep 17 00:00:00 2001 From: "\"Vladimir N. Oleynik\"" Date: Tue, 11 Oct 2005 14:38:01 +0000 Subject: - use complementally '!' to '?' - 'ask' is best 'free' char for this. - more long opt compatibility, can set flag for long opt struct now - more logic: check opt-depend requires and global requires, special for 'id' and 'start-stop-daemon' applets. --- archival/ar.c | 2 +- archival/dpkg_deb.c | 2 +- archival/tar.c | 2 +- coreutils/date.c | 2 +- coreutils/id.c | 21 ++++---- coreutils/install.c | 2 +- debianutils/start_stop_daemon.c | 28 +++++------ libbb/getopt_ulflags.c | 108 ++++++++++++++++++++++++++-------------- util-linux/hwclock.c | 2 +- 9 files changed, 100 insertions(+), 69 deletions(-) diff --git a/archival/ar.c b/archival/ar.c index 411a25e0a..70deb5cbb 100644 --- a/archival/ar.c +++ b/archival/ar.c @@ -66,7 +66,7 @@ extern int ar_main(int argc, char **argv) archive_handle = init_handle(); - bb_opt_complementally = "!p~tx:t~px:x~pt"; + bb_opt_complementally = "?p~tx:t~px:x~pt"; opt = bb_getopt_ulflags(argc, argv, "ptxovcr"); if ((opt == 0) || (optind == argc)) { diff --git a/archival/dpkg_deb.c b/archival/dpkg_deb.c index 1ceaa60e0..f38fb6195 100644 --- a/archival/dpkg_deb.c +++ b/archival/dpkg_deb.c @@ -55,7 +55,7 @@ extern int dpkg_deb_main(int argc, char **argv) control_tar_llist = llist_add_to(control_tar_llist, "control.tar.bz2"); #endif - bb_opt_complementally = "!c~efXx:e~cfXx:f~ceXx:X~cefx:x~cefX"; + bb_opt_complementally = "?c~efXx:e~cfXx:f~ceXx:X~cefx:x~cefX"; opt = bb_getopt_ulflags(argc, argv, "cefXx"); if (opt & DPKG_DEB_OPT_CONTENTS) { diff --git a/archival/tar.c b/archival/tar.c index f6750ae33..d98426748 100644 --- a/archival/tar.c +++ b/archival/tar.c @@ -702,7 +702,7 @@ int tar_main(int argc, char **argv) tar_handle = init_handle(); tar_handle->flags = ARCHIVE_CREATE_LEADING_DIRS | ARCHIVE_PRESERVE_DATE | ARCHIVE_EXTRACT_UNCONDITIONAL; - bb_opt_complementally = "!c~tx:t~cx:x~ct:X*:T*"; + bb_opt_complementally = "?c~tx:t~cx:x~ct:X*:T*"; #ifdef CONFIG_FEATURE_TAR_LONG_OPTIONS bb_applet_long_options = tar_long_options; #endif diff --git a/coreutils/date.c b/coreutils/date.c index 9583a0036..5ee2c74e8 100644 --- a/coreutils/date.c +++ b/coreutils/date.c @@ -151,7 +151,7 @@ int date_main(int argc, char **argv) #else # define GETOPT_ISOFMT #endif - bb_opt_complementally = "!d~ds:s~ds"; + bb_opt_complementally = "?d~ds:s~ds"; opt = bb_getopt_ulflags(argc, argv, "Rs:ud:r:" GETOPT_ISOFMT, &date_str, &date_str, &filename #ifdef CONFIG_FEATURE_DATE_ISOFMT diff --git a/coreutils/id.c b/coreutils/id.c index 28050ddf2..14497b416 100644 --- a/coreutils/id.c +++ b/coreutils/id.c @@ -22,7 +22,7 @@ /* BB_AUDIT SUSv3 _NOT_ compliant -- option -G is not currently supported. */ /* Hacked by Tito Ragusa (C) 2004 to handle usernames of whatever length and to - * be more similar to GNU id. + * be more similar to GNU id. */ #include "busybox.h" @@ -41,10 +41,10 @@ #define JUST_GROUP 8 static short printf_full(unsigned int id, const char *arg, const char prefix) -{ +{ const char *fmt = "%cid=%u"; short status=EXIT_FAILURE; - + if(arg) { fmt = "%cid=%u(%s)"; status=EXIT_SUCCESS; @@ -61,15 +61,14 @@ extern int id_main(int argc, char **argv) unsigned long flags; short status; - bb_opt_complementally = "!u~g:g~u"; + /* Don't allow -n -r -nr -ug -rug -nug -rnug */ + bb_opt_complementally = "?u~g:g~u:r?ug:n?ug"; flags = bb_getopt_ulflags(argc, argv, "rnug"); - /* Don't allow -n -r -nr */ - if ((flags <= 3 && flags > 0) /* Don't allow more than one username */ - || (argc > optind + 1)) + if (argc > (optind + 1)) bb_show_usage(); - + /* This values could be overwritten later */ uid = geteuid(); gid = getegid(); @@ -77,13 +76,13 @@ extern int id_main(int argc, char **argv) uid = getuid(); gid = getgid(); } - + if(argv[optind]) { p=getpwnam(argv[optind]); /* bb_xgetpwnam is needed because it exits on failure */ uid = bb_xgetpwnam(argv[optind]); gid = p->pw_gid; - /* in this case PRINT_REAL is the same */ + /* in this case PRINT_REAL is the same */ } if(flags & (JUST_GROUP | JUST_USER)) { @@ -94,7 +93,7 @@ extern int id_main(int argc, char **argv) } else { bb_printf("%u\n",(flags & JUST_USER) ? uid : gid); } - /* exit */ + /* exit */ bb_fflush_stdout_and_exit(EXIT_SUCCESS); } diff --git a/coreutils/install.c b/coreutils/install.c index 9fcb75405..9e5eb6037 100644 --- a/coreutils/install.c +++ b/coreutils/install.c @@ -61,7 +61,7 @@ extern int install_main(int argc, char **argv) int ret = EXIT_SUCCESS, flags, i, isdir; bb_applet_long_options = install_long_options; - bb_opt_complementally = "!s~d:d~s"; + bb_opt_complementally = "?s~d:d~s"; /* -c exists for backwards compatability, its needed */ flags = bb_getopt_ulflags(argc, argv, "cdpsg:m:o:", &gid_str, &mode_str, &uid_str); /* 'a' must be 2nd */ diff --git a/debianutils/start_stop_daemon.c b/debianutils/start_stop_daemon.c index f9310af8d..b6c463556 100644 --- a/debianutils/start_stop_daemon.c +++ b/debianutils/start_stop_daemon.c @@ -204,18 +204,18 @@ do_stop(void) static const struct option ssd_long_options[] = { - { "stop", 0, NULL, 'K' }, - { "start", 0, NULL, 'S' }, + { "stop", 0, NULL, 'K' }, + { "start", 0, NULL, 'S' }, { "background", 0, NULL, 'b' }, - { "quiet", 0, NULL, 'q' }, + { "quiet", 0, NULL, 'q' }, { "make-pidfile", 0, NULL, 'm' }, { "startas", 1, NULL, 'a' }, - { "name", 1, NULL, 'n' }, - { "signal", 1, NULL, 's' }, - { "user", 1, NULL, 'u' }, - { "exec", 1, NULL, 'x' }, + { "name", 1, NULL, 'n' }, + { "signal", 1, NULL, 's' }, + { "user", 1, NULL, 'u' }, + { "exec", 1, NULL, 'x' }, { "pidfile", 1, NULL, 'p' }, - { 0, 0, 0, 0 } + { 0, 0, 0, 0 } }; #define SSD_CTX_STOP 1 @@ -233,17 +233,13 @@ start_stop_daemon_main(int argc, char **argv) bb_applet_long_options = ssd_long_options; - bb_opt_complementally = "!K~S:S~K"; + /* Check required one context option was given */ + bb_opt_complementally = "?:K?K:S?S:K~S:S~K"; opt = bb_getopt_ulflags(argc, argv, "KSbqma:n:s:u:x:p:", &startas, &cmdname, &signame, &userspec, &execname, &pidfile); - /* Check required one context option was given */ - if ((opt & (SSD_CTX_STOP | SSD_CTX_START)) == 0) { - bb_show_usage(); - } - - if (opt & SSD_OPT_QUIET) - quiet = 1; + + quiet = opt & SSD_OPT_QUIET; if (signame) { signal_nr = bb_xgetlarg(signame, 10, 0, NSIG); diff --git a/libbb/getopt_ulflags.c b/libbb/getopt_ulflags.c index 2e2ee0b6b..5f35c583c 100644 --- a/libbb/getopt_ulflags.c +++ b/libbb/getopt_ulflags.c @@ -197,8 +197,9 @@ Special characters: if (flags & BB_GETOPT_ERROR) bb_show_usage(); - "!" If previous point set BB_GETOPT_ERROR, don`t return and call - previous example internally + "?" A "ask" as the first char in a bb_opt_complementally group give: + if previous point set BB_GETOPT_ERROR, don`t return and + call previous example internally "*" A star after a char in bb_opt_complementally means that the option can occur multiple times: @@ -218,16 +219,38 @@ Special characters: $ grep -e user -e root /etc/passwd root:x:0:0:root:/root:/bin/bash user:x:500:500::/home/user:/bin/bash + + "?" A "ask" between main and group options causes the second of the two + to be depending required if first is given on the command line. + For example from "id" applet: + + // Don't allow -n -r -rn -ug -rug -nug -rnug + bb_opt_complementally = "?u~g:g~u:r?ug:n?ug"; + flags = bb_getopt_ulflags(argc, argv, "rnug"); + + This example allowed only: + $ id; id -u; id -g; id -ru; id -nu; id -rg; id -ng; id -rnu; id -rng + + "?" A "ask" between equivalent options in bb_opt_complementally means + requires this option always, checked after switch off from + complementally logic + For example from "start-stop-daemon" applet: + + // Don't allow -KS -SK, but -S or -K required + bb_opt_complementally = "?:K?K:S?S:K~S:S~K"; + flags = bb_getopt_ulflags(argc, argv, "KS...); + */ const char *bb_opt_complementally; typedef struct { - unsigned char opt; - char list_flg; + int opt; + int list_flg; unsigned long switch_on; unsigned long switch_off; unsigned long incongruously; + unsigned long requires; void **optarg; /* char **optarg or llist_t **optarg */ int *counter; } t_complementally; @@ -245,17 +268,20 @@ unsigned long bb_getopt_ulflags (int argc, char **argv, const char *applet_opts, ...) { unsigned long flags = 0; + unsigned long requires = 0; t_complementally complementally[sizeof(flags) * 8 + 1]; int c; const unsigned char *s; t_complementally *on_off; va_list p; const struct option *l_o; - char flg_show_usage_if_error = 0; - char flg_argv_is_opts = 0; unsigned long trigger; char **pargv = NULL; +#define SHOW_USAGE_IF_ERROR 1 +#define ARGV_IS_OPTS 2 + int spec_flgs = 0; + va_start (p, applet_opts); /* skip GNU extension */ @@ -265,16 +291,13 @@ bb_getopt_ulflags (int argc, char **argv, const char *applet_opts, ...) c = 0; on_off = complementally; + memset(on_off, 0, sizeof(complementally)); + for (; *s; s++) { if(c >= (int)(sizeof(flags)*8)) break; on_off->opt = *s; on_off->switch_on = (1 << c); - on_off->list_flg = 0; - on_off->switch_off = 0; - on_off->incongruously = 0; - on_off->optarg = NULL; - on_off->counter = NULL; if (s[1] == ':') { on_off->optarg = va_arg (p, void **); do @@ -284,9 +307,10 @@ bb_getopt_ulflags (int argc, char **argv, const char *applet_opts, ...) on_off++; c++; } - on_off->opt = 0; for(l_o = bb_applet_long_options; l_o->name; l_o++) { + if(l_o->flag) + continue; for(on_off = complementally; on_off->opt != 0; on_off++) if(on_off->opt == l_o->val) break; @@ -295,16 +319,8 @@ bb_getopt_ulflags (int argc, char **argv, const char *applet_opts, ...) break; on_off->opt = l_o->val; on_off->switch_on = (1 << c); - on_off->list_flg = 0; - on_off->switch_off = 0; - on_off->incongruously = 0; - on_off->counter = NULL; if(l_o->has_arg != no_argument) on_off->optarg = va_arg (p, void **); - else - on_off->optarg = NULL; - on_off++; - on_off->opt = 0; c++; } } @@ -318,12 +334,12 @@ bb_getopt_ulflags (int argc, char **argv, const char *applet_opts, ...) } if (c) continue; - if(*s == '!') { - flg_show_usage_if_error = '!'; + if(*s == '?') { + spec_flgs |= SHOW_USAGE_IF_ERROR; continue; } if(*s == '-') { - flg_argv_is_opts = '-'; + spec_flgs |= ARGV_IS_OPTS; continue; } for (on_off = complementally; on_off->opt; on_off++) @@ -331,18 +347,32 @@ bb_getopt_ulflags (int argc, char **argv, const char *applet_opts, ...) break; pair = on_off; for(s++; *s && *s != ':'; s++) { - if (*s == '-' || *s == '~') { + if (*s == '-' || *s == '~' || *s == '?') { c = *s; } else if(*s == '*') { pair->list_flg++; } else { - unsigned long *pair_switch = &(pair->switch_on); - if(c) - pair_switch = c == '-' ? &(pair->switch_off) : &(pair->incongruously); + unsigned long *pair_switch; + + switch(c) { + case '-': + pair_switch = &(pair->switch_off); + break; + case '~': + pair_switch = &(pair->incongruously); + break; + case '?': + pair_switch = &(pair->requires); + break; + default: + pair_switch = &(pair->switch_on); + } for (on_off = complementally; on_off->opt; on_off++) if (on_off->opt == *s) { if(pair_switch == &(on_off->switch_on)) on_off->counter = va_arg (p, int *); + else if(pair_switch == &(on_off->requires)) + requires |= on_off->switch_on; else *pair_switch |= on_off->switch_on; break; @@ -353,15 +383,16 @@ bb_getopt_ulflags (int argc, char **argv, const char *applet_opts, ...) } while ((c = getopt_long (argc, argv, applet_opts, - bb_applet_long_options, NULL)) > 0) { + bb_applet_long_options, NULL)) >= 0) { loop_arg_is_opt: for (on_off = complementally; on_off->opt != c; on_off++) { - if(!on_off->opt) + /* c==0 if long opt have non NULL flag */ + if(on_off->opt == 0 && c != 0) bb_show_usage (); } if(flags & on_off->incongruously) { - if(flg_show_usage_if_error) + if((spec_flgs & SHOW_USAGE_IF_ERROR)) bb_show_usage (); flags |= BB_GETOPT_ERROR; } @@ -377,15 +408,13 @@ loop_arg_is_opt: } else if (on_off->optarg) { *(char **)(on_off->optarg) = optarg; } - if(flg_argv_is_opts == 'p') + if(pargv != NULL) break; } - if(flg_argv_is_opts) { + if((spec_flgs & ARGV_IS_OPTS)) { /* process argv is option, for example "ps" applet */ - if(flg_argv_is_opts == '-') { - flg_argv_is_opts = 'p'; + if(pargv == NULL) pargv = argv + optind; - } while(*pargv) { c = **pargv; if(c == '\0') { @@ -396,6 +425,13 @@ loop_arg_is_opt: } } } - + /* check depending requires for given options */ + for (on_off = complementally; on_off->opt; on_off++) { + if(on_off->requires && (flags & on_off->switch_on) && + (flags & on_off->requires) == 0) + bb_show_usage (); + } + if(requires && (flags & requires) == 0) + bb_show_usage (); return flags; } diff --git a/util-linux/hwclock.c b/util-linux/hwclock.c index 45959e7a1..3021442b7 100644 --- a/util-linux/hwclock.c +++ b/util-linux/hwclock.c @@ -209,7 +209,7 @@ static const struct option hwclock_long_options[] = { bb_applet_long_options = hwclock_long_options; #endif - bb_opt_complementally = "!r~ws:w~rs:s~wr:l~u:u~l"; + bb_opt_complementally = "?r~ws:w~rs:s~wr:l~u:u~l"; opt = bb_getopt_ulflags(argc, argv, "lursw"); /* If -u or -l wasn't given check if we are using utc */ -- cgit v1.2.3