xref: /illumos-gate/usr/src/cmd/sh/args.c (revision 581cede61ac9c14d8d4ea452562a567189eead78)
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 
39 static struct dolnod *copyargs();
40 static void freedolh(void);
41 extern struct dolnod *freeargs();
42 static struct dolnod *dolh;
43 
44 /* Used to save outermost positional parameters */
45 static struct dolnod *globdolh;
46 static unsigned char **globdolv;
47 static int globdolc;
48 
49 unsigned char	flagadr[16];
50 
51 unsigned 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 
71 long	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 
94 int
95 options(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  */
210 void
211 setargs(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 
227 static void
228 freedolh(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 
245 struct dolnod *
246 freeargs(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 
280 static struct dolnod *
281 copyargs(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 
300 struct dolnod *
301 clean_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 
325 void
326 clearup(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 
372 struct dolnod *savargs(funcnt)
373 int 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 
389 void restorargs(olddolh, funcnt)
390 struct 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 
408 struct dolnod *
409 useargs()
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