[BACK]Return to options.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / bin / sh

Annotation of src/bin/sh/options.c, Revision 1.51

1.51    ! kre         1: /*     $NetBSD: options.c,v 1.50 2017/07/24 12:35:37 kre Exp $ */
1.11      cgd         2:
1.1       cgd         3: /*-
1.5       jtc         4:  * Copyright (c) 1991, 1993
                      5:  *     The Regents of the University of California.  All rights reserved.
1.1       cgd         6:  *
                      7:  * This code is derived from software contributed to Berkeley by
                      8:  * Kenneth Almquist.
                      9:  *
                     10:  * Redistribution and use in source and binary forms, with or without
                     11:  * modification, are permitted provided that the following conditions
                     12:  * are met:
                     13:  * 1. Redistributions of source code must retain the above copyright
                     14:  *    notice, this list of conditions and the following disclaimer.
                     15:  * 2. Redistributions in binary form must reproduce the above copyright
                     16:  *    notice, this list of conditions and the following disclaimer in the
                     17:  *    documentation and/or other materials provided with the distribution.
1.35      agc        18:  * 3. Neither the name of the University nor the names of its contributors
1.1       cgd        19:  *    may be used to endorse or promote products derived from this software
                     20:  *    without specific prior written permission.
                     21:  *
                     22:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     23:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     24:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     25:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     26:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     27:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     28:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     29:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     30:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     31:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     32:  * SUCH DAMAGE.
                     33:  */
                     34:
1.25      christos   35: #include <sys/cdefs.h>
1.1       cgd        36: #ifndef lint
1.11      cgd        37: #if 0
1.14      christos   38: static char sccsid[] = "@(#)options.c  8.2 (Berkeley) 5/4/95";
1.11      cgd        39: #else
1.51    ! kre        40: __RCSID("$NetBSD: options.c,v 1.50 2017/07/24 12:35:37 kre Exp $");
1.11      cgd        41: #endif
1.1       cgd        42: #endif /* not lint */
                     43:
1.14      christos   44: #include <signal.h>
                     45: #include <unistd.h>
                     46: #include <stdlib.h>
                     47:
1.1       cgd        48: #include "shell.h"
                     49: #define DEFINE_OPTIONS
                     50: #include "options.h"
                     51: #undef DEFINE_OPTIONS
1.42      christos   52: #include "builtins.h"
1.1       cgd        53: #include "nodes.h"     /* for other header files */
                     54: #include "eval.h"
                     55: #include "jobs.h"
                     56: #include "input.h"
                     57: #include "output.h"
                     58: #include "trap.h"
                     59: #include "var.h"
                     60: #include "memalloc.h"
                     61: #include "error.h"
                     62: #include "mystring.h"
1.24      christos   63: #ifndef SMALL
1.14      christos   64: #include "myhistedit.h"
                     65: #endif
1.32      christos   66: #include "show.h"
1.1       cgd        67:
                     68: char *arg0;                    /* value of $0 */
                     69: struct shparam shellparam;     /* current positional parameters */
                     70: char **argptr;                 /* argument list for builtin commands */
1.30      christos   71: char *optionarg;               /* set by nextopt (like getopt) */
1.1       cgd        72: char *optptr;                  /* used by nextopt */
                     73:
                     74: char *minusc;                  /* argument to -c option */
                     75:
                     76:
1.32      christos   77: STATIC void options(int);
                     78: STATIC void minus_o(char *, int);
                     79: STATIC void setoption(int, int);
                     80: STATIC int getopts(char *, char *, char **, char ***, char **);
1.1       cgd        81:
                     82:
                     83: /*
                     84:  * Process the shell command line arguments.
                     85:  */
                     86:
                     87: void
1.32      christos   88: procargs(int argc, char **argv)
1.10      cgd        89: {
1.41      lukem      90:        size_t i;
1.48      kre        91:        int psx;
1.1       cgd        92:
                     93:        argptr = argv;
                     94:        if (argc > 0)
                     95:                argptr++;
1.48      kre        96:
                     97:        psx = posix;            /* save what we set it to earlier */
                     98:        /*
                     99:         * option values are mostly boolean 0:off 1:on
                    100:         * we use 2 (just in this routine) to mean "unknown yet"
                    101:         */
1.5       jtc       102:        for (i = 0; i < NOPTS; i++)
                    103:                optlist[i].val = 2;
1.48      kre       104:        posix = psx;            /* restore before processing -o ... */
                    105:
1.1       cgd       106:        options(1);
1.48      kre       107:
1.1       cgd       108:        if (*argptr == NULL && minusc == NULL)
                    109:                sflag = 1;
1.50      kre       110:        if (iflag == 2 && sflag == 1 && isatty(0) && isatty(2))
1.1       cgd       111:                iflag = 1;
1.39      christos  112:        if (iflag == 1 && sflag == 2)
                    113:                iflag = 2;
1.5       jtc       114:        if (mflag == 2)
                    115:                mflag = iflag;
1.44      christos  116: #ifndef DO_SHAREDVFORK
                    117:        if (usefork == 2)
                    118:                usefork = 1;
                    119: #endif
1.49      kre       120: #if DEBUG >= 2
1.48      kre       121:        if (debug == 2)
                    122:                debug = 1;
1.32      christos  123: #endif
1.48      kre       124:        /*
                    125:         * Any options not dealt with as special cases just above,
                    126:         * and which were not set on the command line, are set to
                    127:         * their expected default values (mostly "off")
                    128:         *
                    129:         * then as each option is initialised, save its setting now
                    130:         * as its "default" value for future use ("set -o default").
                    131:         */
                    132:        for (i = 0; i < NOPTS; i++) {
                    133:                if (optlist[i].val == 2)
                    134:                        optlist[i].val = optlist[i].dflt;
                    135:                optlist[i].dflt = optlist[i].val;
                    136:        }
                    137:
1.1       cgd       138:        arg0 = argv[0];
                    139:        if (sflag == 0 && minusc == NULL) {
1.31      wiz       140:                commandname = argv[0];
                    141:                arg0 = *argptr++;
                    142:                setinputfile(arg0, 0);
                    143:                commandname = arg0;
1.1       cgd       144:        }
1.17      christos  145:        /* POSIX 1003.2: first arg after -c cmd is $0, remainder $1... */
1.33      dsl       146:        if (minusc != NULL) {
                    147:                if (argptr == NULL || *argptr == NULL)
                    148:                        error("Bad -c option");
                    149:                minusc = *argptr++;
                    150:                if (*argptr != 0)
                    151:                        arg0 = *argptr++;
                    152:        }
1.17      christos  153:
1.1       cgd       154:        shellparam.p = argptr;
1.19      christos  155:        shellparam.reset = 1;
1.1       cgd       156:        /* assert(shellparam.malloc == 0 && shellparam.nparam == 0); */
                    157:        while (*argptr) {
                    158:                shellparam.nparam++;
                    159:                argptr++;
                    160:        }
1.5       jtc       161:        optschanged();
1.1       cgd       162: }
                    163:
                    164:
1.9       cgd       165: void
1.32      christos  166: optschanged(void)
1.9       cgd       167: {
1.5       jtc       168:        setinteractive(iflag);
1.24      christos  169: #ifndef SMALL
1.5       jtc       170:        histedit();
1.7       cgd       171: #endif
1.5       jtc       172:        setjobctl(mflag);
                    173: }
1.1       cgd       174:
                    175: /*
                    176:  * Process shell options.  The global variable argptr contains a pointer
                    177:  * to the argument list; we advance it past the options.
                    178:  */
                    179:
                    180: STATIC void
1.32      christos  181: options(int cmdline)
1.10      cgd       182: {
1.37      christos  183:        static char empty[] = "";
1.22      tls       184:        char *p;
1.1       cgd       185:        int val;
                    186:        int c;
                    187:
                    188:        if (cmdline)
                    189:                minusc = NULL;
                    190:        while ((p = *argptr) != NULL) {
                    191:                argptr++;
                    192:                if ((c = *p++) == '-') {
                    193:                        val = 1;
1.14      christos  194:                         if (p[0] == '\0' || (p[0] == '-' && p[1] == '\0')) {
1.1       cgd       195:                                 if (!cmdline) {
                    196:                                         /* "-" means turn off -x and -v */
                    197:                                         if (p[0] == '\0')
                    198:                                                 xflag = vflag = 0;
                    199:                                         /* "--" means reset params */
1.13      christos  200:                                         else if (*argptr == NULL)
                    201:                                                setparam(argptr);
1.1       cgd       202:                                 }
                    203:                                break;    /* "-" or  "--" terminates options */
                    204:                        }
                    205:                } else if (c == '+') {
                    206:                        val = 0;
                    207:                } else {
                    208:                        argptr--;
                    209:                        break;
                    210:                }
                    211:                while ((c = *p++) != '\0') {
1.48      kre       212:                        if (val == 1 && c == 'c' && cmdline) {
1.37      christos  213:                                /* command is after shell args*/
                    214:                                minusc = empty;
1.5       jtc       215:                        } else if (c == 'o') {
1.48      kre       216:                                if (*p != '\0')
                    217:                                        minus_o(p, val + (cmdline ? val : 0));
                    218:                                else if (*argptr)
                    219:                                        minus_o(*argptr++,
                    220:                                            val + (cmdline ? val : 0));
                    221:                                else if (!cmdline)
                    222:                                        minus_o(NULL, val);
                    223:                                else
                    224:                                        error("arg for %co missing", "+-"[val]);
                    225:                                break;
1.47      kre       226: #ifdef DEBUG
                    227:                        } else if (c == 'D') {
                    228:                                if (*p) {
                    229:                                        set_debug(p, val);
                    230:                                        break;
                    231:                                } else if (*argptr)
                    232:                                        set_debug(*argptr++, val);
                    233:                                else
                    234:                                        set_debug("*$", val);
                    235: #endif
1.1       cgd       236:                        } else {
                    237:                                setoption(c, val);
                    238:                        }
                    239:                }
                    240:        }
                    241: }
                    242:
1.32      christos  243: static void
1.41      lukem     244: set_opt_val(size_t i, int val)
1.32      christos  245: {
1.41      lukem     246:        size_t j;
1.32      christos  247:        int flag;
                    248:
                    249:        if (val && (flag = optlist[i].opt_set)) {
                    250:                /* some options (eg vi/emacs) are mutually exclusive */
                    251:                for (j = 0; j < NOPTS; j++)
                    252:                    if (optlist[j].opt_set == flag)
                    253:                        optlist[j].val = 0;
                    254:        }
1.51    ! kre       255:        if (i == _SH_OPT_Xflag)
        !           256:                xtracefdsetup(val);
1.32      christos  257:        optlist[i].val = val;
                    258: #ifdef DEBUG
                    259:        if (&optlist[i].val == &debug)
1.51    ! kre       260:                opentrace();    /* different "trace" than the -x one... */
1.32      christos  261: #endif
                    262: }
                    263:
1.5       jtc       264: STATIC void
1.32      christos  265: minus_o(char *name, int val)
1.5       jtc       266: {
1.41      lukem     267:        size_t i;
1.46      christos  268:        const char *sep = ": ";
1.5       jtc       269:
                    270:        if (name == NULL) {
1.40      dsl       271:                if (val) {
1.46      christos  272:                        out1str("Current option settings");
1.40      dsl       273:                        for (i = 0; i < NOPTS; i++) {
1.46      christos  274:                                if (optlist[i].name == NULL)  {
                    275:                                        out1fmt("%s%c%c", sep,
                    276:                                            "+-"[optlist[i].val],
                    277:                                            optlist[i].letter);
                    278:                                        sep = ", ";
                    279:                                }
                    280:                        }
                    281:                        out1c('\n');
                    282:                        for (i = 0; i < NOPTS; i++) {
                    283:                                if (optlist[i].name)
1.48      kre       284:                                    out1fmt("%-19s %s\n", optlist[i].name,
1.40      dsl       285:                                        optlist[i].val ? "on" : "off");
                    286:                        }
                    287:                } else {
1.48      kre       288:                        out1str("set -o default");
1.40      dsl       289:                        for (i = 0; i < NOPTS; i++) {
1.48      kre       290:                                if (optlist[i].val == optlist[i].dflt)
                    291:                                        continue;
1.46      christos  292:                                if (optlist[i].name)
                    293:                                    out1fmt(" %co %s",
1.40      dsl       294:                                        "+-"[optlist[i].val], optlist[i].name);
1.46      christos  295:                                else
                    296:                                    out1fmt(" %c%c", "+-"[optlist[i].val],
                    297:                                        optlist[i].letter);
1.40      dsl       298:                        }
1.46      christos  299:                        out1c('\n');
1.40      dsl       300:                }
1.5       jtc       301:        } else {
1.48      kre       302:                if (val == 1 && equal(name, "default")) { /* special case */
                    303:                        for (i = 0; i < NOPTS; i++)
                    304:                                set_opt_val(i, optlist[i].dflt);
                    305:                        return;
                    306:                }
                    307:                if (val)
                    308:                        val = 1;
1.5       jtc       309:                for (i = 0; i < NOPTS; i++)
1.46      christos  310:                        if (optlist[i].name && equal(name, optlist[i].name)) {
1.32      christos  311:                                set_opt_val(i, val);
1.51    ! kre       312:                                if (i == _SH_OPT_Xflag)
        !           313:                                        set_opt_val(_SH_OPT_xflag, val);
1.5       jtc       314:                                return;
                    315:                        }
1.48      kre       316:                error("Illegal option %co %s", "+-"[val], name);
1.5       jtc       317:        }
                    318: }
1.17      christos  319:
1.1       cgd       320:
                    321: STATIC void
1.32      christos  322: setoption(int flag, int val)
                    323: {
1.41      lukem     324:        size_t i;
1.1       cgd       325:
1.5       jtc       326:        for (i = 0; i < NOPTS; i++)
                    327:                if (optlist[i].letter == flag) {
1.51    ! kre       328:                        set_opt_val(i, val);
        !           329:                        if (i == _SH_OPT_Xflag)
        !           330:                                set_opt_val(_SH_OPT_xflag, val);
1.5       jtc       331:                        return;
                    332:                }
1.48      kre       333:        error("Illegal option %c%c", "+-"[val], flag);
1.28      mycroft   334:        /* NOTREACHED */
1.1       cgd       335: }
                    336:
                    337:
                    338:
                    339: #ifdef mkinit
                    340: INCLUDE "options.h"
                    341:
                    342: SHELLPROC {
1.5       jtc       343:        int i;
                    344:
1.32      christos  345:        for (i = 0; optlist[i].name; i++)
1.5       jtc       346:                optlist[i].val = 0;
                    347:        optschanged();
1.1       cgd       348:
                    349: }
                    350: #endif
                    351:
                    352:
                    353: /*
                    354:  * Set the shell parameters.
                    355:  */
                    356:
                    357: void
1.32      christos  358: setparam(char **argv)
                    359: {
1.1       cgd       360:        char **newparam;
                    361:        char **ap;
                    362:        int nparam;
                    363:
1.38      dsl       364:        for (nparam = 0 ; argv[nparam] ; nparam++)
                    365:                continue;
1.1       cgd       366:        ap = newparam = ckmalloc((nparam + 1) * sizeof *ap);
                    367:        while (*argv) {
                    368:                *ap++ = savestr(*argv++);
                    369:        }
                    370:        *ap = NULL;
                    371:        freeparam(&shellparam);
                    372:        shellparam.malloc = 1;
                    373:        shellparam.nparam = nparam;
                    374:        shellparam.p = newparam;
                    375:        shellparam.optnext = NULL;
                    376: }
                    377:
                    378:
                    379: /*
                    380:  * Free the list of positional parameters.
                    381:  */
                    382:
                    383: void
1.32      christos  384: freeparam(volatile struct shparam *param)
                    385: {
1.1       cgd       386:        char **ap;
                    387:
                    388:        if (param->malloc) {
                    389:                for (ap = param->p ; *ap ; ap++)
                    390:                        ckfree(*ap);
                    391:                ckfree(param->p);
                    392:        }
                    393: }
                    394:
                    395:
                    396:
                    397: /*
                    398:  * The shift builtin command.
                    399:  */
                    400:
1.10      cgd       401: int
1.32      christos  402: shiftcmd(int argc, char **argv)
1.10      cgd       403: {
1.1       cgd       404:        int n;
                    405:        char **ap1, **ap2;
                    406:
1.45      christos  407:        if (argc > 2)
                    408:                error("Usage: shift [n]");
1.1       cgd       409:        n = 1;
                    410:        if (argc > 1)
                    411:                n = number(argv[1]);
                    412:        if (n > shellparam.nparam)
1.5       jtc       413:                error("can't shift that many");
1.1       cgd       414:        INTOFF;
                    415:        shellparam.nparam -= n;
                    416:        for (ap1 = shellparam.p ; --n >= 0 ; ap1++) {
                    417:                if (shellparam.malloc)
                    418:                        ckfree(*ap1);
                    419:        }
                    420:        ap2 = shellparam.p;
1.45      christos  421:        while ((*ap2++ = *ap1++) != NULL)
                    422:                continue;
1.1       cgd       423:        shellparam.optnext = NULL;
                    424:        INTON;
                    425:        return 0;
                    426: }
                    427:
                    428:
                    429:
                    430: /*
                    431:  * The set command builtin.
                    432:  */
                    433:
1.10      cgd       434: int
1.32      christos  435: setcmd(int argc, char **argv)
1.10      cgd       436: {
1.1       cgd       437:        if (argc == 1)
1.46      christos  438:                return showvars(0, 0, 1, 0);
1.1       cgd       439:        INTOFF;
                    440:        options(0);
1.5       jtc       441:        optschanged();
1.1       cgd       442:        if (*argptr != NULL) {
                    443:                setparam(argptr);
                    444:        }
                    445:        INTON;
                    446:        return 0;
                    447: }
                    448:
                    449:
1.16      christos  450: void
1.43      matt      451: getoptsreset(const char *value)
1.16      christos  452: {
1.19      christos  453:        if (number(value) == 1) {
1.18      christos  454:                shellparam.optnext = NULL;
1.19      christos  455:                shellparam.reset = 1;
                    456:        }
1.16      christos  457: }
                    458:
1.1       cgd       459: /*
                    460:  * The getopts builtin.  Shellparam.optnext points to the next argument
                    461:  * to be processed.  Shellparam.optptr points to the next character to
                    462:  * be processed in the current argument.  If shellparam.optnext is NULL,
                    463:  * then it's the first time getopts has been called.
                    464:  */
                    465:
1.10      cgd       466: int
1.32      christos  467: getoptscmd(int argc, char **argv)
1.10      cgd       468: {
1.15      christos  469:        char **optbase;
                    470:
                    471:        if (argc < 3)
1.36      jmmv      472:                error("usage: getopts optstring var [arg]");
1.15      christos  473:        else if (argc == 3)
                    474:                optbase = shellparam.p;
1.17      christos  475:        else
1.15      christos  476:                optbase = &argv[3];
1.1       cgd       477:
1.19      christos  478:        if (shellparam.reset == 1) {
1.15      christos  479:                shellparam.optnext = optbase;
1.1       cgd       480:                shellparam.optptr = NULL;
1.19      christos  481:                shellparam.reset = 0;
1.1       cgd       482:        }
1.15      christos  483:
                    484:        return getopts(argv[1], argv[2], optbase, &shellparam.optnext,
                    485:                       &shellparam.optptr);
                    486: }
                    487:
                    488: STATIC int
1.32      christos  489: getopts(char *optstr, char *optvar, char **optfirst, char ***optnext, char **optpptr)
1.15      christos  490: {
1.22      tls       491:        char *p, *q;
1.15      christos  492:        char c = '?';
                    493:        int done = 0;
                    494:        int ind = 0;
1.16      christos  495:        int err = 0;
1.34      itojun    496:        char s[12];
1.15      christos  497:
1.29      christos  498:        if ((p = *optpptr) == NULL || *p == '\0') {
1.15      christos  499:                /* Current word is done, advance */
1.19      christos  500:                if (*optnext == NULL)
                    501:                        return 1;
1.15      christos  502:                p = **optnext;
1.1       cgd       503:                if (p == NULL || *p != '-' || *++p == '\0') {
                    504: atend:
1.21      christos  505:                        ind = *optnext - optfirst + 1;
1.20      christos  506:                        *optnext = NULL;
1.21      christos  507:                        p = NULL;
1.15      christos  508:                        done = 1;
                    509:                        goto out;
1.1       cgd       510:                }
1.15      christos  511:                (*optnext)++;
1.1       cgd       512:                if (p[0] == '-' && p[1] == '\0')        /* check for "--" */
                    513:                        goto atend;
                    514:        }
1.15      christos  515:
1.1       cgd       516:        c = *p++;
1.15      christos  517:        for (q = optstr; *q != c; ) {
1.1       cgd       518:                if (*q == '\0') {
1.15      christos  519:                        if (optstr[0] == ':') {
                    520:                                s[0] = c;
                    521:                                s[1] = '\0';
1.16      christos  522:                                err |= setvarsafe("OPTARG", s, 0);
1.32      christos  523:                        } else {
1.26      christos  524:                                outfmt(&errout, "Illegal option -%c\n", c);
1.32      christos  525:                                (void) unsetvar("OPTARG", 0);
1.15      christos  526:                        }
1.1       cgd       527:                        c = '?';
1.16      christos  528:                        goto bad;
1.1       cgd       529:                }
                    530:                if (*++q == ':')
                    531:                        q++;
                    532:        }
1.15      christos  533:
1.1       cgd       534:        if (*++q == ':') {
1.15      christos  535:                if (*p == '\0' && (p = **optnext) == NULL) {
                    536:                        if (optstr[0] == ':') {
                    537:                                s[0] = c;
                    538:                                s[1] = '\0';
1.16      christos  539:                                err |= setvarsafe("OPTARG", s, 0);
1.15      christos  540:                                c = ':';
1.32      christos  541:                        } else {
1.26      christos  542:                                outfmt(&errout, "No arg for -%c option\n", c);
1.32      christos  543:                                (void) unsetvar("OPTARG", 0);
1.15      christos  544:                                c = '?';
                    545:                        }
1.16      christos  546:                        goto bad;
1.1       cgd       547:                }
1.15      christos  548:
                    549:                if (p == **optnext)
                    550:                        (*optnext)++;
1.32      christos  551:                err |= setvarsafe("OPTARG", p, 0);
1.1       cgd       552:                p = NULL;
1.32      christos  553:        } else
                    554:                err |= setvarsafe("OPTARG", "", 0);
1.19      christos  555:        ind = *optnext - optfirst + 1;
                    556:        goto out;
                    557:
1.16      christos  558: bad:
                    559:        ind = 1;
                    560:        *optnext = NULL;
                    561:        p = NULL;
1.1       cgd       562: out:
1.29      christos  563:        *optpptr = p;
1.15      christos  564:        fmtstr(s, sizeof(s), "%d", ind);
1.16      christos  565:        err |= setvarsafe("OPTIND", s, VNOFUNC);
1.1       cgd       566:        s[0] = c;
                    567:        s[1] = '\0';
1.16      christos  568:        err |= setvarsafe(optvar, s, 0);
                    569:        if (err) {
                    570:                *optnext = NULL;
1.29      christos  571:                *optpptr = NULL;
1.16      christos  572:                flushall();
                    573:                exraise(EXERROR);
                    574:        }
1.15      christos  575:        return done;
1.1       cgd       576: }
                    577:
                    578: /*
1.5       jtc       579:  * XXX - should get rid of.  have all builtins use getopt(3).  the
                    580:  * library getopt must have the BSD extension static variable "optreset"
                    581:  * otherwise it can't be used within the shell safely.
                    582:  *
1.1       cgd       583:  * Standard option processing (a la getopt) for builtin routines.  The
                    584:  * only argument that is passed to nextopt is the option string; the
                    585:  * other arguments are unnecessary.  It return the character, or '\0' on
                    586:  * end of input.
                    587:  */
                    588:
                    589: int
1.32      christos  590: nextopt(const char *optstring)
                    591: {
1.29      christos  592:        char *p;
                    593:        const char *q;
1.1       cgd       594:        char c;
                    595:
                    596:        if ((p = optptr) == NULL || *p == '\0') {
                    597:                p = *argptr;
                    598:                if (p == NULL || *p != '-' || *++p == '\0')
                    599:                        return '\0';
                    600:                argptr++;
                    601:                if (p[0] == '-' && p[1] == '\0')        /* check for "--" */
                    602:                        return '\0';
                    603:        }
                    604:        c = *p++;
                    605:        for (q = optstring ; *q != c ; ) {
                    606:                if (*q == '\0')
                    607:                        error("Illegal option -%c", c);
                    608:                if (*++q == ':')
                    609:                        q++;
                    610:        }
                    611:        if (*++q == ':') {
                    612:                if (*p == '\0' && (p = *argptr++) == NULL)
                    613:                        error("No arg for -%c option", c);
1.30      christos  614:                optionarg = p;
1.1       cgd       615:                p = NULL;
                    616:        }
                    617:        optptr = p;
                    618:        return c;
                    619: }

CVSweb <webmaster@jp.NetBSD.org>