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