options.c revision 59436
11556Srgrimes/*-
21556Srgrimes * Copyright (c) 1991, 1993
31556Srgrimes *	The Regents of the University of California.  All rights reserved.
41556Srgrimes *
51556Srgrimes * This code is derived from software contributed to Berkeley by
61556Srgrimes * Kenneth Almquist.
71556Srgrimes *
81556Srgrimes * Redistribution and use in source and binary forms, with or without
91556Srgrimes * modification, are permitted provided that the following conditions
101556Srgrimes * are met:
111556Srgrimes * 1. Redistributions of source code must retain the above copyright
121556Srgrimes *    notice, this list of conditions and the following disclaimer.
131556Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
141556Srgrimes *    notice, this list of conditions and the following disclaimer in the
151556Srgrimes *    documentation and/or other materials provided with the distribution.
161556Srgrimes * 3. All advertising materials mentioning features or use of this software
171556Srgrimes *    must display the following acknowledgement:
181556Srgrimes *	This product includes software developed by the University of
191556Srgrimes *	California, Berkeley and its contributors.
201556Srgrimes * 4. Neither the name of the University nor the names of its contributors
211556Srgrimes *    may be used to endorse or promote products derived from this software
221556Srgrimes *    without specific prior written permission.
231556Srgrimes *
241556Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
251556Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
261556Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
271556Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
281556Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
291556Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
301556Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
311556Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
321556Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
331556Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
341556Srgrimes * SUCH DAMAGE.
351556Srgrimes */
361556Srgrimes
371556Srgrimes#ifndef lint
3836150Scharnier#if 0
3936150Scharnierstatic char sccsid[] = "@(#)options.c	8.2 (Berkeley) 5/4/95";
4036150Scharnier#endif
4136150Scharnierstatic const char rcsid[] =
4250471Speter  "$FreeBSD: head/bin/sh/options.c 59436 2000-04-20 09:49:16Z cracauer $";
431556Srgrimes#endif /* not lint */
441556Srgrimes
4517987Speter#include <signal.h>
4617987Speter#include <unistd.h>
4717987Speter#include <stdlib.h>
4817987Speter
491556Srgrimes#include "shell.h"
501556Srgrimes#define DEFINE_OPTIONS
511556Srgrimes#include "options.h"
521556Srgrimes#undef DEFINE_OPTIONS
531556Srgrimes#include "nodes.h"	/* for other header files */
541556Srgrimes#include "eval.h"
551556Srgrimes#include "jobs.h"
561556Srgrimes#include "input.h"
571556Srgrimes#include "output.h"
581556Srgrimes#include "trap.h"
591556Srgrimes#include "var.h"
601556Srgrimes#include "memalloc.h"
611556Srgrimes#include "error.h"
621556Srgrimes#include "mystring.h"
6317987Speter#ifndef NO_HISTORY
6417987Speter#include "myhistedit.h"
6517987Speter#endif
661556Srgrimes
671556Srgrimeschar *arg0;			/* value of $0 */
681556Srgrimesstruct shparam shellparam;	/* current positional parameters */
691556Srgrimeschar **argptr;			/* argument list for builtin commands */
7059436Scracauerchar *shoptarg;			/* set by nextopt (like getopt) */
711556Srgrimeschar *optptr;			/* used by nextopt */
721556Srgrimes
731556Srgrimeschar *minusc;			/* argument to -c option */
741556Srgrimes
751556Srgrimes
7617987SpeterSTATIC void options __P((int));
7717987SpeterSTATIC void minus_o __P((char *, int));
7817987SpeterSTATIC void setoption __P((int, int));
7920425SsteveSTATIC int getopts __P((char *, char *, char **, char ***, char **));
801556Srgrimes
811556Srgrimes
821556Srgrimes/*
831556Srgrimes * Process the shell command line arguments.
841556Srgrimes */
851556Srgrimes
861556Srgrimesvoid
871556Srgrimesprocargs(argc, argv)
8817987Speter	int argc;
891556Srgrimes	char **argv;
9017987Speter{
911556Srgrimes	int i;
921556Srgrimes
931556Srgrimes	argptr = argv;
941556Srgrimes	if (argc > 0)
951556Srgrimes		argptr++;
961556Srgrimes	for (i = 0; i < NOPTS; i++)
971556Srgrimes		optlist[i].val = 2;
9819240Ssteve	privileged = (getuid() != geteuid() || getgid() != getegid());
991556Srgrimes	options(1);
1001556Srgrimes	if (*argptr == NULL && minusc == NULL)
1011556Srgrimes		sflag = 1;
1021556Srgrimes	if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
1031556Srgrimes		iflag = 1;
1041556Srgrimes	if (mflag == 2)
1051556Srgrimes		mflag = iflag;
1061556Srgrimes	for (i = 0; i < NOPTS; i++)
1071556Srgrimes		if (optlist[i].val == 2)
1081556Srgrimes			optlist[i].val = 0;
1091556Srgrimes	arg0 = argv[0];
1101556Srgrimes	if (sflag == 0 && minusc == NULL) {
1111556Srgrimes		commandname = arg0 = *argptr++;
1121556Srgrimes		setinputfile(commandname, 0);
1131556Srgrimes	}
11420425Ssteve	/* POSIX 1003.2: first arg after -c cmd is $0, remainder $1... */
11525227Ssteve	if (argptr && minusc && *argptr)
11611111Sjoerg		arg0 = *argptr++;
11720742Ssteve
1181556Srgrimes	shellparam.p = argptr;
11920742Ssteve	shellparam.reset = 1;
1201556Srgrimes	/* assert(shellparam.malloc == 0 && shellparam.nparam == 0); */
1211556Srgrimes	while (*argptr) {
1221556Srgrimes		shellparam.nparam++;
1231556Srgrimes		argptr++;
1241556Srgrimes	}
1251556Srgrimes	optschanged();
1261556Srgrimes}
1271556Srgrimes
1281556Srgrimes
12917987Spetervoid
13017987Speteroptschanged()
13117987Speter{
1321556Srgrimes	setinteractive(iflag);
13317987Speter#ifndef NO_HISTORY
1341556Srgrimes	histedit();
13517987Speter#endif
1361556Srgrimes	setjobctl(mflag);
1371556Srgrimes}
1381556Srgrimes
1391556Srgrimes/*
1401556Srgrimes * Process shell options.  The global variable argptr contains a pointer
1411556Srgrimes * to the argument list; we advance it past the options.
1421556Srgrimes */
1431556Srgrimes
1441556SrgrimesSTATIC void
14520425Ssteveoptions(cmdline)
14617987Speter	int cmdline;
14717987Speter{
14825227Ssteve	char *p;
1491556Srgrimes	int val;
1501556Srgrimes	int c;
1511556Srgrimes
1521556Srgrimes	if (cmdline)
1531556Srgrimes		minusc = NULL;
1541556Srgrimes	while ((p = *argptr) != NULL) {
1551556Srgrimes		argptr++;
1561556Srgrimes		if ((c = *p++) == '-') {
1571556Srgrimes			val = 1;
15817987Speter                        if (p[0] == '\0' || (p[0] == '-' && p[1] == '\0')) {
1591556Srgrimes                                if (!cmdline) {
1601556Srgrimes                                        /* "-" means turn off -x and -v */
1611556Srgrimes                                        if (p[0] == '\0')
1621556Srgrimes                                                xflag = vflag = 0;
1631556Srgrimes                                        /* "--" means reset params */
1641556Srgrimes                                        else if (*argptr == NULL)
16517987Speter						setparam(argptr);
1661556Srgrimes                                }
1671556Srgrimes				break;	  /* "-" or  "--" terminates options */
1681556Srgrimes			}
1691556Srgrimes		} else if (c == '+') {
1701556Srgrimes			val = 0;
1711556Srgrimes		} else {
1721556Srgrimes			argptr--;
1731556Srgrimes			break;
1741556Srgrimes		}
1751556Srgrimes		while ((c = *p++) != '\0') {
1761556Srgrimes			if (c == 'c' && cmdline) {
1771556Srgrimes				char *q;
1781556Srgrimes#ifdef NOHACK	/* removing this code allows sh -ce 'foo' for compat */
1791556Srgrimes				if (*p == '\0')
1801556Srgrimes#endif
1811556Srgrimes					q = *argptr++;
1821556Srgrimes				if (q == NULL || minusc != NULL)
1831556Srgrimes					error("Bad -c option");
1841556Srgrimes				minusc = q;
1851556Srgrimes#ifdef NOHACK
1861556Srgrimes				break;
1871556Srgrimes#endif
1881556Srgrimes			} else if (c == 'o') {
1891556Srgrimes				minus_o(*argptr, val);
1901556Srgrimes				if (*argptr)
1911556Srgrimes					argptr++;
1921556Srgrimes			} else {
19319240Ssteve				if (c == 'p' && !val && privileged) {
19419240Ssteve					(void) setuid(getuid());
19519240Ssteve					(void) setgid(getgid());
19619240Ssteve				}
1971556Srgrimes				setoption(c, val);
1981556Srgrimes			}
1991556Srgrimes		}
2001556Srgrimes	}
2011556Srgrimes}
2021556Srgrimes
2031556SrgrimesSTATIC void
2041556Srgrimesminus_o(name, val)
2051556Srgrimes	char *name;
2061556Srgrimes	int val;
2071556Srgrimes{
2081556Srgrimes	int i;
2091556Srgrimes
2101556Srgrimes	if (name == NULL) {
2111556Srgrimes		out1str("Current option settings\n");
2121556Srgrimes		for (i = 0; i < NOPTS; i++)
2131556Srgrimes			out1fmt("%-16s%s\n", optlist[i].name,
2141556Srgrimes				optlist[i].val ? "on" : "off");
2151556Srgrimes	} else {
2161556Srgrimes		for (i = 0; i < NOPTS; i++)
2171556Srgrimes			if (equal(name, optlist[i].name)) {
21819240Ssteve				if (!val && privileged && equal(name, "privileged")) {
21919240Ssteve					(void) setuid(getuid());
22019240Ssteve					(void) setgid(getgid());
22119240Ssteve				}
2221556Srgrimes				setoption(optlist[i].letter, val);
2231556Srgrimes				return;
2241556Srgrimes			}
2251556Srgrimes		error("Illegal option -o %s", name);
2261556Srgrimes	}
2271556Srgrimes}
2281556Srgrimes
2298855Srgrimes
2301556SrgrimesSTATIC void
2311556Srgrimessetoption(flag, val)
2321556Srgrimes	char flag;
2331556Srgrimes	int val;
2341556Srgrimes	{
2351556Srgrimes	int i;
2361556Srgrimes
2371556Srgrimes	for (i = 0; i < NOPTS; i++)
2381556Srgrimes		if (optlist[i].letter == flag) {
2391556Srgrimes			optlist[i].val = val;
2401556Srgrimes			if (val) {
2411556Srgrimes				/* #%$ hack for ksh semantics */
2421556Srgrimes				if (flag == 'V')
2431556Srgrimes					Eflag = 0;
2441556Srgrimes				else if (flag == 'E')
2451556Srgrimes					Vflag = 0;
2461556Srgrimes			}
2471556Srgrimes			return;
2481556Srgrimes		}
2491556Srgrimes	error("Illegal option -%c", flag);
2501556Srgrimes}
2511556Srgrimes
2521556Srgrimes
2531556Srgrimes
2541556Srgrimes#ifdef mkinit
2551556SrgrimesINCLUDE "options.h"
2561556Srgrimes
2571556SrgrimesSHELLPROC {
2581556Srgrimes	int i;
2591556Srgrimes
2601556Srgrimes	for (i = 0; i < NOPTS; i++)
2611556Srgrimes		optlist[i].val = 0;
2621556Srgrimes	optschanged();
2631556Srgrimes
2641556Srgrimes}
2651556Srgrimes#endif
2661556Srgrimes
2671556Srgrimes
2681556Srgrimes/*
2691556Srgrimes * Set the shell parameters.
2701556Srgrimes */
2711556Srgrimes
2721556Srgrimesvoid
2731556Srgrimessetparam(argv)
2741556Srgrimes	char **argv;
2751556Srgrimes	{
2761556Srgrimes	char **newparam;
2771556Srgrimes	char **ap;
2781556Srgrimes	int nparam;
2791556Srgrimes
2801556Srgrimes	for (nparam = 0 ; argv[nparam] ; nparam++);
2811556Srgrimes	ap = newparam = ckmalloc((nparam + 1) * sizeof *ap);
2821556Srgrimes	while (*argv) {
2831556Srgrimes		*ap++ = savestr(*argv++);
2841556Srgrimes	}
2851556Srgrimes	*ap = NULL;
2861556Srgrimes	freeparam(&shellparam);
2871556Srgrimes	shellparam.malloc = 1;
2881556Srgrimes	shellparam.nparam = nparam;
2891556Srgrimes	shellparam.p = newparam;
2901556Srgrimes	shellparam.optnext = NULL;
2911556Srgrimes}
2921556Srgrimes
2931556Srgrimes
2941556Srgrimes/*
2951556Srgrimes * Free the list of positional parameters.
2961556Srgrimes */
2971556Srgrimes
2981556Srgrimesvoid
2991556Srgrimesfreeparam(param)
3001556Srgrimes	struct shparam *param;
3011556Srgrimes	{
3021556Srgrimes	char **ap;
3031556Srgrimes
3041556Srgrimes	if (param->malloc) {
3051556Srgrimes		for (ap = param->p ; *ap ; ap++)
3061556Srgrimes			ckfree(*ap);
3071556Srgrimes		ckfree(param->p);
3081556Srgrimes	}
3091556Srgrimes}
3101556Srgrimes
3111556Srgrimes
3121556Srgrimes
3131556Srgrimes/*
3141556Srgrimes * The shift builtin command.
3151556Srgrimes */
3161556Srgrimes
31717987Speterint
31817987Spetershiftcmd(argc, argv)
31917987Speter	int argc;
32020425Ssteve	char **argv;
32117987Speter{
3221556Srgrimes	int n;
3231556Srgrimes	char **ap1, **ap2;
3241556Srgrimes
3251556Srgrimes	n = 1;
3261556Srgrimes	if (argc > 1)
3271556Srgrimes		n = number(argv[1]);
3281556Srgrimes	if (n > shellparam.nparam)
3291556Srgrimes		error("can't shift that many");
3301556Srgrimes	INTOFF;
3311556Srgrimes	shellparam.nparam -= n;
3321556Srgrimes	for (ap1 = shellparam.p ; --n >= 0 ; ap1++) {
3331556Srgrimes		if (shellparam.malloc)
3341556Srgrimes			ckfree(*ap1);
3351556Srgrimes	}
3361556Srgrimes	ap2 = shellparam.p;
3371556Srgrimes	while ((*ap2++ = *ap1++) != NULL);
3381556Srgrimes	shellparam.optnext = NULL;
3391556Srgrimes	INTON;
3401556Srgrimes	return 0;
3411556Srgrimes}
3421556Srgrimes
3431556Srgrimes
3441556Srgrimes
3451556Srgrimes/*
3461556Srgrimes * The set command builtin.
3471556Srgrimes */
3481556Srgrimes
34917987Speterint
35017987Spetersetcmd(argc, argv)
35117987Speter	int argc;
35220425Ssteve	char **argv;
35317987Speter{
3541556Srgrimes	if (argc == 1)
3551556Srgrimes		return showvarscmd(argc, argv);
3561556Srgrimes	INTOFF;
3571556Srgrimes	options(0);
3581556Srgrimes	optschanged();
3591556Srgrimes	if (*argptr != NULL) {
3601556Srgrimes		setparam(argptr);
3611556Srgrimes	}
3621556Srgrimes	INTON;
3631556Srgrimes	return 0;
3641556Srgrimes}
3651556Srgrimes
3661556Srgrimes
36720425Sstevevoid
36820425Sstevegetoptsreset(value)
36920425Ssteve	const char *value;
37020425Ssteve{
37120425Ssteve	if (number(value) == 1) {
37220425Ssteve		shellparam.optnext = NULL;
37320425Ssteve		shellparam.reset = 1;
37420425Ssteve	}
37520425Ssteve}
37620425Ssteve
3771556Srgrimes/*
3781556Srgrimes * The getopts builtin.  Shellparam.optnext points to the next argument
3791556Srgrimes * to be processed.  Shellparam.optptr points to the next character to
3801556Srgrimes * be processed in the current argument.  If shellparam.optnext is NULL,
3811556Srgrimes * then it's the first time getopts has been called.
3821556Srgrimes */
3831556Srgrimes
38417987Speterint
38517987Spetergetoptscmd(argc, argv)
38617987Speter	int argc;
38720425Ssteve	char **argv;
38817987Speter{
38920425Ssteve	char **optbase = NULL;
39020425Ssteve
39120425Ssteve	if (argc < 3)
39220425Ssteve		error("Usage: getopts optstring var [arg]");
39320425Ssteve	else if (argc == 3)
39420425Ssteve		optbase = shellparam.p;
39520425Ssteve	else
39620425Ssteve		optbase = &argv[3];
39720425Ssteve
39820425Ssteve	if (shellparam.reset == 1) {
39920425Ssteve		shellparam.optnext = optbase;
40020425Ssteve		shellparam.optptr = NULL;
40120425Ssteve		shellparam.reset = 0;
40220425Ssteve	}
40320425Ssteve
40420425Ssteve	return getopts(argv[1], argv[2], optbase, &shellparam.optnext,
40520425Ssteve		       &shellparam.optptr);
40620425Ssteve}
40720425Ssteve
40820425SsteveSTATIC int
40920425Sstevegetopts(optstr, optvar, optfirst, optnext, optptr)
41020425Ssteve	char *optstr;
41120425Ssteve	char *optvar;
41220425Ssteve	char **optfirst;
41320425Ssteve	char ***optnext;
41420425Ssteve	char **optptr;
41520425Ssteve{
41625227Ssteve	char *p, *q;
41720425Ssteve	char c = '?';
41820425Ssteve	int done = 0;
41920425Ssteve	int ind = 0;
42020425Ssteve	int err = 0;
4211556Srgrimes	char s[10];
4221556Srgrimes
42320425Ssteve	if ((p = *optptr) == NULL || *p == '\0') {
42420425Ssteve		/* Current word is done, advance */
42520425Ssteve		if (*optnext == NULL)
42620425Ssteve			return 1;
42720425Ssteve		p = **optnext;
4281556Srgrimes		if (p == NULL || *p != '-' || *++p == '\0') {
4291556Srgrimesatend:
43020742Ssteve			ind = *optnext - optfirst + 1;
43120425Ssteve			*optnext = NULL;
43220742Ssteve			p = NULL;
43320425Ssteve			done = 1;
43420425Ssteve			goto out;
4351556Srgrimes		}
43620425Ssteve		(*optnext)++;
4371556Srgrimes		if (p[0] == '-' && p[1] == '\0')	/* check for "--" */
4381556Srgrimes			goto atend;
4391556Srgrimes	}
44020425Ssteve
4411556Srgrimes	c = *p++;
44220425Ssteve	for (q = optstr; *q != c; ) {
4431556Srgrimes		if (*q == '\0') {
44420425Ssteve			if (optstr[0] == ':') {
44520425Ssteve				s[0] = c;
44620425Ssteve				s[1] = '\0';
44720425Ssteve				err |= setvarsafe("OPTARG", s, 0);
44820425Ssteve			}
44920425Ssteve			else {
45020425Ssteve				out1fmt("Illegal option -%c\n", c);
45120425Ssteve				(void) unsetvar("OPTARG");
45220425Ssteve			}
4531556Srgrimes			c = '?';
45420425Ssteve			goto bad;
4551556Srgrimes		}
4561556Srgrimes		if (*++q == ':')
4571556Srgrimes			q++;
4581556Srgrimes	}
45920425Ssteve
4601556Srgrimes	if (*++q == ':') {
46120425Ssteve		if (*p == '\0' && (p = **optnext) == NULL) {
46220425Ssteve			if (optstr[0] == ':') {
46320425Ssteve				s[0] = c;
46420425Ssteve				s[1] = '\0';
46520425Ssteve				err |= setvarsafe("OPTARG", s, 0);
46620425Ssteve				c = ':';
46720425Ssteve			}
46820425Ssteve			else {
46920425Ssteve				out1fmt("No arg for -%c option\n", c);
47020425Ssteve				(void) unsetvar("OPTARG");
47120425Ssteve				c = '?';
47220425Ssteve			}
47320425Ssteve			goto bad;
4741556Srgrimes		}
47520425Ssteve
47620425Ssteve		if (p == **optnext)
47720425Ssteve			(*optnext)++;
47820425Ssteve		setvarsafe("OPTARG", p, 0);
4791556Srgrimes		p = NULL;
4801556Srgrimes	}
48120425Ssteve	else
48220425Ssteve		setvarsafe("OPTARG", "", 0);
48320425Ssteve	ind = *optnext - optfirst + 1;
48420425Ssteve	goto out;
48520425Ssteve
48620425Sstevebad:
48720425Ssteve	ind = 1;
48820425Ssteve	*optnext = NULL;
48920425Ssteve	p = NULL;
4901556Srgrimesout:
49120425Ssteve	*optptr = p;
49220425Ssteve	fmtstr(s, sizeof(s), "%d", ind);
49320425Ssteve	err |= setvarsafe("OPTIND", s, VNOFUNC);
4941556Srgrimes	s[0] = c;
4951556Srgrimes	s[1] = '\0';
49620425Ssteve	err |= setvarsafe(optvar, s, 0);
49720425Ssteve	if (err) {
49820425Ssteve		*optnext = NULL;
49920425Ssteve		*optptr = NULL;
50020425Ssteve		flushall();
50120425Ssteve		exraise(EXERROR);
50220425Ssteve	}
50320425Ssteve	return done;
5041556Srgrimes}
5051556Srgrimes
5061556Srgrimes/*
5071556Srgrimes * XXX - should get rid of.  have all builtins use getopt(3).  the
5081556Srgrimes * library getopt must have the BSD extension static variable "optreset"
5091556Srgrimes * otherwise it can't be used within the shell safely.
5101556Srgrimes *
5111556Srgrimes * Standard option processing (a la getopt) for builtin routines.  The
5121556Srgrimes * only argument that is passed to nextopt is the option string; the
5131556Srgrimes * other arguments are unnecessary.  It return the character, or '\0' on
5141556Srgrimes * end of input.
5151556Srgrimes */
5161556Srgrimes
5171556Srgrimesint
5181556Srgrimesnextopt(optstring)
5191556Srgrimes	char *optstring;
5201556Srgrimes	{
52125227Ssteve	char *p, *q;
5221556Srgrimes	char c;
5231556Srgrimes
5241556Srgrimes	if ((p = optptr) == NULL || *p == '\0') {
5251556Srgrimes		p = *argptr;
5261556Srgrimes		if (p == NULL || *p != '-' || *++p == '\0')
5271556Srgrimes			return '\0';
5281556Srgrimes		argptr++;
5291556Srgrimes		if (p[0] == '-' && p[1] == '\0')	/* check for "--" */
5301556Srgrimes			return '\0';
5311556Srgrimes	}
5321556Srgrimes	c = *p++;
5331556Srgrimes	for (q = optstring ; *q != c ; ) {
5341556Srgrimes		if (*q == '\0')
5351556Srgrimes			error("Illegal option -%c", c);
5361556Srgrimes		if (*++q == ':')
5371556Srgrimes			q++;
5381556Srgrimes	}
5391556Srgrimes	if (*++q == ':') {
5401556Srgrimes		if (*p == '\0' && (p = *argptr++) == NULL)
5411556Srgrimes			error("No arg for -%c option", c);
54259436Scracauer		shoptarg = p;
5431556Srgrimes		p = NULL;
5441556Srgrimes	}
5451556Srgrimes	optptr = p;
5461556Srgrimes	return c;
5471556Srgrimes}
548