1 /***********************************************************************
2 *                                                                      *
3 *               This software is part of the ast package               *
4 *          Copyright (c) 1982-2014 AT&T Intellectual Property          *
5 *                      and is licensed under the                       *
6 *                 Eclipse Public License, Version 1.0                  *
7 *                    by AT&T Intellectual Property                     *
8 *                                                                      *
9 *                A copy of the License is available at                 *
10 *          http://www.eclipse.org/org/documents/epl-v10.html           *
11 *         (with md5 checksum b35adb5213ca9657e911e9befb180842)         *
12 *                                                                      *
13 *              Information and Software Systems Research               *
14 *                            AT&T Research                             *
15 *                           Florham Park NJ                            *
16 *                                                                      *
17 *                    David Korn <dgkorn@gmail.com>                     *
18 *                                                                      *
19 ***********************************************************************/
20 #pragma prototyped
21 /*
22  * UNIX shell
23  *
24  * S. R. Bourne
25  * Rewritten by David Korn
26  * AT&T Labs
27  *
28  */
29 
30 #include	"defs.h"
31 #include	"path.h"
32 #include	"builtins.h"
33 #include	"terminal.h"
34 #include	"edit.h"
35 #include	"jobs.h"
36 #include	"FEATURE/poll"
37 #if SHOPT_KIA
38 #   include	"shlex.h"
39 #   include	"io.h"
40 #endif /* SHOPT_KIA */
41 #if SHOPT_PFSH
42 #   define PFSHOPT	"P"
43 #else
44 #   define PFSHOPT
45 #endif
46 #if SHOPT_BASH
47 #   define BASHOPT	"\374"
48 #else
49 #   define BASHOPT
50 #endif
51 #define HFLAG        "H"
52 
53 #define SORT		1
54 #define PRINT		2
55 
56 static	char		*null;
57 static  pid_t		*procsub;
58 
59 /* The following order is determined by sh_optset */
60 static  const char optksh[] =  PFSHOPT BASHOPT "DircabefhkmnpstuvxBCGEl" HFLAG;
61 static const int flagval[]  =
62 {
63 #if SHOPT_PFSH
64 	SH_PFSH,
65 #endif
66 #if SHOPT_BASH
67 	SH_POSIX,
68 #endif
69 	SH_DICTIONARY, SH_INTERACTIVE, SH_RESTRICTED, SH_CFLAG,
70 	SH_ALLEXPORT, SH_NOTIFY, SH_ERREXIT, SH_NOGLOB, SH_TRACKALL,
71 	SH_KEYWORD, SH_MONITOR, SH_NOEXEC, SH_PRIVILEGED, SH_SFLAG, SH_TFLAG,
72 	SH_NOUNSET, SH_VERBOSE,  SH_XTRACE, SH_BRACEEXPAND, SH_NOCLOBBER,
73 	SH_GLOBSTARS, SH_RC, SH_LOGIN_SHELL, SH_HISTEXPAND,
74 	0
75 };
76 
77 #define NUM_OPTS	(sizeof(flagval)/sizeof(*flagval))
78 
79 typedef struct _arg_
80 {
81 	Shell_t		*sh;
82 	struct dolnod	*argfor; /* linked list of blocks to be cleaned up */
83 	struct dolnod	*dolh;
84 	char flagadr[NUM_OPTS+1];
85 #if SHOPT_KIA
86 	char	*kiafile;
87 #endif /* SHOPT_KIA */
88 } Arg_t;
89 
90 static int 		arg_expand(Shell_t*,struct argnod*,struct argnod**,int);
91 static void 		sh_argset(Arg_t*, char *[]);
92 
93 #define SORT_numeric	01
94 #define SORT_reverse	02
95 struct Node
96 {
97 	union	Value 	vp;
98 	int		index;
99 	unsigned char	bits;
100 	Namval_t	*nodes[1];
101 };
102 
103 struct Sort
104 {
105 	Shell_t		*shp;
106 	Namval_t	*np;
107 	union Value	*vp;
108 	Dt_t		*root;
109 	int		cur;
110 	int		nelem;
111 	char		*flags;
112 	char		*name;
113 	struct Node	*nodes;
114 	struct Node	**nptrs;
115 	char		*keys[1];
116 };
117 
118 static struct Sort *Sp;
119 
arraysort(const char * s1,const char * s2)120 static int arraysort(const char *s1, const char *s2)
121 {
122 	struct Sort *sp = Sp;
123 	Shell_t	*shp = sp->shp;
124 	int r=0, cur=sp->cur;
125 	Namval_t *np1, *np2;
126 	Namfun_t	fun;
127 	char		*cp;
128 	memset(&fun,0,sizeof(Namfun_t));
129 	if(!(np1 = ((struct Node*)s1)->nodes[sp->cur]))
130 	{
131 		sfprintf(shp->strbuf,"%s[%i].%s%c",sp->name,((struct Node*)s1)->index,sp->keys[sp->cur],0);
132 		cp = sfstruse(shp->strbuf);
133 		np1 = nv_create(cp,sp->root,NV_VARNAME|NV_NOFAIL|NV_NOADD|NV_NOSCOPE,&fun);
134 		((struct Node*)s1)->nodes[sp->cur] = np1;
135 	}
136 	if(!(np2 = ((struct Node*)s2)->nodes[sp->cur]))
137 	{
138 		sfprintf( shp->strbuf,"%s[%i].%s%c",sp->name,((struct Node*)s2)->index,sp->keys[sp->cur],0);
139 		cp = sfstruse(shp->strbuf);
140 		np2 = nv_create(cp,sp->root,NV_VARNAME|NV_NOFAIL|NV_NOADD|NV_NOSCOPE,&fun);
141 		((struct Node*)s2)->nodes[sp->cur] = np2;
142 	}
143 	if(sp->flags[sp->cur]&SORT_numeric)
144 	{
145 		Sfdouble_t d1 = np1?nv_getnum(np1):0;
146 		Sfdouble_t d2 = np2?nv_getnum(np2):0;
147 		if(d2<d1)
148 			r = 1;
149 		else if(d2>d1)
150 			r = -1;
151 	}
152 	else if(np1 && np2)
153 	{
154 		char *sp1 = nv_getval(np1);
155 		char *sp2 = nv_getval(np2);
156 		r = strcoll(sp1,sp2);
157 
158 	}
159 	else if(np1)
160 		r = 1;
161 	else if(np2)
162 		r = -1;
163 	if(sp->flags[sp->cur]&SORT_reverse)
164 		r = -r;
165 	if(r==0 && sp->keys[++sp->cur])
166 		r = arraysort(s1,s2);
167 	sp->cur = cur;
168 	return(r);
169 }
170 
alphasort(const char * s1,const char * s2)171 static int alphasort(const char *s1, const char *s2)
172 {
173 	struct Sort	*sp = Sp;
174 	int		r = 0;
175 	char		*sp1, *sp2;
176 	nv_putsub(sp->np, NULL,((struct Node*)s1)->index,0);
177 	sp1 = nv_getval(sp->np);
178 	nv_putsub(sp->np, NULL,((struct Node*)s2)->index,0);
179 	sp2 = nv_getval(sp->np);
180 	r = strcoll(sp1,sp2);
181 	if(sp->flags[0]&SORT_reverse)
182 		r = -r;
183 	return(r);
184 }
185 
numsort(const char * s1,const char * s2)186 static int numsort(const char *s1, const char *s2)
187 {
188 	struct Sort	*sp = Sp;
189 	Sfdouble_t	d1,d2;
190 	int		r=0;
191 	nv_putsub(sp->np, NULL,((struct Node*)s1)->index,0);
192 	d1 = nv_getnum(sp->np);
193 	nv_putsub(sp->np, NULL,((struct Node*)s2)->index,0);
194 	d2 = nv_getnum(sp->np);
195 	if(d2<d1)
196 		r = 1;
197 	else if(d2>d1)
198 		r = -1;
199 	if(sp->flags[0]&SORT_reverse)
200 		r = -r;
201 	return(r);
202 }
203 
204 /* ======== option handling	======== */
205 
sh_argopen(Shell_t * shp)206 void *sh_argopen(Shell_t *shp)
207 {
208 	void *addr = newof(0,Arg_t,1,0);
209 	Arg_t *ap = (Arg_t*)addr;
210 	ap->sh = shp;
211 	return(addr);
212 }
213 
infof(Opt_t * op,Sfio_t * sp,const char * s,Optdisc_t * dp)214 static int infof(Opt_t* op, Sfio_t* sp, const char* s, Optdisc_t* dp)
215 {
216 	Shell_t *shp = sh_getinterp();
217 #if SHOPT_BASH
218 	extern const char sh_bash1[], sh_bash2[];
219 	if(strcmp(s,"bash1")==0)
220 	{
221 		if(sh_isoption(shp,SH_BASH))
222 			sfputr(sp,sh_bash1,-1);
223 	}
224 	else if(strcmp(s,"bash2")==0)
225 	{
226 		if(sh_isoption(shp,SH_BASH))
227 			sfputr(sp,sh_bash2,-1);
228 	}
229 	else if(*s==':' && sh_isoption(shp,SH_BASH))
230 		sfputr(sp,s,-1);
231 	else
232 #endif
233 	if(*s!=':')
234 		sfputr(sp,sh_set,-1);
235 	return(1);
236 }
237 
238 /*
239  *  This routine turns options on and off
240  *  The options "PDicr" are illegal from set command.
241  *  The -o option is used to set option by name
242  *  This routine returns the number of non-option arguments
243  */
sh_argopts(int argc,register char * argv[],void * context)244 int sh_argopts(int argc,register char *argv[], void *context)
245 {
246 	Shell_t		*shp = (Shell_t*)context;
247 	register int	n,o;
248 	register Arg_t	*ap = (Arg_t*)(shp->arg_context);
249 	Lex_t		*lp = (Lex_t*)(shp->lex_context);
250 	Shopt_t		newflags;
251 	int setflag=0, action=0, trace=(int)sh_isoption(shp,SH_XTRACE);
252 	Namval_t *np = NIL(Namval_t*);
253 	const char *sp;
254 	char *keylist=0;
255 	int verbose,f,unsetnp=0;
256 	Optdisc_t disc;
257 	newflags=shp->options;
258 	memset(&disc, 0, sizeof(disc));
259 	disc.version = OPT_VERSION;
260 	disc.infof = infof;
261 	opt_info.disc = &disc;
262 
263 	if(argc>0)
264 		setflag = 4;
265 	else
266 		argc = -argc;
267 	while((n = optget(argv,setflag?sh_optset:sh_optksh)))
268 	{
269 		o=0;
270 		f=*opt_info.option=='-' && (opt_info.num || opt_info.arg);
271 		switch(n)
272 		{
273 	 	    case 'A':
274 			np = nv_open(opt_info.arg,shp->var_tree,NV_NOASSIGN|NV_ARRAY|NV_VARNAME);
275 			if(f)
276 				unsetnp=1;
277 			continue;
278 	 	    case 'K':
279 			keylist = opt_info.arg;
280 			continue;
281 #if SHOPT_BASH
282 		    case 'O':	/* shopt options, only in bash mode */
283 			if(!sh_isoption(shp,SH_BASH))
284 				errormsg(SH_DICT,ERROR_exit(1), e_option, opt_info.name);
285 #endif
286 		    case 'o':	/* set options */
287 		    byname:
288 			if(!opt_info.arg||!*opt_info.arg||*opt_info.arg=='-')
289 			{
290 				action = PRINT;
291 				/* print style: -O => shopt options
292 				 * bash => print unset options also, no heading
293 				 */
294 				verbose = (f?PRINT_VERBOSE:PRINT_NO_HEADER)|
295 					  (n=='O'?PRINT_SHOPT:0)|
296 					  (sh_isoption(shp,SH_BASH)?PRINT_ALL|PRINT_NO_HEADER:0)|
297 					  ((opt_info.arg&&(!*opt_info.arg||*opt_info.arg=='-'))?(PRINT_TABLE|PRINT_NO_HEADER):0);
298 				continue;
299 			}
300 			o = sh_lookopt(opt_info.arg,&f);
301 			if(o<=0
302 				|| (!sh_isoption(shp,SH_BASH) && (o&SH_BASHEXTRA))
303 				|| ((!sh_isoption(shp,SH_BASH) || n=='o') && (o&SH_BASHOPT))
304 
305 				|| (setflag && (o&SH_COMMANDLINE)))
306 			{
307 				errormsg(SH_DICT,2, e_option, opt_info.arg);
308 				error_info.errors++;
309 			}
310 			o &= 0xff;
311 			if(sh_isoption(shp,SH_RESTRICTED) && !f && o==SH_RESTRICTED)
312 				errormsg(SH_DICT,ERROR_exit(1), e_restricted, opt_info.arg);
313 			break;
314 #if SHOPT_BASH
315 		    case -1:	/* --rcfile */
316 			shp->gd->rcfile = opt_info.arg;
317 			continue;
318 		    case -2:	/* --noediting */
319 			if (!f)
320 			{
321 				off_option(&newflags,SH_VI);
322 				off_option(&newflags,SH_EMACS);
323 				off_option(&newflags,SH_GMACS);
324 			}
325 			continue;
326 		    case -3:	/* --profile */
327 			n = 'l';
328 			goto skip;
329 		    case -4:	/* --posix */
330 			/* mask lower 8 bits to find char in optksh string */
331 			n&=0xff;
332 			goto skip;
333 		    case -5:	/* --version */
334 			sfputr(sfstdout, "ksh bash emulation, version ",-1);
335 			np = nv_open("BASH_VERSION",shp->var_tree,0);
336 			sfputr(sfstdout, nv_getval(np),-1);
337 			np = nv_open("MACHTYPE",shp->var_tree,0);
338 			sfprintf(sfstdout, " (%s)\n", nv_getval(np));
339 			sh_exit(shp,0);
340 #endif
341 		    case -6:	/* --default */
342 			{
343 				register const Shtable_t *tp;
344 				for(tp=shtab_options; o = tp->sh_number; tp++)
345 					if(!(o&SH_COMMANDLINE) && is_option(&newflags,o&0xff))
346 						off_option(&newflags,o&0xff);
347 			}
348 		    	continue;
349 	 	    case -7:
350 			f = 0;
351 		    	goto byname;
352 	 	    case 'D':
353 			on_option(&newflags,SH_NOEXEC);
354 			goto skip;
355 		    case 'T':
356 			if (opt_info.num)
357 				shp->test |= opt_info.num;
358 			else
359 				shp->test = 0;
360 		    	continue;
361 		    case 's':
362 			if(setflag)
363 			{
364 				action = SORT;
365 				continue;
366 			}
367 #if SHOPT_KIA
368 			goto skip;
369 		    case 'R':
370 			if(setflag)
371 				n = ':';
372 			else
373 			{
374 				ap->kiafile = opt_info.arg;
375 				n = 'n';
376 			}
377 			/*FALLTHROUGH*/
378 #endif /* SHOPT_KIA */
379 #if SHOPT_REGRESS
380 			goto skip;
381 		    case 'I':
382 			continue;
383 #endif /* SHOPT_REGRESS */
384 		    skip:
385 		    default:
386 			if(sp=strchr(optksh,n))
387 				o = flagval[sp-optksh];
388 			break;
389 		    case ':':
390 			if(opt_info.name[0]=='-'&&opt_info.name[1]=='-')
391 			{
392 				opt_info.arg = argv[opt_info.index-1] + 2;
393 				f = 1;
394 				goto byname;
395 			}
396 			errormsg(SH_DICT,2, "%s", opt_info.arg);
397 			continue;
398 		    case '?':
399 			errormsg(SH_DICT,ERROR_usage(0), "%s", opt_info.arg);
400 			return(-1);
401 		}
402 		if(f)
403 		{
404 			if(o==SH_VI || o==SH_EMACS || o==SH_GMACS)
405 			{
406 				off_option(&newflags,SH_VI);
407 				off_option(&newflags,SH_EMACS);
408 				off_option(&newflags,SH_GMACS);
409 			}
410 			on_option(&newflags,o);
411 			off_option(&shp->offoptions,o);
412 		}
413 		else
414 		{
415 			if(o==SH_XTRACE)
416 				trace = 0;
417 			off_option(&newflags,o);
418 			if(setflag==0)
419 				on_option(&shp->offoptions,o);
420 		}
421 	}
422 	if(error_info.errors)
423 		errormsg(SH_DICT,ERROR_usage(2),"%s",optusage(NIL(char*)));
424 	/* check for '-' or '+' argument */
425 	if((sp=argv[opt_info.index]) && sp[1]==0 && (*sp=='+' || *sp=='-') &&
426 		strcmp(argv[opt_info.index-1],"--"))
427 	{
428 		opt_info.index++;
429 		off_option(&newflags,SH_XTRACE);
430 		off_option(&newflags,SH_VERBOSE);
431 		trace = 0;
432 	}
433 	if(trace)
434 		sh_trace(shp,argv,1);
435 	argc -= opt_info.index;
436 	argv += opt_info.index;
437 	if(action==PRINT)
438 		sh_printopts(shp,newflags,verbose,0);
439 	if(setflag)
440 	{
441 		if(action==SORT)
442 		{
443 			int	(*sortfn)(const char*,const char*) = strcoll;
444 			Namarr_t	*arp;
445 			union Value	*args;
446 			unsigned char	*bits;
447 			if(argc>0)
448 				strsort(argv,argc,sortfn);
449 			else if(np && (arp=nv_arrayptr(np)) && (args = nv_aivec(np,&bits)))
450 			{
451 				struct Sort	*sp;
452 				char		*cp;
453 				int		i, c, keys=0;
454 				size_t		nodesize;
455 				if(keylist)
456 				{
457 					for(cp=keylist;c= *cp; cp++)
458 					{
459 						if(c==',')
460 							keys++;
461 					}
462 					keys++;
463 				}
464 				else
465 					keylist = Empty;
466 				arp->nelem = nv_aipack(arp);;
467 				cp = nv_name(np);
468 				c = strlen(cp);
469 				nodesize = sizeof(struct Node)+(keys-1)*sizeof(Namval_t*);
470 				sp = (struct Sort*)malloc(sizeof(struct Sort)+strlen(keylist)+(sizeof(char*)+1)*keys+(arp->nelem+1)*(nodesize+sizeof(void*))+c+3);
471 				sp->shp = shp;
472 				sp->np = np;
473 				if(!(sp->root = shp->last_root))
474 					sp->root = shp->var_tree;
475 				sp->vp = args;
476 				sp->cur = 0;
477 				sp->nodes = (struct Node*)&sp->keys[keys+2];
478 				memset(sp->nodes, 0, arp->nelem*nodesize);
479 				sp->nptrs = (struct Node**)((char*)sp->nodes+arp->nelem*nodesize);
480 				sp->flags = (char*)&sp->nptrs[arp->nelem+1];
481 				memset(sp->flags,0,keys+1);
482 				sp->name = sp->flags + keys+1;
483 				memcpy(sp->name,cp,c+1);
484 				sp->keys[0] = sp->name+c+1;
485 				strcpy(sp->keys[0],keylist);
486 				cp = (char*)sp->nodes;
487 				for(c=0; c < arp->nelem; c++)
488 				{
489 					if(keylist!=Empty && *keylist!=':')
490 					{
491 						((struct Node*)cp)->index = strtol(args[c].np->nvname,NULL,10);
492 						((struct Node*)cp)->bits = bits[c];
493 					}
494 					else
495 						((struct Node*)cp)->index = c;
496 					((struct Node*)cp)->vp = args[c];
497 					sp->nptrs[c] = (struct Node*)cp;
498 					cp += nodesize;
499 				}
500 				if(!(cp = sp->keys[0]))
501 					cp = keylist;
502 				for(keys=0;c= *cp; cp++)
503 				{
504 					if(c==',')
505 					{
506 						*cp++ = 0;
507 						sp->keys[++keys] = cp;
508 						sp->flags[keys] = 0;
509 					}
510 					else if(c==':')
511 					{
512 					again:
513 						*cp++ = 0;
514 						if((c= *cp) == 'r')
515 						{
516 							sp->flags[keys] |= SORT_reverse;
517 							c = cp[1];
518 						}
519 						else if(c=='n')
520 						{
521 							sp->flags[keys] |= SORT_numeric;
522 							c = cp[1];
523 						}
524 						if(c=='n' || c=='r')
525 							goto again;
526 
527 					}
528 				}
529 				sp->keys[++keys] = 0;
530 				Sp = sp;
531 				if(sp->keys[0] && *sp->keys[0])
532 					sortfn = arraysort;
533 				else if(sp->flags[0]&SORT_numeric)
534 					sortfn = numsort;
535 				else
536 					sortfn = alphasort;
537 				strsort((char**)sp->nptrs,arp->nelem,sortfn);
538 				cp = (char*)sp->nodes;
539 				for(c=0; c < arp->nelem; c++)
540 				{
541 					i = (char*)sp->nptrs[c]-(char*)&sp->nodes[0];
542 					if(i/nodesize !=c)
543 					{
544 						args[c] = ((struct Node*)(cp+i))->vp;
545 						bits[c] = ((struct Node*)(cp+i))->bits;
546 					}
547 				}
548 				free(sp);
549 				nv_close(np);
550 				np = 0;
551 			}
552 			else
553 				strsort(shp->st.dolv+1,shp->st.dolc,sortfn);
554 		}
555 		if(np)
556 		{
557 			if(unsetnp)
558 				nv_unset(np);
559 			nv_setvec(np,0,argc,argv);
560 			nv_close(np);
561 		}
562 		else if(argc>0 || ((sp=argv[-1]) && strcmp(sp,"--")==0))
563 			sh_argset(ap,argv-1);
564 	}
565 	else if(is_option(&newflags,SH_CFLAG))
566 	{
567 		if(!(shp->comdiv = *argv++))
568 		{
569 			errormsg(SH_DICT,2,e_cneedsarg);
570 			errormsg(SH_DICT,ERROR_usage(2),optusage(NIL(char*)));
571 		}
572 		argc--;
573 	}
574 	/* handling SH_INTERACTIVE and SH_PRIVILEGED has been moved to
575 	 * sh_applyopts(), so that the code can be reused from b_shopt(), too
576 	 */
577 	sh_applyopts(shp,newflags);
578 #if SHOPT_KIA
579 	if(ap->kiafile)
580 	{
581 		if(!argv[0])
582 			errormsg(SH_DICT,ERROR_usage(2),"-R requires scriptname");
583 		if(!(lp->kiafile=sfopen(NIL(Sfio_t*),ap->kiafile,"w+")))
584 			errormsg(SH_DICT,ERROR_system(3),e_create,ap->kiafile);
585 		if(!(lp->kiatmp=sftmp(2*SF_BUFSIZE)))
586 			errormsg(SH_DICT,ERROR_system(3),e_tmpcreate);
587 		sfputr(lp->kiafile,";vdb;CIAO/ksh",'\n');
588 		lp->kiabegin = sftell(lp->kiafile);
589 		lp->entity_tree = dtopen(&_Nvdisc,Dtbag);
590 		lp->scriptname = strdup(sh_fmtq(argv[0]));
591 		lp->script=kiaentity(lp,lp->scriptname,-1,'p',-1,0,0,'s',0,"");
592 		lp->fscript=kiaentity(lp,lp->scriptname,-1,'f',-1,0,0,'s',0,"");
593 		lp->unknown=kiaentity(lp,"<unknown>",-1,'p',-1,0,0,'0',0,"");
594 		kiaentity(lp,"<unknown>",-1,'p',0,0,lp->unknown,'0',0,"");
595 		lp->current = lp->script;
596 		ap->kiafile = 0;
597 	}
598 #endif /* SHOPT_KIA */
599 	return(argc);
600 }
601 
602 /* apply new options */
603 
sh_applyopts(Shell_t * shp,Shopt_t newflags)604 void sh_applyopts(Shell_t* shp,Shopt_t newflags)
605 {
606 	/* cannot set -n for interactive shells since there is no way out */
607 	if(sh_isoption(shp,SH_INTERACTIVE))
608 		off_option(&newflags,SH_NOEXEC);
609 	if(is_option(&newflags,SH_PRIVILEGED))
610 		on_option(&newflags,SH_NOUSRPROFILE);
611 	if(!sh_isstate(shp,SH_INIT) && is_option(&newflags,SH_PRIVILEGED) != sh_isoption(shp,SH_PRIVILEGED) || sh_isstate(shp,SH_INIT) && is_option(&((Arg_t*)shp->arg_context)->sh->offoptions,SH_PRIVILEGED) && shp->gd->userid!=shp->gd->euserid)
612 	{
613 		if(!is_option(&newflags,SH_PRIVILEGED))
614 		{
615 			setuid(shp->gd->userid);
616 			setgid(shp->gd->groupid);
617 			if(shp->gd->euserid==0)
618 			{
619 				shp->gd->euserid = shp->gd->userid;
620 				shp->gd->egroupid = shp->gd->groupid;
621 			}
622 		}
623 		else if((shp->gd->userid!=shp->gd->euserid && setuid(shp->gd->euserid)<0) ||
624 			(shp->gd->groupid!=shp->gd->egroupid && setgid(shp->gd->egroupid)<0) ||
625 			(shp->gd->userid==shp->gd->euserid && shp->gd->groupid==shp->gd->egroupid))
626 				off_option(&newflags,SH_PRIVILEGED);
627 	}
628 #if SHOPT_BASH
629 	on_option(&newflags,SH_CMDHIST);
630 	on_option(&newflags,SH_CHECKHASH);
631 	on_option(&newflags,SH_EXECFAIL);
632 	on_option(&newflags,SH_EXPAND_ALIASES);
633 	on_option(&newflags,SH_HISTAPPEND);
634 	on_option(&newflags,SH_INTERACTIVE_COMM);
635 	on_option(&newflags,SH_LITHIST);
636 	on_option(&newflags,SH_NOEMPTYCMDCOMPL);
637 
638 	if(!is_option(&newflags,SH_XPG_ECHO) && sh_isoption(shp,SH_XPG_ECHO))
639 		astconf("UNIVERSE", 0, "ucb");
640 	if(is_option(&newflags,SH_XPG_ECHO) && !sh_isoption(shp,SH_XPG_ECHO))
641 		astconf("UNIVERSE", 0, "att");
642 	if(!is_option(&newflags,SH_PHYSICAL) && sh_isoption(shp,SH_PHYSICAL))
643 		astconf("PATH_RESOLVE", 0, "metaphysical");
644 	if(is_option(&newflags,SH_PHYSICAL) && !sh_isoption(shp,SH_PHYSICAL))
645 		astconf("PATH_RESOLVE", 0, "physical");
646 	if(is_option(&newflags,SH_HISTORY2) && !sh_isoption(shp,SH_HISTORY2))
647 	{
648 		sh_onstate(shp,SH_HISTORY);
649                 sh_onoption(shp,SH_HISTORY);
650 	}
651 	if(!is_option(&newflags,SH_HISTORY2) && sh_isoption(shp,SH_HISTORY2))
652 	{
653 		sh_offstate(shp,SH_HISTORY);
654 		sh_offoption(shp,SH_HISTORY);
655 	}
656 #endif
657 	shp->options = newflags;
658 }
659 
660 /*
661  * returns the value of $-
662  */
sh_argdolminus(void * context)663 char *sh_argdolminus(void *context)
664 {
665 	Shell_t	*shp = (Shell_t*)context;
666 	register Arg_t *ap = (Arg_t*)shp->arg_context;
667 	register const char *cp=optksh;
668 	register char *flagp=ap->flagadr;
669 	while(cp< &optksh[NUM_OPTS])
670 	{
671 		int n = flagval[cp-optksh];
672 		if(sh_isoption(shp,n))
673 			*flagp++ = *cp;
674 		cp++;
675 	}
676 	*flagp = 0;
677 	return(ap->flagadr);
678 }
679 
680 /*
681  * set up positional parameters
682  */
sh_argset(Arg_t * ap,char * argv[])683 static void sh_argset(Arg_t *ap,char *argv[])
684 {
685 	sh_argfree(ap->sh,ap->dolh,0);
686 	ap->dolh = sh_argcreate(argv);
687 	/* link into chain */
688 	ap->dolh->dolnxt = ap->argfor;
689 	ap->argfor = ap->dolh;
690 	ap->sh->st.dolc = ap->dolh->dolnum-1;
691 	ap->sh->st.dolv = ap->dolh->dolval;
692 }
693 
694 /*
695  * free the argument list if the use count is 1
696  * If count is greater than 1 decrement count and return same blk
697  * Free the argument list if the use count is 1 and return next blk
698  * Delete the blk from the argfor chain
699  * If flag is set, then the block dolh is not freed
700  */
sh_argfree(Shell_t * shp,struct dolnod * blk,int flag)701 struct dolnod *sh_argfree(Shell_t *shp, struct dolnod *blk,int flag)
702 {
703 	register struct dolnod*	argr=blk;
704 	register struct dolnod*	argblk;
705 	register Arg_t *ap = (Arg_t*)shp->arg_context;
706 	if(argblk=argr)
707 	{
708 		if((--argblk->dolrefcnt)==0)
709 		{
710 			argr = argblk->dolnxt;
711 			if(flag && argblk==ap->dolh)
712 				ap->dolh->dolrefcnt = 1;
713 			else
714 			{
715 				/* delete from chain */
716 				if(ap->argfor == argblk)
717 					ap->argfor = argblk->dolnxt;
718 				else
719 				{
720 					for(argr=ap->argfor;argr;argr=argr->dolnxt)
721 						if(argr->dolnxt==argblk)
722 							break;
723 					if(!argr)
724 						return(NIL(struct dolnod*));
725 					argr->dolnxt = argblk->dolnxt;
726 					argr = argblk->dolnxt;
727 				}
728 				free((void*)argblk);
729 			}
730 		}
731 	}
732 	return(argr);
733 }
734 
735 /*
736  * grab space for arglist and copy args
737  * The strings are copied after the argment vector
738  */
sh_argcreate(register char * argv[])739 struct dolnod *sh_argcreate(register char *argv[])
740 {
741 	register struct dolnod *dp;
742 	register char **pp=argv, *sp;
743 	register int 	n;
744 	register size_t size=0;
745 	/* count args and number of bytes of arglist */
746 	while(sp= *pp++)
747 		size += strlen(sp);
748 	n = (pp - argv)-1;
749 	dp=new_of(struct dolnod,n*sizeof(char*)+size+n);
750 	dp->dolrefcnt=1;	/* use count */
751 	dp->dolnum = n;
752 	dp->dolnxt = 0;
753 	pp = dp->dolval;
754 	sp = (char*)dp + sizeof(struct dolnod) + n*sizeof(char*);
755 	while(n--)
756 	{
757 		*pp++ = sp;
758 		sp = strcopy(sp, *argv++) + 1;
759 	}
760 	*pp = NIL(char*);
761 	return(dp);
762 }
763 
764 /*
765  *  used to set new arguments for functions
766  */
sh_argnew(Shell_t * shp,char * argi[],struct dolnod ** savargfor)767 struct dolnod *sh_argnew(Shell_t *shp,char *argi[], struct dolnod **savargfor)
768 {
769 	register Arg_t *ap = (Arg_t*)shp->arg_context;
770 	register struct dolnod *olddolh = ap->dolh;
771 	*savargfor = ap->argfor;
772 	ap->dolh = 0;
773 	ap->argfor = 0;
774 	sh_argset(ap,argi);
775 	return(olddolh);
776 }
777 
778 /*
779  * reset arguments as they were before function
780  */
sh_argreset(Shell_t * shp,struct dolnod * blk,struct dolnod * afor)781 void sh_argreset(Shell_t *shp,struct dolnod *blk, struct dolnod *afor)
782 {
783 	register Arg_t *ap = (Arg_t*)shp->arg_context;
784 	while(ap->argfor=sh_argfree(shp,ap->argfor,0));
785 	ap->argfor = afor;
786 	if(ap->dolh = blk)
787 	{
788 		shp->st.dolc = ap->dolh->dolnum-1;
789 		shp->st.dolv = ap->dolh->dolval;
790 	}
791 }
792 
793 /*
794  * increase the use count so that an sh_argset will not make it go away
795  */
sh_arguse(Shell_t * shp)796 struct dolnod *sh_arguse(Shell_t* shp)
797 {
798 	register struct dolnod *dh;
799 	register Arg_t *ap = (Arg_t*)shp->arg_context;
800 	if(dh=ap->dolh)
801 		dh->dolrefcnt++;
802 	return(dh);
803 }
804 
805 /*
806  *  Print option settings on standard output
807  *  if mode is inclusive or of PRINT_*
808  *  if <mask> is set, only options with this mask value are displayed
809  */
sh_printopts(Shell_t * shp,Shopt_t oflags,register int mode,Shopt_t * mask)810 void sh_printopts(Shell_t *shp,Shopt_t oflags,register int mode, Shopt_t *mask)
811 {
812 	register const Shtable_t *tp;
813 	const char *name;
814 	int on;
815 	int value;
816 	if(!(mode&PRINT_NO_HEADER))
817 		sfputr(sfstdout,sh_translate(e_heading),'\n');
818 	if(mode&PRINT_TABLE)
819 	{
820 		size_t	w;
821 		int	c;
822 		int	r;
823 		int	i;
824 
825 		c = 0;
826 		for(tp=shtab_options; value=tp->sh_number; tp++)
827 		{
828 			if(mask && !is_option(mask,value&0xff))
829 				continue;
830 			name = tp->sh_name;
831 			if(name[0] == 'n' && name[1] == 'o' && name[2] != 't')
832 				name += 2;
833 			if(c<(w=strlen(name)))
834 				c = w;
835 		}
836 		c += 4;
837 		if((w = ed_window()) < (2*c))
838 			w = 2*c;
839 		r = w / c;
840 		i = 0;
841 		for(tp=shtab_options; value=tp->sh_number; tp++)
842 		{
843 			if(mask && !is_option(mask,value&0xff))
844 				continue;
845 			on = !!is_option(&oflags,value);
846 			value &= 0xff;
847 			name = tp->sh_name;
848 			if(name[0] == 'n' && name[1] == 'o' && name[2] != 't')
849 			{
850 				name += 2;
851 				on = !on;
852 			}
853 			if(++i>=r)
854 			{
855 				i = 0;
856 				sfprintf(sfstdout, "%s%s\n", on ? "" : "no", name);
857 			}
858 			else
859 				sfprintf(sfstdout, "%s%-*s", on ? "" : "no", on ? c : (c-2), name);
860 		}
861 		if(i)
862 			sfputc(sfstdout,'\n');
863 		return;
864 	}
865 #if SHOPT_RAWONLY
866 	on_option(&oflags,SH_VIRAW);
867 #endif
868 	if(!(mode&(PRINT_ALL|PRINT_VERBOSE))) /* only print set options */
869 	{
870 		if(mode&PRINT_SHOPT)
871 			sfwrite(sfstdout,"shopt -s",3);
872 		else
873 			sfwrite(sfstdout,"set --default",13);
874 	}
875 	for(tp=shtab_options; value=tp->sh_number; tp++)
876 	{
877 		if(mask && !is_option(mask,value&0xff))
878 			continue;
879 		if(sh_isoption(shp,SH_BASH))
880 		{
881 			if (!(mode&PRINT_SHOPT) != !(value&SH_BASHOPT))
882 				continue;
883 		}
884 		else if (value&(SH_BASHEXTRA|SH_BASHOPT))
885 			continue;
886 		on = !!is_option(&oflags,value);
887 		name = tp->sh_name;
888 		if(name[0] == 'n' && name[1] == 'o' && name[2] != 't')
889 		{
890 			name += 2;
891 			on = !on;
892 		}
893 		if(mode&PRINT_VERBOSE)
894 		{
895 			sfputr(sfstdout,name,' ');
896 			sfnputc(sfstdout,' ',24-strlen(name));
897 			sfputr(sfstdout,on ? sh_translate(e_on) : sh_translate(e_off),'\n');
898 		}
899 		else if(mode&PRINT_ALL) /* print unset options also */
900 		{
901 			if(mode&PRINT_SHOPT)
902 				sfprintf(sfstdout, "shopt -%c %s\n",
903 					on?'s':'u',
904 					name);
905 			else
906 				sfprintf(sfstdout, "set %co %s\n",
907 					on?'-':'+',
908 					name);
909 		}
910 		else if(!(value&SH_COMMANDLINE) && is_option(&oflags,value&0xff))
911 			sfprintf(sfstdout," %s%s%s",(mode&PRINT_SHOPT)?"":"--",on?"":"no",name);
912 	}
913 	if(!(mode&(PRINT_VERBOSE|PRINT_ALL)))
914 		sfputc(sfstdout,'\n');
915 }
916 
917 /*
918  * build an argument list
919  */
sh_argbuild(Shell_t * shp,int * nargs,const struct comnod * comptr,int flag)920 char **sh_argbuild(Shell_t *shp,int *nargs, const struct comnod *comptr,int flag)
921 {
922 	register struct argnod	*argp;
923 	struct argnod *arghead=0;
924 	shp->xargmin = 0;
925 	{
926 		register const struct comnod	*ac = comptr;
927 		register int n;
928 		/* see if the arguments have already been expanded */
929 		if(!ac->comarg)
930 		{
931 			*nargs = 0;
932 			return(&null);
933 		}
934 		else if(!(ac->comtyp&COMSCAN))
935 		{
936 			register struct dolnod *ap = (struct dolnod*)ac->comarg;
937 			*nargs = ap->dolnum;
938 			return(ap->dolval+ap->dolbot);
939 		}
940 		shp->lastpath = 0;
941 		procsub = shp->procsub;
942 		*nargs = 0;
943 		if(ac)
944 		{
945 			if(ac->comnamp == SYSLET)
946 				flag |= ARG_LET;
947 			argp = ac->comarg;
948 			while(argp)
949 			{
950 				n = arg_expand(shp,argp,&arghead,flag);
951 				if(n>1)
952 				{
953 					if(shp->xargmin==0)
954 						shp->xargmin = *nargs;
955 					shp->xargmax = *nargs+n;
956 				}
957 				*nargs += n;
958 				argp = argp->argnxt.ap;
959 			}
960 			argp = arghead;
961 		}
962 		if(procsub)
963 			*procsub = 0;
964 	}
965 	{
966 		register char	**comargn;
967 		register int	argn;
968 		register char	**comargm;
969 		argn = *nargs;
970 		/* allow room to prepend args */
971 		argn += 1;
972 
973 		comargn=(char**)stkalloc(shp->stk,(unsigned)(argn+1)*sizeof(char*));
974 		comargm = comargn += argn;
975 		*comargn = NIL(char*);
976 		if(!argp)
977 		{
978 			/* reserve an extra null pointer */
979 			*--comargn = 0;
980 			return(comargn);
981 		}
982 		while(argp)
983 		{
984 			struct argnod *nextarg = argp->argchn.ap;
985 			argp->argchn.ap = 0;
986 			*--comargn = argp->argval;
987 			if(!(argp->argflag&ARG_RAW))
988 				sh_trim(*comargn);
989 			if(!(argp=nextarg) || (argp->argflag&ARG_MAKE))
990 			{
991 				if((argn=comargm-comargn)>1)
992 					strsort(comargn,argn,strcoll);
993 				comargm = comargn;
994 			}
995 		}
996 		shp->last_table = 0;
997 		return(comargn);
998 	}
999 }
1000 
1001 #if _pipe_socketpair && !_socketpair_devfd
1002 #   define sh_pipe(a)	sh_rpipe(a)
1003 #endif
1004 
sh_argprocsub(Shell_t * shp,struct argnod * argp)1005 struct argnod *sh_argprocsub(Shell_t *shp,struct argnod *argp)
1006 {
1007 	/* argument of the form <(cmd) or >(cmd) */
1008 	register struct argnod *ap;
1009 	int nn, monitor, fd, pv[3];
1010 	int subshell = shp->subshell;
1011 	pid_t pid0;
1012 	ap = (struct argnod*)stkseek(shp->stk,ARGVAL);
1013 	ap->argflag |= ARG_MAKE;
1014 	ap->argflag &= ~ARG_RAW;
1015 	fd = argp->argflag&ARG_RAW;
1016 	if(fd==0 && shp->subshell)
1017 		sh_subtmpfile(shp);
1018 #if SHOPT_DEVFD
1019 	sfwrite(shp->stk,e_devfdNN,8);
1020 	pv[2] = 0;
1021 	sh_pipe(pv);
1022 	sfputr(shp->stk,fmtbase((long)pv[fd],10,0),0);
1023 #else
1024 	pv[0] = -1;
1025 	shp->fifo = pathtemp(0,0,0,"ksh.fifo",0);
1026 	mkfifo(shp->fifo,S_IRUSR|S_IWUSR);
1027 	sfputr(shp->stk,shp->fifo,0);
1028 #endif /* SHOPT_DEVFD */
1029 	ap = (struct argnod*)stkfreeze(shp->stk,0);
1030 	shp->inpipe = shp->outpipe = 0;
1031 	if(monitor = (sh_isstate(shp,SH_MONITOR)!=0))
1032 		sh_offstate(shp,SH_MONITOR);
1033 	shp->subshell = 0;
1034 #if SHOPT_DEVFD
1035 #    ifdef SPAWN_cwd
1036 	if(shp->vex || (shp->vex = (void*)spawnvex_open(0)))
1037 		spawnvex_add((Spawnvex_t*)shp->vex,pv[fd],pv[fd],0,0);
1038 	else
1039 #    endif /* SPAWN_cwd */
1040 		fcntl(pv[fd],F_SETFD,0);
1041 	shp->fdstatus[pv[fd]] &= ~IOCLEX;
1042 #endif /* SHOPT_DEVFD */
1043 	pid0=shp->procsub?*shp->procsub:0;
1044 	if(fd)
1045 	{
1046 		if(!shp->procsub)
1047 			shp->procsub = procsub = newof(0,pid_t,shp->nprocsub=4,0);
1048 		else if((nn=procsub-shp->procsub) >= shp->nprocsub)
1049 		{
1050 			shp->nprocsub += 3;
1051 			shp->procsub = newof(shp->procsub,pid_t,shp->nprocsub,0);
1052 			procsub = shp->procsub + nn;
1053 		}
1054 		if(pid0)
1055 			*shp->procsub = 0;
1056 		shp->inpipe = pv;
1057 		sh_exec(shp,(Shnode_t*)argp->argchn.ap,(int)sh_isstate(shp,SH_ERREXIT));
1058 		if(pid0)
1059 			*shp->procsub = pid0;
1060 		*procsub++ = job.lastpost;
1061 	}
1062 	else
1063 	{
1064 		shp->outpipe = pv;
1065 		sh_exec(shp,(Shnode_t*)argp->argchn.ap,(int)sh_isstate(shp,SH_ERREXIT));
1066 	}
1067 	shp->subshell = subshell;
1068 	if(monitor)
1069 		sh_onstate(shp,SH_MONITOR);
1070 #if SHOPT_DEVFD
1071 	sh_close(pv[1-fd]);
1072 	sh_iosave(shp,-pv[fd], shp->topfd, (char*)0);
1073 #else
1074 	free(shp->fifo);
1075 	shp->fifo = 0;
1076 #endif /* SHOPT_DEVFD */
1077 	return(ap);
1078 }
1079 
1080 /* Argument expansion */
arg_expand(Shell_t * shp,register struct argnod * argp,struct argnod ** argchain,int flag)1081 static int arg_expand(Shell_t *shp,register struct argnod *argp, struct argnod **argchain,int flag)
1082 {
1083 	register int count = 0;
1084 	argp->argflag &= ~ARG_MAKE;
1085 	if(*argp->argval==0 && (argp->argflag&ARG_EXP))
1086 	{
1087 		struct argnod *ap;
1088 		ap = sh_argprocsub(shp,argp);
1089 		ap->argchn.ap = *argchain;
1090 		*argchain = ap;
1091 		count++;
1092 	}
1093 	else
1094 	if(!(argp->argflag&ARG_RAW))
1095 	{
1096 #if SHOPT_OPTIMIZE
1097 		struct argnod *ap;
1098 		sh_stats(STAT_ARGEXPAND);
1099 		if(flag&ARG_OPTIMIZE)
1100 			argp->argchn.ap=0;
1101 		if(ap=argp->argchn.ap)
1102 		{
1103 			sh_stats(STAT_ARGHITS);
1104 			count = 1;
1105 			ap->argchn.ap = *argchain;
1106 			ap->argflag |= ARG_RAW;
1107 			ap->argflag &= ~ARG_EXP;
1108 			*argchain = ap;
1109 		}
1110 		else
1111 #endif /* SHOPT_OPTIMIZE */
1112 		count = sh_macexpand(shp,argp,argchain,flag);
1113 	}
1114 	else
1115 	{
1116 		argp->argchn.ap = *argchain;
1117 		*argchain = argp;
1118 		argp->argflag |= ARG_MAKE;
1119 		count++;
1120 	}
1121 	return(count);
1122 }
1123 
1124