1da2e3ebdSchin /***********************************************************************
2da2e3ebdSchin * *
3da2e3ebdSchin * This software is part of the ast package *
4*3e14f97fSRoger A. Faulkner * Copyright (c) 1982-2010 AT&T Intellectual Property *
5da2e3ebdSchin * and is licensed under the *
6da2e3ebdSchin * Common Public License, Version 1.0 *
77c2fbfb3SApril Chin * by AT&T Intellectual Property *
8da2e3ebdSchin * *
9da2e3ebdSchin * A copy of the License is available at *
10da2e3ebdSchin * http://www.opensource.org/licenses/cpl1.0.txt *
11da2e3ebdSchin * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
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 */
29da2e3ebdSchin
30da2e3ebdSchin #include "defs.h"
31da2e3ebdSchin #include "path.h"
32da2e3ebdSchin #include "builtins.h"
33da2e3ebdSchin #include "terminal.h"
34da2e3ebdSchin #include "edit.h"
35da2e3ebdSchin #include "FEATURE/poll"
36da2e3ebdSchin #if SHOPT_KIA
37da2e3ebdSchin # include "shlex.h"
38da2e3ebdSchin # include "io.h"
39da2e3ebdSchin #endif /* SHOPT_KIA */
40da2e3ebdSchin #if SHOPT_PFSH
41da2e3ebdSchin # define PFSHOPT "P"
42da2e3ebdSchin #else
43da2e3ebdSchin # define PFSHOPT
44da2e3ebdSchin #endif
45da2e3ebdSchin #if SHOPT_BASH
467c2fbfb3SApril Chin # define BASHOPT "\374"
47da2e3ebdSchin #else
48da2e3ebdSchin # define BASHOPT
49da2e3ebdSchin #endif
50da2e3ebdSchin #if SHOPT_HISTEXPAND
51da2e3ebdSchin # define HFLAG "H"
52da2e3ebdSchin #else
53da2e3ebdSchin # define HFLAG ""
54da2e3ebdSchin #endif
55da2e3ebdSchin
56da2e3ebdSchin #define SORT 1
57da2e3ebdSchin #define PRINT 2
58da2e3ebdSchin
59da2e3ebdSchin static char *null;
60da2e3ebdSchin
61da2e3ebdSchin /* The following order is determined by sh_optset */
62da2e3ebdSchin static const char optksh[] = PFSHOPT BASHOPT "DircabefhkmnpstuvxBCGEl" HFLAG;
63da2e3ebdSchin static const int flagval[] =
64da2e3ebdSchin {
65da2e3ebdSchin #if SHOPT_PFSH
66da2e3ebdSchin SH_PFSH,
67da2e3ebdSchin #endif
68da2e3ebdSchin #if SHOPT_BASH
697c2fbfb3SApril Chin SH_POSIX,
70da2e3ebdSchin #endif
71da2e3ebdSchin SH_DICTIONARY, SH_INTERACTIVE, SH_RESTRICTED, SH_CFLAG,
72da2e3ebdSchin SH_ALLEXPORT, SH_NOTIFY, SH_ERREXIT, SH_NOGLOB, SH_TRACKALL,
73da2e3ebdSchin SH_KEYWORD, SH_MONITOR, SH_NOEXEC, SH_PRIVILEGED, SH_SFLAG, SH_TFLAG,
74da2e3ebdSchin SH_NOUNSET, SH_VERBOSE, SH_XTRACE, SH_BRACEEXPAND, SH_NOCLOBBER,
75da2e3ebdSchin SH_GLOBSTARS, SH_RC, SH_LOGIN_SHELL,
76da2e3ebdSchin #if SHOPT_HISTEXPAND
77da2e3ebdSchin SH_HISTEXPAND,
78da2e3ebdSchin #endif
79da2e3ebdSchin 0
80da2e3ebdSchin };
81da2e3ebdSchin
82da2e3ebdSchin #define NUM_OPTS (sizeof(flagval)/sizeof(*flagval))
83da2e3ebdSchin
84da2e3ebdSchin typedef struct _arg_
85da2e3ebdSchin {
867c2fbfb3SApril Chin Shell_t *sh;
87da2e3ebdSchin struct dolnod *argfor; /* linked list of blocks to be cleaned up */
88da2e3ebdSchin struct dolnod *dolh;
89da2e3ebdSchin char flagadr[NUM_OPTS+1];
90da2e3ebdSchin #if SHOPT_KIA
91da2e3ebdSchin char *kiafile;
92da2e3ebdSchin #endif /* SHOPT_KIA */
93da2e3ebdSchin } Arg_t;
94da2e3ebdSchin
957c2fbfb3SApril Chin static int arg_expand(Shell_t*,struct argnod*,struct argnod**,int);
967c2fbfb3SApril Chin static void sh_argset(Arg_t*, char *[]);
977c2fbfb3SApril Chin
98da2e3ebdSchin
99da2e3ebdSchin /* ======== option handling ======== */
100da2e3ebdSchin
sh_argopen(Shell_t * shp)101da2e3ebdSchin void *sh_argopen(Shell_t *shp)
102da2e3ebdSchin {
103da2e3ebdSchin void *addr = newof(0,Arg_t,1,0);
104da2e3ebdSchin Arg_t *ap = (Arg_t*)addr;
1057c2fbfb3SApril Chin ap->sh = shp;
106da2e3ebdSchin return(addr);
107da2e3ebdSchin }
108da2e3ebdSchin
infof(Opt_t * op,Sfio_t * sp,const char * s,Optdisc_t * dp)109da2e3ebdSchin static int infof(Opt_t* op, Sfio_t* sp, const char* s, Optdisc_t* dp)
110da2e3ebdSchin {
111da2e3ebdSchin #if SHOPT_BASH
112da2e3ebdSchin extern const char sh_bash1[], sh_bash2[];
113da2e3ebdSchin if(strcmp(s,"bash1")==0)
114da2e3ebdSchin {
115da2e3ebdSchin if(sh_isoption(SH_BASH))
116da2e3ebdSchin sfputr(sp,sh_bash1,-1);
117da2e3ebdSchin }
118da2e3ebdSchin else if(strcmp(s,"bash2")==0)
119da2e3ebdSchin {
120da2e3ebdSchin if(sh_isoption(SH_BASH))
121da2e3ebdSchin sfputr(sp,sh_bash2,-1);
122da2e3ebdSchin }
123da2e3ebdSchin else if(*s==':' && sh_isoption(SH_BASH))
124da2e3ebdSchin sfputr(sp,s,-1);
125da2e3ebdSchin else
126da2e3ebdSchin #endif
127da2e3ebdSchin if(*s!=':')
128da2e3ebdSchin sfputr(sp,sh_set,-1);
129da2e3ebdSchin return(1);
130da2e3ebdSchin }
131da2e3ebdSchin
132da2e3ebdSchin /*
133da2e3ebdSchin * This routine turns options on and off
134da2e3ebdSchin * The options "PDicr" are illegal from set command.
135da2e3ebdSchin * The -o option is used to set option by name
136da2e3ebdSchin * This routine returns the number of non-option arguments
137da2e3ebdSchin */
sh_argopts(int argc,register char * argv[],void * context)1387c2fbfb3SApril Chin int sh_argopts(int argc,register char *argv[], void *context)
139da2e3ebdSchin {
1407c2fbfb3SApril Chin Shell_t *shp = (Shell_t*)context;
141da2e3ebdSchin register int n,o;
1427c2fbfb3SApril Chin register Arg_t *ap = (Arg_t*)(shp->arg_context);
1437c2fbfb3SApril Chin Lex_t *lp = (Lex_t*)(shp->lex_context);
144da2e3ebdSchin Shopt_t newflags;
145da2e3ebdSchin int setflag=0, action=0, trace=(int)sh_isoption(SH_XTRACE);
146da2e3ebdSchin Namval_t *np = NIL(Namval_t*);
147da2e3ebdSchin const char *cp;
148da2e3ebdSchin int verbose,f;
149da2e3ebdSchin Optdisc_t disc;
1507c2fbfb3SApril Chin newflags=ap->sh->options;
151da2e3ebdSchin memset(&disc, 0, sizeof(disc));
152da2e3ebdSchin disc.version = OPT_VERSION;
153da2e3ebdSchin disc.infof = infof;
154da2e3ebdSchin opt_info.disc = &disc;
155da2e3ebdSchin
156da2e3ebdSchin if(argc>0)
157da2e3ebdSchin setflag = 4;
158da2e3ebdSchin else
159da2e3ebdSchin argc = -argc;
160da2e3ebdSchin while((n = optget(argv,setflag?sh_optset:sh_optksh)))
161da2e3ebdSchin {
162da2e3ebdSchin o=0;
1637c2fbfb3SApril Chin f=*opt_info.option=='-' && (opt_info.num || opt_info.arg);
164da2e3ebdSchin switch(n)
165da2e3ebdSchin {
166da2e3ebdSchin case 'A':
1677c2fbfb3SApril Chin np = nv_open(opt_info.arg,ap->sh->var_tree,NV_NOASSIGN|NV_ARRAY|NV_VARNAME);
168da2e3ebdSchin if(f)
169da2e3ebdSchin nv_unset(np);
170da2e3ebdSchin continue;
171da2e3ebdSchin #if SHOPT_BASH
172da2e3ebdSchin case 'O': /* shopt options, only in bash mode */
173da2e3ebdSchin if(!sh_isoption(SH_BASH))
174da2e3ebdSchin errormsg(SH_DICT,ERROR_exit(1), e_option, opt_info.name);
175da2e3ebdSchin #endif
176da2e3ebdSchin case 'o': /* set options */
177da2e3ebdSchin byname:
178da2e3ebdSchin if(!opt_info.arg||!*opt_info.arg||*opt_info.arg=='-')
179da2e3ebdSchin {
180da2e3ebdSchin action = PRINT;
181da2e3ebdSchin /* print style: -O => shopt options
182da2e3ebdSchin * bash => print unset options also, no heading
183da2e3ebdSchin */
184da2e3ebdSchin verbose = (f?PRINT_VERBOSE:PRINT_NO_HEADER)|
185da2e3ebdSchin (n=='O'?PRINT_SHOPT:0)|
186da2e3ebdSchin (sh_isoption(SH_BASH)?PRINT_ALL|PRINT_NO_HEADER:0)|
187da2e3ebdSchin ((opt_info.arg&&(!*opt_info.arg||*opt_info.arg=='-'))?(PRINT_TABLE|PRINT_NO_HEADER):0);
188da2e3ebdSchin continue;
189da2e3ebdSchin }
190da2e3ebdSchin o = sh_lookopt(opt_info.arg,&f);
191da2e3ebdSchin if(o<=0
192da2e3ebdSchin || (!sh_isoption(SH_BASH) && (o&SH_BASHEXTRA))
193da2e3ebdSchin || ((!sh_isoption(SH_BASH) || n=='o') && (o&SH_BASHOPT))
194da2e3ebdSchin
195da2e3ebdSchin || (setflag && (o&SH_COMMANDLINE)))
196da2e3ebdSchin {
197da2e3ebdSchin errormsg(SH_DICT,2, e_option, opt_info.arg);
198da2e3ebdSchin error_info.errors++;
199da2e3ebdSchin }
200da2e3ebdSchin o &= 0xff;
201da2e3ebdSchin if(sh_isoption(SH_RESTRICTED) && !f && o==SH_RESTRICTED)
202da2e3ebdSchin errormsg(SH_DICT,ERROR_exit(1), e_restricted, opt_info.arg);
203da2e3ebdSchin break;
204da2e3ebdSchin #if SHOPT_BASH
205da2e3ebdSchin case -1: /* --rcfile */
2067c2fbfb3SApril Chin ap->sh->rcfile = opt_info.arg;
207da2e3ebdSchin continue;
208da2e3ebdSchin case -2: /* --noediting */
2097c2fbfb3SApril Chin if (!f)
2107c2fbfb3SApril Chin {
211da2e3ebdSchin off_option(&newflags,SH_VI);
212da2e3ebdSchin off_option(&newflags,SH_EMACS);
213da2e3ebdSchin off_option(&newflags,SH_GMACS);
2147c2fbfb3SApril Chin }
215da2e3ebdSchin continue;
216da2e3ebdSchin case -3: /* --profile */
2177c2fbfb3SApril Chin n = 'l';
2187c2fbfb3SApril Chin goto skip;
2197c2fbfb3SApril Chin case -4: /* --posix */
220da2e3ebdSchin /* mask lower 8 bits to find char in optksh string */
221da2e3ebdSchin n&=0xff;
222da2e3ebdSchin goto skip;
2237c2fbfb3SApril Chin case -5: /* --version */
2247c2fbfb3SApril Chin sfputr(sfstdout, "ksh bash emulation, version ",-1);
2257c2fbfb3SApril Chin np = nv_open("BASH_VERSION",ap->sh->var_tree,0);
2267c2fbfb3SApril Chin sfputr(sfstdout, nv_getval(np),-1);
2277c2fbfb3SApril Chin np = nv_open("MACHTYPE",ap->sh->var_tree,0);
2287c2fbfb3SApril Chin sfprintf(sfstdout, " (%s)\n", nv_getval(np));
2297c2fbfb3SApril Chin sh_exit(0);
230da2e3ebdSchin #endif
2317c2fbfb3SApril Chin case -6: /* --default */
2327c2fbfb3SApril Chin {
2337c2fbfb3SApril Chin register const Shtable_t *tp;
2347c2fbfb3SApril Chin for(tp=shtab_options; o = tp->sh_number; tp++)
2357c2fbfb3SApril Chin if(!(o&SH_COMMANDLINE) && is_option(&newflags,o&0xff))
2367c2fbfb3SApril Chin off_option(&newflags,o&0xff);
2377c2fbfb3SApril Chin }
2387c2fbfb3SApril Chin continue;
2397c2fbfb3SApril Chin case -7:
2407c2fbfb3SApril Chin f = 0;
2417c2fbfb3SApril Chin goto byname;
242da2e3ebdSchin case 'D':
243da2e3ebdSchin on_option(&newflags,SH_NOEXEC);
244da2e3ebdSchin goto skip;
2457c2fbfb3SApril Chin case 'T':
2467c2fbfb3SApril Chin if (opt_info.num)
2477c2fbfb3SApril Chin ap->sh->test |= opt_info.num;
2487c2fbfb3SApril Chin else
2497c2fbfb3SApril Chin ap->sh->test = 0;
2507c2fbfb3SApril Chin continue;
251da2e3ebdSchin case 's':
252da2e3ebdSchin if(setflag)
253da2e3ebdSchin {
254da2e3ebdSchin action = SORT;
255da2e3ebdSchin continue;
256da2e3ebdSchin }
257da2e3ebdSchin #if SHOPT_KIA
258da2e3ebdSchin goto skip;
259da2e3ebdSchin case 'R':
260da2e3ebdSchin if(setflag)
261da2e3ebdSchin n = ':';
262da2e3ebdSchin else
263da2e3ebdSchin {
264da2e3ebdSchin ap->kiafile = opt_info.arg;
265da2e3ebdSchin n = 'n';
266da2e3ebdSchin }
26734f9b3eeSRoland Mainz /*FALLTHROUGH*/
268da2e3ebdSchin #endif /* SHOPT_KIA */
26934f9b3eeSRoland Mainz #if SHOPT_REGRESS
27034f9b3eeSRoland Mainz goto skip;
27134f9b3eeSRoland Mainz case 'I':
27234f9b3eeSRoland Mainz continue;
27334f9b3eeSRoland Mainz #endif /* SHOPT_REGRESS */
274da2e3ebdSchin skip:
275da2e3ebdSchin default:
276da2e3ebdSchin if(cp=strchr(optksh,n))
277da2e3ebdSchin o = flagval[cp-optksh];
278da2e3ebdSchin break;
279da2e3ebdSchin case ':':
280da2e3ebdSchin if(opt_info.name[0]=='-'&&opt_info.name[1]=='-')
281da2e3ebdSchin {
282da2e3ebdSchin opt_info.arg = argv[opt_info.index-1] + 2;
283da2e3ebdSchin f = 1;
284da2e3ebdSchin goto byname;
285da2e3ebdSchin }
286da2e3ebdSchin errormsg(SH_DICT,2, "%s", opt_info.arg);
287da2e3ebdSchin continue;
288da2e3ebdSchin case '?':
289da2e3ebdSchin errormsg(SH_DICT,ERROR_usage(0), "%s", opt_info.arg);
290da2e3ebdSchin return(-1);
291da2e3ebdSchin }
292da2e3ebdSchin if(f)
293da2e3ebdSchin {
294da2e3ebdSchin if(o==SH_VI || o==SH_EMACS || o==SH_GMACS)
295da2e3ebdSchin {
296da2e3ebdSchin off_option(&newflags,SH_VI);
297da2e3ebdSchin off_option(&newflags,SH_EMACS);
298da2e3ebdSchin off_option(&newflags,SH_GMACS);
299da2e3ebdSchin }
300da2e3ebdSchin on_option(&newflags,o);
3017c2fbfb3SApril Chin off_option(&ap->sh->offoptions,o);
302da2e3ebdSchin }
303da2e3ebdSchin else
304da2e3ebdSchin {
305da2e3ebdSchin if(o==SH_XTRACE)
306da2e3ebdSchin trace = 0;
307da2e3ebdSchin off_option(&newflags,o);
308da2e3ebdSchin if(setflag==0)
3097c2fbfb3SApril Chin on_option(&ap->sh->offoptions,o);
310da2e3ebdSchin }
311da2e3ebdSchin }
312da2e3ebdSchin if(error_info.errors)
313da2e3ebdSchin errormsg(SH_DICT,ERROR_usage(2),"%s",optusage(NIL(char*)));
314da2e3ebdSchin /* check for '-' or '+' argument */
315da2e3ebdSchin if((cp=argv[opt_info.index]) && cp[1]==0 && (*cp=='+' || *cp=='-') &&
316da2e3ebdSchin strcmp(argv[opt_info.index-1],"--"))
317da2e3ebdSchin {
318da2e3ebdSchin opt_info.index++;
319da2e3ebdSchin off_option(&newflags,SH_XTRACE);
320da2e3ebdSchin off_option(&newflags,SH_VERBOSE);
321da2e3ebdSchin trace = 0;
322da2e3ebdSchin }
323da2e3ebdSchin if(trace)
324da2e3ebdSchin sh_trace(argv,1);
325da2e3ebdSchin argc -= opt_info.index;
326da2e3ebdSchin argv += opt_info.index;
327da2e3ebdSchin if(action==PRINT)
328da2e3ebdSchin sh_printopts(newflags,verbose,0);
329da2e3ebdSchin if(setflag)
330da2e3ebdSchin {
331da2e3ebdSchin if(action==SORT)
332da2e3ebdSchin {
333da2e3ebdSchin if(argc>0)
334da2e3ebdSchin strsort(argv,argc,strcoll);
335da2e3ebdSchin else
3367c2fbfb3SApril Chin strsort(ap->sh->st.dolv+1,ap->sh->st.dolc,strcoll);
337da2e3ebdSchin }
338da2e3ebdSchin if(np)
339da2e3ebdSchin {
340da2e3ebdSchin nv_setvec(np,0,argc,argv);
341da2e3ebdSchin nv_close(np);
342da2e3ebdSchin }
343da2e3ebdSchin else if(argc>0 || ((cp=argv[-1]) && strcmp(cp,"--")==0))
3447c2fbfb3SApril Chin sh_argset(ap,argv-1);
345da2e3ebdSchin }
346da2e3ebdSchin else if(is_option(&newflags,SH_CFLAG))
347da2e3ebdSchin {
3487c2fbfb3SApril Chin if(!(ap->sh->comdiv = *argv++))
349da2e3ebdSchin {
350da2e3ebdSchin errormsg(SH_DICT,2,e_cneedsarg);
351da2e3ebdSchin errormsg(SH_DICT,ERROR_usage(2),optusage(NIL(char*)));
352da2e3ebdSchin }
353da2e3ebdSchin argc--;
354da2e3ebdSchin }
355da2e3ebdSchin /* handling SH_INTERACTIVE and SH_PRIVILEGED has been moved to
356da2e3ebdSchin * sh_applyopts(), so that the code can be reused from b_shopt(), too
357da2e3ebdSchin */
3587c2fbfb3SApril Chin sh_applyopts(ap->sh,newflags);
359da2e3ebdSchin #if SHOPT_KIA
360da2e3ebdSchin if(ap->kiafile)
361da2e3ebdSchin {
3627c2fbfb3SApril Chin if(!argv[0])
3637c2fbfb3SApril Chin errormsg(SH_DICT,ERROR_usage(2),"-R requires scriptname");
3647c2fbfb3SApril Chin if(!(lp->kiafile=sfopen(NIL(Sfio_t*),ap->kiafile,"w+")))
365da2e3ebdSchin errormsg(SH_DICT,ERROR_system(3),e_create,ap->kiafile);
3667c2fbfb3SApril Chin if(!(lp->kiatmp=sftmp(2*SF_BUFSIZE)))
367da2e3ebdSchin errormsg(SH_DICT,ERROR_system(3),e_tmpcreate);
3687c2fbfb3SApril Chin sfputr(lp->kiafile,";vdb;CIAO/ksh",'\n');
3697c2fbfb3SApril Chin lp->kiabegin = sftell(lp->kiafile);
3707c2fbfb3SApril Chin lp->entity_tree = dtopen(&_Nvdisc,Dtbag);
3717c2fbfb3SApril Chin lp->scriptname = strdup(sh_fmtq(argv[0]));
3727c2fbfb3SApril Chin lp->script=kiaentity(lp,lp->scriptname,-1,'p',-1,0,0,'s',0,"");
3737c2fbfb3SApril Chin lp->fscript=kiaentity(lp,lp->scriptname,-1,'f',-1,0,0,'s',0,"");
3747c2fbfb3SApril Chin lp->unknown=kiaentity(lp,"<unknown>",-1,'p',-1,0,0,'0',0,"");
3757c2fbfb3SApril Chin kiaentity(lp,"<unknown>",-1,'p',0,0,lp->unknown,'0',0,"");
3767c2fbfb3SApril Chin lp->current = lp->script;
377da2e3ebdSchin ap->kiafile = 0;
378da2e3ebdSchin }
379da2e3ebdSchin #endif /* SHOPT_KIA */
380da2e3ebdSchin return(argc);
381da2e3ebdSchin }
382da2e3ebdSchin
383da2e3ebdSchin /* apply new options */
384da2e3ebdSchin
sh_applyopts(Shell_t * shp,Shopt_t newflags)3857c2fbfb3SApril Chin void sh_applyopts(Shell_t* shp,Shopt_t newflags)
386da2e3ebdSchin {
387da2e3ebdSchin /* cannot set -n for interactive shells since there is no way out */
388da2e3ebdSchin if(sh_isoption(SH_INTERACTIVE))
389da2e3ebdSchin off_option(&newflags,SH_NOEXEC);
390da2e3ebdSchin if(is_option(&newflags,SH_PRIVILEGED))
391da2e3ebdSchin on_option(&newflags,SH_NOUSRPROFILE);
39234f9b3eeSRoland Mainz 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->userid!=shp->euserid)
393da2e3ebdSchin {
39434f9b3eeSRoland Mainz if(!is_option(&newflags,SH_PRIVILEGED))
395da2e3ebdSchin {
3967c2fbfb3SApril Chin setuid(shp->userid);
3977c2fbfb3SApril Chin setgid(shp->groupid);
3987c2fbfb3SApril Chin if(shp->euserid==0)
399da2e3ebdSchin {
4007c2fbfb3SApril Chin shp->euserid = shp->userid;
4017c2fbfb3SApril Chin shp->egroupid = shp->groupid;
402da2e3ebdSchin }
403da2e3ebdSchin }
4047c2fbfb3SApril Chin else if((shp->userid!=shp->euserid && setuid(shp->euserid)<0) ||
4057c2fbfb3SApril Chin (shp->groupid!=shp->egroupid && setgid(shp->egroupid)<0) ||
4067c2fbfb3SApril Chin (shp->userid==shp->euserid && shp->groupid==shp->egroupid))
407da2e3ebdSchin off_option(&newflags,SH_PRIVILEGED);
408da2e3ebdSchin }
409da2e3ebdSchin #if SHOPT_BASH
410da2e3ebdSchin on_option(&newflags,SH_CMDHIST);
411da2e3ebdSchin on_option(&newflags,SH_CHECKHASH);
412da2e3ebdSchin on_option(&newflags,SH_EXECFAIL);
413da2e3ebdSchin on_option(&newflags,SH_EXPAND_ALIASES);
414da2e3ebdSchin on_option(&newflags,SH_HISTAPPEND);
415da2e3ebdSchin on_option(&newflags,SH_INTERACTIVE_COMM);
416da2e3ebdSchin on_option(&newflags,SH_LITHIST);
417da2e3ebdSchin on_option(&newflags,SH_NOEMPTYCMDCOMPL);
418da2e3ebdSchin
419da2e3ebdSchin if(!is_option(&newflags,SH_XPG_ECHO) && sh_isoption(SH_XPG_ECHO))
420da2e3ebdSchin astconf("UNIVERSE", 0, "ucb");
421da2e3ebdSchin if(is_option(&newflags,SH_XPG_ECHO) && !sh_isoption(SH_XPG_ECHO))
422da2e3ebdSchin astconf("UNIVERSE", 0, "att");
423da2e3ebdSchin if(!is_option(&newflags,SH_PHYSICAL) && sh_isoption(SH_PHYSICAL))
424da2e3ebdSchin astconf("PATH_RESOLVE", 0, "metaphysical");
425da2e3ebdSchin if(is_option(&newflags,SH_PHYSICAL) && !sh_isoption(SH_PHYSICAL))
426da2e3ebdSchin astconf("PATH_RESOLVE", 0, "physical");
427da2e3ebdSchin if(is_option(&newflags,SH_HISTORY2) && !sh_isoption(SH_HISTORY2))
428da2e3ebdSchin {
429da2e3ebdSchin sh_onstate(SH_HISTORY);
430da2e3ebdSchin sh_onoption(SH_HISTORY);
431da2e3ebdSchin }
432da2e3ebdSchin if(!is_option(&newflags,SH_HISTORY2) && sh_isoption(SH_HISTORY2))
433da2e3ebdSchin {
434da2e3ebdSchin sh_offstate(SH_HISTORY);
435da2e3ebdSchin sh_offoption(SH_HISTORY);
436da2e3ebdSchin }
437da2e3ebdSchin #endif
4387c2fbfb3SApril Chin shp->options = newflags;
439da2e3ebdSchin }
4407c2fbfb3SApril Chin
441da2e3ebdSchin /*
442da2e3ebdSchin * returns the value of $-
443da2e3ebdSchin */
sh_argdolminus(void * context)4447c2fbfb3SApril Chin char *sh_argdolminus(void* context)
445da2e3ebdSchin {
4467c2fbfb3SApril Chin register Arg_t *ap = (Arg_t*)context;
447da2e3ebdSchin register const char *cp=optksh;
448da2e3ebdSchin register char *flagp=ap->flagadr;
449da2e3ebdSchin while(cp< &optksh[NUM_OPTS])
450da2e3ebdSchin {
451da2e3ebdSchin int n = flagval[cp-optksh];
452da2e3ebdSchin if(sh_isoption(n))
453da2e3ebdSchin *flagp++ = *cp;
454da2e3ebdSchin cp++;
455da2e3ebdSchin }
456da2e3ebdSchin *flagp = 0;
457da2e3ebdSchin return(ap->flagadr);
458da2e3ebdSchin }
459da2e3ebdSchin
460da2e3ebdSchin /*
461da2e3ebdSchin * set up positional parameters
462da2e3ebdSchin */
sh_argset(Arg_t * ap,char * argv[])4637c2fbfb3SApril Chin static void sh_argset(Arg_t *ap,char *argv[])
464da2e3ebdSchin {
4657c2fbfb3SApril Chin sh_argfree(ap->sh,ap->dolh,0);
466da2e3ebdSchin ap->dolh = sh_argcreate(argv);
467da2e3ebdSchin /* link into chain */
468da2e3ebdSchin ap->dolh->dolnxt = ap->argfor;
469da2e3ebdSchin ap->argfor = ap->dolh;
4707c2fbfb3SApril Chin ap->sh->st.dolc = ap->dolh->dolnum-1;
4717c2fbfb3SApril Chin ap->sh->st.dolv = ap->dolh->dolval;
472da2e3ebdSchin }
473da2e3ebdSchin
474da2e3ebdSchin /*
475da2e3ebdSchin * free the argument list if the use count is 1
476da2e3ebdSchin * If count is greater than 1 decrement count and return same blk
477da2e3ebdSchin * Free the argument list if the use count is 1 and return next blk
478da2e3ebdSchin * Delete the blk from the argfor chain
479da2e3ebdSchin * If flag is set, then the block dolh is not freed
480da2e3ebdSchin */
sh_argfree(Shell_t * shp,struct dolnod * blk,int flag)4817c2fbfb3SApril Chin struct dolnod *sh_argfree(Shell_t *shp, struct dolnod *blk,int flag)
482da2e3ebdSchin {
483da2e3ebdSchin register struct dolnod* argr=blk;
484da2e3ebdSchin register struct dolnod* argblk;
4857c2fbfb3SApril Chin register Arg_t *ap = (Arg_t*)shp->arg_context;
486da2e3ebdSchin if(argblk=argr)
487da2e3ebdSchin {
488da2e3ebdSchin if((--argblk->dolrefcnt)==0)
489da2e3ebdSchin {
490da2e3ebdSchin argr = argblk->dolnxt;
491da2e3ebdSchin if(flag && argblk==ap->dolh)
492da2e3ebdSchin ap->dolh->dolrefcnt = 1;
493da2e3ebdSchin else
494da2e3ebdSchin {
495da2e3ebdSchin /* delete from chain */
496da2e3ebdSchin if(ap->argfor == argblk)
497da2e3ebdSchin ap->argfor = argblk->dolnxt;
498da2e3ebdSchin else
499da2e3ebdSchin {
500da2e3ebdSchin for(argr=ap->argfor;argr;argr=argr->dolnxt)
501da2e3ebdSchin if(argr->dolnxt==argblk)
502da2e3ebdSchin break;
503da2e3ebdSchin if(!argr)
504da2e3ebdSchin return(NIL(struct dolnod*));
505da2e3ebdSchin argr->dolnxt = argblk->dolnxt;
506da2e3ebdSchin argr = argblk->dolnxt;
507da2e3ebdSchin }
508da2e3ebdSchin free((void*)argblk);
509da2e3ebdSchin }
510da2e3ebdSchin }
511da2e3ebdSchin }
512da2e3ebdSchin return(argr);
513da2e3ebdSchin }
514da2e3ebdSchin
515da2e3ebdSchin /*
516da2e3ebdSchin * grab space for arglist and copy args
517da2e3ebdSchin * The strings are copied after the argment vector
518da2e3ebdSchin */
sh_argcreate(register char * argv[])519da2e3ebdSchin struct dolnod *sh_argcreate(register char *argv[])
520da2e3ebdSchin {
521da2e3ebdSchin register struct dolnod *dp;
522da2e3ebdSchin register char **pp=argv, *sp;
523da2e3ebdSchin register int size=0,n;
524da2e3ebdSchin /* count args and number of bytes of arglist */
525da2e3ebdSchin while(sp= *pp++)
526da2e3ebdSchin size += strlen(sp);
527da2e3ebdSchin n = (pp - argv)-1;
528da2e3ebdSchin dp=new_of(struct dolnod,n*sizeof(char*)+size+n);
529da2e3ebdSchin dp->dolrefcnt=1; /* use count */
530da2e3ebdSchin dp->dolnum = n;
531da2e3ebdSchin dp->dolnxt = 0;
532da2e3ebdSchin pp = dp->dolval;
533da2e3ebdSchin sp = (char*)dp + sizeof(struct dolnod) + n*sizeof(char*);
534da2e3ebdSchin while(n--)
535da2e3ebdSchin {
536da2e3ebdSchin *pp++ = sp;
537da2e3ebdSchin sp = strcopy(sp, *argv++) + 1;
538da2e3ebdSchin }
539da2e3ebdSchin *pp = NIL(char*);
540da2e3ebdSchin return(dp);
541da2e3ebdSchin }
542da2e3ebdSchin
543da2e3ebdSchin /*
544da2e3ebdSchin * used to set new arguments for functions
545da2e3ebdSchin */
sh_argnew(Shell_t * shp,char * argi[],struct dolnod ** savargfor)5467c2fbfb3SApril Chin struct dolnod *sh_argnew(Shell_t *shp,char *argi[], struct dolnod **savargfor)
547da2e3ebdSchin {
5487c2fbfb3SApril Chin register Arg_t *ap = (Arg_t*)shp->arg_context;
549da2e3ebdSchin register struct dolnod *olddolh = ap->dolh;
550da2e3ebdSchin *savargfor = ap->argfor;
551da2e3ebdSchin ap->dolh = 0;
552da2e3ebdSchin ap->argfor = 0;
5537c2fbfb3SApril Chin sh_argset(ap,argi);
554da2e3ebdSchin return(olddolh);
555da2e3ebdSchin }
556da2e3ebdSchin
557da2e3ebdSchin /*
558da2e3ebdSchin * reset arguments as they were before function
559da2e3ebdSchin */
sh_argreset(Shell_t * shp,struct dolnod * blk,struct dolnod * afor)5607c2fbfb3SApril Chin void sh_argreset(Shell_t *shp,struct dolnod *blk, struct dolnod *afor)
561da2e3ebdSchin {
5627c2fbfb3SApril Chin register Arg_t *ap = (Arg_t*)shp->arg_context;
5637c2fbfb3SApril Chin while(ap->argfor=sh_argfree(shp,ap->argfor,0));
564da2e3ebdSchin ap->argfor = afor;
565da2e3ebdSchin if(ap->dolh = blk)
566da2e3ebdSchin {
5677c2fbfb3SApril Chin shp->st.dolc = ap->dolh->dolnum-1;
5687c2fbfb3SApril Chin shp->st.dolv = ap->dolh->dolval;
569da2e3ebdSchin }
570da2e3ebdSchin }
571da2e3ebdSchin
572da2e3ebdSchin /*
573da2e3ebdSchin * increase the use count so that an sh_argset will not make it go away
574da2e3ebdSchin */
sh_arguse(Shell_t * shp)5757c2fbfb3SApril Chin struct dolnod *sh_arguse(Shell_t* shp)
576da2e3ebdSchin {
577da2e3ebdSchin register struct dolnod *dh;
5787c2fbfb3SApril Chin register Arg_t *ap = (Arg_t*)shp->arg_context;
579da2e3ebdSchin if(dh=ap->dolh)
580da2e3ebdSchin dh->dolrefcnt++;
581da2e3ebdSchin return(dh);
582da2e3ebdSchin }
583da2e3ebdSchin
584da2e3ebdSchin /*
585da2e3ebdSchin * Print option settings on standard output
586da2e3ebdSchin * if mode is inclusive or of PRINT_*
587da2e3ebdSchin * if <mask> is set, only options with this mask value are displayed
588da2e3ebdSchin */
sh_printopts(Shopt_t oflags,register int mode,Shopt_t * mask)589da2e3ebdSchin void sh_printopts(Shopt_t oflags,register int mode, Shopt_t *mask)
590da2e3ebdSchin {
591da2e3ebdSchin register const Shtable_t *tp;
592da2e3ebdSchin const char *name;
593da2e3ebdSchin int on;
594da2e3ebdSchin int value;
595da2e3ebdSchin if(!(mode&PRINT_NO_HEADER))
596da2e3ebdSchin sfputr(sfstdout,sh_translate(e_heading),'\n');
597da2e3ebdSchin if(mode&PRINT_TABLE)
598da2e3ebdSchin {
599da2e3ebdSchin int w;
600da2e3ebdSchin int c;
601da2e3ebdSchin int r;
602da2e3ebdSchin int i;
603da2e3ebdSchin
604da2e3ebdSchin c = 0;
605da2e3ebdSchin for(tp=shtab_options; value=tp->sh_number; tp++)
606da2e3ebdSchin {
607da2e3ebdSchin if(mask && !is_option(mask,value&0xff))
608da2e3ebdSchin continue;
609da2e3ebdSchin name = tp->sh_name;
610da2e3ebdSchin if(name[0] == 'n' && name[1] == 'o' && name[2] != 't')
611da2e3ebdSchin name += 2;
612da2e3ebdSchin if(c<(w=strlen(name)))
613da2e3ebdSchin c = w;
614da2e3ebdSchin }
615da2e3ebdSchin c += 4;
616da2e3ebdSchin if((w = ed_window()) < (2*c))
617da2e3ebdSchin w = 2*c;
618da2e3ebdSchin r = w / c;
619da2e3ebdSchin i = 0;
620da2e3ebdSchin for(tp=shtab_options; value=tp->sh_number; tp++)
621da2e3ebdSchin {
622da2e3ebdSchin if(mask && !is_option(mask,value&0xff))
623da2e3ebdSchin continue;
624da2e3ebdSchin on = !!is_option(&oflags,value);
625da2e3ebdSchin value &= 0xff;
626da2e3ebdSchin name = tp->sh_name;
627da2e3ebdSchin if(name[0] == 'n' && name[1] == 'o' && name[2] != 't')
628da2e3ebdSchin {
629da2e3ebdSchin name += 2;
630da2e3ebdSchin on = !on;
631da2e3ebdSchin }
632da2e3ebdSchin if(++i>=r)
633da2e3ebdSchin {
634da2e3ebdSchin i = 0;
635da2e3ebdSchin sfprintf(sfstdout, "%s%s\n", on ? "" : "no", name);
636da2e3ebdSchin }
637da2e3ebdSchin else
638da2e3ebdSchin sfprintf(sfstdout, "%s%-*s", on ? "" : "no", on ? c : (c-2), name);
639da2e3ebdSchin }
640da2e3ebdSchin if(i)
641da2e3ebdSchin sfputc(sfstdout,'\n');
642da2e3ebdSchin return;
643da2e3ebdSchin }
644da2e3ebdSchin #if SHOPT_RAWONLY
645da2e3ebdSchin on_option(&oflags,SH_VIRAW);
646da2e3ebdSchin #endif
647da2e3ebdSchin if(!(mode&(PRINT_ALL|PRINT_VERBOSE))) /* only print set options */
648da2e3ebdSchin {
649da2e3ebdSchin if(mode&PRINT_SHOPT)
650da2e3ebdSchin sfwrite(sfstdout,"shopt -s",3);
651da2e3ebdSchin else
6527c2fbfb3SApril Chin sfwrite(sfstdout,"set --default",13);
653da2e3ebdSchin }
654da2e3ebdSchin for(tp=shtab_options; value=tp->sh_number; tp++)
655da2e3ebdSchin {
656da2e3ebdSchin if(mask && !is_option(mask,value&0xff))
657da2e3ebdSchin continue;
658da2e3ebdSchin if(sh_isoption(SH_BASH))
659da2e3ebdSchin {
660da2e3ebdSchin if (!(mode&PRINT_SHOPT) != !(value&SH_BASHOPT))
661da2e3ebdSchin continue;
662da2e3ebdSchin }
663da2e3ebdSchin else if (value&(SH_BASHEXTRA|SH_BASHOPT))
664da2e3ebdSchin continue;
665da2e3ebdSchin on = !!is_option(&oflags,value);
666da2e3ebdSchin name = tp->sh_name;
667da2e3ebdSchin if(name[0] == 'n' && name[1] == 'o' && name[2] != 't')
668da2e3ebdSchin {
669da2e3ebdSchin name += 2;
670da2e3ebdSchin on = !on;
671da2e3ebdSchin }
672da2e3ebdSchin if(mode&PRINT_VERBOSE)
673da2e3ebdSchin {
674da2e3ebdSchin sfputr(sfstdout,name,' ');
675da2e3ebdSchin sfnputc(sfstdout,' ',24-strlen(name));
676da2e3ebdSchin sfputr(sfstdout,on ? sh_translate(e_on) : sh_translate(e_off),'\n');
677da2e3ebdSchin }
678da2e3ebdSchin else if(mode&PRINT_ALL) /* print unset options also */
679da2e3ebdSchin {
680da2e3ebdSchin if(mode&PRINT_SHOPT)
681da2e3ebdSchin sfprintf(sfstdout, "shopt -%c %s\n",
682da2e3ebdSchin on?'s':'u',
683da2e3ebdSchin name);
684da2e3ebdSchin else
685da2e3ebdSchin sfprintf(sfstdout, "set %co %s\n",
686da2e3ebdSchin on?'-':'+',
687da2e3ebdSchin name);
688da2e3ebdSchin }
689da2e3ebdSchin else if(!(value&SH_COMMANDLINE) && is_option(&oflags,value&0xff))
690da2e3ebdSchin sfprintf(sfstdout," %s%s%s",(mode&PRINT_SHOPT)?"":"--",on?"":"no",name);
691da2e3ebdSchin }
692da2e3ebdSchin if(!(mode&(PRINT_VERBOSE|PRINT_ALL)))
693da2e3ebdSchin sfputc(sfstdout,'\n');
694da2e3ebdSchin }
695da2e3ebdSchin
696da2e3ebdSchin /*
697da2e3ebdSchin * build an argument list
698da2e3ebdSchin */
sh_argbuild(Shell_t * shp,int * nargs,const struct comnod * comptr,int flag)6997c2fbfb3SApril Chin char **sh_argbuild(Shell_t *shp,int *nargs, const struct comnod *comptr,int flag)
700da2e3ebdSchin {
701da2e3ebdSchin register struct argnod *argp;
702da2e3ebdSchin struct argnod *arghead=0;
7037c2fbfb3SApril Chin shp->xargmin = 0;
704da2e3ebdSchin {
705da2e3ebdSchin register const struct comnod *ac = comptr;
706da2e3ebdSchin register int n;
707da2e3ebdSchin /* see if the arguments have already been expanded */
708da2e3ebdSchin if(!ac->comarg)
709da2e3ebdSchin {
710da2e3ebdSchin *nargs = 0;
711da2e3ebdSchin return(&null);
712da2e3ebdSchin }
713da2e3ebdSchin else if(!(ac->comtyp&COMSCAN))
714da2e3ebdSchin {
715da2e3ebdSchin register struct dolnod *ap = (struct dolnod*)ac->comarg;
716da2e3ebdSchin *nargs = ap->dolnum;
717da2e3ebdSchin return(ap->dolval+ap->dolbot);
718da2e3ebdSchin }
7197c2fbfb3SApril Chin shp->lastpath = 0;
720da2e3ebdSchin *nargs = 0;
721da2e3ebdSchin if(ac)
722da2e3ebdSchin {
723da2e3ebdSchin if(ac->comnamp == SYSLET)
724da2e3ebdSchin flag |= ARG_LET;
725da2e3ebdSchin argp = ac->comarg;
726da2e3ebdSchin while(argp)
727da2e3ebdSchin {
7287c2fbfb3SApril Chin n = arg_expand(shp,argp,&arghead,flag);
729da2e3ebdSchin if(n>1)
730da2e3ebdSchin {
7317c2fbfb3SApril Chin if(shp->xargmin==0)
7327c2fbfb3SApril Chin shp->xargmin = *nargs;
7337c2fbfb3SApril Chin shp->xargmax = *nargs+n;
734da2e3ebdSchin }
735da2e3ebdSchin *nargs += n;
736da2e3ebdSchin argp = argp->argnxt.ap;
737da2e3ebdSchin }
738da2e3ebdSchin argp = arghead;
739da2e3ebdSchin }
740da2e3ebdSchin }
741da2e3ebdSchin {
742da2e3ebdSchin register char **comargn;
743da2e3ebdSchin register int argn;
744da2e3ebdSchin register char **comargm;
745da2e3ebdSchin argn = *nargs;
746da2e3ebdSchin /* allow room to prepend args */
747da2e3ebdSchin argn += 1;
748da2e3ebdSchin
7497c2fbfb3SApril Chin comargn=(char**)stkalloc(shp->stk,(unsigned)(argn+1)*sizeof(char*));
750da2e3ebdSchin comargm = comargn += argn;
751da2e3ebdSchin *comargn = NIL(char*);
752da2e3ebdSchin if(!argp)
753da2e3ebdSchin {
754da2e3ebdSchin /* reserve an extra null pointer */
755da2e3ebdSchin *--comargn = 0;
756da2e3ebdSchin return(comargn);
757da2e3ebdSchin }
758da2e3ebdSchin while(argp)
759da2e3ebdSchin {
760da2e3ebdSchin struct argnod *nextarg = argp->argchn.ap;
761da2e3ebdSchin argp->argchn.ap = 0;
762da2e3ebdSchin *--comargn = argp->argval;
763da2e3ebdSchin if(!(argp->argflag&ARG_RAW))
764da2e3ebdSchin sh_trim(*comargn);
765da2e3ebdSchin if(!(argp=nextarg) || (argp->argflag&ARG_MAKE))
766da2e3ebdSchin {
767da2e3ebdSchin if((argn=comargm-comargn)>1)
768da2e3ebdSchin strsort(comargn,argn,strcoll);
769da2e3ebdSchin comargm = comargn;
770da2e3ebdSchin }
771da2e3ebdSchin }
7727c2fbfb3SApril Chin shp->last_table = 0;
773da2e3ebdSchin return(comargn);
774da2e3ebdSchin }
775da2e3ebdSchin }
776da2e3ebdSchin
777da2e3ebdSchin #if _pipe_socketpair && !_socketpair_devfd
778da2e3ebdSchin # define sh_pipe arg_pipe
779da2e3ebdSchin /*
780da2e3ebdSchin * create a real pipe (not a socket) and print message on failure
781da2e3ebdSchin */
arg_pipe(register int pv[])782da2e3ebdSchin static int arg_pipe(register int pv[])
783da2e3ebdSchin {
784da2e3ebdSchin int fd[2];
785da2e3ebdSchin if(pipe(fd)<0 || (pv[0]=fd[0])<0 || (pv[1]=fd[1])<0)
786da2e3ebdSchin errormsg(SH_DICT,ERROR_system(1),e_pipe);
787da2e3ebdSchin pv[0] = sh_iomovefd(pv[0]);
788da2e3ebdSchin pv[1] = sh_iomovefd(pv[1]);
789da2e3ebdSchin sh.fdstatus[pv[0]] = IONOSEEK|IOREAD;
790da2e3ebdSchin sh.fdstatus[pv[1]] = IONOSEEK|IOWRITE;
791da2e3ebdSchin sh_subsavefd(pv[0]);
792da2e3ebdSchin sh_subsavefd(pv[1]);
793da2e3ebdSchin return(0);
794da2e3ebdSchin }
795da2e3ebdSchin #endif
796da2e3ebdSchin
sh_argprocsub(Shell_t * shp,struct argnod * argp)79734f9b3eeSRoland Mainz struct argnod *sh_argprocsub(Shell_t *shp,struct argnod *argp)
798da2e3ebdSchin {
79934f9b3eeSRoland Mainz /* argument of the form <(cmd) or >(cmd) */
800da2e3ebdSchin register struct argnod *ap;
801da2e3ebdSchin int monitor, fd, pv[2];
80234f9b3eeSRoland Mainz int subshell = shp->subshell;
8037c2fbfb3SApril Chin ap = (struct argnod*)stkseek(shp->stk,ARGVAL);
804da2e3ebdSchin ap->argflag |= ARG_MAKE;
805da2e3ebdSchin ap->argflag &= ~ARG_RAW;
8067c2fbfb3SApril Chin sfwrite(shp->stk,e_devfdNN,8);
807da2e3ebdSchin sh_pipe(pv);
808da2e3ebdSchin fd = argp->argflag&ARG_RAW;
8097c2fbfb3SApril Chin sfputr(shp->stk,fmtbase((long)pv[fd],10,0),0);
8107c2fbfb3SApril Chin ap = (struct argnod*)stkfreeze(shp->stk,0);
8117c2fbfb3SApril Chin shp->inpipe = shp->outpipe = 0;
812da2e3ebdSchin if(monitor = (sh_isstate(SH_MONITOR)!=0))
813da2e3ebdSchin sh_offstate(SH_MONITOR);
81434f9b3eeSRoland Mainz shp->subshell = 0;
815da2e3ebdSchin if(fd)
816da2e3ebdSchin {
8177c2fbfb3SApril Chin shp->inpipe = pv;
818da2e3ebdSchin sh_exec((Shnode_t*)argp->argchn.ap,(int)sh_isstate(SH_ERREXIT));
819da2e3ebdSchin }
820da2e3ebdSchin else
821da2e3ebdSchin {
8227c2fbfb3SApril Chin shp->outpipe = pv;
823da2e3ebdSchin sh_exec((Shnode_t*)argp->argchn.ap,(int)sh_isstate(SH_ERREXIT));
824da2e3ebdSchin }
82534f9b3eeSRoland Mainz shp->subshell = subshell;
826da2e3ebdSchin if(monitor)
827da2e3ebdSchin sh_onstate(SH_MONITOR);
828da2e3ebdSchin close(pv[1-fd]);
8297c2fbfb3SApril Chin sh_iosave(shp,-pv[fd], shp->topfd, (char*)0);
83034f9b3eeSRoland Mainz return(ap);
83134f9b3eeSRoland Mainz }
83234f9b3eeSRoland Mainz
83334f9b3eeSRoland Mainz /* Argument expansion */
arg_expand(Shell_t * shp,register struct argnod * argp,struct argnod ** argchain,int flag)83434f9b3eeSRoland Mainz static int arg_expand(Shell_t *shp,register struct argnod *argp, struct argnod **argchain,int flag)
83534f9b3eeSRoland Mainz {
83634f9b3eeSRoland Mainz register int count = 0;
83734f9b3eeSRoland Mainz argp->argflag &= ~ARG_MAKE;
83834f9b3eeSRoland Mainz #if SHOPT_DEVFD
83934f9b3eeSRoland Mainz if(*argp->argval==0 && (argp->argflag&ARG_EXP))
84034f9b3eeSRoland Mainz {
84134f9b3eeSRoland Mainz struct argnod *ap;
84234f9b3eeSRoland Mainz ap = sh_argprocsub(shp,argp);
84334f9b3eeSRoland Mainz ap->argchn.ap = *argchain;
84434f9b3eeSRoland Mainz *argchain = ap;
84534f9b3eeSRoland Mainz count++;
846da2e3ebdSchin }
847da2e3ebdSchin else
848da2e3ebdSchin #endif /* SHOPT_DEVFD */
849da2e3ebdSchin if(!(argp->argflag&ARG_RAW))
850da2e3ebdSchin {
851da2e3ebdSchin #if SHOPT_OPTIMIZE
852da2e3ebdSchin struct argnod *ap;
8537c2fbfb3SApril Chin sh_stats(STAT_ARGEXPAND);
854da2e3ebdSchin if(flag&ARG_OPTIMIZE)
855da2e3ebdSchin argp->argchn.ap=0;
856da2e3ebdSchin if(ap=argp->argchn.ap)
857da2e3ebdSchin {
8587c2fbfb3SApril Chin sh_stats(STAT_ARGHITS);
859da2e3ebdSchin count = 1;
860da2e3ebdSchin ap->argchn.ap = *argchain;
861da2e3ebdSchin ap->argflag |= ARG_RAW;
862da2e3ebdSchin ap->argflag &= ~ARG_EXP;
863da2e3ebdSchin *argchain = ap;
864da2e3ebdSchin }
865da2e3ebdSchin else
866da2e3ebdSchin #endif /* SHOPT_OPTIMIZE */
8677c2fbfb3SApril Chin count = sh_macexpand(shp,argp,argchain,flag);
868da2e3ebdSchin }
869da2e3ebdSchin else
870da2e3ebdSchin {
871da2e3ebdSchin argp->argchn.ap = *argchain;
872da2e3ebdSchin *argchain = argp;
873da2e3ebdSchin argp->argflag |= ARG_MAKE;
874da2e3ebdSchin count++;
875da2e3ebdSchin }
876da2e3ebdSchin return(count);
877da2e3ebdSchin }
878da2e3ebdSchin
879