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