1*35126Smarc /*
2*35126Smarc
3*35126Smarc * Copyright (c) 1984, 1985, 1986 AT&T
4*35126Smarc * All Rights Reserved
5*35126Smarc
6*35126Smarc * THIS IS UNPUBLISHED PROPRIETARY SOURCE
7*35126Smarc * CODE OF AT&T.
8*35126Smarc * The copyright notice above does not
9*35126Smarc * evidence any actual or intended
10*35126Smarc * publication of such source code.
11*35126Smarc
12*35126Smarc */
13*35126Smarc /* @(#)args.c 1.1 */
14*35126Smarc /*
15*35126Smarc * UNIX shell
16*35126Smarc *
17*35126Smarc * S. R. Bourne
18*35126Smarc * Rewritten by David Korn
19*35126Smarc * AT&T Bell Laboratories
20*35126Smarc *
21*35126Smarc */
22*35126Smarc
23*35126Smarc #include "flags.h"
24*35126Smarc #include "defs.h"
25*35126Smarc #include "sym.h"
26*35126Smarc #include "mode.h"
27*35126Smarc #include "name.h"
28*35126Smarc #include "io.h"
29*35126Smarc #include "builtins.h"
30*35126Smarc #include "brkincr.h"
31*35126Smarc #include "stak.h"
32*35126Smarc #ifdef DEVFD
33*35126Smarc # ifdef JOBS
34*35126Smarc #include "jobs.h"
35*35126Smarc # endif /* JOBS */
36*35126Smarc #endif /* DEVFD */
37*35126Smarc
38*35126Smarc
39*35126Smarc void arg_set();
40*35126Smarc void arg_reset();
41*35126Smarc void arg_clear();
42*35126Smarc DOLPTR arg_free();
43*35126Smarc DOLPTR arg_use();
44*35126Smarc DOLPTR arg_new();
45*35126Smarc int arg_opts();
46*35126Smarc char **arg_build();
47*35126Smarc char *arg_dolminus();
48*35126Smarc #ifdef DEVFD
49*35126Smarc void close_pipes();
50*35126Smarc #endif /* DEVFD */
51*35126Smarc
52*35126Smarc extern char *malloc();
53*35126Smarc extern char *macro();
54*35126Smarc extern char *movstr();
55*35126Smarc extern char *strchr();
56*35126Smarc extern char *itos();
57*35126Smarc extern void assign();
58*35126Smarc extern void failed();
59*35126Smarc extern void chkpipe();
60*35126Smarc extern void exitsh();
61*35126Smarc extern void free();
62*35126Smarc extern void gsort();
63*35126Smarc extern void trim();
64*35126Smarc extern void p_str();
65*35126Smarc extern void p_nchr();
66*35126Smarc extern void p_setout();
67*35126Smarc extern char *qvalup();
68*35126Smarc
69*35126Smarc static int arg_expand();
70*35126Smarc static DOLPTR copyargs();
71*35126Smarc static void print_opts();
72*35126Smarc static int split();
73*35126Smarc
74*35126Smarc static char *null;
75*35126Smarc static DOLPTR argfor; /* linked list of blocks to be cleaned up */
76*35126Smarc static DOLPTR dolh;
77*35126Smarc static char flagadr[12];
78*35126Smarc static const char flagchar[] =
79*35126Smarc {
80*35126Smarc 'i', 'n', 'v', 't', 's', 'x', 'e', 'r', 'k',
81*35126Smarc 'u', 'f', 'a', 'm', 'h', 'p', 'c', 0
82*35126Smarc };
83*35126Smarc static const optflag flagval[] =
84*35126Smarc {
85*35126Smarc INTFLG, NOEXEC, READPR, ONEFLG, STDFLG, EXECPR, ERRFLG, RSHFLG, KEYFLG,
86*35126Smarc NOSET, NOGLOB, ALLEXP, MONITOR, HASHALL, PRIVM, CFLAG, 0
87*35126Smarc };
88*35126Smarc
89*35126Smarc /* ======== option handling ======== */
90*35126Smarc
91*35126Smarc /*
92*35126Smarc * This routine turns options on and off
93*35126Smarc * The options "sicr" are illegal from set command.
94*35126Smarc * The -o option is used to set option by name
95*35126Smarc * This routine returns the number of non-option arguments
96*35126Smarc */
97*35126Smarc
arg_opts(argc,argv)98*35126Smarc int arg_opts(argc,argv)
99*35126Smarc char **argv;
100*35126Smarc int argc;
101*35126Smarc {
102*35126Smarc register char *cp;
103*35126Smarc register int c;
104*35126Smarc register char **argp=argv;
105*35126Smarc register char *flagc;
106*35126Smarc register optflag newflags=flags;
107*35126Smarc register optflag opt;
108*35126Smarc char minus;
109*35126Smarc int sort = 0;
110*35126Smarc int setflag = eq(*argp,bset);
111*35126Smarc while((cp= *++argp) && ((c= *cp) == '-' || c=='+'))
112*35126Smarc {
113*35126Smarc minus = (c == '-');
114*35126Smarc argc--;
115*35126Smarc if((c= *++cp)==0)
116*35126Smarc {
117*35126Smarc newflags &= ~(EXECPR|READPR);
118*35126Smarc argp++;
119*35126Smarc break;
120*35126Smarc }
121*35126Smarc else if(c == '-')
122*35126Smarc {
123*35126Smarc if(setflag)
124*35126Smarc states |= RWAIT;
125*35126Smarc argp++;
126*35126Smarc break;
127*35126Smarc }
128*35126Smarc while(c= *cp++)
129*35126Smarc {
130*35126Smarc if(setflag)
131*35126Smarc {
132*35126Smarc if(c=='s')
133*35126Smarc {
134*35126Smarc sort++;
135*35126Smarc continue;
136*35126Smarc }
137*35126Smarc else if(strchr("icr",c))
138*35126Smarc failed(argv[1], badopt);
139*35126Smarc }
140*35126Smarc if(c=='c' && minus && argc>=2 && comdiv==0)
141*35126Smarc {
142*35126Smarc comdiv= *++argp;
143*35126Smarc argc--;
144*35126Smarc newflags |= CFLAG;
145*35126Smarc continue;
146*35126Smarc }
147*35126Smarc if(flagc=strchr(flagchar,c))
148*35126Smarc opt = flagval[flagc-flagchar];
149*35126Smarc else if(c != 'o')
150*35126Smarc failed(argv[1],badopt);
151*35126Smarc else
152*35126Smarc {
153*35126Smarc argp++;
154*35126Smarc if(*argp==NULL)
155*35126Smarc {
156*35126Smarc print_opts(newflags);
157*35126Smarc argp--;
158*35126Smarc continue;
159*35126Smarc }
160*35126Smarc else
161*35126Smarc {
162*35126Smarc argc--;
163*35126Smarc c=syslook(*argp,option_flags);
164*35126Smarc opt = 1L<<c;
165*35126Smarc if(opt&(1|INTFLG|RSHFLG))
166*35126Smarc failed(*argp,badopt);
167*35126Smarc }
168*35126Smarc }
169*35126Smarc if(minus)
170*35126Smarc {
171*35126Smarc #if ESH || VSH
172*35126Smarc if(opt&(EDITVI|EMACS|GMACS))
173*35126Smarc newflags &= ~ (EDITVI|EMACS|GMACS);
174*35126Smarc #endif
175*35126Smarc newflags |= opt;
176*35126Smarc }
177*35126Smarc else
178*35126Smarc newflags &= ~opt;
179*35126Smarc }
180*35126Smarc }
181*35126Smarc /* cannot set -n for interactive shells since there is no way out */
182*35126Smarc if(is_option(INTFLG))
183*35126Smarc newflags &= ~NOEXEC;
184*35126Smarc #ifdef RAWONLY
185*35126Smarc if(is_option(EDITVI))
186*35126Smarc newflags |= VIRAW;
187*35126Smarc #endif /* RAWONLY */
188*35126Smarc if(sort)
189*35126Smarc {
190*35126Smarc if(argc>1)
191*35126Smarc gsort(argp,argc-1);
192*35126Smarc else
193*35126Smarc gsort(dolv+1,dolc);
194*35126Smarc }
195*35126Smarc if((newflags&PRIVM) && !is_option(PRIVM))
196*35126Smarc assign(PATHNOD,defpath);
197*35126Smarc flags = newflags;
198*35126Smarc return(argc);
199*35126Smarc }
200*35126Smarc
201*35126Smarc /*
202*35126Smarc * returns the value of $-
203*35126Smarc */
204*35126Smarc
arg_dolminus()205*35126Smarc char *arg_dolminus()
206*35126Smarc {
207*35126Smarc register char *flagc=flagchar;
208*35126Smarc register char *flagp=flagadr;
209*35126Smarc while(*flagc)
210*35126Smarc {
211*35126Smarc if(flags&flagval[flagc-flagchar])
212*35126Smarc *flagp++ = *flagc;
213*35126Smarc flagc++;
214*35126Smarc }
215*35126Smarc *flagp++=0;
216*35126Smarc return(flagadr);
217*35126Smarc }
218*35126Smarc
219*35126Smarc /*
220*35126Smarc * set up positional parameters
221*35126Smarc */
222*35126Smarc
arg_set(argi)223*35126Smarc void arg_set(argi)
224*35126Smarc char *argi[];
225*35126Smarc {
226*35126Smarc register char **argp=argi;
227*35126Smarc register int size = 0; /* count number of bytes needed for strings */
228*35126Smarc register int argn=0;
229*35126Smarc register char *cp;
230*35126Smarc /* count args and number of bytes of arglist */
231*35126Smarc while((cp=(char*)*argp++) != ENDARGS)
232*35126Smarc {
233*35126Smarc size += strlen(cp);
234*35126Smarc }
235*35126Smarc /* free old ones unless on for loop chain */
236*35126Smarc argn = argp - argi;
237*35126Smarc arg_free(dolh,0);
238*35126Smarc dolh=copyargs(argi, --argn, size);
239*35126Smarc dolc=argn-1;
240*35126Smarc }
241*35126Smarc
242*35126Smarc /*
243*35126Smarc * free the argument list if the use count is 1
244*35126Smarc * If count is greater than 1 decrement count and return same blk
245*35126Smarc * Free the argument list if the use count is 1 and return next blk
246*35126Smarc * Delete the blk from the argfor chain
247*35126Smarc * If flag is set, then the block dolh is not freed
248*35126Smarc */
249*35126Smarc
arg_free(blk,flag)250*35126Smarc DOLPTR arg_free(blk,flag)
251*35126Smarc DOLPTR blk;
252*35126Smarc {
253*35126Smarc register DOLPTR argr=blk;
254*35126Smarc register DOLPTR argblk;
255*35126Smarc if(argblk=argr)
256*35126Smarc {
257*35126Smarc if((--argblk->doluse)==0)
258*35126Smarc {
259*35126Smarc if(flag && argblk==dolh)
260*35126Smarc dolh->doluse = 1;
261*35126Smarc else
262*35126Smarc {
263*35126Smarc /* delete from chain */
264*35126Smarc if(argfor == argblk)
265*35126Smarc argfor = argblk->dolnxt;
266*35126Smarc else
267*35126Smarc {
268*35126Smarc for(argr=argfor;argr;argr=argr->dolnxt)
269*35126Smarc if(argr->dolnxt==argblk)
270*35126Smarc break;
271*35126Smarc if(argr==0)
272*35126Smarc {
273*35126Smarc return(NULL);
274*35126Smarc }
275*35126Smarc argr->dolnxt = argblk->dolnxt;
276*35126Smarc }
277*35126Smarc free((char*)argblk);
278*35126Smarc }
279*35126Smarc argr = argblk->dolnxt;
280*35126Smarc }
281*35126Smarc }
282*35126Smarc return(argr);
283*35126Smarc }
284*35126Smarc
285*35126Smarc /*
286*35126Smarc * grab space for arglist and link argblock for cleanup
287*35126Smarc * The strings are copied after the argment vector
288*35126Smarc */
289*35126Smarc
copyargs(from,n,size)290*35126Smarc static DOLPTR copyargs(from, n, size)
291*35126Smarc char *from[];
292*35126Smarc {
293*35126Smarc register DOLPTR dp=(DOLPTR)malloc((unsigned)(DOLTYPE + n*sizeof(char*) + size + n));
294*35126Smarc register char **pp;
295*35126Smarc register char *sp;
296*35126Smarc dp->doluse=1; /* use count */
297*35126Smarc /* link into chain */
298*35126Smarc dp->dolnxt = argfor;
299*35126Smarc argfor = dp;
300*35126Smarc pp= dp->dolarg;
301*35126Smarc dolv=pp;
302*35126Smarc sp = (char*)dp + DOLTYPE + n*sizeof(char*);
303*35126Smarc while(n--)
304*35126Smarc {
305*35126Smarc *pp++ = sp;
306*35126Smarc sp = movstr(*from++,sp) + 1;
307*35126Smarc }
308*35126Smarc *pp = ENDARGS;
309*35126Smarc return(dp);
310*35126Smarc }
311*35126Smarc
312*35126Smarc /*
313*35126Smarc * used to set new argument chain for functions
314*35126Smarc */
315*35126Smarc
arg_new(argi,savargfor)316*35126Smarc DOLPTR arg_new(argi,savargfor)
317*35126Smarc char *argi[];
318*35126Smarc DOLPTR *savargfor;
319*35126Smarc {
320*35126Smarc register DOLPTR olddolh = dolh;
321*35126Smarc *savargfor = argfor;
322*35126Smarc dolh = NULL;
323*35126Smarc argfor = NULL;
324*35126Smarc arg_set(argi);
325*35126Smarc return(olddolh);
326*35126Smarc }
327*35126Smarc
328*35126Smarc /*
329*35126Smarc * reset arguments as they were before function
330*35126Smarc */
331*35126Smarc
arg_reset(blk,afor)332*35126Smarc void arg_reset(blk,afor)
333*35126Smarc DOLPTR blk;
334*35126Smarc DOLPTR afor;
335*35126Smarc {
336*35126Smarc while(argfor=arg_free(argfor,0));
337*35126Smarc dolh = blk;
338*35126Smarc argfor = afor;
339*35126Smarc }
340*35126Smarc
arg_clear()341*35126Smarc void arg_clear()
342*35126Smarc {
343*35126Smarc /* force `for' $* lists to go away */
344*35126Smarc while(argfor=arg_free(argfor,1));
345*35126Smarc /* clean up io files */
346*35126Smarc argfor = dolh;
347*35126Smarc while(pop(0));
348*35126Smarc #ifdef DEVFD
349*35126Smarc close_pipes();
350*35126Smarc #endif /* DEVFD */
351*35126Smarc }
352*35126Smarc
353*35126Smarc /*
354*35126Smarc * increase the use count so that an arg_set will not make it go away
355*35126Smarc */
356*35126Smarc
arg_use()357*35126Smarc DOLPTR arg_use()
358*35126Smarc {
359*35126Smarc register DOLPTR dh;
360*35126Smarc if(dh=dolh)
361*35126Smarc dh->doluse++;
362*35126Smarc return(dh);
363*35126Smarc }
364*35126Smarc
365*35126Smarc /*
366*35126Smarc * Print option settings on standard output
367*35126Smarc */
368*35126Smarc
print_opts(oflags)369*35126Smarc static void print_opts(oflags)
370*35126Smarc #ifndef pdp11
371*35126Smarc register
372*35126Smarc #endif /* pdp11 */
373*35126Smarc optflag oflags;
374*35126Smarc {
375*35126Smarc register SYSPTR syscan = option_flags;
376*35126Smarc #ifndef pdp11
377*35126Smarc register
378*35126Smarc #endif /* pdp11 */
379*35126Smarc optflag value;
380*35126Smarc p_setout(standout);
381*35126Smarc p_str(opt_heading,NL);
382*35126Smarc while(value=syscan->sysval)
383*35126Smarc {
384*35126Smarc value = 1<<value;
385*35126Smarc p_str(syscan->sysnam,SP);
386*35126Smarc p_nchr(SP,16-strlen(syscan->sysnam));
387*35126Smarc if(oflags&value)
388*35126Smarc p_str(on_,NL);
389*35126Smarc else
390*35126Smarc p_str(off_,NL);
391*35126Smarc syscan++;
392*35126Smarc }
393*35126Smarc }
394*35126Smarc
395*35126Smarc
396*35126Smarc /*
397*35126Smarc * build an argument list
398*35126Smarc */
399*35126Smarc
arg_build(nargs,comptr)400*35126Smarc char **arg_build(nargs,comptr)
401*35126Smarc int *nargs;
402*35126Smarc COMPTR comptr;
403*35126Smarc {
404*35126Smarc register ARGPTR argp;
405*35126Smarc {
406*35126Smarc register COMPTR ac = comptr;
407*35126Smarc register ARGPTR schain;
408*35126Smarc /* see if the arguments have already been expanded */
409*35126Smarc if(ac->comarg==NULL)
410*35126Smarc {
411*35126Smarc *nargs = 0;
412*35126Smarc return(&null);
413*35126Smarc }
414*35126Smarc else if((ac->comtyp&COMSCAN)==0)
415*35126Smarc {
416*35126Smarc *nargs = ((DOLPTR)ac->comarg)->doluse;
417*35126Smarc return(((DOLPTR)ac->comarg)->dolarg+1);
418*35126Smarc }
419*35126Smarc schain = gchain;
420*35126Smarc gchain = NULL;
421*35126Smarc *nargs = arg_expand(ac);
422*35126Smarc argp = gchain;
423*35126Smarc gchain = schain;
424*35126Smarc }
425*35126Smarc {
426*35126Smarc register char **comargn;
427*35126Smarc register int argn;
428*35126Smarc register char **comargm;
429*35126Smarc argn = *nargs;
430*35126Smarc argn++; /* allow room to prepend interpreter name */
431*35126Smarc comargn=(char **) getstak(BYTESPERWORD*argn+BYTESPERWORD);
432*35126Smarc comargm = comargn += argn;
433*35126Smarc *comargn = ENDARGS;
434*35126Smarc while(argp)
435*35126Smarc {
436*35126Smarc *--comargn = argp->argval;
437*35126Smarc if((argp->argflag&A_RAW)==0)
438*35126Smarc trim(*comargn);
439*35126Smarc if((argp=argp->argchn)==0 || (argp->argflag&A_MAKE))
440*35126Smarc {
441*35126Smarc if((argn=comargm-comargn)>1)
442*35126Smarc gsort(comargn,argn);
443*35126Smarc comargm = comargn;
444*35126Smarc }
445*35126Smarc }
446*35126Smarc return(comargn);
447*35126Smarc }
448*35126Smarc }
449*35126Smarc
450*35126Smarc #ifdef DEVFD
451*35126Smarc static FILE *to_close[15];
452*35126Smarc
close_pipes()453*35126Smarc void close_pipes()
454*35126Smarc {
455*35126Smarc register FILE **fd = to_close;
456*35126Smarc while(*fd)
457*35126Smarc {
458*35126Smarc fclose(*fd);
459*35126Smarc *fd++ = NULL;
460*35126Smarc }
461*35126Smarc }
462*35126Smarc #endif /* DEVFD */
463*35126Smarc
464*35126Smarc /* Argument list generation */
465*35126Smarc
arg_expand(ac)466*35126Smarc static int arg_expand(ac)
467*35126Smarc COMPTR ac;
468*35126Smarc {
469*35126Smarc register ARGPTR argp;
470*35126Smarc register int count=0;
471*35126Smarc #ifdef DEVFD
472*35126Smarc int indx = 0;
473*35126Smarc close_pipes();
474*35126Smarc #endif /* DEVFD */
475*35126Smarc if(ac)
476*35126Smarc {
477*35126Smarc argp = ac->comarg;
478*35126Smarc while(argp)
479*35126Smarc {
480*35126Smarc argp->argflag &= ~A_MAKE;
481*35126Smarc #ifdef DEVFD
482*35126Smarc if(*argp->argval==0 && (argp->argflag&A_EXP))
483*35126Smarc {
484*35126Smarc /* argument of the form (cmd) */
485*35126Smarc register ARGPTR ap;
486*35126Smarc char *cp;
487*35126Smarc FILE *pv[2];
488*35126Smarc int fd;
489*35126Smarc ap = (ARGPTR)locstak();
490*35126Smarc ap->argflag |= A_MAKE;
491*35126Smarc ap->argflag &= ~A_RAW;
492*35126Smarc ap->argchn= gchain;
493*35126Smarc gchain = ap;
494*35126Smarc count++;
495*35126Smarc cp = movstr(devfd,ap->argval);
496*35126Smarc chkpipe(pv);
497*35126Smarc fd = argp->argflag&A_RAW;
498*35126Smarc endstak(movstr(itos(fileno(pv[fd])),cp));
499*35126Smarc if(fd)
500*35126Smarc execute((TREPTR)argp->argchn,states&ERRFLG,pv,(FILE**)0);
501*35126Smarc else
502*35126Smarc execute((TREPTR)argp->argchn,states&ERRFLG,(FILE**)0,pv);
503*35126Smarc #ifdef JOBS
504*35126Smarc jobstat.j_flag++;
505*35126Smarc #endif /* JOBS */
506*35126Smarc fclose(pv[1-fd]);
507*35126Smarc to_close[indx++] = pv[fd];
508*35126Smarc }
509*35126Smarc else
510*35126Smarc #endif /* DEVFD */
511*35126Smarc if((argp->argflag&A_RAW)==0)
512*35126Smarc {
513*35126Smarc register char *ap; ap = argp->argval;
514*35126Smarc if(argp->argflag&A_MAC)
515*35126Smarc ap = macro(ap);
516*35126Smarc count += split(ap,argp->argflag&A_MAC);
517*35126Smarc }
518*35126Smarc else
519*35126Smarc {
520*35126Smarc argp->argchn= gchain;
521*35126Smarc gchain = argp;
522*35126Smarc argp->argflag |= A_MAKE;
523*35126Smarc count++;
524*35126Smarc }
525*35126Smarc argp = argp->argnxt;
526*35126Smarc }
527*35126Smarc }
528*35126Smarc return(count);
529*35126Smarc }
530*35126Smarc
split(s,macflg)531*35126Smarc static int split(s,macflg) /* blank interpretation routine */
532*35126Smarc char *s;
533*35126Smarc {
534*35126Smarc register char *argp;
535*35126Smarc register int c;
536*35126Smarc register ARGPTR ap;
537*35126Smarc int count=0;
538*35126Smarc int expflag = (is_option(NOGLOB)==0);
539*35126Smarc char *seps = (macflg?qvalup(IFSNOD):NULL);
540*35126Smarc if(seps==NULL || *seps==0)
541*35126Smarc seps = sptbnl;
542*35126Smarc while(1)
543*35126Smarc {
544*35126Smarc if(trapnote&SIGSET)
545*35126Smarc exitsh(SIGFAIL);
546*35126Smarc ap = (ARGPTR)locstak();
547*35126Smarc argp = ap->argval;
548*35126Smarc while(c= *s++)
549*35126Smarc {
550*35126Smarc if(c == ESCAPE)
551*35126Smarc {
552*35126Smarc c = *s++;
553*35126Smarc if(c!='/')
554*35126Smarc *argp++ = ESCAPE;
555*35126Smarc }
556*35126Smarc else if(strchr(seps,c))
557*35126Smarc break;
558*35126Smarc if(argp >= brkend)
559*35126Smarc setbrk(BRKINCR);
560*35126Smarc *argp++ = c;
561*35126Smarc }
562*35126Smarc /* This allows contiguous visible delimiters to count as delimiters */
563*35126Smarc if(argp==ap->argval)
564*35126Smarc {
565*35126Smarc if(c==0)
566*35126Smarc return(count);
567*35126Smarc if(macflg==0 || strchr(sptbnl,c))
568*35126Smarc continue;
569*35126Smarc }
570*35126Smarc else if(c==0)
571*35126Smarc {
572*35126Smarc s--;
573*35126Smarc }
574*35126Smarc /* file name generation */
575*35126Smarc endstak(argp);
576*35126Smarc ap->argflag &= ~(A_RAW|A_MAKE);
577*35126Smarc if(expflag && (c=expand(ap->argval,0)))
578*35126Smarc count += c;
579*35126Smarc else
580*35126Smarc {
581*35126Smarc count++;
582*35126Smarc ap->argchn= gchain;
583*35126Smarc gchain = ap;
584*35126Smarc }
585*35126Smarc gchain->argflag |= A_MAKE;
586*35126Smarc }
587*35126Smarc }
588