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