xref: /illumos-gate/usr/src/cmd/sh/args.c (revision cbb4f598c458692c12cab4febb735fff6b9d736d)
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(unsigned char *from[], int n)
280 {
281 	struct dolnod *np = (struct dolnod *)alloc(sizeof (struct dolnod));
282 	unsigned char **fp = from;
283 	unsigned char **pp;
284 
285 	np -> dolnxt = 0;
286 	np->doluse = 1;	/* use count */
287 	pp = np->dolarg = (unsigned char **)alloc((n+1)*sizeof(char *));
288 	dolv = pp;
289 
290 	while (n--)
291 		*pp++ = make(*fp++);
292 	*pp++ = ENDARGS;
293 	return(np);
294 }
295 
296 
297 struct dolnod *
298 clean_args(struct dolnod *blk)
299 {
300 	unsigned char **argp;
301 	struct dolnod *argr = 0;
302 	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 void
322 clearup(void)
323 {
324 	/*
325 	 * force `for' $* lists to go away
326 	 */
327 	if(globdolv)
328 		dolv = globdolv;
329 	if(globdolc)
330 		dolc = globdolc;
331 	if(globdolh)
332 		dolh = globdolh;
333 	globdolv = 0;
334 	globdolc = 0;
335 	globdolh = 0;
336 	while (argfor = clean_args(argfor))
337 		;
338 	/*
339 	 * clean up io files
340 	 */
341 	while (pop())
342 		;
343 
344 	/*
345 	 * Clean up pipe file descriptor
346 	 * from command substitution
347 	 */
348 
349 	if(savpipe != -1) {
350 		close(savpipe);
351 		savpipe = -1;
352 	}
353 
354 	/*
355 	 * clean up tmp files
356 	*/
357 	while (poptemp())
358 		;
359 }
360 
361 /*
362  * Save positiional parameters before outermost function invocation
363  * in case we are interrupted.
364  * Increment use count for current positional parameters so that they aren't thrown
365  * away.
366  */
367 
368 struct dolnod *savargs(funcnt)
369 int funcnt;
370 {
371 	if (!funcnt) {
372 		globdolh = dolh;
373 		globdolv = dolv;
374 		globdolc = dolc;
375 	}
376 	useargs();
377 	return(dolh);
378 }
379 
380 /* After function invocation, free positional parameters,
381  * restore old positional parameters, and restore
382  * use count.
383  */
384 
385 void restorargs(struct dolnod *olddolh, int funcnt)
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(void)
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