1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License").  You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22
23/*
24 * Copyright 1995 Sun Microsystems, Inc.  All rights reserved.
25 * Use is subject to license terms.
26 */
27
28/*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
29/*	  All Rights Reserved  	*/
30
31#pragma ident	"%Z%%M%	%I%	%E% SMI"
32
33/*
34 *	UNIX shell
35 */
36
37#include	"defs.h"
38
39static struct dolnod *copyargs();
40static void freedolh(void);
41extern struct dolnod *freeargs();
42static struct dolnod *dolh;
43
44/* Used to save outermost positional parameters */
45static struct dolnod *globdolh;
46static unsigned char **globdolv;
47static int globdolc;
48
49unsigned char	flagadr[16];
50
51unsigned char	flagchar[] =
52{
53	'x',
54	'n',
55	'v',
56	't',
57	STDFLG,
58	'i',
59	'e',
60	'r',
61	'k',
62	'u',
63	'h',
64	'f',
65	'a',
66	'm',
67	'p',
68	 0
69};
70
71long	flagval[]  =
72{
73	execpr,
74	noexec,
75	readpr,
76	oneflg,
77	stdflg,
78	intflg,
79	errflg,
80	rshflg,
81	keyflg,
82	setflg,
83	hashflg,
84	nofngflg,
85	exportflg,
86	monitorflg,
87	privflg,
88	  0
89};
90
91/* ========	option handling	======== */
92
93
94int
95options(int argc, unsigned char **argv)
96{
97	unsigned char *cp;
98	unsigned char **argp = argv;
99	unsigned char *flagc;
100	unsigned char	*flagp;
101	int		len;
102	wchar_t		wc;
103
104	if (argc > 1 && *argp[1] == '-')
105	{
106		/*
107		 * if first argument is "--" then options are not
108		 * to be changed. Fix for problems getting
109		 * $1 starting with a "-"
110		 */
111
112		cp = argp[1];
113		if (cp[1] == '-')
114		{
115			argp[1] = argp[0];
116			argc--;
117			return(argc);
118		}
119		if (cp[1] == '\0')
120			flags &= ~(execpr|readpr);
121
122		/*
123		 * Step along 'flagchar[]' looking for matches.
124		 * 'sicrp' are not legal with 'set' command.
125		 */
126		cp++;
127		while (*cp) {
128			if ((len = mbtowc(&wc, (char *)cp, MB_LEN_MAX)) <= 0) {
129				len = 1;
130				wc = (unsigned char)*cp;
131				failed(argv[1],badopt);
132			}
133			cp += len;
134
135			flagc = flagchar;
136			while (*flagc && wc != *flagc)
137				flagc++;
138			if (wc == *flagc)
139			{
140				if (eq(argv[0], "set") && any(wc, "sicrp"))
141					failed(argv[1], badopt);
142				else
143				{
144					flags |= flagval[flagc-flagchar];
145					if (flags & errflg)
146						eflag = errflg;
147				}
148			}
149			else if (wc == 'c' && argc > 2 && comdiv == 0)
150			{
151				comdiv = argp[2];
152				argp[1] = argp[0];
153				argp++;
154				argc--;
155			}
156			else
157				failed(argv[1],badopt);
158		}
159		argp[1] = argp[0];
160		argc--;
161	}
162	else if (argc > 1 && *argp[1] == '+')	/* unset flags x, k, t, n, v, e, u */
163	{
164		cp = argp[1];
165		cp++;
166		while (*cp)
167		{
168			if ((len = mbtowc(&wc, (char *)cp, MB_LEN_MAX)) <= 0) {
169				cp++;
170				continue;
171			}
172
173			flagc = flagchar;
174			while (*flagc && wc != *flagc)
175				flagc++;
176			/*
177			 * step through flags
178			 */
179			if (!any(wc, "sicrp") && wc == *flagc) {
180				flags &= ~(flagval[flagc-flagchar]);
181				if (wc == 'e')
182					eflag = 0;
183			}
184			cp += len;
185		}
186		argp[1] = argp[0];
187		argc--;
188	}
189	/*
190	 * set up $-
191	 */
192	flagp = flagadr;
193	if (flags)
194	{
195		flagc = flagchar;
196		while (*flagc)
197		{
198			if (flags & flagval[flagc-flagchar])
199				*flagp++ = *flagc;
200			flagc++;
201		}
202	}
203	*flagp = 0;
204	return(argc);
205}
206
207/*
208 * sets up positional parameters
209 */
210void
211setargs(unsigned char *argi[])
212{
213	unsigned char **argp = argi;	/* count args */
214	int argn = 0;
215
216	while (*argp++ != (unsigned char *)ENDARGS)
217		argn++;
218	/*
219	 * free old ones unless on for loop chain
220	 */
221	freedolh();
222	dolh = copyargs(argi, argn);
223	dolc = argn - 1;
224}
225
226
227static void
228freedolh(void)
229{
230	unsigned char **argp;
231	struct dolnod *argblk;
232
233	if (argblk = dolh)
234	{
235		if ((--argblk->doluse) == 0)
236		{
237			for (argp = argblk->dolarg; *argp != (unsigned char *)ENDARGS; argp++)
238				free(*argp);
239			free(argblk->dolarg);
240			free(argblk);
241		}
242	}
243}
244
245struct dolnod *
246freeargs(blk)
247	struct dolnod *blk;
248{
249	unsigned char **argp;
250	struct dolnod *argr = 0;
251	struct dolnod *argblk;
252	int cnt;
253
254	if (argblk = blk)
255	{
256		argr = argblk->dolnxt;
257		cnt  = --argblk->doluse;
258
259		if (argblk == dolh)
260		{
261			if (cnt == 1)
262				return(argr);
263			else
264				return(argblk);
265		}
266		else
267		{
268			if (cnt == 0)
269			{
270				for (argp = argblk->dolarg; *argp != (unsigned char *)ENDARGS; argp++)
271					free(*argp);
272				free(argblk->dolarg);
273				free(argblk);
274			}
275		}
276	}
277	return(argr);
278}
279
280static struct dolnod *
281copyargs(from, n)
282	unsigned char	*from[];
283{
284	struct dolnod *np = (struct dolnod *)alloc(sizeof (struct dolnod));
285	unsigned char **fp = from;
286	unsigned char **pp;
287
288	np -> dolnxt = 0;
289	np->doluse = 1;	/* use count */
290	pp = np->dolarg = (unsigned char **)alloc((n+1)*sizeof(char *));
291	dolv = pp;
292
293	while (n--)
294		*pp++ = make(*fp++);
295	*pp++ = ENDARGS;
296	return(np);
297}
298
299
300struct dolnod *
301clean_args(blk)
302	struct dolnod *blk;
303{
304	unsigned char **argp;
305	struct dolnod *argr = 0;
306	struct dolnod *argblk;
307
308	if (argblk = blk)
309	{
310		argr = argblk->dolnxt;
311
312		if (argblk == dolh)
313			argblk->doluse = 1;
314		else
315		{
316			for (argp = argblk->dolarg; *argp != (unsigned char *)ENDARGS; argp++)
317				free(*argp);
318			free(argblk->dolarg);
319			free(argblk);
320		}
321	}
322	return(argr);
323}
324
325void
326clearup(void)
327{
328	/*
329	 * force `for' $* lists to go away
330	 */
331	if(globdolv)
332		dolv = globdolv;
333	if(globdolc)
334		dolc = globdolc;
335	if(globdolh)
336		dolh = globdolh;
337	globdolv = 0;
338	globdolc = 0;
339	globdolh = 0;
340	while (argfor = clean_args(argfor))
341		;
342	/*
343	 * clean up io files
344	 */
345	while (pop())
346		;
347
348	/*
349	 * Clean up pipe file descriptor
350	 * from command substitution
351	 */
352
353	if(savpipe != -1) {
354		close(savpipe);
355		savpipe = -1;
356	}
357
358	/*
359	 * clean up tmp files
360	*/
361	while (poptemp())
362		;
363}
364
365/*
366 * Save positiional parameters before outermost function invocation
367 * in case we are interrupted.
368 * Increment use count for current positional parameters so that they aren't thrown
369 * away.
370 */
371
372struct dolnod *savargs(funcnt)
373int funcnt;
374{
375	if (!funcnt) {
376		globdolh = dolh;
377		globdolv = dolv;
378		globdolc = dolc;
379	}
380	useargs();
381	return(dolh);
382}
383
384/* After function invocation, free positional parameters,
385 * restore old positional parameters, and restore
386 * use count.
387 */
388
389void restorargs(olddolh, funcnt)
390struct dolnod *olddolh;
391{
392	if(argfor != olddolh)
393		while ((argfor = clean_args(argfor)) != olddolh && argfor);
394	if(!argfor)
395		return;
396	freedolh();
397	dolh = olddolh;
398	if(dolh)
399		dolh -> doluse++; /* increment use count so arguments aren't freed */
400	argfor = freeargs(dolh);
401	if(funcnt == 1) {
402		globdolh = 0;
403		globdolv = 0;
404		globdolc = 0;
405	}
406}
407
408struct dolnod *
409useargs()
410{
411	if (dolh)
412	{
413		if (dolh->doluse++ == 1)
414		{
415			dolh->dolnxt = argfor;
416			argfor = dolh;
417		}
418	}
419	return(dolh);
420}
421
422