xref: /csrg-svn/bin/sh/options.c (revision 47135)
1*47135Sbostic /*-
2*47135Sbostic  * Copyright (c) 1991 The Regents of the University of California.
3*47135Sbostic  * All rights reserved.
4*47135Sbostic  *
5*47135Sbostic  * This code is derived from software contributed to Berkeley by
6*47135Sbostic  * Kenneth Almquist.
7*47135Sbostic  *
8*47135Sbostic  * %sccs.include.redist.c%
9*47135Sbostic  */
10*47135Sbostic 
11*47135Sbostic #ifndef lint
12*47135Sbostic static char sccsid[] = "@(#)options.c	5.1 (Berkeley) 03/07/91";
13*47135Sbostic #endif /* not lint */
14*47135Sbostic 
15*47135Sbostic #include "shell.h"
16*47135Sbostic #define DEFINE_OPTIONS
17*47135Sbostic #include "options.h"
18*47135Sbostic #undef DEFINE_OPTIONS
19*47135Sbostic #include "nodes.h"	/* for other header files */
20*47135Sbostic #include "eval.h"
21*47135Sbostic #include "jobs.h"
22*47135Sbostic #include "input.h"
23*47135Sbostic #include "output.h"
24*47135Sbostic #include "trap.h"
25*47135Sbostic #include "var.h"
26*47135Sbostic #include "memalloc.h"
27*47135Sbostic #include "error.h"
28*47135Sbostic #include "mystring.h"
29*47135Sbostic 
30*47135Sbostic char *arg0;			/* value of $0 */
31*47135Sbostic struct shparam shellparam;	/* current positional parameters */
32*47135Sbostic char **argptr;			/* argument list for builtin commands */
33*47135Sbostic char *optarg;			/* set by nextopt (like getopt) */
34*47135Sbostic char *optptr;			/* used by nextopt */
35*47135Sbostic 
36*47135Sbostic char *minusc;			/* argument to -c option */
37*47135Sbostic 
38*47135Sbostic 
39*47135Sbostic #ifdef __STDC__
40*47135Sbostic STATIC void options(int);
41*47135Sbostic STATIC void setoption(int, int);
42*47135Sbostic #else
43*47135Sbostic STATIC void options();
44*47135Sbostic STATIC void setoption();
45*47135Sbostic #endif
46*47135Sbostic 
47*47135Sbostic 
48*47135Sbostic 
49*47135Sbostic /*
50*47135Sbostic  * Process the shell command line arguments.
51*47135Sbostic  */
52*47135Sbostic 
53*47135Sbostic void
54*47135Sbostic procargs(argc, argv)
55*47135Sbostic 	char **argv;
56*47135Sbostic 	{
57*47135Sbostic 	char *p;
58*47135Sbostic 
59*47135Sbostic 	argptr = argv;
60*47135Sbostic 	if (argc > 0)
61*47135Sbostic 		argptr++;
62*47135Sbostic 	for (p = optval ; p < optval + sizeof optval - 1 ; p++)
63*47135Sbostic 		*p = 2;
64*47135Sbostic 	options(1);
65*47135Sbostic 	if (*argptr == NULL && minusc == NULL)
66*47135Sbostic 		sflag = 1;
67*47135Sbostic 	if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
68*47135Sbostic 		iflag = 1;
69*47135Sbostic 	if (jflag == 2)
70*47135Sbostic 		jflag = iflag;
71*47135Sbostic 	for (p = optval ; p < optval + sizeof optval - 1 ; p++)
72*47135Sbostic 		if (*p == 2)
73*47135Sbostic 			*p = 0;
74*47135Sbostic 	arg0 = argv[0];
75*47135Sbostic 	if (sflag == 0 && minusc == NULL) {
76*47135Sbostic 		commandname = arg0 = *argptr++;
77*47135Sbostic 		setinputfile(commandname, 0);
78*47135Sbostic 	}
79*47135Sbostic 	shellparam.p = argptr;
80*47135Sbostic 	/* assert(shellparam.malloc == 0 && shellparam.nparam == 0); */
81*47135Sbostic 	while (*argptr) {
82*47135Sbostic 		shellparam.nparam++;
83*47135Sbostic 		argptr++;
84*47135Sbostic 	}
85*47135Sbostic 	setinteractive(iflag);
86*47135Sbostic 	setjobctl(jflag);
87*47135Sbostic }
88*47135Sbostic 
89*47135Sbostic 
90*47135Sbostic 
91*47135Sbostic /*
92*47135Sbostic  * Process shell options.  The global variable argptr contains a pointer
93*47135Sbostic  * to the argument list; we advance it past the options.
94*47135Sbostic  */
95*47135Sbostic 
96*47135Sbostic STATIC void
97*47135Sbostic options(cmdline) {
98*47135Sbostic 	register char *p;
99*47135Sbostic 	int val;
100*47135Sbostic 	int c;
101*47135Sbostic 
102*47135Sbostic 	minusc = NULL;
103*47135Sbostic 	while ((p = *argptr) != NULL) {
104*47135Sbostic 		argptr++;
105*47135Sbostic 		if ((c = *p++) == '-') {
106*47135Sbostic 			val = 1;
107*47135Sbostic 			if (p[0] == '\0' || p[0] == '-' && p[1] == '\0')
108*47135Sbostic 				break;	  /* "-" or  "--" terminates options */
109*47135Sbostic 		} else if (c == '+') {
110*47135Sbostic 			val = 0;
111*47135Sbostic 		} else {
112*47135Sbostic 			argptr--;
113*47135Sbostic 			break;
114*47135Sbostic 		}
115*47135Sbostic 		while ((c = *p++) != '\0') {
116*47135Sbostic 			if (c == 'c' && cmdline) {
117*47135Sbostic 				char *q;
118*47135Sbostic #ifdef NOHACK
119*47135Sbostic 				if (*p == '\0')
120*47135Sbostic #endif
121*47135Sbostic 					q = *argptr++;
122*47135Sbostic 				if (q == NULL || minusc != NULL)
123*47135Sbostic 					error("Bad -c option");
124*47135Sbostic 				minusc = q;
125*47135Sbostic #ifdef NOHACK
126*47135Sbostic 				break;
127*47135Sbostic #endif
128*47135Sbostic 			} else {
129*47135Sbostic 				setoption(c, val);
130*47135Sbostic 			}
131*47135Sbostic 		}
132*47135Sbostic 		if (! cmdline)
133*47135Sbostic 			break;
134*47135Sbostic 	}
135*47135Sbostic }
136*47135Sbostic 
137*47135Sbostic 
138*47135Sbostic STATIC void
139*47135Sbostic setoption(flag, val)
140*47135Sbostic 	char flag;
141*47135Sbostic 	int val;
142*47135Sbostic 	{
143*47135Sbostic 	register char *p;
144*47135Sbostic 
145*47135Sbostic 	if ((p = strchr(optchar, flag)) == NULL)
146*47135Sbostic 		error("Illegal option -%c", flag);
147*47135Sbostic 	optval[p - optchar] = val;
148*47135Sbostic }
149*47135Sbostic 
150*47135Sbostic 
151*47135Sbostic 
152*47135Sbostic #ifdef mkinit
153*47135Sbostic INCLUDE "options.h"
154*47135Sbostic 
155*47135Sbostic SHELLPROC {
156*47135Sbostic 	char *p;
157*47135Sbostic 
158*47135Sbostic 	for (p = optval ; p < optval + sizeof optval ; p++)
159*47135Sbostic 		*p = 0;
160*47135Sbostic }
161*47135Sbostic #endif
162*47135Sbostic 
163*47135Sbostic 
164*47135Sbostic /*
165*47135Sbostic  * Set the shell parameters.
166*47135Sbostic  */
167*47135Sbostic 
168*47135Sbostic void
169*47135Sbostic setparam(argv)
170*47135Sbostic 	char **argv;
171*47135Sbostic 	{
172*47135Sbostic 	char **newparam;
173*47135Sbostic 	char **ap;
174*47135Sbostic 	int nparam;
175*47135Sbostic 
176*47135Sbostic 	for (nparam = 0 ; argv[nparam] ; nparam++);
177*47135Sbostic 	ap = newparam = ckmalloc((nparam + 1) * sizeof *ap);
178*47135Sbostic 	while (*argv) {
179*47135Sbostic 		*ap++ = savestr(*argv++);
180*47135Sbostic 	}
181*47135Sbostic 	*ap = NULL;
182*47135Sbostic 	freeparam(&shellparam);
183*47135Sbostic 	shellparam.malloc = 1;
184*47135Sbostic 	shellparam.nparam = nparam;
185*47135Sbostic 	shellparam.p = newparam;
186*47135Sbostic 	shellparam.optnext = NULL;
187*47135Sbostic }
188*47135Sbostic 
189*47135Sbostic 
190*47135Sbostic /*
191*47135Sbostic  * Free the list of positional parameters.
192*47135Sbostic  */
193*47135Sbostic 
194*47135Sbostic void
195*47135Sbostic freeparam(param)
196*47135Sbostic 	struct shparam *param;
197*47135Sbostic 	{
198*47135Sbostic 	char **ap;
199*47135Sbostic 
200*47135Sbostic 	if (param->malloc) {
201*47135Sbostic 		for (ap = param->p ; *ap ; ap++)
202*47135Sbostic 			ckfree(*ap);
203*47135Sbostic 		ckfree(param->p);
204*47135Sbostic 	}
205*47135Sbostic }
206*47135Sbostic 
207*47135Sbostic 
208*47135Sbostic 
209*47135Sbostic /*
210*47135Sbostic  * The shift builtin command.
211*47135Sbostic  */
212*47135Sbostic 
213*47135Sbostic shiftcmd(argc, argv)  char **argv; {
214*47135Sbostic 	int n;
215*47135Sbostic 	char **ap1, **ap2;
216*47135Sbostic 
217*47135Sbostic 	n = 1;
218*47135Sbostic 	if (argc > 1)
219*47135Sbostic 		n = number(argv[1]);
220*47135Sbostic 	if (n > shellparam.nparam)
221*47135Sbostic 		n = shellparam.nparam;
222*47135Sbostic 	INTOFF;
223*47135Sbostic 	shellparam.nparam -= n;
224*47135Sbostic 	for (ap1 = shellparam.p ; --n >= 0 ; ap1++) {
225*47135Sbostic 		if (shellparam.malloc)
226*47135Sbostic 			ckfree(*ap1);
227*47135Sbostic 	}
228*47135Sbostic 	ap2 = shellparam.p;
229*47135Sbostic 	while ((*ap2++ = *ap1++) != NULL);
230*47135Sbostic 	shellparam.optnext = NULL;
231*47135Sbostic 	INTON;
232*47135Sbostic 	return 0;
233*47135Sbostic }
234*47135Sbostic 
235*47135Sbostic 
236*47135Sbostic 
237*47135Sbostic /*
238*47135Sbostic  * The set command builtin.
239*47135Sbostic  */
240*47135Sbostic 
241*47135Sbostic setcmd(argc, argv)  char **argv; {
242*47135Sbostic 	if (argc == 1)
243*47135Sbostic 		return showvarscmd(argc, argv);
244*47135Sbostic 	INTOFF;
245*47135Sbostic 	options(0);
246*47135Sbostic 	setinteractive(iflag);
247*47135Sbostic 	setjobctl(jflag);
248*47135Sbostic 	if (*argptr != NULL) {
249*47135Sbostic 		setparam(argptr);
250*47135Sbostic 	}
251*47135Sbostic 	INTON;
252*47135Sbostic 	return 0;
253*47135Sbostic }
254*47135Sbostic 
255*47135Sbostic 
256*47135Sbostic /*
257*47135Sbostic  * The getopts builtin.  Shellparam.optnext points to the next argument
258*47135Sbostic  * to be processed.  Shellparam.optptr points to the next character to
259*47135Sbostic  * be processed in the current argument.  If shellparam.optnext is NULL,
260*47135Sbostic  * then it's the first time getopts has been called.
261*47135Sbostic  */
262*47135Sbostic 
263*47135Sbostic getoptscmd(argc, argv)  char **argv; {
264*47135Sbostic 	register char *p, *q;
265*47135Sbostic 	char c;
266*47135Sbostic 	char s[10];
267*47135Sbostic 
268*47135Sbostic 	if (argc != 3)
269*47135Sbostic 		error("Usage: getopts optstring var");
270*47135Sbostic 	if (shellparam.optnext == NULL) {
271*47135Sbostic 		shellparam.optnext = shellparam.p;
272*47135Sbostic 		shellparam.optptr = NULL;
273*47135Sbostic 	}
274*47135Sbostic 	if ((p = shellparam.optptr) == NULL || *p == '\0') {
275*47135Sbostic 		p = *shellparam.optnext;
276*47135Sbostic 		if (p == NULL || *p != '-' || *++p == '\0') {
277*47135Sbostic atend:
278*47135Sbostic 			fmtstr(s, 10, "%d", shellparam.optnext - shellparam.p + 1);
279*47135Sbostic 			setvar("OPTIND", s, 0);
280*47135Sbostic 			shellparam.optnext = NULL;
281*47135Sbostic 			return 1;
282*47135Sbostic 		}
283*47135Sbostic 		shellparam.optnext++;
284*47135Sbostic 		if (p[0] == '-' && p[1] == '\0')	/* check for "--" */
285*47135Sbostic 			goto atend;
286*47135Sbostic 	}
287*47135Sbostic 	c = *p++;
288*47135Sbostic 	for (q = argv[1] ; *q != c ; ) {
289*47135Sbostic 		if (*q == '\0') {
290*47135Sbostic 			out1fmt("Illegal option -%c\n", c);
291*47135Sbostic 			c = '?';
292*47135Sbostic 			goto out;
293*47135Sbostic 		}
294*47135Sbostic 		if (*++q == ':')
295*47135Sbostic 			q++;
296*47135Sbostic 	}
297*47135Sbostic 	if (*++q == ':') {
298*47135Sbostic 		if (*p == '\0' && (p = *shellparam.optnext) == NULL) {
299*47135Sbostic 			out1fmt("No arg for -%c option\n", c);
300*47135Sbostic 			c = '?';
301*47135Sbostic 			goto out;
302*47135Sbostic 		}
303*47135Sbostic 		shellparam.optnext++;
304*47135Sbostic 		setvar("OPTARG", p, 0);
305*47135Sbostic 		p = NULL;
306*47135Sbostic 	}
307*47135Sbostic out:
308*47135Sbostic 	shellparam.optptr = p;
309*47135Sbostic 	s[0] = c;
310*47135Sbostic 	s[1] = '\0';
311*47135Sbostic 	setvar(argv[2], s, 0);
312*47135Sbostic 	return 0;
313*47135Sbostic }
314*47135Sbostic 
315*47135Sbostic 
316*47135Sbostic /*
317*47135Sbostic  * Standard option processing (a la getopt) for builtin routines.  The
318*47135Sbostic  * only argument that is passed to nextopt is the option string; the
319*47135Sbostic  * other arguments are unnecessary.  It return the character, or -1 on
320*47135Sbostic  * end of input.  This routine assumes that all characters in optstring
321*47135Sbostic  * are positive.
322*47135Sbostic  */
323*47135Sbostic 
324*47135Sbostic int
325*47135Sbostic nextopt(optstring)
326*47135Sbostic 	char *optstring;
327*47135Sbostic 	{
328*47135Sbostic 	register char *p, *q;
329*47135Sbostic 	char c;
330*47135Sbostic 
331*47135Sbostic 	if ((p = optptr) == NULL || *p == '\0') {
332*47135Sbostic 		p = *argptr;
333*47135Sbostic 		if (p == NULL || *p != '-' || *++p == '\0')
334*47135Sbostic 			return -1;
335*47135Sbostic 		argptr++;
336*47135Sbostic 		if (p[0] == '-' && p[1] == '\0')	/* check for "--" */
337*47135Sbostic 			return -1;
338*47135Sbostic 	}
339*47135Sbostic 	c = *p++;
340*47135Sbostic 	for (q = optstring ; *q != c ; ) {
341*47135Sbostic 		if (*q == '\0')
342*47135Sbostic 			error("Illegal option -%c", c);
343*47135Sbostic 		if (*++q == ':')
344*47135Sbostic 			q++;
345*47135Sbostic 	}
346*47135Sbostic 	if (*++q == ':') {
347*47135Sbostic 		if (*p == '\0' && (p = *argptr++) == NULL)
348*47135Sbostic 			error("No arg for -%c option", c);
349*47135Sbostic 		optarg = p;
350*47135Sbostic 		p = NULL;
351*47135Sbostic 	}
352*47135Sbostic 	optptr = p;
353*47135Sbostic 	return c;
354*47135Sbostic }
355