Ignore:
Timestamp:
Feb 25, 2011, 9:26:54 PM (13 years ago)
Author:
Bruno Cornec
Message:
  • Update mindi-busybox to 1.18.3 to avoid problems with the tar command which is now failing on recent versions with busybox 1.7.3
File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/2.2.9/mindi-busybox/libbb/getopt32.c

    r1765 r2725  
    55 * Copyright (C) 2003-2005  Vladimir Oleynik  <dzo@simtreas.ru>
    66 *
    7  * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
     7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
    88 */
    99
     
    3131        "r" will add 1    (bit 0)
    3232        "n" will add 2    (bit 1)
    33         "u  will add 4    (bit 2)
     33        "u" will add 4    (bit 2)
    3434        "g" will add 8    (bit 3)
    3535
     
    7373        Here we want env to process just the '-i', not the '-d'.
    7474
     75 "!"    Report bad option, missing required options,
     76        inconsistent options with all-ones return value (instead of abort).
     77
    7578const char *applet_long_options
    7679
     
    113116
    114117 "ww"   Adjacent double options have a counter associated which indicates
    115         the number of occurences of the option.
     118        the number of occurrences of the option.
    116119        For example the ps applet needs:
    117120        if w is given once, GNU ps sets the width to 132,
    118121        if w is given more than once, it is "unlimited"
    119122
    120         int w_counter = 0;
     123        int w_counter = 0; // must be initialized!
    121124        opt_complementary = "ww";
    122125        getopt32(argv, "w", &w_counter);
     
    138141        f = getopt32(argv, "vb:c", &my_b, &verbose_level);
    139142        if (f & 2)       // -c after -b unsets -b flag
    140                 while (my_b) { dosomething_with(my_b->data); my_b = my_b->link; }
     143                while (my_b) dosomething_with(llist_pop(&my_b));
    141144        if (my_b)        // but llist is stored if -b is specified
    142145                free_llist(my_b);
     
    145148Special characters:
    146149
    147  "-"    A dash as the first char in a opt_complementary group forces
    148         all arguments to be treated as options, even if they have
    149         no leading dashes. Next char in this case can't be a digit (0-9),
    150         use ':' or end of line. For example:
    151 
    152         opt_complementary = "-:w-x:x-w";
    153         getopt32(argv, "wx");
    154 
    155         Allows any arguments to be given without a dash (./program w x)
     150 "-"    A group consisting of just a dash forces all arguments
     151        to be treated as options, even if they have no leading dashes.
     152        Next char in this case can't be a digit (0-9), use ':' or end of line.
     153        Example:
     154
     155        opt_complementary = "-:w-x:x-w"; // "-w-x:x-w" would also work,
     156        getopt32(argv, "wx");            // but is less readable
     157
     158        This makes it possible to use options without a dash (./program w x)
    156159        as well as with a dash (./program -x).
     160
     161        NB: getopt32() will leak a small amount of memory if you use
     162        this option! Do not use it if there is a possibility of recursive
     163        getopt32() calls.
    157164
    158165 "--"   A double dash at the beginning of opt_complementary means the
     
    162169        tar xvf foo.tar
    163170
     171        NB: getopt32() will leak a small amount of memory if you use
     172        this option! Do not use it if there is a possibility of recursive
     173        getopt32() calls.
     174
    164175 "-N"   A dash as the first char in a opt_complementary group followed
    165176        by a single digit (0-9) means that at least N non-option
     
    175186
    176187 "V-"   An option with dash before colon or end-of-line results in
    177         bb_show_usage being called if this option is encountered.
     188        bb_show_usage() being called if this option is encountered.
    178189        This is typically used to implement "print verbose usage message
    179190        and exit" option.
    180191
    181  "-"    A dash between two options causes the second of the two
     192 "a-b"  A dash between two options causes the second of the two
    182193        to be unset (and ignored) if it is given on the command line.
    183194
     
    205216                printf("Detected odd -x usage\n");
    206217
    207  "--"  A double dash between two options, or between an option and a group
     218 "a--b" A double dash between two options, or between an option and a group
    208219        of options, means that they are mutually exclusive.  Unlike
    209220        the "-" case above, an error will be forced if the options
     
    221232        at most once.
    222233
    223  "::"   A double colon after a char in opt_complementary means that the
     234 "a+"   A plus after a char in opt_complementary means that the parameter
     235        for this option is a nonnegative integer. It will be processed
     236        with xatoi_positive() - allowed range is 0..INT_MAX.
     237
     238        int param;  // "unsigned param;" will also work
     239        opt_complementary = "p+";
     240        getopt32(argv, "p:", &param);
     241
     242 "a::"  A double colon after a char in opt_complementary means that the
    224243        option can occur multiple times. Each occurrence will be saved as
    225244        a llist_t element instead of char*.
     
    241260        user:x:500:500::/home/user:/bin/bash
    242261
    243  "?"    An "?" between an option and a group of options means that
     262 "a?b"  A "?" between an option and a group of options means that
    244263        at least one of them is required to occur if the first option
    245264        occurs in preceding command line arguments.
     
    248267
    249268        // Don't allow -n -r -rn -ug -rug -nug -rnug
    250         opt_complementary = "r?ug:n?ug:?u--g:g--u";
     269        opt_complementary = "r?ug:n?ug:u--g:g--u";
    251270        flags = getopt32(argv, "rnug");
    252271
     
    260279
    261280        // Don't allow -KS -SK, but -S or -K is required
    262         opt_complementary = "K:S:?K--S:S--K";
     281        opt_complementary = "K:S:K--S:S--K";
    263282        flags = getopt32(argv, "KS...);
    264283
     
    269288        a '-2' option then unset '-3', '-X' and '-a'; if there is
    270289        a '-2' and after it a '-x' then error out.
     290        But it's far too obfuscated. Use ':' to separate groups.
    271291*/
    272292
    273293/* Code here assumes that 'unsigned' is at least 32 bits wide */
    274294
     295const char *const bb_argv_dash[] = { "-", NULL };
     296
    275297const char *opt_complementary;
    276298
     299enum {
     300    PARAM_STRING,
     301    PARAM_LIST,
     302    PARAM_INT,
     303};
     304
    277305typedef struct {
    278     int opt;
    279     int list_flg;
     306    unsigned char opt_char;
     307    smallint param_type;
    280308    unsigned switch_on;
    281309    unsigned switch_off;
    282310    unsigned incongruously;
    283311    unsigned requires;
    284     void **optarg;               /* char **optarg or llist_t **optarg */
     312    void **optarg;  /* char**, llist_t** or int *. */
    285313    int *counter;
    286314} t_complementary;
    287315
    288316/* You can set applet_long_options for parse called long options */
    289 #if ENABLE_GETOPT_LONG
     317#if ENABLE_LONG_OPTS || ENABLE_FEATURE_GETOPT_LONG
    290318static const struct option bb_null_long_options[1] = {
    291319    { 0, 0, 0, 0 }
     
    296324uint32_t option_mask32;
    297325
    298 uint32_t
     326uint32_t FAST_FUNC
    299327getopt32(char **argv, const char *applet_opts, ...)
    300328{
     
    302330    unsigned flags = 0;
    303331    unsigned requires = 0;
    304     t_complementary complementary[33];
     332    t_complementary complementary[33]; /* last stays zero-filled */
     333    char first_char;
    305334    int c;
    306335    const unsigned char *s;
    307336    t_complementary *on_off;
    308337    va_list p;
    309 #if ENABLE_GETOPT_LONG
     338#if ENABLE_LONG_OPTS || ENABLE_FEATURE_GETOPT_LONG
    310339    const struct option *l_o;
    311340    struct option *long_options = (struct option *) &bb_null_long_options;
    312341#endif
    313342    unsigned trigger;
    314     char **pargv = NULL;
     343    char **pargv;
    315344    int min_arg = 0;
    316345    int max_arg = -1;
     
    319348#define ALL_ARGV_IS_OPTS        2
    320349#define FIRST_ARGV_IS_OPT       4
    321 #define FREE_FIRST_ARGV_IS_OPT  8
     350
    322351    int spec_flgs = 0;
    323352
    324     argc = 0;
     353    /* skip 0: some applets cheat: they do not actually HAVE argv[0] */
     354    argc = 1;
    325355    while (argv[argc])
    326356        argc++;
     
    331361    on_off = complementary;
    332362    memset(on_off, 0, sizeof(complementary));
     363
     364    /* skip bbox extension */
     365    first_char = applet_opts[0];
     366    if (first_char == '!')
     367        applet_opts++;
    333368
    334369    /* skip GNU extension */
     
    337372        s++;
    338373    while (*s) {
    339         if (c >= 32) break;
    340         on_off->opt = *s;
     374        if (c >= 32)
     375            break;
     376        on_off->opt_char = *s;
    341377        on_off->switch_on = (1 << c);
    342378        if (*++s == ':') {
    343379            on_off->optarg = va_arg(p, void **);
    344             while (*++s == ':') /* skip */;
     380            while (*++s == ':')
     381                continue;
    345382        }
    346383        on_off++;
     
    348385    }
    349386
    350 #if ENABLE_GETOPT_LONG
     387#if ENABLE_LONG_OPTS || ENABLE_FEATURE_GETOPT_LONG
    351388    if (applet_long_options) {
    352389        const char *optstr;
     
    375412            if (l_o->flag)
    376413                continue;
    377             for (on_off = complementary; on_off->opt != 0; on_off++)
    378                 if (on_off->opt == l_o->val)
     414            for (on_off = complementary; on_off->opt_char; on_off++)
     415                if (on_off->opt_char == l_o->val)
    379416                    goto next_long;
    380             if (c >= 32) break;
    381             on_off->opt = l_o->val;
     417            if (c >= 32)
     418                break;
     419            on_off->opt_char = l_o->val;
    382420            on_off->switch_on = (1 << c);
    383421            if (l_o->has_arg != no_argument)
     
    386424 next_long: ;
    387425        }
     426        /* Make it unnecessary to clear applet_long_options
     427         * by hand after each call to getopt32
     428         */
     429        applet_long_options = NULL;
    388430    }
    389 #endif /* ENABLE_GETOPT_LONG */
     431#endif /* ENABLE_LONG_OPTS || ENABLE_FEATURE_GETOPT_LONG */
    390432    for (s = (const unsigned char *)opt_complementary; s && *s; s++) {
    391433        t_complementary *pair;
     
    422464            continue;
    423465        }
    424         for (on_off = complementary; on_off->opt; on_off++)
    425             if (on_off->opt == *s)
     466        for (on_off = complementary; on_off->opt_char; on_off++)
     467            if (on_off->opt_char == *s)
    426468                break;
    427469        if (c == ':' && s[2] == ':') {
    428             on_off->list_flg++;
     470            on_off->param_type = PARAM_LIST;
     471            continue;
     472        }
     473        if (c == '+' && (s[2] == ':' || s[2] == '\0')) {
     474            on_off->param_type = PARAM_INT;
    429475            continue;
    430476        }
     
    444490        }
    445491        pair = on_off;
    446         pair_switch = &(pair->switch_on);
     492        pair_switch = &pair->switch_on;
    447493        for (s++; *s && *s != ':'; s++) {
    448494            if (*s == '?') {
    449                 pair_switch = &(pair->requires);
     495                pair_switch = &pair->requires;
    450496            } else if (*s == '-') {
    451                 if (pair_switch == &(pair->switch_off))
    452                     pair_switch = &(pair->incongruously);
     497                if (pair_switch == &pair->switch_off)
     498                    pair_switch = &pair->incongruously;
    453499                else
    454                     pair_switch = &(pair->switch_off);
     500                    pair_switch = &pair->switch_off;
    455501            } else {
    456                 for (on_off = complementary; on_off->opt; on_off++)
    457                     if (on_off->opt == *s) {
     502                for (on_off = complementary; on_off->opt_char; on_off++)
     503                    if (on_off->opt_char == *s) {
    458504                        *pair_switch |= on_off->switch_on;
    459505                        break;
     
    463509        s--;
    464510    }
     511    opt_complementary = NULL;
    465512    va_end(p);
    466513
    467     if (spec_flgs & FIRST_ARGV_IS_OPT) {
    468         if (argv[1] && argv[1][0] != '-' && argv[1][0] != '\0') {
    469             argv[1] = xasprintf("-%s", argv[1]);
    470             if (ENABLE_FEATURE_CLEAN_UP)
    471                 spec_flgs |= FREE_FIRST_ARGV_IS_OPT;
     514    if (spec_flgs & (FIRST_ARGV_IS_OPT | ALL_ARGV_IS_OPTS)) {
     515        pargv = argv + 1;
     516        while (*pargv) {
     517            if (pargv[0][0] != '-' && pargv[0][0] != '\0') {
     518                /* Can't use alloca: opts with params will
     519                 * return pointers to stack!
     520                 * NB: we leak these allocations... */
     521                char *pp = xmalloc(strlen(*pargv) + 2);
     522                *pp = '-';
     523                strcpy(pp + 1, *pargv);
     524                *pargv = pp;
     525            }
     526            if (!(spec_flgs & ALL_ARGV_IS_OPTS))
     527                break;
     528            pargv++;
    472529        }
    473530    }
    474531
    475     /* In case getopt32 was already called, reinit some state */
     532    /* In case getopt32 was already called:
     533     * reset the libc getopt() function, which keeps internal state.
     534     * run_nofork_applet_prime() does this, but we might end up here
     535     * also via gunzip_main() -> gzip_main(). Play safe.
     536     */
     537#ifdef __GLIBC__
     538    optind = 0;
     539#else /* BSD style */
    476540    optind = 1;
    477     /* optarg = NULL; opterr = 0; optopt = 0; ?? */
    478 
    479     /* Note: just "getopt() <= 0" will not work good for
     541    /* optreset = 1; */
     542#endif
     543    /* optarg = NULL; opterr = 0; optopt = 0; - do we need this?? */
     544
     545    pargv = NULL;
     546
     547    /* Note: just "getopt() <= 0" will not work well for
    480548     * "fake" short options, like this one:
    481549     * wget $'-\203' "Test: test" http://kernel.org/
    482550     * (supposed to act as --header, but doesn't) */
    483 #if ENABLE_GETOPT_LONG
     551#if ENABLE_LONG_OPTS || ENABLE_FEATURE_GETOPT_LONG
    484552    while ((c = getopt_long(argc, argv, applet_opts,
    485553            long_options, NULL)) != -1) {
     
    487555    while ((c = getopt(argc, argv, applet_opts)) != -1) {
    488556#endif
    489         c &= 0xff; /* fight libc's sign extends */
    490  loop_arg_is_opt:
    491         for (on_off = complementary; on_off->opt != c; on_off++) {
    492             /* c==0 if long opt have non NULL flag */
    493             if (on_off->opt == 0 && c != 0)
    494                 bb_show_usage();
     557        /* getopt prints "option requires an argument -- X"
     558         * and returns '?' if an option has no arg, but one is reqd */
     559        c &= 0xff; /* fight libc's sign extension */
     560        for (on_off = complementary; on_off->opt_char != c; on_off++) {
     561            /* c can be NUL if long opt has non-NULL ->flag,
     562             * but we construct long opts so that flag
     563             * is always NULL (see above) */
     564            if (on_off->opt_char == '\0' /* && c != '\0' */) {
     565                /* c is probably '?' - "bad option" */
     566                goto error;
     567            }
    495568        }
    496569        if (flags & on_off->incongruously)
    497             bb_show_usage();
     570            goto error;
    498571        trigger = on_off->switch_on & on_off->switch_off;
    499572        flags &= ~(on_off->switch_off ^ trigger);
     
    502575        if (on_off->counter)
    503576            (*(on_off->counter))++;
    504         if (on_off->list_flg) {
    505             llist_add_to_end((llist_t **)(on_off->optarg), optarg);
     577        if (on_off->param_type == PARAM_LIST) {
     578            if (optarg)
     579                llist_add_to_end((llist_t **)(on_off->optarg), optarg);
     580        } else if (on_off->param_type == PARAM_INT) {
     581            if (optarg)
     582//TODO: xatoi_positive indirectly pulls in printf machinery
     583                *(unsigned*)(on_off->optarg) = xatoi_positive(optarg);
    506584        } else if (on_off->optarg) {
    507             *(char **)(on_off->optarg) = optarg;
     585            if (optarg)
     586                *(char **)(on_off->optarg) = optarg;
    508587        }
    509588        if (pargv != NULL)
     
    511590    }
    512591
    513     if (spec_flgs & ALL_ARGV_IS_OPTS) {
    514         /* process argv is option, for example "ps" applet */
    515         if (pargv == NULL)
    516             pargv = argv + optind;
    517         while (*pargv) {
    518             c = **pargv;
    519             if (c == '\0') {
    520                 pargv++;
    521             } else {
    522                 (*pargv)++;
    523                 goto loop_arg_is_opt;
    524             }
    525         }
    526     }
    527 
    528 #if (ENABLE_AR || ENABLE_TAR) && ENABLE_FEATURE_CLEAN_UP
    529     if (spec_flgs & FREE_FIRST_ARGV_IS_OPT)
    530         free(argv[1]);
    531 #endif
    532592    /* check depending requires for given options */
    533     for (on_off = complementary; on_off->opt; on_off++) {
    534         if (on_off->requires && (flags & on_off->switch_on) &&
    535                     (flags & on_off->requires) == 0)
    536             bb_show_usage();
     593    for (on_off = complementary; on_off->opt_char; on_off++) {
     594        if (on_off->requires
     595         && (flags & on_off->switch_on)
     596         && (flags & on_off->requires) == 0
     597        ) {
     598            goto error;
     599        }
    537600    }
    538601    if (requires && (flags & requires) == 0)
    539         bb_show_usage();
     602        goto error;
    540603    argc -= optind;
    541604    if (argc < min_arg || (max_arg >= 0 && argc > max_arg))
    542         bb_show_usage();
     605        goto error;
    543606
    544607    option_mask32 = flags;
    545608    return flags;
     609
     610 error:
     611    if (first_char != '!')
     612        bb_show_usage();
     613    return (int32_t)-1;
    546614}
Note: See TracChangeset for help on using the changeset viewer.