xref: /illumos-gate/usr/src/contrib/ast/src/cmd/ksh93/sh/args.c (revision b30d1939)
1da2e3ebdSchin /***********************************************************************
2da2e3ebdSchin *                                                                      *
3da2e3ebdSchin *               This software is part of the ast package               *
4*b30d1939SAndy Fiddaman *          Copyright (c) 1982-2012 AT&T Intellectual Property          *
5da2e3ebdSchin *                      and is licensed under the                       *
6*b30d1939SAndy Fiddaman *                 Eclipse Public License, Version 1.0                  *
77c2fbfb3SApril Chin *                    by AT&T Intellectual Property                     *
8da2e3ebdSchin *                                                                      *
9da2e3ebdSchin *                A copy of the License is available at                 *
10*b30d1939SAndy Fiddaman *          http://www.eclipse.org/org/documents/epl-v10.html           *
11*b30d1939SAndy Fiddaman *         (with md5 checksum b35adb5213ca9657e911e9befb180842)         *
12da2e3ebdSchin *                                                                      *
13da2e3ebdSchin *              Information and Software Systems Research               *
14da2e3ebdSchin *                            AT&T Research                             *
15da2e3ebdSchin *                           Florham Park NJ                            *
16da2e3ebdSchin *                                                                      *
17da2e3ebdSchin *                  David Korn <dgk@research.att.com>                   *
18da2e3ebdSchin *                                                                      *
19da2e3ebdSchin ***********************************************************************/
20da2e3ebdSchin #pragma prototyped
21da2e3ebdSchin /*
22da2e3ebdSchin  * UNIX shell
23da2e3ebdSchin  *
24da2e3ebdSchin  * S. R. Bourne
25da2e3ebdSchin  * Rewritten by David Korn
26da2e3ebdSchin  * AT&T Labs
27da2e3ebdSchin  *
28da2e3ebdSchin  */
29*b30d1939SAndy Fiddaman /*
30*b30d1939SAndy Fiddaman  * Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
31*b30d1939SAndy Fiddaman  */
32da2e3ebdSchin 
33da2e3ebdSchin #include	"defs.h"
34da2e3ebdSchin #include	"path.h"
35da2e3ebdSchin #include	"builtins.h"
36da2e3ebdSchin #include	"terminal.h"
37da2e3ebdSchin #include	"edit.h"
38da2e3ebdSchin #include	"FEATURE/poll"
39da2e3ebdSchin #if SHOPT_KIA
40da2e3ebdSchin #   include	"shlex.h"
41da2e3ebdSchin #   include	"io.h"
42da2e3ebdSchin #endif /* SHOPT_KIA */
43da2e3ebdSchin #if SHOPT_PFSH
44da2e3ebdSchin #   define PFSHOPT	"P"
45da2e3ebdSchin #else
46da2e3ebdSchin #   define PFSHOPT
47da2e3ebdSchin #endif
48da2e3ebdSchin #if SHOPT_BASH
497c2fbfb3SApril Chin #   define BASHOPT	"\374"
50da2e3ebdSchin #else
51da2e3ebdSchin #   define BASHOPT
52da2e3ebdSchin #endif
53da2e3ebdSchin #if SHOPT_HISTEXPAND
54da2e3ebdSchin #   define HFLAG        "H"
55da2e3ebdSchin #else
56da2e3ebdSchin #   define HFLAG        ""
57da2e3ebdSchin #endif
58da2e3ebdSchin 
59da2e3ebdSchin #define SORT		1
60da2e3ebdSchin #define PRINT		2
61da2e3ebdSchin 
62da2e3ebdSchin static	char		*null;
63da2e3ebdSchin 
64da2e3ebdSchin /* The following order is determined by sh_optset */
65da2e3ebdSchin static  const char optksh[] =  PFSHOPT BASHOPT "DircabefhkmnpstuvxBCGEl" HFLAG;
66da2e3ebdSchin static const int flagval[]  =
67da2e3ebdSchin {
68da2e3ebdSchin #if SHOPT_PFSH
69da2e3ebdSchin 	SH_PFSH,
70da2e3ebdSchin #endif
71da2e3ebdSchin #if SHOPT_BASH
727c2fbfb3SApril Chin 	SH_POSIX,
73da2e3ebdSchin #endif
74da2e3ebdSchin 	SH_DICTIONARY, SH_INTERACTIVE, SH_RESTRICTED, SH_CFLAG,
75da2e3ebdSchin 	SH_ALLEXPORT, SH_NOTIFY, SH_ERREXIT, SH_NOGLOB, SH_TRACKALL,
76da2e3ebdSchin 	SH_KEYWORD, SH_MONITOR, SH_NOEXEC, SH_PRIVILEGED, SH_SFLAG, SH_TFLAG,
77da2e3ebdSchin 	SH_NOUNSET, SH_VERBOSE,  SH_XTRACE, SH_BRACEEXPAND, SH_NOCLOBBER,
78da2e3ebdSchin 	SH_GLOBSTARS, SH_RC, SH_LOGIN_SHELL,
79da2e3ebdSchin #if SHOPT_HISTEXPAND
80da2e3ebdSchin         SH_HISTEXPAND,
81da2e3ebdSchin #endif
82da2e3ebdSchin 	0
83da2e3ebdSchin };
84da2e3ebdSchin 
85da2e3ebdSchin #define NUM_OPTS	(sizeof(flagval)/sizeof(*flagval))
86da2e3ebdSchin 
87da2e3ebdSchin typedef struct _arg_
88da2e3ebdSchin {
897c2fbfb3SApril Chin 	Shell_t		*sh;
90da2e3ebdSchin 	struct dolnod	*argfor; /* linked list of blocks to be cleaned up */
91da2e3ebdSchin 	struct dolnod	*dolh;
92da2e3ebdSchin 	char flagadr[NUM_OPTS+1];
93da2e3ebdSchin #if SHOPT_KIA
94da2e3ebdSchin 	char	*kiafile;
95da2e3ebdSchin #endif /* SHOPT_KIA */
96da2e3ebdSchin } Arg_t;
97da2e3ebdSchin 
987c2fbfb3SApril Chin static int 		arg_expand(Shell_t*,struct argnod*,struct argnod**,int);
997c2fbfb3SApril Chin static void 		sh_argset(Arg_t*, char *[]);
1007c2fbfb3SApril Chin 
101da2e3ebdSchin 
102da2e3ebdSchin /* ======== option handling	======== */
103da2e3ebdSchin 
sh_argopen(Shell_t * shp)104da2e3ebdSchin void *sh_argopen(Shell_t *shp)
105da2e3ebdSchin {
106da2e3ebdSchin 	void *addr = newof(0,Arg_t,1,0);
107da2e3ebdSchin 	Arg_t *ap = (Arg_t*)addr;
1087c2fbfb3SApril Chin 	ap->sh = shp;
109da2e3ebdSchin 	return(addr);
110da2e3ebdSchin }
111da2e3ebdSchin 
infof(Opt_t * op,Sfio_t * sp,const char * s,Optdisc_t * dp)112da2e3ebdSchin static int infof(Opt_t* op, Sfio_t* sp, const char* s, Optdisc_t* dp)
113da2e3ebdSchin {
114da2e3ebdSchin #if SHOPT_BASH
115da2e3ebdSchin 	extern const char sh_bash1[], sh_bash2[];
116da2e3ebdSchin 	if(strcmp(s,"bash1")==0)
117da2e3ebdSchin 	{
118da2e3ebdSchin 		if(sh_isoption(SH_BASH))
119da2e3ebdSchin 			sfputr(sp,sh_bash1,-1);
120da2e3ebdSchin 	}
121da2e3ebdSchin 	else if(strcmp(s,"bash2")==0)
122da2e3ebdSchin 	{
123da2e3ebdSchin 		if(sh_isoption(SH_BASH))
124da2e3ebdSchin 			sfputr(sp,sh_bash2,-1);
125da2e3ebdSchin 	}
126da2e3ebdSchin 	else if(*s==':' && sh_isoption(SH_BASH))
127da2e3ebdSchin 		sfputr(sp,s,-1);
128da2e3ebdSchin 	else
129da2e3ebdSchin #endif
130da2e3ebdSchin 	if(*s!=':')
131da2e3ebdSchin 		sfputr(sp,sh_set,-1);
132da2e3ebdSchin 	return(1);
133da2e3ebdSchin }
134da2e3ebdSchin 
135da2e3ebdSchin /*
136da2e3ebdSchin  *  This routine turns options on and off
137da2e3ebdSchin  *  The options "PDicr" are illegal from set command.
138da2e3ebdSchin  *  The -o option is used to set option by name
139da2e3ebdSchin  *  This routine returns the number of non-option arguments
140da2e3ebdSchin  */
sh_argopts(int argc,register char * argv[],void * context)1417c2fbfb3SApril Chin int sh_argopts(int argc,register char *argv[], void *context)
142da2e3ebdSchin {
1437c2fbfb3SApril Chin 	Shell_t		*shp = (Shell_t*)context;
1447c2fbfb3SApril Chin 	register int	n,o;
1457c2fbfb3SApril Chin 	register Arg_t	*ap = (Arg_t*)(shp->arg_context);
1467c2fbfb3SApril Chin 	Lex_t		*lp = (Lex_t*)(shp->lex_context);
1477c2fbfb3SApril Chin 	Shopt_t		newflags;
148da2e3ebdSchin 	int setflag=0, action=0, trace=(int)sh_isoption(SH_XTRACE);
149da2e3ebdSchin 	Namval_t *np = NIL(Namval_t*);
150da2e3ebdSchin 	const char *cp;
151da2e3ebdSchin 	int verbose,f;
152da2e3ebdSchin 	Optdisc_t disc;
1537c2fbfb3SApril Chin 	newflags=ap->sh->options;
154da2e3ebdSchin 	memset(&disc, 0, sizeof(disc));
155da2e3ebdSchin 	disc.version = OPT_VERSION;
156da2e3ebdSchin 	disc.infof = infof;
157da2e3ebdSchin 	opt_info.disc = &disc;
158da2e3ebdSchin 
159da2e3ebdSchin 	if(argc>0)
160da2e3ebdSchin 		setflag = 4;
161da2e3ebdSchin 	else
162da2e3ebdSchin 		argc = -argc;
163da2e3ebdSchin 	while((n = optget(argv,setflag?sh_optset:sh_optksh)))
164da2e3ebdSchin 	{
165da2e3ebdSchin 		o=0;
1667c2fbfb3SApril Chin 		f=*opt_info.option=='-' && (opt_info.num || opt_info.arg);
167da2e3ebdSchin 		switch(n)
168da2e3ebdSchin 		{
169da2e3ebdSchin 	 	    case 'A':
1707c2fbfb3SApril Chin 			np = nv_open(opt_info.arg,ap->sh->var_tree,NV_NOASSIGN|NV_ARRAY|NV_VARNAME);
171da2e3ebdSchin 			if(f)
172da2e3ebdSchin 				nv_unset(np);
173da2e3ebdSchin 			continue;
174da2e3ebdSchin #if SHOPT_BASH
175da2e3ebdSchin 		    case 'O':	/* shopt options, only in bash mode */
176da2e3ebdSchin 			if(!sh_isoption(SH_BASH))
177da2e3ebdSchin 				errormsg(SH_DICT,ERROR_exit(1), e_option, opt_info.name);
178da2e3ebdSchin #endif
179da2e3ebdSchin 		    case 'o':	/* set options */
180da2e3ebdSchin 		    byname:
181da2e3ebdSchin 			if(!opt_info.arg||!*opt_info.arg||*opt_info.arg=='-')
182da2e3ebdSchin 			{
183da2e3ebdSchin 				action = PRINT;
184da2e3ebdSchin 				/* print style: -O => shopt options
185da2e3ebdSchin 				 * bash => print unset options also, no heading
186da2e3ebdSchin 				 */
187da2e3ebdSchin 				verbose = (f?PRINT_VERBOSE:PRINT_NO_HEADER)|
188da2e3ebdSchin 					  (n=='O'?PRINT_SHOPT:0)|
189da2e3ebdSchin 					  (sh_isoption(SH_BASH)?PRINT_ALL|PRINT_NO_HEADER:0)|
190da2e3ebdSchin 					  ((opt_info.arg&&(!*opt_info.arg||*opt_info.arg=='-'))?(PRINT_TABLE|PRINT_NO_HEADER):0);
191da2e3ebdSchin 				continue;
192da2e3ebdSchin 			}
193da2e3ebdSchin 			o = sh_lookopt(opt_info.arg,&f);
194da2e3ebdSchin 			if(o<=0
195da2e3ebdSchin 				|| (!sh_isoption(SH_BASH) && (o&SH_BASHEXTRA))
196da2e3ebdSchin 				|| ((!sh_isoption(SH_BASH) || n=='o') && (o&SH_BASHOPT))
197da2e3ebdSchin 
198da2e3ebdSchin 				|| (setflag && (o&SH_COMMANDLINE)))
199da2e3ebdSchin 			{
200da2e3ebdSchin 				errormsg(SH_DICT,2, e_option, opt_info.arg);
201da2e3ebdSchin 				error_info.errors++;
202da2e3ebdSchin 			}
203da2e3ebdSchin 			o &= 0xff;
204da2e3ebdSchin 			if(sh_isoption(SH_RESTRICTED) && !f && o==SH_RESTRICTED)
205da2e3ebdSchin 				errormsg(SH_DICT,ERROR_exit(1), e_restricted, opt_info.arg);
206da2e3ebdSchin 			break;
207da2e3ebdSchin #if SHOPT_BASH
208da2e3ebdSchin 		    case -1:	/* --rcfile */
209*b30d1939SAndy Fiddaman 			ap->sh->gd->rcfile = opt_info.arg;
210da2e3ebdSchin 			continue;
211da2e3ebdSchin 		    case -2:	/* --noediting */
2127c2fbfb3SApril Chin 			if (!f)
2137c2fbfb3SApril Chin 			{
2147c2fbfb3SApril Chin 				off_option(&newflags,SH_VI);
2157c2fbfb3SApril Chin 				off_option(&newflags,SH_EMACS);
2167c2fbfb3SApril Chin 				off_option(&newflags,SH_GMACS);
2177c2fbfb3SApril Chin 			}
218da2e3ebdSchin 			continue;
219da2e3ebdSchin 		    case -3:	/* --profile */
2207c2fbfb3SApril Chin 			n = 'l';
2217c2fbfb3SApril Chin 			goto skip;
2227c2fbfb3SApril Chin 		    case -4:	/* --posix */
223da2e3ebdSchin 			/* mask lower 8 bits to find char in optksh string */
224da2e3ebdSchin 			n&=0xff;
225da2e3ebdSchin 			goto skip;
2267c2fbfb3SApril Chin 		    case -5:	/* --version */
2277c2fbfb3SApril Chin 			sfputr(sfstdout, "ksh bash emulation, version ",-1);
2287c2fbfb3SApril Chin 			np = nv_open("BASH_VERSION",ap->sh->var_tree,0);
2297c2fbfb3SApril Chin 			sfputr(sfstdout, nv_getval(np),-1);
2307c2fbfb3SApril Chin 			np = nv_open("MACHTYPE",ap->sh->var_tree,0);
2317c2fbfb3SApril Chin 			sfprintf(sfstdout, " (%s)\n", nv_getval(np));
2327c2fbfb3SApril Chin 			sh_exit(0);
233da2e3ebdSchin #endif
2347c2fbfb3SApril Chin 		    case -6:	/* --default */
2357c2fbfb3SApril Chin 			{
2367c2fbfb3SApril Chin 				register const Shtable_t *tp;
2377c2fbfb3SApril Chin 				for(tp=shtab_options; o = tp->sh_number; tp++)
2387c2fbfb3SApril Chin 					if(!(o&SH_COMMANDLINE) && is_option(&newflags,o&0xff))
2397c2fbfb3SApril Chin 						off_option(&newflags,o&0xff);
2407c2fbfb3SApril Chin 			}
2417c2fbfb3SApril Chin 		    	continue;
2427c2fbfb3SApril Chin 	 	    case -7:
2437c2fbfb3SApril Chin 			f = 0;
2447c2fbfb3SApril Chin 		    	goto byname;
245da2e3ebdSchin 	 	    case 'D':
246da2e3ebdSchin 			on_option(&newflags,SH_NOEXEC);
247da2e3ebdSchin 			goto skip;
2487c2fbfb3SApril Chin 		    case 'T':
2497c2fbfb3SApril Chin 			if (opt_info.num)
2507c2fbfb3SApril Chin 				ap->sh->test |= opt_info.num;
2517c2fbfb3SApril Chin 			else
2527c2fbfb3SApril Chin 				ap->sh->test = 0;
2537c2fbfb3SApril Chin 		    	continue;
254da2e3ebdSchin 		    case 's':
255da2e3ebdSchin 			if(setflag)
256da2e3ebdSchin 			{
257da2e3ebdSchin 				action = SORT;
258da2e3ebdSchin 				continue;
259da2e3ebdSchin 			}
260da2e3ebdSchin #if SHOPT_KIA
261da2e3ebdSchin 			goto skip;
262da2e3ebdSchin 		    case 'R':
263da2e3ebdSchin 			if(setflag)
264da2e3ebdSchin 				n = ':';
265da2e3ebdSchin 			else
266da2e3ebdSchin 			{
267da2e3ebdSchin 				ap->kiafile = opt_info.arg;
268da2e3ebdSchin 				n = 'n';
269da2e3ebdSchin 			}
27034f9b3eeSRoland Mainz 			/*FALLTHROUGH*/
271da2e3ebdSchin #endif /* SHOPT_KIA */
27234f9b3eeSRoland Mainz #if SHOPT_REGRESS
27334f9b3eeSRoland Mainz 			goto skip;
27434f9b3eeSRoland Mainz 		    case 'I':
27534f9b3eeSRoland Mainz 			continue;
27634f9b3eeSRoland Mainz #endif /* SHOPT_REGRESS */
2775ae8bd53SToomas Soome 			/*FALLTHROUGH*/
278da2e3ebdSchin 		    skip:
279da2e3ebdSchin 		    default:
280da2e3ebdSchin 			if(cp=strchr(optksh,n))
281da2e3ebdSchin 				o = flagval[cp-optksh];
282da2e3ebdSchin 			break;
283da2e3ebdSchin 		    case ':':
284da2e3ebdSchin 			if(opt_info.name[0]=='-'&&opt_info.name[1]=='-')
285da2e3ebdSchin 			{
286da2e3ebdSchin 				opt_info.arg = argv[opt_info.index-1] + 2;
287da2e3ebdSchin 				f = 1;
288da2e3ebdSchin 				goto byname;
289da2e3ebdSchin 			}
290da2e3ebdSchin 			errormsg(SH_DICT,2, "%s", opt_info.arg);
291da2e3ebdSchin 			continue;
292da2e3ebdSchin 		    case '?':
293da2e3ebdSchin 			errormsg(SH_DICT,ERROR_usage(0), "%s", opt_info.arg);
294da2e3ebdSchin 			return(-1);
295da2e3ebdSchin 		}
296da2e3ebdSchin 		if(f)
297da2e3ebdSchin 		{
298da2e3ebdSchin 			if(o==SH_VI || o==SH_EMACS || o==SH_GMACS)
299da2e3ebdSchin 			{
300da2e3ebdSchin 				off_option(&newflags,SH_VI);
301da2e3ebdSchin 				off_option(&newflags,SH_EMACS);
302da2e3ebdSchin 				off_option(&newflags,SH_GMACS);
303da2e3ebdSchin 			}
304da2e3ebdSchin 			on_option(&newflags,o);
3057c2fbfb3SApril Chin 			off_option(&ap->sh->offoptions,o);
306da2e3ebdSchin 		}
307da2e3ebdSchin 		else
308da2e3ebdSchin 		{
309*b30d1939SAndy Fiddaman 			if ((o == SH_RESTRICTED) &&
310*b30d1939SAndy Fiddaman 			    sh_isoption(SH_RESTRICTED)) {
311*b30d1939SAndy Fiddaman 				errormsg(SH_DICT, ERROR_exit(1),
312*b30d1939SAndy Fiddaman 				    e_restricted, "r");
313*b30d1939SAndy Fiddaman 			}
314da2e3ebdSchin 			if(o==SH_XTRACE)
315da2e3ebdSchin 				trace = 0;
316da2e3ebdSchin 			off_option(&newflags,o);
317da2e3ebdSchin 			if(setflag==0)
3187c2fbfb3SApril Chin 				on_option(&ap->sh->offoptions,o);
319da2e3ebdSchin 		}
320da2e3ebdSchin 	}
321da2e3ebdSchin 	if(error_info.errors)
322da2e3ebdSchin 		errormsg(SH_DICT,ERROR_usage(2),"%s",optusage(NIL(char*)));
323da2e3ebdSchin 	/* check for '-' or '+' argument */
324da2e3ebdSchin 	if((cp=argv[opt_info.index]) && cp[1]==0 && (*cp=='+' || *cp=='-') &&
325da2e3ebdSchin 		strcmp(argv[opt_info.index-1],"--"))
326da2e3ebdSchin 	{
327da2e3ebdSchin 		opt_info.index++;
328da2e3ebdSchin 		off_option(&newflags,SH_XTRACE);
329da2e3ebdSchin 		off_option(&newflags,SH_VERBOSE);
330da2e3ebdSchin 		trace = 0;
331da2e3ebdSchin 	}
332da2e3ebdSchin 	if(trace)
333*b30d1939SAndy Fiddaman 		sh_trace(shp,argv,1);
334da2e3ebdSchin 	argc -= opt_info.index;
335da2e3ebdSchin 	argv += opt_info.index;
336da2e3ebdSchin 	if(action==PRINT)
337da2e3ebdSchin 		sh_printopts(newflags,verbose,0);
338da2e3ebdSchin 	if(setflag)
339da2e3ebdSchin 	{
340da2e3ebdSchin 		if(action==SORT)
341da2e3ebdSchin 		{
342da2e3ebdSchin 			if(argc>0)
343da2e3ebdSchin 				strsort(argv,argc,strcoll);
344da2e3ebdSchin 			else
3457c2fbfb3SApril Chin 				strsort(ap->sh->st.dolv+1,ap->sh->st.dolc,strcoll);
346da2e3ebdSchin 		}
347da2e3ebdSchin 		if(np)
348da2e3ebdSchin 		{
349da2e3ebdSchin 			nv_setvec(np,0,argc,argv);
350da2e3ebdSchin 			nv_close(np);
351da2e3ebdSchin 		}
352da2e3ebdSchin 		else if(argc>0 || ((cp=argv[-1]) && strcmp(cp,"--")==0))
3537c2fbfb3SApril Chin 			sh_argset(ap,argv-1);
354da2e3ebdSchin 	}
355da2e3ebdSchin 	else if(is_option(&newflags,SH_CFLAG))
356da2e3ebdSchin 	{
3577c2fbfb3SApril Chin 		if(!(ap->sh->comdiv = *argv++))
358da2e3ebdSchin 		{
359da2e3ebdSchin 			errormsg(SH_DICT,2,e_cneedsarg);
360da2e3ebdSchin 			errormsg(SH_DICT,ERROR_usage(2),optusage(NIL(char*)));
361da2e3ebdSchin 		}
362da2e3ebdSchin 		argc--;
363da2e3ebdSchin 	}
364da2e3ebdSchin 	/* handling SH_INTERACTIVE and SH_PRIVILEGED has been moved to
365da2e3ebdSchin 	 * sh_applyopts(), so that the code can be reused from b_shopt(), too
366da2e3ebdSchin 	 */
3677c2fbfb3SApril Chin 	sh_applyopts(ap->sh,newflags);
368da2e3ebdSchin #if SHOPT_KIA
369da2e3ebdSchin 	if(ap->kiafile)
370da2e3ebdSchin 	{
3717c2fbfb3SApril Chin 		if(!argv[0])
3727c2fbfb3SApril Chin 			errormsg(SH_DICT,ERROR_usage(2),"-R requires scriptname");
3737c2fbfb3SApril Chin 		if(!(lp->kiafile=sfopen(NIL(Sfio_t*),ap->kiafile,"w+")))
374da2e3ebdSchin 			errormsg(SH_DICT,ERROR_system(3),e_create,ap->kiafile);
3757c2fbfb3SApril Chin 		if(!(lp->kiatmp=sftmp(2*SF_BUFSIZE)))
376da2e3ebdSchin 			errormsg(SH_DICT,ERROR_system(3),e_tmpcreate);
3777c2fbfb3SApril Chin 		sfputr(lp->kiafile,";vdb;CIAO/ksh",'\n');
3787c2fbfb3SApril Chin 		lp->kiabegin = sftell(lp->kiafile);
3797c2fbfb3SApril Chin 		lp->entity_tree = dtopen(&_Nvdisc,Dtbag);
3807c2fbfb3SApril Chin 		lp->scriptname = strdup(sh_fmtq(argv[0]));
3817c2fbfb3SApril Chin 		lp->script=kiaentity(lp,lp->scriptname,-1,'p',-1,0,0,'s',0,"");
3827c2fbfb3SApril Chin 		lp->fscript=kiaentity(lp,lp->scriptname,-1,'f',-1,0,0,'s',0,"");
3837c2fbfb3SApril Chin 		lp->unknown=kiaentity(lp,"<unknown>",-1,'p',-1,0,0,'0',0,"");
3847c2fbfb3SApril Chin 		kiaentity(lp,"<unknown>",-1,'p',0,0,lp->unknown,'0',0,"");
3857c2fbfb3SApril Chin 		lp->current = lp->script;
386da2e3ebdSchin 		ap->kiafile = 0;
387da2e3ebdSchin 	}
388da2e3ebdSchin #endif /* SHOPT_KIA */
389da2e3ebdSchin 	return(argc);
390da2e3ebdSchin }
391da2e3ebdSchin 
392da2e3ebdSchin /* apply new options */
393da2e3ebdSchin 
sh_applyopts(Shell_t * shp,Shopt_t newflags)3947c2fbfb3SApril Chin void sh_applyopts(Shell_t* shp,Shopt_t newflags)
395da2e3ebdSchin {
396da2e3ebdSchin 	/* cannot set -n for interactive shells since there is no way out */
397da2e3ebdSchin 	if(sh_isoption(SH_INTERACTIVE))
398da2e3ebdSchin 		off_option(&newflags,SH_NOEXEC);
399da2e3ebdSchin 	if(is_option(&newflags,SH_PRIVILEGED))
400da2e3ebdSchin 		on_option(&newflags,SH_NOUSRPROFILE);
401*b30d1939SAndy Fiddaman 	if(!sh_isstate(SH_INIT) && is_option(&newflags,SH_PRIVILEGED) != sh_isoption(SH_PRIVILEGED) || sh_isstate(SH_INIT) && is_option(&((Arg_t*)shp->arg_context)->sh->offoptions,SH_PRIVILEGED) && shp->gd->userid!=shp->gd->euserid)
402da2e3ebdSchin 	{
40334f9b3eeSRoland Mainz 		if(!is_option(&newflags,SH_PRIVILEGED))
404da2e3ebdSchin 		{
405*b30d1939SAndy Fiddaman 			setuid(shp->gd->userid);
406*b30d1939SAndy Fiddaman 			setgid(shp->gd->groupid);
407*b30d1939SAndy Fiddaman 			if(shp->gd->euserid==0)
408da2e3ebdSchin 			{
409*b30d1939SAndy Fiddaman 				shp->gd->euserid = shp->gd->userid;
410*b30d1939SAndy Fiddaman 				shp->gd->egroupid = shp->gd->groupid;
411da2e3ebdSchin 			}
412da2e3ebdSchin 		}
413*b30d1939SAndy Fiddaman 		else if((shp->gd->userid!=shp->gd->euserid && setuid(shp->gd->euserid)<0) ||
414*b30d1939SAndy Fiddaman 			(shp->gd->groupid!=shp->gd->egroupid && setgid(shp->gd->egroupid)<0) ||
415*b30d1939SAndy Fiddaman 			(shp->gd->userid==shp->gd->euserid && shp->gd->groupid==shp->gd->egroupid))
416da2e3ebdSchin 				off_option(&newflags,SH_PRIVILEGED);
417da2e3ebdSchin 	}
418da2e3ebdSchin #if SHOPT_BASH
419da2e3ebdSchin 	on_option(&newflags,SH_CMDHIST);
420da2e3ebdSchin 	on_option(&newflags,SH_CHECKHASH);
421da2e3ebdSchin 	on_option(&newflags,SH_EXECFAIL);
422da2e3ebdSchin 	on_option(&newflags,SH_EXPAND_ALIASES);
423da2e3ebdSchin 	on_option(&newflags,SH_HISTAPPEND);
424da2e3ebdSchin 	on_option(&newflags,SH_INTERACTIVE_COMM);
425da2e3ebdSchin 	on_option(&newflags,SH_LITHIST);
426da2e3ebdSchin 	on_option(&newflags,SH_NOEMPTYCMDCOMPL);
427da2e3ebdSchin 
428da2e3ebdSchin 	if(!is_option(&newflags,SH_XPG_ECHO) && sh_isoption(SH_XPG_ECHO))
429da2e3ebdSchin 		astconf("UNIVERSE", 0, "ucb");
430da2e3ebdSchin 	if(is_option(&newflags,SH_XPG_ECHO) && !sh_isoption(SH_XPG_ECHO))
431da2e3ebdSchin 		astconf("UNIVERSE", 0, "att");
432da2e3ebdSchin 	if(!is_option(&newflags,SH_PHYSICAL) && sh_isoption(SH_PHYSICAL))
433da2e3ebdSchin 		astconf("PATH_RESOLVE", 0, "metaphysical");
434da2e3ebdSchin 	if(is_option(&newflags,SH_PHYSICAL) && !sh_isoption(SH_PHYSICAL))
435da2e3ebdSchin 		astconf("PATH_RESOLVE", 0, "physical");
436da2e3ebdSchin 	if(is_option(&newflags,SH_HISTORY2) && !sh_isoption(SH_HISTORY2))
437da2e3ebdSchin 	{
438da2e3ebdSchin 		sh_onstate(SH_HISTORY);
439da2e3ebdSchin                 sh_onoption(SH_HISTORY);
440da2e3ebdSchin 	}
441da2e3ebdSchin 	if(!is_option(&newflags,SH_HISTORY2) && sh_isoption(SH_HISTORY2))
442da2e3ebdSchin 	{
443da2e3ebdSchin 		sh_offstate(SH_HISTORY);
444da2e3ebdSchin 		sh_offoption(SH_HISTORY);
445da2e3ebdSchin 	}
446da2e3ebdSchin #endif
4477c2fbfb3SApril Chin 	shp->options = newflags;
448da2e3ebdSchin }
4497c2fbfb3SApril Chin 
450da2e3ebdSchin /*
451da2e3ebdSchin  * returns the value of $-
452da2e3ebdSchin  */
sh_argdolminus(void * context)4537c2fbfb3SApril Chin char *sh_argdolminus(void* context)
454da2e3ebdSchin {
4557c2fbfb3SApril Chin 	register Arg_t *ap = (Arg_t*)context;
456da2e3ebdSchin 	register const char *cp=optksh;
457da2e3ebdSchin 	register char *flagp=ap->flagadr;
458da2e3ebdSchin 	while(cp< &optksh[NUM_OPTS])
459da2e3ebdSchin 	{
460da2e3ebdSchin 		int n = flagval[cp-optksh];
461da2e3ebdSchin 		if(sh_isoption(n))
462da2e3ebdSchin 			*flagp++ = *cp;
463da2e3ebdSchin 		cp++;
464da2e3ebdSchin 	}
465da2e3ebdSchin 	*flagp = 0;
466da2e3ebdSchin 	return(ap->flagadr);
467da2e3ebdSchin }
468da2e3ebdSchin 
469da2e3ebdSchin /*
470da2e3ebdSchin  * set up positional parameters
471da2e3ebdSchin  */
sh_argset(Arg_t * ap,char * argv[])4727c2fbfb3SApril Chin static void sh_argset(Arg_t *ap,char *argv[])
473da2e3ebdSchin {
4747c2fbfb3SApril Chin 	sh_argfree(ap->sh,ap->dolh,0);
475da2e3ebdSchin 	ap->dolh = sh_argcreate(argv);
476da2e3ebdSchin 	/* link into chain */
477da2e3ebdSchin 	ap->dolh->dolnxt = ap->argfor;
478da2e3ebdSchin 	ap->argfor = ap->dolh;
4797c2fbfb3SApril Chin 	ap->sh->st.dolc = ap->dolh->dolnum-1;
4807c2fbfb3SApril Chin 	ap->sh->st.dolv = ap->dolh->dolval;
481da2e3ebdSchin }
482da2e3ebdSchin 
483da2e3ebdSchin /*
484da2e3ebdSchin  * free the argument list if the use count is 1
485da2e3ebdSchin  * If count is greater than 1 decrement count and return same blk
486da2e3ebdSchin  * Free the argument list if the use count is 1 and return next blk
487da2e3ebdSchin  * Delete the blk from the argfor chain
488da2e3ebdSchin  * If flag is set, then the block dolh is not freed
489da2e3ebdSchin  */
sh_argfree(Shell_t * shp,struct dolnod * blk,int flag)4907c2fbfb3SApril Chin struct dolnod *sh_argfree(Shell_t *shp, struct dolnod *blk,int flag)
491da2e3ebdSchin {
492da2e3ebdSchin 	register struct dolnod*	argr=blk;
493da2e3ebdSchin 	register struct dolnod*	argblk;
4947c2fbfb3SApril Chin 	register Arg_t *ap = (Arg_t*)shp->arg_context;
495da2e3ebdSchin 	if(argblk=argr)
496da2e3ebdSchin 	{
497da2e3ebdSchin 		if((--argblk->dolrefcnt)==0)
498da2e3ebdSchin 		{
499da2e3ebdSchin 			argr = argblk->dolnxt;
500da2e3ebdSchin 			if(flag && argblk==ap->dolh)
501da2e3ebdSchin 				ap->dolh->dolrefcnt = 1;
502da2e3ebdSchin 			else
503da2e3ebdSchin 			{
504da2e3ebdSchin 				/* delete from chain */
505da2e3ebdSchin 				if(ap->argfor == argblk)
506da2e3ebdSchin 					ap->argfor = argblk->dolnxt;
507da2e3ebdSchin 				else
508da2e3ebdSchin 				{
509da2e3ebdSchin 					for(argr=ap->argfor;argr;argr=argr->dolnxt)
510da2e3ebdSchin 						if(argr->dolnxt==argblk)
511da2e3ebdSchin 							break;
512da2e3ebdSchin 					if(!argr)
513da2e3ebdSchin 						return(NIL(struct dolnod*));
514da2e3ebdSchin 					argr->dolnxt = argblk->dolnxt;
515da2e3ebdSchin 					argr = argblk->dolnxt;
516da2e3ebdSchin 				}
517da2e3ebdSchin 				free((void*)argblk);
518da2e3ebdSchin 			}
519da2e3ebdSchin 		}
520da2e3ebdSchin 	}
521da2e3ebdSchin 	return(argr);
522da2e3ebdSchin }
523da2e3ebdSchin 
524da2e3ebdSchin /*
525da2e3ebdSchin  * grab space for arglist and copy args
526da2e3ebdSchin  * The strings are copied after the argment vector
527da2e3ebdSchin  */
sh_argcreate(register char * argv[])528da2e3ebdSchin struct dolnod *sh_argcreate(register char *argv[])
529da2e3ebdSchin {
530da2e3ebdSchin 	register struct dolnod *dp;
531da2e3ebdSchin 	register char **pp=argv, *sp;
532da2e3ebdSchin 	register int 	size=0,n;
533da2e3ebdSchin 	/* count args and number of bytes of arglist */
534da2e3ebdSchin 	while(sp= *pp++)
535da2e3ebdSchin 		size += strlen(sp);
536da2e3ebdSchin 	n = (pp - argv)-1;
537da2e3ebdSchin 	dp=new_of(struct dolnod,n*sizeof(char*)+size+n);
538da2e3ebdSchin 	dp->dolrefcnt=1;	/* use count */
539da2e3ebdSchin 	dp->dolnum = n;
540da2e3ebdSchin 	dp->dolnxt = 0;
541da2e3ebdSchin 	pp = dp->dolval;
542da2e3ebdSchin 	sp = (char*)dp + sizeof(struct dolnod) + n*sizeof(char*);
543da2e3ebdSchin 	while(n--)
544da2e3ebdSchin 	{
545da2e3ebdSchin 		*pp++ = sp;
546da2e3ebdSchin 		sp = strcopy(sp, *argv++) + 1;
547da2e3ebdSchin 	}
548da2e3ebdSchin 	*pp = NIL(char*);
549da2e3ebdSchin 	return(dp);
550da2e3ebdSchin }
551da2e3ebdSchin 
552da2e3ebdSchin /*
553da2e3ebdSchin  *  used to set new arguments for functions
554da2e3ebdSchin  */
sh_argnew(Shell_t * shp,char * argi[],struct dolnod ** savargfor)5557c2fbfb3SApril Chin struct dolnod *sh_argnew(Shell_t *shp,char *argi[], struct dolnod **savargfor)
556da2e3ebdSchin {
5577c2fbfb3SApril Chin 	register Arg_t *ap = (Arg_t*)shp->arg_context;
558da2e3ebdSchin 	register struct dolnod *olddolh = ap->dolh;
559da2e3ebdSchin 	*savargfor = ap->argfor;
560da2e3ebdSchin 	ap->dolh = 0;
561da2e3ebdSchin 	ap->argfor = 0;
5627c2fbfb3SApril Chin 	sh_argset(ap,argi);
563da2e3ebdSchin 	return(olddolh);
564da2e3ebdSchin }
565da2e3ebdSchin 
566da2e3ebdSchin /*
567da2e3ebdSchin  * reset arguments as they were before function
568da2e3ebdSchin  */
sh_argreset(Shell_t * shp,struct dolnod * blk,struct dolnod * afor)5697c2fbfb3SApril Chin void sh_argreset(Shell_t *shp,struct dolnod *blk, struct dolnod *afor)
570da2e3ebdSchin {
5717c2fbfb3SApril Chin 	register Arg_t *ap = (Arg_t*)shp->arg_context;
5727c2fbfb3SApril Chin 	while(ap->argfor=sh_argfree(shp,ap->argfor,0));
573da2e3ebdSchin 	ap->argfor = afor;
574da2e3ebdSchin 	if(ap->dolh = blk)
575da2e3ebdSchin 	{
5767c2fbfb3SApril Chin 		shp->st.dolc = ap->dolh->dolnum-1;
5777c2fbfb3SApril Chin 		shp->st.dolv = ap->dolh->dolval;
578da2e3ebdSchin 	}
579da2e3ebdSchin }
580da2e3ebdSchin 
581da2e3ebdSchin /*
582da2e3ebdSchin  * increase the use count so that an sh_argset will not make it go away
583da2e3ebdSchin  */
sh_arguse(Shell_t * shp)5847c2fbfb3SApril Chin struct dolnod *sh_arguse(Shell_t* shp)
585da2e3ebdSchin {
586da2e3ebdSchin 	register struct dolnod *dh;
5877c2fbfb3SApril Chin 	register Arg_t *ap = (Arg_t*)shp->arg_context;
588da2e3ebdSchin 	if(dh=ap->dolh)
589da2e3ebdSchin 		dh->dolrefcnt++;
590da2e3ebdSchin 	return(dh);
591da2e3ebdSchin }
592da2e3ebdSchin 
593da2e3ebdSchin /*
594da2e3ebdSchin  *  Print option settings on standard output
595da2e3ebdSchin  *  if mode is inclusive or of PRINT_*
596da2e3ebdSchin  *  if <mask> is set, only options with this mask value are displayed
597da2e3ebdSchin  */
sh_printopts(Shopt_t oflags,register int mode,Shopt_t * mask)598da2e3ebdSchin void sh_printopts(Shopt_t oflags,register int mode, Shopt_t *mask)
599da2e3ebdSchin {
600da2e3ebdSchin 	register const Shtable_t *tp;
601da2e3ebdSchin 	const char *name;
602da2e3ebdSchin 	int on;
603da2e3ebdSchin 	int value;
604da2e3ebdSchin 	if(!(mode&PRINT_NO_HEADER))
605da2e3ebdSchin 		sfputr(sfstdout,sh_translate(e_heading),'\n');
606da2e3ebdSchin 	if(mode&PRINT_TABLE)
607da2e3ebdSchin 	{
608da2e3ebdSchin 		int	w;
609da2e3ebdSchin 		int	c;
610da2e3ebdSchin 		int	r;
611da2e3ebdSchin 		int	i;
612da2e3ebdSchin 
613da2e3ebdSchin 		c = 0;
614da2e3ebdSchin 		for(tp=shtab_options; value=tp->sh_number; tp++)
615da2e3ebdSchin 		{
616da2e3ebdSchin 			if(mask && !is_option(mask,value&0xff))
617da2e3ebdSchin 				continue;
618da2e3ebdSchin 			name = tp->sh_name;
619da2e3ebdSchin 			if(name[0] == 'n' && name[1] == 'o' && name[2] != 't')
620da2e3ebdSchin 				name += 2;
621da2e3ebdSchin 			if(c<(w=strlen(name)))
622da2e3ebdSchin 				c = w;
623da2e3ebdSchin 		}
624da2e3ebdSchin 		c += 4;
625da2e3ebdSchin 		if((w = ed_window()) < (2*c))
626da2e3ebdSchin 			w = 2*c;
627da2e3ebdSchin 		r = w / c;
628da2e3ebdSchin 		i = 0;
629da2e3ebdSchin 		for(tp=shtab_options; value=tp->sh_number; tp++)
630da2e3ebdSchin 		{
631da2e3ebdSchin 			if(mask && !is_option(mask,value&0xff))
632da2e3ebdSchin 				continue;
633da2e3ebdSchin 			on = !!is_option(&oflags,value);
634da2e3ebdSchin 			value &= 0xff;
635da2e3ebdSchin 			name = tp->sh_name;
636da2e3ebdSchin 			if(name[0] == 'n' && name[1] == 'o' && name[2] != 't')
637da2e3ebdSchin 			{
638da2e3ebdSchin 				name += 2;
639da2e3ebdSchin 				on = !on;
640da2e3ebdSchin 			}
641da2e3ebdSchin 			if(++i>=r)
642da2e3ebdSchin 			{
643da2e3ebdSchin 				i = 0;
644da2e3ebdSchin 				sfprintf(sfstdout, "%s%s\n", on ? "" : "no", name);
645da2e3ebdSchin 			}
646da2e3ebdSchin 			else
647da2e3ebdSchin 				sfprintf(sfstdout, "%s%-*s", on ? "" : "no", on ? c : (c-2), name);
648da2e3ebdSchin 		}
649da2e3ebdSchin 		if(i)
650da2e3ebdSchin 			sfputc(sfstdout,'\n');
651da2e3ebdSchin 		return;
652da2e3ebdSchin 	}
653da2e3ebdSchin #if SHOPT_RAWONLY
654da2e3ebdSchin 	on_option(&oflags,SH_VIRAW);
655da2e3ebdSchin #endif
656da2e3ebdSchin 	if(!(mode&(PRINT_ALL|PRINT_VERBOSE))) /* only print set options */
657da2e3ebdSchin 	{
658da2e3ebdSchin 		if(mode&PRINT_SHOPT)
659da2e3ebdSchin 			sfwrite(sfstdout,"shopt -s",3);
660da2e3ebdSchin 		else
6617c2fbfb3SApril Chin 			sfwrite(sfstdout,"set --default",13);
662da2e3ebdSchin 	}
663da2e3ebdSchin 	for(tp=shtab_options; value=tp->sh_number; tp++)
664da2e3ebdSchin 	{
665da2e3ebdSchin 		if(mask && !is_option(mask,value&0xff))
666da2e3ebdSchin 			continue;
667da2e3ebdSchin 		if(sh_isoption(SH_BASH))
668da2e3ebdSchin 		{
669da2e3ebdSchin 			if (!(mode&PRINT_SHOPT) != !(value&SH_BASHOPT))
670da2e3ebdSchin 				continue;
671da2e3ebdSchin 		}
672da2e3ebdSchin 		else if (value&(SH_BASHEXTRA|SH_BASHOPT))
673da2e3ebdSchin 			continue;
674da2e3ebdSchin 		on = !!is_option(&oflags,value);
675da2e3ebdSchin 		name = tp->sh_name;
676da2e3ebdSchin 		if(name[0] == 'n' && name[1] == 'o' && name[2] != 't')
677da2e3ebdSchin 		{
678da2e3ebdSchin 			name += 2;
679da2e3ebdSchin 			on = !on;
680da2e3ebdSchin 		}
681da2e3ebdSchin 		if(mode&PRINT_VERBOSE)
682da2e3ebdSchin 		{
683da2e3ebdSchin 			sfputr(sfstdout,name,' ');
684da2e3ebdSchin 			sfnputc(sfstdout,' ',24-strlen(name));
685da2e3ebdSchin 			sfputr(sfstdout,on ? sh_translate(e_on) : sh_translate(e_off),'\n');
686da2e3ebdSchin 		}
687da2e3ebdSchin 		else if(mode&PRINT_ALL) /* print unset options also */
688da2e3ebdSchin 		{
689da2e3ebdSchin 			if(mode&PRINT_SHOPT)
690da2e3ebdSchin 				sfprintf(sfstdout, "shopt -%c %s\n",
691da2e3ebdSchin 					on?'s':'u',
692da2e3ebdSchin 					name);
693da2e3ebdSchin 			else
694da2e3ebdSchin 				sfprintf(sfstdout, "set %co %s\n",
695da2e3ebdSchin 					on?'-':'+',
696da2e3ebdSchin 					name);
697da2e3ebdSchin 		}
698da2e3ebdSchin 		else if(!(value&SH_COMMANDLINE) && is_option(&oflags,value&0xff))
699da2e3ebdSchin 			sfprintf(sfstdout," %s%s%s",(mode&PRINT_SHOPT)?"":"--",on?"":"no",name);
700da2e3ebdSchin 	}
701da2e3ebdSchin 	if(!(mode&(PRINT_VERBOSE|PRINT_ALL)))
702da2e3ebdSchin 		sfputc(sfstdout,'\n');
703da2e3ebdSchin }
704da2e3ebdSchin 
705da2e3ebdSchin /*
706da2e3ebdSchin  * build an argument list
707da2e3ebdSchin  */
sh_argbuild(Shell_t * shp,int * nargs,const struct comnod * comptr,int flag)7087c2fbfb3SApril Chin char **sh_argbuild(Shell_t *shp,int *nargs, const struct comnod *comptr,int flag)
709da2e3ebdSchin {
710da2e3ebdSchin 	register struct argnod	*argp;
711da2e3ebdSchin 	struct argnod *arghead=0;
7127c2fbfb3SApril Chin 	shp->xargmin = 0;
713da2e3ebdSchin 	{
714da2e3ebdSchin 		register const struct comnod	*ac = comptr;
715da2e3ebdSchin 		register int n;
716da2e3ebdSchin 		/* see if the arguments have already been expanded */
717da2e3ebdSchin 		if(!ac->comarg)
718da2e3ebdSchin 		{
719da2e3ebdSchin 			*nargs = 0;
720da2e3ebdSchin 			return(&null);
721da2e3ebdSchin 		}
722da2e3ebdSchin 		else if(!(ac->comtyp&COMSCAN))
723da2e3ebdSchin 		{
724da2e3ebdSchin 			register struct dolnod *ap = (struct dolnod*)ac->comarg;
725da2e3ebdSchin 			*nargs = ap->dolnum;
726da2e3ebdSchin 			return(ap->dolval+ap->dolbot);
727da2e3ebdSchin 		}
7287c2fbfb3SApril Chin 		shp->lastpath = 0;
729da2e3ebdSchin 		*nargs = 0;
730da2e3ebdSchin 		if(ac)
731da2e3ebdSchin 		{
732da2e3ebdSchin 			if(ac->comnamp == SYSLET)
733da2e3ebdSchin 				flag |= ARG_LET;
734da2e3ebdSchin 			argp = ac->comarg;
735da2e3ebdSchin 			while(argp)
736da2e3ebdSchin 			{
7377c2fbfb3SApril Chin 				n = arg_expand(shp,argp,&arghead,flag);
738da2e3ebdSchin 				if(n>1)
739da2e3ebdSchin 				{
7407c2fbfb3SApril Chin 					if(shp->xargmin==0)
7417c2fbfb3SApril Chin 						shp->xargmin = *nargs;
7427c2fbfb3SApril Chin 					shp->xargmax = *nargs+n;
743da2e3ebdSchin 				}
744da2e3ebdSchin 				*nargs += n;
745da2e3ebdSchin 				argp = argp->argnxt.ap;
746da2e3ebdSchin 			}
747da2e3ebdSchin 			argp = arghead;
748da2e3ebdSchin 		}
749da2e3ebdSchin 	}
750da2e3ebdSchin 	{
751da2e3ebdSchin 		register char	**comargn;
752da2e3ebdSchin 		register int	argn;
753da2e3ebdSchin 		register char	**comargm;
754da2e3ebdSchin 		argn = *nargs;
755da2e3ebdSchin 		/* allow room to prepend args */
756da2e3ebdSchin 		argn += 1;
757da2e3ebdSchin 
7587c2fbfb3SApril Chin 		comargn=(char**)stkalloc(shp->stk,(unsigned)(argn+1)*sizeof(char*));
759da2e3ebdSchin 		comargm = comargn += argn;
760da2e3ebdSchin 		*comargn = NIL(char*);
761da2e3ebdSchin 		if(!argp)
762da2e3ebdSchin 		{
763da2e3ebdSchin 			/* reserve an extra null pointer */
764da2e3ebdSchin 			*--comargn = 0;
765da2e3ebdSchin 			return(comargn);
766da2e3ebdSchin 		}
767da2e3ebdSchin 		while(argp)
768da2e3ebdSchin 		{
769da2e3ebdSchin 			struct argnod *nextarg = argp->argchn.ap;
770da2e3ebdSchin 			argp->argchn.ap = 0;
771da2e3ebdSchin 			*--comargn = argp->argval;
772da2e3ebdSchin 			if(!(argp->argflag&ARG_RAW))
773da2e3ebdSchin 				sh_trim(*comargn);
774da2e3ebdSchin 			if(!(argp=nextarg) || (argp->argflag&ARG_MAKE))
775da2e3ebdSchin 			{
776da2e3ebdSchin 				if((argn=comargm-comargn)>1)
777da2e3ebdSchin 					strsort(comargn,argn,strcoll);
778da2e3ebdSchin 				comargm = comargn;
779da2e3ebdSchin 			}
780da2e3ebdSchin 		}
7817c2fbfb3SApril Chin 		shp->last_table = 0;
782da2e3ebdSchin 		return(comargn);
783da2e3ebdSchin 	}
784da2e3ebdSchin }
785da2e3ebdSchin 
786da2e3ebdSchin #if _pipe_socketpair && !_socketpair_devfd
787*b30d1939SAndy Fiddaman #   define sh_pipe(a)	sh_rpipe(a)
788da2e3ebdSchin #endif
789da2e3ebdSchin 
sh_argprocsub(Shell_t * shp,struct argnod * argp)79034f9b3eeSRoland Mainz struct argnod *sh_argprocsub(Shell_t *shp,struct argnod *argp)
79134f9b3eeSRoland Mainz {
79234f9b3eeSRoland Mainz 	/* argument of the form <(cmd) or >(cmd) */
79334f9b3eeSRoland Mainz 	register struct argnod *ap;
794*b30d1939SAndy Fiddaman 	int monitor, fd, pv[3];
79534f9b3eeSRoland Mainz 	int subshell = shp->subshell;
79634f9b3eeSRoland Mainz 	ap = (struct argnod*)stkseek(shp->stk,ARGVAL);
79734f9b3eeSRoland Mainz 	ap->argflag |= ARG_MAKE;
79834f9b3eeSRoland Mainz 	ap->argflag &= ~ARG_RAW;
799*b30d1939SAndy Fiddaman 	fd = argp->argflag&ARG_RAW;
800*b30d1939SAndy Fiddaman 	if(fd==0 && shp->subshell)
801*b30d1939SAndy Fiddaman 		sh_subtmpfile(shp);
802*b30d1939SAndy Fiddaman #if SHOPT_DEVFD
80334f9b3eeSRoland Mainz 	sfwrite(shp->stk,e_devfdNN,8);
804*b30d1939SAndy Fiddaman 	pv[2] = 0;
80534f9b3eeSRoland Mainz 	sh_pipe(pv);
806*b30d1939SAndy Fiddaman #else
807*b30d1939SAndy Fiddaman 	pv[0] = -1;
808*b30d1939SAndy Fiddaman 	shp->fifo = pathtemp(0,0,0,"ksh.fifo",0);
809*b30d1939SAndy Fiddaman 	mkfifo(shp->fifo,S_IRUSR|S_IWUSR);
810*b30d1939SAndy Fiddaman 	sfputr(shp->stk,shp->fifo,0);
811*b30d1939SAndy Fiddaman #endif /* SHOPT_DEVFD */
81234f9b3eeSRoland Mainz 	sfputr(shp->stk,fmtbase((long)pv[fd],10,0),0);
81334f9b3eeSRoland Mainz 	ap = (struct argnod*)stkfreeze(shp->stk,0);
81434f9b3eeSRoland Mainz 	shp->inpipe = shp->outpipe = 0;
81534f9b3eeSRoland Mainz 	if(monitor = (sh_isstate(SH_MONITOR)!=0))
81634f9b3eeSRoland Mainz 		sh_offstate(SH_MONITOR);
81734f9b3eeSRoland Mainz 	shp->subshell = 0;
81834f9b3eeSRoland Mainz 	if(fd)
81934f9b3eeSRoland Mainz 	{
82034f9b3eeSRoland Mainz 		shp->inpipe = pv;
82134f9b3eeSRoland Mainz 		sh_exec((Shnode_t*)argp->argchn.ap,(int)sh_isstate(SH_ERREXIT));
82234f9b3eeSRoland Mainz 	}
82334f9b3eeSRoland Mainz 	else
82434f9b3eeSRoland Mainz 	{
82534f9b3eeSRoland Mainz 		shp->outpipe = pv;
82634f9b3eeSRoland Mainz 		sh_exec((Shnode_t*)argp->argchn.ap,(int)sh_isstate(SH_ERREXIT));
82734f9b3eeSRoland Mainz 	}
82834f9b3eeSRoland Mainz 	shp->subshell = subshell;
82934f9b3eeSRoland Mainz 	if(monitor)
83034f9b3eeSRoland Mainz 		sh_onstate(SH_MONITOR);
831*b30d1939SAndy Fiddaman #if SHOPT_DEVFD
83234f9b3eeSRoland Mainz 	close(pv[1-fd]);
83334f9b3eeSRoland Mainz 	sh_iosave(shp,-pv[fd], shp->topfd, (char*)0);
834*b30d1939SAndy Fiddaman #else
835*b30d1939SAndy Fiddaman 	free(shp->fifo);
836*b30d1939SAndy Fiddaman 	shp->fifo = 0;
837*b30d1939SAndy Fiddaman #endif /* SHOPT_DEVFD */
83834f9b3eeSRoland Mainz 	return(ap);
83934f9b3eeSRoland Mainz }
84034f9b3eeSRoland Mainz 
841da2e3ebdSchin /* Argument expansion */
arg_expand(Shell_t * shp,register struct argnod * argp,struct argnod ** argchain,int flag)8427c2fbfb3SApril Chin static int arg_expand(Shell_t *shp,register struct argnod *argp, struct argnod **argchain,int flag)
843da2e3ebdSchin {
844da2e3ebdSchin 	register int count = 0;
845da2e3ebdSchin 	argp->argflag &= ~ARG_MAKE;
846da2e3ebdSchin 	if(*argp->argval==0 && (argp->argflag&ARG_EXP))
847da2e3ebdSchin 	{
84834f9b3eeSRoland Mainz 		struct argnod *ap;
84934f9b3eeSRoland Mainz 		ap = sh_argprocsub(shp,argp);
850da2e3ebdSchin 		ap->argchn.ap = *argchain;
851da2e3ebdSchin 		*argchain = ap;
852da2e3ebdSchin 		count++;
853da2e3ebdSchin 	}
854da2e3ebdSchin 	else
855da2e3ebdSchin 	if(!(argp->argflag&ARG_RAW))
856da2e3ebdSchin 	{
857da2e3ebdSchin #if SHOPT_OPTIMIZE
858da2e3ebdSchin 		struct argnod *ap;
8597c2fbfb3SApril Chin 		sh_stats(STAT_ARGEXPAND);
860da2e3ebdSchin 		if(flag&ARG_OPTIMIZE)
861da2e3ebdSchin 			argp->argchn.ap=0;
862da2e3ebdSchin 		if(ap=argp->argchn.ap)
863da2e3ebdSchin 		{
8647c2fbfb3SApril Chin 			sh_stats(STAT_ARGHITS);
865da2e3ebdSchin 			count = 1;
866da2e3ebdSchin 			ap->argchn.ap = *argchain;
867da2e3ebdSchin 			ap->argflag |= ARG_RAW;
868da2e3ebdSchin 			ap->argflag &= ~ARG_EXP;
869da2e3ebdSchin 			*argchain = ap;
870da2e3ebdSchin 		}
871da2e3ebdSchin 		else
872da2e3ebdSchin #endif /* SHOPT_OPTIMIZE */
8737c2fbfb3SApril Chin 		count = sh_macexpand(shp,argp,argchain,flag);
874da2e3ebdSchin 	}
875da2e3ebdSchin 	else
876da2e3ebdSchin 	{
877da2e3ebdSchin 		argp->argchn.ap = *argchain;
878da2e3ebdSchin 		*argchain = argp;
879da2e3ebdSchin 		argp->argflag |= ARG_MAKE;
880da2e3ebdSchin 		count++;
881da2e3ebdSchin 	}
882da2e3ebdSchin 	return(count);
883da2e3ebdSchin }
884da2e3ebdSchin 
885