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