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