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