15ec043808e9e9ca2af2f5230ad100d62b77218f
[oweals/busybox.git] / shell / ash.c
1 /* vi: set sw=4 ts=4: */
2 /*
3  * ash shell port for busybox
4  *
5  * Copyright (c) 1989, 1991, 1993, 1994
6  *      The Regents of the University of California.  All rights reserved.
7  *
8  * This code is derived from software contributed to Berkeley by
9  * Kenneth Almquist.
10  *
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2 of the License, or
14  * (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19  * General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24  *
25  * This version of ash is adapted from the source in Debian's ash 0.3.8-5
26  * package.
27  *
28  * Modified by Erik Andersen <andersee@debian.org> and
29  * Vladimir Oleynik <dzo@simtreas.ru> to be used in busybox
30  *
31  *
32  * Original copyright notice is retained at the end of this file.
33  */
34
35
36 /* Enable this to compile in extra debugging noise.  When debugging is
37  * on, debugging info will be written to $HOME/trace and a quit signal
38  * will generate a core dump. */
39 #undef DEBUG
40
41 /* These are here to work with glibc -- Don't change these... */
42 #undef FNMATCH_BROKEN
43 #undef GLOB_BROKEN
44 #define IFS_BROKEN
45
46 #include <assert.h>
47 #include <stddef.h>
48 #include <ctype.h>
49 #include <dirent.h>
50 #include <errno.h>
51 #include <fcntl.h>
52 #include <limits.h>
53 #include <paths.h>
54 #include <setjmp.h>
55 #include <signal.h>
56 #include <stdarg.h>
57 #include <stdio.h>
58 #include <stdlib.h>
59 #include <string.h>
60 #include <sysexits.h>
61 #include <unistd.h>
62 #include <sys/stat.h>
63 #include <sys/cdefs.h>
64 #include <sys/ioctl.h>
65 #include <sys/param.h>
66 #include <sys/resource.h>
67 #include <sys/time.h>
68 #include <sys/times.h>
69 #include <sys/types.h>
70 #include <sys/wait.h>
71 #include "busybox.h"
72 #include "pwd_.h"
73
74
75 #if !defined(FNMATCH_BROKEN)
76 #include <fnmatch.h>
77 #endif
78 #if !defined(GLOB_BROKEN)
79 #include <glob.h>
80 #endif
81
82 #ifdef CONFIG_ASH_JOB_CONTROL
83 #include <termios.h>
84 #endif
85
86 #include "cmdedit.h"
87
88 /*
89  * This file was generated by the mksyntax program.
90  */
91
92 /* Syntax classes */
93 #define CWORD 0                 /* character is nothing special */
94 #define CNL 1                   /* newline character */
95 #define CBACK 2                 /* a backslash character */
96 #define CSQUOTE 3               /* single quote */
97 #define CDQUOTE 4               /* double quote */
98 #define CENDQUOTE 5             /* a terminating quote */
99 #define CBQUOTE 6               /* backwards single quote */
100 #define CVAR 7                  /* a dollar sign */
101 #define CENDVAR 8               /* a '}' character */
102 #define CLP 9                   /* a left paren in arithmetic */
103 #define CRP 10                  /* a right paren in arithmetic */
104 #define CENDFILE 11             /* end of file */
105 #define CCTL 12                 /* like CWORD, except it must be escaped */
106 #define CSPCL 13                /* these terminate a word */
107 #define CIGN 14                 /* character should be ignored */
108
109 #define SYNBASE 130
110 #define PEOF -130
111
112 #define PEOA -129
113
114 #define TEOF 0
115 #define TNL 1
116 #define TREDIR 2
117 #define TWORD 3
118 #define TASSIGN 4
119 #define TSEMI 5
120 #define TBACKGND 6
121 #define TAND 7
122 #define TOR 8
123 #define TPIPE 9
124 #define TLP 10
125 #define TRP 11
126 #define TENDCASE 12
127 #define TENDBQUOTE 13
128 #define TNOT 14
129 #define TCASE 15
130 #define TDO 16
131 #define TDONE 17
132 #define TELIF 18
133 #define TELSE 19
134 #define TESAC 20
135 #define TFI 21
136 #define TFOR 22
137 #define TIF 23
138 #define TIN 24
139 #define TTHEN 25
140 #define TUNTIL 26
141 #define TWHILE 27
142 #define TBEGIN 28
143 #define TEND 29
144
145
146
147 /* control characters in argument strings */
148 #define CTLESC '\201'
149 #define CTLVAR '\202'
150 #define CTLENDVAR '\203'
151 #define CTLBACKQ '\204'
152 #define CTLQUOTE 01             /* ored with CTLBACKQ code if in quotes */
153 /*      CTLBACKQ | CTLQUOTE == '\205' */
154 #define CTLARI  '\206'
155 #define CTLENDARI '\207'
156 #define CTLQUOTEMARK '\210'
157
158
159 #define is_digit(c)     ((c)>='0' && (c)<='9')
160 #define is_name(c)      (((c) < CTLESC || (c) > CTLENDARI) && ((c) == '_' || isalpha((unsigned char) (c))))
161 #define is_in_name(c)   (((c) < CTLESC || (c) > CTLENDARI) && ((c) == '_' || isalnum((unsigned char) (c))))
162
163 /*
164  * is_special(c) evaluates to 1 for c in "!#$*-0123456789?@"; 0 otherwise
165  * (assuming ascii char codes, as the original implementation did)
166  */
167 #define is_special(c) \
168     ( (((unsigned int)c) - 33 < 32) \
169                          && ((0xc1ff920dUL >> (((unsigned int)c) - 33)) & 1))
170
171 #define digit_val(c)    ((c) - '0')
172
173
174 #define S_DFL 1                 /* default signal handling (SIG_DFL) */
175 #define S_CATCH 2               /* signal is caught */
176 #define S_IGN 3                 /* signal is ignored (SIG_IGN) */
177 #define S_HARD_IGN 4    /* signal is ignored permenantly */
178 #define S_RESET 5               /* temporary - to reset a hard ignored sig */
179
180
181 /* variable substitution byte (follows CTLVAR) */
182 #define VSTYPE  0x0f    /* type of variable substitution */
183 #define VSNUL   0x10    /* colon--treat the empty string as unset */
184 #define VSQUOTE 0x80    /* inside double quotes--suppress splitting */
185
186 /* values of VSTYPE field */
187 #define VSNORMAL        0x1     /* normal variable:  $var or ${var} */
188 #define VSMINUS         0x2     /* ${var-text} */
189 #define VSPLUS          0x3     /* ${var+text} */
190 #define VSQUESTION      0x4     /* ${var?message} */
191 #define VSASSIGN        0x5     /* ${var=text} */
192 #define VSTRIMLEFT      0x6     /* ${var#pattern} */
193 #define VSTRIMLEFTMAX   0x7     /* ${var##pattern} */
194 #define VSTRIMRIGHT     0x8     /* ${var%pattern} */
195 #define VSTRIMRIGHTMAX  0x9     /* ${var%%pattern} */
196 #define VSLENGTH        0xa     /* ${#var} */
197
198 /* flags passed to redirect */
199 #define REDIR_PUSH 01   /* save previous values of file descriptors */
200 #define REDIR_BACKQ 02  /* save the command output to pipe */
201
202 /*
203  * BSD setjmp saves the signal mask, which violates ANSI C and takes time,
204  * so we use _setjmp instead.
205  */
206
207 #if defined(BSD)
208 #define setjmp(jmploc)  _setjmp(jmploc)
209 #define longjmp(jmploc, val)    _longjmp(jmploc, val)
210 #endif
211
212 /*
213  * Most machines require the value returned from malloc to be aligned
214  * in some way.  The following macro will get this right on many machines.
215  */
216
217 #ifndef ALIGN
218 union align {
219         int i;
220         char *cp;
221 };
222
223 #define ALIGN(nbytes)   (((nbytes) + sizeof(union align) - 1) & ~(sizeof(union align) - 1))
224 #endif
225
226 #ifdef CONFIG_LOCALE_SUPPORT
227 #include <locale.h>
228 static void change_lc_all(const char *value);
229 static void change_lc_ctype(const char *value);
230 #endif
231
232 /*
233  * These macros allow the user to suspend the handling of interrupt signals
234  * over a period of time.  This is similar to SIGHOLD to or sigblock, but
235  * much more efficient and portable.  (But hacking the kernel is so much
236  * more fun than worrying about efficiency and portability. :-))
237  */
238
239 static void onint(void);
240 static volatile int suppressint;
241 static volatile int intpending;
242
243 #define INTOFF suppressint++
244 #ifndef CONFIG_ASH_OPTIMIZE_FOR_SIZE
245 #define INTON { if (--suppressint == 0 && intpending) onint(); }
246 #define FORCEINTON {suppressint = 0; if (intpending) onint();}
247 #else
248 static void __inton(void);
249 static void forceinton(void);
250
251 #define INTON __inton()
252 #define FORCEINTON forceinton()
253 #endif
254
255 #define CLEAR_PENDING_INT intpending = 0
256 #define int_pending() intpending
257
258
259 typedef void *pointer;
260
261 #ifndef NULL
262 #define NULL (void *)0
263 #endif
264
265 static pointer stalloc(int);
266 static void stunalloc(pointer);
267 static void ungrabstackstr(char *, char *);
268 static char *growstackstr(void);
269 static char *makestrspace(size_t newlen);
270 static char *sstrdup(const char *);
271
272 /*
273  * Parse trees for commands are allocated in lifo order, so we use a stack
274  * to make this more efficient, and also to avoid all sorts of exception
275  * handling code to handle interrupts in the middle of a parse.
276  *
277  * The size 504 was chosen because the Ultrix malloc handles that size
278  * well.
279  */
280
281 #define MINSIZE 504             /* minimum size of a block */
282
283
284 struct stack_block {
285         struct stack_block *prev;
286         char space[MINSIZE];
287 };
288
289 static struct stack_block stackbase;
290 static struct stack_block *stackp = &stackbase;
291 static struct stackmark *markp;
292 static char *stacknxt = stackbase.space;
293 static int stacknleft = MINSIZE;
294
295
296 #define equal(s1, s2)   (strcmp(s1, s2) == 0)
297
298 #define stackblock() stacknxt
299 #define stackblocksize() stacknleft
300 #define STARTSTACKSTR(p)        p = stackblock(), sstrnleft = stackblocksize()
301
302 #define STPUTC(c, p)    (--sstrnleft >= 0? (*p++ = (c)) : (p = growstackstr(), *p++ = (c)))
303 #define CHECKSTRSPACE(n, p)     { if (sstrnleft < n) p = makestrspace(n); }
304 #define STACKSTRNUL(p)  (sstrnleft == 0? (p = growstackstr(), *p = '\0') : (*p = '\0'))
305
306
307 #define USTPUTC(c, p)   (--sstrnleft, *p++ = (c))
308 #define STUNPUTC(p)     (++sstrnleft, --p)
309 #define STTOPC(p)       p[-1]
310 #define STADJUST(amount, p)     (p += (amount), sstrnleft -= (amount))
311 #define grabstackstr(p) stalloc(stackblocksize() - sstrnleft)
312
313
314
315 #ifdef DEBUG
316 #define TRACE(param)    trace param
317 typedef union node unode;
318 static void trace(const char *, ...);
319 static void trargs(char **);
320 static void showtree(unode *);
321 static void trputc(int);
322 static void trputs(const char *);
323 static void opentrace(void);
324 #else
325 #define TRACE(param)
326 #endif
327
328 #define NSEMI 0
329 #define NCMD 1
330 #define NPIPE 2
331 #define NREDIR 3
332 #define NBACKGND 4
333 #define NSUBSHELL 5
334 #define NAND 6
335 #define NOR 7
336 #define NIF 8
337 #define NWHILE 9
338 #define NUNTIL 10
339 #define NFOR 11
340 #define NCASE 12
341 #define NCLIST 13
342 #define NDEFUN 14
343 #define NARG 15
344 #define NTO 16
345 #define NFROM 17
346 #define NFROMTO 18
347 #define NAPPEND 19
348 #define NTOOV 20
349 #define NTOFD 21
350 #define NFROMFD 22
351 #define NHERE 23
352 #define NXHERE 24
353 #define NNOT 25
354
355 /*
356  * expandarg() flags
357  */
358 #define EXP_FULL        0x1     /* perform word splitting & file globbing */
359 #define EXP_TILDE       0x2     /* do normal tilde expansion */
360 #define EXP_VARTILDE    0x4     /* expand tildes in an assignment */
361 #define EXP_REDIR       0x8     /* file glob for a redirection (1 match only) */
362 #define EXP_CASE        0x10    /* keeps quotes around for CASE pattern */
363 #define EXP_RECORD      0x20    /* need to record arguments for ifs breakup */
364
365
366 #define NOPTS   16
367
368 static char optet_vals[NOPTS];
369
370 static const char *const optlist[NOPTS] = {
371         "e" "errexit",
372         "f" "noglob",
373         "I" "ignoreeof",
374         "i" "interactive",
375         "m" "monitor",
376         "n" "noexec",
377         "s" "stdin",
378         "x" "xtrace",
379         "v" "verbose",
380         "V" "vi",
381         "E" "emacs",
382         "C" "noclobber",
383         "a" "allexport",
384         "b" "notify",
385         "u" "nounset",
386         "q" "quietprofile"
387 };
388
389 #define optent_name(optent) (optent+1)
390 #define optent_letter(optent) optent[0]
391 #define optent_val(optent) optet_vals[optent]
392
393 #define eflag optent_val(0)
394 #define fflag optent_val(1)
395 #define Iflag optent_val(2)
396 #define iflag optent_val(3)
397 #define mflag optent_val(4)
398 #define nflag optent_val(5)
399 #define sflag optent_val(6)
400 #define xflag optent_val(7)
401 #define vflag optent_val(8)
402 #define Vflag optent_val(9)
403 #define Eflag optent_val(10)
404 #define Cflag optent_val(11)
405 #define aflag optent_val(12)
406 #define bflag optent_val(13)
407 #define uflag optent_val(14)
408 #define qflag optent_val(15)
409
410
411 /* Mode argument to forkshell.  Don't change FORK_FG or FORK_BG. */
412 #define FORK_FG 0
413 #define FORK_BG 1
414 #define FORK_NOJOB 2
415
416
417 struct nbinary {
418         int type;
419         union node *ch1;
420         union node *ch2;
421 };
422
423
424 struct ncmd {
425         int type;
426         int backgnd;
427         union node *assign;
428         union node *args;
429         union node *redirect;
430 };
431
432
433 struct npipe {
434         int type;
435         int backgnd;
436         struct nodelist *cmdlist;
437 };
438
439
440 struct nredir {
441         int type;
442         union node *n;
443         union node *redirect;
444 };
445
446
447 struct nif {
448         int type;
449         union node *test;
450         union node *ifpart;
451         union node *elsepart;
452 };
453
454
455 struct nfor {
456         int type;
457         union node *args;
458         union node *body;
459         char *var;
460 };
461
462
463 struct ncase {
464         int type;
465         union node *expr;
466         union node *cases;
467 };
468
469
470 struct nclist {
471         int type;
472         union node *next;
473         union node *pattern;
474         union node *body;
475 };
476
477
478 struct narg {
479         int type;
480         union node *next;
481         char *text;
482         struct nodelist *backquote;
483 };
484
485
486 struct nfile {
487         int type;
488         union node *next;
489         int fd;
490         union node *fname;
491         char *expfname;
492 };
493
494
495 struct ndup {
496         int type;
497         union node *next;
498         int fd;
499         int dupfd;
500         union node *vname;
501 };
502
503
504 struct nhere {
505         int type;
506         union node *next;
507         int fd;
508         union node *doc;
509 };
510
511
512 struct nnot {
513         int type;
514         union node *com;
515 };
516
517
518 union node {
519         int type;
520         struct nbinary nbinary;
521         struct ncmd ncmd;
522         struct npipe npipe;
523         struct nredir nredir;
524         struct nif nif;
525         struct nfor nfor;
526         struct ncase ncase;
527         struct nclist nclist;
528         struct narg narg;
529         struct nfile nfile;
530         struct ndup ndup;
531         struct nhere nhere;
532         struct nnot nnot;
533 };
534
535
536 struct nodelist {
537         struct nodelist *next;
538         union node *n;
539 };
540
541 struct backcmd {                /* result of evalbackcmd */
542         int fd;                         /* file descriptor to read from */
543         char *buf;                      /* buffer */
544         int nleft;                      /* number of chars in buffer */
545         struct job *jp;         /* job structure for command */
546 };
547
548 struct cmdentry {
549         int cmdtype;
550         union param {
551                 int index;
552                 union node *func;
553                 const struct builtincmd *cmd;
554         } u;
555 };
556
557 struct strlist {
558         struct strlist *next;
559         char *text;
560 };
561
562
563 struct arglist {
564         struct strlist *list;
565         struct strlist **lastp;
566 };
567
568 struct strpush {
569         struct strpush *prev;   /* preceding string on stack */
570         char *prevstring;
571         int prevnleft;
572 #ifdef CONFIG_ASH_ALIAS
573         struct alias *ap;       /* if push was associated with an alias */
574 #endif
575         char *string;           /* remember the string since it may change */
576 };
577
578 struct parsefile {
579         struct parsefile *prev; /* preceding file on stack */
580         int linno;                      /* current line */
581         int fd;                         /* file descriptor (or -1 if string) */
582         int nleft;                      /* number of chars left in this line */
583         int lleft;                      /* number of chars left in this buffer */
584         char *nextc;            /* next char in buffer */
585         char *buf;                      /* input buffer */
586         struct strpush *strpush;        /* for pushing strings at this level */
587         struct strpush basestrpush;     /* so pushing one is fast */
588 };
589
590 struct stackmark {
591         struct stack_block *stackp;
592         char *stacknxt;
593         int stacknleft;
594         struct stackmark *marknext;
595 };
596
597 struct shparam {
598         int nparam;                     /* # of positional parameters (without $0) */
599         unsigned char malloc;   /* if parameter list dynamically allocated */
600         char **p;                       /* parameter list */
601         int optind;                     /* next parameter to be processed by getopts */
602         int optoff;                     /* used by getopts */
603 };
604
605 /*
606  * When commands are first encountered, they are entered in a hash table.
607  * This ensures that a full path search will not have to be done for them
608  * on each invocation.
609  *
610  * We should investigate converting to a linear search, even though that
611  * would make the command name "hash" a misnomer.
612  */
613 #define CMDTABLESIZE 31 /* should be prime */
614 #define ARB 1                   /* actual size determined at run time */
615
616
617
618 struct tblentry {
619         struct tblentry *next;  /* next entry in hash chain */
620         union param param;      /* definition of builtin function */
621         short cmdtype;          /* index identifying command */
622         char rehash;            /* if set, cd done since entry created */
623         char cmdname[ARB];      /* name of command */
624 };
625
626
627 static struct tblentry *cmdtable[CMDTABLESIZE];
628 static int builtinloc = -1;     /* index in path of %builtin, or -1 */
629 static int exerrno = 0; /* Last exec error */
630
631
632 static void tryexec(char *, char **, char **);
633 static void printentry(struct tblentry *, int);
634 static void clearcmdentry(int);
635 static struct tblentry *cmdlookup(const char *, int);
636 static void delete_cmd_entry(void);
637 static int path_change(const char *, int *);
638
639
640 static void flushall(void);
641 static void out2fmt(const char *, ...)
642         __attribute__ ((__format__(__printf__, 1, 2)));
643 static int xwrite(int, const char *, int);
644
645 static inline void outstr(const char *p, FILE * file)
646 {
647         fputs(p, file);
648 }
649 static void out1str(const char *p)
650 {
651         outstr(p, stdout);
652 }
653 static void out2str(const char *p)
654 {
655         outstr(p, stderr);
656 }
657
658 #ifndef CONFIG_ASH_OPTIMIZE_FOR_SIZE
659 #define out2c(c)        putc((c), stderr)
660 #else
661 static void out2c(int c)
662 {
663         putc(c, stderr);
664 }
665 #endif
666
667
668 #ifdef CONFIG_ASH_OPTIMIZE_FOR_SIZE
669 #define USE_SIT_FUNCTION
670 #endif
671
672 /* number syntax index */
673 #define  BASESYNTAX  0  /* not in quotes */
674 #define  DQSYNTAX    1  /* in double quotes */
675 #define  SQSYNTAX    2  /* in single quotes */
676 #define  ARISYNTAX   3  /* in arithmetic */
677
678 static const char S_I_T[][4] = {
679                                                                                 /*  0 */ {CSPCL, CIGN, CIGN, CIGN},
680                                                                                 /* PEOA */
681                                                                                         /*  1 */ {CSPCL, CWORD, CWORD, CWORD},
682                                                                                         /* ' ' */
683                                                                         /*  2 */ {CNL, CNL, CNL, CNL},
684                                                                         /* \n */
685                                                                                         /*  3 */ {CWORD, CCTL, CCTL, CWORD},
686                                                                                         /* !*-/:=?[]~ */
687                                                                                                         /*  4 */ {CDQUOTE, CENDQUOTE, CWORD, CDQUOTE},
688                                                                                                         /* '"' */
689                                                                                 /*  5 */ {CVAR, CVAR, CWORD, CVAR},
690                                                                                 /* $ */
691                                                                                                         /*  6 */ {CSQUOTE, CWORD, CENDQUOTE, CSQUOTE},
692                                                                                                         /* "'" */
693                                                                                         /*  7 */ {CSPCL, CWORD, CWORD, CLP},
694                                                                                         /* ( */
695                                                                                         /*  8 */ {CSPCL, CWORD, CWORD, CRP},
696                                                                                         /* ) */
697                                                                                         /*  9 */ {CBACK, CBACK, CCTL, CBACK},
698                                                                                         /* \ */
699                                                                                                         /* 10 */ {CBQUOTE, CBQUOTE, CWORD, CBQUOTE},
700                                                                                                         /* ` */
701                                                                                                         /* 11 */ {CENDVAR, CENDVAR, CWORD, CENDVAR},
702                                                                                                         /* } */
703 #ifndef USE_SIT_FUNCTION
704                                                                                                                 /* 12 */ {CENDFILE, CENDFILE, CENDFILE, CENDFILE},
705                                                                                                                 /* PEOF */
706                                                                                         /* 13 */ {CWORD, CWORD, CWORD, CWORD},
707                                                                                         /* 0-9A-Za-z */
708                                                                                 /* 14 */ {CCTL, CCTL, CCTL, CCTL}
709                                                                                 /* CTLESC ... */
710 #endif
711 };
712
713 #ifdef USE_SIT_FUNCTION
714
715 #define U_C(c) ((unsigned char)(c))
716
717 static int SIT(int c, int syntax)
718 {
719         static const char spec_symbls[] = "\t\n !\"$&'()*-/:;<=>?[\\]`|}~";
720         static const char syntax_index_table[] = {
721                 1, 2, 1, 3, 4, 5, 1, 6, /* "\t\n !\"$&'" */
722                 7, 8, 3, 3, 3, 3, 1, 1, /* "()*-/:;<" */
723                 3, 1, 3, 3, 9, 3, 10, 1,        /* "=>?[\\]`|" */
724                 11, 3
725         };                                      /* "}~" */
726         const char *s;
727         int indx;
728
729         if (c == PEOF)          /* 2^8+2 */
730                 return CENDFILE;
731         if (c == PEOA)          /* 2^8+1 */
732                 indx = 0;
733         else if (U_C(c) >= U_C(CTLESC) && U_C(c) <= U_C(CTLQUOTEMARK))
734                 return CCTL;
735         else {
736                 s = strchr(spec_symbls, c);
737                 if (s == 0)
738                         return CWORD;
739                 indx = syntax_index_table[(s - spec_symbls)];
740         }
741         return S_I_T[indx][syntax];
742 }
743
744 #else                                                   /* USE_SIT_FUNCTION */
745
746 #define SIT(c, syntax) S_I_T[(int)syntax_index_table[((int)c)+SYNBASE]][syntax]
747
748 #define CSPCL_CIGN_CIGN_CIGN                           0
749 #define CSPCL_CWORD_CWORD_CWORD                        1
750 #define CNL_CNL_CNL_CNL                                2
751 #define CWORD_CCTL_CCTL_CWORD                          3
752 #define CDQUOTE_CENDQUOTE_CWORD_CDQUOTE                4
753 #define CVAR_CVAR_CWORD_CVAR                           5
754 #define CSQUOTE_CWORD_CENDQUOTE_CSQUOTE                6
755 #define CSPCL_CWORD_CWORD_CLP                          7
756 #define CSPCL_CWORD_CWORD_CRP                          8
757 #define CBACK_CBACK_CCTL_CBACK                         9
758 #define CBQUOTE_CBQUOTE_CWORD_CBQUOTE                 10
759 #define CENDVAR_CENDVAR_CWORD_CENDVAR                 11
760 #define CENDFILE_CENDFILE_CENDFILE_CENDFILE           12
761 #define CWORD_CWORD_CWORD_CWORD                       13
762 #define CCTL_CCTL_CCTL_CCTL                           14
763
764 static const char syntax_index_table[258] = {
765         /* BASESYNTAX_DQSYNTAX_SQSYNTAX_ARISYNTAX */
766         /*   0  -130 PEOF */ CENDFILE_CENDFILE_CENDFILE_CENDFILE,
767         /*   1  -129 PEOA */ CSPCL_CIGN_CIGN_CIGN,
768         /*   2  -128 0xff */ CWORD_CWORD_CWORD_CWORD,
769                                                                                                 /*   3  -127      */ CCTL_CCTL_CCTL_CCTL,
770                                                                                                 /* CTLQUOTEMARK */
771         /*   4  -126      */ CCTL_CCTL_CCTL_CCTL,
772         /*   5  -125      */ CCTL_CCTL_CCTL_CCTL,
773         /*   6  -124      */ CCTL_CCTL_CCTL_CCTL,
774         /*   7  -123      */ CCTL_CCTL_CCTL_CCTL,
775         /*   8  -122      */ CCTL_CCTL_CCTL_CCTL,
776         /*   9  -121      */ CCTL_CCTL_CCTL_CCTL,
777                                                                                                 /*  10  -120      */ CCTL_CCTL_CCTL_CCTL,
778                                                                                                 /* CTLESC */
779         /*  11  -119      */ CWORD_CWORD_CWORD_CWORD,
780         /*  12  -118      */ CWORD_CWORD_CWORD_CWORD,
781         /*  13  -117      */ CWORD_CWORD_CWORD_CWORD,
782         /*  14  -116      */ CWORD_CWORD_CWORD_CWORD,
783         /*  15  -115      */ CWORD_CWORD_CWORD_CWORD,
784         /*  16  -114      */ CWORD_CWORD_CWORD_CWORD,
785         /*  17  -113      */ CWORD_CWORD_CWORD_CWORD,
786         /*  18  -112      */ CWORD_CWORD_CWORD_CWORD,
787         /*  19  -111      */ CWORD_CWORD_CWORD_CWORD,
788         /*  20  -110      */ CWORD_CWORD_CWORD_CWORD,
789         /*  21  -109      */ CWORD_CWORD_CWORD_CWORD,
790         /*  22  -108      */ CWORD_CWORD_CWORD_CWORD,
791         /*  23  -107      */ CWORD_CWORD_CWORD_CWORD,
792         /*  24  -106      */ CWORD_CWORD_CWORD_CWORD,
793         /*  25  -105      */ CWORD_CWORD_CWORD_CWORD,
794         /*  26  -104      */ CWORD_CWORD_CWORD_CWORD,
795         /*  27  -103      */ CWORD_CWORD_CWORD_CWORD,
796         /*  28  -102      */ CWORD_CWORD_CWORD_CWORD,
797         /*  29  -101      */ CWORD_CWORD_CWORD_CWORD,
798         /*  30  -100      */ CWORD_CWORD_CWORD_CWORD,
799         /*  31   -99      */ CWORD_CWORD_CWORD_CWORD,
800         /*  32   -98      */ CWORD_CWORD_CWORD_CWORD,
801         /*  33   -97      */ CWORD_CWORD_CWORD_CWORD,
802         /*  34   -96      */ CWORD_CWORD_CWORD_CWORD,
803         /*  35   -95      */ CWORD_CWORD_CWORD_CWORD,
804         /*  36   -94      */ CWORD_CWORD_CWORD_CWORD,
805         /*  37   -93      */ CWORD_CWORD_CWORD_CWORD,
806         /*  38   -92      */ CWORD_CWORD_CWORD_CWORD,
807         /*  39   -91      */ CWORD_CWORD_CWORD_CWORD,
808         /*  40   -90      */ CWORD_CWORD_CWORD_CWORD,
809         /*  41   -89      */ CWORD_CWORD_CWORD_CWORD,
810         /*  42   -88      */ CWORD_CWORD_CWORD_CWORD,
811         /*  43   -87      */ CWORD_CWORD_CWORD_CWORD,
812         /*  44   -86      */ CWORD_CWORD_CWORD_CWORD,
813         /*  45   -85      */ CWORD_CWORD_CWORD_CWORD,
814         /*  46   -84      */ CWORD_CWORD_CWORD_CWORD,
815         /*  47   -83      */ CWORD_CWORD_CWORD_CWORD,
816         /*  48   -82      */ CWORD_CWORD_CWORD_CWORD,
817         /*  49   -81      */ CWORD_CWORD_CWORD_CWORD,
818         /*  50   -80      */ CWORD_CWORD_CWORD_CWORD,
819         /*  51   -79      */ CWORD_CWORD_CWORD_CWORD,
820         /*  52   -78      */ CWORD_CWORD_CWORD_CWORD,
821         /*  53   -77      */ CWORD_CWORD_CWORD_CWORD,
822         /*  54   -76      */ CWORD_CWORD_CWORD_CWORD,
823         /*  55   -75      */ CWORD_CWORD_CWORD_CWORD,
824         /*  56   -74      */ CWORD_CWORD_CWORD_CWORD,
825         /*  57   -73      */ CWORD_CWORD_CWORD_CWORD,
826         /*  58   -72      */ CWORD_CWORD_CWORD_CWORD,
827         /*  59   -71      */ CWORD_CWORD_CWORD_CWORD,
828         /*  60   -70      */ CWORD_CWORD_CWORD_CWORD,
829         /*  61   -69      */ CWORD_CWORD_CWORD_CWORD,
830         /*  62   -68      */ CWORD_CWORD_CWORD_CWORD,
831         /*  63   -67      */ CWORD_CWORD_CWORD_CWORD,
832         /*  64   -66      */ CWORD_CWORD_CWORD_CWORD,
833         /*  65   -65      */ CWORD_CWORD_CWORD_CWORD,
834         /*  66   -64      */ CWORD_CWORD_CWORD_CWORD,
835         /*  67   -63      */ CWORD_CWORD_CWORD_CWORD,
836         /*  68   -62      */ CWORD_CWORD_CWORD_CWORD,
837         /*  69   -61      */ CWORD_CWORD_CWORD_CWORD,
838         /*  70   -60      */ CWORD_CWORD_CWORD_CWORD,
839         /*  71   -59      */ CWORD_CWORD_CWORD_CWORD,
840         /*  72   -58      */ CWORD_CWORD_CWORD_CWORD,
841         /*  73   -57      */ CWORD_CWORD_CWORD_CWORD,
842         /*  74   -56      */ CWORD_CWORD_CWORD_CWORD,
843         /*  75   -55      */ CWORD_CWORD_CWORD_CWORD,
844         /*  76   -54      */ CWORD_CWORD_CWORD_CWORD,
845         /*  77   -53      */ CWORD_CWORD_CWORD_CWORD,
846         /*  78   -52      */ CWORD_CWORD_CWORD_CWORD,
847         /*  79   -51      */ CWORD_CWORD_CWORD_CWORD,
848         /*  80   -50      */ CWORD_CWORD_CWORD_CWORD,
849         /*  81   -49      */ CWORD_CWORD_CWORD_CWORD,
850         /*  82   -48      */ CWORD_CWORD_CWORD_CWORD,
851         /*  83   -47      */ CWORD_CWORD_CWORD_CWORD,
852         /*  84   -46      */ CWORD_CWORD_CWORD_CWORD,
853         /*  85   -45      */ CWORD_CWORD_CWORD_CWORD,
854         /*  86   -44      */ CWORD_CWORD_CWORD_CWORD,
855         /*  87   -43      */ CWORD_CWORD_CWORD_CWORD,
856         /*  88   -42      */ CWORD_CWORD_CWORD_CWORD,
857         /*  89   -41      */ CWORD_CWORD_CWORD_CWORD,
858         /*  90   -40      */ CWORD_CWORD_CWORD_CWORD,
859         /*  91   -39      */ CWORD_CWORD_CWORD_CWORD,
860         /*  92   -38      */ CWORD_CWORD_CWORD_CWORD,
861         /*  93   -37      */ CWORD_CWORD_CWORD_CWORD,
862         /*  94   -36      */ CWORD_CWORD_CWORD_CWORD,
863         /*  95   -35      */ CWORD_CWORD_CWORD_CWORD,
864         /*  96   -34      */ CWORD_CWORD_CWORD_CWORD,
865         /*  97   -33      */ CWORD_CWORD_CWORD_CWORD,
866         /*  98   -32      */ CWORD_CWORD_CWORD_CWORD,
867         /*  99   -31      */ CWORD_CWORD_CWORD_CWORD,
868         /* 100   -30      */ CWORD_CWORD_CWORD_CWORD,
869         /* 101   -29      */ CWORD_CWORD_CWORD_CWORD,
870         /* 102   -28      */ CWORD_CWORD_CWORD_CWORD,
871         /* 103   -27      */ CWORD_CWORD_CWORD_CWORD,
872         /* 104   -26      */ CWORD_CWORD_CWORD_CWORD,
873         /* 105   -25      */ CWORD_CWORD_CWORD_CWORD,
874         /* 106   -24      */ CWORD_CWORD_CWORD_CWORD,
875         /* 107   -23      */ CWORD_CWORD_CWORD_CWORD,
876         /* 108   -22      */ CWORD_CWORD_CWORD_CWORD,
877         /* 109   -21      */ CWORD_CWORD_CWORD_CWORD,
878         /* 110   -20      */ CWORD_CWORD_CWORD_CWORD,
879         /* 111   -19      */ CWORD_CWORD_CWORD_CWORD,
880         /* 112   -18      */ CWORD_CWORD_CWORD_CWORD,
881         /* 113   -17      */ CWORD_CWORD_CWORD_CWORD,
882         /* 114   -16      */ CWORD_CWORD_CWORD_CWORD,
883         /* 115   -15      */ CWORD_CWORD_CWORD_CWORD,
884         /* 116   -14      */ CWORD_CWORD_CWORD_CWORD,
885         /* 117   -13      */ CWORD_CWORD_CWORD_CWORD,
886         /* 118   -12      */ CWORD_CWORD_CWORD_CWORD,
887         /* 119   -11      */ CWORD_CWORD_CWORD_CWORD,
888         /* 120   -10      */ CWORD_CWORD_CWORD_CWORD,
889         /* 121    -9      */ CWORD_CWORD_CWORD_CWORD,
890         /* 122    -8      */ CWORD_CWORD_CWORD_CWORD,
891         /* 123    -7      */ CWORD_CWORD_CWORD_CWORD,
892         /* 124    -6      */ CWORD_CWORD_CWORD_CWORD,
893         /* 125    -5      */ CWORD_CWORD_CWORD_CWORD,
894         /* 126    -4      */ CWORD_CWORD_CWORD_CWORD,
895         /* 127    -3      */ CWORD_CWORD_CWORD_CWORD,
896         /* 128    -2      */ CWORD_CWORD_CWORD_CWORD,
897         /* 129    -1      */ CWORD_CWORD_CWORD_CWORD,
898         /* 130     0      */ CWORD_CWORD_CWORD_CWORD,
899         /* 131     1      */ CWORD_CWORD_CWORD_CWORD,
900         /* 132     2      */ CWORD_CWORD_CWORD_CWORD,
901         /* 133     3      */ CWORD_CWORD_CWORD_CWORD,
902         /* 134     4      */ CWORD_CWORD_CWORD_CWORD,
903         /* 135     5      */ CWORD_CWORD_CWORD_CWORD,
904         /* 136     6      */ CWORD_CWORD_CWORD_CWORD,
905         /* 137     7      */ CWORD_CWORD_CWORD_CWORD,
906         /* 138     8      */ CWORD_CWORD_CWORD_CWORD,
907         /* 139     9 "\t" */ CSPCL_CWORD_CWORD_CWORD,
908         /* 140    10 "\n" */ CNL_CNL_CNL_CNL,
909         /* 141    11      */ CWORD_CWORD_CWORD_CWORD,
910         /* 142    12      */ CWORD_CWORD_CWORD_CWORD,
911         /* 143    13      */ CWORD_CWORD_CWORD_CWORD,
912         /* 144    14      */ CWORD_CWORD_CWORD_CWORD,
913         /* 145    15      */ CWORD_CWORD_CWORD_CWORD,
914         /* 146    16      */ CWORD_CWORD_CWORD_CWORD,
915         /* 147    17      */ CWORD_CWORD_CWORD_CWORD,
916         /* 148    18      */ CWORD_CWORD_CWORD_CWORD,
917         /* 149    19      */ CWORD_CWORD_CWORD_CWORD,
918         /* 150    20      */ CWORD_CWORD_CWORD_CWORD,
919         /* 151    21      */ CWORD_CWORD_CWORD_CWORD,
920         /* 152    22      */ CWORD_CWORD_CWORD_CWORD,
921         /* 153    23      */ CWORD_CWORD_CWORD_CWORD,
922         /* 154    24      */ CWORD_CWORD_CWORD_CWORD,
923         /* 155    25      */ CWORD_CWORD_CWORD_CWORD,
924         /* 156    26      */ CWORD_CWORD_CWORD_CWORD,
925         /* 157    27      */ CWORD_CWORD_CWORD_CWORD,
926         /* 158    28      */ CWORD_CWORD_CWORD_CWORD,
927         /* 159    29      */ CWORD_CWORD_CWORD_CWORD,
928         /* 160    30      */ CWORD_CWORD_CWORD_CWORD,
929         /* 161    31      */ CWORD_CWORD_CWORD_CWORD,
930         /* 162    32  " " */ CSPCL_CWORD_CWORD_CWORD,
931         /* 163    33  "!" */ CWORD_CCTL_CCTL_CWORD,
932         /* 164    34  """ */ CDQUOTE_CENDQUOTE_CWORD_CDQUOTE,
933         /* 165    35  "#" */ CWORD_CWORD_CWORD_CWORD,
934         /* 166    36  "$" */ CVAR_CVAR_CWORD_CVAR,
935         /* 167    37  "%" */ CWORD_CWORD_CWORD_CWORD,
936         /* 168    38  "&" */ CSPCL_CWORD_CWORD_CWORD,
937         /* 169    39  "'" */ CSQUOTE_CWORD_CENDQUOTE_CSQUOTE,
938         /* 170    40  "(" */ CSPCL_CWORD_CWORD_CLP,
939         /* 171    41  ")" */ CSPCL_CWORD_CWORD_CRP,
940         /* 172    42  "*" */ CWORD_CCTL_CCTL_CWORD,
941         /* 173    43  "+" */ CWORD_CWORD_CWORD_CWORD,
942         /* 174    44  "," */ CWORD_CWORD_CWORD_CWORD,
943         /* 175    45  "-" */ CWORD_CCTL_CCTL_CWORD,
944         /* 176    46  "." */ CWORD_CWORD_CWORD_CWORD,
945         /* 177    47  "/" */ CWORD_CCTL_CCTL_CWORD,
946         /* 178    48  "0" */ CWORD_CWORD_CWORD_CWORD,
947         /* 179    49  "1" */ CWORD_CWORD_CWORD_CWORD,
948         /* 180    50  "2" */ CWORD_CWORD_CWORD_CWORD,
949         /* 181    51  "3" */ CWORD_CWORD_CWORD_CWORD,
950         /* 182    52  "4" */ CWORD_CWORD_CWORD_CWORD,
951         /* 183    53  "5" */ CWORD_CWORD_CWORD_CWORD,
952         /* 184    54  "6" */ CWORD_CWORD_CWORD_CWORD,
953         /* 185    55  "7" */ CWORD_CWORD_CWORD_CWORD,
954         /* 186    56  "8" */ CWORD_CWORD_CWORD_CWORD,
955         /* 187    57  "9" */ CWORD_CWORD_CWORD_CWORD,
956         /* 188    58  ":" */ CWORD_CCTL_CCTL_CWORD,
957         /* 189    59  ";" */ CSPCL_CWORD_CWORD_CWORD,
958         /* 190    60  "<" */ CSPCL_CWORD_CWORD_CWORD,
959         /* 191    61  "=" */ CWORD_CCTL_CCTL_CWORD,
960         /* 192    62  ">" */ CSPCL_CWORD_CWORD_CWORD,
961         /* 193    63  "?" */ CWORD_CCTL_CCTL_CWORD,
962         /* 194    64  "@" */ CWORD_CWORD_CWORD_CWORD,
963         /* 195    65  "A" */ CWORD_CWORD_CWORD_CWORD,
964         /* 196    66  "B" */ CWORD_CWORD_CWORD_CWORD,
965         /* 197    67  "C" */ CWORD_CWORD_CWORD_CWORD,
966         /* 198    68  "D" */ CWORD_CWORD_CWORD_CWORD,
967         /* 199    69  "E" */ CWORD_CWORD_CWORD_CWORD,
968         /* 200    70  "F" */ CWORD_CWORD_CWORD_CWORD,
969         /* 201    71  "G" */ CWORD_CWORD_CWORD_CWORD,
970         /* 202    72  "H" */ CWORD_CWORD_CWORD_CWORD,
971         /* 203    73  "I" */ CWORD_CWORD_CWORD_CWORD,
972         /* 204    74  "J" */ CWORD_CWORD_CWORD_CWORD,
973         /* 205    75  "K" */ CWORD_CWORD_CWORD_CWORD,
974         /* 206    76  "L" */ CWORD_CWORD_CWORD_CWORD,
975         /* 207    77  "M" */ CWORD_CWORD_CWORD_CWORD,
976         /* 208    78  "N" */ CWORD_CWORD_CWORD_CWORD,
977         /* 209    79  "O" */ CWORD_CWORD_CWORD_CWORD,
978         /* 210    80  "P" */ CWORD_CWORD_CWORD_CWORD,
979         /* 211    81  "Q" */ CWORD_CWORD_CWORD_CWORD,
980         /* 212    82  "R" */ CWORD_CWORD_CWORD_CWORD,
981         /* 213    83  "S" */ CWORD_CWORD_CWORD_CWORD,
982         /* 214    84  "T" */ CWORD_CWORD_CWORD_CWORD,
983         /* 215    85  "U" */ CWORD_CWORD_CWORD_CWORD,
984         /* 216    86  "V" */ CWORD_CWORD_CWORD_CWORD,
985         /* 217    87  "W" */ CWORD_CWORD_CWORD_CWORD,
986         /* 218    88  "X" */ CWORD_CWORD_CWORD_CWORD,
987         /* 219    89  "Y" */ CWORD_CWORD_CWORD_CWORD,
988         /* 220    90  "Z" */ CWORD_CWORD_CWORD_CWORD,
989         /* 221    91  "[" */ CWORD_CCTL_CCTL_CWORD,
990         /* 222    92  "\" */ CBACK_CBACK_CCTL_CBACK,
991         /* 223    93  "]" */ CWORD_CCTL_CCTL_CWORD,
992         /* 224    94  "^" */ CWORD_CWORD_CWORD_CWORD,
993         /* 225    95  "_" */ CWORD_CWORD_CWORD_CWORD,
994         /* 226    96  "`" */ CBQUOTE_CBQUOTE_CWORD_CBQUOTE,
995         /* 227    97  "a" */ CWORD_CWORD_CWORD_CWORD,
996         /* 228    98  "b" */ CWORD_CWORD_CWORD_CWORD,
997         /* 229    99  "c" */ CWORD_CWORD_CWORD_CWORD,
998         /* 230   100  "d" */ CWORD_CWORD_CWORD_CWORD,
999         /* 231   101  "e" */ CWORD_CWORD_CWORD_CWORD,
1000         /* 232   102  "f" */ CWORD_CWORD_CWORD_CWORD,
1001         /* 233   103  "g" */ CWORD_CWORD_CWORD_CWORD,
1002         /* 234   104  "h" */ CWORD_CWORD_CWORD_CWORD,
1003         /* 235   105  "i" */ CWORD_CWORD_CWORD_CWORD,
1004         /* 236   106  "j" */ CWORD_CWORD_CWORD_CWORD,
1005         /* 237   107  "k" */ CWORD_CWORD_CWORD_CWORD,
1006         /* 238   108  "l" */ CWORD_CWORD_CWORD_CWORD,
1007         /* 239   109  "m" */ CWORD_CWORD_CWORD_CWORD,
1008         /* 240   110  "n" */ CWORD_CWORD_CWORD_CWORD,
1009         /* 241   111  "o" */ CWORD_CWORD_CWORD_CWORD,
1010         /* 242   112  "p" */ CWORD_CWORD_CWORD_CWORD,
1011         /* 243   113  "q" */ CWORD_CWORD_CWORD_CWORD,
1012         /* 244   114  "r" */ CWORD_CWORD_CWORD_CWORD,
1013         /* 245   115  "s" */ CWORD_CWORD_CWORD_CWORD,
1014         /* 246   116  "t" */ CWORD_CWORD_CWORD_CWORD,
1015         /* 247   117  "u" */ CWORD_CWORD_CWORD_CWORD,
1016         /* 248   118  "v" */ CWORD_CWORD_CWORD_CWORD,
1017         /* 249   119  "w" */ CWORD_CWORD_CWORD_CWORD,
1018         /* 250   120  "x" */ CWORD_CWORD_CWORD_CWORD,
1019         /* 251   121  "y" */ CWORD_CWORD_CWORD_CWORD,
1020         /* 252   122  "z" */ CWORD_CWORD_CWORD_CWORD,
1021         /* 253   123  "{" */ CWORD_CWORD_CWORD_CWORD,
1022         /* 254   124  "|" */ CSPCL_CWORD_CWORD_CWORD,
1023         /* 255   125  "}" */ CENDVAR_CENDVAR_CWORD_CENDVAR,
1024         /* 256   126  "~" */ CWORD_CCTL_CCTL_CWORD,
1025         /* 257   127      */ CWORD_CWORD_CWORD_CWORD,
1026 };
1027
1028 #endif                                                  /* USE_SIT_FUNCTION */
1029
1030
1031 /* first char is indicating which tokens mark the end of a list */
1032 static const char *const tokname_array[] = {
1033         "\1end of file",
1034         "\0newline",
1035         "\0redirection",
1036         "\0word",
1037         "\0assignment",
1038         "\0;",
1039         "\0&",
1040         "\0&&",
1041         "\0||",
1042         "\0|",
1043         "\0(",
1044         "\1)",
1045         "\1;;",
1046         "\1`",
1047 #define KWDOFFSET 14
1048         /* the following are keywords */
1049         "\0!",
1050         "\0case",
1051         "\1do",
1052         "\1done",
1053         "\1elif",
1054         "\1else",
1055         "\1esac",
1056         "\1fi",
1057         "\0for",
1058         "\0if",
1059         "\0in",
1060         "\1then",
1061         "\0until",
1062         "\0while",
1063         "\0{",
1064         "\1}",
1065 };
1066
1067 static const char *tokname(int tok)
1068 {
1069         static char buf[16];
1070
1071         if (tok >= TSEMI)
1072                 buf[0] = '"';
1073         sprintf(buf + (tok >= TSEMI), "%s%c",
1074                         tokname_array[tok] + 1, (tok >= TSEMI ? '"' : 0));
1075         return buf;
1076 }
1077
1078 static int plinno = 1;  /* input line number */
1079
1080 static int parselleft;  /* copy of parsefile->lleft */
1081
1082 static struct parsefile basepf; /* top level input file */
1083 static char basebuf[BUFSIZ];    /* buffer for top level input file */
1084 static struct parsefile *parsefile = &basepf;   /* current input file */
1085
1086 /*
1087  * NEOF is returned by parsecmd when it encounters an end of file.  It
1088  * must be distinct from NULL, so we use the address of a variable that
1089  * happens to be handy.
1090  */
1091
1092 static int tokpushback; /* last token pushed back */
1093
1094 #define NEOF ((union node *)&tokpushback)
1095 static int checkkwd;    /* 1 == check for kwds, 2 == also eat newlines */
1096
1097
1098 static void error(const char *, ...) __attribute__ ((__noreturn__));
1099 static void exerror(int, const char *, ...) __attribute__ ((__noreturn__));
1100 static void shellexec(char **, char **, const char *, int)
1101         __attribute__ ((noreturn));
1102 static void exitshell(int) __attribute__ ((noreturn));
1103
1104 static int goodname(const char *);
1105 static void ignoresig(int);
1106 static void onsig(int);
1107 static void dotrap(void);
1108 static int decode_signal(const char *, int);
1109
1110 static void shprocvar(void);
1111 static void deletefuncs(void);
1112 static void setparam(char **);
1113 static void freeparam(volatile struct shparam *);
1114
1115 static void find_command(const char *, struct cmdentry *, int, const char *);
1116
1117 static inline void hashcd(void);
1118
1119 /* reasons for skipping commands (see comment on breakcmd routine) */
1120 #define SKIPBREAK       1
1121 #define SKIPCONT        2
1122 #define SKIPFUNC        3
1123 #define SKIPFILE        4
1124
1125 /* values of cmdtype */
1126 #define CMDUNKNOWN -1   /* no entry in table for command */
1127 #define CMDNORMAL 0             /* command is an executable program */
1128 #define CMDBUILTIN 1    /* command is a shell builtin */
1129 #define CMDFUNCTION 2   /* command is a shell function */
1130
1131 #define DO_ERR  1               /* find_command prints errors */
1132 #define DO_ABS  2               /* find_command checks absolute paths */
1133 #define DO_NOFUN        4       /* find_command ignores functions */
1134 #define DO_BRUTE        8       /* find_command ignores hash table */
1135
1136 /*
1137  * Shell variables.
1138  */
1139
1140 /* flags */
1141 #define VEXPORT         0x01    /* variable is exported */
1142 #define VREADONLY       0x02    /* variable cannot be modified */
1143 #define VSTRFIXED       0x04    /* variable struct is staticly allocated */
1144 #define VTEXTFIXED      0x08    /* text is staticly allocated */
1145 #define VSTACK          0x10    /* text is allocated on the stack */
1146 #define VUNSET          0x20    /* the variable is not set */
1147 #define VNOFUNC         0x40    /* don't call the callback function */
1148
1149
1150 struct var {
1151         struct var *next;       /* next entry in hash list */
1152         int flags;                      /* flags are defined above */
1153         char *text;                     /* name=value */
1154         void (*func) (const char *);
1155         /* function to be called when  */
1156         /* the variable gets set/unset */
1157 };
1158
1159 struct localvar {
1160         struct localvar *next;  /* next local variable in list */
1161         struct var *vp;         /* the variable that was made local */
1162         int flags;                      /* saved flags */
1163         char *text;                     /* saved text */
1164 };
1165
1166
1167 #if defined(__GLIBC__) && __GLIBC__ >= 2 && !defined(FNMATCH_BROKEN)
1168 #define rmescapes(p) _rmescapes((p), 0)
1169 static char *_rmescapes(char *, int);
1170 #else
1171 static void rmescapes(char *);
1172 #endif
1173
1174 static int casematch(union node *, const char *);
1175 static void clearredir(void);
1176 static void popstring(void);
1177 static void readcmdfile(const char *);
1178
1179 static int number(const char *);
1180 static int is_number(const char *, int *num);
1181 static char *single_quote(const char *);
1182 static int nextopt(const char *);
1183
1184 static void redirect(union node *, int);
1185 static void popredir(void);
1186 static int dup_as_newfd(int, int);
1187
1188 static void changepath(const char *newval);
1189 static void getoptsreset(const char *value);
1190
1191
1192 static int parsenleft;  /* copy of parsefile->nleft */
1193 static char *parsenextc;        /* copy of parsefile->nextc */
1194 static int rootpid;             /* pid of main shell */
1195 static int rootshell;   /* true if we aren't a child of the main shell */
1196
1197 static const char spcstr[] = " ";
1198 static const char snlfmt[] = "%s\n";
1199
1200 static int sstrnleft;
1201 static int herefd = -1;
1202
1203 static struct localvar *localvars;
1204
1205 static struct var vifs;
1206 static struct var vmail;
1207 static struct var vmpath;
1208 static struct var vpath;
1209 static struct var vps1;
1210 static struct var vps2;
1211 static struct var voptind;
1212
1213 #ifdef CONFIG_LOCALE_SUPPORT
1214 static struct var vlc_all;
1215 static struct var vlc_ctype;
1216 #endif
1217
1218 struct varinit {
1219         struct var *var;
1220         int flags;
1221         const char *text;
1222         void (*func) (const char *);
1223 };
1224
1225 static const char defpathvar[] =
1226         "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin";
1227 #define defpath (defpathvar + 5)
1228
1229 #ifdef IFS_BROKEN
1230 static const char defifsvar[] = "IFS= \t\n";
1231
1232 #define defifs (defifsvar + 4)
1233 #else
1234 static const char defifs[] = " \t\n";
1235 #endif
1236
1237 static const struct varinit varinit[] = {
1238 #ifdef IFS_BROKEN
1239         {&vifs, VSTRFIXED | VTEXTFIXED, defifsvar,
1240 #else
1241         {&vifs, VSTRFIXED | VTEXTFIXED | VUNSET, "IFS=",
1242 #endif
1243          NULL},
1244         {&vmail, VSTRFIXED | VTEXTFIXED | VUNSET, "MAIL=",
1245          NULL},
1246         {&vmpath, VSTRFIXED | VTEXTFIXED | VUNSET, "MAILPATH=",
1247          NULL},
1248         {&vpath, VSTRFIXED | VTEXTFIXED, defpathvar,
1249          changepath},
1250 #if defined(CONFIG_FEATURE_COMMAND_EDITING) && defined(CONFIG_FEATURE_SH_FANCY_PROMPT)
1251         {&vps1, VSTRFIXED | VTEXTFIXED, "PS1=\\w \\$ ",
1252          NULL},
1253 #endif                                                  /* else vps1 depends on uid */
1254         {&vps2, VSTRFIXED | VTEXTFIXED, "PS2=> ",
1255          NULL},
1256         {&voptind, VSTRFIXED | VTEXTFIXED, "OPTIND=1",
1257          getoptsreset},
1258 #ifdef CONFIG_LOCALE_SUPPORT
1259         {&vlc_all, VSTRFIXED | VTEXTFIXED | VUNSET, "LC_ALL=",
1260          change_lc_all},
1261         {&vlc_ctype, VSTRFIXED | VTEXTFIXED | VUNSET, "LC_CTYPE=",
1262          change_lc_ctype},
1263 #endif
1264         {NULL, 0, NULL,
1265          NULL}
1266 };
1267
1268 #define VTABSIZE 39
1269
1270 static struct var *vartab[VTABSIZE];
1271
1272 /*
1273  * The following macros access the values of the above variables.
1274  * They have to skip over the name.  They return the null string
1275  * for unset variables.
1276  */
1277
1278 #define ifsval()        (vifs.text + 4)
1279 #define ifsset()        ((vifs.flags & VUNSET) == 0)
1280 #define mailval()       (vmail.text + 5)
1281 #define mpathval()      (vmpath.text + 9)
1282 #define pathval()       (vpath.text + 5)
1283 #define ps1val()        (vps1.text + 4)
1284 #define ps2val()        (vps2.text + 4)
1285 #define optindval()     (voptind.text + 7)
1286
1287 #define mpathset()      ((vmpath.flags & VUNSET) == 0)
1288
1289 static void initvar(void);
1290 static void setvar(const char *, const char *, int);
1291 static void setvareq(char *, int);
1292 static void listsetvar(struct strlist *);
1293 static const char *lookupvar(const char *);
1294 static const char *bltinlookup(const char *);
1295 static char **environment(void);
1296 static int showvarscmd(int, char **);
1297 static void mklocal(char *);
1298 static void poplocalvars(void);
1299 static int unsetvar(const char *);
1300 static int varequal(const char *, const char *);
1301
1302
1303 static char *arg0;              /* value of $0 */
1304 static struct shparam shellparam;       /* current positional parameters */
1305 static char **argptr;   /* argument list for builtin commands */
1306 static char *optionarg; /* set by nextopt (like getopt) */
1307 static char *optptr;    /* used by nextopt */
1308 static char *minusc;    /* argument to -c option */
1309
1310
1311 #ifdef CONFIG_ASH_ALIAS
1312
1313 #define ALIASINUSE      1
1314 #define ALIASDEAD       2
1315
1316 #define ATABSIZE 39
1317
1318 struct alias {
1319         struct alias *next;
1320         char *name;
1321         char *val;
1322         int flag;
1323 };
1324
1325 static struct alias *atab[ATABSIZE];
1326
1327 static void setalias(char *, char *);
1328 static struct alias **hashalias(const char *);
1329 static struct alias *freealias(struct alias *);
1330 static struct alias **__lookupalias(const char *);
1331
1332 static void setalias(char *name, char *val)
1333 {
1334         struct alias *ap, **app;
1335
1336         app = __lookupalias(name);
1337         ap = *app;
1338         INTOFF;
1339         if (ap) {
1340                 if (!(ap->flag & ALIASINUSE)) {
1341                         free(ap->val);
1342                 }
1343                 ap->val = xstrdup(val);
1344                 ap->flag &= ~ALIASDEAD;
1345         } else {
1346                 /* not found */
1347                 ap = xmalloc(sizeof(struct alias));
1348                 ap->name = xstrdup(name);
1349                 ap->val = xstrdup(val);
1350                 ap->flag = 0;
1351                 ap->next = 0;
1352                 *app = ap;
1353         }
1354         INTON;
1355 }
1356
1357 static int unalias(char *name)
1358 {
1359         struct alias **app;
1360
1361         app = __lookupalias(name);
1362
1363         if (*app) {
1364                 INTOFF;
1365                 *app = freealias(*app);
1366                 INTON;
1367                 return (0);
1368         }
1369
1370         return (1);
1371 }
1372
1373 static void rmaliases(void)
1374 {
1375         struct alias *ap, **app;
1376         int i;
1377
1378         INTOFF;
1379         for (i = 0; i < ATABSIZE; i++) {
1380                 app = &atab[i];
1381                 for (ap = *app; ap; ap = *app) {
1382                         *app = freealias(*app);
1383                         if (ap == *app) {
1384                                 app = &ap->next;
1385                         }
1386                 }
1387         }
1388         INTON;
1389 }
1390
1391 static void printalias(const struct alias *ap)
1392 {
1393         char *p;
1394
1395         p = single_quote(ap->val);
1396         printf("alias %s=%s\n", ap->name, p);
1397         stunalloc(p);
1398 }
1399
1400
1401 /*
1402  * TODO - sort output
1403  */
1404 static int aliascmd(int argc, char **argv)
1405 {
1406         char *n, *v;
1407         int ret = 0;
1408         struct alias *ap;
1409
1410         if (argc == 1) {
1411                 int i;
1412
1413                 for (i = 0; i < ATABSIZE; i++)
1414                         for (ap = atab[i]; ap; ap = ap->next) {
1415                                 printalias(ap);
1416                         }
1417                 return (0);
1418         }
1419         while ((n = *++argv) != NULL) {
1420                 if ((v = strchr(n + 1, '=')) == NULL) { /* n+1: funny ksh stuff */
1421                         if ((ap = *__lookupalias(n)) == NULL) {
1422                                 out2fmt("%s: %s not found\n", "alias", n);
1423                                 ret = 1;
1424                         } else
1425                                 printalias(ap);
1426                 } else {
1427                         *v++ = '\0';
1428                         setalias(n, v);
1429                 }
1430         }
1431
1432         return (ret);
1433 }
1434
1435 static int unaliascmd(int argc, char **argv)
1436 {
1437         int i;
1438
1439         while ((i = nextopt("a")) != '\0') {
1440                 if (i == 'a') {
1441                         rmaliases();
1442                         return (0);
1443                 }
1444         }
1445         for (i = 0; *argptr; argptr++) {
1446                 if (unalias(*argptr)) {
1447                         out2fmt("%s: %s not found\n", "unalias", *argptr);
1448                         i = 1;
1449                 }
1450         }
1451
1452         return (i);
1453 }
1454
1455 static struct alias **hashalias(const char *p)
1456 {
1457         unsigned int hashval;
1458
1459         hashval = *p << 4;
1460         while (*p)
1461                 hashval += *p++;
1462         return &atab[hashval % ATABSIZE];
1463 }
1464
1465 static struct alias *freealias(struct alias *ap)
1466 {
1467         struct alias *next;
1468
1469         if (ap->flag & ALIASINUSE) {
1470                 ap->flag |= ALIASDEAD;
1471                 return ap;
1472         }
1473
1474         next = ap->next;
1475         free(ap->name);
1476         free(ap->val);
1477         free(ap);
1478         return next;
1479 }
1480
1481
1482 static struct alias **__lookupalias(const char *name)
1483 {
1484         struct alias **app = hashalias(name);
1485
1486         for (; *app; app = &(*app)->next) {
1487                 if (equal(name, (*app)->name)) {
1488                         break;
1489                 }
1490         }
1491
1492         return app;
1493 }
1494 #endif
1495
1496 #ifdef CONFIG_ASH_MATH_SUPPORT
1497 /* The generated file arith.c has been replaced with a custom hand
1498  * written implementation written by Aaron Lehmann <aaronl@vitelus.com>.
1499  * This is now part of libbb, so that it can be used by all the shells
1500  * in busybox. */
1501 static void expari(int);
1502 #endif
1503
1504 static char *trap[NSIG];        /* trap handler commands */
1505 static char sigmode[NSIG - 1];  /* current value of signal */
1506 static char gotsig[NSIG - 1];   /* indicates specified signal received */
1507 static int pendingsigs; /* indicates some signal received */
1508
1509 /*
1510  * This file was generated by the mkbuiltins program.
1511  */
1512
1513 #ifdef CONFIG_ASH_JOB_CONTROL
1514 static int bgcmd(int, char **);
1515 static int fgcmd(int, char **);
1516 static int killcmd(int, char **);
1517 #endif
1518 static int bltincmd(int, char **);
1519 static int cdcmd(int, char **);
1520 static int breakcmd(int, char **);
1521
1522 #ifdef CONFIG_ASH_CMDCMD
1523 static int commandcmd(int, char **);
1524 #endif
1525 static int dotcmd(int, char **);
1526 static int evalcmd(int, char **);
1527 static int execcmd(int, char **);
1528 static int exitcmd(int, char **);
1529 static int exportcmd(int, char **);
1530 static int histcmd(int, char **);
1531 static int hashcmd(int, char **);
1532 static int helpcmd(int, char **);
1533 static int jobscmd(int, char **);
1534 static int localcmd(int, char **);
1535 static int pwdcmd(int, char **);
1536 static int readcmd(int, char **);
1537 static int returncmd(int, char **);
1538 static int setcmd(int, char **);
1539 static int setvarcmd(int, char **);
1540 static int shiftcmd(int, char **);
1541 static int trapcmd(int, char **);
1542 static int umaskcmd(int, char **);
1543
1544 #ifdef CONFIG_ASH_ALIAS
1545 static int aliascmd(int, char **);
1546 static int unaliascmd(int, char **);
1547 #endif
1548 static int unsetcmd(int, char **);
1549 static int waitcmd(int, char **);
1550 static int ulimitcmd(int, char **);
1551 static int timescmd(int, char **);
1552
1553 #ifdef CONFIG_ASH_MATH_SUPPORT
1554 static int letcmd(int, char **);
1555 #endif
1556 static int typecmd(int, char **);
1557
1558 #ifdef CONFIG_ASH_GETOPTS
1559 static int getoptscmd(int, char **);
1560 #endif
1561
1562 #ifndef CONFIG_TRUE
1563 static int true_main(int, char **);
1564 #endif
1565 #ifndef CONFIG_FALSE
1566 static int false_main(int, char **);
1567 #endif
1568
1569 static void setpwd(const char *, int);
1570
1571
1572 #define BUILTIN_NOSPEC  "0"
1573 #define BUILTIN_SPECIAL "1"
1574 #define BUILTIN_REGULAR "2"
1575 #define BUILTIN_ASSIGN  "4"
1576 #define BUILTIN_SPEC_ASSG  "5"
1577 #define BUILTIN_REG_ASSG   "6"
1578
1579 #define IS_BUILTIN_SPECIAL(builtincmd) ((builtincmd)->name[0] & 1)
1580 #define IS_BUILTIN_REGULAR(builtincmd) ((builtincmd)->name[0] & 2)
1581 #define IS_BUILTIN_ASSIGN(builtincmd) ((builtincmd)->name[0] & 4)
1582
1583 struct builtincmd {
1584         const char *name;
1585         int (*const builtinfunc) (int, char **);
1586         /* unsigned flags; */
1587 };
1588
1589
1590 /* It is CRUCIAL that this listing be kept in ascii order, otherwise
1591  * the binary search in find_builtin() will stop working. If you value
1592  * your kneecaps, you'll be sure to *make sure* that any changes made
1593  * to this array result in the listing remaining in ascii order. You
1594  * have been warned.
1595  */
1596 static const struct builtincmd builtincmds[] = {
1597         {BUILTIN_SPECIAL ".", dotcmd},  /* first, see declare DOTCMD */
1598         {BUILTIN_SPECIAL ":", true_main},
1599 #ifdef CONFIG_ASH_ALIAS
1600         {BUILTIN_REG_ASSG "alias", aliascmd},
1601 #endif
1602 #ifdef CONFIG_ASH_JOB_CONTROL
1603         {BUILTIN_REGULAR "bg", bgcmd},
1604 #endif
1605         {BUILTIN_SPECIAL "break", breakcmd},
1606         {BUILTIN_SPECIAL "builtin", bltincmd},
1607         {BUILTIN_REGULAR "cd", cdcmd},
1608         {BUILTIN_NOSPEC "chdir", cdcmd},
1609 #ifdef CONFIG_ASH_CMDCMD
1610         {BUILTIN_REGULAR "command", commandcmd},
1611 #endif
1612         {BUILTIN_SPECIAL "continue", breakcmd},
1613         {BUILTIN_SPECIAL "eval", evalcmd},
1614         {BUILTIN_SPECIAL "exec", execcmd},
1615         {BUILTIN_SPECIAL "exit", exitcmd},
1616         {BUILTIN_SPEC_ASSG "export", exportcmd},
1617         {BUILTIN_REGULAR "false", false_main},
1618         {BUILTIN_REGULAR "fc", histcmd},
1619 #ifdef CONFIG_ASH_JOB_CONTROL
1620         {BUILTIN_REGULAR "fg", fgcmd},
1621 #endif
1622 #ifdef CONFIG_ASH_GETOPTS
1623         {BUILTIN_REGULAR "getopts", getoptscmd},
1624 #endif
1625         {BUILTIN_NOSPEC "hash", hashcmd},
1626         {BUILTIN_NOSPEC "help", helpcmd},
1627         {BUILTIN_REGULAR "jobs", jobscmd},
1628 #ifdef CONFIG_ASH_JOB_CONTROL
1629         {BUILTIN_REGULAR "kill", killcmd},
1630 #endif
1631 #ifdef CONFIG_ASH_MATH_SUPPORT
1632         {BUILTIN_REGULAR "let", letcmd},
1633 #endif
1634         {BUILTIN_ASSIGN "local", localcmd},
1635         {BUILTIN_NOSPEC "pwd", pwdcmd},
1636         {BUILTIN_REGULAR "read", readcmd},
1637         {BUILTIN_SPEC_ASSG "readonly", exportcmd},
1638         {BUILTIN_SPECIAL "return", returncmd},
1639         {BUILTIN_SPECIAL "set", setcmd},
1640         {BUILTIN_NOSPEC "setvar", setvarcmd},
1641         {BUILTIN_SPECIAL "shift", shiftcmd},
1642         {BUILTIN_SPECIAL "times", timescmd},
1643         {BUILTIN_SPECIAL "trap", trapcmd},
1644         {BUILTIN_REGULAR "true", true_main},
1645         {BUILTIN_NOSPEC "type", typecmd},
1646         {BUILTIN_NOSPEC "ulimit", ulimitcmd},
1647         {BUILTIN_REGULAR "umask", umaskcmd},
1648 #ifdef CONFIG_ASH_ALIAS
1649         {BUILTIN_REGULAR "unalias", unaliascmd},
1650 #endif
1651         {BUILTIN_SPECIAL "unset", unsetcmd},
1652         {BUILTIN_REGULAR "wait", waitcmd},
1653 };
1654
1655 #define NUMBUILTINS  (sizeof (builtincmds) / sizeof (struct builtincmd) )
1656
1657 #define DOTCMD &builtincmds[0]
1658 static struct builtincmd *BLTINCMD;
1659 static struct builtincmd *EXECCMD;
1660 static struct builtincmd *EVALCMD;
1661
1662 /* states */
1663 #define CONFIG_ASH_JOB_CONTROLTOPPED 1  /* all procs are stopped */
1664 #define JOBDONE 2               /* all procs are completed */
1665
1666 /*
1667  * A job structure contains information about a job.  A job is either a
1668  * single process or a set of processes contained in a pipeline.  In the
1669  * latter case, pidlist will be non-NULL, and will point to a -1 terminated
1670  * array of pids.
1671  */
1672
1673 struct procstat {
1674         pid_t pid;                      /* process id */
1675         int status;                     /* status flags (defined above) */
1676         char *cmd;                      /* text of command being run */
1677 };
1678
1679
1680 static int job_warning; /* user was warned about stopped jobs */
1681
1682 #ifdef CONFIG_ASH_JOB_CONTROL
1683 static void setjobctl(int enable);
1684 #else
1685 #define setjobctl(on)   /* do nothing */
1686 #endif
1687
1688
1689 struct job {
1690         struct procstat ps0;    /* status of process */
1691         struct procstat *ps;    /* status or processes when more than one */
1692         short nprocs;           /* number of processes */
1693         short pgrp;                     /* process group of this job */
1694         char state;                     /* true if job is finished */
1695         char used;                      /* true if this entry is in used */
1696         char changed;           /* true if status has changed */
1697 #ifdef CONFIG_ASH_JOB_CONTROL
1698         char jobctl;            /* job running under job control */
1699 #endif
1700 };
1701
1702 static struct job *jobtab;      /* array of jobs */
1703 static int njobs;               /* size of array */
1704 static int backgndpid = -1;     /* pid of last background process */
1705
1706 #ifdef CONFIG_ASH_JOB_CONTROL
1707 static int initialpgrp; /* pgrp of shell on invocation */
1708 static int curjob;              /* current job */
1709 static int jobctl;
1710 #endif
1711 static int intreceived;
1712
1713 static struct job *makejob(const union node *, int);
1714 static int forkshell(struct job *, const union node *, int);
1715 static int waitforjob(struct job *);
1716
1717 static int docd(char *, int);
1718 static void getpwd(void);
1719
1720 static char *padvance(const char **, const char *);
1721
1722 static char nullstr[1]; /* zero length string */
1723 static char *curdir = nullstr;  /* current working directory */
1724
1725 static int cdcmd(int argc, char **argv)
1726 {
1727         const char *dest;
1728         const char *path;
1729         char *p;
1730         struct stat statb;
1731         int print = 0;
1732
1733         nextopt(nullstr);
1734         if ((dest = *argptr) == NULL && (dest = bltinlookup("HOME")) == NULL)
1735                 error("HOME not set");
1736         if (*dest == '\0')
1737                 dest = ".";
1738         if (dest[0] == '-' && dest[1] == '\0') {
1739                 dest = bltinlookup("OLDPWD");
1740                 if (!dest || !*dest) {
1741                         dest = curdir;
1742                 }
1743                 print = 1;
1744                 if (dest)
1745                         print = 1;
1746                 else
1747                         dest = ".";
1748         }
1749         if (*dest == '/' || (path = bltinlookup("CDPATH")) == NULL)
1750                 path = nullstr;
1751         while ((p = padvance(&path, dest)) != NULL) {
1752                 if (stat(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) {
1753                         if (!print) {
1754                                 /*
1755                                  * XXX - rethink
1756                                  */
1757                                 if (p[0] == '.' && p[1] == '/' && p[2] != '\0')
1758                                         p += 2;
1759                                 print = strcmp(p, dest);
1760                         }
1761                         if (docd(p, print) >= 0)
1762                                 return 0;
1763
1764                 }
1765         }
1766         error("can't cd to %s", dest);
1767         /* NOTREACHED */
1768 }
1769
1770
1771 /*
1772  * Actually do the chdir.  In an interactive shell, print the
1773  * directory name if "print" is nonzero.
1774  */
1775
1776 static int docd(char *dest, int print)
1777 {
1778         TRACE(("docd(\"%s\", %d) called\n", dest, print));
1779         INTOFF;
1780         if (chdir(dest) < 0) {
1781                 INTON;
1782                 return -1;
1783         }
1784         hashcd();
1785         /*
1786          * Update curdir (the name of the current directory) in response to a
1787          * cd command.  We also call hashcd to let the routines in exec.c know
1788          * that the current directory has changed.
1789          */
1790         /* If dest is NULL, we don't know the current directory */
1791         if (dest == NULL || curdir == nullstr)
1792                 setpwd(0, 1);
1793         else
1794                 setpwd(dest, 1);
1795
1796         INTON;
1797         if (print && iflag)
1798                 puts(curdir);
1799         return 0;
1800 }
1801
1802
1803 static int pwdcmd(int argc, char **argv)
1804 {
1805         puts(curdir);
1806         return 0;
1807 }
1808
1809 /* Ask system the current directory */
1810 static void getpwd(void)
1811 {
1812         curdir = xgetcwd(0);
1813         if (curdir == 0)
1814                 curdir = nullstr;
1815 }
1816
1817 static void setpwd(const char *val, int setold)
1818 {
1819         char *cated = NULL;
1820
1821         if (setold) {
1822                 setvar("OLDPWD", curdir, VEXPORT);
1823         }
1824         INTOFF;
1825         if (curdir != nullstr) {
1826                 if (val != NULL && *val != '/')
1827                         val = cated = concat_path_file(curdir, val);
1828                 free(curdir);
1829         }
1830         if (!val)
1831                 getpwd();
1832         else
1833                 curdir = simplify_path(val);
1834         free(cated);
1835         INTON;
1836         setvar("PWD", curdir, VEXPORT);
1837 }
1838
1839 /*
1840  * Errors and exceptions.
1841  */
1842
1843 /*
1844  * Code to handle exceptions in C.
1845  */
1846
1847 /*
1848  * We enclose jmp_buf in a structure so that we can declare pointers to
1849  * jump locations.  The global variable handler contains the location to
1850  * jump to when an exception occurs, and the global variable exception
1851  * contains a code identifying the exeception.  To implement nested
1852  * exception handlers, the user should save the value of handler on entry
1853  * to an inner scope, set handler to point to a jmploc structure for the
1854  * inner scope, and restore handler on exit from the scope.
1855  */
1856
1857 struct jmploc {
1858         jmp_buf loc;
1859 };
1860
1861 /* exceptions */
1862 #define EXINT 0                 /* SIGINT received */
1863 #define EXERROR 1               /* a generic error */
1864 #define EXSHELLPROC 2   /* execute a shell procedure */
1865 #define EXEXEC 3                /* command execution failed */
1866
1867 static struct jmploc *handler;
1868 static int exception;
1869
1870 static void exverror(int, const char *, va_list)
1871         __attribute__ ((__noreturn__));
1872
1873 /*
1874  * Called to raise an exception.  Since C doesn't include exceptions, we
1875  * just do a longjmp to the exception handler.  The type of exception is
1876  * stored in the global variable "exception".
1877  */
1878
1879 static void exraise(int) __attribute__ ((__noreturn__));
1880
1881 static void exraise(int e)
1882 {
1883 #ifdef DEBUG
1884         if (handler == NULL)
1885                 abort();
1886 #endif
1887         flushall();
1888         exception = e;
1889         longjmp(handler->loc, 1);
1890 }
1891
1892
1893 /*
1894  * Called from trap.c when a SIGINT is received.  (If the user specifies
1895  * that SIGINT is to be trapped or ignored using the trap builtin, then
1896  * this routine is not called.)  Suppressint is nonzero when interrupts
1897  * are held using the INTOFF macro.  The call to _exit is necessary because
1898  * there is a short period after a fork before the signal handlers are
1899  * set to the appropriate value for the child.  (The test for iflag is
1900  * just defensive programming.)
1901  */
1902
1903 static void onint(void)
1904 {
1905         sigset_t mysigset;
1906
1907         if (suppressint) {
1908                 intpending++;
1909                 return;
1910         }
1911         intpending = 0;
1912         sigemptyset(&mysigset);
1913         sigprocmask(SIG_SETMASK, &mysigset, NULL);
1914         if (rootshell && iflag)
1915                 exraise(EXINT);
1916         else {
1917                 signal(SIGINT, SIG_DFL);
1918                 raise(SIGINT);
1919         }
1920         /* NOTREACHED */
1921 }
1922
1923
1924 static char *commandname;       /* currently executing command */
1925
1926 /*
1927  * Exverror is called to raise the error exception.  If the first argument
1928  * is not NULL then error prints an error message using printf style
1929  * formatting.  It then raises the error exception.
1930  */
1931 static void exverror(int cond, const char *msg, va_list ap)
1932 {
1933         CLEAR_PENDING_INT;
1934         INTOFF;
1935
1936 #ifdef DEBUG
1937         if (msg)
1938                 TRACE(("exverror(%d, \"%s\") pid=%d\n", cond, msg, getpid()));
1939         else
1940                 TRACE(("exverror(%d, NULL) pid=%d\n", cond, getpid()));
1941 #endif
1942         if (msg) {
1943                 if (commandname)
1944                         out2fmt("%s: ", commandname);
1945                 vfprintf(stderr, msg, ap);
1946                 out2c('\n');
1947         }
1948         exraise(cond);
1949         /* NOTREACHED */
1950 }
1951
1952
1953 static void error(const char *msg, ...)
1954 {
1955         va_list ap;
1956
1957         va_start(ap, msg);
1958         exverror(EXERROR, msg, ap);
1959         /* NOTREACHED */
1960         va_end(ap);
1961 }
1962
1963
1964 static void exerror(int cond, const char *msg, ...)
1965 {
1966         va_list ap;
1967
1968         va_start(ap, msg);
1969         exverror(cond, msg, ap);
1970         /* NOTREACHED */
1971         va_end(ap);
1972 }
1973
1974
1975
1976 /*
1977  * Table of error messages.
1978  */
1979
1980 struct errname {
1981         short errcode;          /* error number */
1982         short action;           /* operation which encountered the error */
1983 };
1984
1985 /*
1986  * Types of operations (passed to the errmsg routine).
1987  */
1988
1989 #define E_OPEN 01               /* opening a file */
1990 #define E_CREAT 02              /* creating a file */
1991 #define E_EXEC 04               /* executing a program */
1992
1993 #define ALL (E_OPEN|E_CREAT|E_EXEC)
1994
1995 static const struct errname errormsg[] = {
1996         {EINTR, ALL},
1997         {EACCES, ALL},
1998         {EIO, ALL},
1999         {ENOENT, E_OPEN},
2000         {ENOENT, E_CREAT},
2001         {ENOENT, E_EXEC},
2002         {ENOTDIR, E_OPEN},
2003         {ENOTDIR, E_CREAT},
2004         {ENOTDIR, E_EXEC},
2005         {EISDIR, ALL},
2006         {EEXIST, E_CREAT},
2007 #ifdef EMFILE
2008         {EMFILE, ALL},
2009 #endif
2010         {ENFILE, ALL},
2011         {ENOSPC, ALL},
2012 #ifdef EDQUOT
2013         {EDQUOT, ALL},
2014 #endif
2015 #ifdef ENOSR
2016         {ENOSR, ALL},
2017 #endif
2018         {ENXIO, ALL},
2019         {EROFS, ALL},
2020         {ETXTBSY, ALL},
2021 #ifdef EAGAIN
2022         {EAGAIN, E_EXEC},
2023 #endif
2024         {ENOMEM, ALL},
2025 #ifdef ENOLINK
2026         {ENOLINK, ALL},
2027 #endif
2028 #ifdef EMULTIHOP
2029         {EMULTIHOP, ALL},
2030 #endif
2031 #ifdef ECOMM
2032         {ECOMM, ALL},
2033 #endif
2034 #ifdef ESTALE
2035         {ESTALE, ALL},
2036 #endif
2037 #ifdef ETIMEDOUT
2038         {ETIMEDOUT, ALL},
2039 #endif
2040 #ifdef ELOOP
2041         {ELOOP, ALL},
2042 #endif
2043         {E2BIG, E_EXEC},
2044 #ifdef ELIBACC
2045         {ELIBACC, E_EXEC},
2046 #endif
2047 };
2048
2049 #define ERRNAME_SIZE (sizeof(errormsg)/sizeof(struct errname))
2050
2051 /*
2052  * Return a string describing an error.  The returned string may be a
2053  * pointer to a static buffer that will be overwritten on the next call.
2054  * Action describes the operation that got the error.
2055  */
2056
2057 static const char *errmsg(int e, int action)
2058 {
2059         struct errname const *ep;
2060         static char buf[12];
2061
2062         for (ep = errormsg; ep < errormsg + ERRNAME_SIZE; ep++) {
2063                 if (ep->errcode == e && (ep->action & action) != 0)
2064                         return strerror(e);
2065         }
2066
2067         snprintf(buf, sizeof buf, "error %d", e);
2068         return buf;
2069 }
2070
2071
2072 #ifdef CONFIG_ASH_OPTIMIZE_FOR_SIZE
2073 static void __inton()
2074 {
2075         if (--suppressint == 0 && intpending) {
2076                 onint();
2077         }
2078 }
2079 static void forceinton(void)
2080 {
2081         suppressint = 0;
2082         if (intpending)
2083                 onint();
2084 }
2085 #endif
2086
2087 /* flags in argument to evaltree */
2088 #define EV_EXIT 01              /* exit after evaluating tree */
2089 #define EV_TESTED 02    /* exit status is checked; ignore -e flag */
2090 #define EV_BACKCMD 04   /* command executing within back quotes */
2091
2092 static int evalskip;    /* set if we are skipping commands */
2093 static int skipcount;   /* number of levels to skip */
2094 static int loopnest;    /* current loop nesting level */
2095 static int funcnest;    /* depth of function calls */
2096
2097
2098 static struct strlist *cmdenviron;      /* environment for builtin command */
2099 static int exitstatus;  /* exit status of last command */
2100 static int oexitstatus; /* saved exit status */
2101
2102 static void evalsubshell(const union node *, int);
2103 static void expredir(union node *);
2104 static void eprintlist(struct strlist *);
2105
2106 static union node *parsecmd(int);
2107
2108 /*
2109  * Called to reset things after an exception.
2110  */
2111
2112 /*
2113  * The eval commmand.
2114  */
2115 static void evalstring(char *, int);
2116
2117 static int evalcmd(int argc, char **argv)
2118 {
2119         char *p;
2120         char *concat;
2121         char **ap;
2122
2123         if (argc > 1) {
2124                 p = argv[1];
2125                 if (argc > 2) {
2126                         STARTSTACKSTR(concat);
2127                         ap = argv + 2;
2128                         for (;;) {
2129                                 while (*p)
2130                                         STPUTC(*p++, concat);
2131                                 if ((p = *ap++) == NULL)
2132                                         break;
2133                                 STPUTC(' ', concat);
2134                         }
2135                         STPUTC('\0', concat);
2136                         p = grabstackstr(concat);
2137                 }
2138                 evalstring(p, EV_TESTED);
2139         }
2140         return exitstatus;
2141 }
2142
2143 /*
2144  * Execute a command or commands contained in a string.
2145  */
2146
2147 static void evaltree(union node *, int);
2148 static void setinputstring(char *);
2149 static void popfile(void);
2150 static void setstackmark(struct stackmark *mark);
2151 static void popstackmark(struct stackmark *mark);
2152
2153
2154 static void evalstring(char *s, int flag)
2155 {
2156         union node *n;
2157         struct stackmark smark;
2158
2159         setstackmark(&smark);
2160         setinputstring(s);
2161         while ((n = parsecmd(0)) != NEOF) {
2162                 evaltree(n, flag);
2163                 popstackmark(&smark);
2164         }
2165         popfile();
2166         popstackmark(&smark);
2167 }
2168
2169 static struct builtincmd *find_builtin(const char *);
2170 static void expandarg(union node *, struct arglist *, int);
2171 static void calcsize(const union node *);
2172 static union node *copynode(const union node *);
2173
2174 /*
2175  * Make a copy of a parse tree.
2176  */
2177
2178 static int funcblocksize;       /* size of structures in function */
2179 static int funcstringsize;      /* size of strings in node */
2180 static pointer funcblock;       /* block to allocate function from */
2181 static char *funcstring;        /* block to allocate strings from */
2182
2183
2184 static inline union node *copyfunc(union node *n)
2185 {
2186         if (n == NULL)
2187                 return NULL;
2188         funcblocksize = 0;
2189         funcstringsize = 0;
2190         calcsize(n);
2191         funcblock = xmalloc(funcblocksize + funcstringsize);
2192         funcstring = (char *) funcblock + funcblocksize;
2193         return copynode(n);
2194 }
2195
2196 /*
2197  * Add a new command entry, replacing any existing command entry for
2198  * the same name.
2199  */
2200
2201 static inline void addcmdentry(char *name, struct cmdentry *entry)
2202 {
2203         struct tblentry *cmdp;
2204
2205         INTOFF;
2206         cmdp = cmdlookup(name, 1);
2207         if (cmdp->cmdtype == CMDFUNCTION) {
2208                 free(cmdp->param.func);
2209         }
2210         cmdp->cmdtype = entry->cmdtype;
2211         cmdp->param = entry->u;
2212         INTON;
2213 }
2214
2215 static inline void evalloop(const union node *n, int flags)
2216 {
2217         int status;
2218
2219         loopnest++;
2220         status = 0;
2221         for (;;) {
2222                 evaltree(n->nbinary.ch1, EV_TESTED);
2223                 if (evalskip) {
2224                   skipping:if (evalskip == SKIPCONT && --skipcount <= 0) {
2225                                 evalskip = 0;
2226                                 continue;
2227                         }
2228                         if (evalskip == SKIPBREAK && --skipcount <= 0)
2229                                 evalskip = 0;
2230                         break;
2231                 }
2232                 if (n->type == NWHILE) {
2233                         if (exitstatus != 0)
2234                                 break;
2235                 } else {
2236                         if (exitstatus == 0)
2237                                 break;
2238                 }
2239                 evaltree(n->nbinary.ch2, flags & EV_TESTED);
2240                 status = exitstatus;
2241                 if (evalskip)
2242                         goto skipping;
2243         }
2244         loopnest--;
2245         exitstatus = status;
2246 }
2247
2248 static void evalfor(const union node *n, int flags)
2249 {
2250         struct arglist arglist;
2251         union node *argp;
2252         struct strlist *sp;
2253         struct stackmark smark;
2254
2255         setstackmark(&smark);
2256         arglist.lastp = &arglist.list;
2257         for (argp = n->nfor.args; argp; argp = argp->narg.next) {
2258                 oexitstatus = exitstatus;
2259                 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE | EXP_RECORD);
2260                 if (evalskip)
2261                         goto out;
2262         }
2263         *arglist.lastp = NULL;
2264
2265         exitstatus = 0;
2266         loopnest++;
2267         for (sp = arglist.list; sp; sp = sp->next) {
2268                 setvar(n->nfor.var, sp->text, 0);
2269                 evaltree(n->nfor.body, flags & EV_TESTED);
2270                 if (evalskip) {
2271                         if (evalskip == SKIPCONT && --skipcount <= 0) {
2272                                 evalskip = 0;
2273                                 continue;
2274                         }
2275                         if (evalskip == SKIPBREAK && --skipcount <= 0)
2276                                 evalskip = 0;
2277                         break;
2278                 }
2279         }
2280         loopnest--;
2281   out:
2282         popstackmark(&smark);
2283 }
2284
2285 static inline void evalcase(const union node *n, int flags)
2286 {
2287         union node *cp;
2288         union node *patp;
2289         struct arglist arglist;
2290         struct stackmark smark;
2291
2292         setstackmark(&smark);
2293         arglist.lastp = &arglist.list;
2294         oexitstatus = exitstatus;
2295         expandarg(n->ncase.expr, &arglist, EXP_TILDE);
2296         for (cp = n->ncase.cases; cp && evalskip == 0; cp = cp->nclist.next) {
2297                 for (patp = cp->nclist.pattern; patp; patp = patp->narg.next) {
2298                         if (casematch(patp, arglist.list->text)) {
2299                                 if (evalskip == 0) {
2300                                         evaltree(cp->nclist.body, flags);
2301                                 }
2302                                 goto out;
2303                         }
2304                 }
2305         }
2306   out:
2307         popstackmark(&smark);
2308 }
2309
2310 /*
2311  * Evaluate a pipeline.  All the processes in the pipeline are children
2312  * of the process creating the pipeline.  (This differs from some versions
2313  * of the shell, which make the last process in a pipeline the parent
2314  * of all the rest.)
2315  */
2316
2317 static inline void evalpipe(union node *n)
2318 {
2319         struct job *jp;
2320         struct nodelist *lp;
2321         int pipelen;
2322         int prevfd;
2323         int pip[2];
2324
2325         TRACE(("evalpipe(0x%lx) called\n", (long) n));
2326         pipelen = 0;
2327         for (lp = n->npipe.cmdlist; lp; lp = lp->next)
2328                 pipelen++;
2329         INTOFF;
2330         jp = makejob(n, pipelen);
2331         prevfd = -1;
2332         for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
2333                 /*
2334                  * Search for a command.  This is called before we fork so that the
2335                  * location of the command will be available in the parent as well as
2336                  * the child.  The check for "goodname" is an overly conservative
2337                  * check that the name will not be subject to expansion.
2338                  */
2339
2340                 struct cmdentry entry;
2341                 union node *lpn = lp->n;
2342
2343                 if (lpn->type == NCMD && lpn->ncmd.args
2344                         && goodname(lpn->ncmd.args->narg.text))
2345                         find_command(lpn->ncmd.args->narg.text, &entry, 0, pathval());
2346
2347                 pip[1] = -1;
2348                 if (lp->next) {
2349                         if (pipe(pip) < 0) {
2350                                 close(prevfd);
2351                                 error("Pipe call failed");
2352                         }
2353                 }
2354                 if (forkshell(jp, lp->n, n->npipe.backgnd) == 0) {
2355                         INTON;
2356                         if (prevfd > 0) {
2357                                 close(0);
2358                                 dup_as_newfd(prevfd, 0);
2359                                 close(prevfd);
2360                                 if (pip[0] == 0) {
2361                                         pip[0] = -1;
2362                                 }
2363                         }
2364                         if (pip[1] >= 0) {
2365                                 if (pip[0] >= 0) {
2366                                         close(pip[0]);
2367                                 }
2368                                 if (pip[1] != 1) {
2369                                         close(1);
2370                                         dup_as_newfd(pip[1], 1);
2371                                         close(pip[1]);
2372                                 }
2373                         }
2374                         evaltree(lp->n, EV_EXIT);
2375                 }
2376                 if (prevfd >= 0)
2377                         close(prevfd);
2378                 prevfd = pip[0];
2379                 close(pip[1]);
2380         }
2381         INTON;
2382         if (n->npipe.backgnd == 0) {
2383                 INTOFF;
2384                 exitstatus = waitforjob(jp);
2385                 TRACE(("evalpipe:  job done exit status %d\n", exitstatus));
2386                 INTON;
2387         }
2388 }
2389
2390 static int isassignment(const char *word)
2391 {
2392         if (!is_name(*word)) {
2393                 return 0;
2394         }
2395         do {
2396                 word++;
2397         } while (is_in_name(*word));
2398         return *word == '=';
2399 }
2400
2401
2402 static void evalcommand(union node *cmd, int flags)
2403 {
2404         struct stackmark smark;
2405         union node *argp;
2406         struct arglist arglist;
2407         struct arglist varlist;
2408         char **argv;
2409         int argc;
2410         char **envp;
2411         struct strlist *sp;
2412         int mode;
2413         struct cmdentry cmdentry;
2414         struct job *jp;
2415         char *volatile savecmdname;
2416         volatile struct shparam saveparam;
2417         struct localvar *volatile savelocalvars;
2418         volatile int e;
2419         char *lastarg;
2420         const char *path;
2421         const struct builtincmd *firstbltin;
2422         struct jmploc *volatile savehandler;
2423         struct jmploc jmploc;
2424
2425 #if __GNUC__
2426         /* Avoid longjmp clobbering */
2427         (void) &argv;
2428         (void) &argc;
2429         (void) &lastarg;
2430         (void) &flags;
2431 #endif
2432
2433         /* First expand the arguments. */
2434         TRACE(("evalcommand(0x%lx, %d) called\n", (long) cmd, flags));
2435         setstackmark(&smark);
2436         arglist.lastp = &arglist.list;
2437         varlist.lastp = &varlist.list;
2438         arglist.list = 0;
2439         oexitstatus = exitstatus;
2440         exitstatus = 0;
2441         path = pathval();
2442         for (argp = cmd->ncmd.assign; argp; argp = argp->narg.next) {
2443                 expandarg(argp, &varlist, EXP_VARTILDE);
2444         }
2445         for (argp = cmd->ncmd.args; argp && !arglist.list; argp = argp->narg.next) {
2446                 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
2447         }
2448         if (argp) {
2449                 struct builtincmd *bcmd;
2450                 int pseudovarflag;
2451
2452                 bcmd = find_builtin(arglist.list->text);
2453                 pseudovarflag = bcmd && IS_BUILTIN_ASSIGN(bcmd);
2454                 for (; argp; argp = argp->narg.next) {
2455                         if (pseudovarflag && isassignment(argp->narg.text)) {
2456                                 expandarg(argp, &arglist, EXP_VARTILDE);
2457                                 continue;
2458                         }
2459                         expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
2460                 }
2461         }
2462         *arglist.lastp = NULL;
2463         *varlist.lastp = NULL;
2464         expredir(cmd->ncmd.redirect);
2465         argc = 0;
2466         for (sp = arglist.list; sp; sp = sp->next)
2467                 argc++;
2468         argv = stalloc(sizeof(char *) * (argc + 1));
2469
2470         for (sp = arglist.list; sp; sp = sp->next) {
2471                 TRACE(("evalcommand arg: %s\n", sp->text));
2472                 *argv++ = sp->text;
2473         }
2474         *argv = NULL;
2475         lastarg = NULL;
2476         if (iflag && funcnest == 0 && argc > 0)
2477                 lastarg = argv[-1];
2478         argv -= argc;
2479
2480         /* Print the command if xflag is set. */
2481         if (xflag) {
2482                 out2c('+');
2483                 eprintlist(varlist.list);
2484                 eprintlist(arglist.list);
2485                 out2c('\n');
2486         }
2487
2488         /* Now locate the command. */
2489         if (argc == 0) {
2490                 cmdentry.cmdtype = CMDBUILTIN;
2491                 firstbltin = cmdentry.u.cmd = BLTINCMD;
2492         } else {
2493                 const char *oldpath;
2494                 int findflag = DO_ERR;
2495                 int oldfindflag;
2496
2497                 /*
2498                  * Modify the command lookup path, if a PATH= assignment
2499                  * is present
2500                  */
2501                 for (sp = varlist.list; sp; sp = sp->next)
2502                         if (varequal(sp->text, defpathvar)) {
2503                                 path = sp->text + 5;
2504                                 findflag |= DO_BRUTE;
2505                         }
2506                 oldpath = path;
2507                 oldfindflag = findflag;
2508                 firstbltin = 0;
2509                 for (;;) {
2510                         find_command(argv[0], &cmdentry, findflag, path);
2511                         if (cmdentry.cmdtype == CMDUNKNOWN) {   /* command not found */
2512                                 exitstatus = 127;
2513                                 goto out;
2514                         }
2515                         /* implement bltin and command here */
2516                         if (cmdentry.cmdtype != CMDBUILTIN) {
2517                                 break;
2518                         }
2519                         if (!firstbltin) {
2520                                 firstbltin = cmdentry.u.cmd;
2521                         }
2522                         if (cmdentry.u.cmd == BLTINCMD) {
2523                                 for (;;) {
2524                                         struct builtincmd *bcmd;
2525
2526                                         argv++;
2527                                         if (--argc == 0)
2528                                                 goto found;
2529                                         if (!(bcmd = find_builtin(*argv))) {
2530                                                 out2fmt("%s: not found\n", *argv);
2531                                                 exitstatus = 127;
2532                                                 goto out;
2533                                         }
2534                                         cmdentry.u.cmd = bcmd;
2535                                         if (bcmd != BLTINCMD)
2536                                                 break;
2537                                 }
2538                         }
2539                         if (cmdentry.u.cmd == find_builtin("command")) {
2540                                 argv++;
2541                                 if (--argc == 0) {
2542                                         goto found;
2543                                 }
2544                                 if (*argv[0] == '-') {
2545                                         if (!equal(argv[0], "-p")) {
2546                                                 argv--;
2547                                                 argc++;
2548                                                 break;
2549                                         }
2550                                         argv++;
2551                                         if (--argc == 0) {
2552                                                 goto found;
2553                                         }
2554                                         path = defpath;
2555                                         findflag |= DO_BRUTE;
2556                                 } else {
2557                                         path = oldpath;
2558                                         findflag = oldfindflag;
2559                                 }
2560                                 findflag |= DO_NOFUN;
2561                                 continue;
2562                         }
2563                   found:
2564                         break;
2565                 }
2566         }
2567
2568         /* Fork off a child process if necessary. */
2569         if (cmd->ncmd.backgnd
2570                 || (cmdentry.cmdtype == CMDNORMAL && (flags & EV_EXIT) == 0)
2571                 ) {
2572                 jp = makejob(cmd, 1);
2573                 mode = cmd->ncmd.backgnd;
2574                 if (forkshell(jp, cmd, mode) != 0)
2575                         goto parent;    /* at end of routine */
2576                 flags |= EV_EXIT;
2577         }
2578
2579         /* This is the child process if a fork occurred. */
2580         /* Execute the command. */
2581         if (cmdentry.cmdtype == CMDFUNCTION) {
2582 #ifdef DEBUG
2583                 trputs("Shell function:  ");
2584                 trargs(argv);
2585 #endif
2586                 exitstatus = oexitstatus;
2587                 redirect(cmd->ncmd.redirect, REDIR_PUSH);
2588                 saveparam = shellparam;
2589                 shellparam.malloc = 0;
2590                 shellparam.nparam = argc - 1;
2591                 shellparam.p = argv + 1;
2592                 INTOFF;
2593                 savelocalvars = localvars;
2594                 localvars = NULL;
2595                 INTON;
2596                 if (setjmp(jmploc.loc)) {
2597                         if (exception == EXSHELLPROC) {
2598                                 freeparam((volatile struct shparam *)
2599                                                   &saveparam);
2600                         } else {
2601                                 saveparam.optind = shellparam.optind;
2602                                 saveparam.optoff = shellparam.optoff;
2603                                 freeparam(&shellparam);
2604                                 shellparam = saveparam;
2605                         }
2606                         poplocalvars();
2607                         localvars = savelocalvars;
2608                         handler = savehandler;
2609                         longjmp(handler->loc, 1);
2610                 }
2611                 savehandler = handler;
2612                 handler = &jmploc;
2613                 for (sp = varlist.list; sp; sp = sp->next)
2614                         mklocal(sp->text);
2615                 funcnest++;
2616                 evaltree(cmdentry.u.func, flags & EV_TESTED);
2617                 funcnest--;
2618                 INTOFF;
2619                 poplocalvars();
2620                 localvars = savelocalvars;
2621                 saveparam.optind = shellparam.optind;
2622                 saveparam.optoff = shellparam.optoff;
2623                 freeparam(&shellparam);
2624                 shellparam = saveparam;
2625                 handler = savehandler;
2626                 popredir();
2627                 INTON;
2628                 if (evalskip == SKIPFUNC) {
2629                         evalskip = 0;
2630                         skipcount = 0;
2631                 }
2632                 if (flags & EV_EXIT)
2633                         exitshell(exitstatus);
2634         } else if (cmdentry.cmdtype == CMDBUILTIN) {
2635 #ifdef DEBUG
2636                 trputs("builtin command:  ");
2637                 trargs(argv);
2638 #endif
2639                 mode = (cmdentry.u.cmd == EXECCMD) ? 0 : REDIR_PUSH;
2640                 redirect(cmd->ncmd.redirect, mode);
2641                 savecmdname = commandname;
2642                 if (IS_BUILTIN_SPECIAL(firstbltin)) {
2643                         listsetvar(varlist.list);
2644                 } else {
2645                         cmdenviron = varlist.list;
2646                 }
2647                 e = -1;
2648                 if (setjmp(jmploc.loc)) {
2649                         e = exception;
2650                         exitstatus = (e == EXINT) ? SIGINT + 128 : 2;
2651                         goto cmddone;
2652                 }
2653                 savehandler = handler;
2654                 handler = &jmploc;
2655                 commandname = argv[0];
2656                 argptr = argv + 1;
2657                 optptr = NULL;  /* initialize nextopt */
2658                 exitstatus = (*cmdentry.u.cmd->builtinfunc) (argc, argv);
2659                 flushall();
2660           cmddone:
2661                 cmdenviron = NULL;
2662                 if (e != EXSHELLPROC) {
2663                         commandname = savecmdname;
2664                         if (flags & EV_EXIT)
2665                                 exitshell(exitstatus);
2666                 }
2667                 handler = savehandler;
2668                 if (e != -1) {
2669                         if ((e != EXERROR && e != EXEXEC)
2670                                 || cmdentry.u.cmd == BLTINCMD
2671                                 || cmdentry.u.cmd == DOTCMD
2672                                 || cmdentry.u.cmd == EVALCMD || cmdentry.u.cmd == EXECCMD)
2673                                 exraise(e);
2674                         FORCEINTON;
2675                 }
2676                 if (cmdentry.u.cmd != EXECCMD)
2677                         popredir();
2678         } else {
2679 #ifdef DEBUG
2680                 trputs("normal command:  ");
2681                 trargs(argv);
2682 #endif
2683                 redirect(cmd->ncmd.redirect, 0);
2684                 clearredir();
2685                 for (sp = varlist.list; sp; sp = sp->next)
2686                         setvareq(sp->text, VEXPORT | VSTACK);
2687                 envp = environment();
2688                 shellexec(argv, envp, path, cmdentry.u.index);
2689         }
2690         goto out;
2691
2692   parent:                               /* parent process gets here (if we forked) */
2693         if (mode == 0) {        /* argument to fork */
2694                 INTOFF;
2695                 exitstatus = waitforjob(jp);
2696                 INTON;
2697         }
2698
2699   out:
2700         if (lastarg)
2701                 setvar("_", lastarg, 0);
2702         popstackmark(&smark);
2703 }
2704
2705 /*
2706  * Evaluate a parse tree.  The value is left in the global variable
2707  * exitstatus.
2708  */
2709 static void evaltree(union node *n, int flags)
2710 {
2711         int checkexit = 0;
2712
2713         if (n == NULL) {
2714                 TRACE(("evaltree(NULL) called\n"));
2715                 goto out;
2716         }
2717         TRACE(("evaltree(0x%lx: %d) called\n", (long) n, n->type));
2718         switch (n->type) {
2719         case NSEMI:
2720                 evaltree(n->nbinary.ch1, flags & EV_TESTED);
2721                 if (evalskip)
2722                         goto out;
2723                 evaltree(n->nbinary.ch2, flags);
2724                 break;
2725         case NAND:
2726                 evaltree(n->nbinary.ch1, EV_TESTED);
2727                 if (evalskip || exitstatus != 0)
2728                         goto out;
2729                 evaltree(n->nbinary.ch2, flags);
2730                 break;
2731         case NOR:
2732                 evaltree(n->nbinary.ch1, EV_TESTED);
2733                 if (evalskip || exitstatus == 0)
2734                         goto out;
2735                 evaltree(n->nbinary.ch2, flags);
2736                 break;
2737         case NREDIR:
2738                 expredir(n->nredir.redirect);
2739                 redirect(n->nredir.redirect, REDIR_PUSH);
2740                 evaltree(n->nredir.n, flags);
2741                 popredir();
2742                 break;
2743         case NSUBSHELL:
2744                 evalsubshell(n, flags);
2745                 break;
2746         case NBACKGND:
2747                 evalsubshell(n, flags);
2748                 break;
2749         case NIF:{
2750                 evaltree(n->nif.test, EV_TESTED);
2751                 if (evalskip)
2752                         goto out;
2753                 if (exitstatus == 0)
2754                         evaltree(n->nif.ifpart, flags);
2755                 else if (n->nif.elsepart)
2756                         evaltree(n->nif.elsepart, flags);
2757                 else
2758                         exitstatus = 0;
2759                 break;
2760         }
2761         case NWHILE:
2762         case NUNTIL:
2763                 evalloop(n, flags);
2764                 break;
2765         case NFOR:
2766                 evalfor(n, flags);
2767                 break;
2768         case NCASE:
2769                 evalcase(n, flags);
2770                 break;
2771         case NDEFUN:{
2772                 struct builtincmd *bcmd;
2773                 struct cmdentry entry;
2774
2775                 if ((bcmd = find_builtin(n->narg.text)) && IS_BUILTIN_SPECIAL(bcmd)
2776                         ) {
2777                         out2fmt("%s is a special built-in\n", n->narg.text);
2778                         exitstatus = 1;
2779                         break;
2780                 }
2781                 entry.cmdtype = CMDFUNCTION;
2782                 entry.u.func = copyfunc(n->narg.next);
2783                 addcmdentry(n->narg.text, &entry);
2784                 exitstatus = 0;
2785                 break;
2786         }
2787         case NNOT:
2788                 evaltree(n->nnot.com, EV_TESTED);
2789                 exitstatus = !exitstatus;
2790                 break;
2791
2792         case NPIPE:
2793                 evalpipe(n);
2794                 checkexit = 1;
2795                 break;
2796         case NCMD:
2797                 evalcommand(n, flags);
2798                 checkexit = 1;
2799                 break;
2800 #ifdef DEBUG
2801         default:
2802                 printf("Node type = %d\n", n->type);
2803                 break;
2804 #endif
2805         }
2806   out:
2807         if (pendingsigs)
2808                 dotrap();
2809         if (flags & EV_EXIT ||
2810                 (checkexit && eflag && exitstatus && !(flags & EV_TESTED))
2811                 )
2812                 exitshell(exitstatus);
2813 }
2814
2815 /*
2816  * Kick off a subshell to evaluate a tree.
2817  */
2818
2819 static void evalsubshell(const union node *n, int flags)
2820 {
2821         struct job *jp;
2822         int backgnd = (n->type == NBACKGND);
2823
2824         expredir(n->nredir.redirect);
2825         jp = makejob(n, 1);
2826         if (forkshell(jp, n, backgnd) == 0) {
2827                 if (backgnd)
2828                         flags &= ~EV_TESTED;
2829                 redirect(n->nredir.redirect, 0);
2830                 evaltree(n->nredir.n, flags | EV_EXIT); /* never returns */
2831         }
2832         if (!backgnd) {
2833                 INTOFF;
2834                 exitstatus = waitforjob(jp);
2835                 INTON;
2836         }
2837 }
2838
2839 /*
2840  * Compute the names of the files in a redirection list.
2841  */
2842
2843 static void fixredir(union node *n, const char *text, int err);
2844
2845 static void expredir(union node *n)
2846 {
2847         union node *redir;
2848
2849         for (redir = n; redir; redir = redir->nfile.next) {
2850                 struct arglist fn;
2851
2852                 fn.lastp = &fn.list;
2853                 oexitstatus = exitstatus;
2854                 switch (redir->type) {
2855                 case NFROMTO:
2856                 case NFROM:
2857                 case NTO:
2858                 case NAPPEND:
2859                 case NTOOV:
2860                         expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
2861                         redir->nfile.expfname = fn.list->text;
2862                         break;
2863                 case NFROMFD:
2864                 case NTOFD:
2865                         if (redir->ndup.vname) {
2866                                 expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE);
2867                                 fixredir(redir, fn.list->text, 1);
2868                         }
2869                         break;
2870                 }
2871         }
2872 }
2873
2874
2875 /*
2876  * Execute a command inside back quotes.  If it's a builtin command, we
2877  * want to save its output in a block obtained from malloc.  Otherwise
2878  * we fork off a subprocess and get the output of the command via a pipe.
2879  * Should be called with interrupts off.
2880  */
2881
2882 static void evalbackcmd(union node *n, struct backcmd *result)
2883 {
2884         int pip[2];
2885         struct job *jp;
2886         struct stackmark smark; /* unnecessary */
2887
2888         setstackmark(&smark);
2889         result->fd = -1;
2890         result->buf = NULL;
2891         result->nleft = 0;
2892         result->jp = NULL;
2893         if (n == NULL) {
2894                 exitstatus = 0;
2895                 goto out;
2896         }
2897         exitstatus = 0;
2898         if (pipe(pip) < 0)
2899                 error("Pipe call failed");
2900         jp = makejob(n, 1);
2901         if (forkshell(jp, n, FORK_NOJOB) == 0) {
2902                 FORCEINTON;
2903                 close(pip[0]);
2904                 if (pip[1] != 1) {
2905                         close(1);
2906                         dup_as_newfd(pip[1], 1);
2907                         close(pip[1]);
2908                 }
2909                 eflag = 0;
2910                 evaltree(n, EV_EXIT);
2911         }
2912         close(pip[1]);
2913         result->fd = pip[0];
2914         result->jp = jp;
2915   out:
2916         popstackmark(&smark);
2917         TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n",
2918                    result->fd, result->buf, result->nleft, result->jp));
2919 }
2920
2921
2922 /*
2923  * Execute a simple command.
2924  */
2925
2926
2927 /*
2928  * Builtin commands.  Builtin commands whose functions are closely
2929  * tied to evaluation are implemented here.
2930  */
2931
2932 /*
2933  * No command given, or a bltin command with no arguments.  Set the
2934  * specified variables.
2935  */
2936
2937 int bltincmd(int argc, char **argv)
2938 {
2939         /*
2940          * Preserve exitstatus of a previous possible redirection
2941          * as POSIX mandates
2942          */
2943         return exitstatus;
2944 }
2945
2946
2947 /*
2948  * Handle break and continue commands.  Break, continue, and return are
2949  * all handled by setting the evalskip flag.  The evaluation routines
2950  * above all check this flag, and if it is set they start skipping
2951  * commands rather than executing them.  The variable skipcount is
2952  * the number of loops to break/continue, or the number of function
2953  * levels to return.  (The latter is always 1.)  It should probably
2954  * be an error to break out of more loops than exist, but it isn't
2955  * in the standard shell so we don't make it one here.
2956  */
2957
2958 static int breakcmd(int argc, char **argv)
2959 {
2960         int n = argc > 1 ? number(argv[1]) : 1;
2961
2962         if (n <= 0)
2963                 error("Illegal number: %s", argv[1]);
2964         if (n > loopnest)
2965                 n = loopnest;
2966         if (n > 0) {
2967                 evalskip = (**argv == 'c') ? SKIPCONT : SKIPBREAK;
2968                 skipcount = n;
2969         }
2970         return 0;
2971 }
2972
2973
2974 /*
2975  * The return command.
2976  */
2977
2978 static int returncmd(int argc, char **argv)
2979 {
2980         int ret = argc > 1 ? number(argv[1]) : oexitstatus;
2981
2982         if (funcnest) {
2983                 evalskip = SKIPFUNC;
2984                 skipcount = 1;
2985                 return ret;
2986         } else {
2987                 /* Do what ksh does; skip the rest of the file */
2988                 evalskip = SKIPFILE;
2989                 skipcount = 1;
2990                 return ret;
2991         }
2992 }
2993
2994
2995 #ifndef CONFIG_FALSE
2996 static int false_main(int argc, char **argv)
2997 {
2998         return 1;
2999 }
3000 #endif
3001
3002 #ifndef CONFIG_TRUE
3003 static int true_main(int argc, char **argv)
3004 {
3005         return 0;
3006 }
3007 #endif
3008
3009 /*
3010  * Controls whether the shell is interactive or not.
3011  */
3012
3013 static void setsignal(int signo);
3014
3015 #ifdef CONFIG_ASH_MAIL
3016 static void chkmail(int silent);
3017 #endif
3018
3019 static void setinteractive(int on)
3020 {
3021         static int is_interactive;
3022         static int do_banner = 0;
3023
3024         if (on == is_interactive)
3025                 return;
3026         setsignal(SIGINT);
3027         setsignal(SIGQUIT);
3028         setsignal(SIGTERM);
3029 #ifdef CONFIG_ASH_MAIL
3030         chkmail(1);
3031 #endif
3032         is_interactive = on;
3033         if (do_banner == 0 && is_interactive) {
3034                 /* Looks like they want an interactive shell */
3035 #ifndef CONFIG_FEATURE_SH_EXTRA_QUIET
3036                 printf("\n\n" BB_BANNER " Built-in shell (ash)\n");
3037                 printf("Enter 'help' for a list of built-in commands.\n\n");
3038 #endif
3039                 do_banner = 1;
3040         }
3041 }
3042
3043 static void optschanged(void)
3044 {
3045         setinteractive(iflag);
3046         setjobctl(mflag);
3047 }
3048
3049
3050 static int execcmd(int argc, char **argv)
3051 {
3052         if (argc > 1) {
3053                 struct strlist *sp;
3054
3055                 iflag = 0;              /* exit on error */
3056                 mflag = 0;
3057                 optschanged();
3058                 for (sp = cmdenviron; sp; sp = sp->next)
3059                         setvareq(sp->text, VEXPORT | VSTACK);
3060                 shellexec(argv + 1, environment(), pathval(), 0);
3061         }
3062         return 0;
3063 }
3064
3065 static void eprintlist(struct strlist *sp)
3066 {
3067         for (; sp; sp = sp->next) {
3068                 out2fmt(" %s", sp->text);
3069         }
3070 }
3071
3072 /*
3073  * Exec a program.  Never returns.  If you change this routine, you may
3074  * have to change the find_command routine as well.
3075  */
3076
3077 static const char *pathopt;     /* set by padvance */
3078
3079 static void shellexec(char **argv, char **envp, const char *path, int idx)
3080 {
3081         char *cmdname;
3082         int e;
3083
3084         if (strchr(argv[0], '/') != NULL) {
3085                 tryexec(argv[0], argv, envp);
3086                 e = errno;
3087         } else {
3088                 e = ENOENT;
3089                 while ((cmdname = padvance(&path, argv[0])) != NULL) {
3090                         if (--idx < 0 && pathopt == NULL) {
3091                                 tryexec(cmdname, argv, envp);
3092                                 if (errno != ENOENT && errno != ENOTDIR)
3093                                         e = errno;
3094                         }
3095                         stunalloc(cmdname);
3096                 }
3097         }
3098
3099         /* Map to POSIX errors */
3100         switch (e) {
3101         case EACCES:
3102                 exerrno = 126;
3103                 break;
3104         case ENOENT:
3105                 exerrno = 127;
3106                 break;
3107         default:
3108                 exerrno = 2;
3109                 break;
3110         }
3111         exerror(EXEXEC, "%s: %s", argv[0], errmsg(e, E_EXEC));
3112         /* NOTREACHED */
3113 }
3114
3115 /*
3116  * Clear traps on a fork.
3117  */
3118 static void clear_traps(void)
3119 {
3120         char **tp;
3121
3122         for (tp = trap; tp < &trap[NSIG]; tp++) {
3123                 if (*tp && **tp) {      /* trap not NULL or SIG_IGN */
3124                         INTOFF;
3125                         free(*tp);
3126                         *tp = NULL;
3127                         if (tp != &trap[0])
3128                                 setsignal(tp - trap);
3129                         INTON;
3130                 }
3131         }
3132 }
3133
3134
3135 static void initshellproc(void)
3136 {
3137
3138 #ifdef CONFIG_ASH_ALIAS
3139         /* from alias.c: */
3140         {
3141                 rmaliases();
3142         }
3143 #endif
3144         /* from eval.c: */
3145         {
3146                 exitstatus = 0;
3147         }
3148
3149         /* from exec.c: */
3150         {
3151                 deletefuncs();
3152         }
3153
3154         /* from jobs.c: */
3155         {
3156                 backgndpid = -1;
3157 #ifdef CONFIG_ASH_JOB_CONTROL
3158                 jobctl = 0;
3159 #endif
3160         }
3161
3162         /* from options.c: */
3163         {
3164                 int i;
3165
3166                 for (i = 0; i < NOPTS; i++)
3167                         optent_val(i) = 0;
3168                 optschanged();
3169
3170         }
3171
3172         /* from redir.c: */
3173         {
3174                 clearredir();
3175         }
3176
3177         /* from trap.c: */
3178         {
3179                 char *sm;
3180
3181                 clear_traps();
3182                 for (sm = sigmode; sm < sigmode + NSIG - 1; sm++) {
3183                         if (*sm == S_IGN)
3184                                 *sm = S_HARD_IGN;
3185                 }
3186         }
3187
3188         /* from var.c: */
3189         {
3190                 shprocvar();
3191         }
3192 }
3193
3194 static int preadbuffer(void);
3195 static void pushfile(void);
3196
3197 /*
3198  * Read a character from the script, returning PEOF on end of file.
3199  * Nul characters in the input are silently discarded.
3200  */
3201
3202 #ifndef CONFIG_ASH_OPTIMIZE_FOR_SIZE
3203 #define pgetc_macro()   (--parsenleft >= 0? *parsenextc++ : preadbuffer())
3204 static int pgetc(void)
3205 {
3206         return pgetc_macro();
3207 }
3208 #else
3209 static int pgetc_macro(void)
3210 {
3211         return --parsenleft >= 0 ? *parsenextc++ : preadbuffer();
3212 }
3213
3214 static inline int pgetc(void)
3215 {
3216         return pgetc_macro();
3217 }
3218 #endif
3219
3220
3221 /*
3222  * Undo the last call to pgetc.  Only one character may be pushed back.
3223  * PEOF may be pushed back.
3224  */
3225
3226 static void pungetc(void)
3227 {
3228         parsenleft++;
3229         parsenextc--;
3230 }
3231
3232
3233 static void popfile(void)
3234 {
3235         struct parsefile *pf = parsefile;
3236
3237         INTOFF;
3238         if (pf->fd >= 0)
3239                 close(pf->fd);
3240         free(pf->buf);
3241         while (pf->strpush)
3242                 popstring();
3243         parsefile = pf->prev;
3244         free(pf);
3245         parsenleft = parsefile->nleft;
3246         parselleft = parsefile->lleft;
3247         parsenextc = parsefile->nextc;
3248         plinno = parsefile->linno;
3249         INTON;
3250 }
3251
3252
3253 /*
3254  * Return to top level.
3255  */
3256
3257 static void popallfiles(void)
3258 {
3259         while (parsefile != &basepf)
3260                 popfile();
3261 }
3262
3263 /*
3264  * Close the file(s) that the shell is reading commands from.  Called
3265  * after a fork is done.
3266  */
3267
3268 static void closescript(void)
3269 {
3270         popallfiles();
3271         if (parsefile->fd > 0) {
3272                 close(parsefile->fd);
3273                 parsefile->fd = 0;
3274         }
3275 }
3276
3277
3278 /*
3279  * Like setinputfile, but takes an open file descriptor.  Call this with
3280  * interrupts off.
3281  */
3282
3283 static void setinputfd(int fd, int push)
3284 {
3285         (void) fcntl(fd, F_SETFD, FD_CLOEXEC);
3286         if (push) {
3287                 pushfile();
3288                 parsefile->buf = 0;
3289         } else {
3290                 closescript();
3291                 while (parsefile->strpush)
3292                         popstring();
3293         }
3294         parsefile->fd = fd;
3295         if (parsefile->buf == NULL)
3296                 parsefile->buf = xmalloc(BUFSIZ);
3297         parselleft = parsenleft = 0;
3298         plinno = 1;
3299 }
3300
3301
3302 /*
3303  * Set the input to take input from a file.  If push is set, push the
3304  * old input onto the stack first.
3305  */
3306
3307 static void setinputfile(const char *fname, int push)
3308 {
3309         int fd;
3310         int myfileno2;
3311
3312         INTOFF;
3313         if ((fd = open(fname, O_RDONLY)) < 0)
3314                 error("Can't open %s", fname);
3315         if (fd < 10) {
3316                 myfileno2 = dup_as_newfd(fd, 10);
3317                 close(fd);
3318                 if (myfileno2 < 0)
3319                         error("Out of file descriptors");
3320                 fd = myfileno2;
3321         }
3322         setinputfd(fd, push);
3323         INTON;
3324 }
3325
3326
3327 static void tryexec(char *cmd, char **argv, char **envp)
3328 {
3329         int e;
3330
3331 #ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL
3332         char *name = cmd;
3333         char **argv_l = argv;
3334         int argc_l;
3335
3336 #ifdef CONFIG_FEATURE_SH_APPLETS_ALWAYS_WIN
3337         name = get_last_path_component(name);
3338 #endif
3339         argv_l = envp;
3340         for (argc_l = 0; *argv_l != NULL; argv_l++, argc_l++)
3341                 putenv(*argv_l);
3342         argv_l = argv;
3343         for (argc_l = 0; *argv_l != NULL; argv_l++, argc_l++)
3344                 optind = 1;
3345         run_applet_by_name(name, argc_l, argv);
3346 #endif
3347         execve(cmd, argv, envp);
3348         e = errno;
3349         if (e == ENOEXEC) {
3350                 INTOFF;
3351                 initshellproc();
3352                 setinputfile(cmd, 0);
3353                 commandname = arg0 = xstrdup(argv[0]);
3354                 setparam(argv + 1);
3355                 exraise(EXSHELLPROC);
3356         }
3357         errno = e;
3358 }
3359
3360 static char *commandtext(const union node *);
3361
3362 /*
3363  * Do a path search.  The variable path (passed by reference) should be
3364  * set to the start of the path before the first call; padvance will update
3365  * this value as it proceeds.  Successive calls to padvance will return
3366  * the possible path expansions in sequence.  If an option (indicated by
3367  * a percent sign) appears in the path entry then the global variable
3368  * pathopt will be set to point to it; otherwise pathopt will be set to
3369  * NULL.
3370  */
3371
3372 static const char *pathopt;
3373
3374 static void growstackblock(void);
3375
3376
3377 static char *padvance(const char **path, const char *name)
3378 {
3379         const char *p;
3380         char *q;
3381         const char *start;
3382         int len;
3383
3384         if (*path == NULL)
3385                 return NULL;
3386         start = *path;
3387         for (p = start; *p && *p != ':' && *p != '%'; p++);
3388         len = p - start + strlen(name) + 2;     /* "2" is for '/' and '\0' */
3389         while (stackblocksize() < len)
3390                 growstackblock();
3391         q = stackblock();
3392         if (p != start) {
3393                 memcpy(q, start, p - start);
3394                 q += p - start;
3395                 *q++ = '/';
3396         }
3397         strcpy(q, name);
3398         pathopt = NULL;
3399         if (*p == '%') {
3400                 pathopt = ++p;
3401                 while (*p && *p != ':')
3402                         p++;
3403         }
3404         if (*p == ':')
3405                 *path = p + 1;
3406         else
3407                 *path = NULL;
3408         return stalloc(len);
3409 }
3410
3411 /*
3412  * Wrapper around strcmp for qsort/bsearch/...
3413  */
3414 static int pstrcmp(const void *a, const void *b)
3415 {
3416         return strcmp((const char *) a, (*(const char *const *) b) + 1);
3417 }
3418
3419 /*
3420  * Find a keyword is in a sorted array.
3421  */
3422
3423 static const char *const *findkwd(const char *s)
3424 {
3425         return bsearch(s, tokname_array + KWDOFFSET,
3426                                    (sizeof(tokname_array) / sizeof(const char *)) - KWDOFFSET,
3427                                    sizeof(const char *), pstrcmp);
3428 }
3429
3430
3431 /*** Command hashing code ***/
3432
3433
3434 static int hashcmd(int argc, char **argv)
3435 {
3436         struct tblentry **pp;
3437         struct tblentry *cmdp;
3438         int c;
3439         int verbose;
3440         struct cmdentry entry;
3441         char *name;
3442
3443 #ifdef CONFIG_ASH_ALIAS
3444         const struct alias *ap;
3445 #endif
3446
3447         verbose = 0;
3448         while ((c = nextopt("rvV")) != '\0') {
3449                 if (c == 'r') {
3450                         clearcmdentry(0);
3451                         return 0;
3452                 } else if (c == 'v' || c == 'V') {
3453                         verbose = c;
3454                 }
3455         }
3456         if (*argptr == NULL) {
3457                 for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
3458                         for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
3459                                 if (cmdp->cmdtype != CMDBUILTIN) {
3460                                         printentry(cmdp, verbose);
3461                                 }
3462                         }
3463                 }
3464                 return 0;
3465         }
3466         c = 0;
3467         while ((name = *argptr++) != NULL) {
3468                 if ((cmdp = cmdlookup(name, 0)) != NULL
3469                         && (cmdp->cmdtype == CMDNORMAL
3470                                 || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0)))
3471                         delete_cmd_entry();
3472 #ifdef CONFIG_ASH_ALIAS
3473                 /* Then look at the aliases */
3474                 if ((ap = *__lookupalias(name)) != NULL) {
3475                         if (verbose == 'v')
3476                                 printf("%s is an alias for %s\n", name, ap->val);
3477                         else
3478                                 printalias(ap);
3479                         continue;
3480                 }
3481 #endif
3482                 /* First look at the keywords */
3483                 if (findkwd(name) != 0) {
3484                         if (verbose == 'v')
3485                                 printf("%s is a shell keyword\n", name);
3486                         else
3487                                 puts(name);
3488                         continue;
3489                 }
3490
3491                 find_command(name, &entry, DO_ERR, pathval());
3492                 if (entry.cmdtype == CMDUNKNOWN)
3493                         c = 1;
3494                 else if (verbose) {
3495                         cmdp = cmdlookup(name, 0);
3496                         if (cmdp)
3497                                 printentry(cmdp, verbose == 'v');
3498                         flushall();
3499                 }
3500         }
3501         return c;
3502 }
3503
3504 static void printentry(struct tblentry *cmdp, int verbose)
3505 {
3506         int idx;
3507         const char *path;
3508         char *name;
3509
3510         printf("%s%s", cmdp->cmdname, (verbose ? " is " : ""));
3511         if (cmdp->cmdtype == CMDNORMAL) {
3512                 idx = cmdp->param.index;
3513                 path = pathval();
3514                 do {
3515                         name = padvance(&path, cmdp->cmdname);
3516                         stunalloc(name);
3517                 } while (--idx >= 0);
3518                 if (verbose)
3519                         out1str(name);
3520         } else if (cmdp->cmdtype == CMDBUILTIN) {
3521                 if (verbose)
3522                         out1str("a shell builtin");
3523         } else if (cmdp->cmdtype == CMDFUNCTION) {
3524                 if (verbose) {
3525                         INTOFF;
3526                         out1str("a function\n");
3527                         name = commandtext(cmdp->param.func);
3528                         printf("%s() {\n %s\n}", cmdp->cmdname, name);
3529                         free(name);
3530                         INTON;
3531                 }
3532 #ifdef DEBUG
3533         } else {
3534                 error("internal error: cmdtype %d", cmdp->cmdtype);
3535 #endif
3536         }
3537         puts(cmdp->rehash ? "*" : nullstr);
3538 }
3539
3540
3541
3542 /*** List the available builtins ***/
3543
3544
3545 static int helpcmd(int argc, char **argv)
3546 {
3547         int col, i;
3548
3549         printf("\nBuilt-in commands:\n-------------------\n");
3550         for (col = 0, i = 0; i < NUMBUILTINS; i++) {
3551                 col += printf("%c%s", ((col == 0) ? '\t' : ' '),
3552                                           builtincmds[i].name + 1);
3553                 if (col > 60) {
3554                         printf("\n");
3555                         col = 0;
3556                 }
3557         }
3558 #ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL
3559         {
3560                 extern const struct BB_applet applets[];
3561                 extern const size_t NUM_APPLETS;
3562
3563                 for (i = 0; i < NUM_APPLETS; i++) {
3564
3565                         col += printf("%c%s", ((col == 0) ? '\t' : ' '), applets[i].name);
3566                         if (col > 60) {
3567                                 printf("\n");
3568                                 col = 0;
3569                         }
3570                 }
3571         }
3572 #endif
3573         printf("\n\n");
3574         return EXIT_SUCCESS;
3575 }
3576
3577 /*
3578  * Resolve a command name.  If you change this routine, you may have to
3579  * change the shellexec routine as well.
3580  */
3581
3582 static int prefix(const char *, const char *);
3583
3584 static void
3585 find_command(const char *name, struct cmdentry *entry, int act,
3586                          const char *path)
3587 {
3588         struct tblentry *cmdp;
3589         int idx;
3590         int prev;
3591         char *fullname;
3592         struct stat statb;
3593         int e;
3594         int bltin;
3595         int firstchange;
3596         int updatetbl;
3597         int regular;
3598         struct builtincmd *bcmd;
3599
3600         /* If name contains a slash, don't use the hash table */
3601         if (strchr(name, '/') != NULL) {
3602                 if (act & DO_ABS) {
3603                         while (stat(name, &statb) < 0) {
3604                                 if (errno != ENOENT && errno != ENOTDIR)
3605                                         e = errno;
3606                                 entry->cmdtype = CMDUNKNOWN;
3607                                 entry->u.index = -1;
3608                                 return;
3609                         }
3610                         entry->cmdtype = CMDNORMAL;
3611                         entry->u.index = -1;
3612                         return;
3613                 }
3614                 entry->cmdtype = CMDNORMAL;
3615                 entry->u.index = 0;
3616                 return;
3617         }
3618
3619         updatetbl = 1;
3620         if (act & DO_BRUTE) {
3621                 firstchange = path_change(path, &bltin);
3622         } else {
3623                 bltin = builtinloc;
3624                 firstchange = 9999;
3625         }
3626
3627         /* If name is in the table, and not invalidated by cd, we're done */
3628         if ((cmdp = cmdlookup(name, 0)) != NULL && cmdp->rehash == 0) {
3629                 if (cmdp->cmdtype == CMDFUNCTION) {
3630                         if (act & DO_NOFUN) {
3631                                 updatetbl = 0;
3632                         } else {
3633                                 goto success;
3634                         }
3635                 } else if (act & DO_BRUTE) {
3636                         if ((cmdp->cmdtype == CMDNORMAL &&
3637                                  cmdp->param.index >= firstchange) ||
3638                                 (cmdp->cmdtype == CMDBUILTIN &&
3639                                  ((builtinloc < 0 && bltin >= 0) ?
3640                                   bltin : builtinloc) >= firstchange)) {
3641                                 /* need to recompute the entry */
3642                         } else {
3643                                 goto success;
3644                         }
3645                 } else {
3646                         goto success;
3647                 }
3648         }
3649
3650         bcmd = find_builtin(name);
3651         regular = bcmd && IS_BUILTIN_REGULAR(bcmd);
3652
3653         if (regular) {
3654                 if (cmdp && (cmdp->cmdtype == CMDBUILTIN)) {
3655                         goto success;
3656                 }
3657         } else if (act & DO_BRUTE) {
3658                 if (firstchange == 0) {
3659                         updatetbl = 0;
3660                 }
3661         }
3662
3663         /* If %builtin not in path, check for builtin next */
3664         if (regular || (bltin < 0 && bcmd)) {
3665           builtin:
3666                 if (!updatetbl) {
3667                         entry->cmdtype = CMDBUILTIN;
3668                         entry->u.cmd = bcmd;
3669                         return;
3670                 }
3671                 INTOFF;
3672                 cmdp = cmdlookup(name, 1);
3673                 cmdp->cmdtype = CMDBUILTIN;
3674                 cmdp->param.cmd = bcmd;
3675                 INTON;
3676                 goto success;
3677         }
3678
3679         /* We have to search path. */
3680         prev = -1;                      /* where to start */
3681         if (cmdp && cmdp->rehash) {     /* doing a rehash */
3682                 if (cmdp->cmdtype == CMDBUILTIN)
3683                         prev = builtinloc;
3684                 else
3685                         prev = cmdp->param.index;
3686         }
3687
3688         e = ENOENT;
3689         idx = -1;
3690   loop:
3691         while ((fullname = padvance(&path, name)) != NULL) {
3692                 stunalloc(fullname);
3693                 idx++;
3694                 if (idx >= firstchange) {
3695                         updatetbl = 0;
3696                 }
3697                 if (pathopt) {
3698                         if (prefix("builtin", pathopt)) {
3699                                 if ((bcmd = find_builtin(name))) {
3700                                         goto builtin;
3701                                 }
3702                                 continue;
3703                         } else if (!(act & DO_NOFUN) && prefix("func", pathopt)) {
3704                                 /* handled below */
3705                         } else {
3706                                 continue;       /* ignore unimplemented options */
3707                         }
3708                 }
3709                 /* if rehash, don't redo absolute path names */
3710                 if (fullname[0] == '/' && idx <= prev && idx < firstchange) {
3711                         if (idx < prev)
3712                                 continue;
3713                         TRACE(("searchexec \"%s\": no change\n", name));
3714                         goto success;
3715                 }
3716                 while (stat(fullname, &statb) < 0) {
3717                         if (errno != ENOENT && errno != ENOTDIR)
3718                                 e = errno;
3719                         goto loop;
3720                 }
3721                 e = EACCES;             /* if we fail, this will be the error */
3722                 if (!S_ISREG(statb.st_mode))
3723                         continue;
3724                 if (pathopt) {  /* this is a %func directory */
3725                         stalloc(strlen(fullname) + 1);
3726                         readcmdfile(fullname);
3727                         if ((cmdp = cmdlookup(name, 0)) == NULL
3728                                 || cmdp->cmdtype != CMDFUNCTION)
3729                                 error("%s not defined in %s", name, fullname);
3730                         stunalloc(fullname);
3731                         goto success;
3732                 }
3733                 TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
3734                 /* If we aren't called with DO_BRUTE and cmdp is set, it must
3735                    be a function and we're being called with DO_NOFUN */
3736                 if (!updatetbl) {
3737                         entry->cmdtype = CMDNORMAL;
3738                         entry->u.index = idx;
3739                         return;
3740                 }
3741                 INTOFF;
3742                 cmdp = cmdlookup(name, 1);
3743                 cmdp->cmdtype = CMDNORMAL;
3744                 cmdp->param.index = idx;
3745                 INTON;
3746                 goto success;
3747         }
3748
3749         /* We failed.  If there was an entry for this command, delete it */
3750         if (cmdp && updatetbl)
3751                 delete_cmd_entry();
3752         if (act & DO_ERR)
3753                 out2fmt("%s: %s\n", name, errmsg(e, E_EXEC));
3754         entry->cmdtype = CMDUNKNOWN;
3755         return;
3756
3757   success:
3758         cmdp->rehash = 0;
3759         entry->cmdtype = cmdp->cmdtype;
3760         entry->u = cmdp->param;
3761 }
3762
3763
3764
3765 /*
3766  * Search the table of builtin commands.
3767  */
3768
3769 static int bstrcmp(const void *name, const void *b)
3770 {
3771         return strcmp((const char *) name, (*(const char *const *) b) + 1);
3772 }
3773
3774 static struct builtincmd *find_builtin(const char *name)
3775 {
3776         struct builtincmd *bp;
3777
3778         bp = bsearch(name, builtincmds, NUMBUILTINS, sizeof(struct builtincmd),
3779                                  bstrcmp);
3780         return bp;
3781 }
3782
3783
3784 /*
3785  * Called when a cd is done.  Marks all commands so the next time they
3786  * are executed they will be rehashed.
3787  */
3788
3789 static inline void hashcd(void)
3790 {
3791         struct tblentry **pp;
3792         struct tblentry *cmdp;
3793
3794         for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
3795                 for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
3796                         if (cmdp->cmdtype == CMDNORMAL
3797                                 || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0))
3798                                 cmdp->rehash = 1;
3799                 }
3800         }
3801 }
3802
3803
3804
3805 /*
3806  * Called before PATH is changed.  The argument is the new value of PATH;
3807  * pathval() still returns the old value at this point.  Called with
3808  * interrupts off.
3809  */
3810
3811 static void changepath(const char *newval)
3812 {
3813         int firstchange;
3814         int bltin;
3815
3816         firstchange = path_change(newval, &bltin);
3817         if (builtinloc < 0 && bltin >= 0)
3818                 builtinloc = bltin;     /* zap builtins */
3819         clearcmdentry(firstchange);
3820         builtinloc = bltin;
3821         /* Ensure that getenv("PATH") stays current */
3822         setenv("PATH", newval, 1);
3823 }
3824
3825
3826 /*
3827  * Clear out command entries.  The argument specifies the first entry in
3828  * PATH which has changed.
3829  */
3830
3831 static void clearcmdentry(int firstchange)
3832 {
3833         struct tblentry **tblp;
3834         struct tblentry **pp;
3835         struct tblentry *cmdp;
3836
3837         INTOFF;
3838         for (tblp = cmdtable; tblp < &cmdtable[CMDTABLESIZE]; tblp++) {
3839                 pp = tblp;
3840                 while ((cmdp = *pp) != NULL) {
3841                         if ((cmdp->cmdtype == CMDNORMAL &&
3842                                  cmdp->param.index >= firstchange)
3843                                 || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= firstchange)) {
3844                                 *pp = cmdp->next;
3845                                 free(cmdp);
3846                         } else {
3847                                 pp = &cmdp->next;
3848                         }
3849                 }
3850         }
3851         INTON;
3852 }
3853
3854
3855 /*
3856  * Delete all functions.
3857  */
3858
3859 static void deletefuncs(void)
3860 {
3861         struct tblentry **tblp;
3862         struct tblentry **pp;
3863         struct tblentry *cmdp;
3864
3865         INTOFF;
3866         for (tblp = cmdtable; tblp < &cmdtable[CMDTABLESIZE]; tblp++) {
3867                 pp = tblp;
3868                 while ((cmdp = *pp) != NULL) {
3869                         if (cmdp->cmdtype == CMDFUNCTION) {
3870                                 *pp = cmdp->next;
3871                                 free(cmdp->param.func);
3872                                 free(cmdp);
3873                         } else {
3874                                 pp = &cmdp->next;
3875                         }
3876                 }
3877         }
3878         INTON;
3879 }
3880
3881
3882
3883 /*
3884  * Locate a command in the command hash table.  If "add" is nonzero,
3885  * add the command to the table if it is not already present.  The
3886  * variable "lastcmdentry" is set to point to the address of the link
3887  * pointing to the entry, so that delete_cmd_entry can delete the
3888  * entry.
3889  */
3890
3891 static struct tblentry **lastcmdentry;
3892
3893 static struct tblentry *cmdlookup(const char *name, int add)
3894 {
3895         int hashval;
3896         const char *p;
3897         struct tblentry *cmdp;
3898         struct tblentry **pp;
3899
3900         p = name;
3901         hashval = *p << 4;
3902         while (*p)
3903                 hashval += *p++;
3904         hashval &= 0x7FFF;
3905         pp = &cmdtable[hashval % CMDTABLESIZE];
3906         for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
3907                 if (equal(cmdp->cmdname, name))
3908                         break;
3909                 pp = &cmdp->next;
3910         }
3911         if (add && cmdp == NULL) {
3912                 INTOFF;
3913                 cmdp = *pp = xmalloc(sizeof(struct tblentry) - ARB
3914                                                          + strlen(name) + 1);
3915                 cmdp->next = NULL;
3916                 cmdp->cmdtype = CMDUNKNOWN;
3917                 cmdp->rehash = 0;
3918                 strcpy(cmdp->cmdname, name);
3919                 INTON;
3920         }
3921         lastcmdentry = pp;
3922         return cmdp;
3923 }
3924
3925 /*
3926  * Delete the command entry returned on the last lookup.
3927  */
3928
3929 static void delete_cmd_entry()
3930 {
3931         struct tblentry *cmdp;
3932
3933         INTOFF;
3934         cmdp = *lastcmdentry;
3935         *lastcmdentry = cmdp->next;
3936         free(cmdp);
3937         INTON;
3938 }
3939
3940
3941
3942
3943
3944 static const unsigned char nodesize[26] = {
3945         ALIGN(sizeof(struct nbinary)),
3946         ALIGN(sizeof(struct ncmd)),
3947         ALIGN(sizeof(struct npipe)),
3948         ALIGN(sizeof(struct nredir)),
3949         ALIGN(sizeof(struct nredir)),
3950         ALIGN(sizeof(struct nredir)),
3951         ALIGN(sizeof(struct nbinary)),
3952         ALIGN(sizeof(struct nbinary)),
3953         ALIGN(sizeof(struct nif)),
3954         ALIGN(sizeof(struct nbinary)),
3955         ALIGN(sizeof(struct nbinary)),
3956         ALIGN(sizeof(struct nfor)),
3957         ALIGN(sizeof(struct ncase)),
3958         ALIGN(sizeof(struct nclist)),
3959         ALIGN(sizeof(struct narg)),
3960         ALIGN(sizeof(struct narg)),
3961         ALIGN(sizeof(struct nfile)),
3962         ALIGN(sizeof(struct nfile)),
3963         ALIGN(sizeof(struct nfile)),
3964         ALIGN(sizeof(struct nfile)),
3965         ALIGN(sizeof(struct nfile)),
3966         ALIGN(sizeof(struct ndup)),
3967         ALIGN(sizeof(struct ndup)),
3968         ALIGN(sizeof(struct nhere)),
3969         ALIGN(sizeof(struct nhere)),
3970         ALIGN(sizeof(struct nnot)),
3971 };
3972
3973
3974
3975 /*
3976  * Delete a function if it exists.
3977  */
3978
3979 static void unsetfunc(char *name)
3980 {
3981         struct tblentry *cmdp;
3982
3983         if ((cmdp = cmdlookup(name, 0)) != NULL && cmdp->cmdtype == CMDFUNCTION) {
3984                 free(cmdp->param.func);
3985                 delete_cmd_entry();
3986         }
3987 }
3988
3989
3990 /*
3991  * Locate and print what a word is...
3992  */
3993
3994 static int typecmd(int argc, char **argv)
3995 {
3996         int i;
3997         int err = 0;
3998         char *argv_a[2];
3999
4000         argv_a[1] = 0;
4001
4002         for (i = 1; i < argc; i++) {
4003                 argv_a[0] = argv[i];
4004                 argptr = argv_a;
4005                 optptr = "v";
4006                 err |= hashcmd(argc, argv);
4007         }
4008         return err;
4009 }
4010
4011 #ifdef CONFIG_ASH_CMDCMD
4012 static int commandcmd(int argc, char **argv)
4013 {
4014         int c;
4015         int default_path = 0;
4016         int verify_only = 0;
4017         int verbose_verify_only = 0;
4018
4019         while ((c = nextopt("pvV")) != '\0')
4020                 switch (c) {
4021                 case 'p':
4022                         default_path = 1;
4023                         break;
4024                 case 'v':
4025                         verify_only = 1;
4026                         break;
4027                 case 'V':
4028                         verbose_verify_only = 1;
4029                         break;
4030                 }
4031
4032         if (default_path + verify_only + verbose_verify_only > 1 || !*argptr) {
4033                 out2str("command [-p] command [arg ...]\n"
4034                                 "command {-v|-V} command\n");
4035                 return EX_USAGE;
4036         }
4037
4038         if (verify_only || verbose_verify_only) {
4039                 char *argv_a[2];
4040
4041                 argv_a[1] = 0;
4042                 argv_a[0] = *argptr;
4043                 argptr = argv_a;
4044                 optptr = verbose_verify_only ? "v" : "V";       /* reverse special */
4045                 return hashcmd(argc, argv);
4046         }
4047
4048         return 0;
4049 }
4050 #endif
4051
4052 static int path_change(const char *newval, int *bltin)
4053 {
4054         const char *old, *new;
4055         int idx;
4056         int firstchange;
4057
4058         old = pathval();
4059         new = newval;
4060         firstchange = 9999;     /* assume no change */
4061         idx = 0;
4062         *bltin = -1;
4063         for (;;) {
4064                 if (*old != *new) {
4065                         firstchange = idx;
4066                         if ((*old == '\0' && *new == ':')
4067                                 || (*old == ':' && *new == '\0'))
4068                                 firstchange++;
4069                         old = new;      /* ignore subsequent differences */
4070                 }
4071                 if (*new == '\0')
4072                         break;
4073                 if (*new == '%' && *bltin < 0 && prefix("builtin", new + 1))
4074                         *bltin = idx;
4075                 if (*new == ':') {
4076                         idx++;
4077                 }
4078                 new++, old++;
4079         }
4080         if (builtinloc >= 0 && *bltin < 0)
4081                 firstchange = 0;
4082         return firstchange;
4083 }
4084
4085 /*
4086  * Routines to expand arguments to commands.  We have to deal with
4087  * backquotes, shell variables, and file metacharacters.
4088  */
4089 /*
4090  * _rmescape() flags
4091  */
4092 #define RMESCAPE_ALLOC  0x1     /* Allocate a new string */
4093 #define RMESCAPE_GLOB   0x2     /* Add backslashes for glob */
4094
4095 /*
4096  * Structure specifying which parts of the string should be searched
4097  * for IFS characters.
4098  */
4099
4100 struct ifsregion {
4101         struct ifsregion *next; /* next region in list */
4102         int begoff;                     /* offset of start of region */
4103         int endoff;                     /* offset of end of region */
4104         int nulonly;            /* search for nul bytes only */
4105 };
4106
4107
4108 static char *expdest;   /* output of current string */
4109 static struct nodelist *argbackq;       /* list of back quote expressions */
4110 static struct ifsregion ifsfirst;       /* first struct in list of ifs regions */
4111 static struct ifsregion *ifslastp;      /* last struct in list */
4112 static struct arglist exparg;   /* holds expanded arg list */
4113
4114 static void argstr(char *, int);
4115 static char *exptilde(char *, int);
4116 static void expbackq(union node *, int, int);
4117 static int subevalvar(char *, char *, int, int, int, int, int);
4118 static int varisset(char *, int);
4119 static void strtodest(const char *, int, int);
4120 static inline void varvalue(char *, int, int);
4121 static void recordregion(int, int, int);
4122 static void removerecordregions(int);
4123 static void ifsbreakup(char *, struct arglist *);
4124 static void ifsfree(void);
4125 static void expandmeta(struct strlist *, int);
4126
4127 #if defined(__GLIBC__) && __GLIBC__ >= 2 && !defined(FNMATCH_BROKEN)
4128 #define preglob(p) _rmescapes((p), RMESCAPE_ALLOC | RMESCAPE_GLOB)
4129 #if !defined(GLOB_BROKEN)
4130 static inline void addglob(const glob_t *);
4131 #endif
4132 #endif
4133 #if !(defined(__GLIBC__) && __GLIBC__ >= 2 && !defined(FNMATCH_BROKEN) && !defined(GLOB_BROKEN))
4134 static void expmeta(char *, char *);
4135 #endif
4136 #if !(defined(__GLIBC__) && __GLIBC__ >= 2 && !defined(FNMATCH_BROKEN) && !defined(GLOB_BROKEN))
4137 static struct strlist *expsort(struct strlist *);
4138 static struct strlist *msort(struct strlist *, int);
4139 #endif
4140 static int patmatch(char *, char *, int);
4141
4142 #if defined(__GLIBC__) && __GLIBC__ >= 2 && !defined(FNMATCH_BROKEN)
4143 static int patmatch2(char *, char *, int);
4144 #else
4145 static int pmatch(char *, char *, int);
4146
4147 #define patmatch2 patmatch
4148 #endif
4149 static char *cvtnum(int, char *);
4150
4151 /*
4152  * Expand shell variables and backquotes inside a here document.
4153  */
4154
4155 /* arg: the document, fd: where to write the expanded version */
4156 static inline void expandhere(union node *arg, int fd)
4157 {
4158         herefd = fd;
4159         expandarg(arg, (struct arglist *) NULL, 0);
4160         xwrite(fd, stackblock(), expdest - stackblock());
4161 }
4162
4163
4164 /*
4165  * Perform variable substitution and command substitution on an argument,
4166  * placing the resulting list of arguments in arglist.  If EXP_FULL is true,
4167  * perform splitting and file name expansion.  When arglist is NULL, perform
4168  * here document expansion.
4169  */
4170
4171 static void expandarg(union node *arg, struct arglist *arglist, int flag)
4172 {
4173         struct strlist *sp;
4174         char *p;
4175
4176         argbackq = arg->narg.backquote;
4177         STARTSTACKSTR(expdest);
4178         ifsfirst.next = NULL;
4179         ifslastp = NULL;
4180         argstr(arg->narg.text, flag);
4181         if (arglist == NULL) {
4182                 return;                 /* here document expanded */
4183         }
4184         STPUTC('\0', expdest);
4185         p = grabstackstr(expdest);
4186         exparg.lastp = &exparg.list;
4187         /*
4188          * TODO - EXP_REDIR
4189          */
4190         if (flag & EXP_FULL) {
4191                 ifsbreakup(p, &exparg);
4192                 *exparg.lastp = NULL;
4193                 exparg.lastp = &exparg.list;
4194                 expandmeta(exparg.list, flag);
4195         } else {
4196                 if (flag & EXP_REDIR)   /*XXX - for now, just remove escapes */
4197                         rmescapes(p);
4198                 sp = (struct strlist *) stalloc(sizeof(struct strlist));
4199                 sp->text = p;
4200                 *exparg.lastp = sp;
4201                 exparg.lastp = &sp->next;
4202         }
4203         ifsfree();
4204         *exparg.lastp = NULL;
4205         if (exparg.list) {
4206                 *arglist->lastp = exparg.list;
4207                 arglist->lastp = exparg.lastp;
4208         }
4209 }
4210
4211
4212 /*
4213  * Expand a variable, and return a pointer to the next character in the
4214  * input string.
4215  */
4216
4217 static inline char *evalvar(char *p, int flag)
4218 {
4219         int subtype;
4220         int varflags;
4221         char *var;
4222         const char *val;
4223         int patloc;
4224         int c;
4225         int set;
4226         int special;
4227         int startloc;
4228         int varlen;
4229         int easy;
4230         int quotes = flag & (EXP_FULL | EXP_CASE);
4231
4232         varflags = *p++;
4233         subtype = varflags & VSTYPE;
4234         var = p;
4235         special = 0;
4236         if (!is_name(*p))
4237                 special = 1;
4238         p = strchr(p, '=') + 1;
4239   again:                                /* jump here after setting a variable with ${var=text} */
4240         if (special) {
4241                 set = varisset(var, varflags & VSNUL);
4242                 val = NULL;
4243         } else {
4244                 val = lookupvar(var);
4245                 if (val == NULL || ((varflags & VSNUL) && val[0] == '\0')) {
4246                         val = NULL;
4247                         set = 0;
4248                 } else
4249                         set = 1;
4250         }
4251         varlen = 0;
4252         startloc = expdest - stackblock();
4253         if (set && subtype != VSPLUS) {
4254                 /* insert the value of the variable */
4255                 if (special) {
4256                         varvalue(var, varflags & VSQUOTE, flag);
4257                         if (subtype == VSLENGTH) {
4258                                 varlen = expdest - stackblock() - startloc;
4259                                 STADJUST(-varlen, expdest);
4260                         }
4261                 } else {
4262                         if (subtype == VSLENGTH) {
4263                                 varlen = strlen(val);
4264                         } else {
4265                                 strtodest(val,
4266                                                   varflags & VSQUOTE ? DQSYNTAX : BASESYNTAX, quotes);
4267                         }
4268                 }
4269         }
4270
4271         if (subtype == VSPLUS)
4272                 set = !set;
4273
4274         easy = ((varflags & VSQUOTE) == 0 ||
4275                         (*var == '@' && shellparam.nparam != 1));
4276
4277
4278         switch (subtype) {
4279         case VSLENGTH:
4280                 expdest = cvtnum(varlen, expdest);
4281                 goto record;
4282
4283         case VSNORMAL:
4284                 if (!easy)
4285                         break;
4286           record:
4287                 recordregion(startloc, expdest - stackblock(), varflags & VSQUOTE);
4288                 break;
4289
4290         case VSPLUS:
4291         case VSMINUS:
4292                 if (!set) {
4293                         argstr(p, flag);
4294                         break;
4295                 }
4296                 if (easy)
4297                         goto record;
4298                 break;
4299
4300         case VSTRIMLEFT:
4301         case VSTRIMLEFTMAX:
4302         case VSTRIMRIGHT:
4303         case VSTRIMRIGHTMAX:
4304                 if (!set)
4305                         break;
4306                 /*
4307                  * Terminate the string and start recording the pattern
4308                  * right after it
4309                  */
4310                 STPUTC('\0', expdest);
4311                 patloc = expdest - stackblock();
4312                 if (subevalvar(p, NULL, patloc, subtype,
4313                                            startloc, varflags, quotes) == 0) {
4314                         int amount = (expdest - stackblock() - patloc) + 1;
4315
4316                         STADJUST(-amount, expdest);
4317                 }
4318                 /* Remove any recorded regions beyond start of variable */
4319                 removerecordregions(startloc);
4320                 goto record;
4321
4322         case VSASSIGN:
4323         case VSQUESTION:
4324                 if (!set) {
4325                         if (subevalvar(p, var, 0, subtype, startloc, varflags, quotes)) {
4326                                 varflags &= ~VSNUL;
4327                                 /*
4328                                  * Remove any recorded regions beyond
4329                                  * start of variable
4330                                  */
4331                                 removerecordregions(startloc);
4332                                 goto again;
4333                         }
4334                         break;
4335                 }
4336                 if (easy)
4337                         goto record;
4338                 break;
4339
4340 #ifdef DEBUG
4341         default:
4342                 abort();
4343 #endif
4344         }
4345
4346         if (subtype != VSNORMAL) {      /* skip to end of alternative */
4347                 int nesting = 1;
4348
4349                 for (;;) {
4350                         if ((c = *p++) == CTLESC)
4351                                 p++;
4352                         else if (c == CTLBACKQ || c == (CTLBACKQ | CTLQUOTE)) {
4353                                 if (set)
4354                                         argbackq = argbackq->next;
4355                         } else if (c == CTLVAR) {
4356                                 if ((*p++ & VSTYPE) != VSNORMAL)
4357                                         nesting++;
4358                         } else if (c == CTLENDVAR) {
4359                                 if (--nesting == 0)
4360                                         break;
4361                         }
4362                 }
4363         }
4364         return p;
4365 }
4366
4367
4368 /*
4369  * Perform variable and command substitution.  If EXP_FULL is set, output CTLESC
4370  * characters to allow for further processing.  Otherwise treat
4371  * $@ like $* since no splitting will be performed.
4372  */
4373
4374 static void argstr(char *p, int flag)
4375 {
4376         char c;
4377         int quotes = flag & (EXP_FULL | EXP_CASE);      /* do CTLESC */
4378         int firsteq = 1;
4379
4380         if (*p == '~' && (flag & (EXP_TILDE | EXP_VARTILDE)))
4381                 p = exptilde(p, flag);
4382         for (;;) {
4383                 switch (c = *p++) {
4384                 case '\0':
4385                 case CTLENDVAR: /* ??? */
4386                         return;
4387                 case CTLQUOTEMARK:
4388                         /* "$@" syntax adherence hack */
4389                         if (p[0] == CTLVAR && p[2] == '@' && p[3] == '=')
4390                                 break;
4391                         if ((flag & EXP_FULL) != 0)
4392                                 STPUTC(c, expdest);
4393                         break;
4394                 case CTLESC:
4395                         if (quotes)
4396                                 STPUTC(c, expdest);
4397                         c = *p++;
4398                         STPUTC(c, expdest);
4399                         break;
4400                 case CTLVAR:
4401                         p = evalvar(p, flag);
4402                         break;
4403                 case CTLBACKQ:
4404                 case CTLBACKQ | CTLQUOTE:
4405                         expbackq(argbackq->n, c & CTLQUOTE, flag);
4406                         argbackq = argbackq->next;
4407                         break;
4408 #ifdef CONFIG_ASH_MATH_SUPPORT
4409                 case CTLENDARI:
4410                         expari(flag);
4411                         break;
4412 #endif
4413                 case ':':
4414                 case '=':
4415                         /*
4416                          * sort of a hack - expand tildes in variable
4417                          * assignments (after the first '=' and after ':'s).
4418                          */
4419                         STPUTC(c, expdest);
4420                         if (flag & EXP_VARTILDE && *p == '~') {
4421                                 if (c == '=') {
4422                                         if (firsteq)
4423                                                 firsteq = 0;
4424                                         else
4425                                                 break;
4426                                 }
4427                                 p = exptilde(p, flag);
4428                         }
4429                         break;
4430                 default:
4431                         STPUTC(c, expdest);
4432                 }
4433         }
4434         return;
4435 }
4436
4437 static char *exptilde(char *p, int flag)
4438 {
4439         char c, *startp = p;
4440         struct passwd *pw;
4441         const char *home;
4442         int quotes = flag & (EXP_FULL | EXP_CASE);
4443
4444         while ((c = *p) != '\0') {
4445                 switch (c) {
4446                 case CTLESC:
4447                         return (startp);
4448                 case CTLQUOTEMARK:
4449                         return (startp);
4450                 case ':':
4451                         if (flag & EXP_VARTILDE)
4452                                 goto done;
4453                         break;
4454                 case '/':
4455                         goto done;
4456                 }
4457                 p++;
4458         }
4459   done:
4460         *p = '\0';
4461         if (*(startp + 1) == '\0') {
4462                 if ((home = lookupvar("HOME")) == NULL)
4463                         goto lose;
4464         } else {
4465                 if ((pw = getpwnam(startp + 1)) == NULL)
4466                         goto lose;
4467                 home = pw->pw_dir;
4468         }
4469         if (*home == '\0')
4470                 goto lose;
4471         *p = c;
4472         strtodest(home, SQSYNTAX, quotes);
4473         return (p);
4474   lose:
4475         *p = c;
4476         return (startp);
4477 }
4478
4479
4480 static void removerecordregions(int endoff)
4481 {
4482         if (ifslastp == NULL)
4483                 return;
4484
4485         if (ifsfirst.endoff > endoff) {
4486                 while (ifsfirst.next != NULL) {
4487                         struct ifsregion *ifsp;
4488
4489                         INTOFF;
4490                         ifsp = ifsfirst.next->next;
4491                         free(ifsfirst.next);
4492                         ifsfirst.next = ifsp;
4493                         INTON;
4494                 }
4495                 if (ifsfirst.begoff > endoff)
4496                         ifslastp = NULL;
4497                 else {
4498                         ifslastp = &ifsfirst;
4499                         ifsfirst.endoff = endoff;
4500                 }
4501                 return;
4502         }
4503
4504         ifslastp = &ifsfirst;
4505         while (ifslastp->next && ifslastp->next->begoff < endoff)
4506                 ifslastp = ifslastp->next;
4507         while (ifslastp->next != NULL) {
4508                 struct ifsregion *ifsp;
4509
4510                 INTOFF;
4511                 ifsp = ifslastp->next->next;
4512                 free(ifslastp->next);
4513                 ifslastp->next = ifsp;
4514                 INTON;
4515         }
4516         if (ifslastp->endoff > endoff)
4517                 ifslastp->endoff = endoff;
4518 }
4519
4520
4521 #ifdef CONFIG_ASH_MATH_SUPPORT
4522 /*
4523  * Expand arithmetic expression.  Backup to start of expression,
4524  * evaluate, place result in (backed up) result, adjust string position.
4525  */
4526 static void expari(int flag)
4527 {
4528         char *p, *start;
4529         int errcode;
4530         int result;
4531         int begoff;
4532         int quotes = flag & (EXP_FULL | EXP_CASE);
4533         int quoted;
4534
4535         /*      ifsfree(); */
4536
4537         /*
4538          * This routine is slightly over-complicated for
4539          * efficiency.  First we make sure there is
4540          * enough space for the result, which may be bigger
4541          * than the expression if we add exponentation.  Next we
4542          * scan backwards looking for the start of arithmetic.  If the
4543          * next previous character is a CTLESC character, then we
4544          * have to rescan starting from the beginning since CTLESC
4545          * characters have to be processed left to right.
4546          */
4547         CHECKSTRSPACE(10, expdest);
4548         USTPUTC('\0', expdest);
4549         start = stackblock();
4550         p = expdest - 1;
4551         while (*p != CTLARI && p >= start)
4552                 --p;
4553         if (*p != CTLARI)
4554                 error("missing CTLARI (shouldn't happen)");
4555         if (p > start && *(p - 1) == CTLESC)
4556                 for (p = start; *p != CTLARI; p++)
4557                         if (*p == CTLESC)
4558                                 p++;
4559
4560         if (p[1] == '"')
4561                 quoted = 1;
4562         else
4563                 quoted = 0;
4564         begoff = p - start;
4565         removerecordregions(begoff);
4566         if (quotes)
4567                 rmescapes(p + 2);
4568         result = arith(p + 2, &errcode);
4569         if (errcode < 0) {
4570                 if (errcode == -2)
4571                         error("divide by zero");
4572                 else
4573                         error("syntax error: \"%s\"\n", p + 2);
4574         }
4575         snprintf(p, 12, "%d", result);
4576
4577         while (*p++);
4578
4579         if (quoted == 0)
4580                 recordregion(begoff, p - 1 - start, 0);
4581         result = expdest - p + 1;
4582         STADJUST(-result, expdest);
4583 }
4584 #endif
4585
4586 /*
4587  * Expand stuff in backwards quotes.
4588  */
4589
4590 static void expbackq(union node *cmd, int quoted, int flag)
4591 {
4592         volatile struct backcmd in;
4593         int i;
4594         char buf[128];
4595         char *p;
4596         char *dest = expdest;
4597         volatile struct ifsregion saveifs;
4598         struct ifsregion *volatile savelastp;
4599         struct nodelist *volatile saveargbackq;
4600         char lastc;
4601         int startloc = dest - stackblock();
4602         int syntax = quoted ? DQSYNTAX : BASESYNTAX;
4603         volatile int saveherefd;
4604         int quotes = flag & (EXP_FULL | EXP_CASE);
4605         struct jmploc jmploc;
4606         struct jmploc *volatile savehandler;
4607         int ex;
4608
4609 #if __GNUC__
4610         /* Avoid longjmp clobbering */
4611         (void) &dest;
4612         (void) &syntax;
4613 #endif
4614
4615         in.fd = -1;
4616         in.buf = 0;
4617         in.jp = 0;
4618
4619         INTOFF;
4620         saveifs = ifsfirst;
4621         savelastp = ifslastp;
4622         saveargbackq = argbackq;
4623         saveherefd = herefd;
4624         herefd = -1;
4625         if ((ex = setjmp(jmploc.loc))) {
4626                 goto err1;
4627         }
4628         savehandler = handler;
4629         handler = &jmploc;
4630         INTON;
4631         p = grabstackstr(dest);
4632         evalbackcmd(cmd, (struct backcmd *) &in);
4633         ungrabstackstr(p, dest);
4634   err1:
4635         INTOFF;
4636         ifsfirst = saveifs;
4637         ifslastp = savelastp;
4638         argbackq = saveargbackq;
4639         herefd = saveherefd;
4640         if (ex) {
4641                 goto err2;
4642         }
4643
4644         p = in.buf;
4645         lastc = '\0';
4646         for (;;) {
4647                 if (--in.nleft < 0) {
4648                         if (in.fd < 0)
4649                                 break;
4650                         i = safe_read(in.fd, buf, sizeof buf);
4651                         TRACE(("expbackq: read returns %d\n", i));
4652                         if (i <= 0)
4653                                 break;
4654                         p = buf;
4655                         in.nleft = i - 1;
4656                 }
4657                 lastc = *p++;
4658                 if (lastc != '\0') {
4659                         if (quotes && SIT(lastc, syntax) == CCTL)
4660                                 STPUTC(CTLESC, dest);
4661                         STPUTC(lastc, dest);
4662                 }
4663         }
4664
4665         /* Eat all trailing newlines */
4666         for (; dest > stackblock() && dest[-1] == '\n';)
4667                 STUNPUTC(dest);
4668
4669   err2:
4670         if (in.fd >= 0)
4671                 close(in.fd);
4672         free(in.buf);
4673         if (in.jp)
4674                 exitstatus = waitforjob(in.jp);
4675         handler = savehandler;
4676         if (ex) {
4677                 longjmp(handler->loc, 1);
4678         }
4679         if (quoted == 0)
4680                 recordregion(startloc, dest - stackblock(), 0);
4681         TRACE(("evalbackq: size=%d: \"%.*s\"\n",
4682                    (dest - stackblock()) - startloc,
4683                    (dest - stackblock()) - startloc, stackblock() + startloc));
4684         expdest = dest;
4685         INTON;
4686 }
4687
4688 static int
4689 subevalvar(char *p, char *str, int strloc, int subtype, int startloc,
4690                    int varflags, int quotes)
4691 {
4692         char *startp;
4693         char *loc = NULL;
4694         char *q;
4695         int c = 0;
4696         int saveherefd = herefd;
4697         struct nodelist *saveargbackq = argbackq;
4698         int amount;
4699
4700         herefd = -1;
4701         argstr(p, subtype != VSASSIGN && subtype != VSQUESTION ? EXP_CASE : 0);
4702         STACKSTRNUL(expdest);
4703         herefd = saveherefd;
4704         argbackq = saveargbackq;
4705         startp = stackblock() + startloc;
4706         if (str == NULL)
4707                 str = stackblock() + strloc;
4708
4709         switch (subtype) {
4710         case VSASSIGN:
4711                 setvar(str, startp, 0);
4712                 amount = startp - expdest;
4713                 STADJUST(amount, expdest);
4714                 varflags &= ~VSNUL;
4715                 if (c != 0)
4716                         *loc = c;
4717                 return 1;
4718
4719         case VSQUESTION:
4720                 if (*p != CTLENDVAR) {
4721                         out2fmt(snlfmt, startp);
4722                         error((char *) NULL);
4723                 }
4724                 error("%.*s: parameter %snot set", p - str - 1,
4725                           str, (varflags & VSNUL) ? "null or " : nullstr);
4726                 /* NOTREACHED */
4727
4728         case VSTRIMLEFT:
4729                 for (loc = startp; loc < str; loc++) {
4730                         c = *loc;
4731                         *loc = '\0';
4732                         if (patmatch2(str, startp, quotes))
4733                                 goto recordleft;
4734                         *loc = c;
4735                         if (quotes && *loc == CTLESC)
4736                                 loc++;
4737                 }
4738                 return 0;
4739
4740         case VSTRIMLEFTMAX:
4741                 for (loc = str - 1; loc >= startp;) {
4742                         c = *loc;
4743                         *loc = '\0';
4744                         if (patmatch2(str, startp, quotes))
4745                                 goto recordleft;
4746                         *loc = c;
4747                         loc--;
4748                         if (quotes && loc > startp && *(loc - 1) == CTLESC) {
4749                                 for (q = startp; q < loc; q++)
4750                                         if (*q == CTLESC)
4751                                                 q++;
4752                                 if (q > loc)
4753                                         loc--;
4754                         }
4755                 }
4756                 return 0;
4757
4758         case VSTRIMRIGHT:
4759                 for (loc = str - 1; loc >= startp;) {
4760                         if (patmatch2(str, loc, quotes))
4761                                 goto recordright;
4762                         loc--;
4763                         if (quotes && loc > startp && *(loc - 1) == CTLESC) {
4764                                 for (q = startp; q < loc; q++)
4765                                         if (*q == CTLESC)
4766                                                 q++;
4767                                 if (q > loc)
4768                                         loc--;
4769                         }
4770                 }
4771                 return 0;
4772
4773         case VSTRIMRIGHTMAX:
4774                 for (loc = startp; loc < str - 1; loc++) {
4775                         if (patmatch2(str, loc, quotes))
4776                                 goto recordright;
4777                         if (quotes && *loc == CTLESC)
4778                                 loc++;
4779                 }
4780                 return 0;
4781
4782 #ifdef DEBUG
4783         default:
4784                 abort();
4785 #endif
4786         }
4787
4788   recordleft:
4789         *loc = c;
4790         amount = ((str - 1) - (loc - startp)) - expdest;
4791         STADJUST(amount, expdest);
4792         while (loc != str - 1)
4793                 *startp++ = *loc++;
4794         return 1;
4795
4796   recordright:
4797         amount = loc - expdest;
4798         STADJUST(amount, expdest);
4799         STPUTC('\0', expdest);
4800         STADJUST(-1, expdest);
4801         return 1;
4802 }
4803
4804
4805 /*
4806  * Test whether a specialized variable is set.
4807  */
4808
4809 static int varisset(char *name, int nulok)
4810 {
4811         if (*name == '!')
4812                 return backgndpid != -1;
4813         else if (*name == '@' || *name == '*') {
4814                 if (*shellparam.p == NULL)
4815                         return 0;
4816
4817                 if (nulok) {
4818                         char **av;
4819
4820                         for (av = shellparam.p; *av; av++)
4821                                 if (**av != '\0')
4822                                         return 1;
4823                         return 0;
4824                 }
4825         } else if (is_digit(*name)) {
4826                 char *ap;
4827                 int num = atoi(name);
4828
4829                 if (num > shellparam.nparam)
4830                         return 0;
4831
4832                 if (num == 0)
4833                         ap = arg0;
4834                 else
4835                         ap = shellparam.p[num - 1];
4836
4837                 if (nulok && (ap == NULL || *ap == '\0'))
4838                         return 0;
4839         }
4840         return 1;
4841 }
4842
4843 /*
4844  * Put a string on the stack.
4845  */
4846
4847 static void strtodest(const char *p, int syntax, int quotes)
4848 {
4849         while (*p) {
4850                 if (quotes && SIT(*p, syntax) == CCTL)
4851                         STPUTC(CTLESC, expdest);
4852                 STPUTC(*p++, expdest);
4853         }
4854 }
4855
4856 /*
4857  * Add the value of a specialized variable to the stack string.
4858  */
4859
4860 static inline void varvalue(char *name, int quoted, int flags)
4861 {
4862         int num;
4863         char *p;
4864         int i;
4865         int sep;
4866         int sepq = 0;
4867         char **ap;
4868         int syntax;
4869         int allow_split = flags & EXP_FULL;
4870         int quotes = flags & (EXP_FULL | EXP_CASE);
4871
4872         syntax = quoted ? DQSYNTAX : BASESYNTAX;
4873         switch (*name) {
4874         case '$':
4875                 num = rootpid;
4876                 goto numvar;
4877         case '?':
4878                 num = oexitstatus;
4879                 goto numvar;
4880         case '#':
4881                 num = shellparam.nparam;
4882                 goto numvar;
4883         case '!':
4884                 num = backgndpid;
4885           numvar:
4886                 expdest = cvtnum(num, expdest);
4887                 break;
4888         case '-':
4889                 for (i = 0; i < NOPTS; i++) {
4890                         if (optent_val(i))
4891                                 STPUTC(optent_letter(optlist[i]), expdest);
4892                 }
4893                 break;
4894         case '@':
4895                 if (allow_split && quoted) {
4896                         sep = 1 << CHAR_BIT;
4897                         goto param;
4898                 }
4899                 /* fall through */
4900         case '*':
4901                 sep = ifsset()? ifsval()[0] : ' ';
4902                 if (quotes) {
4903                         sepq = SIT(sep, syntax) == CCTL;
4904                 }
4905           param:
4906                 for (ap = shellparam.p; (p = *ap++) != NULL;) {
4907                         strtodest(p, syntax, quotes);
4908                         if (*ap && sep) {
4909                                 if (sepq)
4910                                         STPUTC(CTLESC, expdest);
4911                                 STPUTC(sep, expdest);
4912                         }
4913                 }
4914                 break;
4915         case '0':
4916                 strtodest(arg0, syntax, quotes);
4917                 break;
4918         default:
4919                 num = atoi(name);
4920                 if (num > 0 && num <= shellparam.nparam) {
4921                         strtodest(shellparam.p[num - 1], syntax, quotes);
4922                 }
4923                 break;
4924         }
4925 }
4926
4927
4928 /*
4929  * Record the fact that we have to scan this region of the
4930  * string for IFS characters.
4931  */
4932
4933 static void recordregion(int start, int end, int nulonly)
4934 {
4935         struct ifsregion *ifsp;
4936
4937         if (ifslastp == NULL) {
4938                 ifsp = &ifsfirst;
4939         } else {
4940                 INTOFF;
4941                 ifsp = (struct ifsregion *) xmalloc(sizeof(struct ifsregion));
4942                 ifsp->next = NULL;
4943                 ifslastp->next = ifsp;
4944                 INTON;
4945         }
4946         ifslastp = ifsp;
4947         ifslastp->begoff = start;
4948         ifslastp->endoff = end;
4949         ifslastp->nulonly = nulonly;
4950 }
4951
4952
4953
4954 /*
4955  * Break the argument string into pieces based upon IFS and add the
4956  * strings to the argument list.  The regions of the string to be
4957  * searched for IFS characters have been stored by recordregion.
4958  */
4959 static void ifsbreakup(char *string, struct arglist *arglist)
4960 {
4961         struct ifsregion *ifsp;
4962         struct strlist *sp;
4963         char *start;
4964         char *p;
4965         char *q;
4966         const char *ifs, *realifs;
4967         int ifsspc;
4968         int nulonly;
4969
4970
4971         start = string;
4972         ifsspc = 0;
4973         nulonly = 0;
4974         realifs = ifsset()? ifsval() : defifs;
4975         if (ifslastp != NULL) {
4976                 ifsp = &ifsfirst;
4977                 do {
4978                         p = string + ifsp->begoff;
4979                         nulonly = ifsp->nulonly;
4980                         ifs = nulonly ? nullstr : realifs;
4981                         ifsspc = 0;
4982                         while (p < string + ifsp->endoff) {
4983                                 q = p;
4984                                 if (*p == CTLESC)
4985                                         p++;
4986                                 if (strchr(ifs, *p)) {
4987                                         if (!nulonly)
4988                                                 ifsspc = (strchr(defifs, *p) != NULL);
4989                                         /* Ignore IFS whitespace at start */
4990                                         if (q == start && ifsspc) {
4991                                                 p++;
4992                                                 start = p;
4993                                                 continue;
4994                                         }
4995                                         *q = '\0';
4996                                         sp = (struct strlist *) stalloc(sizeof *sp);
4997                                         sp->text = start;
4998                                         *arglist->lastp = sp;
4999                                         arglist->lastp = &sp->next;
5000                                         p++;
5001                                         if (!nulonly) {
5002                                                 for (;;) {
5003                                                         if (p >= string + ifsp->endoff) {
5004                                                                 break;
5005                                                         }
5006                                                         q = p;
5007                                                         if (*p == CTLESC)
5008                                                                 p++;
5009                                                         if (strchr(ifs, *p) == NULL) {
5010                                                                 p = q;
5011                                                                 break;
5012                                                         } else if (strchr(defifs, *p) == NULL) {
5013                                                                 if (ifsspc) {
5014                                                                         p++;
5015                                                                         ifsspc = 0;
5016                                                                 } else {
5017                                                                         p = q;
5018                                                                         break;
5019                                                                 }
5020                                                         } else
5021                                                                 p++;
5022                                                 }
5023                                         }
5024                                         start = p;
5025                                 } else
5026                                         p++;
5027                         }
5028                 } while ((ifsp = ifsp->next) != NULL);
5029                 if (!(*start || (!ifsspc && start > string && nulonly))) {
5030                         return;
5031                 }
5032         }
5033
5034         sp = (struct strlist *) stalloc(sizeof *sp);
5035         sp->text = start;
5036         *arglist->lastp = sp;
5037         arglist->lastp = &sp->next;
5038 }
5039
5040 static void ifsfree(void)
5041 {
5042         while (ifsfirst.next != NULL) {
5043                 struct ifsregion *ifsp;
5044
5045                 INTOFF;
5046                 ifsp = ifsfirst.next->next;
5047                 free(ifsfirst.next);
5048                 ifsfirst.next = ifsp;
5049                 INTON;
5050         }
5051         ifslastp = NULL;
5052         ifsfirst.next = NULL;
5053 }
5054
5055 /*
5056  * Add a file name to the list.
5057  */
5058
5059 static void addfname(const char *name)
5060 {
5061         struct strlist *sp;
5062
5063         sp = (struct strlist *) stalloc(sizeof *sp);
5064         sp->text = sstrdup(name);
5065         *exparg.lastp = sp;
5066         exparg.lastp = &sp->next;
5067 }
5068
5069 /*
5070  * Expand shell metacharacters.  At this point, the only control characters
5071  * should be escapes.  The results are stored in the list exparg.
5072  */
5073
5074 #if defined(__GLIBC__) && __GLIBC__ >= 2 && !defined(FNMATCH_BROKEN) && !defined(GLOB_BROKEN)
5075 static void expandmeta(struct strlist *str, int flag)
5076 {
5077         const char *p;
5078         glob_t pglob;
5079
5080         /* TODO - EXP_REDIR */
5081
5082         while (str) {
5083                 if (fflag)
5084                         goto nometa;
5085                 p = preglob(str->text);
5086                 INTOFF;
5087                 switch (glob(p, 0, 0, &pglob)) {
5088                 case 0:
5089                         if (pglob.gl_pathv[1] == 0 && !strcmp(p, pglob.gl_pathv[0]))
5090                                 goto nometa2;
5091                         addglob(&pglob);
5092                         globfree(&pglob);
5093                         INTON;
5094                         break;
5095                 case GLOB_NOMATCH:
5096                   nometa2:
5097                         globfree(&pglob);
5098                         INTON;
5099                   nometa:
5100                         *exparg.lastp = str;
5101                         rmescapes(str->text);
5102                         exparg.lastp = &str->next;
5103                         break;
5104                 default:                /* GLOB_NOSPACE */
5105                         error("Out of space");
5106                 }
5107                 str = str->next;
5108         }
5109 }
5110
5111
5112 /*
5113  * Add the result of glob(3) to the list.
5114  */
5115
5116 static inline void addglob(const glob_t * pglob)
5117 {
5118         char **p = pglob->gl_pathv;
5119
5120         do {
5121                 addfname(*p);
5122         } while (*++p);
5123 }
5124
5125
5126 #else                                                   /* defined(__GLIBC__) && !defined(FNMATCH_BROKEN) && !defined(GLOB_BROKEN) */
5127 static char *expdir;
5128
5129
5130 static void expandmeta(struct strlist *str, int flag)
5131 {
5132         char *p;
5133         struct strlist **savelastp;
5134         struct strlist *sp;
5135         char c;
5136
5137         /* TODO - EXP_REDIR */
5138
5139         while (str) {
5140                 if (fflag)
5141                         goto nometa;
5142                 p = str->text;
5143                 for (;;) {              /* fast check for meta chars */
5144                         if ((c = *p++) == '\0')
5145                                 goto nometa;
5146                         if (c == '*' || c == '?' || c == '[' || c == '!')
5147                                 break;
5148                 }
5149                 savelastp = exparg.lastp;
5150                 INTOFF;
5151                 if (expdir == NULL) {
5152                         int i = strlen(str->text);
5153
5154                         expdir = xmalloc(i < 2048 ? 2048 : i);  /* XXX */
5155                 }
5156
5157                 expmeta(expdir, str->text);
5158                 free(expdir);
5159                 expdir = NULL;
5160                 INTON;
5161                 if (exparg.lastp == savelastp) {
5162                         /*
5163                          * no matches
5164                          */
5165                   nometa:
5166                         *exparg.lastp = str;
5167                         rmescapes(str->text);
5168                         exparg.lastp = &str->next;
5169                 } else {
5170                         *exparg.lastp = NULL;
5171                         *savelastp = sp = expsort(*savelastp);
5172                         while (sp->next != NULL)
5173                                 sp = sp->next;
5174                         exparg.lastp = &sp->next;
5175                 }
5176                 str = str->next;
5177         }
5178 }
5179
5180
5181 /*
5182  * Do metacharacter (i.e. *, ?, [...]) expansion.
5183  */
5184
5185 static void expmeta(char *enddir, char *name)
5186 {
5187         char *p;
5188         const char *cp;
5189         char *q;
5190         char *start;
5191         char *endname;
5192         int metaflag;
5193         struct stat statb;
5194         DIR *dirp;
5195         struct dirent *dp;
5196         int atend;
5197         int matchdot;
5198
5199         metaflag = 0;
5200         start = name;
5201         for (p = name;; p++) {
5202                 if (*p == '*' || *p == '?')
5203                         metaflag = 1;
5204                 else if (*p == '[') {
5205                         q = p + 1;
5206                         if (*q == '!')
5207                                 q++;
5208                         for (;;) {
5209                                 while (*q == CTLQUOTEMARK)
5210                                         q++;
5211                                 if (*q == CTLESC)
5212                                         q++;
5213                                 if (*q == '/' || *q == '\0')
5214                                         break;
5215                                 if (*++q == ']') {
5216                                         metaflag = 1;
5217                                         break;
5218                                 }
5219                         }
5220                 } else if (*p == '!' && p[1] == '!' && (p == name || p[-1] == '/')) {
5221                         metaflag = 1;
5222                 } else if (*p == '\0')
5223                         break;
5224                 else if (*p == CTLQUOTEMARK)
5225                         continue;
5226                 else if (*p == CTLESC)
5227                         p++;
5228                 if (*p == '/') {
5229                         if (metaflag)
5230                                 break;
5231                         start = p + 1;
5232                 }
5233         }
5234         if (metaflag == 0) {    /* we've reached the end of the file name */
5235                 if (enddir != expdir)
5236                         metaflag++;
5237                 for (p = name;; p++) {
5238                         if (*p == CTLQUOTEMARK)
5239                                 continue;
5240                         if (*p == CTLESC)
5241                                 p++;
5242                         *enddir++ = *p;
5243                         if (*p == '\0')
5244                                 break;
5245                 }
5246                 if (metaflag == 0 || lstat(expdir, &statb) >= 0)
5247                         addfname(expdir);
5248                 return;
5249         }
5250         endname = p;
5251         if (start != name) {
5252                 p = name;
5253                 while (p < start) {
5254                         while (*p == CTLQUOTEMARK)
5255                                 p++;
5256                         if (*p == CTLESC)
5257                                 p++;
5258                         *enddir++ = *p++;
5259                 }
5260         }
5261         if (enddir == expdir) {
5262                 cp = ".";
5263         } else if (enddir == expdir + 1 && *expdir == '/') {
5264                 cp = "/";
5265         } else {
5266                 cp = expdir;
5267                 enddir[-1] = '\0';
5268         }
5269         if ((dirp = opendir(cp)) == NULL)
5270                 return;
5271         if (enddir != expdir)
5272                 enddir[-1] = '/';
5273         if (*endname == 0) {
5274                 atend = 1;
5275         } else {
5276                 atend = 0;
5277                 *endname++ = '\0';
5278         }
5279         matchdot = 0;
5280         p = start;
5281         while (*p == CTLQUOTEMARK)
5282                 p++;
5283         if (*p == CTLESC)
5284                 p++;
5285         if (*p == '.')
5286                 matchdot++;
5287         while (!int_pending() && (dp = readdir(dirp)) != NULL) {
5288                 if (dp->d_name[0] == '.' && !matchdot)
5289                         continue;
5290                 if (patmatch(start, dp->d_name, 0)) {
5291                         if (atend) {
5292                                 strcpy(enddir, dp->d_name);
5293                                 addfname(expdir);
5294                         } else {
5295                                 for (p = enddir, cp = dp->d_name; (*p++ = *cp++) != '\0';)
5296                                         continue;
5297                                 p[-1] = '/';
5298                                 expmeta(p, endname);
5299                         }
5300                 }
5301         }
5302         closedir(dirp);
5303         if (!atend)
5304                 endname[-1] = '/';
5305 }
5306 #endif                                                  /* defined(__GLIBC__) && !defined(FNMATCH_BROKEN) && !defined(GLOB_BROKEN) */
5307
5308
5309
5310 #if !(defined(__GLIBC__) && __GLIBC__ >= 2 && !defined(FNMATCH_BROKEN) && !defined(GLOB_BROKEN))
5311 /*
5312  * Sort the results of file name expansion.  It calculates the number of
5313  * strings to sort and then calls msort (short for merge sort) to do the
5314  * work.
5315  */
5316
5317 static struct strlist *expsort(struct strlist *str)
5318 {
5319         int len;
5320         struct strlist *sp;
5321
5322         len = 0;
5323         for (sp = str; sp; sp = sp->next)
5324                 len++;
5325         return msort(str, len);
5326 }
5327
5328
5329 static struct strlist *msort(struct strlist *list, int len)
5330 {
5331         struct strlist *p, *q = NULL;
5332         struct strlist **lpp;
5333         int half;
5334         int n;
5335
5336         if (len <= 1)
5337                 return list;
5338         half = len >> 1;
5339         p = list;
5340         for (n = half; --n >= 0;) {
5341                 q = p;
5342                 p = p->next;
5343         }
5344         q->next = NULL;         /* terminate first half of list */
5345         q = msort(list, half);  /* sort first half of list */
5346         p = msort(p, len - half);       /* sort second half */
5347         lpp = &list;
5348         for (;;) {
5349                 if (strcmp(p->text, q->text) < 0) {
5350                         *lpp = p;
5351                         lpp = &p->next;
5352                         if ((p = *lpp) == NULL) {
5353                                 *lpp = q;
5354                                 break;
5355                         }
5356                 } else {
5357                         *lpp = q;
5358                         lpp = &q->next;
5359                         if ((q = *lpp) == NULL) {
5360                                 *lpp = p;
5361                                 break;
5362                         }
5363                 }
5364         }
5365         return list;
5366 }
5367 #endif
5368
5369
5370
5371 /*
5372  * Returns true if the pattern matches the string.
5373  */
5374
5375 #if defined(__GLIBC__) && __GLIBC__ >= 2 && !defined(FNMATCH_BROKEN)
5376 /* squoted: string might have quote chars */
5377 static int patmatch(char *pattern, char *string, int squoted)
5378 {
5379         const char *p;
5380         char *q;
5381
5382         p = preglob(pattern);
5383         q = squoted ? _rmescapes(string, RMESCAPE_ALLOC) : string;
5384
5385         return !fnmatch(p, q, 0);
5386 }
5387
5388
5389 static int patmatch2(char *pattern, char *string, int squoted)
5390 {
5391         char *p;
5392         int res;
5393
5394         sstrnleft--;
5395         p = grabstackstr(expdest);
5396         res = patmatch(pattern, string, squoted);
5397         ungrabstackstr(p, expdest);
5398         return res;
5399 }
5400 #else
5401 static int patmatch(char *pattern, char *string, int squoted)
5402 {
5403         return pmatch(pattern, string, squoted);
5404 }
5405
5406
5407 static int pmatch(char *pattern, char *string, int squoted)
5408 {
5409         char *p, *q;
5410         char c;
5411
5412         p = pattern;
5413         q = string;
5414         for (;;) {
5415                 switch (c = *p++) {
5416                 case '\0':
5417                         goto breakloop;
5418                 case CTLESC:
5419                         if (squoted && *q == CTLESC)
5420                                 q++;
5421                         if (*q++ != *p++)
5422                                 return 0;
5423                         break;
5424                 case CTLQUOTEMARK:
5425                         continue;
5426                 case '?':
5427                         if (squoted && *q == CTLESC)
5428                                 q++;
5429                         if (*q++ == '\0')
5430                                 return 0;
5431                         break;
5432                 case '*':
5433                         c = *p;
5434                         while (c == CTLQUOTEMARK || c == '*')
5435                                 c = *++p;
5436                         if (c != CTLESC && c != CTLQUOTEMARK &&
5437                                 c != '?' && c != '*' && c != '[') {
5438                                 while (*q != c) {
5439                                         if (squoted && *q == CTLESC && q[1] == c)
5440                                                 break;
5441                                         if (*q == '\0')
5442                                                 return 0;
5443                                         if (squoted && *q == CTLESC)
5444                                                 q++;
5445                                         q++;
5446                                 }
5447                         }
5448                         do {
5449                                 if (pmatch(p, q, squoted))
5450                                         return 1;
5451                                 if (squoted && *q == CTLESC)
5452                                         q++;
5453                         } while (*q++ != '\0');
5454                         return 0;
5455                 case '[':{
5456                         char *endp;
5457                         int invert, found;
5458                         char chr;
5459
5460                         endp = p;
5461                         if (*endp == '!')
5462                                 endp++;
5463                         for (;;) {
5464                                 while (*endp == CTLQUOTEMARK)
5465                                         endp++;
5466                                 if (*endp == '\0')
5467                                         goto dft;       /* no matching ] */
5468                                 if (*endp == CTLESC)
5469                                         endp++;
5470                                 if (*++endp == ']')
5471                                         break;
5472                         }
5473                         invert = 0;
5474                         if (*p == '!') {
5475                                 invert++;
5476                                 p++;
5477                         }
5478                         found = 0;
5479                         chr = *q++;
5480                         if (squoted && chr == CTLESC)
5481                                 chr = *q++;
5482                         if (chr == '\0')
5483                                 return 0;
5484                         c = *p++;
5485                         do {
5486                                 if (c == CTLQUOTEMARK)
5487                                         continue;
5488                                 if (c == CTLESC)
5489                                         c = *p++;
5490                                 if (*p == '-' && p[1] != ']') {
5491                                         p++;
5492                                         while (*p == CTLQUOTEMARK)
5493                                                 p++;
5494                                         if (*p == CTLESC)
5495                                                 p++;
5496                                         if (chr >= c && chr <= *p)
5497                                                 found = 1;
5498                                         p++;
5499                                 } else {
5500                                         if (chr == c)
5501                                                 found = 1;
5502                                 }
5503                         } while ((c = *p++) != ']');
5504                         if (found == invert)
5505                                 return 0;
5506                         break;
5507                 }
5508                 dft: default:
5509                         if (squoted && *q == CTLESC)
5510                                 q++;
5511                         if (*q++ != c)
5512                                 return 0;
5513                         break;
5514                 }
5515         }
5516   breakloop:
5517         if (*q != '\0')
5518                 return 0;
5519         return 1;
5520 }
5521 #endif
5522
5523
5524
5525 /*
5526  * Remove any CTLESC characters from a string.
5527  */
5528
5529 #if defined(__GLIBC__) && __GLIBC__ >= 2 && !defined(FNMATCH_BROKEN)
5530 static char *_rmescapes(char *str, int flag)
5531 {
5532         char *p, *q, *r;
5533         static const char qchars[] = { CTLESC, CTLQUOTEMARK, 0 };
5534
5535         p = strpbrk(str, qchars);
5536         if (!p) {
5537                 return str;
5538         }
5539         q = p;
5540         r = str;
5541         if (flag & RMESCAPE_ALLOC) {
5542                 size_t len = p - str;
5543
5544                 q = r = stalloc(strlen(p) + len + 1);
5545                 if (len > 0) {
5546                         memcpy(q, str, len);
5547                         q += len;
5548                 }
5549         }
5550         while (*p) {
5551                 if (*p == CTLQUOTEMARK) {
5552                         p++;
5553                         continue;
5554                 }
5555                 if (*p == CTLESC) {
5556                         p++;
5557                         if (flag & RMESCAPE_GLOB && *p != '/') {
5558                                 *q++ = '\\';
5559                         }
5560                 }
5561                 *q++ = *p++;
5562         }
5563         *q = '\0';
5564         return r;
5565 }
5566 #else
5567 static void rmescapes(char *str)
5568 {
5569         char *p, *q;
5570
5571         p = str;
5572         while (*p != CTLESC && *p != CTLQUOTEMARK) {
5573                 if (*p++ == '\0')
5574                         return;
5575         }
5576         q = p;
5577         while (*p) {
5578                 if (*p == CTLQUOTEMARK) {
5579                         p++;
5580                         continue;
5581                 }
5582                 if (*p == CTLESC)
5583                         p++;
5584                 *q++ = *p++;
5585         }
5586         *q = '\0';
5587 }
5588 #endif
5589
5590
5591
5592 /*
5593  * See if a pattern matches in a case statement.
5594  */
5595
5596 static int casematch(union node *pattern, const char *val)
5597 {
5598         struct stackmark smark;
5599         int result;
5600         char *p;
5601
5602         setstackmark(&smark);
5603         argbackq = pattern->narg.backquote;
5604         STARTSTACKSTR(expdest);
5605         ifslastp = NULL;
5606         argstr(pattern->narg.text, EXP_TILDE | EXP_CASE);
5607         STPUTC('\0', expdest);
5608         p = grabstackstr(expdest);
5609         result = patmatch(p, (char *) val, 0);
5610         popstackmark(&smark);
5611         return result;
5612 }
5613
5614 /*
5615  * Our own itoa().
5616  */
5617
5618 static char *cvtnum(int num, char *buf)
5619 {
5620         int len;
5621
5622         CHECKSTRSPACE(32, buf);
5623         len = sprintf(buf, "%d", num);
5624         STADJUST(len, buf);
5625         return buf;
5626 }
5627
5628 /*
5629  * Editline and history functions (and glue).
5630  */
5631 static int histcmd(int argc, char **argv)
5632 {
5633         error("not compiled with history support");
5634         /* NOTREACHED */
5635 }
5636
5637
5638 struct redirtab {
5639         struct redirtab *next;
5640         short renamed[10];      /* Current ash support only 0-9 descriptors */
5641         /* char on arm (and others) can't be negative */
5642 };
5643
5644 static struct redirtab *redirlist;
5645
5646 extern char **environ;
5647
5648
5649
5650 /*
5651  * Initialization code.
5652  */
5653
5654 static void init(void)
5655 {
5656
5657         /* from cd.c: */
5658         {
5659                 curdir = nullstr;
5660                 setpwd(0, 0);
5661         }
5662
5663         /* from input.c: */
5664         {
5665                 basepf.nextc = basepf.buf = basebuf;
5666         }
5667
5668         /* from var.c: */
5669         {
5670                 char **envp;
5671                 char ppid[32];
5672
5673                 initvar();
5674                 for (envp = environ; *envp; envp++) {
5675                         if (strchr(*envp, '=')) {
5676                                 setvareq(*envp, VEXPORT | VTEXTFIXED);
5677                         }
5678                 }
5679
5680                 snprintf(ppid, sizeof(ppid), "%d", (int) getppid());
5681                 setvar("PPID", ppid, 0);
5682         }
5683 }
5684
5685
5686
5687 /*
5688  * This routine is called when an error or an interrupt occurs in an
5689  * interactive shell and control is returned to the main command loop.
5690  */
5691
5692 /* 1 == check for aliases, 2 == also check for assignments */
5693 static int checkalias;  /* also used in no alias mode for check assignments */
5694
5695 static void reset(void)
5696 {
5697
5698         /* from eval.c: */
5699         {
5700                 evalskip = 0;
5701                 loopnest = 0;
5702                 funcnest = 0;
5703         }
5704
5705         /* from input.c: */
5706         {
5707                 if (exception != EXSHELLPROC)
5708                         parselleft = parsenleft = 0;    /* clear input buffer */
5709                 popallfiles();
5710         }
5711
5712         /* from parser.c: */
5713         {
5714                 tokpushback = 0;
5715                 checkkwd = 0;
5716                 checkalias = 0;
5717         }
5718
5719         /* from redir.c: */
5720         {
5721                 while (redirlist)
5722                         popredir();
5723         }
5724
5725 }
5726
5727
5728
5729 /*
5730  * This file implements the input routines used by the parser.
5731  */
5732
5733 #ifdef CONFIG_FEATURE_COMMAND_EDITING
5734 static const char *cmdedit_prompt;
5735 static inline void putprompt(const char *s)
5736 {
5737         cmdedit_prompt = s;
5738 }
5739 #else
5740 static inline void putprompt(const char *s)
5741 {
5742         out2str(s);
5743 }
5744 #endif
5745
5746 #define EOF_NLEFT -99   /* value of parsenleft when EOF pushed back */
5747
5748
5749
5750 /*
5751  * Same as pgetc(), but ignores PEOA.
5752  */
5753
5754 #ifdef CONFIG_ASH_ALIAS
5755 static int pgetc2(void)
5756 {
5757         int c;
5758
5759         do {
5760                 c = pgetc_macro();
5761         } while (c == PEOA);
5762         return c;
5763 }
5764 #else
5765 static inline int pgetc2(void)
5766 {
5767         return pgetc_macro();
5768 }
5769 #endif
5770
5771 /*
5772  * Read a line from the script.
5773  */
5774
5775 static inline char *pfgets(char *line, int len)
5776 {
5777         char *p = line;
5778         int nleft = len;
5779         int c;
5780
5781         while (--nleft > 0) {
5782                 c = pgetc2();
5783                 if (c == PEOF) {
5784                         if (p == line)
5785                                 return NULL;
5786                         break;
5787                 }
5788                 *p++ = c;
5789                 if (c == '\n')
5790                         break;
5791         }
5792         *p = '\0';
5793         return line;
5794 }
5795
5796 static inline int preadfd(void)
5797 {
5798         int nr;
5799         char *buf = parsefile->buf;
5800
5801         parsenextc = buf;
5802
5803   retry:
5804 #ifdef CONFIG_FEATURE_COMMAND_EDITING
5805         {
5806                 if (!iflag || parsefile->fd)
5807                         nr = safe_read(parsefile->fd, buf, BUFSIZ - 1);
5808                 else {
5809                         nr = cmdedit_read_input((char *) cmdedit_prompt, buf);
5810                 }
5811         }
5812 #else
5813         nr = safe_read(parsefile->fd, buf, BUFSIZ - 1);
5814 #endif
5815
5816         if (nr < 0) {
5817                 if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
5818                         int flags = fcntl(0, F_GETFL, 0);
5819
5820                         if (flags >= 0 && flags & O_NONBLOCK) {
5821                                 flags &= ~O_NONBLOCK;
5822                                 if (fcntl(0, F_SETFL, flags) >= 0) {
5823                                         out2str("sh: turning off NDELAY mode\n");
5824                                         goto retry;
5825                                 }
5826                         }
5827                 }
5828         }
5829         return nr;
5830 }
5831
5832 static void popstring(void)
5833 {
5834         struct strpush *sp = parsefile->strpush;
5835
5836         INTOFF;
5837 #ifdef CONFIG_ASH_ALIAS
5838         if (sp->ap) {
5839                 if (parsenextc[-1] == ' ' || parsenextc[-1] == '\t') {
5840                         if (!checkalias) {
5841                                 checkalias = 1;
5842                         }
5843                 }
5844                 if (sp->string != sp->ap->val) {
5845                         free(sp->string);
5846                 }
5847
5848                 sp->ap->flag &= ~ALIASINUSE;
5849                 if (sp->ap->flag & ALIASDEAD) {
5850                         unalias(sp->ap->name);
5851                 }
5852         }
5853 #endif
5854         parsenextc = sp->prevstring;
5855         parsenleft = sp->prevnleft;
5856 /*dprintf("*** calling popstring: restoring to '%s'\n", parsenextc);*/
5857         parsefile->strpush = sp->prev;
5858         if (sp != &(parsefile->basestrpush))
5859                 free(sp);
5860         INTON;
5861 }
5862
5863
5864 /*
5865  * Refill the input buffer and return the next input character:
5866  *
5867  * 1) If a string was pushed back on the input, pop it;
5868  * 2) If an EOF was pushed back (parsenleft == EOF_NLEFT) or we are reading
5869  *    from a string so we can't refill the buffer, return EOF.
5870  * 3) If the is more stuff in this buffer, use it else call read to fill it.
5871  * 4) Process input up to the next newline, deleting nul characters.
5872  */
5873
5874 static int preadbuffer(void)
5875 {
5876         char *p, *q;
5877         int more;
5878         char savec;
5879
5880         while (parsefile->strpush) {
5881 #ifdef CONFIG_ASH_ALIAS
5882                 if (parsenleft == -1 && parsefile->strpush->ap &&
5883                         parsenextc[-1] != ' ' && parsenextc[-1] != '\t') {
5884                         return PEOA;
5885                 }
5886 #endif
5887                 popstring();
5888                 if (--parsenleft >= 0)
5889                         return (*parsenextc++);
5890         }
5891         if (parsenleft == EOF_NLEFT || parsefile->buf == NULL)
5892                 return PEOF;
5893         flushall();
5894
5895   again:
5896         if (parselleft <= 0) {
5897                 if ((parselleft = preadfd()) <= 0) {
5898                         parselleft = parsenleft = EOF_NLEFT;
5899                         return PEOF;
5900                 }
5901         }
5902
5903         q = p = parsenextc;
5904
5905         /* delete nul characters */
5906         for (more = 1; more;) {
5907                 switch (*p) {
5908                 case '\0':
5909                         p++;            /* Skip nul */
5910                         goto check;
5911
5912
5913                 case '\n':
5914                         parsenleft = q - parsenextc;
5915                         more = 0;       /* Stop processing here */
5916                         break;
5917                 }
5918
5919                 *q++ = *p++;
5920           check:
5921                 if (--parselleft <= 0 && more) {
5922                         parsenleft = q - parsenextc - 1;
5923                         if (parsenleft < 0)
5924                                 goto again;
5925                         more = 0;
5926                 }
5927         }
5928
5929         savec = *q;
5930         *q = '\0';
5931
5932         if (vflag) {
5933                 out2str(parsenextc);
5934         }
5935
5936         *q = savec;
5937
5938         return *parsenextc++;
5939 }
5940
5941
5942 /*
5943  * Push a string back onto the input at this current parsefile level.
5944  * We handle aliases this way.
5945  */
5946 static void pushstring(char *s, int len, void *ap)
5947 {
5948         struct strpush *sp;
5949
5950         INTOFF;
5951 /*dprintf("*** calling pushstring: %s, %d\n", s, len);*/
5952         if (parsefile->strpush) {
5953                 sp = xmalloc(sizeof(struct strpush));
5954                 sp->prev = parsefile->strpush;
5955                 parsefile->strpush = sp;
5956         } else
5957                 sp = parsefile->strpush = &(parsefile->basestrpush);
5958         sp->prevstring = parsenextc;
5959         sp->prevnleft = parsenleft;
5960 #ifdef CONFIG_ASH_ALIAS
5961         sp->ap = (struct alias *) ap;
5962         if (ap) {
5963                 ((struct alias *) ap)->flag |= ALIASINUSE;
5964                 sp->string = s;
5965         }
5966 #endif
5967         parsenextc = s;
5968         parsenleft = len;
5969         INTON;
5970 }
5971
5972
5973 /*
5974  * Like setinputfile, but takes input from a string.
5975  */
5976
5977 static void setinputstring(char *string)
5978 {
5979         INTOFF;
5980         pushfile();
5981         parsenextc = string;
5982         parsenleft = strlen(string);
5983         parsefile->buf = NULL;
5984         plinno = 1;
5985         INTON;
5986 }
5987
5988
5989
5990 /*
5991  * To handle the "." command, a stack of input files is used.  Pushfile
5992  * adds a new entry to the stack and popfile restores the previous level.
5993  */
5994
5995 static void pushfile(void)
5996 {
5997         struct parsefile *pf;
5998
5999         parsefile->nleft = parsenleft;
6000         parsefile->lleft = parselleft;
6001         parsefile->nextc = parsenextc;
6002         parsefile->linno = plinno;
6003         pf = (struct parsefile *) xmalloc(sizeof(struct parsefile));
6004         pf->prev = parsefile;
6005         pf->fd = -1;
6006         pf->strpush = NULL;
6007         pf->basestrpush.prev = NULL;
6008         parsefile = pf;
6009 }
6010
6011 #ifdef CONFIG_ASH_JOB_CONTROL
6012 static void restartjob(struct job *);
6013 #endif
6014 static void freejob(struct job *);
6015 static struct job *getjob(const char *);
6016 static int dowait(int, struct job *);
6017 static void waitonint(int);
6018
6019
6020 /*
6021  * We keep track of whether or not fd0 has been redirected.  This is for
6022  * background commands, where we want to redirect fd0 to /dev/null only
6023  * if it hasn't already been redirected.
6024 */
6025 static int fd0_redirected = 0;
6026
6027 /* Return true if fd 0 has already been redirected at least once.  */
6028 static inline int fd0_redirected_p(void)
6029 {
6030         return fd0_redirected != 0;
6031 }
6032
6033 static void dupredirect(const union node *, int, int fd1dup);
6034
6035 #ifdef CONFIG_ASH_JOB_CONTROL
6036 /*
6037  * Turn job control on and off.
6038  *
6039  * Note:  This code assumes that the third arg to ioctl is a character
6040  * pointer, which is true on Berkeley systems but not System V.  Since
6041  * System V doesn't have job control yet, this isn't a problem now.
6042  */
6043
6044
6045
6046 static void setjobctl(int enable)
6047 {
6048 #ifdef OLD_TTY_DRIVER
6049         int ldisc;
6050 #endif
6051
6052         if (enable == jobctl || rootshell == 0)
6053                 return;
6054         if (enable) {
6055                 do {                    /* while we are in the background */
6056 #ifdef OLD_TTY_DRIVER
6057                         if (ioctl(2, TIOCGPGRP, (char *) &initialpgrp) < 0) {
6058 #else
6059                         initialpgrp = tcgetpgrp(2);
6060                         if (initialpgrp < 0) {
6061 #endif
6062                                 out2str("sh: can't access tty; job control turned off\n");
6063                                 mflag = 0;
6064                                 return;
6065                         }
6066                         if (initialpgrp == -1)
6067                                 initialpgrp = getpgrp();
6068                         else if (initialpgrp != getpgrp()) {
6069                                 killpg(initialpgrp, SIGTTIN);
6070                                 continue;
6071                         }
6072                 } while (0);
6073 #ifdef OLD_TTY_DRIVER
6074                 if (ioctl(2, TIOCGETD, (char *) &ldisc) < 0 || ldisc != NTTYDISC) {
6075                         out2str
6076                                 ("sh: need new tty driver to run job control; job control turned off\n");
6077                         mflag = 0;
6078                         return;
6079                 }
6080 #endif
6081                 setsignal(SIGTSTP);
6082                 setsignal(SIGTTOU);
6083                 setsignal(SIGTTIN);
6084                 setpgid(0, rootpid);
6085 #ifdef OLD_TTY_DRIVER
6086                 ioctl(2, TIOCSPGRP, (char *) &rootpid);
6087 #else
6088                 tcsetpgrp(2, rootpid);
6089 #endif
6090         } else {                        /* turning job control off */
6091                 setpgid(0, initialpgrp);
6092 #ifdef OLD_TTY_DRIVER
6093                 ioctl(2, TIOCSPGRP, (char *) &initialpgrp);
6094 #else
6095                 tcsetpgrp(2, initialpgrp);
6096 #endif
6097                 setsignal(SIGTSTP);
6098                 setsignal(SIGTTOU);
6099                 setsignal(SIGTTIN);
6100         }
6101         jobctl = enable;
6102 }
6103 #endif
6104
6105
6106 #ifdef CONFIG_ASH_JOB_CONTROL
6107 static int killcmd(int argc, char **argv)
6108 {
6109         int signo = -1;
6110         int list = 0;
6111         int i;
6112         pid_t pid;
6113         struct job *jp;
6114
6115         if (argc <= 1) {
6116           usage:
6117                 error
6118                         ("Usage: kill [-s sigspec | -signum | -sigspec] [pid | job]... or\n"
6119                          "kill -l [exitstatus]");
6120         }
6121
6122         if (*argv[1] == '-') {
6123                 signo = decode_signal(argv[1] + 1, 1);
6124                 if (signo < 0) {
6125                         int c;
6126
6127                         while ((c = nextopt("ls:")) != '\0')
6128                                 switch (c) {
6129                                 case 'l':
6130                                         list = 1;
6131                                         break;
6132                                 case 's':
6133                                         signo = decode_signal(optionarg, 1);
6134                                         if (signo < 0) {
6135                                                 error("invalid signal number or name: %s", optionarg);
6136                                         }
6137                                         break;
6138 #ifdef DEBUG
6139                                 default:
6140                                         error("nextopt returned character code 0%o", c);
6141 #endif
6142                                 }
6143                 } else
6144                         argptr++;
6145         }
6146
6147         if (!list && signo < 0)
6148                 signo = SIGTERM;
6149
6150         if ((signo < 0 || !*argptr) ^ list) {
6151                 goto usage;
6152         }
6153
6154         if (list) {
6155                 const char *name;
6156
6157                 if (!*argptr) {
6158                         out1str("0\n");
6159                         for (i = 1; i < NSIG; i++) {
6160                                 name = u_signal_names(0, &i, 1);
6161                                 if (name)
6162                                         puts(name);
6163                         }
6164                         return 0;
6165                 }
6166                 name = u_signal_names(*argptr, &signo, -1);
6167                 if (name)
6168                         puts(name);
6169                 else
6170                         error("invalid signal number or exit status: %s", *argptr);
6171                 return 0;
6172         }
6173
6174         do {
6175                 if (**argptr == '%') {
6176                         jp = getjob(*argptr);
6177                         if (jp->jobctl == 0)
6178                                 error("job %s not created under job control", *argptr);
6179                         pid = -jp->ps[0].pid;
6180                 } else
6181                         pid = atoi(*argptr);
6182                 if (kill(pid, signo) != 0)
6183                         error("%s: %m", *argptr);
6184         } while (*++argptr);
6185
6186         return 0;
6187 }
6188
6189 static int fgcmd(int argc, char **argv)
6190 {
6191         struct job *jp;
6192         int pgrp;
6193         int status;
6194
6195         jp = getjob(argv[1]);
6196         if (jp->jobctl == 0)
6197                 error("job not created under job control");
6198         pgrp = jp->ps[0].pid;
6199 #ifdef OLD_TTY_DRIVER
6200         ioctl(2, TIOCSPGRP, (char *) &pgrp);
6201 #else
6202         tcsetpgrp(2, pgrp);
6203 #endif
6204         restartjob(jp);
6205         status = waitforjob(jp);
6206         return status;
6207 }
6208
6209
6210 static int bgcmd(int argc, char **argv)
6211 {
6212         struct job *jp;
6213
6214         do {
6215                 jp = getjob(*++argv);
6216                 if (jp->jobctl == 0)
6217                         error("job not created under job control");
6218                 restartjob(jp);
6219         } while (--argc > 1);
6220         return 0;
6221 }
6222
6223
6224 static void restartjob(struct job *jp)
6225 {
6226         struct procstat *ps;
6227         int i;
6228
6229         if (jp->state == JOBDONE)
6230                 return;
6231         INTOFF;
6232         killpg(jp->ps[0].pid, SIGCONT);
6233         for (ps = jp->ps, i = jp->nprocs; --i >= 0; ps++) {
6234                 if (WIFSTOPPED(ps->status)) {
6235                         ps->status = -1;
6236                         jp->state = 0;
6237                 }
6238         }
6239         INTON;
6240 }
6241 #endif
6242
6243 static void showjobs(int change);
6244
6245
6246 static int jobscmd(int argc, char **argv)
6247 {
6248         showjobs(0);
6249         return 0;
6250 }
6251
6252
6253 /*
6254  * Print a list of jobs.  If "change" is nonzero, only print jobs whose
6255  * statuses have changed since the last call to showjobs.
6256  *
6257  * If the shell is interrupted in the process of creating a job, the
6258  * result may be a job structure containing zero processes.  Such structures
6259  * will be freed here.
6260  */
6261
6262 static void showjobs(int change)
6263 {
6264         int jobno;
6265         int procno;
6266         int i;
6267         struct job *jp;
6268         struct procstat *ps;
6269         int col;
6270         char s[64];
6271
6272         TRACE(("showjobs(%d) called\n", change));
6273         while (dowait(0, (struct job *) NULL) > 0);
6274         for (jobno = 1, jp = jobtab; jobno <= njobs; jobno++, jp++) {
6275                 if (!jp->used)
6276                         continue;
6277                 if (jp->nprocs == 0) {
6278                         freejob(jp);
6279                         continue;
6280                 }
6281                 if (change && !jp->changed)
6282                         continue;
6283                 procno = jp->nprocs;
6284                 for (ps = jp->ps;; ps++) {      /* for each process */
6285                         if (ps == jp->ps)
6286                                 snprintf(s, 64, "[%d] %ld ", jobno, (long) ps->pid);
6287                         else
6288                                 snprintf(s, 64, "    %ld ", (long) ps->pid);
6289                         out1str(s);
6290                         col = strlen(s);
6291                         s[0] = '\0';
6292                         if (ps->status == -1) {
6293                                 /* don't print anything */
6294                         } else if (WIFEXITED(ps->status)) {
6295                                 snprintf(s, 64, "Exit %d", WEXITSTATUS(ps->status));
6296                         } else {
6297 #ifdef CONFIG_ASH_JOB_CONTROL
6298                                 if (WIFSTOPPED(ps->status))
6299                                         i = WSTOPSIG(ps->status);
6300                                 else    /* WIFSIGNALED(ps->status) */
6301 #endif
6302                                         i = WTERMSIG(ps->status);
6303                                 if ((i & 0x7F) < NSIG && sys_siglist[i & 0x7F])
6304                                         strcpy(s, sys_siglist[i & 0x7F]);
6305                                 else
6306                                         snprintf(s, 64, "Signal %d", i & 0x7F);
6307                                 if (WCOREDUMP(ps->status))
6308                                         strcat(s, " (core dumped)");
6309                         }
6310                         out1str(s);
6311                         col += strlen(s);
6312                         printf("%*c%s\n", 30 - col >= 0 ? 30 - col : 0, ' ', ps->cmd);
6313                         if (--procno <= 0)
6314                                 break;
6315                 }
6316                 jp->changed = 0;
6317                 if (jp->state == JOBDONE) {
6318                         freejob(jp);
6319                 }
6320         }
6321 }
6322
6323
6324 /*
6325  * Mark a job structure as unused.
6326  */
6327
6328 static void freejob(struct job *jp)
6329 {
6330         const struct procstat *ps;
6331         int i;
6332
6333         INTOFF;
6334         for (i = jp->nprocs, ps = jp->ps; --i >= 0; ps++) {
6335                 if (ps->cmd != nullstr)
6336                         free(ps->cmd);
6337         }
6338         if (jp->ps != &jp->ps0)
6339                 free(jp->ps);
6340         jp->used = 0;
6341 #ifdef CONFIG_ASH_JOB_CONTROL
6342         if (curjob == jp - jobtab + 1)
6343                 curjob = 0;
6344 #endif
6345         INTON;
6346 }
6347
6348
6349
6350 static int waitcmd(int argc, char **argv)
6351 {
6352         struct job *job;
6353         int status, retval;
6354         struct job *jp;
6355
6356         if (--argc > 0) {
6357           start:
6358                 job = getjob(*++argv);
6359         } else {
6360                 job = NULL;
6361         }
6362         for (;;) {                      /* loop until process terminated or stopped */
6363                 if (job != NULL) {
6364                         if (job->state) {
6365                                 status = job->ps[job->nprocs - 1].status;
6366                                 if (!iflag)
6367                                         freejob(job);
6368                                 if (--argc) {
6369                                         goto start;
6370                                 }
6371                                 if (WIFEXITED(status))
6372                                         retval = WEXITSTATUS(status);
6373 #ifdef CONFIG_ASH_JOB_CONTROL
6374                                 else if (WIFSTOPPED(status))
6375                                         retval = WSTOPSIG(status) + 128;
6376 #endif
6377                                 else {
6378                                         /* XXX: limits number of signals */
6379                                         retval = WTERMSIG(status) + 128;
6380                                 }
6381                                 return retval;
6382                         }
6383                 } else {
6384                         for (jp = jobtab;; jp++) {
6385                                 if (jp >= jobtab + njobs) {     /* no running procs */
6386                                         return 0;
6387                                 }
6388                                 if (jp->used && jp->state == 0)
6389                                         break;
6390                         }
6391                 }
6392                 if (dowait(2, 0) < 0 && errno == EINTR) {
6393                         return 129;
6394                 }
6395         }
6396 }
6397
6398
6399
6400 /*
6401  * Convert a job name to a job structure.
6402  */
6403
6404 static struct job *getjob(const char *name)
6405 {
6406         int jobno;
6407         struct job *jp;
6408         int pid;
6409         int i;
6410
6411         if (name == NULL) {
6412 #ifdef CONFIG_ASH_JOB_CONTROL
6413           currentjob:
6414                 if ((jobno = curjob) == 0 || jobtab[jobno - 1].used == 0)
6415                         error("No current job");
6416                 return &jobtab[jobno - 1];
6417 #else
6418                 error("No current job");
6419 #endif
6420         } else if (name[0] == '%') {
6421                 if (is_digit(name[1])) {
6422                         jobno = number(name + 1);
6423                         if (jobno > 0 && jobno <= njobs && jobtab[jobno - 1].used != 0)
6424                                 return &jobtab[jobno - 1];
6425 #ifdef CONFIG_ASH_JOB_CONTROL
6426                 } else if (name[1] == '%' && name[2] == '\0') {
6427                         goto currentjob;
6428 #endif
6429                 } else {
6430                         struct job *found = NULL;
6431
6432                         for (jp = jobtab, i = njobs; --i >= 0; jp++) {
6433                                 if (jp->used && jp->nprocs > 0
6434                                         && prefix(name + 1, jp->ps[0].cmd)) {
6435                                         if (found)
6436                                                 error("%s: ambiguous", name);
6437                                         found = jp;
6438                                 }
6439                         }
6440                         if (found)
6441                                 return found;
6442                 }
6443         } else if (is_number(name, &pid)) {
6444                 for (jp = jobtab, i = njobs; --i >= 0; jp++) {
6445                         if (jp->used && jp->nprocs > 0
6446                                 && jp->ps[jp->nprocs - 1].pid == pid)
6447                                 return jp;
6448                 }
6449         }
6450         error("No such job: %s", name);
6451         /* NOTREACHED */
6452 }
6453
6454
6455
6456 /*
6457  * Return a new job structure,
6458  */
6459
6460 static struct job *makejob(const union node *node, int nprocs)
6461 {
6462         int i;
6463         struct job *jp;
6464
6465         for (i = njobs, jp = jobtab;; jp++) {
6466                 if (--i < 0) {
6467                         INTOFF;
6468                         if (njobs == 0) {
6469                                 jobtab = xmalloc(4 * sizeof jobtab[0]);
6470                         } else {
6471                                 jp = xmalloc((njobs + 4) * sizeof jobtab[0]);
6472                                 memcpy(jp, jobtab, njobs * sizeof jp[0]);
6473                                 /* Relocate `ps' pointers */
6474                                 for (i = 0; i < njobs; i++)
6475                                         if (jp[i].ps == &jobtab[i].ps0)
6476                                                 jp[i].ps = &jp[i].ps0;
6477                                 free(jobtab);
6478                                 jobtab = jp;
6479                         }
6480                         jp = jobtab + njobs;
6481                         for (i = 4; --i >= 0; jobtab[njobs++].used = 0);
6482                         INTON;
6483                         break;
6484                 }
6485                 if (jp->used == 0)
6486                         break;
6487         }
6488         INTOFF;
6489         jp->state = 0;
6490         jp->used = 1;
6491         jp->changed = 0;
6492         jp->nprocs = 0;
6493 #ifdef CONFIG_ASH_JOB_CONTROL
6494         jp->jobctl = jobctl;
6495 #endif
6496         if (nprocs > 1) {
6497                 jp->ps = xmalloc(nprocs * sizeof(struct procstat));
6498         } else {
6499                 jp->ps = &jp->ps0;
6500         }
6501         INTON;
6502         TRACE(("makejob(0x%lx, %d) returns %%%d\n", (long) node, nprocs,
6503                    jp - jobtab + 1));
6504         return jp;
6505 }
6506
6507
6508 /*
6509  * Fork of a subshell.  If we are doing job control, give the subshell its
6510  * own process group.  Jp is a job structure that the job is to be added to.
6511  * N is the command that will be evaluated by the child.  Both jp and n may
6512  * be NULL.  The mode parameter can be one of the following:
6513  *      FORK_FG - Fork off a foreground process.
6514  *      FORK_BG - Fork off a background process.
6515  *      FORK_NOJOB - Like FORK_FG, but don't give the process its own
6516  *                   process group even if job control is on.
6517  *
6518  * When job control is turned off, background processes have their standard
6519  * input redirected to /dev/null (except for the second and later processes
6520  * in a pipeline).
6521  */
6522
6523
6524
6525 static int forkshell(struct job *jp, const union node *n, int mode)
6526 {
6527         int pid;
6528
6529 #ifdef CONFIG_ASH_JOB_CONTROL
6530         int pgrp;
6531 #endif
6532         const char *devnull = _PATH_DEVNULL;
6533         const char *nullerr = "Can't open %s";
6534
6535         TRACE(("forkshell(%%%d, 0x%lx, %d) called\n", jp - jobtab, (long) n,
6536                    mode));
6537         INTOFF;
6538 #if !defined(__UCLIBC__) || defined(__UCLIBC_HAS_MMU__)
6539         pid = fork();
6540 #else
6541         pid = vfork();
6542 #endif
6543         if (pid == -1) {
6544                 TRACE(("Fork failed, errno=%d\n", errno));
6545                 INTON;
6546                 error("Cannot fork");
6547         }
6548         if (pid == 0) {
6549                 struct job *p;
6550                 int wasroot;
6551                 int i;
6552
6553                 TRACE(("Child shell %d\n", getpid()));
6554                 wasroot = rootshell;
6555                 rootshell = 0;
6556                 closescript();
6557                 INTON;
6558                 clear_traps();
6559 #ifdef CONFIG_ASH_JOB_CONTROL
6560                 jobctl = 0;             /* do job control only in root shell */
6561                 if (wasroot && mode != FORK_NOJOB && mflag) {
6562                         if (jp == NULL || jp->nprocs == 0)
6563                                 pgrp = getpid();
6564                         else
6565                                 pgrp = jp->ps[0].pid;
6566                         setpgid(0, pgrp);
6567                         if (mode == FORK_FG) {
6568                                 /*** this causes superfluous TIOCSPGRPS ***/
6569 #ifdef OLD_TTY_DRIVER
6570                                 if (ioctl(2, TIOCSPGRP, (char *) &pgrp) < 0)
6571                                         error("TIOCSPGRP failed, errno=%d", errno);
6572 #else
6573                                 if (tcsetpgrp(2, pgrp) < 0)
6574                                         error("tcsetpgrp failed, errno=%d", errno);
6575 #endif
6576                         }
6577                         setsignal(SIGTSTP);
6578                         setsignal(SIGTTOU);
6579                 } else if (mode == FORK_BG) {
6580 #else
6581                 if (mode == FORK_BG) {
6582 #endif
6583                         ignoresig(SIGINT);
6584                         ignoresig(SIGQUIT);
6585                         if ((jp == NULL || jp->nprocs == 0) && !fd0_redirected_p()) {
6586                                 close(0);
6587                                 if (open(devnull, O_RDONLY) != 0)
6588                                         error(nullerr, devnull);
6589                         }
6590                 }
6591                 for (i = njobs, p = jobtab; --i >= 0; p++)
6592                         if (p->used)
6593                                 freejob(p);
6594                 if (wasroot && iflag) {
6595                         setsignal(SIGINT);
6596                         setsignal(SIGQUIT);
6597                         setsignal(SIGTERM);
6598                 }
6599                 return pid;
6600         }
6601 #ifdef CONFIG_ASH_JOB_CONTROL
6602         if (rootshell && mode != FORK_NOJOB && mflag) {
6603                 if (jp == NULL || jp->nprocs == 0)
6604                         pgrp = pid;
6605                 else
6606                         pgrp = jp->ps[0].pid;
6607                 setpgid(pid, pgrp);
6608         }
6609 #endif
6610         if (mode == FORK_BG)
6611                 backgndpid = pid;       /* set $! */
6612         if (jp) {
6613                 struct procstat *ps = &jp->ps[jp->nprocs++];
6614
6615                 ps->pid = pid;
6616                 ps->status = -1;
6617                 ps->cmd = nullstr;
6618                 if (iflag && rootshell && n)
6619                         ps->cmd = commandtext(n);
6620         }
6621         INTON;
6622         TRACE(("In parent shell:  child = %d\n", pid));
6623         return pid;
6624 }
6625
6626
6627
6628 /*
6629  * Wait for job to finish.
6630  *
6631  * Under job control we have the problem that while a child process is
6632  * running interrupts generated by the user are sent to the child but not
6633  * to the shell.  This means that an infinite loop started by an inter-
6634  * active user may be hard to kill.  With job control turned off, an
6635  * interactive user may place an interactive program inside a loop.  If
6636  * the interactive program catches interrupts, the user doesn't want
6637  * these interrupts to also abort the loop.  The approach we take here
6638  * is to have the shell ignore interrupt signals while waiting for a
6639  * forground process to terminate, and then send itself an interrupt
6640  * signal if the child process was terminated by an interrupt signal.
6641  * Unfortunately, some programs want to do a bit of cleanup and then
6642  * exit on interrupt; unless these processes terminate themselves by
6643  * sending a signal to themselves (instead of calling exit) they will
6644  * confuse this approach.
6645  */
6646
6647 static int waitforjob(struct job *jp)
6648 {
6649 #ifdef CONFIG_ASH_JOB_CONTROL
6650         int mypgrp = getpgrp();
6651 #endif
6652         int status;
6653         int st;
6654         struct sigaction act, oact;
6655
6656         INTOFF;
6657         intreceived = 0;
6658 #ifdef CONFIG_ASH_JOB_CONTROL
6659         if (!jobctl) {
6660 #else
6661         if (!iflag) {
6662 #endif
6663                 sigaction(SIGINT, 0, &act);
6664                 act.sa_handler = waitonint;
6665                 sigaction(SIGINT, &act, &oact);
6666         }
6667         TRACE(("waitforjob(%%%d) called\n", jp - jobtab + 1));
6668         while (jp->state == 0) {
6669                 dowait(1, jp);
6670         }
6671 #ifdef CONFIG_ASH_JOB_CONTROL
6672         if (!jobctl) {
6673 #else
6674         if (!iflag) {
6675 #endif
6676                 sigaction(SIGINT, &oact, 0);
6677                 if (intreceived)
6678                         kill(getpid(), SIGINT);
6679         }
6680 #ifdef CONFIG_ASH_JOB_CONTROL
6681         if (jp->jobctl) {
6682 #ifdef OLD_TTY_DRIVER
6683                 if (ioctl(2, TIOCSPGRP, (char *) &mypgrp) < 0)
6684                         error("TIOCSPGRP failed, errno=%d\n", errno);
6685 #else
6686                 if (tcsetpgrp(2, mypgrp) < 0)
6687                         error("tcsetpgrp failed, errno=%d\n", errno);
6688 #endif
6689         }
6690         if (jp->state == CONFIG_ASH_JOB_CONTROLTOPPED)
6691                 curjob = jp - jobtab + 1;
6692 #endif
6693         status = jp->ps[jp->nprocs - 1].status;
6694         /* convert to 8 bits */
6695         if (WIFEXITED(status))
6696                 st = WEXITSTATUS(status);
6697 #ifdef CONFIG_ASH_JOB_CONTROL
6698         else if (WIFSTOPPED(status))
6699                 st = WSTOPSIG(status) + 128;
6700 #endif
6701         else
6702                 st = WTERMSIG(status) + 128;
6703 #ifdef CONFIG_ASH_JOB_CONTROL
6704         if (jp->jobctl) {
6705                 /*
6706                  * This is truly gross.
6707                  * If we're doing job control, then we did a TIOCSPGRP which
6708                  * caused us (the shell) to no longer be in the controlling
6709                  * session -- so we wouldn't have seen any ^C/SIGINT.  So, we
6710                  * intuit from the subprocess exit status whether a SIGINT
6711                  * occured, and if so interrupt ourselves.  Yuck.  - mycroft
6712                  */
6713                 if (WIFSIGNALED(status) && WTERMSIG(status) == SIGINT)
6714                         raise(SIGINT);
6715         }
6716         if (jp->state == JOBDONE)
6717 #endif
6718                 freejob(jp);
6719         INTON;
6720         return st;
6721 }
6722
6723
6724
6725 /*
6726  * Wait for a process to terminate.
6727  */
6728
6729 /*
6730  * Do a wait system call.  If job control is compiled in, we accept
6731  * stopped processes.  If block is zero, we return a value of zero
6732  * rather than blocking.
6733  *
6734  * System V doesn't have a non-blocking wait system call.  It does
6735  * have a SIGCLD signal that is sent to a process when one of it's
6736  * children dies.  The obvious way to use SIGCLD would be to install
6737  * a handler for SIGCLD which simply bumped a counter when a SIGCLD
6738  * was received, and have waitproc bump another counter when it got
6739  * the status of a process.  Waitproc would then know that a wait
6740  * system call would not block if the two counters were different.
6741  * This approach doesn't work because if a process has children that
6742  * have not been waited for, System V will send it a SIGCLD when it
6743  * installs a signal handler for SIGCLD.  What this means is that when
6744  * a child exits, the shell will be sent SIGCLD signals continuously
6745  * until is runs out of stack space, unless it does a wait call before
6746  * restoring the signal handler.  The code below takes advantage of
6747  * this (mis)feature by installing a signal handler for SIGCLD and
6748  * then checking to see whether it was called.  If there are any
6749  * children to be waited for, it will be.
6750  *
6751  */
6752
6753 static inline int waitproc(int block, int *status)
6754 {
6755         int flags;
6756
6757         flags = 0;
6758 #ifdef CONFIG_ASH_JOB_CONTROL
6759         if (jobctl)
6760                 flags |= WUNTRACED;
6761 #endif
6762         if (block == 0)
6763                 flags |= WNOHANG;
6764         return wait3(status, flags, (struct rusage *) NULL);
6765 }
6766
6767 static int dowait(int block, struct job *job)
6768 {
6769         int pid;
6770         int status;
6771         struct procstat *sp;
6772         struct job *jp;
6773         struct job *thisjob;
6774         int done;
6775         int stopped;
6776         int core;
6777         int sig;
6778
6779         TRACE(("dowait(%d) called\n", block));
6780         do {
6781                 pid = waitproc(block, &status);
6782                 TRACE(("wait returns %d, status=%d\n", pid, status));
6783         } while (!(block & 2) && pid == -1 && errno == EINTR);
6784         if (pid <= 0)
6785                 return pid;
6786         INTOFF;
6787         thisjob = NULL;
6788         for (jp = jobtab; jp < jobtab + njobs; jp++) {
6789                 if (jp->used) {
6790                         done = 1;
6791                         stopped = 1;
6792                         for (sp = jp->ps; sp < jp->ps + jp->nprocs; sp++) {
6793                                 if (sp->pid == -1)
6794                                         continue;
6795                                 if (sp->pid == pid) {
6796                                         TRACE(("Changing status of proc %d from 0x%x to 0x%x\n",
6797                                                    pid, sp->status, status));
6798                                         sp->status = status;
6799                                         thisjob = jp;
6800                                 }
6801                                 if (sp->status == -1)
6802                                         stopped = 0;
6803                                 else if (WIFSTOPPED(sp->status))
6804                                         done = 0;
6805                         }
6806                         if (stopped) {  /* stopped or done */
6807                                 int state = done ? JOBDONE : CONFIG_ASH_JOB_CONTROLTOPPED;
6808
6809                                 if (jp->state != state) {
6810                                         TRACE(("Job %d: changing state from %d to %d\n",
6811                                                    jp - jobtab + 1, jp->state, state));
6812                                         jp->state = state;
6813 #ifdef CONFIG_ASH_JOB_CONTROL
6814                                         if (done && curjob == jp - jobtab + 1)
6815                                                 curjob = 0;     /* no current job */
6816 #endif
6817                                 }
6818                         }
6819                 }
6820         }
6821         INTON;
6822         if (!rootshell || !iflag || (job && thisjob == job)) {
6823                 core = WCOREDUMP(status);
6824 #ifdef CONFIG_ASH_JOB_CONTROL
6825                 if (WIFSTOPPED(status))
6826                         sig = WSTOPSIG(status);
6827                 else
6828 #endif
6829                 if (WIFEXITED(status))
6830                         sig = 0;
6831                 else
6832                         sig = WTERMSIG(status);
6833
6834                 if (sig != 0 && sig != SIGINT && sig != SIGPIPE) {
6835                         if (thisjob != job)
6836                                 out2fmt("%d: ", pid);
6837 #ifdef CONFIG_ASH_JOB_CONTROL
6838                         if (sig == SIGTSTP && rootshell && iflag)
6839                                 out2fmt("%%%ld ", (long) (job - jobtab + 1));
6840 #endif
6841                         if (sig < NSIG && sys_siglist[sig])
6842                                 out2str(sys_siglist[sig]);
6843                         else
6844                                 out2fmt("Signal %d", sig);
6845                         if (core)
6846                                 out2str(" - core dumped");
6847                         out2c('\n');
6848                 } else {
6849                         TRACE(("Not printing status: status=%d, sig=%d\n", status, sig));
6850                 }
6851         } else {
6852                 TRACE(("Not printing status, rootshell=%d, job=0x%x\n", rootshell,
6853                            job));
6854                 if (thisjob)
6855                         thisjob->changed = 1;
6856         }
6857         return pid;
6858 }
6859
6860
6861
6862
6863 /*
6864  * return 1 if there are stopped jobs, otherwise 0
6865  */
6866 static int stoppedjobs(void)
6867 {
6868         int jobno;
6869         struct job *jp;
6870
6871         if (job_warning)
6872                 return (0);
6873         for (jobno = 1, jp = jobtab; jobno <= njobs; jobno++, jp++) {
6874                 if (jp->used == 0)
6875                         continue;
6876                 if (jp->state == CONFIG_ASH_JOB_CONTROLTOPPED) {
6877                         out2str("You have stopped jobs.\n");
6878                         job_warning = 2;
6879                         return (1);
6880                 }
6881         }
6882
6883         return (0);
6884 }
6885
6886 /*
6887  * Return a string identifying a command (to be printed by the
6888  * jobs command.
6889  */
6890
6891 static char *cmdnextc;
6892 static int cmdnleft;
6893
6894 #define MAXCMDTEXT      200
6895
6896 static void cmdputs(const char *s)
6897 {
6898         const char *p;
6899         char *q;
6900         char c;
6901         int subtype = 0;
6902
6903         if (cmdnleft <= 0)
6904                 return;
6905         p = s;
6906         q = cmdnextc;
6907         while ((c = *p++) != '\0') {
6908                 if (c == CTLESC)
6909                         *q++ = *p++;
6910                 else if (c == CTLVAR) {
6911                         *q++ = '$';
6912                         if (--cmdnleft > 0)
6913                                 *q++ = '{';
6914                         subtype = *p++;
6915                 } else if (c == '=' && subtype != 0) {
6916                         *q++ = "}-+?="[(subtype & VSTYPE) - VSNORMAL];
6917                         subtype = 0;
6918                 } else if (c == CTLENDVAR) {
6919                         *q++ = '}';
6920                 } else if (c == CTLBACKQ || c == CTLBACKQ + CTLQUOTE)
6921                         cmdnleft++;     /* ignore it */
6922                 else
6923                         *q++ = c;
6924                 if (--cmdnleft <= 0) {
6925                         *q++ = '.';
6926                         *q++ = '.';
6927                         *q++ = '.';
6928                         break;
6929                 }
6930         }
6931         cmdnextc = q;
6932 }
6933
6934 #define CMDTXT_TABLE
6935 #ifdef CMDTXT_TABLE
6936 /*
6937  * To collect a lot of redundant code in cmdtxt() case statements, we
6938  * implement a mini language here.  Each type of node struct has an
6939  * associated instruction sequence that operates on its members via
6940  * their offsets.  The instruction are pack in unsigned chars with
6941  * format   IIDDDDDE   where the bits are
6942  *   I : part of the instruction opcode, which are
6943  *       00 : member is a pointer to another node -- process it recursively
6944  *       40 : member is a pointer to a char string -- output it
6945  *       80 : output the string whose index is stored in the data field
6946  *       CC : flag signaling that this case needs external processing
6947  *   D : data - either the (shifted) index of a fixed string to output or
6948  *              the actual offset of the member to operate on in the struct
6949  *              (since we assume bit 0 is set, the offset is not shifted)
6950  *   E : flag signaling end of instruction sequence
6951  *
6952  * WARNING: In order to handle larger offsets for 64bit archs, this code
6953  *          assumes that no offset can be an odd number and stores the
6954  *          end-of-instructions flag in bit 0.
6955  */
6956
6957 #define CMDTXT_NOMORE      0x01 /* NOTE: no offset should be odd */
6958 #define CMDTXT_CHARPTR     0x40
6959 #define CMDTXT_STRING      0x80
6960 #define CMDTXT_SPECIAL     0xC0
6961 #define CMDTXT_OFFSETMASK  0x3E
6962
6963 static const char *const cmdtxt_strings[] = {
6964         /* 0     1    2    3       4       5      6          7     */
6965         "; ", "(", ")", " && ", " || ", "if ", "; then ", "...",
6966         /* 8         9        10       11        12      13       */
6967         "while ", "; do ", "; done", "until ", "for ", " in ...",
6968         /* 14       15     16        17     */
6969         "case ", "???", "() ...", "<<..."
6970 };
6971
6972 static const char *const redir_strings[] = {
6973         ">", "<", "<>", ">>", ">|", ">&", "<&"
6974 };
6975
6976 static const unsigned char cmdtxt_ops[] = {
6977 #define CMDTXT_NSEMI    0
6978         offsetof(union node, nbinary.ch1),
6979         0 | CMDTXT_STRING,
6980         offsetof(union node, nbinary.ch2) | CMDTXT_NOMORE,
6981 #define CMDTXT_NCMD     (CMDTXT_NSEMI + 3)
6982 #define CMDTXT_NPIPE    (CMDTXT_NCMD)
6983 #define  CMDTXT_NCASE    (CMDTXT_NCMD)
6984 #define  CMDTXT_NTO      (CMDTXT_NCMD)
6985 #define  CMDTXT_NFROM    (CMDTXT_NCMD)
6986 #define  CMDTXT_NFROMTO  (CMDTXT_NCMD)
6987 #define  CMDTXT_NAPPEND  (CMDTXT_NCMD)
6988 #define  CMDTXT_NTOOV    (CMDTXT_NCMD)
6989 #define  CMDTXT_NTOFD    (CMDTXT_NCMD)
6990 #define  CMDTXT_NFROMFD  (CMDTXT_NCMD)
6991         CMDTXT_SPECIAL,
6992 #define CMDTXT_NREDIR   (CMDTXT_NPIPE + 1)
6993 #define CMDTXT_NBACKGND (CMDTXT_NREDIR)
6994         offsetof(union node, nredir.n) | CMDTXT_NOMORE,
6995 #define CMDTXT_NSUBSHELL (CMDTXT_NBACKGND + 1)
6996         (1 * 2) | CMDTXT_STRING,
6997         offsetof(union node, nredir.n),
6998         (2 * 2) | CMDTXT_STRING | CMDTXT_NOMORE,
6999 #define CMDTXT_NAND     (CMDTXT_NSUBSHELL + 3)
7000         offsetof(union node, nbinary.ch1),
7001         (3 * 2) | CMDTXT_STRING,
7002         offsetof(union node, nbinary.ch2) | CMDTXT_NOMORE,
7003 #define CMDTXT_NOR      (CMDTXT_NAND + 3)
7004         offsetof(union node, nbinary.ch1),
7005         (4 * 2) | CMDTXT_STRING,
7006         offsetof(union node, nbinary.ch2) | CMDTXT_NOMORE,
7007 #define CMDTXT_NIF      (CMDTXT_NOR + 3)
7008         (5 * 2) | CMDTXT_STRING,
7009         offsetof(union node, nif.test),
7010         (6 * 2) | CMDTXT_STRING,
7011         offsetof(union node, nif.ifpart),
7012         (7 * 2) | CMDTXT_STRING | CMDTXT_NOMORE,
7013 #define CMDTXT_NWHILE   (CMDTXT_NIF + 5)
7014         (8 * 2) | CMDTXT_STRING,
7015         offsetof(union node, nbinary.ch1),
7016         (9 * 2) | CMDTXT_STRING,
7017         offsetof(union node, nbinary.ch2),
7018         (10 * 2) | CMDTXT_STRING | CMDTXT_NOMORE,
7019 #define CMDTXT_NUNTIL   (CMDTXT_NWHILE + 5)
7020         (11 * 2) | CMDTXT_STRING,
7021         offsetof(union node, nbinary.ch1),
7022         (9 * 2) | CMDTXT_STRING,
7023         offsetof(union node, nbinary.ch2),
7024         (10 * 2) | CMDTXT_STRING | CMDTXT_NOMORE,
7025 #define CMDTXT_NFOR     (CMDTXT_NUNTIL + 5)
7026         (12 * 2) | CMDTXT_STRING,
7027         offsetof(union node, nfor.var) | CMDTXT_CHARPTR,
7028         (13 * 2) | CMDTXT_STRING | CMDTXT_NOMORE,
7029 #define CMDTXT_NCLIST   (CMDTXT_NFOR + 3)       /* TODO: IS THIS CORRECT??? */
7030 #define  CMDTXT_NNOT     (CMDTXT_NCLIST)        /* TODO: IS THIS CORRECT??? */
7031         (15 * 2) | CMDTXT_STRING | CMDTXT_NOMORE,
7032 #define CMDTXT_NDEFUN   (CMDTXT_NCLIST + 1)
7033         offsetof(union node, narg.text) | CMDTXT_CHARPTR,
7034         (16 * 2) | CMDTXT_STRING | CMDTXT_NOMORE,
7035 #define CMDTXT_NARG     (CMDTXT_NDEFUN + 2)
7036         offsetof(union node, narg.text) | CMDTXT_CHARPTR | CMDTXT_NOMORE,
7037 #define CMDTXT_NHERE    (CMDTXT_NARG + 1)
7038 #define CMDTXT_NXHERE   (CMDTXT_NHERE)
7039         (17 * 2) | CMDTXT_STRING | CMDTXT_NOMORE,
7040 };
7041
7042 #if CMDTXT_NXHERE != 36
7043 #error CMDTXT_NXHERE
7044 #endif
7045
7046 static const unsigned char cmdtxt_ops_index[26] = {
7047         CMDTXT_NSEMI,
7048         CMDTXT_NCMD,
7049         CMDTXT_NPIPE,
7050         CMDTXT_NREDIR,
7051         CMDTXT_NBACKGND,
7052         CMDTXT_NSUBSHELL,
7053         CMDTXT_NAND,
7054         CMDTXT_NOR,
7055         CMDTXT_NIF,
7056         CMDTXT_NWHILE,
7057         CMDTXT_NUNTIL,
7058         CMDTXT_NFOR,
7059         CMDTXT_NCASE,
7060         CMDTXT_NCLIST,
7061         CMDTXT_NDEFUN,
7062         CMDTXT_NARG,
7063         CMDTXT_NTO,
7064         CMDTXT_NFROM,
7065         CMDTXT_NFROMTO,
7066         CMDTXT_NAPPEND,
7067         CMDTXT_NTOOV,
7068         CMDTXT_NTOFD,
7069         CMDTXT_NFROMFD,
7070         CMDTXT_NHERE,
7071         CMDTXT_NXHERE,
7072         CMDTXT_NNOT,
7073 };
7074
7075 static void cmdtxt(const union node *n)
7076 {
7077         const char *p;
7078
7079         if (n == NULL)
7080                 return;
7081
7082         p = cmdtxt_ops + (int) cmdtxt_ops_index[n->type];
7083         if ((*p & CMDTXT_SPECIAL) != CMDTXT_SPECIAL) {  /* normal case */
7084                 do {
7085                         if (*p & CMDTXT_STRING) {       /* output fixed string */
7086                                 cmdputs(cmdtxt_strings
7087                                                 [((int) (*p & CMDTXT_OFFSETMASK) >> 1)]);
7088                         } else {
7089                                 const char *pf = ((const char *) n)
7090                                         + ((int) (*p & CMDTXT_OFFSETMASK));
7091
7092                                 if (*p & CMDTXT_CHARPTR) {      /* output dynamic string */
7093                                         cmdputs(*((const char **) pf));
7094                                 } else {        /* output field */
7095                                         cmdtxt(*((const union node **) pf));
7096                                 }
7097                         }
7098                 } while (!(*p++ & CMDTXT_NOMORE));
7099         } else if (n->type == NCMD) {
7100                 union node *np;
7101
7102                 for (np = n->ncmd.args; np; np = np->narg.next) {
7103                         cmdtxt(np);
7104                         if (np->narg.next)
7105                                 cmdputs(spcstr);
7106                 }
7107                 for (np = n->ncmd.redirect; np; np = np->nfile.next) {
7108                         cmdputs(spcstr);
7109                         cmdtxt(np);
7110                 }
7111         } else if (n->type == NPIPE) {
7112                 struct nodelist *lp;
7113
7114                 for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
7115                         cmdtxt(lp->n);
7116                         if (lp->next)
7117                                 cmdputs(" | ");
7118                 }
7119         } else if (n->type == NCASE) {
7120                 cmdputs(cmdtxt_strings[14]);
7121                 cmdputs(n->ncase.expr->narg.text);
7122                 cmdputs(cmdtxt_strings[13]);
7123         } else {
7124 #if (NTO != 16) || (NFROM != 17) || (NFROMTO != 18) || (NAPPEND != 19) || (NTOOV != 20) || (NTOFD != 21) || (NFROMFD != 22)
7125 #error Assumption violated regarding range and ordering of NTO ... NFROMFD!
7126 #endif
7127                 char s[2];
7128
7129 #ifdef DEBUG
7130                 assert((n->type >= NTO) && (n->type <= NFROMFD));
7131 #endif
7132
7133                 p = redir_strings[n->type - NTO];
7134                 if (n->nfile.fd != ('>' == *p)) {
7135                         s[0] = n->nfile.fd + '0';
7136                         s[1] = '\0';
7137                         cmdputs(s);
7138                 }
7139                 cmdputs(p);
7140                 if (n->type >= NTOFD) {
7141                         s[0] = n->ndup.dupfd + '0';
7142                         s[1] = '\0';
7143                         cmdputs(s);
7144                 } else {
7145                         cmdtxt(n->nfile.fname);
7146                 }
7147         }
7148 }
7149 #else                                                   /* CMDTXT_TABLE */
7150 static void cmdtxt(const union node *n)
7151 {
7152         union node *np;
7153         struct nodelist *lp;
7154         const char *p;
7155         int i;
7156         char s[2];
7157
7158         if (n == NULL)
7159                 return;
7160         switch (n->type) {
7161         case NSEMI:
7162                 cmdtxt(n->nbinary.ch1);
7163                 cmdputs("; ");
7164                 cmdtxt(n->nbinary.ch2);
7165                 break;
7166         case NAND:
7167                 cmdtxt(n->nbinary.ch1);
7168                 cmdputs(" && ");
7169                 cmdtxt(n->nbinary.ch2);
7170                 break;
7171         case NOR:
7172                 cmdtxt(n->nbinary.ch1);
7173                 cmdputs(" || ");
7174                 cmdtxt(n->nbinary.ch2);
7175                 break;
7176         case NPIPE:
7177                 for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
7178                         cmdtxt(lp->n);
7179                         if (lp->next)
7180                                 cmdputs(" | ");
7181                 }
7182                 break;
7183         case NSUBSHELL:
7184                 cmdputs("(");
7185                 cmdtxt(n->nredir.n);
7186                 cmdputs(")");
7187                 break;
7188         case NREDIR:
7189         case NBACKGND:
7190                 cmdtxt(n->nredir.n);
7191                 break;
7192         case NIF:
7193                 cmdputs("if ");
7194                 cmdtxt(n->nif.test);
7195                 cmdputs("; then ");
7196                 cmdtxt(n->nif.ifpart);
7197                 cmdputs("...");
7198                 break;
7199         case NWHILE:
7200                 cmdputs("while ");
7201                 goto until;
7202         case NUNTIL:
7203                 cmdputs("until ");
7204           until:
7205                 cmdtxt(n->nbinary.ch1);
7206                 cmdputs("; do ");
7207                 cmdtxt(n->nbinary.ch2);
7208                 cmdputs("; done");
7209                 break;
7210         case NFOR:
7211                 cmdputs("for ");
7212                 cmdputs(n->nfor.var);
7213                 cmdputs(" in ...");
7214                 break;
7215         case NCASE:
7216                 cmdputs("case ");
7217                 cmdputs(n->ncase.expr->narg.text);
7218                 cmdputs(" in ...");
7219                 break;
7220         case NDEFUN:
7221                 cmdputs(n->narg.text);
7222                 cmdputs("() ...");
7223                 break;
7224         case NCMD:
7225                 for (np = n->ncmd.args; np; np = np->narg.next) {
7226                         cmdtxt(np);
7227                         if (np->narg.next)
7228                                 cmdputs(spcstr);
7229                 }
7230                 for (np = n->ncmd.redirect; np; np = np->nfile.next) {
7231                         cmdputs(spcstr);
7232                         cmdtxt(np);
7233                 }
7234                 break;
7235         case NARG:
7236                 cmdputs(n->narg.text);
7237                 break;
7238         case NTO:
7239                 p = ">";
7240                 i = 1;
7241                 goto redir;
7242         case NAPPEND:
7243                 p = ">>";
7244                 i = 1;
7245                 goto redir;
7246         case NTOFD:
7247                 p = ">&";
7248                 i = 1;
7249                 goto redir;
7250         case NTOOV:
7251                 p = ">|";
7252                 i = 1;
7253                 goto redir;
7254         case NFROM:
7255                 p = "<";
7256                 i = 0;
7257                 goto redir;
7258         case NFROMFD:
7259                 p = "<&";
7260                 i = 0;
7261                 goto redir;
7262         case NFROMTO:
7263                 p = "<>";
7264                 i = 0;
7265                 goto redir;
7266           redir:
7267                 if (n->nfile.fd != i) {
7268                         s[0] = n->nfile.fd + '0';
7269                         s[1] = '\0';
7270                         cmdputs(s);
7271                 }
7272                 cmdputs(p);
7273                 if (n->type == NTOFD || n->type == NFROMFD) {
7274                         s[0] = n->ndup.dupfd + '0';
7275                         s[1] = '\0';
7276                         cmdputs(s);
7277                 } else {
7278                         cmdtxt(n->nfile.fname);
7279                 }
7280                 break;
7281         case NHERE:
7282         case NXHERE:
7283                 cmdputs("<<...");
7284                 break;
7285         default:
7286                 cmdputs("???");
7287                 break;
7288         }
7289 }
7290 #endif                                                  /* CMDTXT_TABLE */
7291
7292 static char *commandtext(const union node *n)
7293 {
7294         char *name;
7295
7296         cmdnextc = name = xmalloc(MAXCMDTEXT);
7297         cmdnleft = MAXCMDTEXT - 4;
7298         cmdtxt(n);
7299         *cmdnextc = '\0';
7300         return name;
7301 }
7302
7303
7304 static void waitonint(int sig)
7305 {
7306         intreceived = 1;
7307 }
7308
7309 #ifdef CONFIG_ASH_MAIL
7310
7311 /*
7312  * Routines to check for mail.
7313  */
7314
7315
7316 #define MAXMBOXES 10
7317
7318
7319 static int nmboxes;             /* number of mailboxes */
7320 static time_t mailtime[MAXMBOXES];      /* times of mailboxes */
7321
7322
7323
7324 /*
7325  * Print appropriate message(s) if mail has arrived.  If the argument is
7326  * nozero, then the value of MAIL has changed, so we just update the
7327  * values.
7328  */
7329
7330 static void chkmail(int silent)
7331 {
7332         int i;
7333         const char *mpath;
7334         char *p;
7335         char *q;
7336         struct stackmark smark;
7337         struct stat statb;
7338
7339         if (silent)
7340                 nmboxes = 10;
7341         if (nmboxes == 0)
7342                 return;
7343         setstackmark(&smark);
7344         mpath = mpathset()? mpathval() : mailval();
7345         for (i = 0; i < nmboxes; i++) {
7346                 p = padvance(&mpath, nullstr);
7347                 if (p == NULL)
7348                         break;
7349                 if (*p == '\0')
7350                         continue;
7351                 for (q = p; *q; q++);
7352 #ifdef DEBUG
7353                 if (q[-1] != '/')
7354                         abort();
7355 #endif
7356                 q[-1] = '\0';   /* delete trailing '/' */
7357                 if (stat(p, &statb) < 0)
7358                         statb.st_size = 0;
7359                 if (statb.st_size > mailtime[i] && !silent) {
7360                         out2fmt(snlfmt, pathopt ? pathopt : "you have mail");
7361                 }
7362                 mailtime[i] = statb.st_size;
7363         }
7364         nmboxes = i;
7365         popstackmark(&smark);
7366 }
7367
7368 #endif                                                  /* CONFIG_ASH_MAIL */
7369
7370 #define PROFILE 0
7371
7372 #if PROFILE
7373 static short profile_buf[16384];
7374 extern int etext();
7375 #endif
7376
7377 static int isloginsh = 0;
7378
7379 static void read_profile(const char *);
7380 static void cmdloop(int);
7381 static void options(int);
7382 static void setoption(int, int);
7383 static void procargs(int, char **);
7384
7385
7386 /*
7387  * Main routine.  We initialize things, parse the arguments, execute
7388  * profiles if we're a login shell, and then call cmdloop to execute
7389  * commands.  The setjmp call sets up the location to jump to when an
7390  * exception occurs.  When an exception occurs the variable "state"
7391  * is used to figure out how far we had gotten.
7392  */
7393
7394 int ash_main(int argc, char **argv)
7395 {
7396         struct jmploc jmploc;
7397         struct stackmark smark;
7398         volatile int state;
7399         const char *shinit;
7400
7401         BLTINCMD = find_builtin("builtin");
7402         EXECCMD = find_builtin("exec");
7403         EVALCMD = find_builtin("eval");
7404
7405 #ifndef CONFIG_FEATURE_SH_FANCY_PROMPT
7406         unsetenv("PS1");
7407         unsetenv("PS2");
7408 #endif
7409
7410 #if PROFILE
7411         monitor(4, etext, profile_buf, sizeof profile_buf, 50);
7412 #endif
7413 #if defined(linux) || defined(__GNU__)
7414         signal(SIGCHLD, SIG_DFL);
7415 #endif
7416         state = 0;
7417         if (setjmp(jmploc.loc)) {
7418                 INTOFF;
7419                 /*
7420                  * When a shell procedure is executed, we raise the
7421                  * exception EXSHELLPROC to clean up before executing
7422                  * the shell procedure.
7423                  */
7424                 if (exception == EXSHELLPROC) {
7425                         rootpid = getpid();
7426                         rootshell = 1;
7427                         minusc = NULL;
7428                         state = 3;
7429                 } else {
7430                         if (exception == EXEXEC) {
7431                                 exitstatus = exerrno;
7432                         } else if (exception == EXERROR) {
7433                                 exitstatus = 2;
7434                         }
7435                         if (state == 0 || iflag == 0 || !rootshell)
7436                                 exitshell(exitstatus);
7437                 }
7438                 reset();
7439                 if (exception == EXINT) {
7440                         out2c('\n');
7441                 }
7442                 popstackmark(&smark);
7443                 FORCEINTON;             /* enable interrupts */
7444                 if (state == 1)
7445                         goto state1;
7446                 else if (state == 2)
7447                         goto state2;
7448                 else if (state == 3)
7449                         goto state3;
7450                 else
7451                         goto state4;
7452         }
7453         handler = &jmploc;
7454 #ifdef DEBUG
7455         opentrace();
7456         trputs("Shell args:  ");
7457         trargs(argv);
7458 #endif
7459         rootpid = getpid();
7460         rootshell = 1;
7461         init();
7462         setstackmark(&smark);
7463         procargs(argc, argv);
7464         if (argv[0] && argv[0][0] == '-')
7465                 isloginsh = 1;
7466         if (isloginsh) {
7467                 state = 1;
7468                 read_profile("/etc/profile");
7469           state1:
7470                 state = 2;
7471                 read_profile(".profile");
7472         }
7473   state2:
7474         state = 3;
7475 #ifndef linux
7476         if (getuid() == geteuid() && getgid() == getegid()) {
7477 #endif
7478                 if ((shinit = lookupvar("ENV")) != NULL && *shinit != '\0') {
7479                         state = 3;
7480                         read_profile(shinit);
7481                 }
7482 #ifndef linux
7483         }
7484 #endif
7485   state3:
7486         state = 4;
7487         if (sflag == 0 || minusc) {
7488                 static const char sigs[] = {
7489                         SIGINT, SIGQUIT, SIGHUP,
7490 #ifdef SIGTSTP
7491                         SIGTSTP,
7492 #endif
7493                         SIGPIPE
7494                 };
7495
7496 #define SIGSSIZE ((sizeof(sigs)/sizeof(sigs[0])) - 1)   /* trailing nul */
7497                 int i;
7498
7499                 for (i = 0; i < SIGSSIZE; i++)
7500                         setsignal(sigs[i]);
7501         }
7502
7503         if (minusc)
7504                 evalstring(minusc, 0);
7505
7506         if (sflag || minusc == NULL) {
7507           state4:                       /* XXX ??? - why isn't this before the "if" statement */
7508                 cmdloop(1);
7509         }
7510 #if PROFILE
7511         monitor(0);
7512 #endif
7513         exitshell(exitstatus);
7514         /* NOTREACHED */
7515 }
7516
7517
7518 /*
7519  * Read and execute commands.  "Top" is nonzero for the top level command
7520  * loop; it turns on prompting if the shell is interactive.
7521  */
7522
7523 static void cmdloop(int top)
7524 {
7525         union node *n;
7526         struct stackmark smark;
7527         int inter;
7528         int numeof = 0;
7529
7530         TRACE(("cmdloop(%d) called\n", top));
7531         setstackmark(&smark);
7532         for (;;) {
7533                 if (pendingsigs)
7534                         dotrap();
7535                 inter = 0;
7536                 if (iflag && top) {
7537                         inter++;
7538                         showjobs(1);
7539 #ifdef CONFIG_ASH_MAIL
7540                         chkmail(0);
7541 #endif
7542                         flushall();
7543                 }
7544                 n = parsecmd(inter);
7545                 /* showtree(n); DEBUG */
7546                 if (n == NEOF) {
7547                         if (!top || numeof >= 50)
7548                                 break;
7549                         if (!stoppedjobs()) {
7550                                 if (!Iflag)
7551                                         break;
7552                                 out2str("\nUse \"exit\" to leave shell.\n");
7553                         }
7554                         numeof++;
7555                 } else if (n != NULL && nflag == 0) {
7556                         job_warning = (job_warning == 2) ? 1 : 0;
7557                         numeof = 0;
7558                         evaltree(n, 0);
7559                 }
7560                 popstackmark(&smark);
7561                 setstackmark(&smark);
7562                 if (evalskip == SKIPFILE) {
7563                         evalskip = 0;
7564                         break;
7565                 }
7566         }
7567         popstackmark(&smark);
7568 }
7569
7570
7571
7572 /*
7573  * Read /etc/profile or .profile.  Return on error.
7574  */
7575
7576 static void read_profile(const char *name)
7577 {
7578         int fd;
7579         int xflag_save;
7580         int vflag_save;
7581
7582         INTOFF;
7583         if ((fd = open(name, O_RDONLY)) >= 0)
7584                 setinputfd(fd, 1);
7585         INTON;
7586         if (fd < 0)
7587                 return;
7588         /* -q turns off -x and -v just when executing init files */
7589         /* Note: Might do a little redundant work, but reduces code size. */
7590         xflag_save = xflag;
7591         vflag_save = vflag;
7592         if (qflag) {
7593                 vflag = xflag = 0;
7594         }
7595         cmdloop(0);
7596         xflag = xflag_save;
7597         vflag = vflag_save;
7598         popfile();
7599 }
7600
7601
7602
7603 /*
7604  * Read a file containing shell functions.
7605  */
7606
7607 static void readcmdfile(const char *name)
7608 {
7609         int fd;
7610
7611         INTOFF;
7612         if ((fd = open(name, O_RDONLY)) >= 0)
7613                 setinputfd(fd, 1);
7614         else
7615                 error("Can't open %s", name);
7616         INTON;
7617         cmdloop(0);
7618         popfile();
7619 }
7620
7621
7622
7623 /*
7624  * Take commands from a file.  To be compatable we should do a path
7625  * search for the file, which is necessary to find sub-commands.
7626  */
7627
7628 static inline char *find_dot_file(char *mybasename)
7629 {
7630         char *fullname;
7631         const char *path = pathval();
7632         struct stat statb;
7633
7634         /* don't try this for absolute or relative paths */
7635         if (strchr(mybasename, '/'))
7636                 return mybasename;
7637
7638         while ((fullname = padvance(&path, mybasename)) != NULL) {
7639                 if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) {
7640                         /*
7641                          * Don't bother freeing here, since it will
7642                          * be freed by the caller.
7643                          */
7644                         return fullname;
7645                 }
7646                 stunalloc(fullname);
7647         }
7648
7649         /* not found in the PATH */
7650         error("%s: not found", mybasename);
7651         /* NOTREACHED */
7652 }
7653
7654 static int dotcmd(int argc, char **argv)
7655 {
7656         struct strlist *sp;
7657         volatile struct shparam saveparam;
7658
7659         exitstatus = 0;
7660
7661         for (sp = cmdenviron; sp; sp = sp->next)
7662                 setvareq(xstrdup(sp->text), VSTRFIXED | VTEXTFIXED);
7663
7664         if (argc >= 2) {        /* That's what SVR2 does */
7665                 char *fullname;
7666                 struct stackmark smark;
7667
7668                 setstackmark(&smark);
7669                 fullname = find_dot_file(argv[1]);
7670
7671                 if (argc > 2) {
7672                         saveparam = shellparam;
7673                         shellparam.malloc = 0;
7674                         shellparam.nparam = argc - 2;
7675                         shellparam.p = argv + 2;
7676                 };
7677
7678                 setinputfile(fullname, 1);
7679                 commandname = fullname;
7680                 cmdloop(0);
7681                 popfile();
7682
7683                 if (argc > 2) {
7684                         freeparam(&shellparam);
7685                         shellparam = saveparam;
7686                 };
7687
7688                 popstackmark(&smark);
7689         }
7690         return exitstatus;
7691 }
7692
7693
7694 static int exitcmd(int argc, char **argv)
7695 {
7696         if (stoppedjobs())
7697                 return 0;
7698         if (argc > 1)
7699                 exitstatus = number(argv[1]);
7700         else
7701                 exitstatus = oexitstatus;
7702         exitshell(exitstatus);
7703         /* NOTREACHED */
7704 }
7705
7706 static pointer stalloc(int nbytes)
7707 {
7708         char *p;
7709
7710         nbytes = ALIGN(nbytes);
7711         if (nbytes > stacknleft) {
7712                 int blocksize;
7713                 struct stack_block *sp;
7714
7715                 blocksize = nbytes;
7716                 if (blocksize < MINSIZE)
7717                         blocksize = MINSIZE;
7718                 INTOFF;
7719                 sp = xmalloc(sizeof(struct stack_block) - MINSIZE + blocksize);
7720                 sp->prev = stackp;
7721                 stacknxt = sp->space;
7722                 stacknleft = blocksize;
7723                 stackp = sp;
7724                 INTON;
7725         }
7726         p = stacknxt;
7727         stacknxt += nbytes;
7728         stacknleft -= nbytes;
7729         return p;
7730 }
7731
7732
7733 static void stunalloc(pointer p)
7734 {
7735 #ifdef DEBUG
7736         if (p == NULL) {        /*DEBUG */
7737                 write(2, "stunalloc\n", 10);
7738                 abort();
7739         }
7740 #endif
7741         if (!(stacknxt >= (char *) p && (char *) p >= stackp->space)) {
7742                 p = stackp->space;
7743         }
7744         stacknleft += stacknxt - (char *) p;
7745         stacknxt = p;
7746 }
7747
7748
7749 static void setstackmark(struct stackmark *mark)
7750 {
7751         mark->stackp = stackp;
7752         mark->stacknxt = stacknxt;
7753         mark->stacknleft = stacknleft;
7754         mark->marknext = markp;
7755         markp = mark;
7756 }
7757
7758
7759 static void popstackmark(struct stackmark *mark)
7760 {
7761         struct stack_block *sp;
7762
7763         INTOFF;
7764         markp = mark->marknext;
7765         while (stackp != mark->stackp) {
7766                 sp = stackp;
7767                 stackp = sp->prev;
7768                 free(sp);
7769         }
7770         stacknxt = mark->stacknxt;
7771         stacknleft = mark->stacknleft;
7772         INTON;
7773 }
7774
7775
7776 /*
7777  * When the parser reads in a string, it wants to stick the string on the
7778  * stack and only adjust the stack pointer when it knows how big the
7779  * string is.  Stackblock (defined in stack.h) returns a pointer to a block
7780  * of space on top of the stack and stackblocklen returns the length of
7781  * this block.  Growstackblock will grow this space by at least one byte,
7782  * possibly moving it (like realloc).  Grabstackblock actually allocates the
7783  * part of the block that has been used.
7784  */
7785
7786 static void growstackblock(void)
7787 {
7788         char *p;
7789         int newlen = ALIGN(stacknleft * 2 + 100);
7790         char *oldspace = stacknxt;
7791         int oldlen = stacknleft;
7792         struct stack_block *sp;
7793         struct stack_block *oldstackp;
7794
7795         if (stacknxt == stackp->space && stackp != &stackbase) {
7796                 INTOFF;
7797                 oldstackp = stackp;
7798                 sp = stackp;
7799                 stackp = sp->prev;
7800                 sp = xrealloc((pointer) sp,
7801                                           sizeof(struct stack_block) - MINSIZE + newlen);
7802                 sp->prev = stackp;
7803                 stackp = sp;
7804                 stacknxt = sp->space;
7805                 stacknleft = newlen;
7806                 {
7807                         /* Stack marks pointing to the start of the old block
7808                          * must be relocated to point to the new block
7809                          */
7810                         struct stackmark *xmark;
7811
7812                         xmark = markp;
7813                         while (xmark != NULL && xmark->stackp == oldstackp) {
7814                                 xmark->stackp = stackp;
7815                                 xmark->stacknxt = stacknxt;
7816                                 xmark->stacknleft = stacknleft;
7817                                 xmark = xmark->marknext;
7818                         }
7819                 }
7820                 INTON;
7821         } else {
7822                 p = stalloc(newlen);
7823                 memcpy(p, oldspace, oldlen);
7824                 stacknxt = p;   /* free the space */
7825                 stacknleft += newlen;   /* we just allocated */
7826         }
7827 }
7828
7829
7830
7831 static inline void grabstackblock(int len)
7832 {
7833         len = ALIGN(len);
7834         stacknxt += len;
7835         stacknleft -= len;
7836 }
7837
7838
7839
7840 /*
7841  * The following routines are somewhat easier to use that the above.
7842  * The user declares a variable of type STACKSTR, which may be declared
7843  * to be a register.  The macro STARTSTACKSTR initializes things.  Then
7844  * the user uses the macro STPUTC to add characters to the string.  In
7845  * effect, STPUTC(c, p) is the same as *p++ = c except that the stack is
7846  * grown as necessary.  When the user is done, she can just leave the
7847  * string there and refer to it using stackblock().  Or she can allocate
7848  * the space for it using grabstackstr().  If it is necessary to allow
7849  * someone else to use the stack temporarily and then continue to grow
7850  * the string, the user should use grabstack to allocate the space, and
7851  * then call ungrabstr(p) to return to the previous mode of operation.
7852  *
7853  * USTPUTC is like STPUTC except that it doesn't check for overflow.
7854  * CHECKSTACKSPACE can be called before USTPUTC to ensure that there
7855  * is space for at least one character.
7856  */
7857
7858
7859 static char *growstackstr(void)
7860 {
7861         int len = stackblocksize();
7862
7863         if (herefd >= 0 && len >= 1024) {
7864                 xwrite(herefd, stackblock(), len);
7865                 sstrnleft = len - 1;
7866                 return stackblock();
7867         }
7868         growstackblock();
7869         sstrnleft = stackblocksize() - len - 1;
7870         return stackblock() + len;
7871 }
7872
7873
7874 /*
7875  * Called from CHECKSTRSPACE.
7876  */
7877
7878 static char *makestrspace(size_t newlen)
7879 {
7880         int len = stackblocksize() - sstrnleft;
7881
7882         do {
7883                 growstackblock();
7884                 sstrnleft = stackblocksize() - len;
7885         } while (sstrnleft < newlen);
7886         return stackblock() + len;
7887 }
7888
7889
7890
7891 static void ungrabstackstr(char *s, char *p)
7892 {
7893         stacknleft += stacknxt - s;
7894         stacknxt = s;
7895         sstrnleft = stacknleft - (p - s);
7896 }
7897
7898 /*
7899  * Miscelaneous builtins.
7900  */
7901
7902
7903 #undef rflag
7904
7905 #if !defined(__GLIBC__) || __GLIBC__ == 2 && __GLIBC_MINOR__ < 1
7906 typedef long rlim_t;
7907 #endif
7908
7909
7910
7911 /*
7912  * The read builtin.  The -e option causes backslashes to escape the
7913  * following character.
7914  *
7915  * This uses unbuffered input, which may be avoidable in some cases.
7916  */
7917
7918 static int readcmd(int argc, char **argv)
7919 {
7920         char **ap;
7921         int backslash;
7922         char c;
7923         int rflag;
7924         char *prompt;
7925         const char *ifs;
7926         char *p;
7927         int startword;
7928         int status;
7929         int i;
7930
7931         rflag = 0;
7932         prompt = NULL;
7933         while ((i = nextopt("p:r")) != '\0') {
7934                 if (i == 'p')
7935                         prompt = optionarg;
7936                 else
7937                         rflag = 1;
7938         }
7939         if (prompt && isatty(0)) {
7940                 out2str(prompt);        /* read without cmdedit */
7941                 flushall();
7942         }
7943         if (*(ap = argptr) == NULL)
7944                 error("arg count");
7945         if ((ifs = bltinlookup("IFS")) == NULL)
7946                 ifs = defifs;
7947         status = 0;
7948         startword = 1;
7949         backslash = 0;
7950         STARTSTACKSTR(p);
7951         for (;;) {
7952                 if (read(0, &c, 1) != 1) {
7953                         status = 1;
7954                         break;
7955                 }
7956                 if (c == '\0')
7957                         continue;
7958                 if (backslash) {
7959                         backslash = 0;
7960                         if (c != '\n')
7961                                 STPUTC(c, p);
7962                         continue;
7963                 }
7964                 if (!rflag && c == '\\') {
7965                         backslash++;
7966                         continue;
7967                 }
7968                 if (c == '\n')
7969                         break;
7970                 if (startword && *ifs == ' ' && strchr(ifs, c)) {
7971                         continue;
7972                 }
7973                 startword = 0;
7974                 if (backslash && c == '\\') {
7975                         if (read(0, &c, 1) != 1) {
7976                                 status = 1;
7977                                 break;
7978                         }
7979                         STPUTC(c, p);
7980                 } else if (ap[1] != NULL && strchr(ifs, c) != NULL) {
7981                         STACKSTRNUL(p);
7982                         setvar(*ap, stackblock(), 0);
7983                         ap++;
7984                         startword = 1;
7985                         STARTSTACKSTR(p);
7986                 } else {
7987                         STPUTC(c, p);
7988                 }
7989         }
7990         STACKSTRNUL(p);
7991         /* Remove trailing blanks */
7992         while (stackblock() <= --p && strchr(ifs, *p) != NULL)
7993                 *p = '\0';
7994         setvar(*ap, stackblock(), 0);
7995         while (*++ap != NULL)
7996                 setvar(*ap, nullstr, 0);
7997         return status;
7998 }
7999
8000
8001
8002 static int umaskcmd(int argc, char **argv)
8003 {
8004         static const char permuser[3] = "ugo";
8005         static const char permmode[3] = "rwx";
8006         static const short int permmask[] = {
8007                 S_IRUSR, S_IWUSR, S_IXUSR,
8008                 S_IRGRP, S_IWGRP, S_IXGRP,
8009                 S_IROTH, S_IWOTH, S_IXOTH
8010         };
8011
8012         char *ap;
8013         mode_t mask;
8014         int i;
8015         int symbolic_mode = 0;
8016
8017         while (nextopt("S") != '\0') {
8018                 symbolic_mode = 1;
8019         }
8020
8021         INTOFF;
8022         mask = umask(0);
8023         umask(mask);
8024         INTON;
8025
8026         if ((ap = *argptr) == NULL) {
8027                 if (symbolic_mode) {
8028                         char buf[18];
8029                         char *p = buf;
8030
8031                         for (i = 0; i < 3; i++) {
8032                                 int j;
8033
8034                                 *p++ = permuser[i];
8035                                 *p++ = '=';
8036                                 for (j = 0; j < 3; j++) {
8037                                         if ((mask & permmask[3 * i + j]) == 0) {
8038                                                 *p++ = permmode[j];
8039                                         }
8040                                 }
8041                                 *p++ = ',';
8042                         }
8043                         *--p = 0;
8044                         puts(buf);
8045                 } else {
8046                         printf("%.4o\n", mask);
8047                 }
8048         } else {
8049                 if (is_digit((unsigned char) *ap)) {
8050                         mask = 0;
8051                         do {
8052                                 if (*ap >= '8' || *ap < '0')
8053                                         error("Illegal number: %s", argv[1]);
8054                                 mask = (mask << 3) + (*ap - '0');
8055                         } while (*++ap != '\0');
8056                         umask(mask);
8057                 } else {
8058                         mask = ~mask & 0777;
8059                         if (!parse_mode(ap, &mask)) {
8060                                 error("Illegal mode: %s", ap);
8061                         }
8062                         umask(~mask & 0777);
8063                 }
8064         }
8065         return 0;
8066 }
8067
8068 /*
8069  * ulimit builtin
8070  *
8071  * This code, originally by Doug Gwyn, Doug Kingston, Eric Gisin, and
8072  * Michael Rendell was ripped from pdksh 5.0.8 and hacked for use with
8073  * ash by J.T. Conklin.
8074  *
8075  * Public domain.
8076  */
8077
8078 struct limits {
8079         const char *name;
8080         short cmd;
8081         short factor;           /* multiply by to get rlim_{cur,max} values */
8082 };
8083
8084 static const struct limits limits[] = {
8085 #ifdef RLIMIT_CPU
8086         {"time(seconds)", RLIMIT_CPU, 1},
8087 #endif
8088 #ifdef RLIMIT_FSIZE
8089         {"file(blocks)", RLIMIT_FSIZE, 512},
8090 #endif
8091 #ifdef RLIMIT_DATA
8092         {"data(kbytes)", RLIMIT_DATA, 1024},
8093 #endif
8094 #ifdef RLIMIT_STACK
8095         {"stack(kbytes)", RLIMIT_STACK, 1024},
8096 #endif
8097 #ifdef  RLIMIT_CORE
8098         {"coredump(blocks)", RLIMIT_CORE, 512},
8099 #endif
8100 #ifdef RLIMIT_RSS
8101         {"memory(kbytes)", RLIMIT_RSS, 1024},
8102 #endif
8103 #ifdef RLIMIT_MEMLOCK
8104         {"locked memory(kbytes)", RLIMIT_MEMLOCK, 1024},
8105 #endif
8106 #ifdef RLIMIT_NPROC
8107         {"process(processes)", RLIMIT_NPROC, 1},
8108 #endif
8109 #ifdef RLIMIT_NOFILE
8110         {"nofiles(descriptors)", RLIMIT_NOFILE, 1},
8111 #endif
8112 #ifdef RLIMIT_VMEM
8113         {"vmemory(kbytes)", RLIMIT_VMEM, 1024},
8114 #endif
8115 #ifdef RLIMIT_SWAP
8116         {"swap(kbytes)", RLIMIT_SWAP, 1024},
8117 #endif
8118         {NULL, 0, 0}
8119 };
8120
8121 static int ulimitcmd(int argc, char **argv)
8122 {
8123         static const char unlimited_string[] = "unlimited";
8124         int c;
8125         rlim_t val = 0;
8126         enum { SOFT = 0x1, HARD = 0x2 } how = SOFT | HARD;
8127         const struct limits *l;
8128         int set, all = 0;
8129         int optc, what;
8130         struct rlimit limit;
8131
8132         what = 'f';
8133
8134         while ((optc = nextopt("HSa"
8135 #ifdef RLIMIT_CPU
8136                                                    "t"
8137 #endif
8138 #ifdef RLIMIT_FSIZE
8139                                                    "f"
8140 #endif
8141 #ifdef RLIMIT_DATA
8142                                                    "d"
8143 #endif
8144 #ifdef RLIMIT_STACK
8145                                                    "s"
8146 #endif
8147 #ifdef  RLIMIT_CORE
8148                                                    "c"
8149 #endif
8150 #ifdef RLIMIT_RSS
8151                                                    "m"
8152 #endif
8153 #ifdef RLIMIT_MEMLOCK
8154                                                    "l"
8155 #endif
8156 #ifdef RLIMIT_NPROC
8157                                                    "p"
8158 #endif
8159 #ifdef RLIMIT_NOFILE
8160                                                    "n"
8161 #endif
8162 #ifdef RLIMIT_VMEM
8163                                                    "v"
8164 #endif
8165 #ifdef RLIMIT_SWAP
8166                                                    "w"
8167 #endif
8168                         )) != '\0') {
8169                 if (optc == 'H') {
8170                         how = HARD;
8171                 } else if (optc == 'S') {
8172                         how = SOFT;
8173                 } else if (optc == 'a') {
8174                         all = 1;
8175                 } else {
8176                         what = optc;
8177                 }
8178         }
8179
8180         for (l = limits; l->name; l++) {
8181                 if (l->name[0] == what)
8182                         break;
8183                 if (l->name[1] == 'w' && what == 'w')
8184                         break;
8185         }
8186
8187         set = *argptr ? 1 : 0;
8188         if (set) {
8189                 char *p = *argptr;
8190
8191                 if (all || argptr[1])
8192                         error("too many arguments");
8193                 if (strcmp(p, unlimited_string) == 0)
8194                         val = RLIM_INFINITY;
8195                 else {
8196                         val = (rlim_t) 0;
8197
8198                         while ((c = *p++) >= '0' && c <= '9') {
8199                                 val = (val * 10) + (long) (c - '0');
8200                                 if (val < (rlim_t) 0)
8201                                         break;
8202                         }
8203                         if (c)
8204                                 error("bad number");
8205                         val *= l->factor;
8206                 }
8207         }
8208
8209         if (all) {
8210                 for (l = limits; l->name; l++) {
8211                         printf("%-20s ", l->name);
8212                         getrlimit(l->cmd, &limit);
8213                   OUTPUT_LIMIT:
8214                         if (how & SOFT)
8215                                 val = limit.rlim_cur;
8216                         else if (how & HARD)
8217                                 val = limit.rlim_max;
8218
8219                         if (val == RLIM_INFINITY)
8220                                 puts(unlimited_string);
8221                         else {
8222                                 val /= l->factor;
8223                                 printf("%lld\n", (long long) val);
8224                         }
8225                         if (!all) {
8226                                 break;
8227                         }
8228                 }
8229                 return 0;
8230         }
8231
8232         if (!set) {
8233                 goto OUTPUT_LIMIT;
8234         }
8235
8236         getrlimit(l->cmd, &limit);
8237         if (how & HARD)
8238                 limit.rlim_max = val;
8239         if (how & SOFT)
8240                 limit.rlim_cur = val;
8241         if (setrlimit(l->cmd, &limit) < 0)
8242                 error("error setting limit (%m)");
8243         return 0;
8244 }
8245
8246 /*
8247  * prefix -- see if pfx is a prefix of string.
8248  */
8249
8250 static int prefix(char const *pfx, char const *string)
8251 {
8252         while (*pfx) {
8253                 if (*pfx++ != *string++)
8254                         return 0;
8255         }
8256         return 1;
8257 }
8258
8259 /*
8260  * Return true if s is a string of digits, and save munber in intptr
8261  * nagative is bad
8262  */
8263
8264 static int is_number(const char *p, int *intptr)
8265 {
8266         int ret = 0;
8267
8268         do {
8269                 if (!is_digit(*p))
8270                         return 0;
8271                 ret *= 10;
8272                 ret += digit_val(*p);
8273                 p++;
8274         } while (*p != '\0');
8275
8276         *intptr = ret;
8277         return 1;
8278 }
8279
8280 /*
8281  * Convert a string of digits to an integer, printing an error message on
8282  * failure.
8283  */
8284
8285 static int number(const char *s)
8286 {
8287         int i;
8288
8289         if (!is_number(s, &i))
8290                 error("Illegal number: %s", s);
8291         return i;
8292 }
8293
8294 /*
8295  * Produce a possibly single quoted string suitable as input to the shell.
8296  * The return string is allocated on the stack.
8297  */
8298
8299 static char *single_quote(const char *s)
8300 {
8301         char *p;
8302
8303         STARTSTACKSTR(p);
8304
8305         do {
8306                 char *q = p;
8307                 size_t len1, len1p, len2, len2p;
8308
8309                 len1 = strcspn(s, "'");
8310                 len2 = strspn(s + len1, "'");
8311
8312                 len1p = len1 ? len1 + 2 : len1;
8313                 len2p = len2 + ((len2 < 2) ? len2 : 2);
8314
8315                 CHECKSTRSPACE(len1p + len2p + 1, p);
8316
8317                 if (len1) {
8318                         *p = '\'';
8319                         q = p + 1 + len1;
8320                         memcpy(p + 1, s, len1);
8321                         *q++ = '\'';
8322                         s += len1;
8323                 }
8324
8325                 if (len2 > 1) {
8326                         *q = '"';
8327                         q += 1 + len2;
8328                         memcpy(q + 1, s, len2);
8329                         *q = '"';
8330                         s += len2;
8331                 } else if (len2 == 1) {
8332                         *q++ = '\\';
8333                         *q = '\'';
8334                         s++;
8335                 }
8336
8337                 STADJUST(len1p + len2p, p);
8338         } while (*s);
8339
8340         USTPUTC(0, p);
8341
8342         return grabstackstr(p);
8343 }
8344
8345 /*
8346  * Like strdup but works with the ash stack.
8347  */
8348
8349 static char *sstrdup(const char *p)
8350 {
8351         size_t len = strlen(p) + 1;
8352
8353         return memcpy(stalloc(len), p, len);
8354 }
8355
8356
8357 /*
8358  * Routine for dealing with parsed shell commands.
8359  */
8360
8361
8362 static void sizenodelist(const struct nodelist *);
8363 static struct nodelist *copynodelist(const struct nodelist *);
8364 static char *nodexstrdup(const char *);
8365
8366 #define CALCSIZE_TABLE
8367 #define COPYNODE_TABLE
8368 #if defined(CALCSIZE_TABLE) || defined(COPYNODE_TABLE)
8369 /*
8370  * To collect a lot of redundant code in case statements for copynode()
8371  * and calcsize(), we implement a mini language here.  Each type of node
8372  * struct has an associated instruction sequence that operates on its
8373  * members via their offsets.  The instruction are pack in unsigned chars
8374  * with format   IIDDDDDE   where the bits are
8375  *   I : part of the instruction opcode, which are
8376  *       00 : member is a pointer to another node
8377  *       40 : member is an integer
8378  *       80 : member is a pointer to a nodelist
8379  *       CC : member is a pointer to a char string
8380  *   D : data - the actual offset of the member to operate on in the struct
8381  *              (since we assume bit 0 is set, it is not shifted)
8382  *   E : flag signaling end of instruction sequence
8383  *
8384  * WARNING: In order to handle larger offsets for 64bit archs, this code
8385  *          assumes that no offset can be an odd number and stores the
8386  *          end-of-instructions flag in bit 0.
8387  */
8388
8389 #define NODE_INTEGER    0x40
8390 #define NODE_NODELIST   0x80
8391 #define NODE_CHARPTR    0xC0
8392 #define NODE_NOMORE             0x01    /* Note: no offset should be odd (aligned) */
8393 #define NODE_MBRMASK    0xC0
8394 #define NODE_OFFSETMASK 0x3E
8395
8396 static const unsigned char copynode_ops[35] = {
8397 #define COPYNODE_OPS0   0
8398         offsetof(union node, nbinary.ch2),
8399         offsetof(union node, nbinary.ch1) | NODE_NOMORE,
8400 #define COPYNODE_OPS1   (COPYNODE_OPS0 + 2)
8401         offsetof(union node, ncmd.redirect),
8402         offsetof(union node, ncmd.args),
8403         offsetof(union node, ncmd.assign),
8404         offsetof(union node, ncmd.backgnd) | NODE_INTEGER | NODE_NOMORE,
8405 #define COPYNODE_OPS2   (COPYNODE_OPS1 + 4)
8406         offsetof(union node, npipe.cmdlist) | NODE_NODELIST,
8407         offsetof(union node, npipe.backgnd) | NODE_INTEGER | NODE_NOMORE,
8408 #define COPYNODE_OPS3   (COPYNODE_OPS2 + 2)
8409         offsetof(union node, nredir.redirect),
8410         offsetof(union node, nredir.n) | NODE_NOMORE,
8411 #define COPYNODE_OPS4   (COPYNODE_OPS3 + 2)
8412         offsetof(union node, nif.elsepart),
8413         offsetof(union node, nif.ifpart),
8414         offsetof(union node, nif.test) | NODE_NOMORE,
8415 #define COPYNODE_OPS5   (COPYNODE_OPS4 + 3)
8416         offsetof(union node, nfor.var) | NODE_CHARPTR,
8417         offsetof(union node, nfor.body),
8418         offsetof(union node, nfor.args) | NODE_NOMORE,
8419 #define COPYNODE_OPS6   (COPYNODE_OPS5 + 3)
8420         offsetof(union node, ncase.cases),
8421         offsetof(union node, ncase.expr) | NODE_NOMORE,
8422 #define COPYNODE_OPS7   (COPYNODE_OPS6 + 2)
8423         offsetof(union node, nclist.body),
8424         offsetof(union node, nclist.pattern),
8425         offsetof(union node, nclist.next) | NODE_NOMORE,
8426 #define COPYNODE_OPS8   (COPYNODE_OPS7 + 3)
8427         offsetof(union node, narg.backquote) | NODE_NODELIST,
8428         offsetof(union node, narg.text) | NODE_CHARPTR,
8429         offsetof(union node, narg.next) | NODE_NOMORE,
8430 #define COPYNODE_OPS9   (COPYNODE_OPS8 + 3)
8431         offsetof(union node, nfile.fname),
8432         offsetof(union node, nfile.fd) | NODE_INTEGER,
8433         offsetof(union node, nfile.next) | NODE_NOMORE,
8434 #define COPYNODE_OPS10   (COPYNODE_OPS9 + 3)
8435         offsetof(union node, ndup.vname),
8436         offsetof(union node, ndup.dupfd) | NODE_INTEGER,
8437         offsetof(union node, ndup.fd) | NODE_INTEGER,
8438         offsetof(union node, ndup.next) | NODE_NOMORE,
8439 #define COPYNODE_OPS11   (COPYNODE_OPS10 + 4)
8440         offsetof(union node, nhere.doc),
8441         offsetof(union node, nhere.fd) | NODE_INTEGER,
8442         offsetof(union node, nhere.next) | NODE_NOMORE,
8443 #define COPYNODE_OPS12   (COPYNODE_OPS11 + 3)
8444         offsetof(union node, nnot.com) | NODE_NOMORE,
8445 };
8446
8447 #if COPYNODE_OPS12 != 34
8448 #error COPYNODE_OPS12 is incorrect
8449 #endif
8450
8451 static const unsigned char copynode_ops_index[26] = {
8452         COPYNODE_OPS0,          /* NSEMI */
8453         COPYNODE_OPS1,          /* NCMD */
8454         COPYNODE_OPS2,          /* NPIPE */
8455         COPYNODE_OPS3,          /* NREDIR */
8456         COPYNODE_OPS3,          /* NBACKGND */
8457         COPYNODE_OPS3,          /* NSUBSHELL */
8458         COPYNODE_OPS0,          /* NAND */
8459         COPYNODE_OPS0,          /* NOR */
8460         COPYNODE_OPS4,          /* NIF */
8461         COPYNODE_OPS0,          /* NWHILE */
8462         COPYNODE_OPS0,          /* NUNTIL */
8463         COPYNODE_OPS5,          /* NFOR */
8464         COPYNODE_OPS6,          /* NCASE */
8465         COPYNODE_OPS7,          /* NCLIST */
8466         COPYNODE_OPS8,          /* NDEFUN */
8467         COPYNODE_OPS8,          /* NARG */
8468         COPYNODE_OPS9,          /* NTO */
8469         COPYNODE_OPS9,          /* NFROM */
8470         COPYNODE_OPS9,          /* NFROMTO */
8471         COPYNODE_OPS9,          /* NAPPEND */
8472         COPYNODE_OPS9,          /* NTOOV */
8473         COPYNODE_OPS10,         /* NTOFD */
8474         COPYNODE_OPS10,         /* NFROMFD */
8475         COPYNODE_OPS11,         /* NHERE */
8476         COPYNODE_OPS11,         /* NXHERE */
8477         COPYNODE_OPS12,         /* NNOT */
8478 };
8479
8480 #if NODE_CHARPTR != NODE_MBRMASK
8481 #error NODE_CHARPTR != NODE_MBRMASK!!!
8482 #endif
8483 #endif                                                  /* defined(CALCSIZE_TABLE) || defined(COPYNODE_TABLE) */
8484
8485 #ifdef COPYNODE_TABLE
8486 static union node *copynode(const union node *n)
8487 {
8488         union node *new;
8489         const unsigned char *p;
8490
8491         if (n == NULL) {
8492                 return NULL;
8493         }
8494         new = funcblock;
8495         new->type = n->type;
8496         funcblock = (char *) funcblock + (int) nodesize[n->type];
8497         p = copynode_ops + (int) copynode_ops_index[n->type];
8498         do {
8499                 char *nn = ((char *) new) + ((int) (*p & NODE_OFFSETMASK));
8500                 const char *no = ((const char *) n) + ((int) (*p & NODE_OFFSETMASK));
8501
8502                 if (!(*p & NODE_MBRMASK)) {     /* standard node */
8503                         *((union node **) nn) = copynode(*((const union node **) no));
8504                 } else if ((*p & NODE_MBRMASK) == NODE_CHARPTR) {       /* string */
8505                         *((const char **) nn) = nodexstrdup(*((const char **) no));
8506                 } else if (*p & NODE_NODELIST) {        /* nodelist */
8507                         *((struct nodelist **) nn)
8508                                 = copynodelist(*((const struct nodelist **) no));
8509                 } else {                /* integer */
8510                         *((int *) nn) = *((int *) no);
8511                 }
8512         } while (!(*p++ & NODE_NOMORE));
8513         return new;
8514 }
8515 #else                                                   /* COPYNODE_TABLE */
8516 static union node *copynode(const union node *n)
8517 {
8518         union node *new;
8519
8520         if (n == NULL)
8521                 return NULL;
8522         new = funcblock;
8523         funcblock = (char *) funcblock + nodesize[n->type];
8524         switch (n->type) {
8525         case NSEMI:
8526         case NAND:
8527         case NOR:
8528         case NWHILE:
8529         case NUNTIL:
8530                 new->nbinary.ch2 = copynode(n->nbinary.ch2);
8531                 new->nbinary.ch1 = copynode(n->nbinary.ch1);
8532                 break;
8533         case NCMD:
8534                 new->ncmd.redirect = copynode(n->ncmd.redirect);
8535                 new->ncmd.args = copynode(n->ncmd.args);
8536                 new->ncmd.assign = copynode(n->ncmd.assign);
8537                 new->ncmd.backgnd = n->ncmd.backgnd;
8538                 break;
8539         case NPIPE:
8540                 new->npipe.cmdlist = copynodelist(n->npipe.cmdlist);
8541                 new->npipe.backgnd = n->npipe.backgnd;
8542                 break;
8543         case NREDIR:
8544         case NBACKGND:
8545         case NSUBSHELL:
8546                 new->nredir.redirect = copynode(n->nredir.redirect);
8547                 new->nredir.n = copynode(n->nredir.n);
8548                 break;
8549         case NIF:
8550                 new->nif.elsepart = copynode(n->nif.elsepart);
8551                 new->nif.ifpart = copynode(n->nif.ifpart);
8552                 new->nif.test = copynode(n->nif.test);
8553                 break;
8554         case NFOR:
8555                 new->nfor.var = nodexstrdup(n->nfor.var);
8556                 new->nfor.body = copynode(n->nfor.body);
8557                 new->nfor.args = copynode(n->nfor.args);
8558                 break;
8559         case NCASE:
8560                 new->ncase.cases = copynode(n->ncase.cases);
8561                 new->ncase.expr = copynode(n->ncase.expr);
8562                 break;
8563         case NCLIST:
8564                 new->nclist.body = copynode(n->nclist.body);
8565                 new->nclist.pattern = copynode(n->nclist.pattern);
8566                 new->nclist.next = copynode(n->nclist.next);
8567                 break;
8568         case NDEFUN:
8569         case NARG:
8570                 new->narg.backquote = copynodelist(n->narg.backquote);
8571                 new->narg.text = nodexstrdup(n->narg.text);
8572                 new->narg.next = copynode(n->narg.next);
8573                 break;
8574         case NTO:
8575         case NFROM:
8576         case NFROMTO:
8577         case NAPPEND:
8578         case NTOOV:
8579                 new->nfile.fname = copynode(n->nfile.fname);
8580                 new->nfile.fd = n->nfile.fd;
8581                 new->nfile.next = copynode(n->nfile.next);
8582                 break;
8583         case NTOFD:
8584         case NFROMFD:
8585                 new->ndup.vname = copynode(n->ndup.vname);
8586                 new->ndup.dupfd = n->ndup.dupfd;
8587                 new->ndup.fd = n->ndup.fd;
8588                 new->ndup.next = copynode(n->ndup.next);
8589                 break;
8590         case NHERE:
8591         case NXHERE:
8592                 new->nhere.doc = copynode(n->nhere.doc);
8593                 new->nhere.fd = n->nhere.fd;
8594                 new->nhere.next = copynode(n->nhere.next);
8595                 break;
8596         case NNOT:
8597                 new->nnot.com = copynode(n->nnot.com);
8598                 break;
8599         };
8600         new->type = n->type;
8601         return new;
8602 }
8603 #endif                                                  /* COPYNODE_TABLE */
8604
8605 #ifdef CALCSIZE_TABLE
8606 static void calcsize(const union node *n)
8607 {
8608         const unsigned char *p;
8609
8610         if (n == NULL)
8611                 return;
8612         funcblocksize += (int) nodesize[n->type];
8613
8614         p = copynode_ops + (int) copynode_ops_index[n->type];
8615         do {
8616                 const char *no = ((const char *) n) + ((int) (*p & NODE_OFFSETMASK));
8617
8618                 if (!(*p & NODE_MBRMASK)) {     /* standard node */
8619                         calcsize(*((const union node **) no));
8620                 } else if ((*p & NODE_MBRMASK) == NODE_CHARPTR) {       /* string */
8621                         funcstringsize += strlen(*((const char **) no)) + 1;
8622                 } else if (*p & NODE_NODELIST) {        /* nodelist */
8623                         sizenodelist(*((const struct nodelist **) no));
8624                 }                               /* else integer -- ignore */
8625         } while (!(*p++ & NODE_NOMORE));
8626 }
8627 #else                                                   /* CALCSIZE_TABLE */
8628 static void calcsize(const union node *n)
8629 {
8630         if (n == NULL)
8631                 return;
8632         funcblocksize += nodesize[n->type];
8633         switch (n->type) {
8634         case NSEMI:
8635         case NAND:
8636         case NOR:
8637         case NWHILE:
8638         case NUNTIL:
8639                 calcsize(n->nbinary.ch2);
8640                 calcsize(n->nbinary.ch1);
8641                 break;
8642         case NCMD:
8643                 calcsize(n->ncmd.redirect);
8644                 calcsize(n->ncmd.args);
8645                 calcsize(n->ncmd.assign);
8646                 break;
8647         case NPIPE:
8648                 sizenodelist(n->npipe.cmdlist);
8649                 break;
8650         case NREDIR:
8651         case NBACKGND:
8652         case NSUBSHELL:
8653                 calcsize(n->nredir.redirect);
8654                 calcsize(n->nredir.n);
8655                 break;
8656         case NIF:
8657                 calcsize(n->nif.elsepart);
8658                 calcsize(n->nif.ifpart);
8659                 calcsize(n->nif.test);
8660                 break;
8661         case NFOR:
8662                 funcstringsize += strlen(n->nfor.var) + 1;
8663                 calcsize(n->nfor.body);
8664                 calcsize(n->nfor.args);
8665                 break;
8666         case NCASE:
8667                 calcsize(n->ncase.cases);
8668                 calcsize(n->ncase.expr);
8669                 break;
8670         case NCLIST:
8671                 calcsize(n->nclist.body);
8672                 calcsize(n->nclist.pattern);
8673                 calcsize(n->nclist.next);
8674                 break;
8675         case NDEFUN:
8676         case NARG:
8677                 sizenodelist(n->narg.backquote);
8678                 funcstringsize += strlen(n->narg.text) + 1;
8679                 calcsize(n->narg.next);
8680                 break;
8681         case NTO:
8682         case NFROM:
8683         case NFROMTO:
8684         case NAPPEND:
8685         case NTOOV:
8686                 calcsize(n->nfile.fname);
8687                 calcsize(n->nfile.next);
8688                 break;
8689         case NTOFD:
8690         case NFROMFD:
8691                 calcsize(n->ndup.vname);
8692                 calcsize(n->ndup.next);
8693                 break;
8694         case NHERE:
8695         case NXHERE:
8696                 calcsize(n->nhere.doc);
8697                 calcsize(n->nhere.next);
8698                 break;
8699         case NNOT:
8700                 calcsize(n->nnot.com);
8701                 break;
8702         };
8703 }
8704 #endif                                                  /* CALCSIZE_TABLE */
8705
8706 static void sizenodelist(const struct nodelist *lp)
8707 {
8708         while (lp) {
8709                 funcblocksize += ALIGN(sizeof(struct nodelist));
8710                 calcsize(lp->n);
8711                 lp = lp->next;
8712         }
8713 }
8714
8715
8716 static struct nodelist *copynodelist(const struct nodelist *lp)
8717 {
8718         struct nodelist *start;
8719         struct nodelist **lpp;
8720
8721         lpp = &start;
8722         while (lp) {
8723                 *lpp = funcblock;
8724                 funcblock = (char *) funcblock + ALIGN(sizeof(struct nodelist));
8725                 (*lpp)->n = copynode(lp->n);
8726                 lp = lp->next;
8727                 lpp = &(*lpp)->next;
8728         }
8729         *lpp = NULL;
8730         return start;
8731 }
8732
8733
8734 static char *nodexstrdup(const char *s)
8735 {
8736         const char *p = s;
8737         char *q = funcstring;
8738         char *rtn = funcstring;
8739
8740         while ((*q++ = *p++) != '\0')
8741                 continue;
8742         funcstring = q;
8743         return rtn;
8744 }
8745
8746 #ifdef CONFIG_ASH_GETOPTS
8747 static int getopts(char *, char *, char **, int *, int *);
8748 #endif
8749
8750 /*
8751  * Process the shell command line arguments.
8752  */
8753
8754 static void procargs(int argc, char **argv)
8755 {
8756         int i;
8757
8758         argptr = argv;
8759         if (argc > 0)
8760                 argptr++;
8761         for (i = 0; i < NOPTS; i++)
8762                 optent_val(i) = 2;
8763         options(1);
8764         if (*argptr == NULL && minusc == NULL)
8765                 sflag = 1;
8766         if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
8767                 iflag = 1;
8768         if (mflag == 2)
8769                 mflag = iflag;
8770         for (i = 0; i < NOPTS; i++)
8771                 if (optent_val(i) == 2)
8772                         optent_val(i) = 0;
8773         arg0 = argv[0];
8774         if (sflag == 0 && minusc == NULL) {
8775                 commandname = argv[0];
8776                 arg0 = *argptr++;
8777                 setinputfile(arg0, 0);
8778                 commandname = arg0;
8779         }
8780         /* POSIX 1003.2: first arg after -c cmd is $0, remainder $1... */
8781         if (argptr && minusc && *argptr)
8782                 arg0 = *argptr++;
8783
8784         shellparam.p = argptr;
8785         shellparam.optind = 1;
8786         shellparam.optoff = -1;
8787         /* assert(shellparam.malloc == 0 && shellparam.nparam == 0); */
8788         while (*argptr) {
8789                 shellparam.nparam++;
8790                 argptr++;
8791         }
8792         optschanged();
8793 }
8794
8795
8796
8797 /*
8798  * Process shell options.  The global variable argptr contains a pointer
8799  * to the argument list; we advance it past the options.
8800  */
8801
8802 static inline void minus_o(const char *name, int val)
8803 {
8804         int i;
8805
8806         if (name == NULL) {
8807                 out1str("Current option settings\n");
8808                 for (i = 0; i < NOPTS; i++)
8809                         printf("%-16s%s\n", optent_name(optlist[i]),
8810                                    optent_val(i) ? "on" : "off");
8811         } else {
8812                 for (i = 0; i < NOPTS; i++)
8813                         if (equal(name, optent_name(optlist[i]))) {
8814                                 setoption(optent_letter(optlist[i]), val);
8815                                 return;
8816                         }
8817                 error("Illegal option -o %s", name);
8818         }
8819 }
8820
8821
8822 static void options(int cmdline)
8823 {
8824         char *p;
8825         int val;
8826         int c;
8827
8828         if (cmdline)
8829                 minusc = NULL;
8830         while ((p = *argptr) != NULL) {
8831                 argptr++;
8832                 if ((c = *p++) == '-') {
8833                         val = 1;
8834                         if (p[0] == '\0' || (p[0] == '-' && p[1] == '\0')) {
8835                                 if (!cmdline) {
8836                                         /* "-" means turn off -x and -v */
8837                                         if (p[0] == '\0')
8838                                                 xflag = vflag = 0;
8839                                         /* "--" means reset params */
8840                                         else if (*argptr == NULL)
8841                                                 setparam(argptr);
8842                                 }
8843                                 break;  /* "-" or  "--" terminates options */
8844                         }
8845                 } else if (c == '+') {
8846                         val = 0;
8847                 } else {
8848                         argptr--;
8849                         break;
8850                 }
8851                 while ((c = *p++) != '\0') {
8852                         if (c == 'c' && cmdline) {
8853                                 char *q;
8854
8855 #ifdef NOHACK                   /* removing this code allows sh -ce 'foo' for compat */
8856                                 if (*p == '\0')
8857 #endif
8858                                         q = *argptr++;
8859                                 if (q == NULL || minusc != NULL)
8860                                         error("Bad -c option");
8861                                 minusc = q;
8862 #ifdef NOHACK
8863                                 break;
8864 #endif
8865                         } else if (c == 'o') {
8866                                 minus_o(*argptr, val);
8867                                 if (*argptr)
8868                                         argptr++;
8869                         } else if (cmdline && (c == '-')) {     /* long options */
8870                                 if (strcmp(p, "login") == 0)
8871                                         isloginsh = 1;
8872                                 break;
8873                         } else {
8874                                 setoption(c, val);
8875                         }
8876                 }
8877         }
8878 }
8879
8880
8881 static void setoption(int flag, int val)
8882 {
8883         int i;
8884
8885         for (i = 0; i < NOPTS; i++)
8886                 if (optent_letter(optlist[i]) == flag) {
8887                         optent_val(i) = val;
8888                         if (val) {
8889                                 /* #%$ hack for ksh semantics */
8890                                 if (flag == 'V')
8891                                         Eflag = 0;
8892                                 else if (flag == 'E')
8893                                         Vflag = 0;
8894                         }
8895                         return;
8896                 }
8897         error("Illegal option -%c", flag);
8898         /* NOTREACHED */
8899 }
8900
8901
8902
8903 /*
8904  * Set the shell parameters.
8905  */
8906
8907 static void setparam(char **argv)
8908 {
8909         char **newparam;
8910         char **ap;
8911         int nparam;
8912
8913         for (nparam = 0; argv[nparam]; nparam++);
8914         ap = newparam = xmalloc((nparam + 1) * sizeof *ap);
8915         while (*argv) {
8916                 *ap++ = xstrdup(*argv++);
8917         }
8918         *ap = NULL;
8919         freeparam(&shellparam);
8920         shellparam.malloc = 1;
8921         shellparam.nparam = nparam;
8922         shellparam.p = newparam;
8923         shellparam.optind = 1;
8924         shellparam.optoff = -1;
8925 }
8926
8927
8928 /*
8929  * Free the list of positional parameters.
8930  */
8931
8932 static void freeparam(volatile struct shparam *param)
8933 {
8934         char **ap;
8935
8936         if (param->malloc) {
8937                 for (ap = param->p; *ap; ap++)
8938                         free(*ap);
8939                 free(param->p);
8940         }
8941 }
8942
8943
8944
8945 /*
8946  * The shift builtin command.
8947  */
8948
8949 static int shiftcmd(int argc, char **argv)
8950 {
8951         int n;
8952         char **ap1, **ap2;
8953
8954         n = 1;
8955         if (argc > 1)
8956                 n = number(argv[1]);
8957         if (n > shellparam.nparam)
8958                 error("can't shift that many");
8959         INTOFF;
8960         shellparam.nparam -= n;
8961         for (ap1 = shellparam.p; --n >= 0; ap1++) {
8962                 if (shellparam.malloc)
8963                         free(*ap1);
8964         }
8965         ap2 = shellparam.p;
8966         while ((*ap2++ = *ap1++) != NULL);
8967         shellparam.optind = 1;
8968         shellparam.optoff = -1;
8969         INTON;
8970         return 0;
8971 }
8972
8973
8974
8975 /*
8976  * The set command builtin.
8977  */
8978
8979 static int setcmd(int argc, char **argv)
8980 {
8981         if (argc == 1)
8982                 return showvarscmd(argc, argv);
8983         INTOFF;
8984         options(0);
8985         optschanged();
8986         if (*argptr != NULL) {
8987                 setparam(argptr);
8988         }
8989         INTON;
8990         return 0;
8991 }
8992
8993
8994 static void getoptsreset(const char *value)
8995 {
8996         shellparam.optind = number(value);
8997         shellparam.optoff = -1;
8998 }
8999
9000 #ifdef CONFIG_LOCALE_SUPPORT
9001 static void change_lc_all(const char *value)
9002 {
9003         if (value != 0 && *value != 0)
9004                 setlocale(LC_ALL, value);
9005 }
9006
9007 static void change_lc_ctype(const char *value)
9008 {
9009         if (value != 0 && *value != 0)
9010                 setlocale(LC_CTYPE, value);
9011 }
9012
9013 #endif
9014
9015 #ifdef CONFIG_ASH_GETOPTS
9016 /*
9017  * The getopts builtin.  Shellparam.optnext points to the next argument
9018  * to be processed.  Shellparam.optptr points to the next character to
9019  * be processed in the current argument.  If shellparam.optnext is NULL,
9020  * then it's the first time getopts has been called.
9021  */
9022
9023 static int getoptscmd(int argc, char **argv)
9024 {
9025         char **optbase;
9026
9027         if (argc < 3)
9028                 error("Usage: getopts optstring var [arg]");
9029         else if (argc == 3) {
9030                 optbase = shellparam.p;
9031                 if (shellparam.optind > shellparam.nparam + 1) {
9032                         shellparam.optind = 1;
9033                         shellparam.optoff = -1;
9034                 }
9035         } else {
9036                 optbase = &argv[3];
9037                 if (shellparam.optind > argc - 2) {
9038                         shellparam.optind = 1;
9039                         shellparam.optoff = -1;
9040                 }
9041         }
9042
9043         return getopts(argv[1], argv[2], optbase, &shellparam.optind,
9044                                    &shellparam.optoff);
9045 }
9046
9047 /*
9048  * Safe version of setvar, returns 1 on success 0 on failure.
9049  */
9050
9051 static int setvarsafe(const char *name, const char *val, int flags)
9052 {
9053         struct jmploc jmploc;
9054         struct jmploc *volatile savehandler = handler;
9055         int err = 0;
9056
9057 #ifdef __GNUC__
9058         (void) &err;
9059 #endif
9060
9061         if (setjmp(jmploc.loc))
9062                 err = 1;
9063         else {
9064                 handler = &jmploc;
9065                 setvar(name, val, flags);
9066         }
9067         handler = savehandler;
9068         return err;
9069 }
9070
9071 static int
9072 getopts(char *optstr, char *optvar, char **optfirst, int *myoptind,
9073                 int *optoff)
9074 {
9075         char *p, *q;
9076         char c = '?';
9077         int done = 0;
9078         int err = 0;
9079         char s[10];
9080         char **optnext = optfirst + *myoptind - 1;
9081
9082         if (*myoptind <= 1 || *optoff < 0 || !(*(optnext - 1)) ||
9083                 strlen(*(optnext - 1)) < *optoff)
9084                 p = NULL;
9085         else
9086                 p = *(optnext - 1) + *optoff;
9087         if (p == NULL || *p == '\0') {
9088                 /* Current word is done, advance */
9089                 if (optnext == NULL)
9090                         return 1;
9091                 p = *optnext;
9092                 if (p == NULL || *p != '-' || *++p == '\0') {
9093                   atend:
9094                         *myoptind = optnext - optfirst + 1;
9095                         p = NULL;
9096                         done = 1;
9097                         goto out;
9098                 }
9099                 optnext++;
9100                 if (p[0] == '-' && p[1] == '\0')        /* check for "--" */
9101                         goto atend;
9102         }
9103
9104         c = *p++;
9105         for (q = optstr; *q != c;) {
9106                 if (*q == '\0') {
9107                         if (optstr[0] == ':') {
9108                                 s[0] = c;
9109                                 s[1] = '\0';
9110                                 err |= setvarsafe("OPTARG", s, 0);
9111                         } else {
9112                                 out2fmt("Illegal option -%c\n", c);
9113                                 (void) unsetvar("OPTARG");
9114                         }
9115                         c = '?';
9116                         goto bad;
9117                 }
9118                 if (*++q == ':')
9119                         q++;
9120         }
9121
9122         if (*++q == ':') {
9123                 if (*p == '\0' && (p = *optnext) == NULL) {
9124                         if (optstr[0] == ':') {
9125                                 s[0] = c;
9126                                 s[1] = '\0';
9127                                 err |= setvarsafe("OPTARG", s, 0);
9128                                 c = ':';
9129                         } else {
9130                                 out2fmt("No arg for -%c option\n", c);
9131                                 (void) unsetvar("OPTARG");
9132                                 c = '?';
9133                         }
9134                         goto bad;
9135                 }
9136
9137                 if (p == *optnext)
9138                         optnext++;
9139                 setvarsafe("OPTARG", p, 0);
9140                 p = NULL;
9141         } else
9142                 setvarsafe("OPTARG", "", 0);
9143         *myoptind = optnext - optfirst + 1;
9144         goto out;
9145
9146   bad:
9147         *myoptind = 1;
9148         p = NULL;
9149   out:
9150         *optoff = p ? p - *(optnext - 1) : -1;
9151         snprintf(s, sizeof(s), "%d", *myoptind);
9152         err |= setvarsafe("OPTIND", s, VNOFUNC);
9153         s[0] = c;
9154         s[1] = '\0';
9155         err |= setvarsafe(optvar, s, 0);
9156         if (err) {
9157                 *myoptind = 1;
9158                 *optoff = -1;
9159                 exraise(EXERROR);
9160         }
9161         return done;
9162 }
9163 #endif
9164
9165 /*
9166  * XXX - should get rid of.  have all builtins use getopt(3).  the
9167  * library getopt must have the BSD extension static variable "optreset"
9168  * otherwise it can't be used within the shell safely.
9169  *
9170  * Standard option processing (a la getopt) for builtin routines.  The
9171  * only argument that is passed to nextopt is the option string; the
9172  * other arguments are unnecessary.  It return the character, or '\0' on
9173  * end of input.
9174  */
9175
9176 static int nextopt(const char *optstring)
9177 {
9178         char *p;
9179         const char *q;
9180         char c;
9181
9182         if ((p = optptr) == NULL || *p == '\0') {
9183                 p = *argptr;
9184                 if (p == NULL || *p != '-' || *++p == '\0')
9185                         return '\0';
9186                 argptr++;
9187                 if (p[0] == '-' && p[1] == '\0')        /* check for "--" */
9188                         return '\0';
9189         }
9190         c = *p++;
9191         for (q = optstring; *q != c;) {
9192                 if (*q == '\0')
9193                         error("Illegal option -%c", c);
9194                 if (*++q == ':')
9195                         q++;
9196         }
9197         if (*++q == ':') {
9198                 if (*p == '\0' && (p = *argptr++) == NULL)
9199                         error("No arg for -%c option", c);
9200                 optionarg = p;
9201                 p = NULL;
9202         }
9203         optptr = p;
9204         return c;
9205 }
9206
9207 static void flushall()
9208 {
9209         INTOFF;
9210         fflush(stdout);
9211         INTON;
9212 }
9213
9214
9215 static void out2fmt(const char *fmt, ...)
9216 {
9217         va_list ap;
9218
9219         va_start(ap, fmt);
9220         vfprintf(stderr, fmt, ap);
9221         va_end(ap);
9222 }
9223
9224 /*
9225  * Version of write which resumes after a signal is caught.
9226  */
9227
9228 static int xwrite(int fd, const char *buf, int nbytes)
9229 {
9230         int ntry;
9231         int i;
9232         int n;
9233
9234         n = nbytes;
9235         ntry = 0;
9236         for (;;) {
9237                 i = write(fd, buf, n);
9238                 if (i > 0) {
9239                         if ((n -= i) <= 0)
9240                                 return nbytes;
9241                         buf += i;
9242                         ntry = 0;
9243                 } else if (i == 0) {
9244                         if (++ntry > 10)
9245                                 return nbytes - n;
9246                 } else if (errno != EINTR) {
9247                         return -1;
9248                 }
9249         }
9250 }
9251
9252
9253 /*
9254  * Shell command parser.
9255  */
9256
9257 #define EOFMARKLEN 79
9258
9259
9260
9261 struct heredoc {
9262         struct heredoc *next;   /* next here document in list */
9263         union node *here;       /* redirection node */
9264         char *eofmark;          /* string indicating end of input */
9265         int striptabs;          /* if set, strip leading tabs */
9266 };
9267
9268 static struct heredoc *heredoclist;     /* list of here documents to read */
9269 static int parsebackquote;      /* nonzero if we are inside backquotes */
9270 static int doprompt;    /* if set, prompt the user */
9271 static int needprompt;  /* true if interactive and at start of line */
9272 static int lasttoken;   /* last token read */
9273
9274 static char *wordtext;  /* text of last word returned by readtoken */
9275
9276 static struct nodelist *backquotelist;
9277 static union node *redirnode;
9278 static struct heredoc *heredoc;
9279 static int quoteflag;   /* set if (part of) last token was quoted */
9280 static int startlinno;  /* line # where last token started */
9281
9282
9283 static union node *list(int);
9284 static union node *andor(void);
9285 static union node *pipeline(void);
9286 static union node *command(void);
9287 static union node *simplecmd(union node **rpp, union node *redir);
9288 static void parsefname(void);
9289 static void parseheredoc(void);
9290 static char peektoken(void);
9291 static int readtoken(void);
9292 static int xxreadtoken(void);
9293 static int readtoken1(int, int, const char *, int);
9294 static int noexpand(char *);
9295 static void synexpect(int) __attribute__ ((noreturn));
9296 static void synerror(const char *) __attribute__ ((noreturn));
9297 static void setprompt(int);
9298
9299
9300 /*
9301  * Read and parse a command.  Returns NEOF on end of file.  (NULL is a
9302  * valid parse tree indicating a blank line.)
9303  */
9304
9305 static union node *parsecmd(int interact)
9306 {
9307         int t;
9308
9309         tokpushback = 0;
9310         doprompt = interact;
9311         if (doprompt)
9312                 setprompt(1);
9313         else
9314                 setprompt(0);
9315         needprompt = 0;
9316         t = readtoken();
9317         if (t == TEOF)
9318                 return NEOF;
9319         if (t == TNL)
9320                 return NULL;
9321         tokpushback++;
9322         return list(1);
9323 }
9324
9325
9326 static union node *list(int nlflag)
9327 {
9328         union node *n1, *n2, *n3;
9329         int tok;
9330
9331         checkkwd = 2;
9332         if (nlflag == 0 && peektoken())
9333                 return NULL;
9334         n1 = NULL;
9335         for (;;) {
9336                 n2 = andor();
9337                 tok = readtoken();
9338                 if (tok == TBACKGND) {
9339                         if (n2->type == NCMD || n2->type == NPIPE) {
9340                                 n2->ncmd.backgnd = 1;
9341                         } else if (n2->type == NREDIR) {
9342                                 n2->type = NBACKGND;
9343                         } else {
9344                                 n3 = (union node *) stalloc(sizeof(struct nredir));
9345                                 n3->type = NBACKGND;
9346                                 n3->nredir.n = n2;
9347                                 n3->nredir.redirect = NULL;
9348                                 n2 = n3;
9349                         }
9350                 }
9351                 if (n1 == NULL) {
9352                         n1 = n2;
9353                 } else {
9354                         n3 = (union node *) stalloc(sizeof(struct nbinary));
9355                         n3->type = NSEMI;
9356                         n3->nbinary.ch1 = n1;
9357                         n3->nbinary.ch2 = n2;
9358                         n1 = n3;
9359                 }
9360                 switch (tok) {
9361                 case TBACKGND:
9362                 case TSEMI:
9363                         tok = readtoken();
9364                         /* fall through */
9365                 case TNL:
9366                         if (tok == TNL) {
9367                                 parseheredoc();
9368                                 if (nlflag)
9369                                         return n1;
9370                         } else {
9371                                 tokpushback++;
9372                         }
9373                         checkkwd = 2;
9374                         if (peektoken())
9375                                 return n1;
9376                         break;
9377                 case TEOF:
9378                         if (heredoclist)
9379                                 parseheredoc();
9380                         else
9381                                 pungetc();      /* push back EOF on input */
9382                         return n1;
9383                 default:
9384                         if (nlflag)
9385                                 synexpect(-1);
9386                         tokpushback++;
9387                         return n1;
9388                 }
9389         }
9390 }
9391
9392
9393
9394 static union node *andor()
9395 {
9396         union node *n1, *n2, *n3;
9397         int t;
9398
9399         checkkwd = 1;
9400         n1 = pipeline();
9401         for (;;) {
9402                 if ((t = readtoken()) == TAND) {
9403                         t = NAND;
9404                 } else if (t == TOR) {
9405                         t = NOR;
9406                 } else {
9407                         tokpushback++;
9408                         return n1;
9409                 }
9410                 checkkwd = 2;
9411                 n2 = pipeline();
9412                 n3 = (union node *) stalloc(sizeof(struct nbinary));
9413                 n3->type = t;
9414                 n3->nbinary.ch1 = n1;
9415                 n3->nbinary.ch2 = n2;
9416                 n1 = n3;
9417         }
9418 }
9419
9420
9421
9422 static union node *pipeline()
9423 {
9424         union node *n1, *n2, *pipenode;
9425         struct nodelist *lp, *prev;
9426         int negate;
9427
9428         negate = 0;
9429         TRACE(("pipeline: entered\n"));
9430         if (readtoken() == TNOT) {
9431                 negate = !negate;
9432                 checkkwd = 1;
9433         } else
9434                 tokpushback++;
9435         n1 = command();
9436         if (readtoken() == TPIPE) {
9437                 pipenode = (union node *) stalloc(sizeof(struct npipe));
9438                 pipenode->type = NPIPE;
9439                 pipenode->npipe.backgnd = 0;
9440                 lp = (struct nodelist *) stalloc(sizeof(struct nodelist));
9441                 pipenode->npipe.cmdlist = lp;
9442                 lp->n = n1;
9443                 do {
9444                         prev = lp;
9445                         lp = (struct nodelist *) stalloc(sizeof(struct nodelist));
9446                         checkkwd = 2;
9447                         lp->n = command();
9448                         prev->next = lp;
9449                 } while (readtoken() == TPIPE);
9450                 lp->next = NULL;
9451                 n1 = pipenode;
9452         }
9453         tokpushback++;
9454         if (negate) {
9455                 n2 = (union node *) stalloc(sizeof(struct nnot));
9456                 n2->type = NNOT;
9457                 n2->nnot.com = n1;
9458                 return n2;
9459         } else
9460                 return n1;
9461 }
9462
9463
9464
9465 static union node *command(void)
9466 {
9467         union node *n1, *n2;
9468         union node *ap, **app;
9469         union node *cp, **cpp;
9470         union node *redir, **rpp;
9471         int t;
9472
9473         redir = NULL;
9474         n1 = NULL;
9475         rpp = &redir;
9476
9477         /* Check for redirection which may precede command */
9478         while (readtoken() == TREDIR) {
9479                 *rpp = n2 = redirnode;
9480                 rpp = &n2->nfile.next;
9481                 parsefname();
9482         }
9483         tokpushback++;
9484
9485         switch (readtoken()) {
9486         case TIF:
9487                 n1 = (union node *) stalloc(sizeof(struct nif));
9488                 n1->type = NIF;
9489                 n1->nif.test = list(0);
9490                 if (readtoken() != TTHEN)
9491                         synexpect(TTHEN);
9492                 n1->nif.ifpart = list(0);
9493                 n2 = n1;
9494                 while (readtoken() == TELIF) {
9495                         n2->nif.elsepart = (union node *) stalloc(sizeof(struct nif));
9496                         n2 = n2->nif.elsepart;
9497                         n2->type = NIF;
9498                         n2->nif.test = list(0);
9499                         if (readtoken() != TTHEN)
9500                                 synexpect(TTHEN);
9501                         n2->nif.ifpart = list(0);
9502                 }
9503                 if (lasttoken == TELSE)
9504                         n2->nif.elsepart = list(0);
9505                 else {
9506                         n2->nif.elsepart = NULL;
9507                         tokpushback++;
9508                 }
9509                 if (readtoken() != TFI)
9510                         synexpect(TFI);
9511                 checkkwd = 1;
9512                 break;
9513         case TWHILE:
9514         case TUNTIL:{
9515                 int got;
9516                 n1 = (union node *) stalloc(sizeof(struct nbinary));
9517                 n1->type = (lasttoken == TWHILE) ? NWHILE : NUNTIL;
9518                 n1->nbinary.ch1 = list(0);
9519                 if ((got = readtoken()) != TDO) {
9520                         TRACE(("expecting DO got %s %s\n", tokname(got),
9521                                    got == TWORD ? wordtext : ""));
9522                         synexpect(TDO);
9523                 }
9524                 n1->nbinary.ch2 = list(0);
9525                 if (readtoken() != TDONE)
9526                         synexpect(TDONE);
9527                 checkkwd = 1;
9528                 break;
9529         }
9530         case TFOR:
9531                 if (readtoken() != TWORD || quoteflag || !goodname(wordtext))
9532                         synerror("Bad for loop variable");
9533                 n1 = (union node *) stalloc(sizeof(struct nfor));
9534                 n1->type = NFOR;
9535                 n1->nfor.var = wordtext;
9536                 checkkwd = 1;
9537                 if (readtoken() == TIN) {
9538                         app = &ap;
9539                         while (readtoken() == TWORD) {
9540                                 n2 = (union node *) stalloc(sizeof(struct narg));
9541                                 n2->type = NARG;
9542                                 n2->narg.text = wordtext;
9543                                 n2->narg.backquote = backquotelist;
9544                                 *app = n2;
9545                                 app = &n2->narg.next;
9546                         }
9547                         *app = NULL;
9548                         n1->nfor.args = ap;
9549                         if (lasttoken != TNL && lasttoken != TSEMI)
9550                                 synexpect(-1);
9551                 } else {
9552                         static char argvars[5] = { CTLVAR, VSNORMAL | VSQUOTE,
9553                                 '@', '=', '\0'
9554                         };
9555                         n2 = (union node *) stalloc(sizeof(struct narg));
9556                         n2->type = NARG;
9557                         n2->narg.text = argvars;
9558                         n2->narg.backquote = NULL;
9559                         n2->narg.next = NULL;
9560                         n1->nfor.args = n2;
9561                         /*
9562                          * Newline or semicolon here is optional (but note
9563                          * that the original Bourne shell only allowed NL).
9564                          */
9565                         if (lasttoken != TNL && lasttoken != TSEMI)
9566                                 tokpushback++;
9567                 }
9568                 checkkwd = 2;
9569                 if (readtoken() != TDO)
9570                         synexpect(TDO);
9571                 n1->nfor.body = list(0);
9572                 if (readtoken() != TDONE)
9573                         synexpect(TDONE);
9574                 checkkwd = 1;
9575                 break;
9576         case TCASE:
9577                 n1 = (union node *) stalloc(sizeof(struct ncase));
9578                 n1->type = NCASE;
9579                 if (readtoken() != TWORD)
9580                         synexpect(TWORD);
9581                 n1->ncase.expr = n2 = (union node *) stalloc(sizeof(struct narg));
9582                 n2->type = NARG;
9583                 n2->narg.text = wordtext;
9584                 n2->narg.backquote = backquotelist;
9585                 n2->narg.next = NULL;
9586                 do {
9587                         checkkwd = 1;
9588                 } while (readtoken() == TNL);
9589                 if (lasttoken != TIN)
9590                         synerror("expecting \"in\"");
9591                 cpp = &n1->ncase.cases;
9592                 checkkwd = 2, readtoken();
9593                 do {
9594                         if (lasttoken == TLP)
9595                                 readtoken();
9596                         *cpp = cp = (union node *) stalloc(sizeof(struct nclist));
9597                         cp->type = NCLIST;
9598                         app = &cp->nclist.pattern;
9599                         for (;;) {
9600                                 *app = ap = (union node *) stalloc(sizeof(struct narg));
9601                                 ap->type = NARG;
9602                                 ap->narg.text = wordtext;
9603                                 ap->narg.backquote = backquotelist;
9604                                 if (checkkwd = 2, readtoken() != TPIPE)
9605                                         break;
9606                                 app = &ap->narg.next;
9607                                 readtoken();
9608                         }
9609                         ap->narg.next = NULL;
9610                         if (lasttoken != TRP)
9611                                 synexpect(TRP);
9612                         cp->nclist.body = list(0);
9613
9614                         checkkwd = 2;
9615                         if ((t = readtoken()) != TESAC) {
9616                                 if (t != TENDCASE)
9617                                         synexpect(TENDCASE);
9618                                 else
9619                                         checkkwd = 2, readtoken();
9620                         }
9621                         cpp = &cp->nclist.next;
9622                 } while (lasttoken != TESAC);
9623                 *cpp = NULL;
9624                 checkkwd = 1;
9625                 break;
9626         case TLP:
9627                 n1 = (union node *) stalloc(sizeof(struct nredir));
9628                 n1->type = NSUBSHELL;
9629                 n1->nredir.n = list(0);
9630                 n1->nredir.redirect = NULL;
9631                 if (readtoken() != TRP)
9632                         synexpect(TRP);
9633                 checkkwd = 1;
9634                 break;
9635         case TBEGIN:
9636                 n1 = list(0);
9637                 if (readtoken() != TEND)
9638                         synexpect(TEND);
9639                 checkkwd = 1;
9640                 break;
9641                 /* Handle an empty command like other simple commands.  */
9642         case TSEMI:
9643         case TAND:
9644         case TOR:
9645         case TNL:
9646         case TEOF:
9647         case TRP:
9648         case TBACKGND:
9649                 /*
9650                  * An empty command before a ; doesn't make much sense, and
9651                  * should certainly be disallowed in the case of `if ;'.
9652                  */
9653                 if (!redir)
9654                         synexpect(-1);
9655         case TWORD:
9656                 tokpushback++;
9657                 n1 = simplecmd(rpp, redir);
9658                 return n1;
9659         default:
9660                 synexpect(-1);
9661                 /* NOTREACHED */
9662         }
9663
9664         /* Now check for redirection which may follow command */
9665         while (readtoken() == TREDIR) {
9666                 *rpp = n2 = redirnode;
9667                 rpp = &n2->nfile.next;
9668                 parsefname();
9669         }
9670         tokpushback++;
9671         *rpp = NULL;
9672         if (redir) {
9673                 if (n1->type != NSUBSHELL) {
9674                         n2 = (union node *) stalloc(sizeof(struct nredir));
9675                         n2->type = NREDIR;
9676                         n2->nredir.n = n1;
9677                         n1 = n2;
9678                 }
9679                 n1->nredir.redirect = redir;
9680         }
9681
9682         return n1;
9683 }
9684
9685
9686 static union node *simplecmd(union node **rpp, union node *redir)
9687 {
9688         union node *args, **app;
9689         union node *n = NULL;
9690         union node *vars, **vpp;
9691         union node **orig_rpp;
9692
9693         args = NULL;
9694         app = &args;
9695         vars = NULL;
9696         vpp = &vars;
9697
9698         /* If we don't have any redirections already, then we must reset
9699            rpp to be the address of the local redir variable.  */
9700         if (redir == 0)
9701                 rpp = &redir;
9702         /* We save the incoming value, because we need this for shell
9703            functions.  There can not be a redirect or an argument between
9704            the function name and the open parenthesis.  */
9705         orig_rpp = rpp;
9706
9707         checkalias = 2;
9708         for (;;) {
9709                 switch (readtoken()) {
9710                 case TWORD:
9711                 case TASSIGN:
9712                         n = (union node *) stalloc(sizeof(struct narg));
9713                         n->type = NARG;
9714                         n->narg.text = wordtext;
9715                         n->narg.backquote = backquotelist;
9716                         if (lasttoken == TWORD) {
9717                                 *app = n;
9718                                 app = &n->narg.next;
9719                         } else {
9720                                 *vpp = n;
9721                                 vpp = &n->narg.next;
9722                         }
9723                         break;
9724                 case TREDIR:
9725                         *rpp = n = redirnode;
9726                         rpp = &n->nfile.next;
9727                         parsefname();   /* read name of redirection file */
9728                         break;
9729                 case TLP:
9730                         if (args && app == &args->narg.next && !vars && rpp == orig_rpp) {
9731                                 /* We have a function */
9732                                 if (readtoken() != TRP)
9733                                         synexpect(TRP);
9734                                 n->type = NDEFUN;
9735                                 checkkwd = 2;
9736                                 n->narg.next = command();
9737                                 return n;
9738                         }
9739                         /* fall through */
9740                 default:
9741                         tokpushback++;
9742                         goto out;
9743                 }
9744         }
9745   out:
9746         *app = NULL;
9747         *vpp = NULL;
9748         *rpp = NULL;
9749         n = (union node *) stalloc(sizeof(struct ncmd));
9750         n->type = NCMD;
9751         n->ncmd.backgnd = 0;
9752         n->ncmd.args = args;
9753         n->ncmd.assign = vars;
9754         n->ncmd.redirect = redir;
9755         return n;
9756 }
9757
9758 static union node *makename(void)
9759 {
9760         union node *n;
9761
9762         n = (union node *) stalloc(sizeof(struct narg));
9763         n->type = NARG;
9764         n->narg.next = NULL;
9765         n->narg.text = wordtext;
9766         n->narg.backquote = backquotelist;
9767         return n;
9768 }
9769
9770 static void fixredir(union node *n, const char *text, int err)
9771 {
9772         TRACE(("Fix redir %s %d\n", text, err));
9773         if (!err)
9774                 n->ndup.vname = NULL;
9775
9776         if (is_digit(text[0]) && text[1] == '\0')
9777                 n->ndup.dupfd = digit_val(text[0]);
9778         else if (text[0] == '-' && text[1] == '\0')
9779                 n->ndup.dupfd = -1;
9780         else {
9781
9782                 if (err)
9783                         synerror("Bad fd number");
9784                 else
9785                         n->ndup.vname = makename();
9786         }
9787 }
9788
9789
9790 static void parsefname(void)
9791 {
9792         union node *n = redirnode;
9793
9794         if (readtoken() != TWORD)
9795                 synexpect(-1);
9796         if (n->type == NHERE) {
9797                 struct heredoc *here = heredoc;
9798                 struct heredoc *p;
9799                 int i;
9800
9801                 if (quoteflag == 0)
9802                         n->type = NXHERE;
9803                 TRACE(("Here document %d\n", n->type));
9804                 if (here->striptabs) {
9805                         while (*wordtext == '\t')
9806                                 wordtext++;
9807                 }
9808                 if (!noexpand(wordtext) || (i = strlen(wordtext)) == 0
9809                         || i > EOFMARKLEN)
9810                         synerror("Illegal eof marker for << redirection");
9811                 rmescapes(wordtext);
9812                 here->eofmark = wordtext;
9813                 here->next = NULL;
9814                 if (heredoclist == NULL)
9815                         heredoclist = here;
9816                 else {
9817                         for (p = heredoclist; p->next; p = p->next);
9818                         p->next = here;
9819                 }
9820         } else if (n->type == NTOFD || n->type == NFROMFD) {
9821                 fixredir(n, wordtext, 0);
9822         } else {
9823                 n->nfile.fname = makename();
9824         }
9825 }
9826
9827
9828 /*
9829  * Input any here documents.
9830  */
9831
9832 static void parseheredoc()
9833 {
9834         struct heredoc *here;
9835         union node *n;
9836
9837         while (heredoclist) {
9838                 here = heredoclist;
9839                 heredoclist = here->next;
9840                 if (needprompt) {
9841                         setprompt(2);
9842                         needprompt = 0;
9843                 }
9844                 readtoken1(pgetc(), here->here->type == NHERE ? SQSYNTAX : DQSYNTAX,
9845                                    here->eofmark, here->striptabs);
9846                 n = (union node *) stalloc(sizeof(struct narg));
9847                 n->narg.type = NARG;
9848                 n->narg.next = NULL;
9849                 n->narg.text = wordtext;
9850                 n->narg.backquote = backquotelist;
9851                 here->here->nhere.doc = n;
9852         }
9853 }
9854
9855 static char peektoken()
9856 {
9857         int t;
9858
9859         t = readtoken();
9860         tokpushback++;
9861         return tokname_array[t][0];
9862 }
9863
9864 static int readtoken()
9865 {
9866         int t;
9867
9868         int savecheckalias = checkalias;
9869
9870 #ifdef CONFIG_ASH_ALIAS
9871         int savecheckkwd = checkkwd;
9872         struct alias *ap;
9873 #endif
9874
9875 #ifdef DEBUG
9876         int alreadyseen = tokpushback;
9877 #endif
9878
9879 #ifdef CONFIG_ASH_ALIAS
9880   top:
9881 #endif
9882
9883         t = xxreadtoken();
9884
9885         checkalias = savecheckalias;
9886
9887         if (checkkwd) {
9888                 /*
9889                  * eat newlines
9890                  */
9891                 if (checkkwd == 2) {
9892                         checkkwd = 0;
9893                         while (t == TNL) {
9894                                 parseheredoc();
9895                                 t = xxreadtoken();
9896                         }
9897                 }
9898                 checkkwd = 0;
9899                 /*
9900                  * check for keywords
9901                  */
9902                 if (t == TWORD && !quoteflag) {
9903                         const char *const *pp;
9904
9905                         if ((pp = findkwd(wordtext))) {
9906                                 lasttoken = t = pp - tokname_array;
9907                                 TRACE(("keyword %s recognized\n", tokname(t)));
9908                                 goto out;
9909                         }
9910                 }
9911         }
9912
9913
9914         if (t != TWORD) {
9915                 if (t != TREDIR) {
9916                         checkalias = 0;
9917                 }
9918         } else if (checkalias == 2 && isassignment(wordtext)) {
9919                 lasttoken = t = TASSIGN;
9920         } else if (checkalias) {
9921 #ifdef CONFIG_ASH_ALIAS
9922                 if (!quoteflag && (ap = *__lookupalias(wordtext)) != NULL
9923                         && !(ap->flag & ALIASINUSE)) {
9924                         if (*ap->val) {
9925                                 pushstring(ap->val, strlen(ap->val), ap);
9926                         }
9927                         checkkwd = savecheckkwd;
9928                         goto top;
9929                 }
9930 #endif
9931                 checkalias = 0;
9932         }
9933   out:
9934 #ifdef DEBUG
9935         if (!alreadyseen)
9936                 TRACE(("token %s %s\n", tokname(t), t == TWORD
9937                            || t == TASSIGN ? wordtext : ""));
9938         else
9939                 TRACE(("reread token %s %s\n", tokname(t), t == TWORD
9940                            || t == TASSIGN ? wordtext : ""));
9941 #endif
9942         return (t);
9943 }
9944
9945
9946 /*
9947  * Read the next input token.
9948  * If the token is a word, we set backquotelist to the list of cmds in
9949  *      backquotes.  We set quoteflag to true if any part of the word was
9950  *      quoted.
9951  * If the token is TREDIR, then we set redirnode to a structure containing
9952  *      the redirection.
9953  * In all cases, the variable startlinno is set to the number of the line
9954  *      on which the token starts.
9955  *
9956  * [Change comment:  here documents and internal procedures]
9957  * [Readtoken shouldn't have any arguments.  Perhaps we should make the
9958  *  word parsing code into a separate routine.  In this case, readtoken
9959  *  doesn't need to have any internal procedures, but parseword does.
9960  *  We could also make parseoperator in essence the main routine, and
9961  *  have parseword (readtoken1?) handle both words and redirection.]
9962  */
9963
9964 #define NEW_xxreadtoken
9965 #ifdef NEW_xxreadtoken
9966
9967 static const char xxreadtoken_chars[] = "\n()&|;";      /* singles must be first! */
9968 static const char xxreadtoken_tokens[] = {
9969         TNL, TLP, TRP,          /* only single occurrence allowed */
9970         TBACKGND, TPIPE, TSEMI, /* if single occurrence */
9971         TEOF,                           /* corresponds to trailing nul */
9972         TAND, TOR, TENDCASE,    /* if double occurrence */
9973 };
9974
9975 #define xxreadtoken_doubles \
9976         (sizeof(xxreadtoken_tokens) - sizeof(xxreadtoken_chars))
9977 #define xxreadtoken_singles \
9978         (sizeof(xxreadtoken_chars) - xxreadtoken_doubles - 1)
9979
9980 static int xxreadtoken()
9981 {
9982         int c;
9983
9984         if (tokpushback) {
9985                 tokpushback = 0;
9986                 return lasttoken;
9987         }
9988         if (needprompt) {
9989                 setprompt(2);
9990                 needprompt = 0;
9991         }
9992         startlinno = plinno;
9993         for (;;) {                      /* until token or start of word found */
9994                 c = pgetc_macro();
9995
9996                 if ((c != ' ') && (c != '\t')
9997 #ifdef CONFIG_ASH_ALIAS
9998                         && (c != PEOA)
9999 #endif
10000                         ) {
10001                         if (c == '#') {
10002                                 while ((c = pgetc()) != '\n' && c != PEOF);
10003                                 pungetc();
10004                         } else if (c == '\\') {
10005                                 if (pgetc() != '\n') {
10006                                         pungetc();
10007                                         goto READTOKEN1;
10008                                 }
10009                                 startlinno = ++plinno;
10010                                 setprompt(doprompt ? 2 : 0);
10011                         } else {
10012                                 const char *p
10013                                         = xxreadtoken_chars + sizeof(xxreadtoken_chars) - 1;
10014
10015                                 if (c != PEOF) {
10016                                         if (c == '\n') {
10017                                                 plinno++;
10018                                                 needprompt = doprompt;
10019                                         }
10020
10021                                         p = strchr(xxreadtoken_chars, c);
10022                                         if (p == NULL) {
10023                                           READTOKEN1:
10024                                                 return readtoken1(c, BASESYNTAX, (char *) NULL, 0);
10025                                         }
10026
10027                                         if (p - xxreadtoken_chars >= xxreadtoken_singles) {
10028                                                 if (pgetc() == *p) {    /* double occurrence? */
10029                                                         p += xxreadtoken_doubles + 1;
10030                                                 } else {
10031                                                         pungetc();
10032                                                 }
10033                                         }
10034                                 }
10035
10036                                 return lasttoken = xxreadtoken_tokens[p - xxreadtoken_chars];
10037                         }
10038                 }
10039         }
10040 }
10041
10042
10043 #else
10044 #define RETURN(token)   return lasttoken = token
10045
10046 static int xxreadtoken()
10047 {
10048         int c;
10049
10050         if (tokpushback) {
10051                 tokpushback = 0;
10052                 return lasttoken;
10053         }
10054         if (needprompt) {
10055                 setprompt(2);
10056                 needprompt = 0;
10057         }
10058         startlinno = plinno;
10059         for (;;) {                      /* until token or start of word found */
10060                 c = pgetc_macro();
10061                 switch (c) {
10062                 case ' ':
10063                 case '\t':
10064 #ifdef CONFIG_ASH_ALIAS
10065                 case PEOA:
10066 #endif
10067                         continue;
10068                 case '#':
10069                         while ((c = pgetc()) != '\n' && c != PEOF);
10070                         pungetc();
10071                         continue;
10072                 case '\\':
10073                         if (pgetc() == '\n') {
10074                                 startlinno = ++plinno;
10075                                 if (doprompt)
10076                                         setprompt(2);
10077                                 else
10078                                         setprompt(0);
10079                                 continue;
10080                         }
10081                         pungetc();
10082                         goto breakloop;
10083                 case '\n':
10084                         plinno++;
10085                         needprompt = doprompt;
10086                         RETURN(TNL);
10087                 case PEOF:
10088                         RETURN(TEOF);
10089                 case '&':
10090                         if (pgetc() == '&')
10091                                 RETURN(TAND);
10092                         pungetc();
10093                         RETURN(TBACKGND);
10094                 case '|':
10095                         if (pgetc() == '|')
10096                                 RETURN(TOR);
10097                         pungetc();
10098                         RETURN(TPIPE);
10099                 case ';':
10100                         if (pgetc() == ';')
10101                                 RETURN(TENDCASE);
10102                         pungetc();
10103                         RETURN(TSEMI);
10104                 case '(':
10105                         RETURN(TLP);
10106                 case ')':
10107                         RETURN(TRP);
10108                 default:
10109                         goto breakloop;
10110                 }
10111         }
10112   breakloop:
10113         return readtoken1(c, BASESYNTAX, (char *) NULL, 0);
10114 #undef RETURN
10115 }
10116 #endif
10117
10118 /*
10119  * If eofmark is NULL, read a word or a redirection symbol.  If eofmark
10120  * is not NULL, read a here document.  In the latter case, eofmark is the
10121  * word which marks the end of the document and striptabs is true if
10122  * leading tabs should be stripped from the document.  The argument firstc
10123  * is the first character of the input token or document.
10124  *
10125  * Because C does not have internal subroutines, I have simulated them
10126  * using goto's to implement the subroutine linkage.  The following macros
10127  * will run code that appears at the end of readtoken1.
10128  */
10129
10130 #define CHECKEND()      {goto checkend; checkend_return:;}
10131 #define PARSEREDIR()    {goto parseredir; parseredir_return:;}
10132 #define PARSESUB()      {goto parsesub; parsesub_return:;}
10133 #define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
10134 #define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
10135 #define PARSEARITH()    {goto parsearith; parsearith_return:;}
10136
10137 static int
10138 readtoken1(int firstc, int syntax, const char *eofmark, int striptabs)
10139 {
10140         int c = firstc;
10141         char *out;
10142         int len;
10143         char line[EOFMARKLEN + 1];
10144         struct nodelist *bqlist;
10145         int quotef;
10146         int dblquote;
10147         int varnest;            /* levels of variables expansion */
10148         int arinest;            /* levels of arithmetic expansion */
10149         int parenlevel;         /* levels of parens in arithmetic */
10150         int dqvarnest;          /* levels of variables expansion within double quotes */
10151         int oldstyle;
10152         int prevsyntax;         /* syntax before arithmetic */
10153
10154 #if __GNUC__
10155         /* Avoid longjmp clobbering */
10156         (void) &out;
10157         (void) &quotef;
10158         (void) &dblquote;
10159         (void) &varnest;
10160         (void) &arinest;
10161         (void) &parenlevel;
10162         (void) &dqvarnest;
10163         (void) &oldstyle;
10164         (void) &prevsyntax;
10165         (void) &syntax;
10166 #endif
10167
10168         startlinno = plinno;
10169         dblquote = 0;
10170         if (syntax == DQSYNTAX)
10171                 dblquote = 1;
10172         quotef = 0;
10173         bqlist = NULL;
10174         varnest = 0;
10175         arinest = 0;
10176         parenlevel = 0;
10177         dqvarnest = 0;
10178
10179         STARTSTACKSTR(out);
10180   loop:{                                /* for each line, until end of word */
10181                 CHECKEND();             /* set c to PEOF if at end of here document */
10182                 for (;;) {              /* until end of line or end of word */
10183                         CHECKSTRSPACE(3, out);  /* permit 3 calls to USTPUTC */
10184                         switch (SIT(c, syntax)) {
10185                         case CNL:       /* '\n' */
10186                                 if (syntax == BASESYNTAX)
10187                                         goto endword;   /* exit outer loop */
10188                                 USTPUTC(c, out);
10189                                 plinno++;
10190                                 if (doprompt)
10191                                         setprompt(2);
10192                                 else
10193                                         setprompt(0);
10194                                 c = pgetc();
10195                                 goto loop;      /* continue outer loop */
10196                         case CWORD:
10197                                 USTPUTC(c, out);
10198                                 break;
10199                         case CCTL:
10200                                 if ((eofmark == NULL || dblquote) && dqvarnest == 0)
10201                                         USTPUTC(CTLESC, out);
10202                                 USTPUTC(c, out);
10203                                 break;
10204                         case CBACK:     /* backslash */
10205                                 c = pgetc2();
10206                                 if (c == PEOF) {
10207                                         USTPUTC('\\', out);
10208                                         pungetc();
10209                                 } else if (c == '\n') {
10210                                         if (doprompt)
10211                                                 setprompt(2);
10212                                         else
10213                                                 setprompt(0);
10214                                 } else {
10215                                         if (dblquote && c != '\\' && c != '`' && c != '$'
10216                                                 && (c != '"' || eofmark != NULL))
10217                                                 USTPUTC('\\', out);
10218                                         if (SIT(c, SQSYNTAX) == CCTL)
10219                                                 USTPUTC(CTLESC, out);
10220                                         else if (eofmark == NULL)
10221                                                 USTPUTC(CTLQUOTEMARK, out);
10222                                         USTPUTC(c, out);
10223                                         quotef++;
10224                                 }
10225                                 break;
10226                         case CSQUOTE:
10227                                 if (eofmark == NULL)
10228                                         USTPUTC(CTLQUOTEMARK, out);
10229                                 syntax = SQSYNTAX;
10230                                 break;
10231                         case CDQUOTE:
10232                                 if (eofmark == NULL)
10233                                         USTPUTC(CTLQUOTEMARK, out);
10234                                 syntax = DQSYNTAX;
10235                                 dblquote = 1;
10236                                 break;
10237                         case CENDQUOTE:
10238                                 if (eofmark != NULL && arinest == 0 && varnest == 0) {
10239                                         USTPUTC(c, out);
10240                                 } else {
10241                                         if (arinest) {
10242                                                 syntax = ARISYNTAX;
10243                                                 dblquote = 0;
10244                                         } else if (eofmark == NULL && dqvarnest == 0) {
10245                                                 syntax = BASESYNTAX;
10246                                                 dblquote = 0;
10247                                         }
10248                                         quotef++;
10249                                 }
10250                                 break;
10251                         case CVAR:      /* '$' */
10252                                 PARSESUB();     /* parse substitution */
10253                                 break;
10254                         case CENDVAR:   /* '}' */
10255                                 if (varnest > 0) {
10256                                         varnest--;
10257                                         if (dqvarnest > 0) {
10258                                                 dqvarnest--;
10259                                         }
10260                                         USTPUTC(CTLENDVAR, out);
10261                                 } else {
10262                                         USTPUTC(c, out);
10263                                 }
10264                                 break;
10265 #ifdef CONFIG_ASH_MATH_SUPPORT
10266                         case CLP:       /* '(' in arithmetic */
10267                                 parenlevel++;
10268                                 USTPUTC(c, out);
10269                                 break;
10270                         case CRP:       /* ')' in arithmetic */
10271                                 if (parenlevel > 0) {
10272                                         USTPUTC(c, out);
10273                                         --parenlevel;
10274                                 } else {
10275                                         if (pgetc() == ')') {
10276                                                 if (--arinest == 0) {
10277                                                         USTPUTC(CTLENDARI, out);
10278                                                         syntax = prevsyntax;
10279                                                         if (syntax == DQSYNTAX)
10280                                                                 dblquote = 1;
10281                                                         else
10282                                                                 dblquote = 0;
10283                                                 } else
10284                                                         USTPUTC(')', out);
10285                                         } else {
10286                                                 /*
10287                                                  * unbalanced parens
10288                                                  *  (don't 2nd guess - no error)
10289                                                  */
10290                                                 pungetc();
10291                                                 USTPUTC(')', out);
10292                                         }
10293                                 }
10294                                 break;
10295 #endif
10296                         case CBQUOTE:   /* '`' */
10297                                 PARSEBACKQOLD();
10298                                 break;
10299                         case CENDFILE:
10300                                 goto endword;   /* exit outer loop */
10301                         case CIGN:
10302                                 break;
10303                         default:
10304                                 if (varnest == 0)
10305                                         goto endword;   /* exit outer loop */
10306 #ifdef CONFIG_ASH_ALIAS
10307                                 if (c != PEOA)
10308 #endif
10309                                         USTPUTC(c, out);
10310
10311                         }
10312                         c = pgetc_macro();
10313                 }
10314         }
10315   endword:
10316         if (syntax == ARISYNTAX)
10317                 synerror("Missing '))'");
10318         if (syntax != BASESYNTAX && !parsebackquote && eofmark == NULL)
10319                 synerror("Unterminated quoted string");
10320         if (varnest != 0) {
10321                 startlinno = plinno;
10322                 synerror("Missing '}'");
10323         }
10324         USTPUTC('\0', out);
10325         len = out - stackblock();
10326         out = stackblock();
10327         if (eofmark == NULL) {
10328                 if ((c == '>' || c == '<')
10329                         && quotef == 0 && len <= 2 && (*out == '\0' || is_digit(*out))) {
10330                         PARSEREDIR();
10331                         return lasttoken = TREDIR;
10332                 } else {
10333                         pungetc();
10334                 }
10335         }
10336         quoteflag = quotef;
10337         backquotelist = bqlist;
10338         grabstackblock(len);
10339         wordtext = out;
10340         return lasttoken = TWORD;
10341 /* end of readtoken routine */
10342
10343
10344
10345 /*
10346  * Check to see whether we are at the end of the here document.  When this
10347  * is called, c is set to the first character of the next input line.  If
10348  * we are at the end of the here document, this routine sets the c to PEOF.
10349  */
10350
10351   checkend:{
10352                 if (eofmark) {
10353 #ifdef CONFIG_ASH_ALIAS
10354                         if (c == PEOA) {
10355                                 c = pgetc2();
10356                         }
10357 #endif
10358                         if (striptabs) {
10359                                 while (c == '\t') {
10360                                         c = pgetc2();
10361                                 }
10362                         }
10363                         if (c == *eofmark) {
10364                                 if (pfgets(line, sizeof line) != NULL) {
10365                                         const char *p, *q;
10366
10367                                         p = line;
10368                                         for (q = eofmark + 1; *q && *p == *q; p++, q++);
10369                                         if (*p == '\n' && *q == '\0') {
10370                                                 c = PEOF;
10371                                                 plinno++;
10372                                                 needprompt = doprompt;
10373                                         } else {
10374                                                 pushstring(line, strlen(line), NULL);
10375                                         }
10376                                 }
10377                         }
10378                 }
10379                 goto checkend_return;
10380         }
10381
10382
10383 /*
10384  * Parse a redirection operator.  The variable "out" points to a string
10385  * specifying the fd to be redirected.  The variable "c" contains the
10386  * first character of the redirection operator.
10387  */
10388
10389   parseredir:{
10390                 char fd = *out;
10391                 union node *np;
10392
10393                 np = (union node *) stalloc(sizeof(struct nfile));
10394                 if (c == '>') {
10395                         np->nfile.fd = 1;
10396                         c = pgetc();
10397                         if (c == '>')
10398                                 np->type = NAPPEND;
10399                         else if (c == '&')
10400                                 np->type = NTOFD;
10401                         else if (c == '|')
10402                                 np->type = NTOOV;
10403                         else {
10404                                 np->type = NTO;
10405                                 pungetc();
10406                         }
10407                 } else {                /* c == '<' */
10408                         np->nfile.fd = 0;
10409                         switch (c = pgetc()) {
10410                         case '<':
10411                                 if (sizeof(struct nfile) != sizeof(struct nhere)) {
10412                                         np = (union node *) stalloc(sizeof(struct nhere));
10413                                         np->nfile.fd = 0;
10414                                 }
10415                                 np->type = NHERE;
10416                                 heredoc = (struct heredoc *) stalloc(sizeof(struct heredoc));
10417                                 heredoc->here = np;
10418                                 if ((c = pgetc()) == '-') {
10419                                         heredoc->striptabs = 1;
10420                                 } else {
10421                                         heredoc->striptabs = 0;
10422                                         pungetc();
10423                                 }
10424                                 break;
10425
10426                         case '&':
10427                                 np->type = NFROMFD;
10428                                 break;
10429
10430                         case '>':
10431                                 np->type = NFROMTO;
10432                                 break;
10433
10434                         default:
10435                                 np->type = NFROM;
10436                                 pungetc();
10437                                 break;
10438                         }
10439                 }
10440                 if (fd != '\0')
10441                         np->nfile.fd = digit_val(fd);
10442                 redirnode = np;
10443                 goto parseredir_return;
10444         }
10445
10446
10447 /*
10448  * Parse a substitution.  At this point, we have read the dollar sign
10449  * and nothing else.
10450  */
10451
10452   parsesub:{
10453                 int subtype;
10454                 int typeloc;
10455                 int flags;
10456                 char *p;
10457                 static const char types[] = "}-+?=";
10458
10459                 c = pgetc();
10460                 if (c <= PEOA ||
10461                         (c != '(' && c != '{' && !is_name(c) && !is_special(c))
10462                         ) {
10463                         USTPUTC('$', out);
10464                         pungetc();
10465                 } else if (c == '(') {  /* $(command) or $((arith)) */
10466                         if (pgetc() == '(') {
10467                                 PARSEARITH();
10468                         } else {
10469                                 pungetc();
10470                                 PARSEBACKQNEW();
10471                         }
10472                 } else {
10473                         USTPUTC(CTLVAR, out);
10474                         typeloc = out - stackblock();
10475                         USTPUTC(VSNORMAL, out);
10476                         subtype = VSNORMAL;
10477                         if (c == '{') {
10478                                 c = pgetc();
10479                                 if (c == '#') {
10480                                         if ((c = pgetc()) == '}')
10481                                                 c = '#';
10482                                         else
10483                                                 subtype = VSLENGTH;
10484                                 } else
10485                                         subtype = 0;
10486                         }
10487                         if (c > PEOA && is_name(c)) {
10488                                 do {
10489                                         STPUTC(c, out);
10490                                         c = pgetc();
10491                                 } while (c > PEOA && is_in_name(c));
10492                         } else if (is_digit(c)) {
10493                                 do {
10494                                         USTPUTC(c, out);
10495                                         c = pgetc();
10496                                 } while (is_digit(c));
10497                         } else if (is_special(c)) {
10498                                 USTPUTC(c, out);
10499                                 c = pgetc();
10500                         } else
10501                           badsub:synerror("Bad substitution");
10502
10503                         STPUTC('=', out);
10504                         flags = 0;
10505                         if (subtype == 0) {
10506                                 switch (c) {
10507                                 case ':':
10508                                         flags = VSNUL;
10509                                         c = pgetc();
10510                                  /*FALLTHROUGH*/ default:
10511                                         p = strchr(types, c);
10512                                         if (p == NULL)
10513                                                 goto badsub;
10514                                         subtype = p - types + VSNORMAL;
10515                                         break;
10516                                 case '%':
10517                                 case '#':
10518                                 {
10519                                         int cc = c;
10520
10521                                         subtype = c == '#' ? VSTRIMLEFT : VSTRIMRIGHT;
10522                                         c = pgetc();
10523                                         if (c == cc)
10524                                                 subtype++;
10525                                         else
10526                                                 pungetc();
10527                                         break;
10528                                 }
10529                                 }
10530                         } else {
10531                                 pungetc();
10532                         }
10533                         if (dblquote || arinest)
10534                                 flags |= VSQUOTE;
10535                         *(stackblock() + typeloc) = subtype | flags;
10536                         if (subtype != VSNORMAL) {
10537                                 varnest++;
10538                                 if (dblquote) {
10539                                         dqvarnest++;
10540                                 }
10541                         }
10542                 }
10543                 goto parsesub_return;
10544         }
10545
10546
10547 /*
10548  * Called to parse command substitutions.  Newstyle is set if the command
10549  * is enclosed inside $(...); nlpp is a pointer to the head of the linked
10550  * list of commands (passed by reference), and savelen is the number of
10551  * characters on the top of the stack which must be preserved.
10552  */
10553
10554   parsebackq:{
10555                 struct nodelist **nlpp;
10556                 int savepbq;
10557                 union node *n;
10558                 char *volatile str;
10559                 struct jmploc jmploc;
10560                 struct jmploc *volatile savehandler;
10561                 int savelen;
10562                 int saveprompt;
10563
10564 #ifdef __GNUC__
10565                 (void) &saveprompt;
10566 #endif
10567
10568                 savepbq = parsebackquote;
10569                 if (setjmp(jmploc.loc)) {
10570                         free(str);
10571                         parsebackquote = 0;
10572                         handler = savehandler;
10573                         longjmp(handler->loc, 1);
10574                 }
10575                 INTOFF;
10576                 str = NULL;
10577                 savelen = out - stackblock();
10578                 if (savelen > 0) {
10579                         str = xmalloc(savelen);
10580                         memcpy(str, stackblock(), savelen);
10581                 }
10582                 savehandler = handler;
10583                 handler = &jmploc;
10584                 INTON;
10585                 if (oldstyle) {
10586                         /* We must read until the closing backquote, giving special
10587                            treatment to some slashes, and then push the string and
10588                            reread it as input, interpreting it normally.  */
10589                         char *pout;
10590                         int pc;
10591                         int psavelen;
10592                         char *pstr;
10593
10594
10595                         STARTSTACKSTR(pout);
10596                         for (;;) {
10597                                 if (needprompt) {
10598                                         setprompt(2);
10599                                         needprompt = 0;
10600                                 }
10601                                 switch (pc = pgetc()) {
10602                                 case '`':
10603                                         goto done;
10604
10605                                 case '\\':
10606                                         if ((pc = pgetc()) == '\n') {
10607                                                 plinno++;
10608                                                 if (doprompt)
10609                                                         setprompt(2);
10610                                                 else
10611                                                         setprompt(0);
10612                                                 /*
10613                                                  * If eating a newline, avoid putting
10614                                                  * the newline into the new character
10615                                                  * stream (via the STPUTC after the
10616                                                  * switch).
10617                                                  */
10618                                                 continue;
10619                                         }
10620                                         if (pc != '\\' && pc != '`' && pc != '$'
10621                                                 && (!dblquote || pc != '"'))
10622                                                 STPUTC('\\', pout);
10623                                         if (pc > PEOA) {
10624                                                 break;
10625                                         }
10626                                         /* fall through */
10627
10628                                 case PEOF:
10629 #ifdef CONFIG_ASH_ALIAS
10630                                 case PEOA:
10631 #endif
10632                                         startlinno = plinno;
10633                                         synerror("EOF in backquote substitution");
10634
10635                                 case '\n':
10636                                         plinno++;
10637                                         needprompt = doprompt;
10638                                         break;
10639
10640                                 default:
10641                                         break;
10642                                 }
10643                                 STPUTC(pc, pout);
10644                         }
10645                   done:
10646                         STPUTC('\0', pout);
10647                         psavelen = pout - stackblock();
10648                         if (psavelen > 0) {
10649                                 pstr = grabstackstr(pout);
10650                                 setinputstring(pstr);
10651                         }
10652                 }
10653                 nlpp = &bqlist;
10654                 while (*nlpp)
10655                         nlpp = &(*nlpp)->next;
10656                 *nlpp = (struct nodelist *) stalloc(sizeof(struct nodelist));
10657                 (*nlpp)->next = NULL;
10658                 parsebackquote = oldstyle;
10659
10660                 if (oldstyle) {
10661                         saveprompt = doprompt;
10662                         doprompt = 0;
10663                 }
10664
10665                 n = list(0);
10666
10667                 if (oldstyle)
10668                         doprompt = saveprompt;
10669                 else {
10670                         if (readtoken() != TRP)
10671                                 synexpect(TRP);
10672                 }
10673
10674                 (*nlpp)->n = n;
10675                 if (oldstyle) {
10676                         /*
10677                          * Start reading from old file again, ignoring any pushed back
10678                          * tokens left from the backquote parsing
10679                          */
10680                         popfile();
10681                         tokpushback = 0;
10682                 }
10683                 while (stackblocksize() <= savelen)
10684                         growstackblock();
10685                 STARTSTACKSTR(out);
10686                 if (str) {
10687                         memcpy(out, str, savelen);
10688                         STADJUST(savelen, out);
10689                         INTOFF;
10690                         free(str);
10691                         str = NULL;
10692                         INTON;
10693                 }
10694                 parsebackquote = savepbq;
10695                 handler = savehandler;
10696                 if (arinest || dblquote)
10697                         USTPUTC(CTLBACKQ | CTLQUOTE, out);
10698                 else
10699                         USTPUTC(CTLBACKQ, out);
10700                 if (oldstyle)
10701                         goto parsebackq_oldreturn;
10702                 else
10703                         goto parsebackq_newreturn;
10704         }
10705
10706 /*
10707  * Parse an arithmetic expansion (indicate start of one and set state)
10708  */
10709   parsearith:{
10710
10711                 if (++arinest == 1) {
10712                         prevsyntax = syntax;
10713                         syntax = ARISYNTAX;
10714                         USTPUTC(CTLARI, out);
10715                         if (dblquote)
10716                                 USTPUTC('"', out);
10717                         else
10718                                 USTPUTC(' ', out);
10719                 } else {
10720                         /*
10721                          * we collapse embedded arithmetic expansion to
10722                          * parenthesis, which should be equivalent
10723                          */
10724                         USTPUTC('(', out);
10725                 }
10726                 goto parsearith_return;
10727         }
10728
10729 }                                               /* end of readtoken */
10730
10731
10732 /*
10733  * Returns true if the text contains nothing to expand (no dollar signs
10734  * or backquotes).
10735  */
10736
10737 static int noexpand(char *text)
10738 {
10739         char *p;
10740         char c;
10741
10742         p = text;
10743         while ((c = *p++) != '\0') {
10744                 if (c == CTLQUOTEMARK)
10745                         continue;
10746                 if (c == CTLESC)
10747                         p++;
10748                 else if (SIT(c, BASESYNTAX) == CCTL)
10749                         return 0;
10750         }
10751         return 1;
10752 }
10753
10754
10755 /*
10756  * Return true if the argument is a legal variable name (a letter or
10757  * underscore followed by zero or more letters, underscores, and digits).
10758  */
10759
10760 static int goodname(const char *name)
10761 {
10762         const char *p;
10763
10764         p = name;
10765         if (!is_name(*p))
10766                 return 0;
10767         while (*++p) {
10768                 if (!is_in_name(*p))
10769                         return 0;
10770         }
10771         return 1;
10772 }
10773
10774
10775 /*
10776  * Called when an unexpected token is read during the parse.  The argument
10777  * is the token that is expected, or -1 if more than one type of token can
10778  * occur at this point.
10779  */
10780
10781 static void synexpect(int token)
10782 {
10783         char msg[64];
10784         int l;
10785
10786         l = sprintf(msg, "%s unexpected", tokname(lasttoken));
10787         if (token >= 0)
10788                 sprintf(msg + l, " (expecting %s)", tokname(token));
10789         synerror(msg);
10790         /* NOTREACHED */
10791 }
10792
10793
10794 static void synerror(const char *msg)
10795 {
10796         if (commandname)
10797                 out2fmt("%s: %d: ", commandname, startlinno);
10798         out2fmt("Syntax error: %s\n", msg);
10799         error((char *) NULL);
10800         /* NOTREACHED */
10801 }
10802
10803
10804 /*
10805  * called by editline -- any expansions to the prompt
10806  *    should be added here.
10807  */
10808 static void setprompt(int whichprompt)
10809 {
10810         char *prompt;
10811
10812         switch (whichprompt) {
10813         case 1:
10814                 prompt = ps1val();
10815                 break;
10816         case 2:
10817                 prompt = ps2val();
10818                 break;
10819         default:                        /* 0 */
10820                 prompt = "";
10821         }
10822         putprompt(prompt);
10823 }
10824
10825
10826 /*
10827  * Code for dealing with input/output redirection.
10828  */
10829
10830 #define EMPTY -2                /* marks an unused slot in redirtab */
10831 #ifndef PIPE_BUF
10832 # define PIPESIZE 4096  /* amount of buffering in a pipe */
10833 #else
10834 # define PIPESIZE PIPE_BUF
10835 #endif
10836
10837
10838 /*
10839  * Open a file in noclobber mode.
10840  * The code was copied from bash.
10841  */
10842 static inline int noclobberopen(const char *fname)
10843 {
10844         int r, fd;
10845         struct stat finfo, finfo2;
10846
10847         /*
10848          * If the file exists and is a regular file, return an error
10849          * immediately.
10850          */
10851         r = stat(fname, &finfo);
10852         if (r == 0 && S_ISREG(finfo.st_mode)) {
10853                 errno = EEXIST;
10854                 return -1;
10855         }
10856
10857         /*
10858          * If the file was not present (r != 0), make sure we open it
10859          * exclusively so that if it is created before we open it, our open
10860          * will fail.  Make sure that we do not truncate an existing file.
10861          * Note that we don't turn on O_EXCL unless the stat failed -- if the
10862          * file was not a regular file, we leave O_EXCL off.
10863          */
10864         if (r != 0)
10865                 return open(fname, O_WRONLY | O_CREAT | O_EXCL, 0666);
10866         fd = open(fname, O_WRONLY | O_CREAT, 0666);
10867
10868         /* If the open failed, return the file descriptor right away. */
10869         if (fd < 0)
10870                 return fd;
10871
10872         /*
10873          * OK, the open succeeded, but the file may have been changed from a
10874          * non-regular file to a regular file between the stat and the open.
10875          * We are assuming that the O_EXCL open handles the case where FILENAME
10876          * did not exist and is symlinked to an existing file between the stat
10877          * and open.
10878          */
10879
10880         /*
10881          * If we can open it and fstat the file descriptor, and neither check
10882          * revealed that it was a regular file, and the file has not been
10883          * replaced, return the file descriptor.
10884          */
10885         if (fstat(fd, &finfo2) == 0 && !S_ISREG(finfo2.st_mode) &&
10886                 finfo.st_dev == finfo2.st_dev && finfo.st_ino == finfo2.st_ino)
10887                 return fd;
10888
10889         /* The file has been replaced.  badness. */
10890         close(fd);
10891         errno = EEXIST;
10892         return -1;
10893 }
10894
10895 /*
10896  * Handle here documents.  Normally we fork off a process to write the
10897  * data to a pipe.  If the document is short, we can stuff the data in
10898  * the pipe without forking.
10899  */
10900
10901 static inline int openhere(const union node *redir)
10902 {
10903         int pip[2];
10904         int len = 0;
10905
10906         if (pipe(pip) < 0)
10907                 error("Pipe call failed");
10908         if (redir->type == NHERE) {
10909                 len = strlen(redir->nhere.doc->narg.text);
10910                 if (len <= PIPESIZE) {
10911                         xwrite(pip[1], redir->nhere.doc->narg.text, len);
10912                         goto out;
10913                 }
10914         }
10915         if (forkshell((struct job *) NULL, (union node *) NULL, FORK_NOJOB) == 0) {
10916                 close(pip[0]);
10917                 signal(SIGINT, SIG_IGN);
10918                 signal(SIGQUIT, SIG_IGN);
10919                 signal(SIGHUP, SIG_IGN);
10920 #ifdef SIGTSTP
10921                 signal(SIGTSTP, SIG_IGN);
10922 #endif
10923                 signal(SIGPIPE, SIG_DFL);
10924                 if (redir->type == NHERE)
10925                         xwrite(pip[1], redir->nhere.doc->narg.text, len);
10926                 else
10927                         expandhere(redir->nhere.doc, pip[1]);
10928                 _exit(0);
10929         }
10930   out:
10931         close(pip[1]);
10932         return pip[0];
10933 }
10934
10935
10936 static inline int openredirect(const union node *redir)
10937 {
10938         char *fname;
10939         int f;
10940
10941         switch (redir->nfile.type) {
10942         case NFROM:
10943                 fname = redir->nfile.expfname;
10944                 if ((f = open(fname, O_RDONLY)) < 0)
10945                         goto eopen;
10946                 break;
10947         case NFROMTO:
10948                 fname = redir->nfile.expfname;
10949                 if ((f = open(fname, O_RDWR | O_CREAT | O_TRUNC, 0666)) < 0)
10950                         goto ecreate;
10951                 break;
10952         case NTO:
10953                 /* Take care of noclobber mode. */
10954                 if (Cflag) {
10955                         fname = redir->nfile.expfname;
10956                         if ((f = noclobberopen(fname)) < 0)
10957                                 goto ecreate;
10958                         break;
10959                 }
10960         case NTOOV:
10961                 fname = redir->nfile.expfname;
10962 #ifdef O_CREAT
10963                 if ((f = open(fname, O_WRONLY | O_CREAT | O_TRUNC, 0666)) < 0)
10964                         goto ecreate;
10965 #else
10966                 if ((f = creat(fname, 0666)) < 0)
10967                         goto ecreate;
10968 #endif
10969                 break;
10970         case NAPPEND:
10971                 fname = redir->nfile.expfname;
10972 #ifdef O_APPEND
10973                 if ((f = open(fname, O_WRONLY | O_CREAT | O_APPEND, 0666)) < 0)
10974                         goto ecreate;
10975 #else
10976                 if ((f = open(fname, O_WRONLY)) < 0 && (f = creat(fname, 0666)) < 0)
10977                         goto ecreate;
10978                 lseek(f, (off_t) 0, 2);
10979 #endif
10980                 break;
10981         default:
10982 #ifdef DEBUG
10983                 abort();
10984 #endif
10985                 /* Fall through to eliminate warning. */
10986         case NTOFD:
10987         case NFROMFD:
10988                 f = -1;
10989                 break;
10990         case NHERE:
10991         case NXHERE:
10992                 f = openhere(redir);
10993                 break;
10994         }
10995
10996         return f;
10997   ecreate:
10998         error("cannot create %s: %s", fname, errmsg(errno, E_CREAT));
10999   eopen:
11000         error("cannot open %s: %s", fname, errmsg(errno, E_OPEN));
11001 }
11002
11003
11004 /*
11005  * Process a list of redirection commands.  If the REDIR_PUSH flag is set,
11006  * old file descriptors are stashed away so that the redirection can be
11007  * undone by calling popredir.  If the REDIR_BACKQ flag is set, then the
11008  * standard output, and the standard error if it becomes a duplicate of
11009  * stdout.
11010  */
11011
11012 static void redirect(union node *redir, int flags)
11013 {
11014         union node *n;
11015         struct redirtab *sv = NULL;
11016         int i = EMPTY;
11017         int fd;
11018         int newfd;
11019         int try;
11020         int fd1dup = flags & REDIR_BACKQ;;      /* stdout `cmd` redir to pipe */
11021
11022         if (flags & REDIR_PUSH) {
11023                 sv = xmalloc(sizeof(struct redirtab));
11024                 for (i = 0; i < 10; i++)
11025                         sv->renamed[i] = EMPTY;
11026                 sv->next = redirlist;
11027                 redirlist = sv;
11028         }
11029         for (n = redir; n; n = n->nfile.next) {
11030                 fd = n->nfile.fd;
11031                 try = 0;
11032                 if ((n->nfile.type == NTOFD || n->nfile.type == NFROMFD) &&
11033                         n->ndup.dupfd == fd)
11034                         continue;       /* redirect from/to same file descriptor */
11035
11036                 INTOFF;
11037                 newfd = openredirect(n);
11038                 if ((flags & REDIR_PUSH) && sv->renamed[fd] == EMPTY) {
11039                         if (newfd == fd) {
11040                                 try++;
11041                         } else if ((i = fcntl(fd, F_DUPFD, 10)) == -1) {
11042                                 switch (errno) {
11043                                 case EBADF:
11044                                         if (!try) {
11045                                                 dupredirect(n, newfd, fd1dup);
11046                                                 try++;
11047                                                 break;
11048                                         }
11049                                         /* FALLTHROUGH */
11050                                 default:
11051                                         if (newfd >= 0) {
11052                                                 close(newfd);
11053                                         }
11054                                         INTON;
11055                                         error("%d: %m", fd);
11056                                         /* NOTREACHED */
11057                                 }
11058                         }
11059                         if (!try) {
11060                                 close(fd);
11061                                 if (flags & REDIR_PUSH) {
11062                                         sv->renamed[fd] = i;
11063                                 }
11064                         }
11065                 } else if (fd != newfd) {
11066                         close(fd);
11067                 }
11068                 if (fd == 0)
11069                         fd0_redirected++;
11070                 if (!try)
11071                         dupredirect(n, newfd, fd1dup);
11072                 INTON;
11073         }
11074 }
11075
11076
11077 static void dupredirect(const union node *redir, int f, int fd1dup)
11078 {
11079         int fd = redir->nfile.fd;
11080
11081         if (fd == 1)
11082                 fd1dup = 0;
11083         if (redir->nfile.type == NTOFD || redir->nfile.type == NFROMFD) {
11084                 if (redir->ndup.dupfd >= 0) {   /* if not ">&-" */
11085                         if (redir->ndup.dupfd != 1 || fd1dup != 1)
11086                                 dup_as_newfd(redir->ndup.dupfd, fd);
11087                 }
11088                 return;
11089         }
11090
11091         if (f != fd) {
11092                 dup_as_newfd(f, fd);
11093                 close(f);
11094         }
11095         return;
11096 }
11097
11098
11099
11100 /*
11101  * Undo the effects of the last redirection.
11102  */
11103
11104 static void popredir(void)
11105 {
11106         struct redirtab *rp = redirlist;
11107         int i;
11108
11109         INTOFF;
11110         for (i = 0; i < 10; i++) {
11111                 if (rp->renamed[i] != EMPTY) {
11112                         if (i == 0)
11113                                 fd0_redirected--;
11114                         close(i);
11115                         if (rp->renamed[i] >= 0) {
11116                                 dup_as_newfd(rp->renamed[i], i);
11117                                 close(rp->renamed[i]);
11118                         }
11119                 }
11120         }
11121         redirlist = rp->next;
11122         free(rp);
11123         INTON;
11124 }
11125
11126 /*
11127  * Discard all saved file descriptors.
11128  */
11129
11130 static void clearredir(void)
11131 {
11132         struct redirtab *rp;
11133         int i;
11134
11135         for (rp = redirlist; rp; rp = rp->next) {
11136                 for (i = 0; i < 10; i++) {
11137                         if (rp->renamed[i] >= 0) {
11138                                 close(rp->renamed[i]);
11139                         }
11140                         rp->renamed[i] = EMPTY;
11141                 }
11142         }
11143 }
11144
11145
11146 /*
11147  * Copy a file descriptor to be >= to.  Returns -1
11148  * if the source file descriptor is closed, EMPTY if there are no unused
11149  * file descriptors left.
11150  */
11151
11152 static int dup_as_newfd(int from, int to)
11153 {
11154         int newfd;
11155
11156         newfd = fcntl(from, F_DUPFD, to);
11157         if (newfd < 0) {
11158                 if (errno == EMFILE)
11159                         return EMPTY;
11160                 else
11161                         error("%d: %m", from);
11162         }
11163         return newfd;
11164 }
11165
11166 #ifdef DEBUG
11167 /*
11168  * Debugging stuff.
11169  */
11170 static void shtree(union node *, int, char *, FILE *);
11171 static void shcmd(union node *, FILE *);
11172 static void sharg(union node *, FILE *);
11173 static void indent(int, char *, FILE *);
11174 static void trstring(char *);
11175
11176
11177 static void showtree(n)
11178         unode *n;
11179 {
11180         trputs("showtree called\n");
11181         shtree(n, 1, NULL, stdout);
11182 }
11183
11184
11185 static void shtree(union node *n, int ind, char *pfx, FILE * fp)
11186 {
11187         struct nodelist *lp;
11188         const char *s;
11189
11190         if (n == NULL)
11191                 return;
11192
11193         indent(ind, pfx, fp);
11194         switch (n->type) {
11195         case NSEMI:
11196                 s = "; ";
11197                 goto binop;
11198         case NAND:
11199                 s = " && ";
11200                 goto binop;
11201         case NOR:
11202                 s = " || ";
11203           binop:
11204                 shtree(n->nbinary.ch1, ind, NULL, fp);
11205                 /*    if (ind < 0) */
11206                 fputs(s, fp);
11207                 shtree(n->nbinary.ch2, ind, NULL, fp);
11208                 break;
11209         case NCMD:
11210                 shcmd(n, fp);
11211                 if (ind >= 0)
11212                         putc('\n', fp);
11213                 break;
11214         case NPIPE:
11215                 for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
11216                         shcmd(lp->n, fp);
11217                         if (lp->next)
11218                                 fputs(" | ", fp);
11219                 }
11220                 if (n->npipe.backgnd)
11221                         fputs(" &", fp);
11222                 if (ind >= 0)
11223                         putc('\n', fp);
11224                 break;
11225         default:
11226                 fprintf(fp, "<node type %d>", n->type);
11227                 if (ind >= 0)
11228                         putc('\n', fp);
11229                 break;
11230         }
11231 }
11232
11233
11234
11235 static void shcmd(union node *cmd, FILE * fp)
11236 {
11237         union node *np;
11238         int first;
11239         const char *s;
11240         int dftfd;
11241
11242         first = 1;
11243         for (np = cmd->ncmd.args; np; np = np->narg.next) {
11244                 if (!first)
11245                         putchar(' ');
11246                 sharg(np, fp);
11247                 first = 0;
11248         }
11249         for (np = cmd->ncmd.redirect; np; np = np->nfile.next) {
11250                 if (!first)
11251                         putchar(' ');
11252 #if 1
11253                 s = "*error*";
11254                 dftfd = 0;
11255                 if ((np->nfile.type <= NFROMFD) && (np->nfile.type >= NTO)) {
11256                         s = redir_strings[np->nfile.type - NTO];
11257                         if (*s == '>') {
11258                                 dftfd = 1;
11259                         }
11260                 }
11261 #else
11262                 switch (np->nfile.type) {
11263                 case NTO:
11264                         s = ">";
11265                         dftfd = 1;
11266                         break;
11267                 case NAPPEND:
11268                         s = ">>";
11269                         dftfd = 1;
11270                         break;
11271                 case NTOFD:
11272                         s = ">&";
11273                         dftfd = 1;
11274                         break;
11275                 case NTOOV:
11276                         s = ">|";
11277                         dftfd = 1;
11278                         break;
11279                 case NFROM:
11280                         s = "<";
11281                         dftfd = 0;
11282                         break;
11283                 case NFROMFD:
11284                         s = "<&";
11285                         dftfd = 0;
11286                         break;
11287                 case NFROMTO:
11288                         s = "<>";
11289                         dftfd = 0;
11290                         break;
11291                 default:
11292                         s = "*error*";
11293                         dftfd = 0;
11294                         break;
11295                 }
11296 #endif
11297                 if (np->nfile.fd != dftfd)
11298                         fprintf(fp, "%d", np->nfile.fd);
11299                 fputs(s, fp);
11300                 if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) {
11301                         fprintf(fp, "%d", np->ndup.dupfd);
11302                 } else {
11303                         sharg(np->nfile.fname, fp);
11304                 }
11305                 first = 0;
11306         }
11307 }
11308
11309 static void sharg(union node *arg, FILE * fp)
11310 {
11311         char *p;
11312         struct nodelist *bqlist;
11313         int subtype;
11314
11315         if (arg->type != NARG) {
11316                 printf("<node type %d>\n", arg->type);
11317                 fflush(stdout);
11318                 abort();
11319         }
11320         bqlist = arg->narg.backquote;
11321         for (p = arg->narg.text; *p; p++) {
11322                 switch (*p) {
11323                 case CTLESC:
11324                         putc(*++p, fp);
11325                         break;
11326                 case CTLVAR:
11327                         putc('$', fp);
11328                         putc('{', fp);
11329                         subtype = *++p;
11330                         if (subtype == VSLENGTH)
11331                                 putc('#', fp);
11332
11333                         while (*p != '=')
11334                                 putc(*p++, fp);
11335
11336                         if (subtype & VSNUL)
11337                                 putc(':', fp);
11338
11339                         switch (subtype & VSTYPE) {
11340                         case VSNORMAL:
11341                                 putc('}', fp);
11342                                 break;
11343                         case VSMINUS:
11344                                 putc('-', fp);
11345                                 break;
11346                         case VSPLUS:
11347                                 putc('+', fp);
11348                                 break;
11349                         case VSQUESTION:
11350                                 putc('?', fp);
11351                                 break;
11352                         case VSASSIGN:
11353                                 putc('=', fp);
11354                                 break;
11355                         case VSTRIMLEFT:
11356                                 putc('#', fp);
11357                                 break;
11358                         case VSTRIMLEFTMAX:
11359                                 putc('#', fp);
11360                                 putc('#', fp);
11361                                 break;
11362                         case VSTRIMRIGHT:
11363                                 putc('%', fp);
11364                                 break;
11365                         case VSTRIMRIGHTMAX:
11366                                 putc('%', fp);
11367                                 putc('%', fp);
11368                                 break;
11369                         case VSLENGTH:
11370                                 break;
11371                         default:
11372                                 printf("<subtype %d>", subtype);
11373                         }
11374                         break;
11375                 case CTLENDVAR:
11376                         putc('}', fp);
11377                         break;
11378                 case CTLBACKQ:
11379                 case CTLBACKQ | CTLQUOTE:
11380                         putc('$', fp);
11381                         putc('(', fp);
11382                         shtree(bqlist->n, -1, NULL, fp);
11383                         putc(')', fp);
11384                         break;
11385                 default:
11386                         putc(*p, fp);
11387                         break;
11388                 }
11389         }
11390 }
11391
11392
11393 static void indent(int amount, char *pfx, FILE * fp)
11394 {
11395         int i;
11396
11397         for (i = 0; i < amount; i++) {
11398                 if (pfx && i == amount - 1)
11399                         fputs(pfx, fp);
11400                 putc('\t', fp);
11401         }
11402 }
11403
11404
11405 FILE *tracefile;
11406
11407 #if DEBUG == 2
11408 static int debug = 1;
11409 #else
11410 static int debug = 0;
11411 #endif
11412
11413
11414 static void trputc(int c)
11415 {
11416         if (tracefile == NULL)
11417                 return;
11418         putc(c, tracefile);
11419         if (c == '\n')
11420                 fflush(tracefile);
11421 }
11422
11423 static void trace(const char *fmt, ...)
11424 {
11425         va_list va;
11426
11427         va_start(va, fmt);
11428         if (tracefile != NULL) {
11429                 (void) vfprintf(tracefile, fmt, va);
11430                 if (strchr(fmt, '\n'))
11431                         (void) fflush(tracefile);
11432         }
11433         va_end(va);
11434 }
11435
11436
11437 static void trputs(const char *s)
11438 {
11439         if (tracefile == NULL)
11440                 return;
11441         fputs(s, tracefile);
11442         if (strchr(s, '\n'))
11443                 fflush(tracefile);
11444 }
11445
11446
11447 static void trstring(char *s)
11448 {
11449         char *p;
11450         char c;
11451
11452         if (tracefile == NULL)
11453                 return;
11454         putc('"', tracefile);
11455         for (p = s; *p; p++) {
11456                 switch (*p) {
11457                 case '\n':
11458                         c = 'n';
11459                         goto backslash;
11460                 case '\t':
11461                         c = 't';
11462                         goto backslash;
11463                 case '\r':
11464                         c = 'r';
11465                         goto backslash;
11466                 case '"':
11467                         c = '"';
11468                         goto backslash;
11469                 case '\\':
11470                         c = '\\';
11471                         goto backslash;
11472                 case CTLESC:
11473                         c = 'e';
11474                         goto backslash;
11475                 case CTLVAR:
11476                         c = 'v';
11477                         goto backslash;
11478                 case CTLVAR + CTLQUOTE:
11479                         c = 'V';
11480                         goto backslash;
11481                 case CTLBACKQ:
11482                         c = 'q';
11483                         goto backslash;
11484                 case CTLBACKQ + CTLQUOTE:
11485                         c = 'Q';
11486                         goto backslash;
11487                   backslash:putc('\\', tracefile);
11488                         putc(c, tracefile);
11489                         break;
11490                 default:
11491                         if (*p >= ' ' && *p <= '~')
11492                                 putc(*p, tracefile);
11493                         else {
11494                                 putc('\\', tracefile);
11495                                 putc(*p >> 6 & 03, tracefile);
11496                                 putc(*p >> 3 & 07, tracefile);
11497                                 putc(*p & 07, tracefile);
11498                         }
11499                         break;
11500                 }
11501         }
11502         putc('"', tracefile);
11503 }
11504
11505
11506 static void trargs(char **ap)
11507 {
11508         if (tracefile == NULL)
11509                 return;
11510         while (*ap) {
11511                 trstring(*ap++);
11512                 if (*ap)
11513                         putc(' ', tracefile);
11514                 else
11515                         putc('\n', tracefile);
11516         }
11517         fflush(tracefile);
11518 }
11519
11520
11521 static void opentrace()
11522 {
11523         char s[100];
11524
11525 #ifdef O_APPEND
11526         int flags;
11527 #endif
11528
11529         if (!debug)
11530                 return;
11531 #ifdef not_this_way
11532         {
11533                 char *p;
11534
11535                 if ((p = getenv("HOME")) == NULL) {
11536                         if (geteuid() == 0)
11537                                 p = "/";
11538                         else
11539                                 p = "/tmp";
11540                 }
11541                 strcpy(s, p);
11542                 strcat(s, "/trace");
11543         }
11544 #else
11545         strcpy(s, "./trace");
11546 #endif                                                  /* not_this_way */
11547         if ((tracefile = wfopen(s, "a")) == NULL)
11548                 return;
11549 #ifdef O_APPEND
11550         if ((flags = fcntl(fileno(tracefile), F_GETFL, 0)) >= 0)
11551                 fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND);
11552 #endif
11553         fputs("\nTracing started.\n", tracefile);
11554         fflush(tracefile);
11555 }
11556 #endif                                                  /* DEBUG */
11557
11558
11559 /*
11560  * The trap builtin.
11561  */
11562
11563 static int trapcmd(int argc, char **argv)
11564 {
11565         char *action;
11566         char **ap;
11567         int signo;
11568
11569         if (argc <= 1) {
11570                 for (signo = 0; signo < NSIG; signo++) {
11571                         if (trap[signo] != NULL) {
11572                                 char *p;
11573                                 const char *sn;
11574
11575                                 p = single_quote(trap[signo]);
11576                                 sn = sys_siglist[signo];
11577                                 if (sn == NULL)
11578                                         sn = u_signal_names(0, &signo, 0);
11579                                 if (sn == NULL)
11580                                         sn = "???";
11581                                 printf("trap -- %s %s\n", p, sn);
11582                                 stunalloc(p);
11583                         }
11584                 }
11585                 return 0;
11586         }
11587         ap = argv + 1;
11588         if (argc == 2)
11589                 action = NULL;
11590         else
11591                 action = *ap++;
11592         while (*ap) {
11593                 if ((signo = decode_signal(*ap, 0)) < 0)
11594                         error("%s: bad trap", *ap);
11595                 INTOFF;
11596                 if (action) {
11597                         if (action[0] == '-' && action[1] == '\0')
11598                                 action = NULL;
11599                         else
11600                                 action = xstrdup(action);
11601                 }
11602                 free(trap[signo]);
11603                 trap[signo] = action;
11604                 if (signo != 0)
11605                         setsignal(signo);
11606                 INTON;
11607                 ap++;
11608         }
11609         return 0;
11610 }
11611
11612
11613
11614
11615
11616
11617 /*
11618  * Set the signal handler for the specified signal.  The routine figures
11619  * out what it should be set to.
11620  */
11621
11622 static void setsignal(int signo)
11623 {
11624         int action;
11625         char *t;
11626         struct sigaction act;
11627
11628         if ((t = trap[signo]) == NULL)
11629                 action = S_DFL;
11630         else if (*t != '\0')
11631                 action = S_CATCH;
11632         else
11633                 action = S_IGN;
11634         if (rootshell && action == S_DFL) {
11635                 switch (signo) {
11636                 case SIGINT:
11637                         if (iflag || minusc || sflag == 0)
11638                                 action = S_CATCH;
11639                         break;
11640                 case SIGQUIT:
11641 #ifdef DEBUG
11642                 {
11643
11644                         if (debug)
11645                                 break;
11646                 }
11647 #endif
11648                         /* FALLTHROUGH */
11649                 case SIGTERM:
11650                         if (iflag)
11651                                 action = S_IGN;
11652                         break;
11653 #ifdef CONFIG_ASH_JOB_CONTROL
11654                 case SIGTSTP:
11655                 case SIGTTOU:
11656                         if (mflag)
11657                                 action = S_IGN;
11658                         break;
11659 #endif
11660                 }
11661         }
11662
11663         t = &sigmode[signo - 1];
11664         if (*t == 0) {
11665                 /*
11666                  * current setting unknown
11667                  */
11668                 if (sigaction(signo, 0, &act) == -1) {
11669                         /*
11670                          * Pretend it worked; maybe we should give a warning
11671                          * here, but other shells don't. We don't alter
11672                          * sigmode, so that we retry every time.
11673                          */
11674                         return;
11675                 }
11676                 if (act.sa_handler == SIG_IGN) {
11677                         if (mflag && (signo == SIGTSTP ||
11678                                                   signo == SIGTTIN || signo == SIGTTOU)) {
11679                                 *t = S_IGN;     /* don't hard ignore these */
11680                         } else
11681                                 *t = S_HARD_IGN;
11682                 } else {
11683                         *t = S_RESET;   /* force to be set */
11684                 }
11685         }
11686         if (*t == S_HARD_IGN || *t == action)
11687                 return;
11688         act.sa_handler = ((action == S_CATCH) ? onsig
11689                                           : ((action == S_IGN) ? SIG_IGN : SIG_DFL));
11690         *t = action;
11691         act.sa_flags = 0;
11692         sigemptyset(&act.sa_mask);
11693         sigaction(signo, &act, 0);
11694 }
11695
11696 /*
11697  * Ignore a signal.
11698  */
11699
11700 static void ignoresig(int signo)
11701 {
11702         if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) {
11703                 signal(signo, SIG_IGN);
11704         }
11705         sigmode[signo - 1] = S_HARD_IGN;
11706 }
11707
11708
11709 /*
11710  * Signal handler.
11711  */
11712
11713 static void onsig(int signo)
11714 {
11715         if (signo == SIGINT && trap[SIGINT] == NULL) {
11716                 onint();
11717                 return;
11718         }
11719         gotsig[signo - 1] = 1;
11720         pendingsigs++;
11721 }
11722
11723
11724 /*
11725  * Called to execute a trap.  Perhaps we should avoid entering new trap
11726  * handlers while we are executing a trap handler.
11727  */
11728
11729 static void dotrap(void)
11730 {
11731         int i;
11732         int savestatus;
11733
11734         for (;;) {
11735                 for (i = 1;; i++) {
11736                         if (gotsig[i - 1])
11737                                 break;
11738                         if (i >= NSIG - 1)
11739                                 goto done;
11740                 }
11741                 gotsig[i - 1] = 0;
11742                 savestatus = exitstatus;
11743                 evalstring(trap[i], 0);
11744                 exitstatus = savestatus;
11745         }
11746   done:
11747         pendingsigs = 0;
11748 }
11749
11750 /*
11751  * Called to exit the shell.
11752  */
11753
11754 static void exitshell(int status)
11755 {
11756         struct jmploc loc1, loc2;
11757         char *p;
11758
11759         TRACE(("exitshell(%d) pid=%d\n", status, getpid()));
11760         if (setjmp(loc1.loc)) {
11761                 goto l1;
11762         }
11763         if (setjmp(loc2.loc)) {
11764                 goto l2;
11765         }
11766         handler = &loc1;
11767         if ((p = trap[0]) != NULL && *p != '\0') {
11768                 trap[0] = NULL;
11769                 evalstring(p, 0);
11770         }
11771   l1:handler = &loc2;   /* probably unnecessary */
11772         flushall();
11773 #ifdef CONFIG_ASH_JOB_CONTROL
11774         setjobctl(0);
11775 #endif
11776   l2:_exit(status);
11777         /* NOTREACHED */
11778 }
11779
11780 static int decode_signal(const char *string, int minsig)
11781 {
11782         int signo;
11783         const char *name = u_signal_names(string, &signo, minsig);
11784
11785         return name ? signo : -1;
11786 }
11787
11788 static struct var **hashvar(const char *);
11789 static void showvars(const char *, int, int);
11790 static struct var **findvar(struct var **, const char *);
11791
11792 /*
11793  * Initialize the varable symbol tables and import the environment
11794  */
11795
11796 /*
11797  * This routine initializes the builtin variables.  It is called when the
11798  * shell is initialized and again when a shell procedure is spawned.
11799  */
11800
11801 static void initvar()
11802 {
11803         const struct varinit *ip;
11804         struct var *vp;
11805         struct var **vpp;
11806
11807         for (ip = varinit; (vp = ip->var) != NULL; ip++) {
11808                 if ((vp->flags & VEXPORT) == 0) {
11809                         vpp = hashvar(ip->text);
11810                         vp->next = *vpp;
11811                         *vpp = vp;
11812                         vp->text = xstrdup(ip->text);
11813                         vp->flags = ip->flags;
11814                         vp->func = ip->func;
11815                 }
11816         }
11817 #if !defined(CONFIG_FEATURE_COMMAND_EDITING) || !defined(CONFIG_FEATURE_SH_FANCY_PROMPT)
11818         /*
11819          * PS1 depends on uid
11820          */
11821         if ((vps1.flags & VEXPORT) == 0) {
11822                 vpp = hashvar("PS1=$");
11823                 vps1.next = *vpp;
11824                 *vpp = &vps1;
11825                 vps1.text = xstrdup(geteuid()? "PS1=$ " : "PS1=# ");
11826                 vps1.flags = VSTRFIXED | VTEXTFIXED;
11827         }
11828 #endif
11829 }
11830
11831 /*
11832  * Set the value of a variable.  The flags argument is ored with the
11833  * flags of the variable.  If val is NULL, the variable is unset.
11834  */
11835
11836 static void setvar(const char *name, const char *val, int flags)
11837 {
11838         const char *p;
11839         int len;
11840         int namelen;
11841         char *nameeq;
11842         int isbad;
11843         int vallen = 0;
11844
11845         isbad = 0;
11846         p = name;
11847         if (!is_name(*p))
11848                 isbad = 1;
11849         p++;
11850         for (;;) {
11851                 if (!is_in_name(*p)) {
11852                         if (*p == '\0' || *p == '=')
11853                                 break;
11854                         isbad = 1;
11855                 }
11856                 p++;
11857         }
11858         namelen = p - name;
11859         if (isbad)
11860                 error("%.*s: bad variable name", namelen, name);
11861         len = namelen + 2;      /* 2 is space for '=' and '\0' */
11862         if (val == NULL) {
11863                 flags |= VUNSET;
11864         } else {
11865                 len += vallen = strlen(val);
11866         }
11867         INTOFF;
11868         nameeq = xmalloc(len);
11869         memcpy(nameeq, name, namelen);
11870         nameeq[namelen] = '=';
11871         if (val) {
11872                 memcpy(nameeq + namelen + 1, val, vallen + 1);
11873         } else {
11874                 nameeq[namelen + 1] = '\0';
11875         }
11876         setvareq(nameeq, flags);
11877         INTON;
11878 }
11879
11880
11881
11882 /*
11883  * Same as setvar except that the variable and value are passed in
11884  * the first argument as name=value.  Since the first argument will
11885  * be actually stored in the table, it should not be a string that
11886  * will go away.
11887  */
11888
11889 static void setvareq(char *s, int flags)
11890 {
11891         struct var *vp, **vpp;
11892
11893         vpp = hashvar(s);
11894         flags |= (VEXPORT & (((unsigned) (1 - aflag)) - 1));
11895         if ((vp = *findvar(vpp, s))) {
11896                 if (vp->flags & VREADONLY) {
11897                         size_t len = strchr(s, '=') - s;
11898
11899                         error("%.*s: is read only", len, s);
11900                 }
11901                 INTOFF;
11902
11903                 if (vp->func && (flags & VNOFUNC) == 0)
11904                         (*vp->func) (strchr(s, '=') + 1);
11905
11906                 if ((vp->flags & (VTEXTFIXED | VSTACK)) == 0)
11907                         free(vp->text);
11908
11909                 vp->flags &= ~(VTEXTFIXED | VSTACK | VUNSET);
11910                 vp->flags |= flags;
11911                 vp->text = s;
11912
11913 #ifdef CONFIG_ASH_MAIL
11914                 /*
11915                  * We could roll this to a function, to handle it as
11916                  * a regular variable function callback, but why bother?
11917                  */
11918                 if (iflag && (vp == &vmpath || (vp == &vmail && !mpathset())))
11919                         chkmail(1);
11920 #endif
11921                 INTON;
11922                 return;
11923         }
11924         /* not found */
11925         vp = xmalloc(sizeof(*vp));
11926         vp->flags = flags;
11927         vp->text = s;
11928         vp->next = *vpp;
11929         vp->func = NULL;
11930         *vpp = vp;
11931 }
11932
11933
11934
11935 /*
11936  * Process a linked list of variable assignments.
11937  */
11938
11939 static void listsetvar(struct strlist *mylist)
11940 {
11941         struct strlist *lp;
11942
11943         INTOFF;
11944         for (lp = mylist; lp; lp = lp->next) {
11945                 setvareq(xstrdup(lp->text), 0);
11946         }
11947         INTON;
11948 }
11949
11950
11951
11952 /*
11953  * Find the value of a variable.  Returns NULL if not set.
11954  */
11955
11956 static const char *lookupvar(const char *name)
11957 {
11958         struct var *v;
11959
11960         if ((v = *findvar(hashvar(name), name)) && !(v->flags & VUNSET)) {
11961                 return strchr(v->text, '=') + 1;
11962         }
11963         return NULL;
11964 }
11965
11966
11967
11968 /*
11969  * Search the environment of a builtin command.
11970  */
11971
11972 static const char *bltinlookup(const char *name)
11973 {
11974         const struct strlist *sp;
11975
11976         for (sp = cmdenviron; sp; sp = sp->next) {
11977                 if (varequal(sp->text, name))
11978                         return strchr(sp->text, '=') + 1;
11979         }
11980         return lookupvar(name);
11981 }
11982
11983
11984
11985 /*
11986  * Generate a list of exported variables.  This routine is used to construct
11987  * the third argument to execve when executing a program.
11988  */
11989
11990 static char **environment()
11991 {
11992         int nenv;
11993         struct var **vpp;
11994         struct var *vp;
11995         char **env;
11996         char **ep;
11997
11998         nenv = 0;
11999         for (vpp = vartab; vpp < vartab + VTABSIZE; vpp++) {
12000                 for (vp = *vpp; vp; vp = vp->next)
12001                         if (vp->flags & VEXPORT)
12002                                 nenv++;
12003         }
12004         ep = env = stalloc((nenv + 1) * sizeof *env);
12005         for (vpp = vartab; vpp < vartab + VTABSIZE; vpp++) {
12006                 for (vp = *vpp; vp; vp = vp->next)
12007                         if (vp->flags & VEXPORT)
12008                                 *ep++ = vp->text;
12009         }
12010         *ep = NULL;
12011         return env;
12012 }
12013
12014
12015 /*
12016  * Called when a shell procedure is invoked to clear out nonexported
12017  * variables.  It is also necessary to reallocate variables of with
12018  * VSTACK set since these are currently allocated on the stack.
12019  */
12020
12021 static void shprocvar(void)
12022 {
12023         struct var **vpp;
12024         struct var *vp, **prev;
12025
12026         for (vpp = vartab; vpp < vartab + VTABSIZE; vpp++) {
12027                 for (prev = vpp; (vp = *prev) != NULL;) {
12028                         if ((vp->flags & VEXPORT) == 0) {
12029                                 *prev = vp->next;
12030                                 if ((vp->flags & VTEXTFIXED) == 0)
12031                                         free(vp->text);
12032                                 if ((vp->flags & VSTRFIXED) == 0)
12033                                         free(vp);
12034                         } else {
12035                                 if (vp->flags & VSTACK) {
12036                                         vp->text = xstrdup(vp->text);
12037                                         vp->flags &= ~VSTACK;
12038                                 }
12039                                 prev = &vp->next;
12040                         }
12041                 }
12042         }
12043         initvar();
12044 }
12045
12046
12047
12048 /*
12049  * Command to list all variables which are set.  Currently this command
12050  * is invoked from the set command when the set command is called without
12051  * any variables.
12052  */
12053
12054 static int showvarscmd(int argc, char **argv)
12055 {
12056         showvars(nullstr, VUNSET, VUNSET);
12057         return 0;
12058 }
12059
12060
12061
12062 /*
12063  * The export and readonly commands.
12064  */
12065
12066 static int exportcmd(int argc, char **argv)
12067 {
12068         struct var *vp;
12069         char *name;
12070         const char *p;
12071         int flag = argv[0][0] == 'r' ? VREADONLY : VEXPORT;
12072         int pflag;
12073
12074         listsetvar(cmdenviron);
12075         pflag = (nextopt("p") == 'p');
12076         if (argc > 1 && !pflag) {
12077                 while ((name = *argptr++) != NULL) {
12078                         if ((p = strchr(name, '=')) != NULL) {
12079                                 p++;
12080                         } else {
12081                                 if ((vp = *findvar(hashvar(name), name))) {
12082                                         vp->flags |= flag;
12083                                         goto found;
12084                                 }
12085                         }
12086                         setvar(name, p, flag);
12087                   found:;
12088                 }
12089         } else {
12090                 showvars(argv[0], flag, 0);
12091         }
12092         return 0;
12093 }
12094
12095
12096 /*
12097  * The "local" command.
12098  */
12099
12100 /* funcnest nonzero if we are currently evaluating a function */
12101
12102 static int localcmd(int argc, char **argv)
12103 {
12104         char *name;
12105
12106         if (!funcnest)
12107                 error("Not in a function");
12108         while ((name = *argptr++) != NULL) {
12109                 mklocal(name);
12110         }
12111         return 0;
12112 }
12113
12114
12115 /*
12116  * Make a variable a local variable.  When a variable is made local, it's
12117  * value and flags are saved in a localvar structure.  The saved values
12118  * will be restored when the shell function returns.  We handle the name
12119  * "-" as a special case.
12120  */
12121
12122 static void mklocal(char *name)
12123 {
12124         struct localvar *lvp;
12125         struct var **vpp;
12126         struct var *vp;
12127
12128         INTOFF;
12129         lvp = xmalloc(sizeof(struct localvar));
12130         if (name[0] == '-' && name[1] == '\0') {
12131                 char *p;
12132
12133                 p = xmalloc(sizeof optet_vals);
12134                 lvp->text = memcpy(p, optet_vals, sizeof optet_vals);
12135                 vp = NULL;
12136         } else {
12137                 vpp = hashvar(name);
12138                 vp = *findvar(vpp, name);
12139                 if (vp == NULL) {
12140                         if (strchr(name, '='))
12141                                 setvareq(xstrdup(name), VSTRFIXED);
12142                         else
12143                                 setvar(name, NULL, VSTRFIXED);
12144                         vp = *vpp;      /* the new variable */
12145                         lvp->text = NULL;
12146                         lvp->flags = VUNSET;
12147                 } else {
12148                         lvp->text = vp->text;
12149                         lvp->flags = vp->flags;
12150                         vp->flags |= VSTRFIXED | VTEXTFIXED;
12151                         if (strchr(name, '='))
12152                                 setvareq(xstrdup(name), 0);
12153                 }
12154         }
12155         lvp->vp = vp;
12156         lvp->next = localvars;
12157         localvars = lvp;
12158         INTON;
12159 }
12160
12161
12162 /*
12163  * Called after a function returns.
12164  */
12165
12166 static void poplocalvars()
12167 {
12168         struct localvar *lvp;
12169         struct var *vp;
12170
12171         while ((lvp = localvars) != NULL) {
12172                 localvars = lvp->next;
12173                 vp = lvp->vp;
12174                 if (vp == NULL) {       /* $- saved */
12175                         memcpy(optet_vals, lvp->text, sizeof optet_vals);
12176                         free(lvp->text);
12177                 } else if ((lvp->flags & (VUNSET | VSTRFIXED)) == VUNSET) {
12178                         (void) unsetvar(vp->text);
12179                 } else {
12180                         if ((vp->flags & VTEXTFIXED) == 0)
12181                                 free(vp->text);
12182                         vp->flags = lvp->flags;
12183                         vp->text = lvp->text;
12184                 }
12185                 free(lvp);
12186         }
12187 }
12188
12189
12190 static int setvarcmd(int argc, char **argv)
12191 {
12192         if (argc <= 2)
12193                 return unsetcmd(argc, argv);
12194         else if (argc == 3)
12195                 setvar(argv[1], argv[2], 0);
12196         else
12197                 error("List assignment not implemented");
12198         return 0;
12199 }
12200
12201
12202 /*
12203  * The unset builtin command.  We unset the function before we unset the
12204  * variable to allow a function to be unset when there is a readonly variable
12205  * with the same name.
12206  */
12207
12208 static int unsetcmd(int argc, char **argv)
12209 {
12210         char **ap;
12211         int i;
12212         int flg_func = 0;
12213         int flg_var = 0;
12214         int ret = 0;
12215
12216         while ((i = nextopt("vf")) != '\0') {
12217                 if (i == 'f')
12218                         flg_func = 1;
12219                 else
12220                         flg_var = 1;
12221         }
12222         if (flg_func == 0 && flg_var == 0)
12223                 flg_var = 1;
12224
12225         for (ap = argptr; *ap; ap++) {
12226                 if (flg_func)
12227                         unsetfunc(*ap);
12228                 if (flg_var)
12229                         ret |= unsetvar(*ap);
12230         }
12231         return ret;
12232 }
12233
12234
12235 /*
12236  * Unset the specified variable.
12237  */
12238
12239 static int unsetvar(const char *s)
12240 {
12241         struct var **vpp;
12242         struct var *vp;
12243
12244         vpp = findvar(hashvar(s), s);
12245         vp = *vpp;
12246         if (vp) {
12247                 if (vp->flags & VREADONLY)
12248                         return (1);
12249                 INTOFF;
12250                 if (*(strchr(vp->text, '=') + 1) != '\0')
12251                         setvar(s, nullstr, 0);
12252                 vp->flags &= ~VEXPORT;
12253                 vp->flags |= VUNSET;
12254                 if ((vp->flags & VSTRFIXED) == 0) {
12255                         if ((vp->flags & VTEXTFIXED) == 0)
12256                                 free(vp->text);
12257                         *vpp = vp->next;
12258                         free(vp);
12259                 }
12260                 INTON;
12261                 return (0);
12262         }
12263
12264         return (0);
12265 }
12266
12267
12268
12269 /*
12270  * Find the appropriate entry in the hash table from the name.
12271  */
12272
12273 static struct var **hashvar(const char *p)
12274 {
12275         unsigned int hashval;
12276
12277         hashval = ((unsigned char) *p) << 4;
12278         while (*p && *p != '=')
12279                 hashval += (unsigned char) *p++;
12280         return &vartab[hashval % VTABSIZE];
12281 }
12282
12283
12284
12285 /*
12286  * Returns true if the two strings specify the same varable.  The first
12287  * variable name is terminated by '='; the second may be terminated by
12288  * either '=' or '\0'.
12289  */
12290
12291 static int varequal(const char *p, const char *q)
12292 {
12293         while (*p == *q++) {
12294                 if (*p++ == '=')
12295                         return 1;
12296         }
12297         if (*p == '=' && *(q - 1) == '\0')
12298                 return 1;
12299         return 0;
12300 }
12301
12302 static void showvars(const char *myprefix, int mask, int xor)
12303 {
12304         struct var **vpp;
12305         struct var *vp;
12306         const char *sep = myprefix == nullstr ? myprefix : spcstr;
12307
12308         for (vpp = vartab; vpp < vartab + VTABSIZE; vpp++) {
12309                 for (vp = *vpp; vp; vp = vp->next) {
12310                         if ((vp->flags & mask) ^ xor) {
12311                                 char *p;
12312                                 int len;
12313
12314                                 p = strchr(vp->text, '=') + 1;
12315                                 len = p - vp->text;
12316                                 p = single_quote(p);
12317
12318                                 printf("%s%s%.*s%s\n", myprefix, sep, len, vp->text, p);
12319                                 stunalloc(p);
12320                         }
12321                 }
12322         }
12323 }
12324
12325 static struct var **findvar(struct var **vpp, const char *name)
12326 {
12327         for (; *vpp; vpp = &(*vpp)->next) {
12328                 if (varequal((*vpp)->text, name)) {
12329                         break;
12330                 }
12331         }
12332         return vpp;
12333 }
12334
12335 /*
12336  * Copyright (c) 1999 Herbert Xu <herbert@debian.org>
12337  * This file contains code for the times builtin.
12338  * $Id: ash.c,v 1.57 2002/08/22 18:30:15 bug1 Exp $
12339  */
12340 static int timescmd(int argc, char **argv)
12341 {
12342         struct tms buf;
12343         long int clk_tck = sysconf(_SC_CLK_TCK);
12344
12345         times(&buf);
12346         printf("%dm%fs %dm%fs\n%dm%fs %dm%fs\n",
12347                    (int) (buf.tms_utime / clk_tck / 60),
12348                    ((double) buf.tms_utime) / clk_tck,
12349                    (int) (buf.tms_stime / clk_tck / 60),
12350                    ((double) buf.tms_stime) / clk_tck,
12351                    (int) (buf.tms_cutime / clk_tck / 60),
12352                    ((double) buf.tms_cutime) / clk_tck,
12353                    (int) (buf.tms_cstime / clk_tck / 60),
12354                    ((double) buf.tms_cstime) / clk_tck);
12355         return 0;
12356 }
12357
12358 #ifdef CONFIG_ASH_MATH_SUPPORT
12359 /* The let builtin.  */
12360 int letcmd(int argc, char **argv)
12361 {
12362         int errcode;
12363         long result = 0;
12364
12365         if (argc == 2) {
12366                 char *tmp, *expression, p[13];
12367
12368                 expression = strchr(argv[1], '=');
12369                 if (!expression) {
12370                         /* Cannot use 'error()' here, or the return code
12371                          * will be incorrect */
12372                         out2fmt("sh: let: syntax error: \"%s\"\n", argv[1]);
12373                         return 0;
12374                 }
12375                 *expression = '\0';
12376                 tmp = ++expression;
12377                 result = arith(tmp, &errcode);
12378                 if (errcode < 0) {
12379                         /* Cannot use 'error()' here, or the return code
12380                          * will be incorrect */
12381                         out2fmt("sh: let: ");
12382                         if (errcode == -2)
12383                                 out2fmt("divide by zero");
12384                         else
12385                                 out2fmt("syntax error: \"%s=%s\"\n", argv[1], expression);
12386                         return 0;
12387                 }
12388                 snprintf(p, 12, "%ld", result);
12389                 setvar(argv[1], xstrdup(p), 0);
12390         } else if (argc >= 3)
12391                 synerror("invalid operand");
12392         return !result;
12393 }
12394 #endif
12395
12396
12397
12398 /*-
12399  * Copyright (c) 1989, 1991, 1993, 1994
12400  *      The Regents of the University of California.  All rights reserved.
12401  *
12402  * This code is derived from software contributed to Berkeley by
12403  * Kenneth Almquist.
12404  *
12405  * Redistribution and use in source and binary forms, with or without
12406  * modification, are permitted provided that the following conditions
12407  * are met:
12408  * 1. Redistributions of source code must retain the above copyright
12409  *    notice, this list of conditions and the following disclaimer.
12410  * 2. Redistributions in binary form must reproduce the above copyright
12411  *    notice, this list of conditions and the following disclaimer in the
12412  *    documentation and/or other materials provided with the distribution.
12413  *
12414  * 3. <BSD Advertising Clause omitted per the July 22, 1999 licensing change
12415  *              ftp://ftp.cs.berkeley.edu/pub/4bsd/README.Impt.License.Change>
12416  *
12417  * 4. Neither the name of the University nor the names of its contributors
12418  *    may be used to endorse or promote products derived from this software
12419  *    without specific prior written permission.
12420  *
12421  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
12422  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
12423  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
12424  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
12425  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
12426  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
12427  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
12428  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
12429  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
12430  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
12431  * SUCH DAMAGE.
12432  */