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