Annotation of embedaddon/sudo/compat/getopt_long.c, revision 1.1

1.1     ! misho       1: /*     $OpenBSD: getopt_long.c,v 1.26 2013/06/08 22:47:56 millert Exp $        */
        !             2: /*     $NetBSD: getopt_long.c,v 1.15 2002/01/31 22:43:40 tv Exp $      */
        !             3: /*     $FreeBSD: head/lib/libc/stdlib/getopt_long.c 236936 2012-06-11 22:25:20Z delphij $      */
        !             4: 
        !             5: /*
        !             6:  * Copyright (c) 2002 Todd C. Miller <Todd.Miller@courtesan.com>
        !             7:  *
        !             8:  * Permission to use, copy, modify, and distribute this software for any
        !             9:  * purpose with or without fee is hereby granted, provided that the above
        !            10:  * copyright notice and this permission notice appear in all copies.
        !            11:  *
        !            12:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
        !            13:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
        !            14:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
        !            15:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
        !            16:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
        !            17:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
        !            18:  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
        !            19:  *
        !            20:  * Sponsored in part by the Defense Advanced Research Projects
        !            21:  * Agency (DARPA) and Air Force Research Laboratory, Air Force
        !            22:  * Materiel Command, USAF, under agreement number F39502-99-1-0512.
        !            23:  */
        !            24: /*-
        !            25:  * Copyright (c) 2000 The NetBSD Foundation, Inc.
        !            26:  * All rights reserved.
        !            27:  *
        !            28:  * This code is derived from software contributed to The NetBSD Foundation
        !            29:  * by Dieter Baron and Thomas Klausner.
        !            30:  *
        !            31:  * Redistribution and use in source and binary forms, with or without
        !            32:  * modification, are permitted provided that the following conditions
        !            33:  * are met:
        !            34:  * 1. Redistributions of source code must retain the above copyright
        !            35:  *    notice, this list of conditions and the following disclaimer.
        !            36:  * 2. Redistributions in binary form must reproduce the above copyright
        !            37:  *    notice, this list of conditions and the following disclaimer in the
        !            38:  *    documentation and/or other materials provided with the distribution.
        !            39:  *
        !            40:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
        !            41:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
        !            42:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
        !            43:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
        !            44:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
        !            45:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
        !            46:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
        !            47:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
        !            48:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
        !            49:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
        !            50:  * POSSIBILITY OF SUCH DAMAGE.
        !            51:  */
        !            52: 
        !            53: #include <config.h>
        !            54: 
        !            55: #include <stdio.h>
        !            56: #ifdef STDC_HEADERS
        !            57: # include <stdlib.h>
        !            58: # include <stddef.h>
        !            59: #else
        !            60: # ifdef HAVE_STDLIB_H
        !            61: #  include <stdlib.h>
        !            62: # endif
        !            63: #endif /* STDC_HEADERS */
        !            64: #ifdef HAVE_STRING_H
        !            65: # include <string.h>
        !            66: #endif /* HAVE_STRING_H */
        !            67: #ifdef HAVE_STRINGS_H
        !            68: # include <strings.h>
        !            69: #endif /* HAVE_STRINGS_H */
        !            70: 
        !            71: #define SUDO_ERROR_WRAP 0
        !            72: 
        !            73: #include "missing.h"
        !            74: #include "fatal.h"
        !            75: #include "compat/getopt.h"
        !            76: 
        !            77: #define GNU_COMPATIBLE         /* Be more compatible with GNU getopt. */
        !            78: 
        !            79: #ifdef REPLACE_GETOPT
        !            80: int    opterr = 1;             /* if error message should be printed */
        !            81: int    optind = 1;             /* index into parent argv vector */
        !            82: int    optopt = '?';           /* character checked for validity */
        !            83: char    *optarg;               /* argument associated with option */
        !            84: #else
        !            85: extern int     opterr;         /* if error message should be printed */
        !            86: extern int     optind;         /* index into parent argv vector */
        !            87: extern int     optopt;         /* character checked for validity */
        !            88: extern char    *optarg;                /* argument associated with option */
        !            89: #endif
        !            90: #if !defined(REPLACE_GETOPT) && !defined(HAVE_OPTRESET)
        !            91: int    optreset;               /* reset getopt */
        !            92: #endif
        !            93: 
        !            94: #define PRINT_ERROR    ((opterr) && (*options != ':'))
        !            95: 
        !            96: #define FLAG_PERMUTE   0x01    /* permute non-options to the end of argv */
        !            97: #define FLAG_ALLARGS   0x02    /* treat non-options as args to option "-1" */
        !            98: #define FLAG_LONGONLY  0x04    /* operate as getopt_long_only */
        !            99: 
        !           100: /* return values */
        !           101: #define        BADCH           (int)'?'
        !           102: #define        BADARG          ((*options == ':') ? (int)':' : (int)'?')
        !           103: #define        INORDER         (int)1
        !           104: 
        !           105: #define        EMSG            ""
        !           106: 
        !           107: #ifdef GNU_COMPATIBLE
        !           108: #define NO_PREFIX      (-1)
        !           109: #define D_PREFIX       0
        !           110: #define DD_PREFIX      1
        !           111: #define W_PREFIX       2
        !           112: #endif
        !           113: 
        !           114: static int getopt_internal(int, char * const *, const char *,
        !           115:                           const struct option *, int *, int);
        !           116: static int parse_long_options(char * const *, const char *,
        !           117:                              const struct option *, int *, int, int);
        !           118: static int gcd(int, int);
        !           119: static void permute_args(int, int, int, char * const *);
        !           120: 
        !           121: static char *place = EMSG; /* option letter processing */
        !           122: 
        !           123: /* XXX: set optreset to 1 rather than these two */
        !           124: static int nonopt_start = -1; /* first non option argument (for permute) */
        !           125: static int nonopt_end = -1;   /* first option after non options (for permute) */
        !           126: 
        !           127: /* Error messages */
        !           128: static const char recargchar[] = "option requires an argument -- %c";
        !           129: static const char illoptchar[] = "illegal option -- %c"; /* From P1003.2 */
        !           130: #ifdef GNU_COMPATIBLE
        !           131: static int dash_prefix = NO_PREFIX;
        !           132: static const char gnuoptchar[] = "invalid option -- %c";
        !           133: 
        !           134: static const char recargstring[] = "option `%s%s' requires an argument";
        !           135: static const char ambig[] = "option `%s%.*s' is ambiguous";
        !           136: static const char noarg[] = "option `%s%.*s' doesn't allow an argument";
        !           137: static const char illoptstring[] = "unrecognized option `%s%s'";
        !           138: #else
        !           139: static const char recargstring[] = "option requires an argument -- %s";
        !           140: static const char ambig[] = "ambiguous option -- %.*s";
        !           141: static const char noarg[] = "option doesn't take an argument -- %.*s";
        !           142: static const char illoptstring[] = "unknown option -- %s";
        !           143: #endif
        !           144: 
        !           145: /*
        !           146:  * Compute the greatest common divisor of a and b.
        !           147:  */
        !           148: static int
        !           149: gcd(int a, int b)
        !           150: {
        !           151:        int c;
        !           152: 
        !           153:        c = a % b;
        !           154:        while (c != 0) {
        !           155:                a = b;
        !           156:                b = c;
        !           157:                c = a % b;
        !           158:        }
        !           159: 
        !           160:        return (b);
        !           161: }
        !           162: 
        !           163: /*
        !           164:  * Exchange the block from nonopt_start to nonopt_end with the block
        !           165:  * from nonopt_end to opt_end (keeping the same order of arguments
        !           166:  * in each block).
        !           167:  */
        !           168: static void
        !           169: permute_args(int panonopt_start, int panonopt_end, int opt_end,
        !           170:        char * const *nargv)
        !           171: {
        !           172:        int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos;
        !           173:        char *swap;
        !           174: 
        !           175:        /*
        !           176:         * compute lengths of blocks and number and size of cycles
        !           177:         */
        !           178:        nnonopts = panonopt_end - panonopt_start;
        !           179:        nopts = opt_end - panonopt_end;
        !           180:        ncycle = gcd(nnonopts, nopts);
        !           181:        cyclelen = (opt_end - panonopt_start) / ncycle;
        !           182: 
        !           183:        for (i = 0; i < ncycle; i++) {
        !           184:                cstart = panonopt_end+i;
        !           185:                pos = cstart;
        !           186:                for (j = 0; j < cyclelen; j++) {
        !           187:                        if (pos >= panonopt_end)
        !           188:                                pos -= nnonopts;
        !           189:                        else
        !           190:                                pos += nopts;
        !           191:                        swap = nargv[pos];
        !           192:                        /* LINTED const cast */
        !           193:                        ((char **) nargv)[pos] = nargv[cstart];
        !           194:                        /* LINTED const cast */
        !           195:                        ((char **)nargv)[cstart] = swap;
        !           196:                }
        !           197:        }
        !           198: }
        !           199: 
        !           200: /*
        !           201:  * parse_long_options --
        !           202:  *     Parse long options in argc/argv argument vector.
        !           203:  * Returns -1 if short_too is set and the option does not match long_options.
        !           204:  */
        !           205: static int
        !           206: parse_long_options(char * const *nargv, const char *options,
        !           207:        const struct option *long_options, int *idx, int short_too, int flags)
        !           208: {
        !           209:        char *current_argv, *has_equal;
        !           210: #ifdef GNU_COMPATIBLE
        !           211:        char *current_dash;
        !           212: #endif
        !           213:        size_t current_argv_len;
        !           214:        int i, match, exact_match, second_partial_match;
        !           215: 
        !           216:        current_argv = place;
        !           217: #ifdef GNU_COMPATIBLE
        !           218:        switch (dash_prefix) {
        !           219:                case D_PREFIX:
        !           220:                        current_dash = "-";
        !           221:                        break;
        !           222:                case DD_PREFIX:
        !           223:                        current_dash = "--";
        !           224:                        break;
        !           225:                case W_PREFIX:
        !           226:                        current_dash = "-W ";
        !           227:                        break;
        !           228:                default:
        !           229:                        current_dash = "";
        !           230:                        break;
        !           231:        }
        !           232: #endif
        !           233:        match = -1;
        !           234:        exact_match = 0;
        !           235:        second_partial_match = 0;
        !           236: 
        !           237:        optind++;
        !           238: 
        !           239:        if ((has_equal = strchr(current_argv, '=')) != NULL) {
        !           240:                /* argument found (--option=arg) */
        !           241:                current_argv_len = has_equal - current_argv;
        !           242:                has_equal++;
        !           243:        } else
        !           244:                current_argv_len = strlen(current_argv);
        !           245: 
        !           246:        for (i = 0; long_options[i].name; i++) {
        !           247:                /* find matching long option */
        !           248:                if (strncmp(current_argv, long_options[i].name,
        !           249:                    current_argv_len))
        !           250:                        continue;
        !           251: 
        !           252:                if (strlen(long_options[i].name) == current_argv_len) {
        !           253:                        /* exact match */
        !           254:                        match = i;
        !           255:                        exact_match = 1;
        !           256:                        break;
        !           257:                }
        !           258:                /*
        !           259:                 * If this is a known short option, don't allow
        !           260:                 * a partial match of a single character.
        !           261:                 */
        !           262:                if (short_too && current_argv_len == 1)
        !           263:                        continue;
        !           264: 
        !           265:                if (match == -1)        /* first partial match */
        !           266:                        match = i;
        !           267:                else if ((flags & FLAG_LONGONLY) ||
        !           268:                         long_options[i].has_arg !=
        !           269:                             long_options[match].has_arg ||
        !           270:                         long_options[i].flag != long_options[match].flag ||
        !           271:                         long_options[i].val != long_options[match].val)
        !           272:                        second_partial_match = 1;
        !           273:        }
        !           274:        if (!exact_match && second_partial_match) {
        !           275:                /* ambiguous abbreviation */
        !           276:                if (PRINT_ERROR)
        !           277:                        warningx(ambig,
        !           278: #ifdef GNU_COMPATIBLE
        !           279:                             current_dash,
        !           280: #endif
        !           281:                             (int)current_argv_len,
        !           282:                             current_argv);
        !           283:                optopt = 0;
        !           284:                return (BADCH);
        !           285:        }
        !           286:        if (match != -1) {              /* option found */
        !           287:                if (long_options[match].has_arg == no_argument
        !           288:                    && has_equal) {
        !           289:                        if (PRINT_ERROR)
        !           290:                                warningx(noarg,
        !           291: #ifdef GNU_COMPATIBLE
        !           292:                                     current_dash,
        !           293: #endif
        !           294:                                     (int)current_argv_len,
        !           295:                                     current_argv);
        !           296:                        /*
        !           297:                         * XXX: GNU sets optopt to val regardless of flag
        !           298:                         */
        !           299:                        if (long_options[match].flag == NULL)
        !           300:                                optopt = long_options[match].val;
        !           301:                        else
        !           302:                                optopt = 0;
        !           303: #ifdef GNU_COMPATIBLE
        !           304:                        return (BADCH);
        !           305: #else
        !           306:                        return (BADARG);
        !           307: #endif
        !           308:                }
        !           309:                if (long_options[match].has_arg == required_argument ||
        !           310:                    long_options[match].has_arg == optional_argument) {
        !           311:                        if (has_equal)
        !           312:                                optarg = has_equal;
        !           313:                        else if (long_options[match].has_arg ==
        !           314:                            required_argument) {
        !           315:                                /*
        !           316:                                 * optional argument doesn't use next nargv
        !           317:                                 */
        !           318:                                optarg = nargv[optind++];
        !           319:                        }
        !           320:                }
        !           321:                if ((long_options[match].has_arg == required_argument)
        !           322:                    && (optarg == NULL)) {
        !           323:                        /*
        !           324:                         * Missing argument; leading ':' indicates no error
        !           325:                         * should be generated.
        !           326:                         */
        !           327:                        if (PRINT_ERROR)
        !           328:                                warningx(recargstring,
        !           329: #ifdef GNU_COMPATIBLE
        !           330:                                    current_dash,
        !           331: #endif
        !           332:                                    current_argv);
        !           333:                        /*
        !           334:                         * XXX: GNU sets optopt to val regardless of flag
        !           335:                         */
        !           336:                        if (long_options[match].flag == NULL)
        !           337:                                optopt = long_options[match].val;
        !           338:                        else
        !           339:                                optopt = 0;
        !           340:                        --optind;
        !           341:                        return (BADARG);
        !           342:                }
        !           343:        } else {                        /* unknown option */
        !           344:                if (short_too) {
        !           345:                        --optind;
        !           346:                        return (-1);
        !           347:                }
        !           348:                if (PRINT_ERROR)
        !           349:                        warningx(illoptstring,
        !           350: #ifdef GNU_COMPATIBLE
        !           351:                              current_dash,
        !           352: #endif
        !           353:                              current_argv);
        !           354:                optopt = 0;
        !           355:                return (BADCH);
        !           356:        }
        !           357:        if (idx)
        !           358:                *idx = match;
        !           359:        if (long_options[match].flag) {
        !           360:                *long_options[match].flag = long_options[match].val;
        !           361:                return (0);
        !           362:        } else
        !           363:                return (long_options[match].val);
        !           364: }
        !           365: 
        !           366: /*
        !           367:  * getopt_internal --
        !           368:  *     Parse argc/argv argument vector.  Called by user level routines.
        !           369:  */
        !           370: static int
        !           371: getopt_internal(int nargc, char * const *nargv, const char *options,
        !           372:        const struct option *long_options, int *idx, int flags)
        !           373: {
        !           374:        char *oli;                              /* option letter list index */
        !           375:        int optchar, short_too;
        !           376:        int posixly_correct;    /* no static, can be changed on the fly */
        !           377: 
        !           378:        if (options == NULL)
        !           379:                return (-1);
        !           380: 
        !           381:        /*
        !           382:         * Disable GNU extensions if POSIXLY_CORRECT is set or options
        !           383:         * string begins with a '+'.
        !           384:         */
        !           385:        posixly_correct = (getenv("POSIXLY_CORRECT") != NULL);
        !           386: #ifdef GNU_COMPATIBLE
        !           387:        if (*options == '-')
        !           388:                flags |= FLAG_ALLARGS;
        !           389:        else if (posixly_correct || *options == '+')
        !           390:                flags &= ~FLAG_PERMUTE;
        !           391: #else
        !           392:        if (posixly_correct || *options == '+')
        !           393:                flags &= ~FLAG_PERMUTE;
        !           394:        else if (*options == '-')
        !           395:                flags |= FLAG_ALLARGS;
        !           396: #endif
        !           397:        if (*options == '+' || *options == '-')
        !           398:                options++;
        !           399: 
        !           400:        /*
        !           401:         * XXX Some GNU programs (like cvs) set optind to 0 instead of
        !           402:         * XXX using optreset.  Work around this braindamage.
        !           403:         */
        !           404:        if (optind == 0)
        !           405:                optind = optreset = 1;
        !           406: 
        !           407:        optarg = NULL;
        !           408:        if (optreset)
        !           409:                nonopt_start = nonopt_end = -1;
        !           410: start:
        !           411:        if (optreset || !*place) {              /* update scanning pointer */
        !           412:                optreset = 0;
        !           413:                if (optind >= nargc) {          /* end of argument vector */
        !           414:                        place = EMSG;
        !           415:                        if (nonopt_end != -1) {
        !           416:                                /* do permutation, if we have to */
        !           417:                                permute_args(nonopt_start, nonopt_end,
        !           418:                                    optind, nargv);
        !           419:                                optind -= nonopt_end - nonopt_start;
        !           420:                        }
        !           421:                        else if (nonopt_start != -1) {
        !           422:                                /*
        !           423:                                 * If we skipped non-options, set optind
        !           424:                                 * to the first of them.
        !           425:                                 */
        !           426:                                optind = nonopt_start;
        !           427:                        }
        !           428:                        nonopt_start = nonopt_end = -1;
        !           429:                        return (-1);
        !           430:                }
        !           431:                if (*(place = nargv[optind]) != '-' ||
        !           432: #ifdef GNU_COMPATIBLE
        !           433:                    place[1] == '\0') {
        !           434: #else
        !           435:                    (place[1] == '\0' && strchr(options, '-') == NULL)) {
        !           436: #endif
        !           437:                        place = EMSG;           /* found non-option */
        !           438:                        if (flags & FLAG_ALLARGS) {
        !           439:                                /*
        !           440:                                 * GNU extension:
        !           441:                                 * return non-option as argument to option 1
        !           442:                                 */
        !           443:                                optarg = nargv[optind++];
        !           444:                                return (INORDER);
        !           445:                        }
        !           446:                        if (!(flags & FLAG_PERMUTE)) {
        !           447:                                /*
        !           448:                                 * If no permutation wanted, stop parsing
        !           449:                                 * at first non-option.
        !           450:                                 */
        !           451:                                return (-1);
        !           452:                        }
        !           453:                        /* do permutation */
        !           454:                        if (nonopt_start == -1)
        !           455:                                nonopt_start = optind;
        !           456:                        else if (nonopt_end != -1) {
        !           457:                                permute_args(nonopt_start, nonopt_end,
        !           458:                                    optind, nargv);
        !           459:                                nonopt_start = optind -
        !           460:                                    (nonopt_end - nonopt_start);
        !           461:                                nonopt_end = -1;
        !           462:                        }
        !           463:                        optind++;
        !           464:                        /* process next argument */
        !           465:                        goto start;
        !           466:                }
        !           467:                if (nonopt_start != -1 && nonopt_end == -1)
        !           468:                        nonopt_end = optind;
        !           469: 
        !           470:                /*
        !           471:                 * If we have "-" do nothing, if "--" we are done.
        !           472:                 */
        !           473:                if (place[1] != '\0' && *++place == '-' && place[1] == '\0') {
        !           474:                        optind++;
        !           475:                        place = EMSG;
        !           476:                        /*
        !           477:                         * We found an option (--), so if we skipped
        !           478:                         * non-options, we have to permute.
        !           479:                         */
        !           480:                        if (nonopt_end != -1) {
        !           481:                                permute_args(nonopt_start, nonopt_end,
        !           482:                                    optind, nargv);
        !           483:                                optind -= nonopt_end - nonopt_start;
        !           484:                        }
        !           485:                        nonopt_start = nonopt_end = -1;
        !           486:                        return (-1);
        !           487:                }
        !           488:        }
        !           489: 
        !           490:        /*
        !           491:         * Check long options if:
        !           492:         *  1) we were passed some
        !           493:         *  2) the arg is not just "-"
        !           494:         *  3) either the arg starts with -- we are getopt_long_only()
        !           495:         */
        !           496:        if (long_options != NULL && place != nargv[optind] &&
        !           497:            (*place == '-' || (flags & FLAG_LONGONLY))) {
        !           498:                short_too = 0;
        !           499: #ifdef GNU_COMPATIBLE
        !           500:                dash_prefix = D_PREFIX;
        !           501: #endif
        !           502:                if (*place == '-') {
        !           503:                        place++;                /* --foo long option */
        !           504: #ifdef GNU_COMPATIBLE
        !           505:                        dash_prefix = DD_PREFIX;
        !           506: #endif
        !           507:                } else if (*place != ':' && strchr(options, *place) != NULL)
        !           508:                        short_too = 1;          /* could be short option too */
        !           509: 
        !           510:                optchar = parse_long_options(nargv, options, long_options,
        !           511:                    idx, short_too, flags);
        !           512:                if (optchar != -1) {
        !           513:                        place = EMSG;
        !           514:                        return (optchar);
        !           515:                }
        !           516:        }
        !           517: 
        !           518:        if ((optchar = (int)*place++) == (int)':' ||
        !           519:            (optchar == (int)'-' && *place != '\0') ||
        !           520:            (oli = strchr(options, optchar)) == NULL) {
        !           521:                /*
        !           522:                 * If the user specified "-" and  '-' isn't listed in
        !           523:                 * options, return -1 (non-option) as per POSIX.
        !           524:                 * Otherwise, it is an unknown option character (or ':').
        !           525:                 */
        !           526:                if (optchar == (int)'-' && *place == '\0')
        !           527:                        return (-1);
        !           528:                if (!*place)
        !           529:                        ++optind;
        !           530: #ifdef GNU_COMPATIBLE
        !           531:                if (PRINT_ERROR)
        !           532:                        warningx(posixly_correct ? illoptchar : gnuoptchar,
        !           533:                              optchar);
        !           534: #else
        !           535:                if (PRINT_ERROR)
        !           536:                        warningx(illoptchar, optchar);
        !           537: #endif
        !           538:                optopt = optchar;
        !           539:                return (BADCH);
        !           540:        }
        !           541:        if (long_options != NULL && optchar == 'W' && oli[1] == ';') {
        !           542:                /* -W long-option */
        !           543:                if (*place)                     /* no space */
        !           544:                        /* NOTHING */;
        !           545:                else if (++optind >= nargc) {   /* no arg */
        !           546:                        place = EMSG;
        !           547:                        if (PRINT_ERROR)
        !           548:                                warningx(recargchar, optchar);
        !           549:                        optopt = optchar;
        !           550:                        return (BADARG);
        !           551:                } else                          /* white space */
        !           552:                        place = nargv[optind];
        !           553: #ifdef GNU_COMPATIBLE
        !           554:                dash_prefix = W_PREFIX;
        !           555: #endif
        !           556:                optchar = parse_long_options(nargv, options, long_options,
        !           557:                    idx, 0, flags);
        !           558:                place = EMSG;
        !           559:                return (optchar);
        !           560:        }
        !           561:        if (*++oli != ':') {                    /* doesn't take argument */
        !           562:                if (!*place)
        !           563:                        ++optind;
        !           564:        } else {                                /* takes (optional) argument */
        !           565:                optarg = NULL;
        !           566:                if (*place)                     /* no white space */
        !           567:                        optarg = place;
        !           568:                else if (oli[1] != ':') {       /* arg not optional */
        !           569:                        if (++optind >= nargc) {        /* no arg */
        !           570:                                place = EMSG;
        !           571:                                if (PRINT_ERROR)
        !           572:                                        warningx(recargchar, optchar);
        !           573:                                optopt = optchar;
        !           574:                                return (BADARG);
        !           575:                        } else
        !           576:                                optarg = nargv[optind];
        !           577:                }
        !           578:                place = EMSG;
        !           579:                ++optind;
        !           580:        }
        !           581:        /* dump back option letter */
        !           582:        return (optchar);
        !           583: }
        !           584: 
        !           585: #ifdef REPLACE_GETOPT
        !           586: /*
        !           587:  * getopt --
        !           588:  *     Parse argc/argv argument vector.
        !           589:  */
        !           590: int
        !           591: getopt(int nargc, char * const *nargv, const char *options)
        !           592: {
        !           593: 
        !           594:        /*
        !           595:         * We don't pass FLAG_PERMUTE to getopt_internal() since
        !           596:         * the BSD getopt(3) (unlike GNU) has never done this.
        !           597:         *
        !           598:         * Furthermore, since many privileged programs call getopt()
        !           599:         * before dropping privileges it makes sense to keep things
        !           600:         * as simple (and bug-free) as possible.
        !           601:         */
        !           602:        return (getopt_internal(nargc, nargv, options, NULL, NULL, 0));
        !           603: }
        !           604: #endif /* REPLACE_GETOPT */
        !           605: 
        !           606: /*
        !           607:  * getopt_long --
        !           608:  *     Parse argc/argv argument vector.
        !           609:  */
        !           610: int
        !           611: getopt_long(int nargc, char * const *nargv, const char *options,
        !           612:        const struct option *long_options, int *idx)
        !           613: {
        !           614: 
        !           615:        return (getopt_internal(nargc, nargv, options, long_options, idx,
        !           616:            FLAG_PERMUTE));
        !           617: }
        !           618: 
        !           619: /*
        !           620:  * getopt_long_only --
        !           621:  *     Parse argc/argv argument vector.
        !           622:  */
        !           623: int
        !           624: getopt_long_only(int nargc, char * const *nargv, const char *options,
        !           625:        const struct option *long_options, int *idx)
        !           626: {
        !           627: 
        !           628:        return (getopt_internal(nargc, nargv, options, long_options, idx,
        !           629:            FLAG_PERMUTE|FLAG_LONGONLY));
        !           630: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>