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