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