Patch from Terje Kvernes adding quite a lot of missing documentation
[oweals/busybox.git] / shell / msh.c
1 /* vi: set sw=4 ts=4: */
2 /*
3  * Minix shell port for busybox
4  *
5  * This version of the Minix shell was adapted for use in busybox
6  * by Erik Andersen <andersen@codepoet.org>
7  *
8  * - backtick expansion did not work properly
9  *   Jonas Holmberg <jonas.holmberg@axis.com>
10  *   Robert Schwebel <r.schwebel@pengutronix.de>
11  *   Erik Andersen <andersen@codepoet.org>
12  *
13  * This program is free software; you can redistribute it and/or modify
14  * it under the terms of the GNU General Public License as published by
15  * the Free Software Foundation; either version 2 of the License, or
16  * (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21  * General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software
25  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26  * 
27  * Original copyright notice is retained at the end of this file.
28  */
29
30 #include <ctype.h>
31 #include <dirent.h>
32 #include <errno.h>
33 #include <fcntl.h>
34 #include <limits.h>
35 #include <setjmp.h>
36 #include <signal.h>
37 #include <stddef.h>
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <string.h>
41 #include <time.h>
42 #include <unistd.h>
43 #include <sys/stat.h>
44 #include <sys/times.h>
45 #include <sys/types.h>
46 #include <sys/wait.h>
47
48 #include "cmdedit.h"
49 #include "busybox.h"
50
51
52 /* -------- sh.h -------- */
53 /*
54  * shell
55  */
56
57 #define LINELIM 2100
58 #define NPUSH   8       /* limit to input nesting */
59
60 #undef NOFILE
61 #define NOFILE  20      /* Number of open files */
62 #define NUFILE  10      /* Number of user-accessible files */
63 #define FDBASE  10      /* First file usable by Shell */
64
65 /*
66  * values returned by wait
67  */
68 #define WAITSIG(s) ((s)&0177)
69 #define WAITVAL(s) (((s)>>8)&0377)
70 #define WAITCORE(s) (((s)&0200)!=0)
71
72 /*
73  * library and system defintions
74  */
75 typedef void xint;      /* base type of jmp_buf, for not broken compilers */
76
77 /*
78  * shell components
79  */
80
81 #define QUOTE   0200
82
83 #define NOBLOCK ((struct op *)NULL)
84 #define NOWORD  ((char *)NULL)
85 #define NOWORDS ((char **)NULL)
86 #define NOPIPE  ((int *)NULL)
87
88 /*
89  * Description of a command or an operation on commands.
90  * Might eventually use a union.
91  */
92 struct op {
93         int     type;   /* operation type, see below */
94         char    **words;        /* arguments to a command */
95         struct  ioword  **ioact;        /* IO actions (eg, < > >>) */
96         struct op *left;
97         struct op *right;
98         char    *str;   /* identifier for case and for */
99 };
100
101 #define TCOM    1       /* command */
102 #define TPAREN  2       /* (c-list) */
103 #define TPIPE   3       /* a | b */
104 #define TLIST   4       /* a [&;] b */
105 #define TOR     5       /* || */
106 #define TAND    6       /* && */
107 #define TFOR    7
108 #define TDO     8
109 #define TCASE   9
110 #define TIF     10
111 #define TWHILE  11
112 #define TUNTIL  12
113 #define TELIF   13
114 #define TPAT    14      /* pattern in case */
115 #define TBRACE  15      /* {c-list} */
116 #define TASYNC  16      /* c & */
117
118 /*
119  * actions determining the environment of a process
120  */
121 #define BIT(i)  (1<<(i))
122 #define FEXEC   BIT(0)  /* execute without forking */
123
124 /*
125  * flags to control evaluation of words
126  */
127 #define DOSUB   1       /* interpret $, `, and quotes */
128 #define DOBLANK 2       /* perform blank interpretation */
129 #define DOGLOB  4       /* interpret [?* */
130 #define DOKEY   8       /* move words with `=' to 2nd arg. list */
131 #define DOTRIM  16      /* trim resulting string */
132
133 #define DOALL   (DOSUB|DOBLANK|DOGLOB|DOKEY|DOTRIM)
134
135 static  char    **dolv;
136 static  int     dolc;
137 static  int     exstat;
138 static  char    gflg;
139 static  int     interactive;    /* Is this an interactive shell */
140 static  int     execflg;
141 static  int     multiline;      /* \n changed to ; */
142 static  struct  op      *outtree;       /* result from parser */
143
144 static  xint    *failpt;
145 static  xint    *errpt;
146 static  struct brkcon   *brklist;
147 static  int     isbreak;
148 static int newfile(char *s);
149 static char *findeq(char *cp);
150 static char *cclass(char *p, int sub);
151 static void initarea(void);
152 extern int msh_main(int argc, char **argv);
153
154
155 struct  brkcon {
156         jmp_buf brkpt;
157         struct  brkcon  *nextlev;
158 } ;
159
160 /*
161  * redirection
162  */
163 struct ioword {
164         short   io_unit;        /* unit affected */
165         short   io_flag;        /* action (below) */
166         char    *io_name;       /* file name */
167 };
168 #define IOREAD  1       /* < */
169 #define IOHERE  2       /* << (here file) */
170 #define IOWRITE 4       /* > */
171 #define IOCAT   8       /* >> */
172 #define IOXHERE 16      /* ${}, ` in << */
173 #define IODUP   32      /* >&digit */
174 #define IOCLOSE 64      /* >&- */
175
176 #define IODEFAULT (-1)  /* token for default IO unit */
177
178 static  struct  wdblock *wdlist;
179 static  struct  wdblock *iolist;
180
181 /*
182  * parsing & execution environment
183  */
184 static struct   env {
185         char    *linep;
186         struct  io      *iobase;
187         struct  io      *iop;
188         xint    *errpt;
189         int     iofd;
190         struct  env     *oenv;
191 } e;
192
193 /*
194  * flags:
195  * -e: quit on error
196  * -k: look for name=value everywhere on command line
197  * -n: no execution
198  * -t: exit after reading and executing one command
199  * -v: echo as read
200  * -x: trace
201  * -u: unset variables net diagnostic
202  */
203 static  char    *flag;
204
205 static  char    *null;  /* null value for variable */
206 static  int     intr;   /* interrupt pending */
207
208 static  char    *trap[_NSIG+1];
209 static  char    ourtrap[_NSIG+1];
210 static  int     trapset;        /* trap pending */
211
212 static  int     heedint;        /* heed interrupt signals */
213
214 static  int     yynerrs;        /* yacc */
215
216 static  char    line[LINELIM];
217 static  char    *elinep;
218
219 /*
220  * other functions
221  */
222 static int(*inbuilt(char *s))(struct op *);
223
224
225 static char *rexecve (char *c , char **v, char **envp );
226 static char *space (int n );
227 static char *strsave (char *s, int a );
228 static char *evalstr (char *cp, int f );
229 static char *putn (int n );
230 static char *itoa (int n );
231 static char *unquote (char *as );
232 static struct var *lookup (char *n );
233 static int rlookup (char *n );
234 static struct wdblock *glob (char *cp, struct wdblock *wb );
235 static int my_getc( int ec);
236 static int subgetc (int ec, int quoted );
237 static char **makenv (void);
238 static char **eval (char **ap, int f );
239 static int setstatus (int s );
240 static int waitfor (int lastpid, int canintr );
241
242 static void onintr (int s ); /* SIGINT handler */
243
244 static int newenv (int f );
245 static void quitenv (void);
246 static void err (char *s );
247 static int anys (char *s1, char *s2 );
248 static int any (int c, char *s );
249 static void next (int f );
250 static void setdash (void);
251 static void onecommand (void);
252 static void runtrap (int i );
253 static int gmatch (char *s, char *p );
254
255 /*
256  * error handling
257  */
258 static void leave (void); /* abort shell (or fail in subshell) */
259 static void fail (void);         /* fail but return to process next command */
260 static void warn (char *s );
261 static void sig (int i );        /* default signal handler */
262
263
264
265 /* -------- area stuff -------- */
266
267 #define REGSIZE         sizeof(struct region)
268 #define GROWBY          256
269 //#define       SHRINKBY   64
270 #undef  SHRINKBY
271 #define FREE 32767
272 #define BUSY 0
273 #define ALIGN (sizeof(int)-1)
274
275
276 struct region {
277         struct  region *next;
278         int     area;
279 };
280
281
282
283 /* -------- grammar stuff -------- */
284 typedef union {
285         char    *cp;
286         char    **wp;
287         int     i;
288         struct  op *o;
289 } YYSTYPE;
290 #define WORD    256
291 #define LOGAND  257
292 #define LOGOR   258
293 #define BREAK   259
294 #define IF      260
295 #define THEN    261
296 #define ELSE    262
297 #define ELIF    263
298 #define FI      264
299 #define CASE    265
300 #define ESAC    266
301 #define FOR     267
302 #define WHILE   268
303 #define UNTIL   269
304 #define DO      270
305 #define DONE    271
306 #define IN      272
307 #define YYERRCODE 300
308
309 /* flags to yylex */
310 #define CONTIN  01      /* skip new lines to complete command */
311
312 #define SYNTAXERR       zzerr()
313 static struct op *pipeline(int cf );
314 static struct op *andor(void);
315 static struct op *c_list(void);
316 static int synio(int cf );
317 static void musthave (int c, int cf );
318 static struct op *simple(void);
319 static struct op *nested(int type, int mark );
320 static struct op *command(int cf );
321 static struct op *dogroup(int onlydone );
322 static struct op *thenpart(void);
323 static struct op *elsepart(void);
324 static struct op *caselist(void);
325 static struct op *casepart(void);
326 static char **pattern(void);
327 static char **wordlist(void);
328 static struct op *list(struct op *t1, struct op *t2 );
329 static struct op *block(int type, struct op *t1, struct op *t2, char **wp );
330 static struct op *newtp(void);
331 static struct op *namelist(struct op *t );
332 static char **copyw(void);
333 static void word(char *cp );
334 static struct ioword **copyio(void);
335 static struct ioword *io (int u, int f, char *cp );
336 static void zzerr(void);
337 static void yyerror(char *s );
338 static int yylex(int cf );
339 static int collect(int c, int c1 );
340 static int dual(int c );
341 static void diag(int ec );
342 static char *tree(unsigned size );
343
344 /* -------- var.h -------- */
345
346 struct  var {
347         char    *value;
348         char    *name;
349         struct  var     *next;
350         char    status;
351 };
352 #define COPYV   1       /* flag to setval, suggesting copy */
353 #define RONLY   01      /* variable is read-only */
354 #define EXPORT  02      /* variable is to be exported */
355 #define GETCELL 04      /* name & value space was got with getcell */
356
357 static  struct  var     *vlist;         /* dictionary */
358
359 static  struct  var     *homedir;       /* home directory */
360 static  struct  var     *prompt;        /* main prompt */
361 static  struct  var     *cprompt;       /* continuation prompt */
362 static  struct  var     *path;          /* search path for commands */
363 static  struct  var     *shell;         /* shell to interpret command files */
364 static  struct  var     *ifs;           /* field separators */
365
366 static int yyparse (void);
367 static struct var *lookup (char *n );
368 static void setval (struct var *vp, char *val );
369 static void nameval (struct var *vp, char *val, char *name );
370 static void export (struct var *vp );
371 static void ronly (struct var *vp );
372 static int isassign (char *s );
373 static int checkname (char *cp );
374 static int assign (char *s, int cf );
375 static void putvlist (int f, int out );
376 static int eqname (char *n1, char *n2 );
377
378 static int execute (struct op *t, int *pin, int *pout, int act );
379
380 /* -------- io.h -------- */
381 /* io buffer */
382 struct iobuf {
383   unsigned id;                          /* buffer id */
384   char buf[512];                        /* buffer */
385   char *bufp;                           /* pointer into buffer */
386   char *ebufp;                          /* pointer to end of buffer */
387 };
388
389 /* possible arguments to an IO function */
390 struct ioarg {
391         char    *aword;
392         char    **awordlist;
393         int     afile;          /* file descriptor */
394         unsigned afid;          /* buffer id */
395         long    afpos;          /* file position */
396         struct iobuf *afbuf;    /* buffer for this file */
397 };
398 //static struct ioarg ioargstack[NPUSH];
399 #define AFID_NOBUF      (~0)
400 #define AFID_ID         0
401
402 /* an input generator's state */
403 struct  io {
404         int     (*iofn)(struct  ioarg *, struct io *);
405         struct  ioarg   *argp;
406         int     peekc;
407         char    prev;           /* previous character read by readc() */
408         char    nlcount;        /* for `'s */
409         char    xchar;          /* for `'s */
410         char    task;           /* reason for pushed IO */
411 };
412 //static        struct  io      iostack[NPUSH];
413 #define XOTHER  0       /* none of the below */
414 #define XDOLL   1       /* expanding ${} */
415 #define XGRAVE  2       /* expanding `'s */
416 #define XIO     3       /* file IO */
417
418 /* in substitution */
419 #define INSUB() (e.iop->task == XGRAVE || e.iop->task == XDOLL)
420
421 /*
422  * input generators for IO structure
423  */
424 static int nlchar (struct ioarg *ap );
425 static int strchar (struct ioarg *ap );
426 static int qstrchar (struct ioarg *ap );
427 static int filechar (struct ioarg *ap );
428 static int herechar (struct ioarg *ap );
429 static int linechar (struct ioarg *ap );
430 static int gravechar (struct ioarg *ap, struct io *iop );
431 static int qgravechar (struct ioarg *ap, struct io *iop );
432 static int dolchar (struct ioarg *ap );
433 static int wdchar (struct ioarg *ap );
434 static void scraphere (void);
435 static void freehere (int area );
436 static void gethere (void);
437 static void markhere (char *s, struct ioword *iop );
438 static int herein (char *hname, int xdoll );
439 static int run (struct ioarg *argp, int (*f)(struct ioarg *));
440
441 /*
442  * IO functions
443  */
444 static int eofc (void);
445 static int readc (void);
446 static void unget (int c );
447 static void ioecho (int c );
448 static void prs (char *s );
449 static void prn (unsigned u );
450 static void closef (int i );
451 static void closeall (void);
452
453 /*
454  * IO control
455  */
456 static void pushio (struct ioarg *argp, int (*f)(struct ioarg *));
457 static int remap (int fd );
458 static int openpipe (int *pv );
459 static void closepipe (int *pv );
460 static struct io *setbase (struct io *ip );
461
462 static  struct  ioarg   temparg;        /* temporary for PUSHIO */
463 #define PUSHIO(what,arg,gen) ((temparg.what = (arg)),pushio(&temparg,(gen)))
464 #define RUN(what,arg,gen) ((temparg.what = (arg)), run(&temparg,(gen)))
465
466 /* -------- word.h -------- */
467
468 #define NSTART  16      /* default number of words to allow for initially */
469
470 struct  wdblock {
471         short   w_bsize;
472         short   w_nword;
473         /* bounds are arbitrary */
474         char    *w_words[1];
475 };
476
477 static struct wdblock *addword (char *wd, struct wdblock *wb );
478 static struct wdblock *newword (int nw );
479 static char **getwords (struct wdblock *wb );
480
481 /* -------- area.h -------- */
482
483 /*
484  * storage allocation
485  */
486 static char *getcell (unsigned nbytes );
487 static void garbage (void);
488 static void setarea (char *cp, int a );
489 static int getarea (char *cp );
490 static void freearea (int a );
491 static void freecell (char *cp );
492 static  int     areanum;        /* current allocation area */
493
494 #define NEW(type) (type *)getcell(sizeof(type))
495 #define DELETE(obj)     freecell((char *)obj)
496
497
498 /* -------- misc stuff -------- */
499
500 static int forkexec (struct op *t, int *pin, int *pout, int act, char **wp, int *pforked );
501 static int iosetup (struct ioword *iop, int pipein, int pipeout );
502 static void echo(char **wp );
503 static struct op **find1case (struct op *t, char *w );
504 static struct op *findcase (struct op *t, char *w );
505 static void brkset(struct brkcon *bc );
506 static int dolabel(struct op *t );
507 static int dohelp(struct op *t );
508 static int dochdir(struct op *t );
509 static int doshift(struct op *t );
510 static int dologin(struct op *t );
511 static int doumask(struct op *t );
512 static int doexec(struct op *t );
513 static int dodot(struct op *t );
514 static int dowait(struct op *t );
515 static int doread(struct op *t );
516 static int doeval(struct op *t );
517 static int dotrap(struct op *t );
518 static int getsig(char *s );
519 static void setsig (int n, sighandler_t f);
520 static int getn(char *as );
521 static int dobreak(struct op *t );
522 static int docontinue(struct op *t );
523 static int brkcontin (char *cp, int val );
524 static int doexit(struct op *t );
525 static int doexport(struct op *t );
526 static int doreadonly(struct op *t );
527 static void rdexp (char **wp, void (*f)(struct var *), int key);
528 static void badid(char *s );
529 static int doset(struct op *t );
530 static void varput (char *s, int out );
531 static int dotimes(struct op *t );
532 static int expand (char *cp, struct wdblock **wbp, int f );
533 static char *blank(int f );
534 static int dollar(int quoted );
535 static int grave(int quoted );
536 static void globname (char *we, char *pp );
537 static char *generate (char *start1, char *end1, char *middle, char *end );
538 static int anyspcl(struct wdblock *wb );
539 static int xstrcmp (char *p1, char *p2 );
540 static void glob0 (char *a0, unsigned int a1, int a2, int (*a3)(char *, char *));
541 static void glob1 (char *base, char *lim );
542 static void glob2 (char *i, char *j );
543 static void glob3 (char *i, char *j, char *k );
544 static void readhere (char **name, char *s, int ec );
545 static void pushio (struct ioarg *argp, int (*f)(struct ioarg *));
546 static int xxchar(struct ioarg *ap );
547
548 struct  here {
549         char    *h_tag;
550         int     h_dosub;
551         struct  ioword *h_iop;
552         struct  here    *h_next;
553 };
554
555 static  char    *signame[] = {
556         "Signal 0",
557         "Hangup",
558         (char *)NULL,   /* interrupt */
559         "Quit",
560         "Illegal instruction",
561         "Trace/BPT trap",
562         "Abort",
563         "Bus error",
564         "Floating Point Exception",
565         "Killed",
566         "SIGUSR1",
567         "SIGSEGV",
568         "SIGUSR2",
569         (char *)NULL,   /* broken pipe */
570         "Alarm clock",
571         "Terminated",
572 };
573 #define NSIGNAL (sizeof(signame)/sizeof(signame[0]))
574
575 struct res {
576         char *r_name;
577         int       r_val;
578 };
579 static struct res restab[] = {
580     {"for",             FOR},
581     {"case",    CASE},
582     {"esac",    ESAC},
583     {"while",   WHILE},
584     {"do",              DO},
585     {"done",    DONE},
586     {"if",              IF},
587     {"in",              IN},
588     {"then",    THEN},
589     {"else",    ELSE},
590     {"elif",    ELIF},
591     {"until",   UNTIL},
592     {"fi",              FI},
593
594     {";;",              BREAK},
595     {"||",              LOGOR},
596     {"&&",              LOGAND},
597     {"{",               '{'},
598     {"}",               '}'},
599     {0,         0},
600 };
601
602
603 struct builtincmd {
604         const char *name;
605         int (*builtinfunc)(struct op *t);
606 };
607 static const struct     builtincmd      builtincmds[] = {
608     {".",               dodot},
609     {":",               dolabel},
610     {"break",   dobreak},
611     {"cd",              dochdir},
612     {"continue",docontinue},
613     {"eval",    doeval},
614     {"exec",    doexec},
615     {"exit",    doexit},
616     {"export",  doexport},
617     {"help",    dohelp},
618     {"login",   dologin},
619     {"newgrp",  dologin},
620     {"read",    doread},
621     {"readonly",doreadonly},
622     {"set",             doset},
623     {"shift",   doshift},
624     {"times",   dotimes},
625     {"trap",    dotrap},
626     {"umask",   doumask},
627     {"wait",    dowait},
628     {0,0}
629 };
630
631 /* Globals */
632 extern  char    **environ;      /* environment pointer */
633 static char     **dolv;
634 static int      dolc;
635 static int      exstat;
636 static char     gflg;
637 static int      interactive;    /* Is this an interactive shell */
638 static int      execflg;
639 static int      multiline;      /* \n changed to ; */
640 static struct   op      *outtree;       /* result from parser */
641 static xint     *failpt;
642 static xint     *errpt;
643 static struct   brkcon  *brklist;
644 static int      isbreak;
645 static struct   wdblock *wdlist;
646 static struct   wdblock *iolist;
647 static char     *trap[_NSIG+1];
648 static char     ourtrap[_NSIG+1];
649 static int      trapset;        /* trap pending */
650 static int      yynerrs;        /* yacc */
651 static char     line[LINELIM];
652 static struct   var     *vlist;         /* dictionary */
653 static struct   var     *homedir;       /* home directory */
654 static struct   var     *prompt;        /* main prompt */
655 static struct   var     *cprompt;       /* continuation prompt */
656 static struct   var     *path;          /* search path for commands */
657 static struct   var     *shell;         /* shell to interpret command files */
658 static struct   var     *ifs;           /* field separators */
659 static struct   ioarg ioargstack[NPUSH];
660 static struct   io      iostack[NPUSH];
661 static int      areanum;        /* current allocation area */
662 static int      intr;
663 static int      inparse;
664 static char     flags['z'-'a'+1];
665 static char     *flag = flags-'a';
666 static char     *elinep = line+sizeof(line)-5;
667 static char     *null   = "";
668 static int      heedint =1;
669 static struct env e ={line, iostack, iostack-1, (xint *)NULL, FDBASE, (struct env *)NULL};
670 static void (*qflag)(int) = SIG_IGN;
671 static char     shellname[] = "/bin/sh";
672 static  int     startl;
673 static  int     peeksym;
674 static  int     nlseen;
675 static  int     iounit = IODEFAULT;
676 static  YYSTYPE yylval;
677 static struct iobuf sharedbuf = {AFID_NOBUF};
678 static struct iobuf mainbuf = {AFID_NOBUF};
679 static unsigned bufid = AFID_ID;        /* buffer id counter */
680 static struct ioarg temparg = {0, 0, 0, AFID_NOBUF, 0};
681 static  struct here *inhere;            /* list of hear docs while parsing */
682 static  struct here *acthere;           /* list of active here documents */
683 static  struct region *areabot;         /* bottom of area */
684 static  struct region *areatop;         /* top of area */
685 static  struct region *areanxt;         /* starting point of scan */
686 static void * brktop;
687 static void * brkaddr;
688
689
690 #ifdef CONFIG_FEATURE_COMMAND_EDITING
691 static char * current_prompt;
692 #endif
693
694 /* -------- sh.c -------- */
695 /*
696  * shell
697  */
698
699
700 extern int msh_main(int argc, char **argv)
701 {
702         register int f;
703         register char *s;
704         int cflag;
705         char *name, **ap;
706         int (*iof)(struct ioarg *);
707
708         initarea();
709         if ((ap = environ) != NULL) {
710                 while (*ap)
711                         assign(*ap++, !COPYV);
712                 for (ap = environ; *ap;)
713                         export(lookup(*ap++));
714         }
715         closeall();
716         areanum = 1;
717
718         shell = lookup("SHELL");
719         if (shell->value == null)
720                 setval(shell, shellname);
721         export(shell);
722
723         homedir = lookup("HOME");
724         if (homedir->value == null)
725                 setval(homedir, "/");
726         export(homedir);
727
728         setval(lookup("$"), putn(getpid()));
729
730         path = lookup("PATH");
731         if (path->value == null) {
732                 if (geteuid() == 0)
733                         setval(path, "/sbin:/bin:/usr/sbin:/usr/bin");
734                 else
735                         setval(path, "/bin:/usr/bin");
736         }
737         export(path);
738
739         ifs = lookup("IFS");
740         if (ifs->value == null)
741                 setval(ifs, " \t\n");
742
743         prompt = lookup("PS1");
744 #ifdef CONFIG_FEATURE_SH_FANCY_PROMPT
745         if (prompt->value == null)
746 #endif
747                 setval(prompt, "$ ");
748         if (geteuid() == 0) {
749                 setval(prompt, "# ");
750                 prompt->status &= ~EXPORT;
751         }
752         cprompt = lookup("PS2");
753 #ifdef CONFIG_FEATURE_SH_FANCY_PROMPT
754         if (cprompt->value == null)
755 #endif
756                 setval(cprompt, "> ");
757
758         iof = filechar;
759         cflag = 0;
760         name = *argv++;
761         if (--argc >= 1) {
762                 if(argv[0][0] == '-' && argv[0][1] != '\0') {
763                         for (s = argv[0]+1; *s; s++)
764                                 switch (*s) {
765                                 case 'c':
766                                         prompt->status &= ~EXPORT;
767                                         cprompt->status &= ~EXPORT;
768                                         setval(prompt, "");
769                                         setval(cprompt, "");
770                                         cflag = 1;
771                                         if (--argc > 0)
772                                                 PUSHIO(aword, *++argv, iof = nlchar);
773                                         break;
774         
775                                 case 'q':
776                                         qflag = SIG_DFL;
777                                         break;
778
779                                 case 's':
780                                         /* standard input */
781                                         break;
782
783                                 case 't':
784                                         prompt->status &= ~EXPORT;
785                                         setval(prompt, "");
786                                         iof = linechar;
787                                         break;
788         
789                                 case 'i':
790                                         interactive++;
791                                 default:
792                                         if (*s>='a' && *s<='z')
793                                                 flag[(int)*s]++;
794                                 }
795                 } else {
796                         argv--;
797                         argc++;
798                 }
799                 if (iof == filechar && --argc > 0) {
800                         setval(prompt, "");
801                         setval(cprompt, "");
802                         prompt->status &= ~EXPORT;
803                         cprompt->status &= ~EXPORT;
804                         if (newfile(name = *++argv))
805                                 exit(1);
806                 }
807         }
808         setdash();
809         if (e.iop < iostack) {
810                 PUSHIO(afile, 0, iof);
811                 if (isatty(0) && isatty(1) && !cflag) {
812                         interactive++;
813 #ifndef CONFIG_FEATURE_SH_EXTRA_QUIET 
814                         printf( "\n\n" BB_BANNER " Built-in shell (msh)\n");
815                         printf( "Enter 'help' for a list of built-in commands.\n\n");
816 #endif
817                 }
818         }
819         signal(SIGQUIT, qflag);
820         if (name && name[0] == '-') {
821                 interactive++;
822                 if ((f = open(".profile", 0)) >= 0)
823                         next(remap(f));
824                 if ((f = open("/etc/profile", 0)) >= 0)
825                         next(remap(f));
826         }
827         if (interactive)
828                 signal(SIGTERM, sig);
829         if (signal(SIGINT, SIG_IGN) != SIG_IGN)
830                 signal(SIGINT, onintr);
831         dolv = argv;
832         dolc = argc;
833         dolv[0] = name;
834         if (dolc > 1) {
835                 for (ap = ++argv; --argc > 0;) {
836                         if (assign(*ap = *argv++, !COPYV)) {
837                                 dolc--; /* keyword */
838                         } else {
839                                 ap++;
840                         }
841                 }
842         }       
843         setval(lookup("#"), putn((--dolc < 0) ? (dolc = 0) : dolc));
844
845         for (;;) {
846                 if (interactive && e.iop <= iostack) {
847 #ifdef CONFIG_FEATURE_COMMAND_EDITING
848                         current_prompt=prompt->value;
849 #else
850                         prs(prompt->value);
851 #endif
852                 }
853                 onecommand();
854                 /* Ensure that getenv("PATH") stays current */
855                 setenv("PATH", path->value, 1);
856         }
857 }
858
859 static void
860 setdash()
861 {
862         register char *cp;
863         register int c;
864         char m['z'-'a'+1];
865
866         cp = m;
867         for (c='a'; c<='z'; c++)
868                 if (flag[(int)c])
869                         *cp++ = c;
870         *cp = 0;
871         setval(lookup("-"), m);
872 }
873
874 static int
875 newfile(s)
876 register char *s;
877 {
878         register int f;
879
880         if (strcmp(s, "-") != 0) {
881                 f = open(s, 0);
882                 if (f < 0) {
883                         prs(s);
884                         err(": cannot open");
885                         return(1);
886                 }
887         } else
888                 f = 0;
889         next(remap(f));
890         return(0);
891 }
892
893 static void
894 onecommand()
895 {
896         register int i;
897         jmp_buf m1;
898
899         while (e.oenv)
900                 quitenv();
901         areanum = 1;
902         freehere(areanum);
903         freearea(areanum);
904         garbage();
905         wdlist = 0;
906         iolist = 0;
907         e.errpt = 0;
908         e.linep = line;
909         yynerrs = 0;
910         multiline = 0;
911         inparse = 1;
912         intr = 0;
913         execflg = 0;
914         setjmp(failpt = m1);    /* Bruce Evans' fix */
915         if (setjmp(failpt = m1) || yyparse() || intr) {
916                 while (e.oenv)
917                         quitenv();
918                 scraphere();
919                 if (!interactive && intr)
920                         leave();
921                 inparse = 0;
922                 intr = 0;
923                 return;
924         }
925         inparse = 0;
926         brklist = 0;
927         intr = 0;
928         execflg = 0;
929         if (!flag['n'])
930                 execute(outtree, NOPIPE, NOPIPE, 0);
931         if (!interactive && intr) {
932                 execflg = 0;
933                 leave();
934         }
935         if ((i = trapset) != 0) {
936                 trapset = 0;
937                 runtrap(i);
938         }
939 }
940
941 static void
942 fail()
943 {
944         longjmp(failpt, 1);
945         /* NOTREACHED */
946 }
947
948 static void
949 leave()
950 {
951         if (execflg)
952                 fail();
953         scraphere();
954         freehere(1);
955         runtrap(0);
956         exit(exstat);
957         /* NOTREACHED */
958 }
959
960 static void
961 warn(s)
962 register char *s;
963 {
964         if(*s) {
965                 prs(s);
966                 exstat = -1;
967         }
968         prs("\n");
969         if (flag['e'])
970                 leave();
971 }
972
973 static void
974 err(s)
975 char *s;
976 {
977         warn(s);
978         if (flag['n'])
979                 return;
980         if (!interactive)
981                 leave();
982         if (e.errpt)
983                 longjmp(e.errpt, 1);
984         closeall();
985         e.iop = e.iobase = iostack;
986 }
987
988 static int
989 newenv(f)
990 int f;
991 {
992         register struct env *ep;
993
994         if (f) {
995                 quitenv();
996                 return(1);
997         }
998         ep = (struct env *) space(sizeof(*ep));
999         if (ep == NULL) {
1000                 while (e.oenv)
1001                         quitenv();
1002                 fail();
1003         }
1004         *ep = e;
1005         e.oenv = ep;
1006         e.errpt = errpt;
1007         return(0);
1008 }
1009
1010 static void
1011 quitenv()
1012 {
1013         register struct env *ep;
1014         register int fd;
1015
1016         if ((ep = e.oenv) != NULL) {
1017                 fd = e.iofd;
1018                 e = *ep;
1019                 /* should close `'d files */
1020                 DELETE(ep);
1021                 while (--fd >= e.iofd)
1022                         close(fd);
1023         }
1024 }
1025
1026 /*
1027  * Is any character from s1 in s2?
1028  */
1029 static int
1030 anys(s1, s2)
1031 register char *s1, *s2;
1032 {
1033         while (*s1)
1034                 if (any(*s1++, s2))
1035                         return(1);
1036         return(0);
1037 }
1038
1039 /*
1040  * Is character c in s?
1041  */
1042 static int
1043 any(c, s)
1044 register int c;
1045 register char *s;
1046 {
1047         while (*s)
1048                 if (*s++ == c)
1049                         return(1);
1050         return(0);
1051 }
1052
1053 static char *
1054 putn(n)
1055 register int n;
1056 {
1057         return(itoa(n));
1058 }
1059
1060 static char *
1061 itoa(n)
1062 register int n;
1063 {
1064         static char s[20];
1065         snprintf(s, sizeof(s), "%u", n);
1066         return(s);
1067 }
1068
1069 static void
1070 next(int f)
1071 {
1072         PUSHIO(afile, f, filechar);
1073 }
1074
1075 static void
1076 onintr(s)
1077 int s;                          /* ANSI C requires a parameter */
1078 {
1079         signal(SIGINT, onintr);
1080         intr = 1;
1081         if (interactive) {
1082                 if (inparse) {
1083                         prs("\n");
1084                         fail();
1085                 }
1086         }
1087         else if (heedint) {
1088                 execflg = 0;
1089                 leave();
1090         }
1091 }
1092
1093 static char *
1094 space(n)
1095 int n;
1096 {
1097         register char *cp;
1098
1099         if ((cp = getcell(n)) == 0)
1100                 err("out of string space");
1101         return(cp);
1102 }
1103
1104 static char *
1105 strsave(s, a)
1106 register char *s;
1107 int a;
1108 {
1109         register char *cp, *xp;
1110
1111         if ((cp = space(strlen(s)+1)) != NULL) {
1112                 setarea((char *)cp, a);
1113                 for (xp = cp; (*xp++ = *s++) != '\0';)
1114                         ;
1115                 return(cp);
1116         }
1117         return("");
1118 }
1119
1120 /*
1121  * trap handling
1122  */
1123 static void
1124 sig(i)
1125 register int i;
1126 {
1127         trapset = i;
1128         signal(i, sig);
1129 }
1130
1131 static void runtrap(i)
1132 int i;
1133 {
1134         char *trapstr;
1135
1136         if ((trapstr = trap[i]) == NULL)
1137                 return;
1138         if (i == 0)
1139                 trap[i] = 0;
1140         RUN(aword, trapstr, nlchar);
1141 }
1142
1143 /* -------- var.c -------- */
1144
1145 /*
1146  * Find the given name in the dictionary
1147  * and return its value.  If the name was
1148  * not previously there, enter it now and
1149  * return a null value.
1150  */
1151 static struct var *
1152 lookup(n)
1153 register char *n;
1154 {
1155         register struct var *vp;
1156         register char *cp;
1157         register int c;
1158         static struct var dummy;
1159
1160         if (isdigit(*n)) {
1161                 dummy.name = n;
1162                 for (c = 0; isdigit(*n) && c < 1000; n++)
1163                         c = c*10 + *n-'0';
1164                 dummy.status = RONLY;
1165                 dummy.value = c <= dolc? dolv[c]: null;
1166                 return(&dummy);
1167         }
1168         for (vp = vlist; vp; vp = vp->next)
1169                 if (eqname(vp->name, n))
1170                         return(vp);
1171         cp = findeq(n);
1172         vp = (struct var *)space(sizeof(*vp));
1173         if (vp == 0 || (vp->name = space((int)(cp-n)+2)) == 0) {
1174                 dummy.name = dummy.value = "";
1175                 return(&dummy);
1176         }
1177         for (cp = vp->name; (*cp = *n++) && *cp != '='; cp++)
1178                 ;
1179         if (*cp == 0)
1180                 *cp = '=';
1181         *++cp = 0;
1182         setarea((char *)vp, 0);
1183         setarea((char *)vp->name, 0);
1184         vp->value = null;
1185         vp->next = vlist;
1186         vp->status = GETCELL;
1187         vlist = vp;
1188         return(vp);
1189 }
1190
1191 /*
1192  * give variable at `vp' the value `val'.
1193  */
1194 static void
1195 setval(vp, val)
1196 struct var *vp;
1197 char *val;
1198 {
1199         nameval(vp, val, (char *)NULL);
1200 }
1201
1202 /*
1203  * if name is not NULL, it must be
1204  * a prefix of the space `val',
1205  * and end with `='.
1206  * this is all so that exporting
1207  * values is reasonably painless.
1208  */
1209 static void
1210 nameval(vp, val, name)
1211 register struct var *vp;
1212 char *val, *name;
1213 {
1214         register char *cp, *xp;
1215         char *nv;
1216         int fl;
1217
1218         if (vp->status & RONLY) {
1219                 for (xp = vp->name; *xp && *xp != '=';)
1220                         putc(*xp++, stderr);
1221                 err(" is read-only");
1222                 return;
1223         }
1224         fl = 0;
1225         if (name == NULL) {
1226                 xp = space(strlen(vp->name)+strlen(val)+2);
1227                 if (xp == 0)
1228                         return;
1229                 /* make string:  name=value */
1230                 setarea((char *)xp, 0);
1231                 name = xp;
1232                 for (cp = vp->name; (*xp = *cp++) && *xp!='='; xp++)
1233                         ;
1234                 if (*xp++ == 0)
1235                         xp[-1] = '=';
1236                 nv = xp;
1237                 for (cp = val; (*xp++ = *cp++) != '\0';)
1238                         ;
1239                 val = nv;
1240                 fl = GETCELL;
1241         }
1242         if (vp->status & GETCELL)
1243                 freecell(vp->name);    /* form new string `name=value' */
1244         vp->name = name;
1245         vp->value = val;
1246         vp->status |= fl;
1247 }
1248
1249 static void
1250 export(vp)
1251 struct var *vp;
1252 {
1253         vp->status |= EXPORT;
1254 }
1255
1256 static void
1257 ronly(vp)
1258 struct var *vp;
1259 {
1260         if (isalpha(vp->name[0]) || vp->name[0] == '_') /* not an internal symbol */
1261                 vp->status |= RONLY;
1262 }
1263
1264 static int
1265 isassign(s)
1266 register char *s;
1267 {
1268         if (!isalpha((int)*s) && *s != '_')
1269                 return(0);
1270         for (; *s != '='; s++)
1271                 if (*s == 0 || (!isalnum(*s) && *s != '_'))
1272                         return(0);
1273         return(1);
1274 }
1275
1276 static int
1277 assign(s, cf)
1278 register char *s;
1279 int cf;
1280 {
1281         register char *cp;
1282         struct var *vp;
1283
1284         if (!isalpha(*s) && *s != '_')
1285                 return(0);
1286         for (cp = s; *cp != '='; cp++)
1287                 if (*cp == 0 || (!isalnum(*cp) && *cp != '_'))
1288                         return(0);
1289         vp = lookup(s);
1290         nameval(vp, ++cp, cf == COPYV? (char *)NULL: s);
1291         if (cf != COPYV)
1292                 vp->status &= ~GETCELL;
1293         return(1);
1294 }
1295
1296 static int
1297 checkname(cp)
1298 register char *cp;
1299 {
1300         if (!isalpha(*cp++) && *(cp-1) != '_')
1301                 return(0);
1302         while (*cp)
1303                 if (!isalnum(*cp++) && *(cp-1) != '_')
1304                         return(0);
1305         return(1);
1306 }
1307
1308 static void
1309 putvlist(f, out)
1310 register int f, out;
1311 {
1312         register struct var *vp;
1313
1314         for (vp = vlist; vp; vp = vp->next)
1315                 if (vp->status & f && (isalpha(*vp->name) || *vp->name == '_')) {
1316                         if (vp->status & EXPORT)
1317                                 write(out, "export ", 7);
1318                         if (vp->status & RONLY)
1319                                 write(out, "readonly ", 9);
1320                         write(out, vp->name, (int)(findeq(vp->name) - vp->name));
1321                         write(out, "\n", 1);
1322                 }
1323 }
1324
1325 static int
1326 eqname(n1, n2)
1327 register char *n1, *n2;
1328 {
1329         for (; *n1 != '=' && *n1 != 0; n1++)
1330                 if (*n2++ != *n1)
1331                         return(0);
1332         return(*n2 == 0 || *n2 == '=');
1333 }
1334
1335 static char *
1336 findeq(cp)
1337 register char *cp;
1338 {
1339         while (*cp != '\0' && *cp != '=')
1340                 cp++;
1341         return(cp);
1342 }
1343
1344 /* -------- gmatch.c -------- */
1345 /*
1346  * int gmatch(string, pattern)
1347  * char *string, *pattern;
1348  *
1349  * Match a pattern as in sh(1).
1350  */
1351
1352 #define CMASK   0377
1353 #define QUOTE   0200
1354 #define QMASK   (CMASK&~QUOTE)
1355 #define NOT     '!'     /* might use ^ */
1356
1357 static int
1358 gmatch(s, p)
1359 register char *s, *p;
1360 {
1361         register int sc, pc;
1362
1363         if (s == NULL || p == NULL)
1364                 return(0);
1365         while ((pc = *p++ & CMASK) != '\0') {
1366                 sc = *s++ & QMASK;
1367                 switch (pc) {
1368                 case '[':
1369                         if ((p = cclass(p, sc)) == NULL)
1370                                 return(0);
1371                         break;
1372
1373                 case '?':
1374                         if (sc == 0)
1375                                 return(0);
1376                         break;
1377
1378                 case '*':
1379                         s--;
1380                         do {
1381                                 if (*p == '\0' || gmatch(s, p))
1382                                         return(1);
1383                         } while (*s++ != '\0');
1384                         return(0);
1385
1386                 default:
1387                         if (sc != (pc&~QUOTE))
1388                                 return(0);
1389                 }
1390         }
1391         return(*s == 0);
1392 }
1393
1394 static char *
1395 cclass(p, sub)
1396 register char *p;
1397 register int sub;
1398 {
1399         register int c, d, not, found;
1400
1401         if ((not = *p == NOT) != 0)
1402                 p++;
1403         found = not;
1404         do {
1405                 if (*p == '\0')
1406                         return((char *)NULL);
1407                 c = *p & CMASK;
1408                 if (p[1] == '-' && p[2] != ']') {
1409                         d = p[2] & CMASK;
1410                         p++;
1411                 } else
1412                         d = c;
1413                 if (c == sub || (c <= sub && sub <= d))
1414                         found = !not;
1415         } while (*++p != ']');
1416         return(found? p+1: (char *)NULL);
1417 }
1418
1419
1420 /* -------- area.c -------- */
1421
1422 /*
1423  * All memory between (char *)areabot and (char *)(areatop+1) is
1424  * exclusively administered by the area management routines.
1425  * It is assumed that sbrk() and brk() manipulate the high end.
1426  */
1427
1428 #define sbrk(X) ({ void * __q = (void *)-1; if (brkaddr + (int)(X) < brktop) { __q = brkaddr; brkaddr+=(int)(X); } __q;})
1429
1430 static void
1431 initarea()
1432 {
1433         brkaddr = malloc(65000);
1434         brktop = brkaddr + 65000;
1435
1436         while ((int)sbrk(0) & ALIGN)
1437                 sbrk(1);
1438         areabot = (struct region *)sbrk(REGSIZE);
1439
1440         areabot->next = areabot;
1441         areabot->area = BUSY;
1442         areatop = areabot;
1443         areanxt = areabot;
1444 }
1445
1446 char *
1447 getcell(nbytes)
1448 unsigned nbytes;
1449 {
1450         register int nregio;
1451         register struct region *p, *q;
1452         register int i;
1453
1454         if (nbytes == 0) {
1455                 puts("getcell(0)");
1456                 abort();
1457         }       /* silly and defeats the algorithm */
1458         /*
1459          * round upwards and add administration area
1460          */
1461         nregio = (nbytes+(REGSIZE-1))/REGSIZE + 1;
1462         for (p = areanxt;;) {
1463                 if (p->area > areanum) {
1464                         /*
1465                          * merge free cells
1466                          */
1467                         while ((q = p->next)->area > areanum && q != areanxt)
1468                                 p->next = q->next;
1469                         /*
1470                          * exit loop if cell big enough
1471                          */
1472                         if (q >= p + nregio)
1473                                 goto found;
1474                 }
1475                 p = p->next;
1476                 if (p == areanxt)
1477                         break;
1478         }
1479         i = nregio >= GROWBY ? nregio : GROWBY;
1480         p = (struct region *)sbrk(i * REGSIZE);
1481         if (p == (struct region *)-1)
1482                 return((char *)NULL);
1483         p--;
1484         if (p != areatop) {
1485                 puts("not contig");
1486                 abort();        /* allocated areas are contiguous */
1487         }
1488         q = p + i;
1489         p->next = q;
1490         p->area = FREE;
1491         q->next = areabot;
1492         q->area = BUSY;
1493         areatop = q;
1494 found:
1495         /*
1496          * we found a FREE area big enough, pointed to by 'p', and up to 'q'
1497          */
1498         areanxt = p + nregio;
1499         if (areanxt < q) {
1500                 /*
1501                  * split into requested area and rest
1502                  */
1503                 if (areanxt+1 > q) {
1504                         puts("OOM");
1505                         abort();        /* insufficient space left for admin */
1506                 }
1507                 areanxt->next = q;
1508                 areanxt->area = FREE;
1509                 p->next = areanxt;
1510         }
1511         p->area = areanum;
1512         return((char *)(p+1));
1513 }
1514
1515 static void
1516 freecell(cp)
1517 char *cp;
1518 {
1519         register struct region *p;
1520
1521         if ((p = (struct region *)cp) != NULL) {
1522                 p--;
1523                 if (p < areanxt)
1524                         areanxt = p;
1525                 p->area = FREE;
1526         }
1527 }
1528
1529 static void
1530 freearea(a)
1531 register int a;
1532 {
1533         register struct region *p, *top;
1534
1535         top = areatop;
1536         for (p = areabot; p != top; p = p->next)
1537                 if (p->area >= a)
1538                         p->area = FREE;
1539 }
1540
1541 static void
1542 setarea(cp,a)
1543 char *cp;
1544 int a;
1545 {
1546         register struct region *p;
1547
1548         if ((p = (struct region *)cp) != NULL)
1549                 (p-1)->area = a;
1550 }
1551
1552 int
1553 getarea(cp)
1554 char *cp;
1555 {
1556         return ((struct region*)cp-1)->area;
1557 }
1558
1559 static void
1560 garbage()
1561 {
1562         register struct region *p, *q, *top;
1563
1564         top = areatop;
1565         for (p = areabot; p != top; p = p->next) {
1566                 if (p->area > areanum) {
1567                         while ((q = p->next)->area > areanum)
1568                                 p->next = q->next;
1569                         areanxt = p;
1570                 }
1571         }
1572 #ifdef SHRINKBY
1573         if (areatop >= q + SHRINKBY && q->area > areanum) {
1574                 brk((char *)(q+1));
1575                 q->next = areabot;
1576                 q->area = BUSY;
1577                 areatop = q;
1578         }
1579 #endif
1580 }
1581
1582 /* -------- csyn.c -------- */
1583 /*
1584  * shell: syntax (C version)
1585  */
1586
1587
1588 int
1589 yyparse()
1590 {
1591         startl  = 1;
1592         peeksym = 0;
1593         yynerrs = 0;
1594         outtree = c_list();
1595         musthave('\n', 0);
1596         return(yynerrs!=0);
1597 }
1598
1599 static struct op *
1600 pipeline(cf)
1601 int cf;
1602 {
1603         register struct op *t, *p;
1604         register int c;
1605
1606         t = command(cf);
1607         if (t != NULL) {
1608                 while ((c = yylex(0)) == '|') {
1609                         if ((p = command(CONTIN)) == NULL)
1610                                 SYNTAXERR;
1611                         if (t->type != TPAREN && t->type != TCOM) {
1612                                 /* shell statement */
1613                                 t = block(TPAREN, t, NOBLOCK, NOWORDS);
1614                         }
1615                         t = block(TPIPE, t, p, NOWORDS);
1616                 }
1617                 peeksym = c;
1618         }
1619         return(t);
1620 }
1621
1622 static struct op *
1623 andor()
1624 {
1625         register struct op *t, *p;
1626         register int c;
1627
1628         t = pipeline(0);
1629         if (t != NULL) {
1630                 while ((c = yylex(0)) == LOGAND || c == LOGOR) {
1631                         if ((p = pipeline(CONTIN)) == NULL)
1632                                 SYNTAXERR;
1633                         t = block(c == LOGAND? TAND: TOR, t, p, NOWORDS);
1634                 }
1635                 peeksym = c;
1636         }
1637         return(t);
1638 }
1639
1640 static struct op *
1641 c_list()
1642 {
1643         register struct op *t, *p;
1644         register int c;
1645
1646         t = andor();
1647         if (t != NULL) {
1648                 if((peeksym = yylex(0)) == '&')
1649                         t = block(TASYNC, t, NOBLOCK, NOWORDS);
1650                 while ((c = yylex(0)) == ';' || c == '&' || (multiline && c == '\n')) {
1651                         if ((p = andor()) == NULL)
1652                                 return(t);
1653                         if((peeksym = yylex(0)) == '&')
1654                                 p = block(TASYNC, p, NOBLOCK, NOWORDS);
1655                         t = list(t, p);
1656                 }
1657                 peeksym = c;
1658         }
1659         return(t);
1660 }
1661
1662
1663 static int
1664 synio(cf)
1665 int cf;
1666 {
1667         register struct ioword *iop;
1668         register int i;
1669         register int c;
1670
1671         if ((c = yylex(cf)) != '<' && c != '>') {
1672                 peeksym = c;
1673                 return(0);
1674         }
1675         i = yylval.i;
1676         musthave(WORD, 0);
1677         iop = io(iounit, i, yylval.cp);
1678         iounit = IODEFAULT;
1679         if (i & IOHERE)
1680                 markhere(yylval.cp, iop);
1681         return(1);
1682 }
1683
1684 static void
1685 musthave(c, cf)
1686 int c, cf;
1687 {
1688         if ((peeksym = yylex(cf)) != c)
1689                 SYNTAXERR;
1690         peeksym = 0;
1691 }
1692
1693 static struct op *
1694 simple()
1695 {
1696         register struct op *t;
1697
1698         t = NULL;
1699         for (;;) {
1700                 switch (peeksym = yylex(0)) {
1701                 case '<':
1702                 case '>':
1703                         (void) synio(0);
1704                         break;
1705
1706                 case WORD:
1707                         if (t == NULL) {
1708                                 t = newtp();
1709                                 t->type = TCOM;
1710                         }
1711                         peeksym = 0;
1712                         word(yylval.cp);
1713                         break;
1714
1715                 default:
1716                         return(t);
1717                 }
1718         }
1719 }
1720
1721 static struct op *
1722 nested(type, mark)
1723 int type, mark;
1724 {
1725         register struct op *t;
1726
1727         multiline++;
1728         t = c_list();
1729         musthave(mark, 0);
1730         multiline--;
1731         return(block(type, t, NOBLOCK, NOWORDS));
1732 }
1733
1734 static struct op *
1735 command(cf)
1736 int cf;
1737 {
1738         register struct op *t;
1739         struct wdblock *iosave;
1740         register int c;
1741
1742         iosave = iolist;
1743         iolist = NULL;
1744         if (multiline)
1745                 cf |= CONTIN;
1746         while (synio(cf))
1747                 cf = 0;
1748         switch (c = yylex(cf)) {
1749         default:
1750                 peeksym = c;
1751                 if ((t = simple()) == NULL) {
1752                         if (iolist == NULL)
1753                                 return((struct op *)NULL);
1754                         t = newtp();
1755                         t->type = TCOM;
1756                 }
1757                 break;
1758
1759         case '(':
1760                 t = nested(TPAREN, ')');
1761                 break;
1762
1763         case '{':
1764                 t = nested(TBRACE, '}');
1765                 break;
1766
1767         case FOR:
1768                 t = newtp();
1769                 t->type = TFOR;
1770                 musthave(WORD, 0);
1771                 startl = 1;
1772                 t->str = yylval.cp;
1773                 multiline++;
1774                 t->words = wordlist();
1775                 if ((c = yylex(0)) != '\n' && c != ';')
1776                         peeksym = c;
1777                 t->left = dogroup(0);
1778                 multiline--;
1779                 break;
1780
1781         case WHILE:
1782         case UNTIL:
1783                 multiline++;
1784                 t = newtp();
1785                 t->type = c == WHILE? TWHILE: TUNTIL;
1786                 t->left = c_list();
1787                 t->right = dogroup(1);
1788                 t->words = NULL;
1789                 multiline--;
1790                 break;
1791
1792         case CASE:
1793                 t = newtp();
1794                 t->type = TCASE;
1795                 musthave(WORD, 0);
1796                 t->str = yylval.cp;
1797                 startl++;
1798                 multiline++;
1799                 musthave(IN, CONTIN);
1800                 startl++;
1801                 t->left = caselist();
1802                 musthave(ESAC, 0);
1803                 multiline--;
1804                 break;
1805
1806         case IF:
1807                 multiline++;
1808                 t = newtp();
1809                 t->type = TIF;
1810                 t->left = c_list();
1811                 t->right = thenpart();
1812                 musthave(FI, 0);
1813                 multiline--;
1814                 break;
1815         }
1816         while (synio(0))
1817                 ;
1818         t = namelist(t);
1819         iolist = iosave;
1820         return(t);
1821 }
1822
1823 static struct op *
1824 dogroup(onlydone)
1825 int onlydone;
1826 {
1827         register int c;
1828         register struct op *mylist;
1829
1830         c = yylex(CONTIN);
1831         if (c == DONE && onlydone)
1832                 return((struct op *)NULL);
1833         if (c != DO)
1834                 SYNTAXERR;
1835         mylist = c_list();
1836         musthave(DONE, 0);
1837         return(mylist);
1838 }
1839
1840 static struct op *
1841 thenpart()
1842 {
1843         register int c;
1844         register struct op *t;
1845
1846         if ((c = yylex(0)) != THEN) {
1847                 peeksym = c;
1848                 return((struct op *)NULL);
1849         }
1850         t = newtp();
1851         t->type = 0;
1852         t->left = c_list();
1853         if (t->left == NULL)
1854                 SYNTAXERR;
1855         t->right = elsepart();
1856         return(t);
1857 }
1858
1859 static struct op *
1860 elsepart()
1861 {
1862         register int c;
1863         register struct op *t;
1864
1865         switch (c = yylex(0)) {
1866         case ELSE:
1867                 if ((t = c_list()) == NULL)
1868                         SYNTAXERR;
1869                 return(t);
1870
1871         case ELIF:
1872                 t = newtp();
1873                 t->type = TELIF;
1874                 t->left = c_list();
1875                 t->right = thenpart();
1876                 return(t);
1877
1878         default:
1879                 peeksym = c;
1880                 return((struct op *)NULL);
1881         }
1882 }
1883
1884 static struct op *
1885 caselist()
1886 {
1887         register struct op *t;
1888
1889         t = NULL;
1890         while ((peeksym = yylex(CONTIN)) != ESAC)
1891                 t = list(t, casepart());
1892         return(t);
1893 }
1894
1895 static struct op *
1896 casepart()
1897 {
1898         register struct op *t;
1899
1900         t = newtp();
1901         t->type = TPAT;
1902         t->words = pattern();
1903         musthave(')', 0);
1904         t->left = c_list();
1905         if ((peeksym = yylex(CONTIN)) != ESAC)
1906                 musthave(BREAK, CONTIN);
1907         return(t);
1908 }
1909
1910 static char **
1911 pattern()
1912 {
1913         register int c, cf;
1914
1915         cf = CONTIN;
1916         do {
1917                 musthave(WORD, cf);
1918                 word(yylval.cp);
1919                 cf = 0;
1920         } while ((c = yylex(0)) == '|');
1921         peeksym = c;
1922         word(NOWORD);
1923         return(copyw());
1924 }
1925
1926 static char **
1927 wordlist()
1928 {
1929         register int c;
1930
1931         if ((c = yylex(0)) != IN) {
1932                 peeksym = c;
1933                 return((char **)NULL);
1934         }
1935         startl = 0;
1936         while ((c = yylex(0)) == WORD)
1937                 word(yylval.cp);
1938         word(NOWORD);
1939         peeksym = c;
1940         return(copyw());
1941 }
1942
1943 /*
1944  * supporting functions
1945  */
1946 static struct op *
1947 list(t1, t2)
1948 register struct op *t1, *t2;
1949 {
1950         if (t1 == NULL)
1951                 return(t2);
1952         if (t2 == NULL)
1953                 return(t1);
1954         return(block(TLIST, t1, t2, NOWORDS));
1955 }
1956
1957 static struct op *
1958 block(type, t1, t2, wp)
1959 int type;
1960 struct op *t1, *t2;
1961 char **wp;
1962 {
1963         register struct op *t;
1964
1965         t = newtp();
1966         t->type = type;
1967         t->left = t1;
1968         t->right = t2;
1969         t->words = wp;
1970         return(t);
1971 }
1972
1973 static int
1974 rlookup(n)
1975 register char *n;
1976 {
1977         register struct res *rp;
1978
1979         for (rp = restab; rp->r_name; rp++)
1980                 if (strcmp(rp->r_name, n) == 0)
1981                         return(rp->r_val);
1982         return(0);
1983 }
1984
1985 static struct op *
1986 newtp()
1987 {
1988         register struct op *t;
1989
1990         t = (struct op *)tree(sizeof(*t));
1991         t->type = 0;
1992         t->words = NULL;
1993         t->ioact = NULL;
1994         t->left = NULL;
1995         t->right = NULL;
1996         t->str = NULL;
1997         return(t);
1998 }
1999
2000 static struct op *
2001 namelist(t)
2002 register struct op *t;
2003 {
2004         if (iolist) {
2005                 iolist = addword((char *)NULL, iolist);
2006                 t->ioact = copyio();
2007         } else
2008                 t->ioact = NULL;
2009         if (t->type != TCOM) {
2010                 if (t->type != TPAREN && t->ioact != NULL) {
2011                         t = block(TPAREN, t, NOBLOCK, NOWORDS);
2012                         t->ioact = t->left->ioact;
2013                         t->left->ioact = NULL;
2014                 }
2015                 return(t);
2016         }
2017         word(NOWORD);
2018         t->words = copyw();
2019         return(t);
2020 }
2021
2022 static char **
2023 copyw()
2024 {
2025         register char **wd;
2026
2027         wd = getwords(wdlist);
2028         wdlist = 0;
2029         return(wd);
2030 }
2031
2032 static void
2033 word(cp)
2034 char *cp;
2035 {
2036         wdlist = addword(cp, wdlist);
2037 }
2038
2039 static struct ioword **
2040 copyio()
2041 {
2042         register struct ioword **iop;
2043
2044         iop = (struct ioword **) getwords(iolist);
2045         iolist = 0;
2046         return(iop);
2047 }
2048
2049 static struct ioword *
2050 io(u, f, cp)
2051 int u;
2052 int f;
2053 char *cp;
2054 {
2055         register struct ioword *iop;
2056
2057         iop = (struct ioword *) tree(sizeof(*iop));
2058         iop->io_unit = u;
2059         iop->io_flag = f;
2060         iop->io_name = cp;
2061         iolist = addword((char *)iop, iolist);
2062         return(iop);
2063 }
2064
2065 static void
2066 zzerr()
2067 {
2068         yyerror("syntax error");
2069 }
2070
2071 static void
2072 yyerror(s)
2073 char *s;
2074 {
2075         yynerrs++;
2076         if (interactive && e.iop <= iostack) {
2077                 multiline = 0;
2078                 while (eofc() == 0 && yylex(0) != '\n')
2079                         ;
2080         }
2081         err(s);
2082         fail();
2083 }
2084
2085 static int
2086 yylex(cf)
2087 int cf;
2088 {
2089         register int c, c1;
2090         int atstart;
2091
2092         if ((c = peeksym) > 0) {
2093                 peeksym = 0;
2094                 if (c == '\n')
2095                         startl = 1;
2096                 return(c);
2097         }
2098         nlseen = 0;
2099         e.linep = line;
2100         atstart = startl;
2101         startl = 0;
2102         yylval.i = 0;
2103
2104 loop:
2105         while ((c = my_getc(0)) == ' ' || c == '\t')
2106                 ;
2107         switch (c) {
2108         default:
2109                 if (any(c, "0123456789")) {
2110                         unget(c1 = my_getc(0));
2111                         if (c1 == '<' || c1 == '>') {
2112                                 iounit = c - '0';
2113                                 goto loop;
2114                         }
2115                         *e.linep++ = c;
2116                         c = c1;
2117                 }
2118                 break;
2119
2120         case '#':
2121                 while ((c = my_getc(0)) != 0 && c != '\n')
2122                         ;
2123                 unget(c);
2124                 goto loop;
2125
2126         case 0:
2127                 return(c);
2128
2129         case '$':
2130                 *e.linep++ = c;
2131                 if ((c = my_getc(0)) == '{') {
2132                         if ((c = collect(c, '}')) != '\0')
2133                                 return(c);
2134                         goto pack;
2135                 }
2136                 break;
2137
2138         case '`':
2139         case '\'':
2140         case '"':
2141                 if ((c = collect(c, c)) != '\0')
2142                         return(c);
2143                 goto pack;
2144
2145         case '|':
2146         case '&':
2147         case ';':
2148                 if ((c1 = dual(c)) != '\0') {
2149                         startl = 1;
2150                         return(c1);
2151                 }
2152                 startl = 1;
2153                 return(c);
2154         case '^':
2155                 startl = 1;
2156                 return('|');
2157         case '>':
2158         case '<':
2159                 diag(c);
2160                 return(c);
2161
2162         case '\n':
2163                 nlseen++;
2164                 gethere();
2165                 startl = 1;
2166                 if (multiline || cf & CONTIN) {
2167                         if (interactive && e.iop <= iostack) {
2168 #ifdef CONFIG_FEATURE_COMMAND_EDITING
2169                         current_prompt=cprompt->value;
2170 #else
2171                         prs(cprompt->value);
2172 #endif
2173                         }
2174                         if (cf & CONTIN)
2175                                 goto loop;
2176                 }
2177                 return(c);
2178
2179         case '(':
2180         case ')':
2181                 startl = 1;
2182                 return(c);
2183         }
2184
2185         unget(c);
2186
2187 pack:
2188         while ((c = my_getc(0)) != 0 && !any(c, "`$ '\"\t;&<>()|^\n"))
2189                 if (e.linep >= elinep)
2190                         err("word too long");
2191                 else
2192                         *e.linep++ = c;
2193         unget(c);
2194         if(any(c, "\"'`$"))
2195                 goto loop;
2196         *e.linep++ = '\0';
2197         if (atstart && (c = rlookup(line))!=0) {
2198                 startl = 1;
2199                 return(c);
2200         }
2201         yylval.cp = strsave(line, areanum);
2202         return(WORD);
2203 }
2204
2205 static int
2206 collect(c, c1)
2207 register int c, c1;
2208 {
2209         char s[2];
2210
2211         *e.linep++ = c;
2212         while ((c = my_getc(c1)) != c1) {
2213                 if (c == 0) {
2214                         unget(c);
2215                         s[0] = c1;
2216                         s[1] = 0;
2217                         prs("no closing "); yyerror(s);
2218                         return(YYERRCODE);
2219                 }
2220                 if (interactive && c == '\n' && e.iop <= iostack) {
2221 #ifdef CONFIG_FEATURE_COMMAND_EDITING
2222                     current_prompt=cprompt->value;
2223 #else
2224                     prs(cprompt->value);
2225 #endif
2226                 }
2227                 *e.linep++ = c;
2228         }
2229         *e.linep++ = c;
2230         return(0);
2231 }
2232
2233 static int
2234 dual(c)
2235 register int c;
2236 {
2237         char s[3];
2238         register char *cp = s;
2239
2240         *cp++ = c;
2241         *cp++ = my_getc(0);
2242         *cp = 0;
2243         if ((c = rlookup(s)) == 0)
2244                 unget(*--cp);
2245         return(c);
2246 }
2247
2248 static void
2249 diag(ec)
2250 register int ec;
2251 {
2252         register int c;
2253
2254         c = my_getc(0);
2255         if (c == '>' || c == '<') {
2256                 if (c != ec)
2257                         zzerr();
2258                 yylval.i = ec == '>'? IOWRITE|IOCAT: IOHERE;
2259                 c = my_getc(0);
2260         } else
2261                 yylval.i = ec == '>'? IOWRITE: IOREAD;
2262         if (c != '&' || yylval.i == IOHERE)
2263                 unget(c);
2264         else
2265                 yylval.i |= IODUP;
2266 }
2267
2268 static char *
2269 tree(size)
2270 unsigned size;
2271 {
2272         register char *t;
2273
2274         if ((t = getcell(size)) == NULL) {
2275                 prs("command line too complicated\n");
2276                 fail();
2277                 /* NOTREACHED */
2278         }
2279         return(t);
2280 }
2281
2282 /* VARARGS1 */
2283 /* ARGSUSED */
2284
2285 /* -------- exec.c -------- */
2286
2287 /*
2288  * execute tree
2289  */
2290
2291
2292 static int
2293 execute(t, pin, pout, act)
2294 register struct op *t;
2295 int *pin, *pout;
2296 int act;
2297 {
2298         register struct op *t1;
2299         volatile int i, rv, a;
2300         char *cp, **wp, **wp2;
2301         struct var *vp;
2302         struct brkcon bc;
2303
2304 #if __GNUC__
2305         /* Avoid longjmp clobbering */
2306         (void) &wp;
2307 #endif  
2308
2309
2310         if (t == NULL)
2311                 return(0);
2312         rv = 0;
2313         a = areanum++;
2314         wp = (wp2 = t->words) != NULL
2315              ? eval(wp2, t->type == TCOM ? DOALL : DOALL & ~DOKEY)
2316              : NULL;
2317
2318         switch(t->type) {
2319         case TPAREN:
2320                 rv = execute(t->left, pin, pout, 0);
2321                 break;
2322                         
2323         case TCOM:
2324                 {
2325                         int child;
2326                         rv = forkexec(t, pin, pout, act, wp, &child);
2327                         if (child) {
2328                                 exstat = rv;
2329                                 leave();
2330                         }
2331                 }
2332                 break;
2333
2334         case TPIPE:
2335                 {
2336                     int pv[2];
2337                     if ((rv = openpipe(pv)) < 0)
2338                         break;
2339                     pv[0] = remap(pv[0]);
2340                     pv[1] = remap(pv[1]);
2341                     (void) execute(t->left, pin, pv, 0);
2342                     rv = execute(t->right, pv, pout, 0);
2343                 }
2344                 break;
2345
2346         case TLIST:
2347                 (void) execute(t->left, pin, pout, 0);
2348                 rv = execute(t->right, pin, pout, 0);
2349                 break;
2350
2351         case TASYNC:
2352         {
2353                 int hinteractive = interactive;
2354
2355                 i = vfork();
2356                 if (i != 0) {
2357                         interactive = hinteractive;
2358                         if (i != -1) {
2359                                 setval(lookup("!"), putn(i));
2360                                 if (pin != NULL)
2361                                         closepipe(pin);
2362                                 if (interactive) {
2363                                         prs(putn(i));
2364                                         prs("\n");
2365                                 }
2366                         } else
2367                                 rv = -1;
2368                         setstatus(rv);
2369                 } else {
2370                         signal(SIGINT, SIG_IGN);
2371                         signal(SIGQUIT, SIG_IGN);
2372                         if (interactive)
2373                                 signal(SIGTERM, SIG_DFL);
2374                         interactive = 0;
2375                         if (pin == NULL) {
2376                                 close(0);
2377                                 open("/dev/null", 0);
2378                         }
2379                         exit(execute(t->left, pin, pout, FEXEC));
2380                 }
2381         }
2382                 break;
2383
2384         case TOR:
2385         case TAND:
2386                 rv = execute(t->left, pin, pout, 0);
2387                 if ((t1 = t->right)!=NULL && (rv == 0) == (t->type == TAND))
2388                         rv = execute(t1, pin, pout, 0);
2389                 break;
2390
2391         case TFOR:
2392                 if (wp == NULL) {
2393                         wp = dolv+1;
2394                         if ((i = dolc) < 0)
2395                                 i = 0;
2396                 } else {
2397                         i = -1;
2398                         while (*wp++ != NULL)
2399                                 ;                       
2400                 }
2401                 vp = lookup(t->str);
2402                 while (setjmp(bc.brkpt))
2403                         if (isbreak)
2404                                 goto broken;
2405                 brkset(&bc);
2406                 for (t1 = t->left; i-- && *wp != NULL;) {
2407                         setval(vp, *wp++);
2408                         rv = execute(t1, pin, pout, 0);
2409                 }
2410                 brklist = brklist->nextlev;
2411                 break;
2412
2413         case TWHILE:
2414         case TUNTIL:
2415                 while (setjmp(bc.brkpt))
2416                         if (isbreak)
2417                                 goto broken;
2418                 brkset(&bc);
2419                 t1 = t->left;
2420                 while ((execute(t1, pin, pout, 0) == 0) == (t->type == TWHILE))
2421                         rv = execute(t->right, pin, pout, 0);
2422                 brklist = brklist->nextlev;
2423                 break;
2424
2425         case TIF:
2426         case TELIF:
2427                 if (t->right != NULL) {
2428                 rv = !execute(t->left, pin, pout, 0) ?
2429                         execute(t->right->left, pin, pout, 0):
2430                         execute(t->right->right, pin, pout, 0);
2431                 }
2432                 break;
2433
2434         case TCASE:
2435                 if ((cp = evalstr(t->str, DOSUB|DOTRIM)) == 0)
2436                         cp = "";
2437                 if ((t1 = findcase(t->left, cp)) != NULL)
2438                         rv = execute(t1, pin, pout, 0);
2439                 break;
2440
2441         case TBRACE:
2442 /*
2443                 if (iopp = t->ioact)
2444                         while (*iopp)
2445                                 if (iosetup(*iopp++, pin!=NULL, pout!=NULL)) {
2446                                         rv = -1;
2447                                         break;
2448                                 }
2449 */
2450                 if (rv >= 0 && (t1 = t->left))
2451                         rv = execute(t1, pin, pout, 0);
2452                 break;
2453         }
2454
2455 broken:
2456         t->words = wp2;
2457         isbreak = 0;
2458         freehere(areanum);
2459         freearea(areanum);
2460         areanum = a;
2461         if (interactive && intr) {
2462                 closeall();
2463                 fail();
2464         }
2465         if ((i = trapset) != 0) {
2466                 trapset = 0;
2467                 runtrap(i);
2468         }
2469         return(rv);
2470 }
2471
2472 static int
2473 forkexec( register struct op *t, int *pin, int *pout, int act, char **wp, int *pforked)
2474 {
2475         int i, rv;
2476         int (*shcom)(struct op *) = NULL;
2477         register int f;
2478         char *cp = NULL;
2479         struct ioword **iopp;
2480         int resetsig;
2481         char **owp;
2482
2483         int *hpin = pin;
2484         int *hpout = pout;
2485         int hforked;
2486         char *hwp;
2487         int hinteractive;
2488         int hintr;
2489         struct brkcon * hbrklist;
2490         int hexecflg;
2491
2492 #if __GNUC__
2493         /* Avoid longjmp clobbering */
2494         (void) &pin;
2495         (void) &pout;
2496         (void) &wp;
2497         (void) &shcom;
2498         (void) &cp;
2499         (void) &resetsig;
2500         (void) &owp;
2501 #endif  
2502
2503         owp = wp;
2504         resetsig = 0;
2505         *pforked = 0;
2506         rv = -1;        /* system-detected error */
2507         if (t->type == TCOM) {
2508                 while ((cp = *wp++) != NULL)
2509                         ;
2510                 cp = *wp;
2511
2512                 /* strip all initial assignments */
2513                 /* not correct wrt PATH=yyy command  etc */
2514                 if (flag['x'])
2515                         echo (cp ? wp: owp);
2516                 if (cp == NULL && t->ioact == NULL) {
2517                         while ((cp = *owp++) != NULL && assign(cp, COPYV))
2518                                 ;
2519                         return(setstatus(0));
2520                 }
2521                 else if (cp != NULL)
2522                         shcom = inbuilt(cp);
2523         }
2524         t->words = wp;
2525         f = act;
2526         if (shcom == NULL && (f & FEXEC) == 0) {
2527
2528                 hpin = pin;
2529                 hpout = pout;
2530                 hforked = *pforked;
2531                 hwp = *wp;
2532                 hinteractive = interactive;
2533                 hintr = intr;
2534                 hbrklist = brklist;
2535                 hexecflg = execflg;
2536         
2537                 i = vfork();
2538                 if (i != 0) {
2539                         /* who wrote this crappy non vfork safe shit? */
2540                         pin = hpin;
2541                         pout = hpout;
2542                         *pforked = hforked;
2543                         *wp = hwp;
2544                         interactive = hinteractive;
2545                         intr = hintr;
2546                         brklist = hbrklist;
2547                         execflg = hexecflg;
2548
2549                         *pforked = 0;
2550                         if (i == -1)
2551                                 return(rv);
2552                         if (pin != NULL)
2553                                 closepipe(pin);
2554                         return(pout==NULL? setstatus(waitfor(i,0)): 0);
2555                 }
2556
2557                 if (interactive) {
2558                         signal(SIGINT, SIG_IGN);
2559                         signal(SIGQUIT, SIG_IGN);
2560                         resetsig = 1;
2561                 }
2562                 interactive = 0;
2563                 intr = 0;
2564                 (*pforked)++;
2565                 brklist = 0;
2566                 execflg = 0;
2567         }       
2568         if (owp != NULL)
2569                 while ((cp = *owp++) != NULL && assign(cp, COPYV))
2570                         if (shcom == NULL)
2571                                 export(lookup(cp));
2572 #ifdef COMPIPE
2573         if ((pin != NULL || pout != NULL) && shcom != NULL && shcom != doexec) {
2574                 err("piping to/from shell builtins not yet done");
2575                 return(-1);
2576         }
2577 #endif
2578         if (pin != NULL) {
2579                 dup2(pin[0], 0);
2580                 closepipe(pin);
2581         }
2582         if (pout != NULL) {
2583                 dup2(pout[1], 1);
2584                 closepipe(pout);
2585         }
2586         if ((iopp = t->ioact) != NULL) {
2587                 if (shcom != NULL && shcom != doexec) {
2588                         prs(cp);
2589                         err(": cannot redirect shell command");
2590                         return(-1);
2591                 }
2592                 while (*iopp)
2593                         if (iosetup(*iopp++, pin!=NULL, pout!=NULL))
2594                                 return(rv);
2595         }
2596         if (shcom)
2597                 return(setstatus((*shcom)(t)));
2598         /* should use FIOCEXCL */
2599         for (i=FDBASE; i<NOFILE; i++)
2600                 close(i);
2601         if (resetsig) {
2602                 signal(SIGINT, SIG_DFL);
2603                 signal(SIGQUIT, SIG_DFL);
2604         }
2605         if (t->type == TPAREN)
2606                 exit(execute(t->left, NOPIPE, NOPIPE, FEXEC));
2607         if (wp[0] == NULL)
2608                 exit(0);
2609
2610         cp = rexecve(wp[0], wp, makenv());
2611         prs(wp[0]); prs(": "); warn(cp);
2612         if (!execflg)
2613                 trap[0] = NULL;
2614         leave();
2615         /* NOTREACHED */
2616         exit(1);
2617 }
2618
2619 /*
2620  * 0< 1> are ignored as required
2621  * within pipelines.
2622  */
2623 static int
2624 iosetup(iop, pipein, pipeout)
2625 register struct ioword *iop;
2626 int pipein, pipeout;
2627 {
2628         register int u = -1;
2629         char *cp=NULL, *msg;
2630
2631         if (iop->io_unit == IODEFAULT)  /* take default */
2632                 iop->io_unit = iop->io_flag&(IOREAD|IOHERE)? 0: 1;
2633         if (pipein && iop->io_unit == 0)
2634                 return(0);
2635         if (pipeout && iop->io_unit == 1)
2636                 return(0);
2637         msg = iop->io_flag&(IOREAD|IOHERE)? "open": "create";
2638         if ((iop->io_flag & IOHERE) == 0) {
2639                 cp = iop->io_name;
2640                 if ((cp = evalstr(cp, DOSUB|DOTRIM)) == NULL)
2641                         return(1);
2642         }
2643         if (iop->io_flag & IODUP) {
2644                 if (cp[1] || (!isdigit(*cp) && *cp != '-')) {
2645                         prs(cp);
2646                         err(": illegal >& argument");
2647                         return(1);
2648                 }
2649                 if (*cp == '-')
2650                         iop->io_flag = IOCLOSE;
2651                 iop->io_flag &= ~(IOREAD|IOWRITE);
2652         }
2653         switch (iop->io_flag) {
2654         case IOREAD:
2655                 u = open(cp, 0);
2656                 break;
2657
2658         case IOHERE:
2659         case IOHERE|IOXHERE:
2660                 u = herein(iop->io_name, iop->io_flag&IOXHERE);
2661                 cp = "here file";
2662                 break;
2663
2664         case IOWRITE|IOCAT:
2665                 if ((u = open(cp, 1)) >= 0) {
2666                         lseek(u, (long)0, 2);
2667                         break;
2668                 }
2669         case IOWRITE:
2670                 u = creat(cp, 0666);
2671                 break;
2672
2673         case IODUP:
2674                 u = dup2(*cp-'0', iop->io_unit);
2675                 break;
2676
2677         case IOCLOSE:
2678                 close(iop->io_unit);
2679                 return(0);
2680         }
2681         if (u < 0) {
2682                 prs(cp);
2683                 prs(": cannot ");
2684                 warn(msg);
2685                 return(1);
2686         } else {
2687                 if (u != iop->io_unit) {
2688                         dup2(u, iop->io_unit);
2689                         close(u);
2690                 }
2691         }
2692         return(0);
2693 }
2694
2695 static void
2696 echo(wp)
2697 register char **wp;
2698 {
2699         register int i;
2700
2701         prs("+");
2702         for (i=0; wp[i]; i++) {
2703                 if (i)
2704                         prs(" ");
2705                 prs(wp[i]);
2706         }
2707         prs("\n");
2708 }
2709
2710 static struct op **
2711 find1case(t, w)
2712 struct op *t;
2713 char *w;
2714 {
2715         register struct op *t1;
2716         struct op **tp;
2717         register char **wp, *cp;
2718
2719         if (t == NULL)
2720                 return((struct op **)NULL);
2721         if (t->type == TLIST) {
2722                 if ((tp = find1case(t->left, w)) != NULL)
2723                         return(tp);
2724                 t1 = t->right;  /* TPAT */
2725         } else
2726                 t1 = t;
2727         for (wp = t1->words; *wp;)
2728                 if ((cp = evalstr(*wp++, DOSUB)) && gmatch(w, cp))
2729                         return(&t1->left);
2730         return((struct op **)NULL);
2731 }
2732
2733 static struct op *
2734 findcase(t, w)
2735 struct op *t;
2736 char *w;
2737 {
2738         register struct op **tp;
2739
2740         return((tp = find1case(t, w)) != NULL? *tp: (struct op *)NULL);
2741 }
2742
2743 /*
2744  * Enter a new loop level (marked for break/continue).
2745  */
2746 static void
2747 brkset(bc)
2748 struct brkcon *bc;
2749 {
2750         bc->nextlev = brklist;
2751         brklist = bc;
2752 }
2753
2754 /*
2755  * Wait for the last process created.
2756  * Print a message for each process found
2757  * that was killed by a signal.
2758  * Ignore interrupt signals while waiting
2759  * unless `canintr' is true.
2760  */
2761 static int
2762 waitfor(lastpid, canintr)
2763 register int lastpid;
2764 int canintr;
2765 {
2766         register int pid, rv;
2767         int s;
2768         int oheedint = heedint;
2769
2770         heedint = 0;
2771         rv = 0;
2772         do {
2773                 pid = wait(&s);
2774                 if (pid == -1) {
2775                         if (errno != EINTR || canintr)
2776                                 break;
2777                 } else {
2778                         if ((rv = WAITSIG(s)) != 0) {
2779                                 if (rv < NSIGNAL) {
2780                                         if (signame[rv] != NULL) {
2781                                                 if (pid != lastpid) {
2782                                                         prn(pid);
2783                                                         prs(": ");
2784                                                 }
2785                                                 prs(signame[rv]);
2786                                         }
2787                                 } else {
2788                                         if (pid != lastpid) {
2789                                                 prn(pid);
2790                                                 prs(": ");
2791                                         }
2792                                         prs("Signal "); prn(rv); prs(" ");
2793                                 }
2794                                 if (WAITCORE(s))
2795                                         prs(" - core dumped");
2796                                 if (rv >= NSIGNAL || signame[rv])
2797                                         prs("\n");
2798                                 rv = -1;
2799                         } else
2800                                 rv = WAITVAL(s);
2801                 }
2802         } while (pid != lastpid);
2803         heedint = oheedint;
2804         if (intr) {
2805                 if (interactive) {
2806                         if (canintr)
2807                                 intr = 0;
2808                 } else {
2809                         if (exstat == 0) exstat = rv;
2810                         onintr(0);
2811                 }
2812         }
2813         return(rv);
2814 }
2815
2816 static int
2817 setstatus(s)
2818 register int s;
2819 {
2820         exstat = s;
2821         setval(lookup("?"), putn(s));
2822         return(s);
2823 }
2824
2825 /*
2826  * PATH-searching interface to execve.
2827  * If getenv("PATH") were kept up-to-date,
2828  * execvp might be used.
2829  */
2830 static char *
2831 rexecve(c, v, envp)
2832 char *c, **v, **envp;
2833 {
2834         register int i;
2835         register char *sp, *tp;
2836         int eacces = 0, asis = 0;
2837
2838 #ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL
2839         char *name = c;
2840 #ifdef CONFIG_FEATURE_SH_APPLETS_ALWAYS_WIN
2841         name = bb_get_last_path_component(name);
2842 #endif
2843         optind = 1;
2844         if (find_applet_by_name(name)) {
2845                 /* We have to exec here since we vforked.  Running 
2846                  * run_applet_by_name() won't work and bad things
2847                  * will happen. */
2848                 execve("/proc/self/exe", v, envp);
2849                 execve("busybox", v, envp);
2850         }
2851 #endif
2852
2853         sp = any('/', c)? "": path->value;
2854         asis = *sp == '\0';
2855         while (asis || *sp != '\0') {
2856                 asis = 0;
2857                 tp = e.linep;
2858                 for (; *sp != '\0'; tp++)
2859                         if ((*tp = *sp++) == ':') {
2860                                 asis = *sp == '\0';
2861                                 break;
2862                         }
2863                 if (tp != e.linep)
2864                         *tp++ = '/';
2865                 for (i = 0; (*tp++ = c[i++]) != '\0';)
2866                         ;
2867
2868                 execve(e.linep, v, envp);
2869                 switch (errno) {
2870                 case ENOEXEC:
2871                         *v = e.linep;
2872                         tp = *--v;
2873                         *v = e.linep;
2874                         execve(shellname, v, envp);
2875                         *v = tp;
2876                         return("no Shell");
2877
2878                 case ENOMEM:
2879                         return((char*)bb_msg_memory_exhausted);
2880
2881                 case E2BIG:
2882                         return("argument list too long");
2883
2884                 case EACCES:
2885                         eacces++;
2886                         break;
2887                 }
2888         }
2889         return(errno==ENOENT ? "not found" : "cannot execute");
2890 }
2891
2892 /*
2893  * Run the command produced by generator `f'
2894  * applied to stream `arg'.
2895  */
2896 static int
2897 run(struct ioarg *argp, int (*f)(struct ioarg *))
2898 {
2899         struct op *otree;
2900         struct wdblock *swdlist;
2901         struct wdblock *siolist;
2902         jmp_buf ev, rt;
2903         xint *ofail;
2904         int rv;
2905
2906 #if __GNUC__
2907         /* Avoid longjmp clobbering */
2908         (void) &rv;
2909 #endif
2910
2911         areanum++;
2912         swdlist = wdlist;
2913         siolist = iolist;
2914         otree = outtree;
2915         ofail = failpt;
2916         rv = -1;
2917         if (newenv(setjmp(errpt = ev)) == 0) {
2918                 wdlist = 0;
2919                 iolist = 0;
2920                 pushio(argp, f);
2921                 e.iobase = e.iop;
2922                 yynerrs = 0;
2923                 if (setjmp(failpt = rt) == 0 && yyparse() == 0)
2924                         rv = execute(outtree, NOPIPE, NOPIPE, 0);
2925                 quitenv();
2926         }
2927         wdlist = swdlist;
2928         iolist = siolist;
2929         failpt = ofail;
2930         outtree = otree;
2931         freearea(areanum--);
2932         return(rv);
2933 }
2934
2935 /* -------- do.c -------- */
2936
2937 /*
2938  * built-in commands: doX
2939  */
2940
2941 static int dohelp(struct op *t )
2942 {
2943         int col;
2944         const struct builtincmd *x;
2945
2946         printf("\nBuilt-in commands:\n");
2947         printf("-------------------\n");
2948
2949         for (col=0, x = builtincmds; x->builtinfunc != NULL; x++) {
2950                 if (!x->name)
2951                         continue;
2952                 col += printf("%s%s", ((col == 0) ? "\t" : " "), x->name);
2953                 if (col > 60) {
2954                         printf("\n");
2955                         col = 0;
2956                 }
2957         }
2958 #ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL
2959         {
2960                 int i;
2961                 const struct BB_applet *applet;
2962                 extern const struct BB_applet applets[];
2963                 extern const size_t NUM_APPLETS;
2964
2965                 for (i=0, applet = applets; i < NUM_APPLETS; applet++, i++) {
2966                         if (!applet->name)
2967                                 continue;
2968                 
2969                         col += printf("%s%s", ((col == 0) ? "\t" : " "), 
2970                                         applet->name);
2971                         if (col > 60) {
2972                                 printf("\n");
2973                                 col = 0;
2974                         }
2975                 }
2976         }
2977 #endif
2978         printf("\n\n");
2979         return EXIT_SUCCESS;
2980 }
2981
2982
2983
2984 static int dolabel(struct op *t )
2985 {
2986         return(0);
2987 }
2988
2989 static int
2990 dochdir(t)
2991 register struct op *t;
2992 {
2993         register char *cp, *er;
2994
2995         if ((cp = t->words[1]) == NULL && (cp = homedir->value) == NULL)
2996                 er = ": no home directory";
2997         else if(chdir(cp) < 0)
2998                 er = ": bad directory";
2999         else
3000                 return(0);
3001         prs(cp != NULL? cp: "cd");
3002         err(er);
3003         return(1);
3004 }
3005
3006 static int
3007 doshift(t)
3008 register struct op *t;
3009 {
3010         register int n;
3011
3012         n = t->words[1]? getn(t->words[1]): 1;
3013         if(dolc < n) {
3014                 err("nothing to shift");
3015                 return(1);
3016         }
3017         dolv[n] = dolv[0];
3018         dolv += n;
3019         dolc -= n;
3020         setval(lookup("#"), putn(dolc));
3021         return(0);
3022 }
3023
3024 /*
3025  * execute login and newgrp directly
3026  */
3027 static int
3028 dologin(t)
3029 struct op *t;
3030 {
3031         register char *cp;
3032
3033         if (interactive) {
3034                 signal(SIGINT, SIG_DFL);
3035                 signal(SIGQUIT, SIG_DFL);
3036         }
3037         cp = rexecve(t->words[0], t->words, makenv());
3038         prs(t->words[0]); prs(": "); err(cp);
3039         return(1);
3040 }
3041
3042 static int
3043 doumask(t)
3044 register struct op *t;
3045 {
3046         register int i, n;
3047         register char *cp;
3048
3049         if ((cp = t->words[1]) == NULL) {
3050                 i = umask(0);
3051                 umask(i);
3052                 for (n=3*4; (n-=3) >= 0;)
3053                         putc('0'+((i>>n)&07), stderr);
3054                 putc('\n', stderr);
3055         } else {
3056                 for (n=0; *cp>='0' && *cp<='9'; cp++)
3057                         n = n*8 + (*cp-'0');
3058                 umask(n);
3059         }
3060         return(0);
3061 }
3062
3063 static int
3064 doexec(t)
3065 register struct op *t;
3066 {
3067         register int i;
3068         jmp_buf ex;
3069         xint *ofail;
3070
3071         t->ioact = NULL;
3072         for(i = 0; (t->words[i]=t->words[i+1]) != NULL; i++)
3073                 ;
3074         if (i == 0)
3075                 return(1);
3076         execflg = 1;
3077         ofail = failpt;
3078         if (setjmp(failpt = ex) == 0)
3079                 execute(t, NOPIPE, NOPIPE, FEXEC);
3080         failpt = ofail;
3081         execflg = 0;
3082         return(1);
3083 }
3084
3085 static int
3086 dodot(t)
3087 struct op *t;
3088 {
3089         register int i;
3090         register char *sp, *tp;
3091         char *cp;
3092
3093         if ((cp = t->words[1]) == NULL)
3094                 return(0);
3095         sp = any('/', cp)? ":": path->value;
3096         while (*sp) {
3097                 tp = e.linep;
3098                 while (*sp && (*tp = *sp++) != ':')
3099                         tp++;
3100                 if (tp != e.linep)
3101                         *tp++ = '/';
3102                 for (i = 0; (*tp++ = cp[i++]) != '\0';)
3103                         ;
3104                 if ((i = open(e.linep, 0)) >= 0) {
3105                         exstat = 0;
3106                         next(remap(i));
3107                         return(exstat);
3108                 }
3109         }
3110         prs(cp);
3111         err(": not found");
3112         return(-1);
3113 }
3114
3115 static int
3116 dowait(t)
3117 struct op *t;
3118 {
3119         register int i;
3120         register char *cp;
3121
3122         if ((cp = t->words[1]) != NULL) {
3123                 i = getn(cp);
3124                 if (i == 0)
3125                         return(0);
3126         } else
3127                 i = -1;
3128         setstatus(waitfor(i, 1));
3129         return(0);
3130 }
3131
3132 static int
3133 doread(t)
3134 struct op *t;
3135 {
3136         register char *cp, **wp;
3137         register int nb = 0;
3138         register int  nl = 0;
3139
3140         if (t->words[1] == NULL) {
3141                 err("Usage: read name ...");
3142                 return(1);
3143         }
3144         for (wp = t->words+1; *wp; wp++) {
3145                 for (cp = e.linep; !nl && cp < elinep-1; cp++)
3146                         if ((nb = read(0, cp, sizeof(*cp))) != sizeof(*cp) ||
3147                             (nl = (*cp == '\n')) ||
3148                             (wp[1] && any(*cp, ifs->value)))
3149                                 break;
3150                 *cp = 0;
3151                 if (nb <= 0)
3152                         break;
3153                 setval(lookup(*wp), e.linep);
3154         }
3155         return(nb <= 0);
3156 }
3157
3158 static int
3159 doeval(t)
3160 register struct op *t;
3161 {
3162         return(RUN(awordlist, t->words+1, wdchar));
3163 }
3164
3165 static int
3166 dotrap(t)
3167 register struct op *t;
3168 {
3169         register int  n, i;
3170         register int  resetsig;
3171
3172         if (t->words[1] == NULL) {
3173                 for (i=0; i<=_NSIG; i++)
3174                         if (trap[i]) {
3175                                 prn(i);
3176                                 prs(": ");
3177                                 prs(trap[i]);
3178                                 prs("\n");
3179                         }
3180                 return(0);
3181         }
3182         resetsig = isdigit(*t->words[1]);
3183         for (i = resetsig ? 1 : 2; t->words[i] != NULL; ++i) {
3184                 n = getsig(t->words[i]);
3185                 freecell(trap[n]);
3186                 trap[n] = 0;
3187                 if (!resetsig) {
3188                         if (*t->words[1] != '\0') {
3189                                 trap[n] = strsave(t->words[1], 0);
3190                                 setsig(n, sig);
3191                         } else
3192                                 setsig(n, SIG_IGN);
3193                 } else {
3194                         if (interactive)
3195                                 if (n == SIGINT)
3196                                         setsig(n, onintr);
3197                                 else
3198                                         setsig(n, n == SIGQUIT ? SIG_IGN 
3199                                                                : SIG_DFL);
3200                         else
3201                                 setsig(n, SIG_DFL);
3202                 }
3203         }
3204         return(0);
3205 }
3206
3207 static int
3208 getsig(s)
3209 char *s;
3210 {
3211         register int n;
3212
3213         if ((n = getn(s)) < 0 || n > _NSIG) {
3214                 err("trap: bad signal number");
3215                 n = 0;
3216         }
3217         return(n);
3218 }
3219
3220 static void
3221 setsig( register int n, sighandler_t f)
3222 {
3223         if (n == 0)
3224                 return;
3225         if (signal(n, SIG_IGN) != SIG_IGN || ourtrap[n]) {
3226                 ourtrap[n] = 1;
3227                 signal(n, f);
3228         }
3229 }
3230
3231 static int
3232 getn(as)
3233 char *as;
3234 {
3235         register char *s;
3236         register int n, m;
3237
3238         s = as;
3239         m = 1;
3240         if (*s == '-') {
3241                 m = -1;
3242                 s++;
3243         }
3244         for (n = 0; isdigit(*s); s++)
3245                 n = (n*10) + (*s-'0');
3246         if (*s) {
3247                 prs(as);
3248                 err(": bad number");
3249         }
3250         return(n*m);
3251 }
3252
3253 static int
3254 dobreak(t)
3255 struct op *t;
3256 {
3257         return(brkcontin(t->words[1], 1));
3258 }
3259
3260 static int
3261 docontinue(t)
3262 struct op *t;
3263 {
3264         return(brkcontin(t->words[1], 0));
3265 }
3266
3267 static int
3268 brkcontin(cp, val)
3269 register char *cp;
3270 int val;
3271 {
3272         register struct brkcon *bc;
3273         register int nl;
3274
3275         nl = cp == NULL? 1: getn(cp);
3276         if (nl <= 0)
3277                 nl = 999;
3278         do {
3279                 if ((bc = brklist) == NULL)
3280                         break;
3281                 brklist = bc->nextlev;
3282         } while (--nl);
3283         if (nl) {
3284                 err("bad break/continue level");
3285                 return(1);
3286         }
3287         isbreak = val;
3288         longjmp(bc->brkpt, 1);
3289         /* NOTREACHED */
3290 }
3291
3292 static int
3293 doexit(t)
3294 struct op *t;
3295 {
3296         register char *cp;
3297
3298         execflg = 0;
3299         if ((cp = t->words[1]) != NULL)
3300                 setstatus(getn(cp));
3301         leave();
3302         /* NOTREACHED */
3303         return(0);
3304 }
3305
3306 static int
3307 doexport(t)
3308 struct op *t;
3309 {
3310         rdexp(t->words+1, export, EXPORT);
3311         return(0);
3312 }
3313
3314 static int
3315 doreadonly(t)
3316 struct op *t;
3317 {
3318         rdexp(t->words+1, ronly, RONLY);
3319         return(0);
3320 }
3321
3322 static void rdexp (char **wp, void (*f)(struct var *), int key)
3323 {
3324         if (*wp != NULL) {
3325                 for (; *wp != NULL; wp++) {
3326                         if (isassign(*wp)) {
3327                                 char *cp;
3328                                 assign(*wp, COPYV);
3329                                 for (cp = *wp; *cp != '='; cp++)
3330                                         ;
3331                                 *cp = '\0';
3332                         }
3333                         if (checkname(*wp))
3334                                 (*f)(lookup(*wp));
3335                         else
3336                                 badid(*wp);
3337                 }
3338         } else
3339                 putvlist(key, 1);
3340 }
3341
3342 static void
3343 badid(s)
3344 register char *s;
3345 {
3346         prs(s);
3347         err(": bad identifier");
3348 }
3349
3350 static int
3351 doset(t)
3352 register struct op *t;
3353 {
3354         register struct var *vp;
3355         register char *cp;
3356         register int n;
3357
3358         if ((cp = t->words[1]) == NULL) {
3359                 for (vp = vlist; vp; vp = vp->next)
3360                         varput(vp->name, 1);
3361                 return(0);
3362         }
3363         if (*cp == '-') {
3364                 /* bad: t->words++; */
3365                 for(n = 0; (t->words[n]=t->words[n+1]) != NULL; n++)
3366                         ;
3367                 if (*++cp == 0)
3368                         flag['x'] = flag['v'] = 0;
3369                 else
3370                         for (; *cp; cp++)
3371                                 switch (*cp) {
3372                                 case 'e':
3373                                         if (!interactive)
3374                                                 flag['e']++;
3375                                         break;
3376
3377                                 default:
3378                                         if (*cp>='a' && *cp<='z')
3379                                                 flag[(int)*cp]++;
3380                                         break;
3381                                 }
3382                 setdash();
3383         }
3384         if (t->words[1]) {
3385                 t->words[0] = dolv[0];
3386                 for (n=1; t->words[n]; n++)
3387                         setarea((char *)t->words[n], 0);
3388                 dolc = n-1;
3389                 dolv = t->words;
3390                 setval(lookup("#"), putn(dolc));
3391                 setarea((char *)(dolv-1), 0);
3392         }
3393         return(0);
3394 }
3395
3396 static void
3397 varput(s, out)
3398 register char *s;
3399 int out;
3400 {
3401         if (isalnum(*s) || *s == '_') {
3402                 write(out, s, strlen(s));
3403                 write(out, "\n", 1);
3404         }
3405 }
3406
3407
3408 /*
3409  * Copyright (c) 1999 Herbert Xu <herbert@debian.org>
3410  * This file contains code for the times builtin.
3411  */
3412 static int dotimes(struct op *t )
3413 {
3414         struct tms buf;
3415         long int clk_tck = sysconf(_SC_CLK_TCK);
3416
3417         times(&buf);
3418         printf("%dm%fs %dm%fs\n%dm%fs %dm%fs\n",
3419                (int) (buf.tms_utime / clk_tck / 60),
3420                ((double) buf.tms_utime) / clk_tck,
3421                (int) (buf.tms_stime / clk_tck / 60),
3422                ((double) buf.tms_stime) / clk_tck,
3423                (int) (buf.tms_cutime / clk_tck / 60),
3424                ((double) buf.tms_cutime) / clk_tck,
3425                (int) (buf.tms_cstime / clk_tck / 60),
3426                ((double) buf.tms_cstime) / clk_tck);
3427         return 0;
3428 }
3429
3430
3431 static int(*inbuilt(char *s))(struct op *)
3432 {
3433         const struct builtincmd *bp;
3434
3435         for (bp = builtincmds; bp->name != NULL; bp++)
3436                 if (strcmp(bp->name, s) == 0)
3437                         return(bp->builtinfunc);
3438
3439         return(NULL);
3440 }
3441
3442 /* -------- eval.c -------- */
3443
3444 /*
3445  * ${}
3446  * `command`
3447  * blank interpretation
3448  * quoting
3449  * glob
3450  */
3451
3452 static char ** eval( char **ap, int f)
3453 {
3454         struct wdblock *wb;
3455         char **wp;
3456         char **wf;
3457         jmp_buf ev;
3458
3459 #if __GNUC__
3460         /* Avoid longjmp clobbering */
3461         (void) &wp;
3462         (void) &ap;
3463 #endif
3464         wp = NULL;
3465         wb = NULL;
3466         wf = NULL;
3467         if (newenv(setjmp(errpt = ev)) == 0) {
3468                 while (*ap && isassign(*ap))
3469                         expand(*ap++, &wb, f & ~DOGLOB);
3470                 if (flag['k']) {
3471                         for (wf = ap; *wf; wf++) {
3472                                 if (isassign(*wf))
3473                                         expand(*wf, &wb, f & ~DOGLOB);
3474                         }
3475                 }
3476                 for (wb = addword((char *)0, wb); *ap; ap++) {
3477                         if (!flag['k'] || !isassign(*ap))
3478                                 expand(*ap, &wb, f & ~DOKEY);
3479                 }
3480                 wb = addword((char *)0, wb);
3481                 wp = getwords(wb);
3482                 quitenv();
3483         } else
3484                 gflg = 1;
3485         return(gflg? (char **)NULL: wp);
3486 }
3487
3488 /*
3489  * Make the exported environment from the exported
3490  * names in the dictionary. Keyword assignments
3491  * will already have been done.
3492  */
3493 static char **
3494 makenv()
3495
3496 {
3497         register struct wdblock *wb;
3498         register struct var *vp;
3499
3500         wb = NULL;
3501         for (vp = vlist; vp; vp = vp->next)
3502                 if (vp->status & EXPORT)
3503                         wb = addword(vp->name, wb);
3504         wb = addword((char *)0, wb);
3505         return(getwords(wb));
3506 }
3507
3508 static char *
3509 evalstr(cp, f)
3510 register char *cp;
3511 int f;
3512 {
3513         struct wdblock *wb;
3514
3515         wb = NULL;
3516         if (expand(cp, &wb, f)) {
3517                 if (wb == NULL || wb->w_nword == 0 || (cp = wb->w_words[0]) == NULL)
3518                         cp = "";
3519                 DELETE(wb);
3520         } else
3521                 cp = NULL;
3522         return(cp);
3523 }
3524
3525 static int
3526 expand( char *cp, register struct wdblock **wbp, int f)
3527 {
3528         jmp_buf ev;
3529
3530 #if __GNUC__
3531         /* Avoid longjmp clobbering */
3532         (void) &cp;
3533 #endif
3534         gflg = 0;
3535         if (cp == NULL)
3536                 return(0);
3537         if (!anys("$`'\"", cp) &&
3538             !anys(ifs->value, cp) &&
3539             ((f&DOGLOB)==0 || !anys("[*?", cp))) {
3540                 cp = strsave(cp, areanum);
3541                 if (f & DOTRIM)
3542                         unquote(cp);
3543                 *wbp = addword(cp, *wbp);
3544                 return(1);
3545         }
3546         if (newenv(setjmp(errpt = ev)) == 0) {
3547                 PUSHIO(aword, cp, strchar);
3548                 e.iobase = e.iop;
3549                 while ((cp = blank(f)) && gflg == 0) {
3550                         e.linep = cp;
3551                         cp = strsave(cp, areanum);
3552                         if ((f&DOGLOB) == 0) {
3553                                 if (f & DOTRIM)
3554                                         unquote(cp);
3555                                 *wbp = addword(cp, *wbp);
3556                         } else
3557                                 *wbp = glob(cp, *wbp);
3558                 }
3559                 quitenv();
3560         } else
3561                 gflg = 1;
3562         return(gflg == 0);
3563 }
3564
3565 /*
3566  * Blank interpretation and quoting
3567  */
3568 static char *
3569 blank(f)
3570 int f;
3571 {
3572         register int c, c1;
3573         register char *sp;
3574         int scanequals, foundequals;
3575
3576         sp = e.linep;
3577         scanequals = f & DOKEY;
3578         foundequals = 0;
3579
3580 loop:
3581         switch (c = subgetc('"', foundequals)) {
3582         case 0:
3583                 if (sp == e.linep)
3584                         return(0);
3585                 *e.linep++ = 0;
3586                 return(sp);
3587
3588         default:
3589                 if (f & DOBLANK && any(c, ifs->value))
3590                         goto loop;
3591                 break;
3592
3593         case '"':
3594         case '\'':
3595                 scanequals = 0;
3596                 if (INSUB())
3597                         break;
3598                 for (c1 = c; (c = subgetc(c1, 1)) != c1;) {
3599                         if (c == 0)
3600                                 break;
3601                         if (c == '\'' || !any(c, "$`\""))
3602                                 c |= QUOTE;
3603                         *e.linep++ = c;
3604                 }
3605                 c = 0;
3606         }
3607         unget(c);
3608         if (!isalpha(c) && c != '_')
3609                 scanequals = 0;
3610         for (;;) {
3611                 c = subgetc('"', foundequals);
3612                 if (c == 0 ||
3613                     f & (DOBLANK && any(c, ifs->value)) ||
3614                     (!INSUB() && any(c, "\"'"))) {
3615                         scanequals = 0;
3616                         unget(c);
3617                         if (any(c, "\"'"))
3618                                 goto loop;
3619                         break;
3620                 }
3621                 if (scanequals) {
3622                         if (c == '=') {
3623                                 foundequals = 1;
3624                                 scanequals  = 0;
3625                         }
3626                         else if (!isalnum(c) && c != '_')
3627                                 scanequals = 0;
3628                 }
3629                 *e.linep++ = c;
3630         }
3631         *e.linep++ = 0;
3632         return(sp);
3633 }
3634
3635 /*
3636  * Get characters, substituting for ` and $
3637  */
3638 static int
3639 subgetc(ec, quoted)
3640 register char ec;
3641 int quoted;
3642 {
3643         register char c;
3644
3645 again:
3646         c = my_getc(ec);
3647         if (!INSUB() && ec != '\'') {
3648                 if (c == '`') {
3649                         if (grave(quoted) == 0)
3650                                 return(0);
3651                         e.iop->task = XGRAVE;
3652                         goto again;
3653                 }
3654                 if (c == '$' && (c = dollar(quoted)) == 0) {
3655                         e.iop->task = XDOLL;
3656                         goto again;
3657                 }
3658         }
3659         return(c);
3660 }
3661
3662 /*
3663  * Prepare to generate the string returned by ${} substitution.
3664  */
3665 static int
3666 dollar(quoted)
3667 int quoted;
3668 {
3669         int otask;
3670         struct io *oiop;
3671         char *dolp;
3672         register char *s, c, *cp=NULL;
3673         struct var *vp;
3674
3675         c = readc();
3676         s = e.linep;
3677         if (c != '{') {
3678                 *e.linep++ = c;
3679                 if (isalpha(c) || c == '_') {
3680                         while ((c = readc())!=0 && (isalnum(c) || c == '_'))
3681                                 if (e.linep < elinep)
3682                                         *e.linep++ = c;
3683                         unget(c);
3684                 }
3685                 c = 0;
3686         } else {
3687                 oiop = e.iop;
3688                 otask = e.iop->task;
3689                 e.iop->task = XOTHER;
3690                 while ((c = subgetc('"', 0))!=0 && c!='}' && c!='\n')
3691                         if (e.linep < elinep)
3692                                 *e.linep++ = c;
3693                 if (oiop == e.iop)
3694                         e.iop->task = otask;
3695                 if (c != '}') {
3696                         err("unclosed ${");
3697                         gflg++;
3698                         return(c);
3699                 }
3700         }
3701         if (e.linep >= elinep) {
3702                 err("string in ${} too long");
3703                 gflg++;
3704                 e.linep -= 10;
3705         }
3706         *e.linep = 0;
3707         if (*s)
3708                 for (cp = s+1; *cp; cp++)
3709                         if (any(*cp, "=-+?")) {
3710                                 c = *cp;
3711                                 *cp++ = 0;
3712                                 break;
3713                         }
3714         if (s[1] == 0 && (*s == '*' || *s == '@')) {
3715                 if (dolc > 1) {
3716                         /* currently this does not distinguish $* and $@ */
3717                         /* should check dollar */
3718                         e.linep = s;
3719                         PUSHIO(awordlist, dolv+1, dolchar);
3720                         return(0);
3721                 } else {        /* trap the nasty ${=} */
3722                         s[0] = '1';
3723                         s[1] = 0;
3724                 }
3725         }
3726         vp = lookup(s);
3727         if ((dolp = vp->value) == null) {
3728                 switch (c) {
3729                 case '=':
3730                         if (isdigit(*s)) {
3731                                 err("cannot use ${...=...} with $n");
3732                                 gflg++;
3733                                 break;
3734                         }
3735                         setval(vp, cp);
3736                         dolp = vp->value;
3737                         break;
3738
3739                 case '-':
3740                         dolp = strsave(cp, areanum);
3741                         break;
3742
3743                 case '?':
3744                         if (*cp == 0) {
3745                                 prs("missing value for ");
3746                                 err(s);
3747                         } else
3748                                 err(cp);
3749                         gflg++;
3750                         break;
3751                 }
3752         } else if (c == '+')
3753                 dolp = strsave(cp, areanum);
3754         if (flag['u'] && dolp == null) {
3755                 prs("unset variable: ");
3756                 err(s);
3757                 gflg++;
3758         }
3759         e.linep = s;
3760         PUSHIO(aword, dolp, quoted ? qstrchar : strchar);
3761         return(0);
3762 }
3763
3764 /*
3765  * Run the command in `...` and read its output.
3766  */
3767
3768 static int
3769 grave(quoted)
3770 int quoted;
3771 {
3772         char *cp;
3773         register int i;
3774         int j;
3775         int pf[2];
3776         static char child_cmd[LINELIM];
3777         char *src;
3778         char *dest;
3779         int count;
3780         int ignore;
3781         int ignore_once;
3782         char *argument_list[4];
3783
3784 #if __GNUC__
3785         /* Avoid longjmp clobbering */
3786         (void) &cp;
3787 #endif
3788         
3789         for (cp = e.iop->argp->aword; *cp != '`'; cp++)
3790                 if (*cp == 0) {
3791                         err("no closing `");
3792                         return(0);
3793                 }
3794
3795         /* string copy with dollar expansion */
3796         src = e.iop->argp->aword;
3797         dest = child_cmd;
3798         count = 0;
3799         ignore = 0;
3800         ignore_once = 0;
3801         while ((*src != '`') && (count < LINELIM)) {
3802                 if (*src == '\'')
3803                         ignore = !ignore;
3804                 if (*src == '\\')
3805                         ignore_once = 1;
3806                 if (*src == '$' && !ignore && !ignore_once) {
3807                         struct var *vp;
3808                         char var_name[LINELIM];
3809                         char alt_value[LINELIM];
3810                         int var_index = 0;
3811                         int alt_index = 0;
3812                         char operator = 0;
3813                         int braces = 0;
3814                         char *value;
3815
3816                         src++;
3817                         if (*src == '{') {
3818                                 braces = 1;
3819                                 src++;
3820                         }
3821
3822                         var_name[var_index++] = *src++;
3823                         while (isalnum(*src))
3824                                 var_name[var_index++] = *src++;
3825                         var_name[var_index] = 0;
3826
3827                         if (braces) {
3828                                 switch (*src) {
3829                                 case '}':
3830                                         break;
3831                                 case '-':
3832                                 case '=':
3833                                 case '+':
3834                                 case '?':
3835                                         operator = *src;
3836                                         break;
3837                                 default:
3838                                         err("unclosed ${\n");
3839                                         return(0);
3840                                 }
3841                                 if (operator) { 
3842                                         src++;
3843                                         while (*src && (*src != '}')) {
3844                                                 alt_value[alt_index++] = *src++;
3845                                         }
3846                                         alt_value[alt_index] = 0;
3847                                         if (*src != '}') {
3848                                                 err("unclosed ${\n");
3849                                                 return(0);
3850                                         }
3851                                 }
3852                                 src++;
3853                         }
3854
3855                         vp = lookup(var_name);
3856                         if (vp->value != null)
3857                                 value = (operator == '+')? alt_value : vp->value;
3858                         else if (operator == '?') {
3859                                 err(alt_value);
3860                                 return(0);
3861                         } else if (alt_index && (operator != '+')) {
3862                                 value = alt_value;
3863                                 if (operator == '=')
3864                                         setval(vp, value);
3865                         } else
3866                                 continue;
3867
3868                         while (*value && (count < LINELIM)) {
3869                                 *dest++ = *value++;
3870                                 count++;
3871                         }
3872                 } else {
3873                         *dest++ = *src++;
3874                         count++;
3875                         ignore_once = 0;
3876                 }
3877         }
3878         *dest = '\0';
3879         
3880         if (openpipe(pf) < 0)
3881                 return(0);
3882         while ((i = vfork()) == -1 && errno == EAGAIN)
3883                 ;
3884         if (i < 0) {
3885                 closepipe(pf);
3886                 err((char*)bb_msg_memory_exhausted);
3887                 return(0);
3888         }
3889         if (i != 0) {
3890                 waitpid(i, NULL, 0);
3891                 e.iop->argp->aword = ++cp;
3892                 close(pf[1]);
3893                 PUSHIO(afile, remap(pf[0]), (int(*)(struct ioarg *))((quoted)? qgravechar: gravechar));
3894                 return(1);
3895         }
3896         /* allow trapped signals */
3897         /* XXX - Maybe this signal stuff should go as well? */
3898         for (j=0; j<=_NSIG; j++)
3899                 if (ourtrap[j] && signal(j, SIG_IGN) != SIG_IGN)
3900                         signal(j, SIG_DFL);
3901         
3902         dup2(pf[1], 1);
3903         closepipe(pf);
3904
3905         argument_list[0] = shellname;
3906         argument_list[1] = "-c";
3907         argument_list[2] = child_cmd;
3908         argument_list[3] = 0;
3909
3910         prs(rexecve(argument_list[0], argument_list, makenv()));
3911         _exit(1);
3912 }
3913
3914
3915 static char *
3916 unquote(as)
3917 register char *as;
3918 {
3919         register char *s;
3920
3921         if ((s = as) != NULL)
3922                 while (*s)
3923                         *s++ &= ~QUOTE;
3924         return(as);
3925 }
3926
3927 /* -------- glob.c -------- */
3928
3929 /*
3930  * glob
3931  */
3932
3933 #define scopy(x) strsave((x), areanum)
3934 #define BLKSIZ  512
3935 #define NDENT   ((BLKSIZ+sizeof(struct dirent)-1)/sizeof(struct dirent))
3936
3937 static  struct wdblock  *cl, *nl;
3938 static  char    spcl[] = "[?*";
3939
3940 static struct wdblock *
3941 glob(cp, wb)
3942 char *cp;
3943 struct wdblock *wb;
3944 {
3945         register int i;
3946         register char *pp;
3947
3948         if (cp == 0)
3949                 return(wb);
3950         i = 0;
3951         for (pp = cp; *pp; pp++)
3952                 if (any(*pp, spcl))
3953                         i++;
3954                 else if (!any(*pp & ~QUOTE, spcl))
3955                         *pp &= ~QUOTE;
3956         if (i != 0) {
3957                 for (cl = addword(scopy(cp), (struct wdblock *)0); anyspcl(cl); cl = nl) {
3958                         nl = newword(cl->w_nword*2);
3959                         for(i=0; i<cl->w_nword; i++) { /* for each argument */
3960                                 for (pp = cl->w_words[i]; *pp; pp++)
3961                                         if (any(*pp, spcl)) {
3962                                                 globname(cl->w_words[i], pp);
3963                                                 break;
3964                                         }
3965                                 if (*pp == '\0')
3966                                         nl = addword(scopy(cl->w_words[i]), nl);
3967                         }
3968                         for(i=0; i<cl->w_nword; i++)
3969                                 DELETE(cl->w_words[i]);
3970                         DELETE(cl);
3971                 }
3972                 for(i=0; i<cl->w_nword; i++)
3973                         unquote(cl->w_words[i]);
3974                 glob0((char *)cl->w_words, cl->w_nword, sizeof(char *), xstrcmp);
3975                 if (cl->w_nword) {
3976                         for (i=0; i<cl->w_nword; i++)
3977                                 wb = addword(cl->w_words[i], wb);
3978                         DELETE(cl);
3979                         return(wb);
3980                 }
3981         }
3982         wb = addword(unquote(cp), wb);
3983         return(wb);
3984 }
3985
3986 static void
3987 globname(we, pp)
3988 char *we;
3989 register char *pp;
3990 {
3991         register char *np, *cp;
3992         char *name, *gp, *dp;
3993         int k;
3994         DIR *dirp;
3995         struct dirent *de;
3996         char dname[NAME_MAX+1];
3997         struct stat dbuf;
3998
3999         for (np = we; np != pp; pp--)
4000                 if (pp[-1] == '/')
4001                         break;
4002         for (dp = cp = space((int)(pp-np)+3); np < pp;)
4003                 *cp++ = *np++;
4004         *cp++ = '.';
4005         *cp = '\0';
4006         for (gp = cp = space(strlen(pp)+1); *np && *np != '/';)
4007                 *cp++ = *np++;
4008         *cp = '\0';
4009         dirp = opendir(dp);
4010         if (dirp == 0) {
4011                 DELETE(dp);
4012                 DELETE(gp);
4013                 return;
4014         }
4015         dname[NAME_MAX] = '\0';
4016         while ((de=readdir(dirp))!=NULL) {
4017                 /* XXX Hmmm... What this could be? (abial) */
4018                 /*
4019                 if (ent[j].d_ino == 0)
4020                         continue;
4021                 */
4022                 strncpy(dname, de->d_name, NAME_MAX);
4023                         if (dname[0] == '.')
4024                                 if (*gp != '.')
4025                                         continue;
4026                         for(k=0; k<NAME_MAX; k++)
4027                                 if (any(dname[k], spcl))
4028                                         dname[k] |= QUOTE;
4029                         if (gmatch(dname, gp)) {
4030                                 name = generate(we, pp, dname, np);
4031                                 if (*np && !anys(np, spcl)) {
4032                                         if (stat(name,&dbuf)) {
4033                                                 DELETE(name);
4034                                                 continue;
4035                                         }
4036                                 }
4037                                 nl = addword(name, nl);
4038                         }
4039         }
4040         closedir(dirp);
4041         DELETE(dp);
4042         DELETE(gp);
4043 }
4044
4045 /*
4046  * generate a pathname as below.
4047  * start..end1 / middle end
4048  * the slashes come for free
4049  */
4050 static char *
4051 generate(start1, end1, middle, end)
4052 char *start1;
4053 register char *end1;
4054 char *middle, *end;
4055 {
4056         char *p;
4057         register char *op, *xp;
4058
4059         p = op = space((int)(end1-start1)+strlen(middle)+strlen(end)+2);
4060         for (xp = start1; xp != end1;)
4061                 *op++ = *xp++;
4062         for (xp = middle; (*op++ = *xp++) != '\0';)
4063                 ;
4064         op--;
4065         for (xp = end; (*op++ = *xp++) != '\0';)
4066                 ;
4067         return(p);
4068 }
4069
4070 static int
4071 anyspcl(wb)
4072 register struct wdblock *wb;
4073 {
4074         register int i;
4075         register char **wd;
4076
4077         wd = wb->w_words;
4078         for (i=0; i<wb->w_nword; i++)
4079                 if (anys(spcl, *wd++))
4080                         return(1);
4081         return(0);
4082 }
4083
4084 static int
4085 xstrcmp(p1, p2)
4086 char *p1, *p2;
4087 {
4088         return(strcmp(*(char **)p1, *(char **)p2));
4089 }
4090
4091 /* -------- word.c -------- */
4092
4093 static struct wdblock *
4094 newword(nw)
4095 register int nw;
4096 {
4097         register struct wdblock *wb;
4098
4099         wb = (struct wdblock *) space(sizeof(*wb) + nw*sizeof(char *));
4100         wb->w_bsize = nw;
4101         wb->w_nword = 0;
4102         return(wb);
4103 }
4104
4105 static struct wdblock *
4106 addword(wd, wb)
4107 char *wd;
4108 register struct wdblock *wb;
4109 {
4110         register struct wdblock *wb2;
4111         register int nw;
4112
4113         if (wb == NULL)
4114                 wb = newword(NSTART);
4115         if ((nw = wb->w_nword) >= wb->w_bsize) {
4116                 wb2 = newword(nw * 2);
4117                 memcpy((char *)wb2->w_words, (char *)wb->w_words, nw*sizeof(char *));
4118                 wb2->w_nword = nw;
4119                 DELETE(wb);
4120                 wb = wb2;
4121         }
4122         wb->w_words[wb->w_nword++] = wd;
4123         return(wb);
4124 }
4125 static 
4126 char **
4127 getwords(wb)
4128 register struct wdblock *wb;
4129 {
4130         register char **wd;
4131         register int nb;
4132
4133         if (wb == NULL)
4134                 return((char **)NULL);
4135         if (wb->w_nword == 0) {
4136                 DELETE(wb);
4137                 return((char **)NULL);
4138         }
4139         wd = (char **) space(nb = sizeof(*wd) * wb->w_nword);
4140         memcpy((char *)wd, (char *)wb->w_words, nb);
4141         DELETE(wb);     /* perhaps should done by caller */
4142         return(wd);
4143 }
4144
4145 int (*func)(char *, char *);
4146 int     globv;
4147
4148 static void
4149 glob0(a0, a1, a2, a3)
4150 char *a0;
4151 unsigned a1;
4152 int a2;
4153 int (*a3) (char *, char *);
4154 {
4155         func = a3;
4156         globv = a2;
4157         glob1(a0, a0 + a1 * a2);
4158 }
4159
4160 static void
4161 glob1(base, lim)
4162 char *base, *lim;
4163 {
4164         register char *i, *j;
4165         int v2;
4166         char *lptr, *hptr;
4167         int c;
4168         unsigned n;
4169
4170
4171         v2 = globv;
4172
4173 top:
4174         if ((n=(int)(lim-base)) <= v2)
4175                 return;
4176         n = v2 * (n / (2*v2));
4177         hptr = lptr = base+n;
4178         i = base;
4179         j = lim-v2;
4180         for(;;) {
4181                 if (i < lptr) {
4182                         if ((c = (*func)(i, lptr)) == 0) {
4183                                 glob2(i, lptr -= v2);
4184                                 continue;
4185                         }
4186                         if (c < 0) {
4187                                 i += v2;
4188                                 continue;
4189                         }
4190                 }
4191
4192 begin:
4193                 if (j > hptr) {
4194                         if ((c = (*func)(hptr, j)) == 0) {
4195                                 glob2(hptr += v2, j);
4196                                 goto begin;
4197                         }
4198                         if (c > 0) {
4199                                 if (i == lptr) {
4200                                         glob3(i, hptr += v2, j);
4201                                         i = lptr += v2;
4202                                         goto begin;
4203                                 }
4204                                 glob2(i, j);
4205                                 j -= v2;
4206                                 i += v2;
4207                                 continue;
4208                         }
4209                         j -= v2;
4210                         goto begin;
4211                 }
4212
4213
4214                 if (i == lptr) {
4215                         if (lptr-base >= lim-hptr) {
4216                                 glob1(hptr+v2, lim);
4217                                 lim = lptr;
4218                         } else {
4219                                 glob1(base, lptr);
4220                                 base = hptr+v2;
4221                         }
4222                         goto top;
4223                 }
4224
4225
4226                 glob3(j, lptr -= v2, i);
4227                 j = hptr -= v2;
4228         }
4229 }
4230
4231 static void
4232 glob2(i, j)
4233 char *i, *j;
4234 {
4235         register char *index1, *index2, c;
4236         int m;
4237
4238         m = globv;
4239         index1 = i;
4240         index2 = j;
4241         do {
4242                 c = *index1;
4243                 *index1++ = *index2;
4244                 *index2++ = c;
4245         } while(--m);
4246 }
4247
4248 static void
4249 glob3(i, j, k)
4250 char *i, *j, *k;
4251 {
4252         register char *index1, *index2, *index3;
4253         int c;
4254         int m;
4255
4256         m = globv;
4257         index1 = i;
4258         index2 = j;
4259         index3 = k;
4260         do {
4261                 c = *index1;
4262                 *index1++ = *index3;
4263                 *index3++ = *index2;
4264                 *index2++ = c;
4265         } while(--m);
4266 }
4267
4268 /* -------- io.c -------- */
4269
4270 /*
4271  * shell IO
4272  */
4273
4274 static int my_getc( int ec)
4275 {
4276         register int c;
4277
4278         if(e.linep > elinep) {
4279                 while((c=readc()) != '\n' && c)
4280                         ;
4281                 err("input line too long");
4282                 gflg++;
4283                 return(c);
4284         }
4285         c = readc();
4286         if ((ec != '\'') && (ec != '`') && (e.iop->task != XGRAVE)) {
4287                 if(c == '\\') {
4288                         c = readc();
4289                         if (c == '\n' && ec != '\"')
4290                                 return(my_getc(ec));
4291                         c |= QUOTE;
4292                 }
4293         }
4294         return(c);
4295 }
4296
4297 static void
4298 unget(c)
4299 int c;
4300 {
4301         if (e.iop >= e.iobase)
4302                 e.iop->peekc = c;
4303 }
4304
4305 static int
4306 eofc()
4307
4308 {
4309   return e.iop < e.iobase || (e.iop->peekc == 0 && e.iop->prev == 0);
4310 }
4311
4312 static int
4313 readc()
4314 {
4315         register int c;
4316
4317         for (; e.iop >= e.iobase; e.iop--)
4318                 if ((c = e.iop->peekc) != '\0') {
4319                         e.iop->peekc = 0;
4320                         return(c);
4321                 }
4322                 else {
4323                     if (e.iop->prev != 0) {
4324                         if ((c = (*e.iop->iofn)(e.iop->argp, e.iop)) != '\0') {
4325                                 if (c == -1) {
4326                                         e.iop++;
4327                                         continue;
4328                                 }
4329                                 if (e.iop == iostack)
4330                                         ioecho(c);
4331                                 return(e.iop->prev = c);
4332                         }
4333                         else if (e.iop->task == XIO && e.iop->prev != '\n') {
4334                                 e.iop->prev = 0;
4335                                 if (e.iop == iostack)
4336                                         ioecho('\n');
4337                                 return '\n';
4338                         }
4339                     }
4340                     if (e.iop->task == XIO) {
4341                         if (multiline)
4342                             return e.iop->prev = 0;
4343                         if (interactive && e.iop == iostack+1) {
4344 #ifdef CONFIG_FEATURE_COMMAND_EDITING
4345                             current_prompt=prompt->value;
4346 #else
4347                             prs(prompt->value);
4348 #endif
4349                         }
4350                     }
4351                 }
4352         if (e.iop >= iostack)
4353                 return(0);
4354         leave();
4355         /* NOTREACHED */
4356         return(0);
4357 }
4358
4359 static void
4360 ioecho(c)
4361 char c;
4362 {
4363         if (flag['v'])
4364                 write(2, &c, sizeof c);
4365 }
4366
4367 static void
4368 pushio(struct ioarg *argp, int (*fn)(struct ioarg *))
4369 {
4370         if (++e.iop >= &iostack[NPUSH]) {
4371                 e.iop--;
4372                 err("Shell input nested too deeply");
4373                 gflg++;
4374                 return;
4375         }
4376         e.iop->iofn = (int (*)(struct  ioarg *, struct io *))fn;
4377
4378         if (argp->afid != AFID_NOBUF)
4379           e.iop->argp = argp;
4380         else {
4381           e.iop->argp  = ioargstack + (e.iop - iostack);
4382           *e.iop->argp = *argp;
4383           e.iop->argp->afbuf = e.iop == &iostack[0] ? &mainbuf : &sharedbuf;
4384           if (isatty(e.iop->argp->afile) == 0 &&
4385               (e.iop == &iostack[0] ||
4386                lseek(e.iop->argp->afile, 0L, 1) != -1)) {
4387             if (++bufid == AFID_NOBUF)
4388               bufid = AFID_ID;
4389             e.iop->argp->afid  = bufid;
4390           }
4391         }
4392
4393         e.iop->prev  = ~'\n';
4394         e.iop->peekc = 0;
4395         e.iop->xchar = 0;
4396         e.iop->nlcount = 0;
4397         if (fn == filechar || fn == linechar)
4398                 e.iop->task = XIO;
4399         else if (fn == (int(*)(struct ioarg *))gravechar || fn == (int(*)(struct ioarg *))qgravechar)
4400                 e.iop->task = XGRAVE;
4401         else
4402                 e.iop->task = XOTHER;
4403 }
4404
4405 static struct io *
4406 setbase(ip)
4407 struct io *ip;
4408 {
4409         register struct io *xp;
4410
4411         xp = e.iobase;
4412         e.iobase = ip;
4413         return(xp);
4414 }
4415
4416 /*
4417  * Input generating functions
4418  */
4419
4420 /*
4421  * Produce the characters of a string, then a newline, then EOF.
4422  */
4423 static int
4424 nlchar(ap)
4425 register struct ioarg *ap;
4426 {
4427         register int c;
4428
4429         if (ap->aword == NULL)
4430                 return(0);
4431         if ((c = *ap->aword++) == 0) {
4432                 ap->aword = NULL;
4433                 return('\n');
4434         }
4435         return(c);
4436 }
4437
4438 /*
4439  * Given a list of words, produce the characters
4440  * in them, with a space after each word.
4441  */
4442 static int
4443 wdchar(ap)
4444 register struct ioarg *ap;
4445 {
4446         register char c;
4447         register char **wl;
4448
4449         if ((wl = ap->awordlist) == NULL)
4450                 return(0);
4451         if (*wl != NULL) {
4452                 if ((c = *(*wl)++) != 0)
4453                         return(c & 0177);
4454                 ap->awordlist++;
4455                 return(' ');
4456         }
4457         ap->awordlist = NULL;
4458         return('\n');
4459 }
4460
4461 /*
4462  * Return the characters of a list of words,
4463  * producing a space between them.
4464  */
4465 static int
4466 dolchar(ap)
4467 register struct ioarg *ap;
4468 {
4469         register char *wp;
4470
4471         if ((wp = *ap->awordlist++) != NULL) {
4472                 PUSHIO(aword, wp, *ap->awordlist == NULL? strchar: xxchar);
4473                 return(-1);
4474         }
4475         return(0);
4476 }
4477
4478 static int
4479 xxchar(ap)
4480 register struct ioarg *ap;
4481 {
4482         register int c;
4483
4484         if (ap->aword == NULL)
4485                 return(0);
4486         if ((c = *ap->aword++) == '\0') {
4487                 ap->aword = NULL;
4488                 return(' ');
4489         }
4490         return(c);
4491 }
4492
4493 /*
4494  * Produce the characters from a single word (string).
4495  */
4496 static int
4497 strchar(ap)
4498 register struct ioarg *ap;
4499 {
4500         register int c;
4501
4502         if (ap->aword == NULL || (c = *ap->aword++) == 0)
4503                 return(0);
4504         return(c);
4505 }
4506
4507 /*
4508  * Produce quoted characters from a single word (string).
4509  */
4510 static int
4511 qstrchar(ap)
4512 register struct ioarg *ap;
4513 {
4514         register int c;
4515
4516         if (ap->aword == NULL || (c = *ap->aword++) == 0)
4517                 return(0);
4518         return(c|QUOTE);
4519 }
4520
4521 /*
4522  * Return the characters from a file.
4523  */
4524 static int
4525 filechar(ap)
4526 register struct ioarg *ap;
4527 {
4528         register int i;
4529         char c;
4530         struct iobuf *bp = ap->afbuf;
4531
4532         if (ap->afid != AFID_NOBUF) {
4533           if ((i = ap->afid != bp->id) || bp->bufp == bp->ebufp) {
4534             if (i)
4535               lseek(ap->afile, ap->afpos, 0);
4536             i = safe_read(ap->afile, bp->buf, sizeof(bp->buf));
4537             if (i <= 0) {
4538               closef(ap->afile);
4539               return 0;
4540             }
4541             bp->id = ap->afid;
4542             bp->ebufp = (bp->bufp  = bp->buf) + i;
4543           }
4544           ap->afpos++;
4545           return *bp->bufp++ & 0177;
4546         }
4547
4548 #ifdef CONFIG_FEATURE_COMMAND_EDITING
4549         if (interactive && isatty(ap->afile)) {
4550             static char mycommand[BUFSIZ];
4551             static int position = 0, size = 0;
4552
4553             while (size == 0 || position >= size) {
4554                 cmdedit_read_input(current_prompt, mycommand);
4555                 size = strlen(mycommand);
4556                 position = 0;
4557             }
4558             c = mycommand[position];
4559             position++;
4560             return(c);
4561         } else 
4562 #endif
4563         {
4564                 i = safe_read(ap->afile, &c, sizeof(c));
4565                 return(i == sizeof(c)? c&0177: (closef(ap->afile), 0));
4566         }
4567 }
4568
4569 /*
4570  * Return the characters from a here temp file.
4571  */
4572 static int
4573 herechar(ap)
4574 register struct ioarg *ap;
4575 {
4576         char c;
4577
4578
4579         if (read(ap->afile, &c, sizeof(c)) != sizeof(c)) {
4580                 close(ap->afile);
4581                 c = 0;
4582         }
4583         return (c);
4584
4585 }
4586
4587 /*
4588  * Return the characters produced by a process (`...`).
4589  * Quote them if required, and remove any trailing newline characters.
4590  */
4591 static int
4592 gravechar(ap, iop)
4593 struct ioarg *ap;
4594 struct io *iop;
4595 {
4596         register int c;
4597
4598         if ((c = qgravechar(ap, iop)&~QUOTE) == '\n')
4599                 c = ' ';
4600         return(c);
4601 }
4602
4603 static int
4604 qgravechar(ap, iop)
4605 register struct ioarg *ap;
4606 struct io *iop;
4607 {
4608         register int c;
4609
4610         if (iop->xchar) {
4611                 if (iop->nlcount) {
4612                         iop->nlcount--;
4613                         return('\n'|QUOTE);
4614                 }
4615                 c = iop->xchar;
4616                 iop->xchar = 0;
4617         } else if ((c = filechar(ap)) == '\n') {
4618                 iop->nlcount = 1;
4619                 while ((c = filechar(ap)) == '\n')
4620                         iop->nlcount++;
4621                 iop->xchar = c;
4622                 if (c == 0)
4623                         return(c);
4624                 iop->nlcount--;
4625                 c = '\n';
4626         }
4627         return(c!=0? c|QUOTE: 0);
4628 }
4629
4630 /*
4631  * Return a single command (usually the first line) from a file.
4632  */
4633 static int
4634 linechar(ap)
4635 register struct ioarg *ap;
4636 {
4637         register int c;
4638
4639         if ((c = filechar(ap)) == '\n') {
4640                 if (!multiline) {
4641                         closef(ap->afile);
4642                         ap->afile = -1; /* illegal value */
4643                 }
4644         }
4645         return(c);
4646 }
4647
4648 static void
4649 prs(s)
4650 register char *s;
4651 {
4652         if (*s)
4653                 write(2, s, strlen(s));
4654 }
4655
4656 static void
4657 prn(u)
4658 unsigned u;
4659 {
4660         prs(itoa(u));
4661 }
4662
4663 static void
4664 closef(i)
4665 register int i;
4666 {
4667         if (i > 2)
4668                 close(i);
4669 }
4670
4671 static void
4672 closeall()
4673 {
4674         register int u;
4675
4676         for (u=NUFILE; u<NOFILE;)
4677                 close(u++);
4678 }
4679
4680 /*
4681  * remap fd into Shell's fd space
4682  */
4683 static int
4684 remap(fd)
4685 register int fd;
4686 {
4687         register int i;
4688         int map[NOFILE];
4689
4690         if (fd < e.iofd) {
4691                 for (i=0; i<NOFILE; i++)
4692                         map[i] = 0;
4693                 do {
4694                         map[fd] = 1;
4695                         fd = dup(fd);
4696                 } while (fd >= 0 && fd < e.iofd);
4697                 for (i=0; i<NOFILE; i++)
4698                         if (map[i])
4699                                 close(i);
4700                 if (fd < 0)
4701                         err("too many files open in shell");
4702         }
4703         return(fd);
4704 }
4705
4706 static int
4707 openpipe(pv)
4708 register int *pv;
4709 {
4710         register int i;
4711
4712         if ((i = pipe(pv)) < 0)
4713                 err("can't create pipe - try again");
4714         return(i);
4715 }
4716
4717 static void
4718 closepipe(pv)
4719 register int *pv;
4720 {
4721         if (pv != NULL) {
4722                 close(*pv++);
4723                 close(*pv);
4724         }
4725 }
4726
4727 /* -------- here.c -------- */
4728
4729 /*
4730  * here documents
4731  */
4732
4733 static void
4734 markhere(s, iop)
4735 register char *s;
4736 struct ioword *iop;
4737 {
4738         register struct here *h, *lh;
4739
4740         h = (struct here *) space(sizeof(struct here));
4741         if (h == 0)
4742                 return;
4743         h->h_tag = evalstr(s, DOSUB);
4744         if (h->h_tag == 0)
4745                 return;
4746         h->h_iop = iop;
4747         iop->io_name = 0;
4748         h->h_next = NULL;
4749         if (inhere == 0)
4750                 inhere = h;
4751         else
4752                 for (lh = inhere; lh!=NULL; lh = lh->h_next)
4753                         if (lh->h_next == 0) {
4754                                 lh->h_next = h;
4755                                 break;
4756                         }
4757         iop->io_flag |= IOHERE|IOXHERE;
4758         for (s = h->h_tag; *s; s++)
4759                 if (*s & QUOTE) {
4760                         iop->io_flag &= ~ IOXHERE;
4761                         *s &= ~ QUOTE;
4762                 }
4763         h->h_dosub = iop->io_flag & IOXHERE;
4764 }
4765
4766 static void
4767 gethere()
4768 {
4769         register struct here *h, *hp;
4770
4771         /* Scan here files first leaving inhere list in place */
4772         for (hp = h = inhere; h != NULL; hp = h, h = h->h_next)
4773           readhere(&h->h_iop->io_name, h->h_tag, h->h_dosub? 0: '\'');
4774
4775         /* Make inhere list active - keep list intact for scraphere */
4776         if (hp != NULL) {
4777           hp->h_next = acthere;
4778           acthere    = inhere;
4779           inhere     = NULL;
4780         }
4781 }
4782
4783 static void
4784 readhere(name, s, ec)
4785 char **name;
4786 register char *s;
4787 int ec;
4788 {
4789         int tf;
4790         char tname[30] = ".msh_XXXXXX";
4791         register int c;
4792         jmp_buf ev;
4793         char myline [LINELIM+1];
4794         char *thenext;
4795
4796         tf = mkstemp(tname);
4797         if (tf < 0)
4798                 return;
4799         *name = strsave(tname, areanum);
4800         if (newenv(setjmp(errpt = ev)) != 0)
4801                 unlink(tname);
4802         else {
4803                 pushio(e.iop->argp, (int(*)(struct ioarg *))e.iop->iofn);
4804                 e.iobase = e.iop;
4805                 for (;;) {
4806                     if (interactive && e.iop <= iostack) {
4807 #ifdef CONFIG_FEATURE_COMMAND_EDITING
4808                             current_prompt=cprompt->value;
4809 #else
4810                             prs(cprompt->value);
4811 #endif
4812                         }
4813                         thenext = myline;
4814                         while ((c = my_getc(ec)) != '\n' && c) {
4815                                 if (ec == '\'')
4816                                         c &= ~ QUOTE;
4817                                 if (thenext >= &myline[LINELIM]) {
4818                                         c = 0;
4819                                         break;
4820                                 }
4821                                 *thenext++ = c;
4822                         }
4823                         *thenext = 0;
4824                         if (strcmp(s, myline) == 0 || c == 0)
4825                                 break;
4826                         *thenext++ = '\n';
4827                         write (tf, myline, (int)(thenext-myline));
4828                 }
4829                 if (c == 0) {
4830                         prs("here document `"); prs(s); err("' unclosed");
4831                 }
4832                 quitenv();
4833         }
4834         close(tf);
4835 }
4836
4837 /*
4838  * open here temp file.
4839  * if unquoted here, expand here temp file into second temp file.
4840  */
4841 static int
4842 herein(hname, xdoll)
4843 char *hname;
4844 int xdoll;
4845 {
4846         register int hf;
4847         int tf;
4848
4849 #if __GNUC__
4850         /* Avoid longjmp clobbering */
4851         (void) &tf;
4852 #endif
4853         if (hname == 0)
4854                 return(-1);
4855         hf = open(hname, 0);
4856         if (hf < 0)
4857                 return (-1);
4858         if (xdoll) {
4859                 char c;
4860                 char tname[30] = ".msh_XXXXXX";
4861                 jmp_buf ev;
4862         
4863                 tf = mkstemp(tname);
4864                 if (tf < 0)
4865                         return (-1);
4866                 if (newenv(setjmp(errpt = ev)) == 0) {
4867                         PUSHIO(afile, hf, herechar);
4868                         setbase(e.iop);
4869                         while ((c = subgetc(0, 0)) != 0) {
4870                                 c &= ~ QUOTE;
4871                                 write(tf, &c, sizeof c);
4872                         }
4873                         quitenv();
4874                 } else
4875                         unlink(tname);
4876                 close(tf);
4877                 tf = open(tname, 0);
4878                 unlink(tname);
4879                 return (tf);
4880         } else
4881                 return (hf);
4882 }
4883
4884 static void
4885 scraphere()
4886 {
4887         register struct here *h;
4888
4889         for (h = inhere; h != NULL; h = h->h_next) {
4890                 if (h->h_iop && h->h_iop->io_name)
4891                   unlink(h->h_iop->io_name);
4892         }
4893         inhere = NULL;
4894 }
4895
4896 /* unlink here temp files before a freearea(area) */
4897 static void
4898 freehere(area)
4899 int area;
4900 {
4901         register struct here *h, *hl;
4902
4903         hl = NULL;
4904         for (h = acthere; h != NULL; h = h->h_next)
4905                 if (getarea((char *) h) >= area) {
4906                         if (h->h_iop->io_name != NULL)
4907                                 unlink(h->h_iop->io_name);
4908                         if (hl == NULL)
4909                                 acthere = h->h_next;
4910                         else
4911                                 hl->h_next = h->h_next;
4912                 } else
4913                         hl = h;
4914 }
4915
4916
4917
4918 /*
4919  * Copyright (c) 1987,1997, Prentice Hall
4920  * All rights reserved.
4921  * 
4922  * Redistribution and use of the MINIX operating system in source and
4923  * binary forms, with or without modification, are permitted provided
4924  * that the following conditions are met:
4925  * 
4926  * Redistributions of source code must retain the above copyright
4927  * notice, this list of conditions and the following disclaimer.
4928  * 
4929  * Redistributions in binary form must reproduce the above
4930  * copyright notice, this list of conditions and the following
4931  * disclaimer in the documentation and/or other materials provided
4932  * with the distribution.
4933  * 
4934  * Neither the name of Prentice Hall nor the names of the software
4935  * authors or contributors may be used to endorse or promote
4936  * products derived from this software without specific prior
4937  * written permission.
4938  * 
4939  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS, AUTHORS, AND
4940  * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
4941  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
4942  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
4943  * IN NO EVENT SHALL PRENTICE HALL OR ANY AUTHORS OR CONTRIBUTORS BE
4944  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
4945  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
4946  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
4947  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
4948  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
4949  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
4950  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
4951  *
4952  */
4953