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