OSDN Git Service

- use complementally '!' to '?' - 'ask' is best 'free' char for this.
author"Vladimir N. Oleynik" <dzo@simtreas.ru>
Tue, 11 Oct 2005 14:38:01 +0000 (14:38 -0000)
committer"Vladimir N. Oleynik" <dzo@simtreas.ru>
Tue, 11 Oct 2005 14:38:01 +0000 (14:38 -0000)
- 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
archival/dpkg_deb.c
archival/tar.c
coreutils/date.c
coreutils/id.c
coreutils/install.c
debianutils/start_stop_daemon.c
libbb/getopt_ulflags.c
util-linux/hwclock.c

index 411a25e..70deb5c 100644 (file)
@@ -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)) {
index 1ceaa60..f38fb61 100644 (file)
@@ -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) {
index f6750ae..d984267 100644 (file)
@@ -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
index 9583a00..5ee2c74 100644 (file)
@@ -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
index 28050dd..14497b4 100644 (file)
@@ -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"
 #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);
        }
 
index 9fcb754..9e5eb60 100644 (file)
@@ -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 */
 
index f9310af..b6c4635 100644 (file)
@@ -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);
index 2e2ee0b..5f35c58 100644 (file)
@@ -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;
 }
index 45959e7..3021442 100644 (file)
@@ -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 */