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