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