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