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