Use %m, not strerror, and strerror(err) was broken anyways and should have been
[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 #if defined(__uClinux__)
89 #error "Do not even bother, ash will not run on uClinux"
90 #endif
91
92 /*
93  * This file was generated by the mksyntax program.
94  */
95
96 /* Syntax classes */
97 #define CWORD 0                 /* character is nothing special */
98 #define CNL 1                   /* newline character */
99 #define CBACK 2                 /* a backslash character */
100 #define CSQUOTE 3               /* single quote */
101 #define CDQUOTE 4               /* double quote */
102 #define CENDQUOTE 5             /* a terminating quote */
103 #define CBQUOTE 6               /* backwards single quote */
104 #define CVAR 7                  /* a dollar sign */
105 #define CENDVAR 8               /* a '}' character */
106 #define CLP 9                   /* a left paren in arithmetic */
107 #define CRP 10                  /* a right paren in arithmetic */
108 #define CENDFILE 11             /* end of file */
109 #define CCTL 12                 /* like CWORD, except it must be escaped */
110 #define CSPCL 13                /* these terminate a word */
111 #define CIGN 14                 /* character should be ignored */
112
113 #define SYNBASE 130
114 #define PEOF -130
115
116 #define PEOA -129
117
118 #define TEOF 0
119 #define TNL 1
120 #define TREDIR 2
121 #define TWORD 3
122 #define TASSIGN 4
123 #define TSEMI 5
124 #define TBACKGND 6
125 #define TAND 7
126 #define TOR 8
127 #define TPIPE 9
128 #define TLP 10
129 #define TRP 11
130 #define TENDCASE 12
131 #define TENDBQUOTE 13
132 #define TNOT 14
133 #define TCASE 15
134 #define TDO 16
135 #define TDONE 17
136 #define TELIF 18
137 #define TELSE 19
138 #define TESAC 20
139 #define TFI 21
140 #define TFOR 22
141 #define TIF 23
142 #define TIN 24
143 #define TTHEN 25
144 #define TUNTIL 26
145 #define TWHILE 27
146 #define TBEGIN 28
147 #define TEND 29
148
149
150
151 /* control characters in argument strings */
152 #define CTLESC '\201'
153 #define CTLVAR '\202'
154 #define CTLENDVAR '\203'
155 #define CTLBACKQ '\204'
156 #define CTLQUOTE 01             /* ored with CTLBACKQ code if in quotes */
157 /*      CTLBACKQ | CTLQUOTE == '\205' */
158 #define CTLARI  '\206'
159 #define CTLENDARI '\207'
160 #define CTLQUOTEMARK '\210'
161
162
163 #define is_digit(c)     ((c)>='0' && (c)<='9')
164 #define is_name(c)      (((c) < CTLESC || (c) > CTLENDARI) && ((c) == '_' || isalpha((unsigned char) (c))))
165 #define is_in_name(c)   (((c) < CTLESC || (c) > CTLENDARI) && ((c) == '_' || isalnum((unsigned char) (c))))
166
167 /*
168  * is_special(c) evaluates to 1 for c in "!#$*-0123456789?@"; 0 otherwise
169  * (assuming ascii char codes, as the original implementation did)
170  */
171 #define is_special(c) \
172     ( (((unsigned int)c) - 33 < 32) \
173                          && ((0xc1ff920dUL >> (((unsigned int)c) - 33)) & 1))
174
175 #define digit_val(c)    ((c) - '0')
176
177
178 #define S_DFL 1                 /* default signal handling (SIG_DFL) */
179 #define S_CATCH 2               /* signal is caught */
180 #define S_IGN 3                 /* signal is ignored (SIG_IGN) */
181 #define S_HARD_IGN 4    /* signal is ignored permenantly */
182 #define S_RESET 5               /* temporary - to reset a hard ignored sig */
183
184
185 /* variable substitution byte (follows CTLVAR) */
186 #define VSTYPE  0x0f    /* type of variable substitution */
187 #define VSNUL   0x10    /* colon--treat the empty string as unset */
188 #define VSQUOTE 0x80    /* inside double quotes--suppress splitting */
189
190 /* values of VSTYPE field */
191 #define VSNORMAL        0x1     /* normal variable:  $var or ${var} */
192 #define VSMINUS         0x2     /* ${var-text} */
193 #define VSPLUS          0x3     /* ${var+text} */
194 #define VSQUESTION      0x4     /* ${var?message} */
195 #define VSASSIGN        0x5     /* ${var=text} */
196 #define VSTRIMLEFT      0x6     /* ${var#pattern} */
197 #define VSTRIMLEFTMAX   0x7     /* ${var##pattern} */
198 #define VSTRIMRIGHT     0x8     /* ${var%pattern} */
199 #define VSTRIMRIGHTMAX  0x9     /* ${var%%pattern} */
200 #define VSLENGTH        0xa     /* ${#var} */
201
202 /* flags passed to redirect */
203 #define REDIR_PUSH 01   /* save previous values of file descriptors */
204 #define REDIR_BACKQ 02  /* save the command output to pipe */
205
206 /*
207  * BSD setjmp saves the signal mask, which violates ANSI C and takes time,
208  * so we use _setjmp instead.
209  */
210
211 #if defined(BSD)
212 #define setjmp(jmploc)  _setjmp(jmploc)
213 #define longjmp(jmploc, val)    _longjmp(jmploc, val)
214 #endif
215
216 /*
217  * Most machines require the value returned from malloc to be aligned
218  * in some way.  The following macro will get this right on many machines.
219  */
220
221 #ifndef ALIGN
222 union align {
223         int i;
224         char *cp;
225 };
226
227 #define ALIGN(nbytes)   (((nbytes) + sizeof(union align) - 1) & ~(sizeof(union align) - 1))
228 #endif
229
230 #ifdef CONFIG_LOCALE_SUPPORT
231 #include <locale.h>
232 static void change_lc_all(const char *value);
233 static void change_lc_ctype(const char *value);
234 #endif
235
236 /*
237  * These macros allow the user to suspend the handling of interrupt signals
238  * over a period of time.  This is similar to SIGHOLD to or sigblock, but
239  * much more efficient and portable.  (But hacking the kernel is so much
240  * more fun than worrying about efficiency and portability. :-))
241  */
242
243 static void onint(void);
244 static volatile int suppressint;
245 static volatile int intpending;
246
247 #define INTOFF suppressint++
248 #ifndef CONFIG_ASH_OPTIMIZE_FOR_SIZE
249 #define INTON { if (--suppressint == 0 && intpending) onint(); }
250 #define FORCEINTON {suppressint = 0; if (intpending) onint();}
251 #else
252 static void __inton(void);
253 static void forceinton(void);
254
255 #define INTON __inton()
256 #define FORCEINTON forceinton()
257 #endif
258
259 #define CLEAR_PENDING_INT intpending = 0
260 #define int_pending() intpending
261
262
263 typedef void *pointer;
264
265 #ifndef NULL
266 #define NULL (void *)0
267 #endif
268
269 static pointer stalloc(int);
270 static void stunalloc(pointer);
271 static void ungrabstackstr(char *, char *);
272 static char *growstackstr(void);
273 static char *makestrspace(size_t newlen);
274
275 /*
276  * Parse trees for commands are allocated in lifo order, so we use a stack
277  * to make this more efficient, and also to avoid all sorts of exception
278  * handling code to handle interrupts in the middle of a parse.
279  *
280  * The size 504 was chosen because the Ultrix malloc handles that size
281  * well.
282  */
283
284 #define MINSIZE 504             /* minimum size of a block */
285
286
287 struct stack_block {
288         struct stack_block *prev;
289         char space[MINSIZE];
290 };
291
292 static struct stack_block stackbase;
293 static struct stack_block *stackp = &stackbase;
294 static struct stackmark *markp;
295 static char *stacknxt = stackbase.space;
296 static int stacknleft = MINSIZE;
297
298
299 #define equal(s1, s2)   (strcmp(s1, s2) == 0)
300
301 #define stackblock() stacknxt
302 #define stackblocksize() stacknleft
303 #define STARTSTACKSTR(p)        p = stackblock(), sstrnleft = stackblocksize()
304
305 #define STPUTC(c, p)    (--sstrnleft >= 0? (*p++ = (c)) : (p = growstackstr(), *p++ = (c)))
306 #define CHECKSTRSPACE(n, p)     { if (sstrnleft < n) p = makestrspace(n); }
307 #define STACKSTRNUL(p)  (sstrnleft == 0? (p = growstackstr(), *p = '\0') : (*p = '\0'))
308
309
310 #define USTPUTC(c, p)   (--sstrnleft, *p++ = (c))
311 #define STUNPUTC(p)     (++sstrnleft, --p)
312 #define STTOPC(p)       p[-1]
313 #define STADJUST(amount, p)     (p += (amount), sstrnleft -= (amount))
314 #define grabstackstr(p) stalloc(stackblocksize() - sstrnleft)
315
316
317 #ifdef DEBUG
318 #define TRACE(param)    trace param
319 typedef union node unode;
320 static void trace(const char *, ...);
321 static void trargs(char **);
322 static void showtree(unode *);
323 static void trputc(int);
324 static void trputs(const char *);
325 static void opentrace(void);
326 #else
327 #define TRACE(param)
328 #endif
329
330 #define NSEMI 0
331 #define NCMD 1
332 #define NPIPE 2
333 #define NREDIR 3
334 #define NBACKGND 4
335 #define NSUBSHELL 5
336 #define NAND 6
337 #define NOR 7
338 #define NIF 8
339 #define NWHILE 9
340 #define NUNTIL 10
341 #define NFOR 11
342 #define NCASE 12
343 #define NCLIST 13
344 #define NDEFUN 14
345 #define NARG 15
346 #define NTO 16
347 #define NFROM 17
348 #define NFROMTO 18
349 #define NAPPEND 19
350 #define NTOOV 20
351 #define NTOFD 21
352 #define NFROMFD 22
353 #define NHERE 23
354 #define NXHERE 24
355 #define NNOT 25
356
357 /*
358  * expandarg() flags
359  */
360 #define EXP_FULL        0x1     /* perform word splitting & file globbing */
361 #define EXP_TILDE       0x2     /* do normal tilde expansion */
362 #define EXP_VARTILDE    0x4     /* expand tildes in an assignment */
363 #define EXP_REDIR       0x8     /* file glob for a redirection (1 match only) */
364 #define EXP_CASE        0x10    /* keeps quotes around for CASE pattern */
365 #define EXP_RECORD      0x20    /* need to record arguments for ifs breakup */
366
367
368 #define NOPTS   16
369
370 static char optet_vals[NOPTS];
371
372 static const char *const optlist[NOPTS] = {
373         "e" "errexit",
374         "f" "noglob",
375         "I" "ignoreeof",
376         "i" "interactive",
377         "m" "monitor",
378         "n" "noexec",
379         "s" "stdin",
380         "x" "xtrace",
381         "v" "verbose",
382         "V" "vi",
383         "E" "emacs",
384         "C" "noclobber",
385         "a" "allexport",
386         "b" "notify",
387         "u" "nounset",
388         "q" "quietprofile"
389 };
390
391 #define optent_name(optent) (optent+1)
392 #define optent_letter(optent) optent[0]
393 #define optent_val(optent) optet_vals[optent]
394
395 #define eflag optent_val(0)
396 #define fflag optent_val(1)
397 #define Iflag optent_val(2)
398 #define iflag optent_val(3)
399 #define mflag optent_val(4)
400 #define nflag optent_val(5)
401 #define sflag optent_val(6)
402 #define xflag optent_val(7)
403 #define vflag optent_val(8)
404 #define Vflag optent_val(9)
405 #define Eflag optent_val(10)
406 #define Cflag optent_val(11)
407 #define aflag optent_val(12)
408 #define bflag optent_val(13)
409 #define uflag optent_val(14)
410 #define qflag optent_val(15)
411
412
413 /* Mode argument to forkshell.  Don't change FORK_FG or FORK_BG. */
414 #define FORK_FG 0
415 #define FORK_BG 1
416 #define FORK_NOJOB 2
417
418
419 struct nbinary {
420         int type;
421         union node *ch1;
422         union node *ch2;
423 };
424
425
426 struct ncmd {
427         int type;
428         int backgnd;
429         union node *assign;
430         union node *args;
431         union node *redirect;
432 };
433
434
435 struct npipe {
436         int type;
437         int backgnd;
438         struct nodelist *cmdlist;
439 };
440
441
442 struct nredir {
443         int type;
444         union node *n;
445         union node *redirect;
446 };
447
448
449 struct nif {
450         int type;
451         union node *test;
452         union node *ifpart;
453         union node *elsepart;
454 };
455
456
457 struct nfor {
458         int type;
459         union node *args;
460         union node *body;
461         char *var;
462 };
463
464
465 struct ncase {
466         int type;
467         union node *expr;
468         union node *cases;
469 };
470
471
472 struct nclist {
473         int type;
474         union node *next;
475         union node *pattern;
476         union node *body;
477 };
478
479
480 struct narg {
481         int type;
482         union node *next;
483         char *text;
484         struct nodelist *backquote;
485 };
486
487
488 struct nfile {
489         int type;
490         union node *next;
491         int fd;
492         union node *fname;
493         char *expfname;
494 };
495
496
497 struct ndup {
498         int type;
499         union node *next;
500         int fd;
501         int dupfd;
502         union node *vname;
503 };
504
505
506 struct nhere {
507         int type;
508         union node *next;
509         int fd;
510         union node *doc;
511 };
512
513
514 struct nnot {
515         int type;
516         union node *com;
517 };
518
519
520 union node {
521         int type;
522         struct nbinary nbinary;
523         struct ncmd ncmd;
524         struct npipe npipe;
525         struct nredir nredir;
526         struct nif nif;
527         struct nfor nfor;
528         struct ncase ncase;
529         struct nclist nclist;
530         struct narg narg;
531         struct nfile nfile;
532         struct ndup ndup;
533         struct nhere nhere;
534         struct nnot nnot;
535 };
536
537
538 struct nodelist {
539         struct nodelist *next;
540         union node *n;
541 };
542
543 struct backcmd {                /* result of evalbackcmd */
544         int fd;                         /* file descriptor to read from */
545         char *buf;                      /* buffer */
546         int nleft;                      /* number of chars in buffer */
547         struct job *jp;         /* job structure for command */
548 };
549
550 struct cmdentry {
551         int cmdtype;
552         union param {
553                 int index;
554                 union node *func;
555                 const struct builtincmd *cmd;
556         } u;
557 };
558
559 struct strlist {
560         struct strlist *next;
561         char *text;
562 };
563
564
565 struct arglist {
566         struct strlist *list;
567         struct strlist **lastp;
568 };
569
570 struct strpush {
571         struct strpush *prev;   /* preceding string on stack */
572         char *prevstring;
573         int prevnleft;
574 #ifdef CONFIG_ASH_ALIAS
575         struct alias *ap;       /* if push was associated with an alias */
576 #endif
577         char *string;           /* remember the string since it may change */
578 };
579
580 struct parsefile {
581         struct parsefile *prev; /* preceding file on stack */
582         int linno;                      /* current line */
583         int fd;                         /* file descriptor (or -1 if string) */
584         int nleft;                      /* number of chars left in this line */
585         int lleft;                      /* number of chars left in this buffer */
586         char *nextc;            /* next char in buffer */
587         char *buf;                      /* input buffer */
588         struct strpush *strpush;        /* for pushing strings at this level */
589         struct strpush basestrpush;     /* so pushing one is fast */
590 };
591
592 struct stackmark {
593         struct stack_block *stackp;
594         char *stacknxt;
595         int stacknleft;
596         struct stackmark *marknext;
597 };
598
599 struct shparam {
600         int nparam;                     /* # of positional parameters (without $0) */
601         unsigned char malloc;   /* if parameter list dynamically allocated */
602         char **p;                       /* parameter list */
603         int optind;                     /* next parameter to be processed by getopts */
604         int optoff;                     /* used by getopts */
605 };
606
607 /*
608  * When commands are first encountered, they are entered in a hash table.
609  * This ensures that a full path search will not have to be done for them
610  * on each invocation.
611  *
612  * We should investigate converting to a linear search, even though that
613  * would make the command name "hash" a misnomer.
614  */
615 #define CMDTABLESIZE 31 /* should be prime */
616 #define ARB 1                   /* actual size determined at run time */
617
618
619
620 struct tblentry {
621         struct tblentry *next;  /* next entry in hash chain */
622         union param param;      /* definition of builtin function */
623         short cmdtype;          /* index identifying command */
624         char rehash;            /* if set, cd done since entry created */
625         char cmdname[ARB];      /* name of command */
626 };
627
628
629 static struct tblentry *cmdtable[CMDTABLESIZE];
630 static int builtinloc = -1;     /* index in path of %builtin, or -1 */
631 static int exerrno = 0; /* Last exec error */
632
633
634 static void tryexec(char *, char **, char **);
635 static void printentry(struct tblentry *, int);
636 static void clearcmdentry(int);
637 static struct tblentry *cmdlookup(const char *, int);
638 static void delete_cmd_entry(void);
639 static int path_change(const char *, int *);
640
641
642 static void flushall(void);
643 static void out2fmt(const char *, ...)
644         __attribute__ ((__format__(__printf__, 1, 2)));
645 static int xwrite(int, const char *, int);
646
647 static inline void outstr(const char *p, FILE * file)
648 {
649         fputs(p, file);
650 }
651 static void out1str(const char *p)
652 {
653         outstr(p, stdout);
654 }
655 static void out2str(const char *p)
656 {
657         outstr(p, stderr);
658 }
659
660 #ifndef CONFIG_ASH_OPTIMIZE_FOR_SIZE
661 #define out2c(c)        putc((c), stderr)
662 #else
663 static void out2c(int c)
664 {
665         putc(c, stderr);
666 }
667 #endif
668
669
670 #ifdef CONFIG_ASH_OPTIMIZE_FOR_SIZE
671 #define USE_SIT_FUNCTION
672 #endif
673
674 /* number syntax index */
675 #define  BASESYNTAX  0  /* not in quotes */
676 #define  DQSYNTAX    1  /* in double quotes */
677 #define  SQSYNTAX    2  /* in single quotes */
678 #define  ARISYNTAX   3  /* in arithmetic */
679
680 static const char S_I_T[][4] = {
681         {CSPCL, CIGN, CIGN, CIGN},      /* 0, PEOA */
682         {CSPCL, CWORD, CWORD, CWORD},   /* 1, ' ' */
683         {CNL, CNL, CNL, CNL},   /* 2, \n */
684         {CWORD, CCTL, CCTL, CWORD},     /* 3, !*-/:=?[]~ */
685         {CDQUOTE, CENDQUOTE, CWORD, CDQUOTE},   /* 4, '"' */
686         {CVAR, CVAR, CWORD, CVAR},      /* 5, $ */
687         {CSQUOTE, CWORD, CENDQUOTE, CSQUOTE},   /* 6, "'" */
688         {CSPCL, CWORD, CWORD, CLP},     /* 7, ( */
689         {CSPCL, CWORD, CWORD, CRP},     /* 8, ) */
690         {CBACK, CBACK, CCTL, CBACK},    /* 9, \ */
691         {CBQUOTE, CBQUOTE, CWORD, CBQUOTE},     /* 10, ` */
692         {CENDVAR, CENDVAR, CWORD, CENDVAR},     /* 11, } */
693 #ifndef USE_SIT_FUNCTION
694         {CENDFILE, CENDFILE, CENDFILE, CENDFILE},       /* 12, PEOF */
695         {CWORD, CWORD, CWORD, CWORD},   /* 13, 0-9A-Za-z */
696         {CCTL, CCTL, CCTL, CCTL}        /* 14, CTLESC ... */
697 #endif
698 };
699
700 #ifdef USE_SIT_FUNCTION
701
702 #define U_C(c) ((unsigned char)(c))
703
704 static int SIT(int c, int syntax)
705 {
706         static const char spec_symbls[] = "\t\n !\"$&'()*-/:;<=>?[\\]`|}~";
707         static const char syntax_index_table[] = {
708                 1, 2, 1, 3, 4, 5, 1, 6, /* "\t\n !\"$&'" */
709                 7, 8, 3, 3, 3, 3, 1, 1, /* "()*-/:;<" */
710                 3, 1, 3, 3, 9, 3, 10, 1,        /* "=>?[\\]`|" */
711                 11, 3
712         };                                      /* "}~" */
713         const char *s;
714         int indx;
715
716         if (c == PEOF)          /* 2^8+2 */
717                 return CENDFILE;
718         if (c == PEOA)          /* 2^8+1 */
719                 indx = 0;
720         else if (U_C(c) >= U_C(CTLESC) && U_C(c) <= U_C(CTLQUOTEMARK))
721                 return CCTL;
722         else {
723                 s = strchr(spec_symbls, c);
724                 if (s == 0)
725                         return CWORD;
726                 indx = syntax_index_table[(s - spec_symbls)];
727         }
728         return S_I_T[indx][syntax];
729 }
730
731 #else                                                   /* USE_SIT_FUNCTION */
732
733 #define SIT(c, syntax) S_I_T[(int)syntax_index_table[((int)c)+SYNBASE]][syntax]
734
735 #define CSPCL_CIGN_CIGN_CIGN                           0
736 #define CSPCL_CWORD_CWORD_CWORD                        1
737 #define CNL_CNL_CNL_CNL                                2
738 #define CWORD_CCTL_CCTL_CWORD                          3
739 #define CDQUOTE_CENDQUOTE_CWORD_CDQUOTE                4
740 #define CVAR_CVAR_CWORD_CVAR                           5
741 #define CSQUOTE_CWORD_CENDQUOTE_CSQUOTE                6
742 #define CSPCL_CWORD_CWORD_CLP                          7
743 #define CSPCL_CWORD_CWORD_CRP                          8
744 #define CBACK_CBACK_CCTL_CBACK                         9
745 #define CBQUOTE_CBQUOTE_CWORD_CBQUOTE                 10
746 #define CENDVAR_CENDVAR_CWORD_CENDVAR                 11
747 #define CENDFILE_CENDFILE_CENDFILE_CENDFILE           12
748 #define CWORD_CWORD_CWORD_CWORD                       13
749 #define CCTL_CCTL_CCTL_CCTL                           14
750
751 static const char syntax_index_table[258] = {
752         /* BASESYNTAX_DQSYNTAX_SQSYNTAX_ARISYNTAX */
753         /*   0  -130 PEOF */ CENDFILE_CENDFILE_CENDFILE_CENDFILE,
754         /*   1  -129 PEOA */ CSPCL_CIGN_CIGN_CIGN,
755         /*   2  -128 0xff */ CWORD_CWORD_CWORD_CWORD,
756         /*   3  -127      */ CCTL_CCTL_CCTL_CCTL,
757         /* CTLQUOTEMARK */
758         /*   4  -126      */ CCTL_CCTL_CCTL_CCTL,
759         /*   5  -125      */ CCTL_CCTL_CCTL_CCTL,
760         /*   6  -124      */ CCTL_CCTL_CCTL_CCTL,
761         /*   7  -123      */ CCTL_CCTL_CCTL_CCTL,
762         /*   8  -122      */ CCTL_CCTL_CCTL_CCTL,
763         /*   9  -121      */ CCTL_CCTL_CCTL_CCTL,
764         /*  10  -120      */ CCTL_CCTL_CCTL_CCTL,
765         /* CTLESC */
766         /*  11  -119      */ CWORD_CWORD_CWORD_CWORD,
767         /*  12  -118      */ CWORD_CWORD_CWORD_CWORD,
768         /*  13  -117      */ CWORD_CWORD_CWORD_CWORD,
769         /*  14  -116      */ CWORD_CWORD_CWORD_CWORD,
770         /*  15  -115      */ CWORD_CWORD_CWORD_CWORD,
771         /*  16  -114      */ CWORD_CWORD_CWORD_CWORD,
772         /*  17  -113      */ CWORD_CWORD_CWORD_CWORD,
773         /*  18  -112      */ CWORD_CWORD_CWORD_CWORD,
774         /*  19  -111      */ CWORD_CWORD_CWORD_CWORD,
775         /*  20  -110      */ CWORD_CWORD_CWORD_CWORD,
776         /*  21  -109      */ CWORD_CWORD_CWORD_CWORD,
777         /*  22  -108      */ CWORD_CWORD_CWORD_CWORD,
778         /*  23  -107      */ CWORD_CWORD_CWORD_CWORD,
779         /*  24  -106      */ CWORD_CWORD_CWORD_CWORD,
780         /*  25  -105      */ CWORD_CWORD_CWORD_CWORD,
781         /*  26  -104      */ CWORD_CWORD_CWORD_CWORD,
782         /*  27  -103      */ CWORD_CWORD_CWORD_CWORD,
783         /*  28  -102      */ CWORD_CWORD_CWORD_CWORD,
784         /*  29  -101      */ CWORD_CWORD_CWORD_CWORD,
785         /*  30  -100      */ CWORD_CWORD_CWORD_CWORD,
786         /*  31   -99      */ CWORD_CWORD_CWORD_CWORD,
787         /*  32   -98      */ CWORD_CWORD_CWORD_CWORD,
788         /*  33   -97      */ CWORD_CWORD_CWORD_CWORD,
789         /*  34   -96      */ CWORD_CWORD_CWORD_CWORD,
790         /*  35   -95      */ CWORD_CWORD_CWORD_CWORD,
791         /*  36   -94      */ CWORD_CWORD_CWORD_CWORD,
792         /*  37   -93      */ CWORD_CWORD_CWORD_CWORD,
793         /*  38   -92      */ CWORD_CWORD_CWORD_CWORD,
794         /*  39   -91      */ CWORD_CWORD_CWORD_CWORD,
795         /*  40   -90      */ CWORD_CWORD_CWORD_CWORD,
796         /*  41   -89      */ CWORD_CWORD_CWORD_CWORD,
797         /*  42   -88      */ CWORD_CWORD_CWORD_CWORD,
798         /*  43   -87      */ CWORD_CWORD_CWORD_CWORD,
799         /*  44   -86      */ CWORD_CWORD_CWORD_CWORD,
800         /*  45   -85      */ CWORD_CWORD_CWORD_CWORD,
801         /*  46   -84      */ CWORD_CWORD_CWORD_CWORD,
802         /*  47   -83      */ CWORD_CWORD_CWORD_CWORD,
803         /*  48   -82      */ CWORD_CWORD_CWORD_CWORD,
804         /*  49   -81      */ CWORD_CWORD_CWORD_CWORD,
805         /*  50   -80      */ CWORD_CWORD_CWORD_CWORD,
806         /*  51   -79      */ CWORD_CWORD_CWORD_CWORD,
807         /*  52   -78      */ CWORD_CWORD_CWORD_CWORD,
808         /*  53   -77      */ CWORD_CWORD_CWORD_CWORD,
809         /*  54   -76      */ CWORD_CWORD_CWORD_CWORD,
810         /*  55   -75      */ CWORD_CWORD_CWORD_CWORD,
811         /*  56   -74      */ CWORD_CWORD_CWORD_CWORD,
812         /*  57   -73      */ CWORD_CWORD_CWORD_CWORD,
813         /*  58   -72      */ CWORD_CWORD_CWORD_CWORD,
814         /*  59   -71      */ CWORD_CWORD_CWORD_CWORD,
815         /*  60   -70      */ CWORD_CWORD_CWORD_CWORD,
816         /*  61   -69      */ CWORD_CWORD_CWORD_CWORD,
817         /*  62   -68      */ CWORD_CWORD_CWORD_CWORD,
818         /*  63   -67      */ CWORD_CWORD_CWORD_CWORD,
819         /*  64   -66      */ CWORD_CWORD_CWORD_CWORD,
820         /*  65   -65      */ CWORD_CWORD_CWORD_CWORD,
821         /*  66   -64      */ CWORD_CWORD_CWORD_CWORD,
822         /*  67   -63      */ CWORD_CWORD_CWORD_CWORD,
823         /*  68   -62      */ CWORD_CWORD_CWORD_CWORD,
824         /*  69   -61      */ CWORD_CWORD_CWORD_CWORD,
825         /*  70   -60      */ CWORD_CWORD_CWORD_CWORD,
826         /*  71   -59      */ CWORD_CWORD_CWORD_CWORD,
827         /*  72   -58      */ CWORD_CWORD_CWORD_CWORD,
828         /*  73   -57      */ CWORD_CWORD_CWORD_CWORD,
829         /*  74   -56      */ CWORD_CWORD_CWORD_CWORD,
830         /*  75   -55      */ CWORD_CWORD_CWORD_CWORD,
831         /*  76   -54      */ CWORD_CWORD_CWORD_CWORD,
832         /*  77   -53      */ CWORD_CWORD_CWORD_CWORD,
833         /*  78   -52      */ CWORD_CWORD_CWORD_CWORD,
834         /*  79   -51      */ CWORD_CWORD_CWORD_CWORD,
835         /*  80   -50      */ CWORD_CWORD_CWORD_CWORD,
836         /*  81   -49      */ CWORD_CWORD_CWORD_CWORD,
837         /*  82   -48      */ CWORD_CWORD_CWORD_CWORD,
838         /*  83   -47      */ CWORD_CWORD_CWORD_CWORD,
839         /*  84   -46      */ CWORD_CWORD_CWORD_CWORD,
840         /*  85   -45      */ CWORD_CWORD_CWORD_CWORD,
841         /*  86   -44      */ CWORD_CWORD_CWORD_CWORD,
842         /*  87   -43      */ CWORD_CWORD_CWORD_CWORD,
843         /*  88   -42      */ CWORD_CWORD_CWORD_CWORD,
844         /*  89   -41      */ CWORD_CWORD_CWORD_CWORD,
845         /*  90   -40      */ CWORD_CWORD_CWORD_CWORD,
846         /*  91   -39      */ CWORD_CWORD_CWORD_CWORD,
847         /*  92   -38      */ CWORD_CWORD_CWORD_CWORD,
848         /*  93   -37      */ CWORD_CWORD_CWORD_CWORD,
849         /*  94   -36      */ CWORD_CWORD_CWORD_CWORD,
850         /*  95   -35      */ CWORD_CWORD_CWORD_CWORD,
851         /*  96   -34      */ CWORD_CWORD_CWORD_CWORD,
852         /*  97   -33      */ CWORD_CWORD_CWORD_CWORD,
853         /*  98   -32      */ CWORD_CWORD_CWORD_CWORD,
854         /*  99   -31      */ CWORD_CWORD_CWORD_CWORD,
855         /* 100   -30      */ CWORD_CWORD_CWORD_CWORD,
856         /* 101   -29      */ CWORD_CWORD_CWORD_CWORD,
857         /* 102   -28      */ CWORD_CWORD_CWORD_CWORD,
858         /* 103   -27      */ CWORD_CWORD_CWORD_CWORD,
859         /* 104   -26      */ CWORD_CWORD_CWORD_CWORD,
860         /* 105   -25      */ CWORD_CWORD_CWORD_CWORD,
861         /* 106   -24      */ CWORD_CWORD_CWORD_CWORD,
862         /* 107   -23      */ CWORD_CWORD_CWORD_CWORD,
863         /* 108   -22      */ CWORD_CWORD_CWORD_CWORD,
864         /* 109   -21      */ CWORD_CWORD_CWORD_CWORD,
865         /* 110   -20      */ CWORD_CWORD_CWORD_CWORD,
866         /* 111   -19      */ CWORD_CWORD_CWORD_CWORD,
867         /* 112   -18      */ CWORD_CWORD_CWORD_CWORD,
868         /* 113   -17      */ CWORD_CWORD_CWORD_CWORD,
869         /* 114   -16      */ CWORD_CWORD_CWORD_CWORD,
870         /* 115   -15      */ CWORD_CWORD_CWORD_CWORD,
871         /* 116   -14      */ CWORD_CWORD_CWORD_CWORD,
872         /* 117   -13      */ CWORD_CWORD_CWORD_CWORD,
873         /* 118   -12      */ CWORD_CWORD_CWORD_CWORD,
874         /* 119   -11      */ CWORD_CWORD_CWORD_CWORD,
875         /* 120   -10      */ CWORD_CWORD_CWORD_CWORD,
876         /* 121    -9      */ CWORD_CWORD_CWORD_CWORD,
877         /* 122    -8      */ CWORD_CWORD_CWORD_CWORD,
878         /* 123    -7      */ CWORD_CWORD_CWORD_CWORD,
879         /* 124    -6      */ CWORD_CWORD_CWORD_CWORD,
880         /* 125    -5      */ CWORD_CWORD_CWORD_CWORD,
881         /* 126    -4      */ CWORD_CWORD_CWORD_CWORD,
882         /* 127    -3      */ CWORD_CWORD_CWORD_CWORD,
883         /* 128    -2      */ CWORD_CWORD_CWORD_CWORD,
884         /* 129    -1      */ CWORD_CWORD_CWORD_CWORD,
885         /* 130     0      */ CWORD_CWORD_CWORD_CWORD,
886         /* 131     1      */ CWORD_CWORD_CWORD_CWORD,
887         /* 132     2      */ CWORD_CWORD_CWORD_CWORD,
888         /* 133     3      */ CWORD_CWORD_CWORD_CWORD,
889         /* 134     4      */ CWORD_CWORD_CWORD_CWORD,
890         /* 135     5      */ CWORD_CWORD_CWORD_CWORD,
891         /* 136     6      */ CWORD_CWORD_CWORD_CWORD,
892         /* 137     7      */ CWORD_CWORD_CWORD_CWORD,
893         /* 138     8      */ CWORD_CWORD_CWORD_CWORD,
894         /* 139     9 "\t" */ CSPCL_CWORD_CWORD_CWORD,
895         /* 140    10 "\n" */ CNL_CNL_CNL_CNL,
896         /* 141    11      */ CWORD_CWORD_CWORD_CWORD,
897         /* 142    12      */ CWORD_CWORD_CWORD_CWORD,
898         /* 143    13      */ CWORD_CWORD_CWORD_CWORD,
899         /* 144    14      */ CWORD_CWORD_CWORD_CWORD,
900         /* 145    15      */ CWORD_CWORD_CWORD_CWORD,
901         /* 146    16      */ CWORD_CWORD_CWORD_CWORD,
902         /* 147    17      */ CWORD_CWORD_CWORD_CWORD,
903         /* 148    18      */ CWORD_CWORD_CWORD_CWORD,
904         /* 149    19      */ CWORD_CWORD_CWORD_CWORD,
905         /* 150    20      */ CWORD_CWORD_CWORD_CWORD,
906         /* 151    21      */ CWORD_CWORD_CWORD_CWORD,
907         /* 152    22      */ CWORD_CWORD_CWORD_CWORD,
908         /* 153    23      */ CWORD_CWORD_CWORD_CWORD,
909         /* 154    24      */ CWORD_CWORD_CWORD_CWORD,
910         /* 155    25      */ CWORD_CWORD_CWORD_CWORD,
911         /* 156    26      */ CWORD_CWORD_CWORD_CWORD,
912         /* 157    27      */ CWORD_CWORD_CWORD_CWORD,
913         /* 158    28      */ CWORD_CWORD_CWORD_CWORD,
914         /* 159    29      */ CWORD_CWORD_CWORD_CWORD,
915         /* 160    30      */ CWORD_CWORD_CWORD_CWORD,
916         /* 161    31      */ CWORD_CWORD_CWORD_CWORD,
917         /* 162    32  " " */ CSPCL_CWORD_CWORD_CWORD,
918         /* 163    33  "!" */ CWORD_CCTL_CCTL_CWORD,
919         /* 164    34  """ */ CDQUOTE_CENDQUOTE_CWORD_CDQUOTE,
920         /* 165    35  "#" */ CWORD_CWORD_CWORD_CWORD,
921         /* 166    36  "$" */ CVAR_CVAR_CWORD_CVAR,
922         /* 167    37  "%" */ CWORD_CWORD_CWORD_CWORD,
923         /* 168    38  "&" */ CSPCL_CWORD_CWORD_CWORD,
924         /* 169    39  "'" */ CSQUOTE_CWORD_CENDQUOTE_CSQUOTE,
925         /* 170    40  "(" */ CSPCL_CWORD_CWORD_CLP,
926         /* 171    41  ")" */ CSPCL_CWORD_CWORD_CRP,
927         /* 172    42  "*" */ CWORD_CCTL_CCTL_CWORD,
928         /* 173    43  "+" */ CWORD_CWORD_CWORD_CWORD,
929         /* 174    44  "," */ CWORD_CWORD_CWORD_CWORD,
930         /* 175    45  "-" */ CWORD_CCTL_CCTL_CWORD,
931         /* 176    46  "." */ CWORD_CWORD_CWORD_CWORD,
932         /* 177    47  "/" */ CWORD_CCTL_CCTL_CWORD,
933         /* 178    48  "0" */ CWORD_CWORD_CWORD_CWORD,
934         /* 179    49  "1" */ CWORD_CWORD_CWORD_CWORD,
935         /* 180    50  "2" */ CWORD_CWORD_CWORD_CWORD,
936         /* 181    51  "3" */ CWORD_CWORD_CWORD_CWORD,
937         /* 182    52  "4" */ CWORD_CWORD_CWORD_CWORD,
938         /* 183    53  "5" */ CWORD_CWORD_CWORD_CWORD,
939         /* 184    54  "6" */ CWORD_CWORD_CWORD_CWORD,
940         /* 185    55  "7" */ CWORD_CWORD_CWORD_CWORD,
941         /* 186    56  "8" */ CWORD_CWORD_CWORD_CWORD,
942         /* 187    57  "9" */ CWORD_CWORD_CWORD_CWORD,
943         /* 188    58  ":" */ CWORD_CCTL_CCTL_CWORD,
944         /* 189    59  ";" */ CSPCL_CWORD_CWORD_CWORD,
945         /* 190    60  "<" */ CSPCL_CWORD_CWORD_CWORD,
946         /* 191    61  "=" */ CWORD_CCTL_CCTL_CWORD,
947         /* 192    62  ">" */ CSPCL_CWORD_CWORD_CWORD,
948         /* 193    63  "?" */ CWORD_CCTL_CCTL_CWORD,
949         /* 194    64  "@" */ CWORD_CWORD_CWORD_CWORD,
950         /* 195    65  "A" */ CWORD_CWORD_CWORD_CWORD,
951         /* 196    66  "B" */ CWORD_CWORD_CWORD_CWORD,
952         /* 197    67  "C" */ CWORD_CWORD_CWORD_CWORD,
953         /* 198    68  "D" */ CWORD_CWORD_CWORD_CWORD,
954         /* 199    69  "E" */ CWORD_CWORD_CWORD_CWORD,
955         /* 200    70  "F" */ CWORD_CWORD_CWORD_CWORD,
956         /* 201    71  "G" */ CWORD_CWORD_CWORD_CWORD,
957         /* 202    72  "H" */ CWORD_CWORD_CWORD_CWORD,
958         /* 203    73  "I" */ CWORD_CWORD_CWORD_CWORD,
959         /* 204    74  "J" */ CWORD_CWORD_CWORD_CWORD,
960         /* 205    75  "K" */ CWORD_CWORD_CWORD_CWORD,
961         /* 206    76  "L" */ CWORD_CWORD_CWORD_CWORD,
962         /* 207    77  "M" */ CWORD_CWORD_CWORD_CWORD,
963         /* 208    78  "N" */ CWORD_CWORD_CWORD_CWORD,
964         /* 209    79  "O" */ CWORD_CWORD_CWORD_CWORD,
965         /* 210    80  "P" */ CWORD_CWORD_CWORD_CWORD,
966         /* 211    81  "Q" */ CWORD_CWORD_CWORD_CWORD,
967         /* 212    82  "R" */ CWORD_CWORD_CWORD_CWORD,
968         /* 213    83  "S" */ CWORD_CWORD_CWORD_CWORD,
969         /* 214    84  "T" */ CWORD_CWORD_CWORD_CWORD,
970         /* 215    85  "U" */ CWORD_CWORD_CWORD_CWORD,
971         /* 216    86  "V" */ CWORD_CWORD_CWORD_CWORD,
972         /* 217    87  "W" */ CWORD_CWORD_CWORD_CWORD,
973         /* 218    88  "X" */ CWORD_CWORD_CWORD_CWORD,
974         /* 219    89  "Y" */ CWORD_CWORD_CWORD_CWORD,
975         /* 220    90  "Z" */ CWORD_CWORD_CWORD_CWORD,
976         /* 221    91  "[" */ CWORD_CCTL_CCTL_CWORD,
977         /* 222    92  "\" */ CBACK_CBACK_CCTL_CBACK,
978         /* 223    93  "]" */ CWORD_CCTL_CCTL_CWORD,
979         /* 224    94  "^" */ CWORD_CWORD_CWORD_CWORD,
980         /* 225    95  "_" */ CWORD_CWORD_CWORD_CWORD,
981         /* 226    96  "`" */ CBQUOTE_CBQUOTE_CWORD_CBQUOTE,
982         /* 227    97  "a" */ CWORD_CWORD_CWORD_CWORD,
983         /* 228    98  "b" */ CWORD_CWORD_CWORD_CWORD,
984         /* 229    99  "c" */ CWORD_CWORD_CWORD_CWORD,
985         /* 230   100  "d" */ CWORD_CWORD_CWORD_CWORD,
986         /* 231   101  "e" */ CWORD_CWORD_CWORD_CWORD,
987         /* 232   102  "f" */ CWORD_CWORD_CWORD_CWORD,
988         /* 233   103  "g" */ CWORD_CWORD_CWORD_CWORD,
989         /* 234   104  "h" */ CWORD_CWORD_CWORD_CWORD,
990         /* 235   105  "i" */ CWORD_CWORD_CWORD_CWORD,
991         /* 236   106  "j" */ CWORD_CWORD_CWORD_CWORD,
992         /* 237   107  "k" */ CWORD_CWORD_CWORD_CWORD,
993         /* 238   108  "l" */ CWORD_CWORD_CWORD_CWORD,
994         /* 239   109  "m" */ CWORD_CWORD_CWORD_CWORD,
995         /* 240   110  "n" */ CWORD_CWORD_CWORD_CWORD,
996         /* 241   111  "o" */ CWORD_CWORD_CWORD_CWORD,
997         /* 242   112  "p" */ CWORD_CWORD_CWORD_CWORD,
998         /* 243   113  "q" */ CWORD_CWORD_CWORD_CWORD,
999         /* 244   114  "r" */ CWORD_CWORD_CWORD_CWORD,
1000         /* 245   115  "s" */ CWORD_CWORD_CWORD_CWORD,
1001         /* 246   116  "t" */ CWORD_CWORD_CWORD_CWORD,
1002         /* 247   117  "u" */ CWORD_CWORD_CWORD_CWORD,
1003         /* 248   118  "v" */ CWORD_CWORD_CWORD_CWORD,
1004         /* 249   119  "w" */ CWORD_CWORD_CWORD_CWORD,
1005         /* 250   120  "x" */ CWORD_CWORD_CWORD_CWORD,
1006         /* 251   121  "y" */ CWORD_CWORD_CWORD_CWORD,
1007         /* 252   122  "z" */ CWORD_CWORD_CWORD_CWORD,
1008         /* 253   123  "{" */ CWORD_CWORD_CWORD_CWORD,
1009         /* 254   124  "|" */ CSPCL_CWORD_CWORD_CWORD,
1010         /* 255   125  "}" */ CENDVAR_CENDVAR_CWORD_CENDVAR,
1011         /* 256   126  "~" */ CWORD_CCTL_CCTL_CWORD,
1012         /* 257   127      */ CWORD_CWORD_CWORD_CWORD,
1013 };
1014
1015 #endif                                                  /* USE_SIT_FUNCTION */
1016
1017
1018 /* first char is indicating which tokens mark the end of a list */
1019 static const char *const tokname_array[] = {
1020         "\1end of file",
1021         "\0newline",
1022         "\0redirection",
1023         "\0word",
1024         "\0assignment",
1025         "\0;",
1026         "\0&",
1027         "\0&&",
1028         "\0||",
1029         "\0|",
1030         "\0(",
1031         "\1)",
1032         "\1;;",
1033         "\1`",
1034 #define KWDOFFSET 14
1035         /* the following are keywords */
1036         "\0!",
1037         "\0case",
1038         "\1do",
1039         "\1done",
1040         "\1elif",
1041         "\1else",
1042         "\1esac",
1043         "\1fi",
1044         "\0for",
1045         "\0if",
1046         "\0in",
1047         "\1then",
1048         "\0until",
1049         "\0while",
1050         "\0{",
1051         "\1}",
1052 };
1053
1054 static const char *tokname(int tok)
1055 {
1056         static char buf[16];
1057
1058         if (tok >= TSEMI)
1059                 buf[0] = '"';
1060         sprintf(buf + (tok >= TSEMI), "%s%c",
1061                         tokname_array[tok] + 1, (tok >= TSEMI ? '"' : 0));
1062         return buf;
1063 }
1064
1065 static int plinno = 1;  /* input line number */
1066
1067 static int parselleft;  /* copy of parsefile->lleft */
1068
1069 static struct parsefile basepf; /* top level input file */
1070 static char basebuf[BUFSIZ];    /* buffer for top level input file */
1071 static struct parsefile *parsefile = &basepf;   /* current input file */
1072
1073 /*
1074  * NEOF is returned by parsecmd when it encounters an end of file.  It
1075  * must be distinct from NULL, so we use the address of a variable that
1076  * happens to be handy.
1077  */
1078
1079 static int tokpushback; /* last token pushed back */
1080
1081 #define NEOF ((union node *)&tokpushback)
1082 static int checkkwd;    /* 1 == check for kwds, 2 == also eat newlines */
1083
1084
1085 static void error(const char *, ...) __attribute__ ((__noreturn__));
1086 static void exerror(int, const char *, ...) __attribute__ ((__noreturn__));
1087 static void shellexec(char **, char **, const char *, int)
1088         __attribute__ ((noreturn));
1089 static void exitshell(int) __attribute__ ((noreturn));
1090
1091 static int goodname(const char *);
1092 static void ignoresig(int);
1093 static void onsig(int);
1094 static void dotrap(void);
1095 static int decode_signal(const char *, int);
1096
1097 static void setparam(char **);
1098 static void freeparam(volatile struct shparam *);
1099
1100 /* reasons for skipping commands (see comment on breakcmd routine) */
1101 #define SKIPBREAK       1
1102 #define SKIPCONT        2
1103 #define SKIPFUNC        3
1104 #define SKIPFILE        4
1105
1106 /* values of cmdtype */
1107 #define CMDUNKNOWN -1   /* no entry in table for command */
1108 #define CMDNORMAL 0             /* command is an executable program */
1109 #define CMDBUILTIN 1    /* command is a shell builtin */
1110 #define CMDFUNCTION 2   /* command is a shell function */
1111
1112 #define DO_ERR  1               /* find_command prints errors */
1113 #define DO_ABS  2               /* find_command checks absolute paths */
1114 #define DO_NOFUN        4       /* find_command ignores functions */
1115 #define DO_BRUTE        8       /* find_command ignores hash table */
1116
1117 /*
1118  * Shell variables.
1119  */
1120
1121 /* flags */
1122 #define VEXPORT         0x01    /* variable is exported */
1123 #define VREADONLY       0x02    /* variable cannot be modified */
1124 #define VSTRFIXED       0x04    /* variable struct is staticly allocated */
1125 #define VTEXTFIXED      0x08    /* text is staticly allocated */
1126 #define VSTACK          0x10    /* text is allocated on the stack */
1127 #define VUNSET          0x20    /* the variable is not set */
1128 #define VNOFUNC         0x40    /* don't call the callback function */
1129
1130
1131 struct var {
1132         struct var *next;       /* next entry in hash list */
1133         int flags;                      /* flags are defined above */
1134         char *text;                     /* name=value */
1135         void (*func) (const char *);
1136         /* function to be called when  */
1137         /* the variable gets set/unset */
1138 };
1139
1140 struct localvar {
1141         struct localvar *next;  /* next local variable in list */
1142         struct var *vp;         /* the variable that was made local */
1143         int flags;                      /* saved flags */
1144         char *text;                     /* saved text */
1145 };
1146
1147
1148 #if defined(__GLIBC__) && __GLIBC__ >= 2 && !defined(FNMATCH_BROKEN)
1149 #define rmescapes(p) _rmescapes((p), 0)
1150 static char *_rmescapes(char *, int);
1151 #else
1152 static void rmescapes(char *);
1153 #endif
1154
1155 static int casematch(union node *, const char *);
1156 static void clearredir(void);
1157 static void popstring(void);
1158 static void readcmdfile(const char *);
1159
1160 static int number(const char *);
1161 static int is_number(const char *, int *num);
1162 static char *single_quote(const char *);
1163 static int nextopt(const char *);
1164
1165 static void redirect(union node *, int);
1166 static void popredir(void);
1167 static int dup_as_newfd(int, int);
1168
1169 static void changepath(const char *newval);
1170 static void getoptsreset(const char *value);
1171
1172
1173 static int parsenleft;  /* copy of parsefile->nleft */
1174 static char *parsenextc;        /* copy of parsefile->nextc */
1175 static int rootpid;             /* pid of main shell */
1176 static int rootshell;   /* true if we aren't a child of the main shell */
1177
1178 static const char spcstr[] = " ";
1179 static const char snlfmt[] = "%s\n";
1180
1181 static int sstrnleft;
1182 static int herefd = -1;
1183
1184 static struct localvar *localvars;
1185
1186 static struct var vifs;
1187 static struct var vmail;
1188 static struct var vmpath;
1189 static struct var vpath;
1190 static struct var vps1;
1191 static struct var vps2;
1192 static struct var voptind;
1193
1194 #ifdef CONFIG_LOCALE_SUPPORT
1195 static struct var vlc_all;
1196 static struct var vlc_ctype;
1197 #endif
1198
1199 struct varinit {
1200         struct var *var;
1201         int flags;
1202         const char *text;
1203         void (*func) (const char *);
1204 };
1205
1206 static const char defpathvar[] =
1207         "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin";
1208 #define defpath (defpathvar + 5)
1209
1210 #ifdef IFS_BROKEN
1211 static const char defifsvar[] = "IFS= \t\n";
1212
1213 #define defifs (defifsvar + 4)
1214 #else
1215 static const char defifs[] = " \t\n";
1216 #endif
1217
1218 static const struct varinit varinit[] = {
1219 #ifdef IFS_BROKEN
1220         {&vifs, VSTRFIXED | VTEXTFIXED, defifsvar,
1221 #else
1222         {&vifs, VSTRFIXED | VTEXTFIXED | VUNSET, "IFS=",
1223 #endif
1224          NULL},
1225         {&vmail, VSTRFIXED | VTEXTFIXED | VUNSET, "MAIL=",
1226          NULL},
1227         {&vmpath, VSTRFIXED | VTEXTFIXED | VUNSET, "MAILPATH=",
1228          NULL},
1229         {&vpath, VSTRFIXED | VTEXTFIXED, defpathvar,
1230          changepath},
1231 #if defined(CONFIG_FEATURE_COMMAND_EDITING) && defined(CONFIG_FEATURE_SH_FANCY_PROMPT)
1232         {&vps1, VSTRFIXED | VTEXTFIXED, "PS1=\\w \\$ ",
1233          NULL},
1234 #endif                                                  /* else vps1 depends on uid */
1235         {&vps2, VSTRFIXED | VTEXTFIXED, "PS2=> ",
1236          NULL},
1237         {&voptind, VSTRFIXED | VTEXTFIXED, "OPTIND=1",
1238          getoptsreset},
1239 #ifdef CONFIG_LOCALE_SUPPORT
1240         {&vlc_all, VSTRFIXED | VTEXTFIXED | VUNSET, "LC_ALL=",
1241          change_lc_all},
1242         {&vlc_ctype, VSTRFIXED | VTEXTFIXED | VUNSET, "LC_CTYPE=",
1243          change_lc_ctype},
1244 #endif
1245         {NULL, 0, NULL,
1246          NULL}
1247 };
1248
1249 #define VTABSIZE 39
1250
1251 static struct var *vartab[VTABSIZE];
1252
1253 /*
1254  * The following macros access the values of the above variables.
1255  * They have to skip over the name.  They return the null string
1256  * for unset variables.
1257  */
1258
1259 #define ifsval()        (vifs.text + 4)
1260 #define ifsset()        ((vifs.flags & VUNSET) == 0)
1261 #define mailval()       (vmail.text + 5)
1262 #define mpathval()      (vmpath.text + 9)
1263 #define pathval()       (vpath.text + 5)
1264 #define ps1val()        (vps1.text + 4)
1265 #define ps2val()        (vps2.text + 4)
1266 #define optindval()     (voptind.text + 7)
1267
1268 #define mpathset()      ((vmpath.flags & VUNSET) == 0)
1269
1270 static void initvar(void);
1271 static void setvar(const char *, const char *, int);
1272 static void setvareq(char *, int);
1273 static void listsetvar(struct strlist *);
1274 static const char *lookupvar(const char *);
1275 static const char *bltinlookup(const char *);
1276 static char **environment(void);
1277 static int showvarscmd(int, char **);
1278 static void mklocal(char *);
1279 static void poplocalvars(void);
1280 static int unsetvar(const char *);
1281 static int varequal(const char *, const char *);
1282
1283
1284 static char *arg0;              /* value of $0 */
1285 static struct shparam shellparam;       /* current positional parameters */
1286 static char **argptr;   /* argument list for builtin commands */
1287 static char *optionarg; /* set by nextopt (like getopt) */
1288 static char *optptr;    /* used by nextopt */
1289 static char *minusc;    /* argument to -c option */
1290
1291
1292 #ifdef CONFIG_ASH_ALIAS
1293
1294 #define ALIASINUSE      1
1295 #define ALIASDEAD       2
1296
1297 #define ATABSIZE 39
1298
1299 struct alias {
1300         struct alias *next;
1301         char *name;
1302         char *val;
1303         int flag;
1304 };
1305
1306 static struct alias *atab[ATABSIZE];
1307
1308 static void setalias(char *, char *);
1309 static struct alias **hashalias(const char *);
1310 static struct alias *freealias(struct alias *);
1311 static struct alias **__lookupalias(const char *);
1312
1313 static void setalias(char *name, char *val)
1314 {
1315         struct alias *ap, **app;
1316
1317         app = __lookupalias(name);
1318         ap = *app;
1319         INTOFF;
1320         if (ap) {
1321                 if (!(ap->flag & ALIASINUSE)) {
1322                         free(ap->val);
1323                 }
1324                 ap->val = xstrdup(val);
1325                 ap->flag &= ~ALIASDEAD;
1326         } else {
1327                 /* not found */
1328                 ap = xmalloc(sizeof(struct alias));
1329                 ap->name = xstrdup(name);
1330                 ap->val = xstrdup(val);
1331                 ap->flag = 0;
1332                 ap->next = 0;
1333                 *app = ap;
1334         }
1335         INTON;
1336 }
1337
1338 static int unalias(char *name)
1339 {
1340         struct alias **app;
1341
1342         app = __lookupalias(name);
1343
1344         if (*app) {
1345                 INTOFF;
1346                 *app = freealias(*app);
1347                 INTON;
1348                 return (0);
1349         }
1350
1351         return (1);
1352 }
1353
1354 static void rmaliases(void)
1355 {
1356         struct alias *ap, **app;
1357         int i;
1358
1359         INTOFF;
1360         for (i = 0; i < ATABSIZE; i++) {
1361                 app = &atab[i];
1362                 for (ap = *app; ap; ap = *app) {
1363                         *app = freealias(*app);
1364                         if (ap == *app) {
1365                                 app = &ap->next;
1366                         }
1367                 }
1368         }
1369         INTON;
1370 }
1371
1372 static void printalias(const struct alias *ap)
1373 {
1374         char *p;
1375
1376         p = single_quote(ap->val);
1377         printf("alias %s=%s\n", ap->name, p);
1378         stunalloc(p);
1379 }
1380
1381
1382 /*
1383  * TODO - sort output
1384  */
1385 static int aliascmd(int argc, char **argv)
1386 {
1387         char *n, *v;
1388         int ret = 0;
1389         struct alias *ap;
1390
1391         if (argc == 1) {
1392                 int i;
1393
1394                 for (i = 0; i < ATABSIZE; i++)
1395                         for (ap = atab[i]; ap; ap = ap->next) {
1396                                 printalias(ap);
1397                         }
1398                 return (0);
1399         }
1400         while ((n = *++argv) != NULL) {
1401                 if ((v = strchr(n + 1, '=')) == NULL) { /* n+1: funny ksh stuff */
1402                         if ((ap = *__lookupalias(n)) == NULL) {
1403                                 out2fmt("%s: %s not found\n", "alias", n);
1404                                 ret = 1;
1405                         } else
1406                                 printalias(ap);
1407                 } else {
1408                         *v++ = '\0';
1409                         setalias(n, v);
1410                 }
1411         }
1412
1413         return (ret);
1414 }
1415
1416 static int unaliascmd(int argc, char **argv)
1417 {
1418         int i;
1419
1420         while ((i = nextopt("a")) != '\0') {
1421                 if (i == 'a') {
1422                         rmaliases();
1423                         return (0);
1424                 }
1425         }
1426         for (i = 0; *argptr; argptr++) {
1427                 if (unalias(*argptr)) {
1428                         out2fmt("%s: %s not found\n", "unalias", *argptr);
1429                         i = 1;
1430                 }
1431         }
1432
1433         return (i);
1434 }
1435
1436 static struct alias **hashalias(const char *p)
1437 {
1438         unsigned int hashval;
1439
1440         hashval = *p << 4;
1441         while (*p)
1442                 hashval += *p++;
1443         return &atab[hashval % ATABSIZE];
1444 }
1445
1446 static struct alias *freealias(struct alias *ap)
1447 {
1448         struct alias *next;
1449
1450         if (ap->flag & ALIASINUSE) {
1451                 ap->flag |= ALIASDEAD;
1452                 return ap;
1453         }
1454
1455         next = ap->next;
1456         free(ap->name);
1457         free(ap->val);
1458         free(ap);
1459         return next;
1460 }
1461
1462
1463 static struct alias **__lookupalias(const char *name)
1464 {
1465         struct alias **app = hashalias(name);
1466
1467         for (; *app; app = &(*app)->next) {
1468                 if (equal(name, (*app)->name)) {
1469                         break;
1470                 }
1471         }
1472
1473         return app;
1474 }
1475 #endif
1476
1477 #ifdef CONFIG_ASH_MATH_SUPPORT
1478 /* The generated file arith.c has been replaced with a custom hand
1479  * written implementation written by Aaron Lehmann <aaronl@vitelus.com>.
1480  * This is now part of libbb, so that it can be used by all the shells
1481  * in busybox. */
1482 static void expari(int);
1483 #endif
1484
1485 static char *trap[NSIG];        /* trap handler commands */
1486 static char sigmode[NSIG - 1];  /* current value of signal */
1487 static char gotsig[NSIG - 1];   /* indicates specified signal received */
1488 static int pendingsigs; /* indicates some signal received */
1489
1490 /*
1491  * This file was generated by the mkbuiltins program.
1492  */
1493
1494 #ifdef CONFIG_ASH_JOB_CONTROL
1495 static int bgcmd(int, char **);
1496 static int fgcmd(int, char **);
1497 static int killcmd(int, char **);
1498 #endif
1499 static int bltincmd(int, char **);
1500 static int cdcmd(int, char **);
1501 static int breakcmd(int, char **);
1502
1503 #ifdef CONFIG_ASH_CMDCMD
1504 static int commandcmd(int, char **);
1505 #endif
1506 static int dotcmd(int, char **);
1507 static int evalcmd(int, char **);
1508 static int execcmd(int, char **);
1509 static int exitcmd(int, char **);
1510 static int exportcmd(int, char **);
1511 static int histcmd(int, char **);
1512 static int hashcmd(int, char **);
1513 static int helpcmd(int, char **);
1514 static int jobscmd(int, char **);
1515 static int localcmd(int, char **);
1516 static int pwdcmd(int, char **);
1517 static int readcmd(int, char **);
1518 static int returncmd(int, char **);
1519 static int setcmd(int, char **);
1520 static int setvarcmd(int, char **);
1521 static int shiftcmd(int, char **);
1522 static int trapcmd(int, char **);
1523 static int umaskcmd(int, char **);
1524
1525 #ifdef CONFIG_ASH_ALIAS
1526 static int aliascmd(int, char **);
1527 static int unaliascmd(int, char **);
1528 #endif
1529 static int unsetcmd(int, char **);
1530 static int waitcmd(int, char **);
1531 static int ulimitcmd(int, char **);
1532 static int timescmd(int, char **);
1533
1534 #ifdef CONFIG_ASH_MATH_SUPPORT
1535 static int letcmd(int, char **);
1536 #endif
1537 static int typecmd(int, char **);
1538
1539 #ifdef CONFIG_ASH_GETOPTS
1540 static int getoptscmd(int, char **);
1541 #endif
1542
1543 #ifndef CONFIG_TRUE
1544 static int true_main(int, char **);
1545 #endif
1546 #ifndef CONFIG_FALSE
1547 static int false_main(int, char **);
1548 #endif
1549
1550 static void setpwd(const char *, int);
1551
1552
1553 #define BUILTIN_NOSPEC  "0"
1554 #define BUILTIN_SPECIAL "1"
1555 #define BUILTIN_REGULAR "2"
1556 #define BUILTIN_ASSIGN  "4"
1557 #define BUILTIN_SPEC_ASSG  "5"
1558 #define BUILTIN_REG_ASSG   "6"
1559
1560 #define IS_BUILTIN_SPECIAL(builtincmd) ((builtincmd)->name[0] & 1)
1561 #define IS_BUILTIN_REGULAR(builtincmd) ((builtincmd)->name[0] & 2)
1562 #define IS_BUILTIN_ASSIGN(builtincmd) ((builtincmd)->name[0] & 4)
1563
1564 struct builtincmd {
1565         const char *name;
1566         int (*const builtinfunc) (int, char **);
1567         //unsigned flags;
1568 };
1569
1570
1571 /* It is CRUCIAL that this listing be kept in ascii order, otherwise
1572  * the binary search in find_builtin() will stop working. If you value
1573  * your kneecaps, you'll be sure to *make sure* that any changes made
1574  * to this array result in the listing remaining in ascii order. You
1575  * have been warned.
1576  */
1577 static const struct builtincmd builtincmds[] = {
1578         {BUILTIN_SPECIAL ".", dotcmd},  /* first, see declare DOTCMD */
1579         {BUILTIN_SPECIAL ":", true_main},
1580 #ifdef CONFIG_ASH_ALIAS
1581         {BUILTIN_REG_ASSG "alias", aliascmd},
1582 #endif
1583 #ifdef CONFIG_ASH_JOB_CONTROL
1584         {BUILTIN_REGULAR "bg", bgcmd},
1585 #endif
1586         {BUILTIN_SPECIAL "break", breakcmd},
1587         {BUILTIN_SPECIAL "builtin", bltincmd},
1588         {BUILTIN_REGULAR "cd", cdcmd},
1589         {BUILTIN_NOSPEC "chdir", cdcmd},
1590 #ifdef CONFIG_ASH_CMDCMD
1591         {BUILTIN_REGULAR "command", commandcmd},
1592 #endif
1593         {BUILTIN_SPECIAL "continue", breakcmd},
1594         {BUILTIN_SPECIAL "eval", evalcmd},
1595         {BUILTIN_SPECIAL "exec", execcmd},
1596         {BUILTIN_SPECIAL "exit", exitcmd},
1597         {BUILTIN_SPEC_ASSG "export", exportcmd},
1598         {BUILTIN_REGULAR "false", false_main},
1599         {BUILTIN_REGULAR "fc", histcmd},
1600 #ifdef CONFIG_ASH_JOB_CONTROL
1601         {BUILTIN_REGULAR "fg", fgcmd},
1602 #endif
1603 #ifdef CONFIG_ASH_GETOPTS
1604         {BUILTIN_REGULAR "getopts", getoptscmd},
1605 #endif
1606         {BUILTIN_NOSPEC "hash", hashcmd},
1607         {BUILTIN_NOSPEC "help", helpcmd},
1608         {BUILTIN_REGULAR "jobs", jobscmd},
1609 #ifdef CONFIG_ASH_JOB_CONTROL
1610         {BUILTIN_REGULAR "kill", killcmd},
1611 #endif
1612 #ifdef CONFIG_ASH_MATH_SUPPORT
1613         {BUILTIN_REGULAR "let", letcmd},
1614 #endif
1615         {BUILTIN_ASSIGN "local", localcmd},
1616         {BUILTIN_NOSPEC "pwd", pwdcmd},
1617         {BUILTIN_REGULAR "read", readcmd},
1618         {BUILTIN_SPEC_ASSG "readonly", exportcmd},
1619         {BUILTIN_SPECIAL "return", returncmd},
1620         {BUILTIN_SPECIAL "set", setcmd},
1621         {BUILTIN_NOSPEC "setvar", setvarcmd},
1622         {BUILTIN_SPECIAL "shift", shiftcmd},
1623         {BUILTIN_SPECIAL "times", timescmd},
1624         {BUILTIN_SPECIAL "trap", trapcmd},
1625         {BUILTIN_REGULAR "true", true_main},
1626         {BUILTIN_NOSPEC "type", typecmd},
1627         {BUILTIN_NOSPEC "ulimit", ulimitcmd},
1628         {BUILTIN_REGULAR "umask", umaskcmd},
1629 #ifdef CONFIG_ASH_ALIAS
1630         {BUILTIN_REGULAR "unalias", unaliascmd},
1631 #endif
1632         {BUILTIN_SPECIAL "unset", unsetcmd},
1633         {BUILTIN_REGULAR "wait", waitcmd},
1634 };
1635
1636 #define NUMBUILTINS  (sizeof (builtincmds) / sizeof (struct builtincmd) )
1637
1638 #define DOTCMD &builtincmds[0]
1639 static struct builtincmd *BLTINCMD;
1640 static struct builtincmd *EXECCMD;
1641 static struct builtincmd *EVALCMD;
1642
1643 /* states */
1644 #define JOBSTOPPED 1    /* all procs are stopped */
1645 #define JOBDONE 2               /* all procs are completed */
1646
1647 /*
1648  * A job structure contains information about a job.  A job is either a
1649  * single process or a set of processes contained in a pipeline.  In the
1650  * latter case, pidlist will be non-NULL, and will point to a -1 terminated
1651  * array of pids.
1652  */
1653
1654 struct procstat {
1655         pid_t pid;                      /* process id */
1656         int status;                     /* status flags (defined above) */
1657         char *cmd;                      /* text of command being run */
1658 };
1659
1660
1661 static int job_warning; /* user was warned about stopped jobs */
1662
1663 #ifdef CONFIG_ASH_JOB_CONTROL
1664 static void setjobctl(int enable);
1665 #else
1666 #define setjobctl(on)   /* do nothing */
1667 #endif
1668
1669
1670 struct job {
1671         struct procstat ps0;    /* status of process */
1672         struct procstat *ps;    /* status or processes when more than one */
1673         short nprocs;           /* number of processes */
1674         short pgrp;                     /* process group of this job */
1675         char state;                     /* true if job is finished */
1676         char used;                      /* true if this entry is in used */
1677         char changed;           /* true if status has changed */
1678 #ifdef CONFIG_ASH_JOB_CONTROL
1679         char jobctl;            /* job running under job control */
1680 #endif
1681 };
1682
1683 static struct job *jobtab;      /* array of jobs */
1684 static int njobs;               /* size of array */
1685 static int backgndpid = -1;     /* pid of last background process */
1686
1687 #ifdef CONFIG_ASH_JOB_CONTROL
1688 static int initialpgrp; /* pgrp of shell on invocation */
1689 static int curjob;              /* current job */
1690 static int jobctl;
1691 #endif
1692
1693 static struct job *makejob(const union node *, int);
1694 static int forkshell(struct job *, const union node *, int);
1695 static int waitforjob(struct job *);
1696
1697 static int docd(char *, int);
1698 static void getpwd(void);
1699
1700 static char *padvance(const char **, const char *);
1701
1702 static char nullstr[1]; /* zero length string */
1703 static char *curdir = nullstr;  /* current working directory */
1704
1705 static int cdcmd(int argc, char **argv)
1706 {
1707         const char *dest;
1708         const char *path;
1709         char *p;
1710         struct stat statb;
1711         int print = 0;
1712
1713         nextopt(nullstr);
1714         if ((dest = *argptr) == NULL && (dest = bltinlookup("HOME")) == NULL)
1715                 error("HOME not set");
1716         if (*dest == '\0')
1717                 dest = ".";
1718         if (dest[0] == '-' && dest[1] == '\0') {
1719                 dest = bltinlookup("OLDPWD");
1720                 if (!dest || !*dest) {
1721                         dest = curdir;
1722                 }
1723                 print = 1;
1724                 if (dest)
1725                         print = 1;
1726                 else
1727                         dest = ".";
1728         }
1729         if (*dest == '/' || (path = bltinlookup("CDPATH")) == NULL)
1730                 path = nullstr;
1731         while ((p = padvance(&path, dest)) != NULL) {
1732                 if (stat(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) {
1733                         if (!print) {
1734                                 /*
1735                                  * XXX - rethink
1736                                  */
1737                                 if (p[0] == '.' && p[1] == '/' && p[2] != '\0')
1738                                         p += 2;
1739                                 print = strcmp(p, dest);
1740                         }
1741                         if (docd(p, print) >= 0)
1742                                 return 0;
1743
1744                 }
1745         }
1746         error("can't cd to %s", dest);
1747         /* NOTREACHED */
1748 }
1749
1750
1751 /*
1752  * Update curdir (the name of the current directory) in response to a
1753  * cd command.  We also call hashcd to let the routines in exec.c know
1754  * that the current directory has changed.
1755  */
1756
1757 static void hashcd(void);
1758
1759 static inline void updatepwd(const char *dir)
1760 {
1761         hashcd();                       /* update command hash table */
1762
1763         /*
1764          * If our argument is NULL, we don't know the current directory
1765          */
1766         if (dir == NULL || curdir == nullstr) {
1767                 setpwd(0, 1);
1768         } else {
1769                 setpwd(dir, 1);
1770         }
1771 }
1772
1773 /*
1774  * Actually do the chdir.  In an interactive shell, print the
1775  * directory name if "print" is nonzero.
1776  */
1777
1778 static int docd(char *dest, int print)
1779 {
1780         TRACE(("docd(\"%s\", %d) called\n", dest, print));
1781         INTOFF;
1782         if (chdir(dest) < 0) {
1783                 INTON;
1784                 return -1;
1785         }
1786         updatepwd(dest);
1787         INTON;
1788         if (print && iflag)
1789                 puts(curdir);
1790         return 0;
1791 }
1792
1793
1794 static int pwdcmd(int argc, char **argv)
1795 {
1796         puts(curdir);
1797         return 0;
1798 }
1799
1800 /* Ask system the current directory */
1801 static void getpwd(void)
1802 {
1803         curdir = xgetcwd(0);
1804         if (curdir == 0)
1805                 curdir = nullstr;
1806 }
1807
1808 static void setpwd(const char *val, int setold)
1809 {
1810         char *cated = NULL;
1811
1812         if (setold) {
1813                 setvar("OLDPWD", curdir, VEXPORT);
1814         }
1815         INTOFF;
1816         if (curdir != nullstr) {
1817                 if (val != NULL && *val != '/')
1818                         val = cated = concat_path_file(curdir, val);
1819                 free(curdir);
1820         }
1821         if (!val)
1822                 getpwd();
1823         else
1824                 curdir = simplify_path(val);
1825         free(cated);
1826         INTON;
1827         setvar("PWD", curdir, VEXPORT);
1828 }
1829
1830 /*
1831  * Errors and exceptions.
1832  */
1833
1834 /*
1835  * Code to handle exceptions in C.
1836  */
1837
1838 /*
1839  * We enclose jmp_buf in a structure so that we can declare pointers to
1840  * jump locations.  The global variable handler contains the location to
1841  * jump to when an exception occurs, and the global variable exception
1842  * contains a code identifying the exeception.  To implement nested
1843  * exception handlers, the user should save the value of handler on entry
1844  * to an inner scope, set handler to point to a jmploc structure for the
1845  * inner scope, and restore handler on exit from the scope.
1846  */
1847
1848 struct jmploc {
1849         jmp_buf loc;
1850 };
1851
1852 /* exceptions */
1853 #define EXINT 0                 /* SIGINT received */
1854 #define EXERROR 1               /* a generic error */
1855 #define EXSHELLPROC 2   /* execute a shell procedure */
1856 #define EXEXEC 3                /* command execution failed */
1857 #define EXREDIR 4               /* redirection error */
1858
1859 static struct jmploc *handler;
1860 static int exception;
1861
1862 static void exverror(int, const char *, va_list)
1863         __attribute__ ((__noreturn__));
1864
1865 /*
1866  * Called to raise an exception.  Since C doesn't include exceptions, we
1867  * just do a longjmp to the exception handler.  The type of exception is
1868  * stored in the global variable "exception".
1869  */
1870
1871 static void exraise(int) __attribute__ ((__noreturn__));
1872
1873 static void exraise(int e)
1874 {
1875 #ifdef DEBUG
1876         if (handler == NULL)
1877                 abort();
1878 #endif
1879         flushall();
1880         exception = e;
1881         longjmp(handler->loc, 1);
1882 }
1883
1884
1885 /*
1886  * Called from trap.c when a SIGINT is received.  (If the user specifies
1887  * that SIGINT is to be trapped or ignored using the trap builtin, then
1888  * this routine is not called.)  Suppressint is nonzero when interrupts
1889  * are held using the INTOFF macro.  The call to _exit is necessary because
1890  * there is a short period after a fork before the signal handlers are
1891  * set to the appropriate value for the child.  (The test for iflag is
1892  * just defensive programming.)
1893  */
1894
1895 static void onint(void)
1896 {
1897         sigset_t mysigset;
1898
1899         if (suppressint) {
1900                 intpending++;
1901                 return;
1902         }
1903         intpending = 0;
1904         sigemptyset(&mysigset);
1905         sigprocmask(SIG_SETMASK, &mysigset, NULL);
1906         if (!(rootshell && iflag)) {
1907                 signal(SIGINT, SIG_DFL);
1908                 raise(SIGINT);
1909         }
1910         exraise(EXINT);
1911         /* NOTREACHED */
1912 }
1913
1914
1915 static char *commandname;       /* currently executing command */
1916
1917 /*
1918  * Exverror is called to raise the error exception.  If the first argument
1919  * is not NULL then error prints an error message using printf style
1920  * formatting.  It then raises the error exception.
1921  */
1922 static void exverror(int cond, const char *msg, va_list ap)
1923 {
1924         CLEAR_PENDING_INT;
1925         INTOFF;
1926
1927 #ifdef DEBUG
1928         if (msg)
1929                 TRACE(("exverror(%d, \"%s\") pid=%d\n", cond, msg, getpid()));
1930         else
1931                 TRACE(("exverror(%d, NULL) pid=%d\n", cond, getpid()));
1932 #endif
1933         if (msg) {
1934                 if (commandname)
1935                         out2fmt("%s: ", commandname);
1936                 vfprintf(stderr, msg, ap);
1937                 out2c('\n');
1938         }
1939         exraise(cond);
1940         /* NOTREACHED */
1941 }
1942
1943
1944 static void error(const char *msg, ...)
1945 {
1946         va_list ap;
1947
1948         va_start(ap, msg);
1949         exverror(EXERROR, msg, ap);
1950         /* NOTREACHED */
1951         va_end(ap);
1952 }
1953
1954
1955 static void exerror(int cond, const char *msg, ...)
1956 {
1957         va_list ap;
1958
1959         va_start(ap, msg);
1960         exverror(cond, msg, ap);
1961         /* NOTREACHED */
1962         va_end(ap);
1963 }
1964
1965
1966
1967 /*
1968  * Table of error messages.
1969  */
1970
1971 struct errname {
1972         short errcode;          /* error number */
1973         short action;           /* operation which encountered the error */
1974 };
1975
1976 /*
1977  * Types of operations (passed to the errmsg routine).
1978  */
1979
1980 #define E_OPEN 01               /* opening a file */
1981 #define E_CREAT 02              /* creating a file */
1982 #define E_EXEC 04               /* executing a program */
1983
1984 #define ALL (E_OPEN|E_CREAT|E_EXEC)
1985
1986 static const struct errname errormsg[] = {
1987         {EINTR, ALL},
1988         {EACCES, ALL},
1989         {EIO, ALL},
1990         {ENOENT, E_OPEN},
1991         {ENOENT, E_CREAT},
1992         {ENOENT, E_EXEC},
1993         {ENOTDIR, E_OPEN},
1994         {ENOTDIR, E_CREAT},
1995         {ENOTDIR, E_EXEC},
1996         {EISDIR, ALL},
1997         {EEXIST, E_CREAT},
1998 #ifdef EMFILE
1999         {EMFILE, ALL},
2000 #endif
2001         {ENFILE, ALL},
2002         {ENOSPC, ALL},
2003 #ifdef EDQUOT
2004         {EDQUOT, ALL},
2005 #endif
2006 #ifdef ENOSR
2007         {ENOSR, ALL},
2008 #endif
2009         {ENXIO, ALL},
2010         {EROFS, ALL},
2011         {ETXTBSY, ALL},
2012 #ifdef EAGAIN
2013         {EAGAIN, E_EXEC},
2014 #endif
2015         {ENOMEM, ALL},
2016 #ifdef ENOLINK
2017         {ENOLINK, ALL},
2018 #endif
2019 #ifdef EMULTIHOP
2020         {EMULTIHOP, ALL},
2021 #endif
2022 #ifdef ECOMM
2023         {ECOMM, ALL},
2024 #endif
2025 #ifdef ESTALE
2026         {ESTALE, ALL},
2027 #endif
2028 #ifdef ETIMEDOUT
2029         {ETIMEDOUT, ALL},
2030 #endif
2031 #ifdef ELOOP
2032         {ELOOP, ALL},
2033 #endif
2034         {E2BIG, E_EXEC},
2035 #ifdef ELIBACC
2036         {ELIBACC, E_EXEC},
2037 #endif
2038 };
2039
2040 #define ERRNAME_SIZE (sizeof(errormsg)/sizeof(struct errname))
2041
2042 /*
2043  * Return a string describing an error.  The returned string may be a
2044  * pointer to a static buffer that will be overwritten on the next call.
2045  * Action describes the operation that got the error.
2046  */
2047
2048 static const char *errmsg(int e, int action)
2049 {
2050         struct errname const *ep;
2051         static char buf[12];
2052
2053         for (ep = errormsg; ep < errormsg + ERRNAME_SIZE; ep++) {
2054                 if (ep->errcode == e && (ep->action & action) != 0)
2055                         return strerror(e);
2056         }
2057
2058         snprintf(buf, sizeof buf, "error %d", e);
2059         return buf;
2060 }
2061
2062
2063 #ifdef CONFIG_ASH_OPTIMIZE_FOR_SIZE
2064 static void __inton()
2065 {
2066         if (--suppressint == 0 && intpending) {
2067                 onint();
2068         }
2069 }
2070 static void forceinton(void)
2071 {
2072         suppressint = 0;
2073         if (intpending)
2074                 onint();
2075 }
2076 #endif
2077
2078 /* flags in argument to evaltree */
2079 #define EV_EXIT 01              /* exit after evaluating tree */
2080 #define EV_TESTED 02    /* exit status is checked; ignore -e flag */
2081 #define EV_BACKCMD 04   /* command executing within back quotes */
2082
2083 static int evalskip;    /* set if we are skipping commands */
2084 static int skipcount;   /* number of levels to skip */
2085 static int loopnest;    /* current loop nesting level */
2086 static int funcnest;    /* depth of function calls */
2087
2088
2089 static struct strlist *cmdenviron;      /* environment for builtin command */
2090 static int exitstatus;  /* exit status of last command */
2091 static int oexitstatus; /* saved exit status */
2092
2093 static void evalsubshell(const union node *, int);
2094 static void expredir(union node *);
2095 static void prehash(union node *);
2096 static void eprintlist(struct strlist *);
2097
2098 static union node *parsecmd(int);
2099
2100 /*
2101  * Called to reset things after an exception.
2102  */
2103
2104 /*
2105  * The eval commmand.
2106  */
2107 static void evalstring(char *, int);
2108
2109 static int evalcmd(int argc, char **argv)
2110 {
2111         char *p;
2112         char *concat;
2113         char **ap;
2114
2115         if (argc > 1) {
2116                 p = argv[1];
2117                 if (argc > 2) {
2118                         STARTSTACKSTR(concat);
2119                         ap = argv + 2;
2120                         for (;;) {
2121                                 while (*p)
2122                                         STPUTC(*p++, concat);
2123                                 if ((p = *ap++) == NULL)
2124                                         break;
2125                                 STPUTC(' ', concat);
2126                         }
2127                         STPUTC('\0', concat);
2128                         p = grabstackstr(concat);
2129                 }
2130                 evalstring(p, EV_TESTED);
2131         }
2132         return exitstatus;
2133 }
2134
2135 /*
2136  * Execute a command or commands contained in a string.
2137  */
2138
2139 static void evaltree(union node *, int);
2140 static void setinputstring(char *);
2141 static void popfile(void);
2142 static void setstackmark(struct stackmark *mark);
2143 static void popstackmark(struct stackmark *mark);
2144
2145
2146 static void evalstring(char *s, int flag)
2147 {
2148         union node *n;
2149         struct stackmark smark;
2150
2151         setstackmark(&smark);
2152         setinputstring(s);
2153         while ((n = parsecmd(0)) != NEOF) {
2154                 evaltree(n, flag);
2155                 popstackmark(&smark);
2156         }
2157         popfile();
2158         popstackmark(&smark);
2159 }
2160
2161 static struct builtincmd *find_builtin(const char *);
2162 static void expandarg(union node *, struct arglist *, int);
2163 static void calcsize(const union node *);
2164 static union node *copynode(const union node *);
2165
2166 /*
2167  * Make a copy of a parse tree.
2168  */
2169
2170 static int funcblocksize;       /* size of structures in function */
2171 static int funcstringsize;      /* size of strings in node */
2172 static pointer funcblock;       /* block to allocate function from */
2173 static char *funcstring;        /* block to allocate strings from */
2174
2175
2176 static inline union node *copyfunc(union node *n)
2177 {
2178         if (n == NULL)
2179                 return NULL;
2180         funcblocksize = 0;
2181         funcstringsize = 0;
2182         calcsize(n);
2183         funcblock = xmalloc(funcblocksize + funcstringsize);
2184         funcstring = (char *) funcblock + funcblocksize;
2185         return copynode(n);
2186 }
2187
2188 /*
2189  * Add a new command entry, replacing any existing command entry for
2190  * the same name.
2191  */
2192
2193 static inline void addcmdentry(char *name, struct cmdentry *entry)
2194 {
2195         struct tblentry *cmdp;
2196
2197         INTOFF;
2198         cmdp = cmdlookup(name, 1);
2199         if (cmdp->cmdtype == CMDFUNCTION) {
2200                 free(cmdp->param.func);
2201         }
2202         cmdp->cmdtype = entry->cmdtype;
2203         cmdp->param = entry->u;
2204         INTON;
2205 }
2206
2207 static inline void evalloop(const union node *n, int flags)
2208 {
2209         int status;
2210
2211         loopnest++;
2212         status = 0;
2213         flags &= EV_TESTED;
2214         for (;;) {
2215                 evaltree(n->nbinary.ch1, EV_TESTED);
2216                 if (evalskip) {
2217                   skipping:if (evalskip == SKIPCONT && --skipcount <= 0) {
2218                                 evalskip = 0;
2219                                 continue;
2220                         }
2221                         if (evalskip == SKIPBREAK && --skipcount <= 0)
2222                                 evalskip = 0;
2223                         break;
2224                 }
2225                 if (n->type == NWHILE) {
2226                         if (exitstatus != 0)
2227                                 break;
2228                 } else {
2229                         if (exitstatus == 0)
2230                                 break;
2231                 }
2232                 evaltree(n->nbinary.ch2, flags);
2233                 status = exitstatus;
2234                 if (evalskip)
2235                         goto skipping;
2236         }
2237         loopnest--;
2238         exitstatus = status;
2239 }
2240
2241 static void evalfor(const union node *n, int flags)
2242 {
2243         struct arglist arglist;
2244         union node *argp;
2245         struct strlist *sp;
2246         struct stackmark smark;
2247
2248         setstackmark(&smark);
2249         arglist.lastp = &arglist.list;
2250         for (argp = n->nfor.args; argp; argp = argp->narg.next) {
2251                 oexitstatus = exitstatus;
2252                 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE | EXP_RECORD);
2253                 if (evalskip)
2254                         goto out;
2255         }
2256         *arglist.lastp = NULL;
2257
2258         exitstatus = 0;
2259         loopnest++;
2260         flags &= EV_TESTED;
2261         for (sp = arglist.list; sp; sp = sp->next) {
2262                 setvar(n->nfor.var, sp->text, 0);
2263                 evaltree(n->nfor.body, flags);
2264                 if (evalskip) {
2265                         if (evalskip == SKIPCONT && --skipcount <= 0) {
2266                                 evalskip = 0;
2267                                 continue;
2268                         }
2269                         if (evalskip == SKIPBREAK && --skipcount <= 0)
2270                                 evalskip = 0;
2271                         break;
2272                 }
2273         }
2274         loopnest--;
2275   out:
2276         popstackmark(&smark);
2277 }
2278
2279 static inline void evalcase(const union node *n, int flags)
2280 {
2281         union node *cp;
2282         union node *patp;
2283         struct arglist arglist;
2284         struct stackmark smark;
2285
2286         setstackmark(&smark);
2287         arglist.lastp = &arglist.list;
2288         oexitstatus = exitstatus;
2289         expandarg(n->ncase.expr, &arglist, EXP_TILDE);
2290         for (cp = n->ncase.cases; cp && evalskip == 0; cp = cp->nclist.next) {
2291                 for (patp = cp->nclist.pattern; patp; patp = patp->narg.next) {
2292                         if (casematch(patp, arglist.list->text)) {
2293                                 if (evalskip == 0) {
2294                                         evaltree(cp->nclist.body, flags);
2295                                 }
2296                                 goto out;
2297                         }
2298                 }
2299         }
2300   out:
2301         popstackmark(&smark);
2302 }
2303
2304 /*
2305  * Evaluate a pipeline.  All the processes in the pipeline are children
2306  * of the process creating the pipeline.  (This differs from some versions
2307  * of the shell, which make the last process in a pipeline the parent
2308  * of all the rest.)
2309  */
2310
2311 static inline void evalpipe(union node *n, int flags)
2312 {
2313         struct job *jp;
2314         struct nodelist *lp;
2315         int pipelen;
2316         int prevfd;
2317         int pip[2];
2318
2319         TRACE(("evalpipe(0x%lx) called\n", (long) n));
2320         pipelen = 0;
2321         for (lp = n->npipe.cmdlist; lp; lp = lp->next)
2322                 pipelen++;
2323         flags |= EV_EXIT;
2324         INTOFF;
2325         jp = makejob(n, pipelen);
2326         prevfd = -1;
2327         for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
2328                 prehash(lp->n);
2329                 pip[1] = -1;
2330                 if (lp->next) {
2331                         if (pipe(pip) < 0) {
2332                                 close(prevfd);
2333                                 error("Pipe call failed");
2334                         }
2335                 }
2336                 if (forkshell(jp, lp->n, n->npipe.backgnd) == 0) {
2337                         INTON;
2338                         if (pip[1] >= 0) {
2339                                 close(pip[0]);
2340                         }
2341                         if (prevfd > 0) {
2342                                 dup2(prevfd, 0);
2343                                 close(prevfd);
2344                         }
2345                         if (pip[1] > 1) {
2346                                 dup2(pip[1], 1);
2347                                 close(pip[1]);
2348                         }
2349                         evaltree(lp->n, flags);
2350                 }
2351                 if (prevfd >= 0)
2352                         close(prevfd);
2353                 prevfd = pip[0];
2354                 close(pip[1]);
2355         }
2356         if (n->npipe.backgnd == 0) {
2357                 exitstatus = waitforjob(jp);
2358                 TRACE(("evalpipe:  job done exit status %d\n", exitstatus));
2359         }
2360         INTON;
2361 }
2362
2363 static void find_command(const char *, struct cmdentry *, int, const char *);
2364
2365 static int isassignment(const char *word)
2366 {
2367         if (!is_name(*word)) {
2368                 return 0;
2369         }
2370         do {
2371                 word++;
2372         } while (is_in_name(*word));
2373         return *word == '=';
2374 }
2375
2376
2377 static void evalcommand(union node *cmd, int flags)
2378 {
2379         struct stackmark smark;
2380         union node *argp;
2381         struct arglist arglist;
2382         struct arglist varlist;
2383         char **argv;
2384         int argc;
2385         char **envp;
2386         struct strlist *sp;
2387         int mode;
2388         struct cmdentry cmdentry;
2389         struct job *jp;
2390         char *volatile savecmdname;
2391         volatile struct shparam saveparam;
2392         struct localvar *volatile savelocalvars;
2393         volatile int e;
2394         char *lastarg;
2395         const char *path;
2396         int spclbltin;
2397         struct jmploc *volatile savehandler;
2398         struct jmploc jmploc;
2399
2400 #if __GNUC__
2401         /* Avoid longjmp clobbering */
2402         (void) &argv;
2403         (void) &argc;
2404         (void) &lastarg;
2405         (void) &flags;
2406         (void) &spclbltin;
2407 #endif
2408
2409         /* First expand the arguments. */
2410         TRACE(("evalcommand(0x%lx, %d) called\n", (long) cmd, flags));
2411         setstackmark(&smark);
2412         arglist.lastp = &arglist.list;
2413         varlist.lastp = &varlist.list;
2414         arglist.list = 0;
2415         oexitstatus = exitstatus;
2416         exitstatus = 0;
2417         path = pathval();
2418         for (argp = cmd->ncmd.assign; argp; argp = argp->narg.next) {
2419                 expandarg(argp, &varlist, EXP_VARTILDE);
2420         }
2421         for (argp = cmd->ncmd.args; argp; argp = argp->narg.next) {
2422                 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
2423         }
2424         *arglist.lastp = NULL;
2425         *varlist.lastp = NULL;
2426         expredir(cmd->ncmd.redirect);
2427         argc = 0;
2428         for (sp = arglist.list; sp; sp = sp->next)
2429                 argc++;
2430         argv = stalloc(sizeof(char *) * (argc + 1));
2431
2432         for (sp = arglist.list; sp; sp = sp->next) {
2433                 TRACE(("evalcommand arg: %s\n", sp->text));
2434                 *argv++ = sp->text;
2435         }
2436         *argv = NULL;
2437         lastarg = NULL;
2438         if (iflag && funcnest == 0 && argc > 0)
2439                 lastarg = argv[-1];
2440         argv -= argc;
2441
2442         /* Print the command if xflag is set. */
2443         if (xflag) {
2444                 out2c('+');
2445                 eprintlist(varlist.list);
2446                 eprintlist(arglist.list);
2447                 out2c('\n');
2448         }
2449
2450         /* Now locate the command. */
2451         if (argc == 0) {
2452                 cmdentry.cmdtype = CMDBUILTIN;
2453                 cmdentry.u.cmd = BLTINCMD;
2454                 spclbltin = 1;
2455         } else {
2456                 const char *oldpath;
2457                 int findflag = DO_ERR;
2458                 int oldfindflag;
2459
2460                 /*
2461                  * Modify the command lookup path, if a PATH= assignment
2462                  * is present
2463                  */
2464                 for (sp = varlist.list; sp; sp = sp->next)
2465                         if (varequal(sp->text, defpathvar)) {
2466                                 path = sp->text + 5;
2467                                 findflag |= DO_BRUTE;
2468                         }
2469                 oldpath = path;
2470                 oldfindflag = findflag;
2471                 spclbltin = -1;
2472                 for (;;) {
2473                         find_command(argv[0], &cmdentry, findflag, path);
2474                         if (cmdentry.cmdtype == CMDUNKNOWN) {   /* command not found */
2475                                 exitstatus = 127;
2476                                 goto out;
2477                         }
2478                         /* implement bltin and command here */
2479                         if (cmdentry.cmdtype != CMDBUILTIN) {
2480                                 break;
2481                         }
2482                         if (spclbltin < 0) {
2483                                 spclbltin = !!(IS_BUILTIN_SPECIAL(cmdentry.u.cmd)) * 2;
2484                         }
2485                         if (cmdentry.u.cmd == BLTINCMD) {
2486                                 for (;;) {
2487                                         struct builtincmd *bcmd;
2488
2489                                         argv++;
2490                                         if (--argc == 0)
2491                                                 goto found;
2492                                         if (!(bcmd = find_builtin(*argv))) {
2493                                                 out2fmt("%s: not found\n", *argv);
2494                                                 exitstatus = 127;
2495                                                 goto out;
2496                                         }
2497                                         cmdentry.u.cmd = bcmd;
2498                                         if (bcmd != BLTINCMD)
2499                                                 break;
2500                                 }
2501                         }
2502                         if (cmdentry.u.cmd == find_builtin("command")) {
2503                                 argv++;
2504                                 if (--argc == 0) {
2505                                         goto found;
2506                                 }
2507                                 if (*argv[0] == '-') {
2508                                         if (!equal(argv[0], "-p")) {
2509                                                 argv--;
2510                                                 argc++;
2511                                                 break;
2512                                         }
2513                                         argv++;
2514                                         if (--argc == 0) {
2515                                                 goto found;
2516                                         }
2517                                         path = defpath;
2518                                         findflag |= DO_BRUTE;
2519                                 } else {
2520                                         path = oldpath;
2521                                         findflag = oldfindflag;
2522                                 }
2523                                 findflag |= DO_NOFUN;
2524                                 continue;
2525                         }
2526                   found:
2527                         break;
2528                 }
2529         }
2530
2531         /* Fork off a child process if necessary. */
2532         if (cmd->ncmd.backgnd
2533                 || (cmdentry.cmdtype == CMDNORMAL && (!(flags & EV_EXIT) || trap[0]))
2534                 ) {
2535                 INTOFF;
2536                 jp = makejob(cmd, 1);
2537                 mode = cmd->ncmd.backgnd;
2538                 if (forkshell(jp, cmd, mode) != 0)
2539                         goto parent;    /* at end of routine */
2540                 FORCEINTON;
2541                 flags |= EV_EXIT;
2542         } else {
2543                 flags &= ~EV_EXIT;
2544         }
2545
2546         /* This is the child process if a fork occurred. */
2547         /* Execute the command. */
2548         if (cmdentry.cmdtype == CMDFUNCTION) {
2549 #ifdef DEBUG
2550                 trputs("Shell function:  ");
2551                 trargs(argv);
2552 #endif
2553                 exitstatus = oexitstatus;
2554                 saveparam = shellparam;
2555                 shellparam.malloc = 0;
2556                 shellparam.nparam = argc - 1;
2557                 shellparam.p = argv + 1;
2558                 INTOFF;
2559                 savelocalvars = localvars;
2560                 localvars = NULL;
2561                 INTON;
2562                 if (setjmp(jmploc.loc)) {
2563                         if (exception == EXREDIR) {
2564                                 exitstatus = 2;
2565                                 goto funcdone;
2566                         }
2567                         saveparam.optind = shellparam.optind;
2568                         saveparam.optoff = shellparam.optoff;
2569                         freeparam(&shellparam);
2570                         shellparam = saveparam;
2571                         poplocalvars();
2572                         localvars = savelocalvars;
2573                         handler = savehandler;
2574                         longjmp(handler->loc, 1);
2575                 }
2576                 savehandler = handler;
2577                 handler = &jmploc;
2578                 redirect(cmd->ncmd.redirect, REDIR_PUSH);
2579                 listsetvar(varlist.list);
2580                 funcnest++;
2581                 evaltree(cmdentry.u.func, flags & EV_TESTED);
2582                 funcnest--;
2583           funcdone:
2584                 INTOFF;
2585                 poplocalvars();
2586                 localvars = savelocalvars;
2587                 saveparam.optind = shellparam.optind;
2588                 saveparam.optoff = shellparam.optoff;
2589                 freeparam(&shellparam);
2590                 shellparam = saveparam;
2591                 handler = savehandler;
2592                 popredir();
2593                 INTON;
2594                 if (evalskip == SKIPFUNC) {
2595                         evalskip = 0;
2596                         skipcount = 0;
2597                 }
2598         } else if (cmdentry.cmdtype == CMDBUILTIN) {
2599                 int redir;
2600
2601 #ifdef DEBUG
2602                 trputs("builtin command:  ");
2603                 trargs(argv);
2604 #endif
2605                 redir = (cmdentry.u.cmd == EXECCMD) ? 0 : REDIR_PUSH;
2606                 savecmdname = commandname;
2607                 if (spclbltin) {
2608                         listsetvar(varlist.list);
2609                 } else {
2610                         cmdenviron = varlist.list;
2611                 }
2612                 e = -1;
2613                 if (setjmp(jmploc.loc)) {
2614                         e = exception;
2615                         exitstatus = (e == EXINT) ? SIGINT + 128 : 2;
2616                         goto cmddone;
2617                 }
2618                 savehandler = handler;
2619                 handler = &jmploc;
2620                 redirect(cmd->ncmd.redirect, redir);
2621                 commandname = argv[0];
2622                 argptr = argv + 1;
2623                 optptr = NULL;  /* initialize nextopt */
2624                 exitstatus = (*cmdentry.u.cmd->builtinfunc) (argc, argv);
2625                 flushall();
2626           cmddone:
2627                 cmdenviron = NULL;
2628                 commandname = savecmdname;
2629                 handler = savehandler;
2630                 if (e != -1) {
2631                         if (e == EXINT || spclbltin & 2) {
2632                                 if (e == EXREDIR)
2633                                         exraise(e);
2634                         }
2635                         FORCEINTON;
2636                 }
2637                 if (cmdentry.u.cmd != EXECCMD)
2638                         popredir();
2639         } else {
2640 #ifdef DEBUG
2641                 trputs("normal command:  ");
2642                 trargs(argv);
2643 #endif
2644                 redirect(cmd->ncmd.redirect, 0);
2645                 clearredir();
2646                 for (sp = varlist.list; sp; sp = sp->next)
2647                         setvareq(sp->text, VEXPORT | VSTACK);
2648                 envp = environment();
2649                 shellexec(argv, envp, path, cmdentry.u.index);
2650         }
2651         if (flags & EV_EXIT)
2652                 exitshell(exitstatus);
2653         goto out;
2654
2655   parent:                               /* parent process gets here (if we forked) */
2656         if (mode == 0) {        /* argument to fork */
2657                 exitstatus = waitforjob(jp);
2658         }
2659         INTON;
2660
2661   out:
2662         if (lastarg)
2663                 setvar("_", lastarg, 0);
2664         popstackmark(&smark);
2665 }
2666
2667 /*
2668  * Evaluate a parse tree.  The value is left in the global variable
2669  * exitstatus.
2670  */
2671 static void evaltree(union node *n, int flags)
2672 {
2673         int checkexit = 0;
2674
2675         if (n == NULL) {
2676                 TRACE(("evaltree(NULL) called\n"));
2677                 goto out;
2678         }
2679         TRACE(("evaltree(0x%lx: %d) called\n", (long) n, n->type));
2680         switch (n->type) {
2681         case NSEMI:
2682                 evaltree(n->nbinary.ch1, flags & EV_TESTED);
2683                 if (evalskip)
2684                         goto out;
2685                 evaltree(n->nbinary.ch2, flags);
2686                 break;
2687         case NAND:
2688                 evaltree(n->nbinary.ch1, EV_TESTED);
2689                 if (evalskip || exitstatus != 0)
2690                         goto out;
2691                 evaltree(n->nbinary.ch2, flags);
2692                 break;
2693         case NOR:
2694                 evaltree(n->nbinary.ch1, EV_TESTED);
2695                 if (evalskip || exitstatus == 0)
2696                         goto out;
2697                 evaltree(n->nbinary.ch2, flags);
2698                 break;
2699         case NREDIR:
2700                 expredir(n->nredir.redirect);
2701                 redirect(n->nredir.redirect, REDIR_PUSH);
2702                 evaltree(n->nredir.n, flags);
2703                 popredir();
2704                 break;
2705         case NSUBSHELL:
2706                 evalsubshell(n, flags);
2707                 break;
2708         case NBACKGND:
2709                 evalsubshell(n, flags);
2710                 break;
2711         case NIF:{
2712                 evaltree(n->nif.test, EV_TESTED);
2713                 if (evalskip)
2714                         goto out;
2715                 if (exitstatus == 0)
2716                         evaltree(n->nif.ifpart, flags);
2717                 else if (n->nif.elsepart)
2718                         evaltree(n->nif.elsepart, flags);
2719                 else
2720                         exitstatus = 0;
2721                 break;
2722         }
2723         case NWHILE:
2724         case NUNTIL:
2725                 evalloop(n, flags);
2726                 break;
2727         case NFOR:
2728                 evalfor(n, flags);
2729                 break;
2730         case NCASE:
2731                 evalcase(n, flags);
2732                 break;
2733         case NDEFUN:{
2734                 struct builtincmd *bcmd;
2735                 struct cmdentry entry;
2736
2737                 if ((bcmd = find_builtin(n->narg.text)) && IS_BUILTIN_SPECIAL(bcmd)
2738                         ) {
2739                         out2fmt("%s is a special built-in\n", n->narg.text);
2740                         exitstatus = 1;
2741                         break;
2742                 }
2743                 entry.cmdtype = CMDFUNCTION;
2744                 entry.u.func = copyfunc(n->narg.next);
2745                 addcmdentry(n->narg.text, &entry);
2746                 exitstatus = 0;
2747                 break;
2748         }
2749         case NNOT:
2750                 evaltree(n->nnot.com, EV_TESTED);
2751                 exitstatus = !exitstatus;
2752                 break;
2753
2754         case NPIPE:
2755                 evalpipe(n, flags);
2756                 checkexit = 1;
2757                 break;
2758         case NCMD:
2759                 evalcommand(n, flags);
2760                 checkexit = 1;
2761                 break;
2762 #ifdef DEBUG
2763         default:
2764                 printf("Node type = %d\n", n->type);
2765                 break;
2766 #endif
2767         }
2768   out:
2769         if (pendingsigs)
2770                 dotrap();
2771         if (flags & EV_EXIT ||
2772                 (checkexit && eflag && exitstatus && !(flags & EV_TESTED))
2773                 )
2774                 exitshell(exitstatus);
2775 }
2776
2777 /*
2778  * Kick off a subshell to evaluate a tree.
2779  */
2780
2781 static void evalsubshell(const union node *n, int flags)
2782 {
2783         struct job *jp = 0;
2784         int backgnd = (n->type == NBACKGND);
2785
2786         expredir(n->nredir.redirect);
2787         if (!backgnd && flags & EV_EXIT && !trap[0])
2788                 goto nofork;
2789         INTOFF;
2790         jp = makejob(n, 1);
2791         if (forkshell(jp, n, backgnd) == 0) {
2792                 INTON;
2793                 flags |= EV_EXIT;
2794                 if (backgnd)
2795                         flags &= ~EV_TESTED;
2796           nofork:
2797                 redirect(n->nredir.redirect, 0);
2798                 evaltree(n->nredir.n, flags);   /* never returns */
2799         }
2800         if (!backgnd) {
2801                 exitstatus = waitforjob(jp);
2802         }
2803         INTON;
2804 }
2805
2806 /*
2807  * Compute the names of the files in a redirection list.
2808  */
2809
2810 static void fixredir(union node *n, const char *text, int err);
2811
2812 static void expredir(union node *n)
2813 {
2814         union node *redir;
2815
2816         for (redir = n; redir; redir = redir->nfile.next) {
2817                 struct arglist fn;
2818
2819                 fn.lastp = &fn.list;
2820                 oexitstatus = exitstatus;
2821                 switch (redir->type) {
2822                 case NFROMTO:
2823                 case NFROM:
2824                 case NTO:
2825                 case NAPPEND:
2826                 case NTOOV:
2827                         expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
2828                         redir->nfile.expfname = fn.list->text;
2829                         break;
2830                 case NFROMFD:
2831                 case NTOFD:
2832                         if (redir->ndup.vname) {
2833                                 expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE);
2834                                 fixredir(redir, fn.list->text, 1);
2835                         }
2836                         break;
2837                 }
2838         }
2839 }
2840
2841
2842 /*
2843  * Execute a command inside back quotes.  If it's a builtin command, we
2844  * want to save its output in a block obtained from malloc.  Otherwise
2845  * we fork off a subprocess and get the output of the command via a pipe.
2846  * Should be called with interrupts off.
2847  */
2848
2849 static void evalbackcmd(union node *n, struct backcmd *result)
2850 {
2851         int pip[2];
2852         struct job *jp;
2853         struct stackmark smark; /* unnecessary */
2854
2855         setstackmark(&smark);
2856         result->fd = -1;
2857         result->buf = NULL;
2858         result->nleft = 0;
2859         result->jp = NULL;
2860         if (n == NULL) {
2861                 exitstatus = 0;
2862                 goto out;
2863         }
2864         exitstatus = 0;
2865         if (pipe(pip) < 0)
2866                 error("Pipe call failed");
2867         jp = makejob(n, 1);
2868         if (forkshell(jp, n, FORK_NOJOB) == 0) {
2869                 FORCEINTON;
2870                 close(pip[0]);
2871                 if (pip[1] != 1) {
2872                         close(1);
2873                         dup_as_newfd(pip[1], 1);
2874                         close(pip[1]);
2875                 }
2876                 eflag = 0;
2877                 evaltree(n, EV_EXIT);
2878         }
2879         close(pip[1]);
2880         result->fd = pip[0];
2881         result->jp = jp;
2882   out:
2883         popstackmark(&smark);
2884         TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n",
2885                    result->fd, result->buf, result->nleft, result->jp));
2886 }
2887
2888
2889 /*
2890  * Execute a simple command.
2891  */
2892
2893 /*
2894  * Search for a command.  This is called before we fork so that the
2895  * location of the command will be available in the parent as well as
2896  * the child.  The check for "goodname" is an overly conservative
2897  * check that the name will not be subject to expansion.
2898  */
2899
2900 static void prehash(union node *n)
2901 {
2902         struct cmdentry entry;
2903
2904         if (n->type == NCMD && n->ncmd.args)
2905                 if (goodname(n->ncmd.args->narg.text))
2906                         find_command(n->ncmd.args->narg.text, &entry, 0, pathval());
2907 }
2908
2909
2910 /*
2911  * Builtin commands.  Builtin commands whose functions are closely
2912  * tied to evaluation are implemented here.
2913  */
2914
2915 /*
2916  * No command given, or a bltin command with no arguments.  Set the
2917  * specified variables.
2918  */
2919
2920 int bltincmd(int argc, char **argv)
2921 {
2922         /*
2923          * Preserve exitstatus of a previous possible redirection
2924          * as POSIX mandates
2925          */
2926         return exitstatus;
2927 }
2928
2929
2930 /*
2931  * Handle break and continue commands.  Break, continue, and return are
2932  * all handled by setting the evalskip flag.  The evaluation routines
2933  * above all check this flag, and if it is set they start skipping
2934  * commands rather than executing them.  The variable skipcount is
2935  * the number of loops to break/continue, or the number of function
2936  * levels to return.  (The latter is always 1.)  It should probably
2937  * be an error to break out of more loops than exist, but it isn't
2938  * in the standard shell so we don't make it one here.
2939  */
2940
2941 static int breakcmd(int argc, char **argv)
2942 {
2943         int n = argc > 1 ? number(argv[1]) : 1;
2944
2945         if (n <= 0)
2946                 error("Illegal number: %s", argv[1]);
2947         if (n > loopnest)
2948                 n = loopnest;
2949         if (n > 0) {
2950                 evalskip = (**argv == 'c') ? SKIPCONT : SKIPBREAK;
2951                 skipcount = n;
2952         }
2953         return 0;
2954 }
2955
2956
2957 /*
2958  * The return command.
2959  */
2960
2961 static int returncmd(int argc, char **argv)
2962 {
2963         int ret = argc > 1 ? number(argv[1]) : oexitstatus;
2964
2965         if (funcnest) {
2966                 evalskip = SKIPFUNC;
2967                 skipcount = 1;
2968                 return ret;
2969         } else {
2970                 /* Do what ksh does; skip the rest of the file */
2971                 evalskip = SKIPFILE;
2972                 skipcount = 1;
2973                 return ret;
2974         }
2975 }
2976
2977
2978 #ifndef CONFIG_FALSE
2979 static int false_main(int argc, char **argv)
2980 {
2981         return 1;
2982 }
2983 #endif
2984
2985 #ifndef CONFIG_TRUE
2986 static int true_main(int argc, char **argv)
2987 {
2988         return 0;
2989 }
2990 #endif
2991
2992 /*
2993  * Controls whether the shell is interactive or not.
2994  */
2995
2996 static void setsignal(int signo);
2997
2998 #ifdef CONFIG_ASH_MAIL
2999 static void chkmail(int silent);
3000 #endif
3001
3002 static void setinteractive(int on)
3003 {
3004         static int is_interactive;
3005         static int do_banner = 0;
3006
3007         if (on == is_interactive)
3008                 return;
3009         setsignal(SIGINT);
3010         setsignal(SIGQUIT);
3011         setsignal(SIGTERM);
3012 #ifdef CONFIG_ASH_MAIL
3013         chkmail(1);
3014 #endif
3015         is_interactive = on;
3016         if (do_banner == 0 && is_interactive) {
3017                 /* Looks like they want an interactive shell */
3018 #ifndef CONFIG_FEATURE_SH_EXTRA_QUIET
3019                 printf("\n\n" BB_BANNER " Built-in shell (ash)\n");
3020                 printf("Enter 'help' for a list of built-in commands.\n\n");
3021 #endif
3022                 do_banner = 1;
3023         }
3024 }
3025
3026 static void optschanged(void)
3027 {
3028         setinteractive(iflag);
3029         setjobctl(mflag);
3030 }
3031
3032
3033 static int execcmd(int argc, char **argv)
3034 {
3035         if (argc > 1) {
3036                 struct strlist *sp;
3037
3038                 iflag = 0;              /* exit on error */
3039                 mflag = 0;
3040                 optschanged();
3041                 for (sp = cmdenviron; sp; sp = sp->next)
3042                         setvareq(sp->text, VEXPORT | VSTACK);
3043                 shellexec(argv + 1, environment(), pathval(), 0);
3044         }
3045         return 0;
3046 }
3047
3048 static void eprintlist(struct strlist *sp)
3049 {
3050         for (; sp; sp = sp->next) {
3051                 out2fmt(" %s", sp->text);
3052         }
3053 }
3054
3055 /*
3056  * Exec a program.  Never returns.  If you change this routine, you may
3057  * have to change the find_command routine as well.
3058  */
3059
3060 static const char *pathopt;     /* set by padvance */
3061
3062 static void shellexec(char **argv, char **envp, const char *path, int idx)
3063 {
3064         char *cmdname;
3065         int e;
3066
3067         if (strchr(argv[0], '/') != NULL
3068 #ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL
3069                 || find_applet_by_name(argv[0])
3070 #endif 
3071         )
3072         {
3073                 tryexec(argv[0], argv, envp);
3074                 e = errno;
3075         } else {
3076                 e = ENOENT;
3077                 while ((cmdname = padvance(&path, argv[0])) != NULL) {
3078                         if (--idx < 0 && pathopt == NULL) {
3079                                 tryexec(cmdname, argv, envp);
3080                                 if (errno != ENOENT && errno != ENOTDIR)
3081                                         e = errno;
3082                         }
3083                         stunalloc(cmdname);
3084                 }
3085         }
3086
3087         /* Map to POSIX errors */
3088         switch (e) {
3089         case EACCES:
3090                 exerrno = 126;
3091                 break;
3092         case ENOENT:
3093                 exerrno = 127;
3094                 break;
3095         default:
3096                 exerrno = 2;
3097                 break;
3098         }
3099         exerror(EXEXEC, "%s: %s", argv[0], errmsg(e, E_EXEC));
3100         /* NOTREACHED */
3101 }
3102
3103 /*
3104  * Clear traps on a fork.
3105  */
3106 static void clear_traps(void)
3107 {
3108         char **tp;
3109
3110         for (tp = trap; tp < &trap[NSIG]; tp++) {
3111                 if (*tp && **tp) {      /* trap not NULL or SIG_IGN */
3112                         INTOFF;
3113                         free(*tp);
3114                         *tp = NULL;
3115                         if (tp != &trap[0])
3116                                 setsignal(tp - trap);
3117                         INTON;
3118                 }
3119         }
3120 }
3121
3122
3123 static int preadbuffer(void);
3124 static void pushfile(void);
3125
3126 /*
3127  * Read a character from the script, returning PEOF on end of file.
3128  * Nul characters in the input are silently discarded.
3129  */
3130
3131 #ifndef CONFIG_ASH_OPTIMIZE_FOR_SIZE
3132 #define pgetc_macro()   (--parsenleft >= 0? *parsenextc++ : preadbuffer())
3133 static int pgetc(void)
3134 {
3135         return pgetc_macro();
3136 }
3137 #else
3138 static int pgetc_macro(void)
3139 {
3140         return --parsenleft >= 0 ? *parsenextc++ : preadbuffer();
3141 }
3142
3143 static inline int pgetc(void)
3144 {
3145         return pgetc_macro();
3146 }
3147 #endif
3148
3149
3150 /*
3151  * Undo the last call to pgetc.  Only one character may be pushed back.
3152  * PEOF may be pushed back.
3153  */
3154
3155 static void pungetc(void)
3156 {
3157         parsenleft++;
3158         parsenextc--;
3159 }
3160
3161
3162 static void popfile(void)
3163 {
3164         struct parsefile *pf = parsefile;
3165
3166         INTOFF;
3167         if (pf->fd >= 0)
3168                 close(pf->fd);
3169         free(pf->buf);
3170         while (pf->strpush)
3171                 popstring();
3172         parsefile = pf->prev;
3173         free(pf);
3174         parsenleft = parsefile->nleft;
3175         parselleft = parsefile->lleft;
3176         parsenextc = parsefile->nextc;
3177         plinno = parsefile->linno;
3178         INTON;
3179 }
3180
3181
3182 /*
3183  * Return to top level.
3184  */
3185
3186 static void popallfiles(void)
3187 {
3188         while (parsefile != &basepf)
3189                 popfile();
3190 }
3191
3192 /*
3193  * Close the file(s) that the shell is reading commands from.  Called
3194  * after a fork is done.
3195  */
3196
3197 static void closescript(void)
3198 {
3199         popallfiles();
3200         if (parsefile->fd > 0) {
3201                 close(parsefile->fd);
3202                 parsefile->fd = 0;
3203         }
3204 }
3205
3206
3207 /*
3208  * Like setinputfile, but takes an open file descriptor.  Call this with
3209  * interrupts off.
3210  */
3211
3212 static void setinputfd(int fd, int push)
3213 {
3214         (void) fcntl(fd, F_SETFD, FD_CLOEXEC);
3215         if (push) {
3216                 pushfile();
3217                 parsefile->buf = 0;
3218         } else {
3219                 closescript();
3220                 while (parsefile->strpush)
3221                         popstring();
3222         }
3223         parsefile->fd = fd;
3224         if (parsefile->buf == NULL)
3225                 parsefile->buf = xmalloc(BUFSIZ);
3226         parselleft = parsenleft = 0;
3227         plinno = 1;
3228 }
3229
3230
3231 /*
3232  * Set the input to take input from a file.  If push is set, push the
3233  * old input onto the stack first.
3234  */
3235
3236 static void setinputfile(const char *fname, int push)
3237 {
3238         int fd;
3239         int myfileno2;
3240
3241         INTOFF;
3242         if ((fd = open(fname, O_RDONLY)) < 0)
3243                 error("Can't open %s", fname);
3244         if (fd < 10) {
3245                 myfileno2 = dup_as_newfd(fd, 10);
3246                 close(fd);
3247                 if (myfileno2 < 0)
3248                         error("Out of file descriptors");
3249                 fd = myfileno2;
3250         }
3251         setinputfd(fd, push);
3252         INTON;
3253 }
3254
3255
3256 static void tryexec(char *cmd, char **argv, char **envp)
3257 {
3258         int repeated = 0;
3259
3260 #ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL
3261         char *name = cmd;
3262         char **argv_l = argv;
3263         int argc_l;
3264
3265 #ifdef CONFIG_FEATURE_SH_APPLETS_ALWAYS_WIN
3266         name = get_last_path_component(name);
3267 #endif
3268         argv_l = envp;
3269         for (argc_l = 0; *argv_l != NULL; argv_l++, argc_l++)
3270                 putenv(*argv_l);
3271         argv_l = argv;
3272         for (argc_l = 0; *argv_l != NULL; argv_l++, argc_l++)
3273                 optind = 1;
3274         run_applet_by_name(name, argc_l, argv);
3275 #endif
3276   repeat:
3277         execve(cmd, argv, envp);
3278         if (repeated++) {
3279                 free(argv);
3280         } else if (errno == ENOEXEC) {
3281                 char **ap;
3282                 char **new;
3283
3284                 for (ap = argv; *ap; ap++);
3285                 ap = new = xmalloc((ap - argv + 2) * sizeof(char *));
3286                 *ap++ = cmd = "/bin/sh";
3287                 while ((*ap++ = *argv++));
3288                 argv = new;
3289                 goto repeat;
3290         }
3291 }
3292
3293 static char *commandtext(const union node *);
3294
3295 /*
3296  * Do a path search.  The variable path (passed by reference) should be
3297  * set to the start of the path before the first call; padvance will update
3298  * this value as it proceeds.  Successive calls to padvance will return
3299  * the possible path expansions in sequence.  If an option (indicated by
3300  * a percent sign) appears in the path entry then the global variable
3301  * pathopt will be set to point to it; otherwise pathopt will be set to
3302  * NULL.
3303  */
3304
3305 static const char *pathopt;
3306
3307 static void growstackblock(void);
3308
3309
3310 static char *padvance(const char **path, const char *name)
3311 {
3312         const char *p;
3313         char *q;
3314         const char *start;
3315         int len;
3316
3317         if (*path == NULL)
3318                 return NULL;
3319         start = *path;
3320         for (p = start; *p && *p != ':' && *p != '%'; p++);
3321         len = p - start + strlen(name) + 2;     /* "2" is for '/' and '\0' */
3322         while (stackblocksize() < len)
3323                 growstackblock();
3324         q = stackblock();
3325         if (p != start) {
3326                 memcpy(q, start, p - start);
3327                 q += p - start;
3328                 *q++ = '/';
3329         }
3330         strcpy(q, name);
3331         pathopt = NULL;
3332         if (*p == '%') {
3333                 pathopt = ++p;
3334                 while (*p && *p != ':')
3335                         p++;
3336         }
3337         if (*p == ':')
3338                 *path = p + 1;
3339         else
3340                 *path = NULL;
3341         return stalloc(len);
3342 }
3343
3344 /*
3345  * Wrapper around strcmp for qsort/bsearch/...
3346  */
3347 static int pstrcmp(const void *a, const void *b)
3348 {
3349         return strcmp((const char *) a, (*(const char *const *) b) + 1);
3350 }
3351
3352 /*
3353  * Find a keyword is in a sorted array.
3354  */
3355
3356 static const char *const *findkwd(const char *s)
3357 {
3358         return bsearch(s, tokname_array + KWDOFFSET,
3359                                    (sizeof(tokname_array) / sizeof(const char *)) - KWDOFFSET,
3360                                    sizeof(const char *), pstrcmp);
3361 }
3362
3363
3364 /*** Command hashing code ***/
3365
3366 static int hashcmd(int argc, char **argv)
3367 {
3368         struct tblentry **pp;
3369         struct tblentry *cmdp;
3370         int c;
3371         int verbose;
3372         struct cmdentry entry;
3373         char *name;
3374
3375 #ifdef CONFIG_ASH_ALIAS
3376         const struct alias *ap;
3377 #endif
3378
3379         verbose = 0;
3380         while ((c = nextopt("rvV")) != '\0') {
3381                 if (c == 'r') {
3382                         clearcmdentry(0);
3383                         return 0;
3384                 } else if (c == 'v' || c == 'V') {
3385                         verbose = c;
3386                 }
3387         }
3388         if (*argptr == NULL) {
3389                 for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
3390                         for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
3391                                 if (cmdp->cmdtype != CMDBUILTIN) {
3392                                         printentry(cmdp, verbose);
3393                                 }
3394                         }
3395                 }
3396                 return 0;
3397         }
3398         c = 0;
3399         while ((name = *argptr++) != NULL) {
3400                 if ((cmdp = cmdlookup(name, 0)) != NULL
3401                         && (cmdp->cmdtype == CMDNORMAL
3402                                 || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0)))
3403                         delete_cmd_entry();
3404 #ifdef CONFIG_ASH_ALIAS
3405                 /* Then look at the aliases */
3406                 if ((ap = *__lookupalias(name)) != NULL) {
3407                         if (verbose == 'v')
3408                                 printf("%s is an alias for %s\n", name, ap->val);
3409                         else
3410                                 printalias(ap);
3411                         continue;
3412                 }
3413 #endif
3414                 /* First look at the keywords */
3415                 if (findkwd(name) != 0) {
3416                         if (verbose == 'v')
3417                                 printf("%s is a shell keyword\n", name);
3418                         else
3419                                 puts(name);
3420                         continue;
3421                 }
3422
3423                 find_command(name, &entry, DO_ERR, pathval());
3424                 if (entry.cmdtype == CMDUNKNOWN)
3425                         c = 1;
3426                 else if (verbose) {
3427                         cmdp = cmdlookup(name, 0);
3428                         if (cmdp)
3429                                 printentry(cmdp, verbose == 'v');
3430                         flushall();
3431                 }
3432         }
3433         return c;
3434 }
3435
3436 static void printentry(struct tblentry *cmdp, int verbose)
3437 {
3438         int idx;
3439         const char *path;
3440         char *name;
3441
3442         printf("%s%s", cmdp->cmdname, (verbose ? " is " : ""));
3443         if (cmdp->cmdtype == CMDNORMAL) {
3444                 idx = cmdp->param.index;
3445                 path = pathval();
3446                 do {
3447                         name = padvance(&path, cmdp->cmdname);
3448                         stunalloc(name);
3449                 } while (--idx >= 0);
3450                 if (verbose)
3451                         out1str(name);
3452         } else if (cmdp->cmdtype == CMDBUILTIN) {
3453                 if (verbose)
3454                         out1str("a shell builtin");
3455         } else if (cmdp->cmdtype == CMDFUNCTION) {
3456                 if (verbose) {
3457                         INTOFF;
3458                         out1str("a function\n");
3459                         name = commandtext(cmdp->param.func);
3460                         printf("%s() {\n %s\n}", cmdp->cmdname, name);
3461                         free(name);
3462                         INTON;
3463                 }
3464 #ifdef DEBUG
3465         } else {
3466                 error("internal error: cmdtype %d", cmdp->cmdtype);
3467 #endif
3468         }
3469         puts(cmdp->rehash ? "*" : nullstr);
3470 }
3471
3472
3473
3474 /*** List the available builtins ***/
3475
3476
3477 static int helpcmd(int argc, char **argv)
3478 {
3479         int col, i;
3480
3481         printf("\nBuilt-in commands:\n-------------------\n");
3482         for (col = 0, i = 0; i < NUMBUILTINS; i++) {
3483                 col += printf("%c%s", ((col == 0) ? '\t' : ' '),
3484                                           builtincmds[i].name + 1);
3485                 if (col > 60) {
3486                         printf("\n");
3487                         col = 0;
3488                 }
3489         }
3490 #ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL
3491         {
3492                 extern const struct BB_applet applets[];
3493                 extern const size_t NUM_APPLETS;
3494
3495                 for (i = 0; i < NUM_APPLETS; i++) {
3496
3497                         col += printf("%c%s", ((col == 0) ? '\t' : ' '), applets[i].name);
3498                         if (col > 60) {
3499                                 printf("\n");
3500                                 col = 0;
3501                         }
3502                 }
3503         }
3504 #endif
3505         printf("\n\n");
3506         return EXIT_SUCCESS;
3507 }
3508
3509 /*
3510  * Resolve a command name.  If you change this routine, you may have to
3511  * change the shellexec routine as well.
3512  */
3513
3514 static int prefix(const char *, const char *);
3515
3516 static void
3517 find_command(const char *name, struct cmdentry *entry, int act,
3518                          const char *path)
3519 {
3520         struct tblentry *cmdp;
3521         int idx;
3522         int prev;
3523         char *fullname;
3524         struct stat statb;
3525         int e;
3526         int bltin;
3527         int firstchange;
3528         int updatetbl;
3529         int regular;
3530         struct builtincmd *bcmd;
3531
3532         /* If name contains a slash, don't use the hash table */
3533         if (strchr(name, '/') != NULL) {
3534                 if (act & DO_ABS) {
3535                         while (stat(name, &statb) < 0) {
3536                                 if (errno != ENOENT && errno != ENOTDIR)
3537                                         e = errno;
3538                                 entry->cmdtype = CMDUNKNOWN;
3539                                 entry->u.index = -1;
3540                                 return;
3541                         }
3542                         entry->cmdtype = CMDNORMAL;
3543                         entry->u.index = -1;
3544                         return;
3545                 }
3546                 entry->cmdtype = CMDNORMAL;
3547                 entry->u.index = 0;
3548                 return;
3549         }
3550
3551 #ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL
3552         if (find_applet_by_name(name)) {
3553                 entry->cmdtype = CMDNORMAL;
3554                 entry->u.index = -1;
3555                 return;
3556         }
3557 #endif
3558
3559         updatetbl = 1;
3560         if (act & DO_BRUTE) {
3561                 firstchange = path_change(path, &bltin);
3562         } else {
3563                 bltin = builtinloc;
3564                 firstchange = 9999;
3565         }
3566
3567         /* If name is in the table, and not invalidated by cd, we're done */
3568         if ((cmdp = cmdlookup(name, 0)) != NULL && cmdp->rehash == 0) {
3569                 if (cmdp->cmdtype == CMDFUNCTION) {
3570                         if (act & DO_NOFUN) {
3571                                 updatetbl = 0;
3572                         } else {
3573                                 goto success;
3574                         }
3575                 } else if (act & DO_BRUTE) {
3576                         if ((cmdp->cmdtype == CMDNORMAL &&
3577                                  cmdp->param.index >= firstchange) ||
3578                                 (cmdp->cmdtype == CMDBUILTIN &&
3579                                  ((builtinloc < 0 && bltin >= 0) ?
3580                                   bltin : builtinloc) >= firstchange)) {
3581                                 /* need to recompute the entry */
3582                         } else {
3583                                 goto success;
3584                         }
3585                 } else {
3586                         goto success;
3587                 }
3588         }
3589
3590         bcmd = find_builtin(name);
3591         regular = bcmd && IS_BUILTIN_REGULAR(bcmd);
3592
3593         if (regular) {
3594                 if (cmdp && (cmdp->cmdtype == CMDBUILTIN)) {
3595                         goto success;
3596                 }
3597         } else if (act & DO_BRUTE) {
3598                 if (firstchange == 0) {
3599                         updatetbl = 0;
3600                 }
3601         }
3602
3603         /* If %builtin not in path, check for builtin next */
3604         if (regular || (bltin < 0 && bcmd)) {
3605           builtin:
3606                 if (!updatetbl) {
3607                         entry->cmdtype = CMDBUILTIN;
3608                         entry->u.cmd = bcmd;
3609                         return;
3610                 }
3611                 INTOFF;
3612                 cmdp = cmdlookup(name, 1);
3613                 cmdp->cmdtype = CMDBUILTIN;
3614                 cmdp->param.cmd = bcmd;
3615                 INTON;
3616                 goto success;
3617         }
3618
3619         /* We have to search path. */
3620         prev = -1;                      /* where to start */
3621         if (cmdp && cmdp->rehash) {     /* doing a rehash */
3622                 if (cmdp->cmdtype == CMDBUILTIN)
3623                         prev = builtinloc;
3624                 else
3625                         prev = cmdp->param.index;
3626         }
3627
3628         e = ENOENT;
3629         idx = -1;
3630   loop:
3631         while ((fullname = padvance(&path, name)) != NULL) {
3632                 stunalloc(fullname);
3633                 idx++;
3634                 if (idx >= firstchange) {
3635                         updatetbl = 0;
3636                 }
3637                 if (pathopt) {
3638                         if (prefix("builtin", pathopt)) {
3639                                 if ((bcmd = find_builtin(name))) {
3640                                         goto builtin;
3641                                 }
3642                                 continue;
3643                         } else if (!(act & DO_NOFUN) && prefix("func", pathopt)) {
3644                                 /* handled below */
3645                         } else {
3646                                 continue;       /* ignore unimplemented options */
3647                         }
3648                 }
3649                 /* if rehash, don't redo absolute path names */
3650                 if (fullname[0] == '/' && idx <= prev && idx < firstchange) {
3651                         if (idx < prev)
3652                                 continue;
3653                         TRACE(("searchexec \"%s\": no change\n", name));
3654                         goto success;
3655                 }
3656                 while (stat(fullname, &statb) < 0) {
3657                         if (errno != ENOENT && errno != ENOTDIR)
3658                                 e = errno;
3659                         goto loop;
3660                 }
3661                 e = EACCES;             /* if we fail, this will be the error */
3662                 if (!S_ISREG(statb.st_mode))
3663                         continue;
3664                 if (pathopt) {  /* this is a %func directory */
3665                         stalloc(strlen(fullname) + 1);
3666                         readcmdfile(fullname);
3667                         if ((cmdp = cmdlookup(name, 0)) == NULL
3668                                 || cmdp->cmdtype != CMDFUNCTION)
3669                                 error("%s not defined in %s", name, fullname);
3670                         stunalloc(fullname);
3671                         goto success;
3672                 }
3673                 TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
3674                 /* If we aren't called with DO_BRUTE and cmdp is set, it must
3675                    be a function and we're being called with DO_NOFUN */
3676                 if (!updatetbl) {
3677                         entry->cmdtype = CMDNORMAL;
3678                         entry->u.index = idx;
3679                         return;
3680                 }
3681                 INTOFF;
3682                 cmdp = cmdlookup(name, 1);
3683                 cmdp->cmdtype = CMDNORMAL;
3684                 cmdp->param.index = idx;
3685                 INTON;
3686                 goto success;
3687         }
3688
3689         /* We failed.  If there was an entry for this command, delete it */
3690         if (cmdp && updatetbl)
3691                 delete_cmd_entry();
3692         if (act & DO_ERR)
3693                 out2fmt("%s: %s\n", name, errmsg(e, E_EXEC));
3694         entry->cmdtype = CMDUNKNOWN;
3695         return;
3696
3697   success:
3698         cmdp->rehash = 0;
3699         entry->cmdtype = cmdp->cmdtype;
3700         entry->u = cmdp->param;
3701 }
3702
3703
3704
3705 /*
3706  * Search the table of builtin commands.
3707  */
3708
3709 static struct builtincmd *find_builtin(const char *name)
3710 {
3711         struct builtincmd *bp;
3712
3713         bp = bsearch(name, builtincmds, NUMBUILTINS, sizeof(struct builtincmd),
3714                                  pstrcmp);
3715         return bp;
3716 }
3717
3718
3719 /*
3720  * Called when a cd is done.  Marks all commands so the next time they
3721  * are executed they will be rehashed.
3722  */
3723
3724 static void hashcd(void)
3725 {
3726         struct tblentry **pp;
3727         struct tblentry *cmdp;
3728
3729         for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
3730                 for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
3731                         if (cmdp->cmdtype == CMDNORMAL
3732                                 || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0))
3733                                 cmdp->rehash = 1;
3734                 }
3735         }
3736 }
3737
3738
3739
3740 /*
3741  * Called before PATH is changed.  The argument is the new value of PATH;
3742  * pathval() still returns the old value at this point.  Called with
3743  * interrupts off.
3744  */
3745
3746 static void changepath(const char *newval)
3747 {
3748         int firstchange;
3749         int bltin;
3750
3751         firstchange = path_change(newval, &bltin);
3752         if (builtinloc < 0 && bltin >= 0)
3753                 builtinloc = bltin;     /* zap builtins */
3754         clearcmdentry(firstchange);
3755         builtinloc = bltin;
3756         /* Ensure that getenv("PATH") stays current */
3757         setenv("PATH", newval, 1);
3758 }
3759
3760
3761 /*
3762  * Clear out command entries.  The argument specifies the first entry in
3763  * PATH which has changed.
3764  */
3765
3766 static void clearcmdentry(int firstchange)
3767 {
3768         struct tblentry **tblp;
3769         struct tblentry **pp;
3770         struct tblentry *cmdp;
3771
3772         INTOFF;
3773         for (tblp = cmdtable; tblp < &cmdtable[CMDTABLESIZE]; tblp++) {
3774                 pp = tblp;
3775                 while ((cmdp = *pp) != NULL) {
3776                         if ((cmdp->cmdtype == CMDNORMAL &&
3777                                  cmdp->param.index >= firstchange)
3778                                 || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= firstchange)) {
3779                                 *pp = cmdp->next;
3780                                 free(cmdp);
3781                         } else {
3782                                 pp = &cmdp->next;
3783                         }
3784                 }
3785         }
3786         INTON;
3787 }
3788
3789
3790 /*
3791  * Locate a command in the command hash table.  If "add" is nonzero,
3792  * add the command to the table if it is not already present.  The
3793  * variable "lastcmdentry" is set to point to the address of the link
3794  * pointing to the entry, so that delete_cmd_entry can delete the
3795  * entry.
3796  */
3797
3798 static struct tblentry **lastcmdentry;
3799
3800 static struct tblentry *cmdlookup(const char *name, int add)
3801 {
3802         int hashval;
3803         const char *p;
3804         struct tblentry *cmdp;
3805         struct tblentry **pp;
3806
3807         p = name;
3808         hashval = *p << 4;
3809         while (*p)
3810                 hashval += *p++;
3811         hashval &= 0x7FFF;
3812         pp = &cmdtable[hashval % CMDTABLESIZE];
3813         for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
3814                 if (equal(cmdp->cmdname, name))
3815                         break;
3816                 pp = &cmdp->next;
3817         }
3818         if (add && cmdp == NULL) {
3819                 INTOFF;
3820                 cmdp = *pp = xmalloc(sizeof(struct tblentry) - ARB
3821                                                          + strlen(name) + 1);
3822                 cmdp->next = NULL;
3823                 cmdp->cmdtype = CMDUNKNOWN;
3824                 cmdp->rehash = 0;
3825                 strcpy(cmdp->cmdname, name);
3826                 INTON;
3827         }
3828         lastcmdentry = pp;
3829         return cmdp;
3830 }
3831
3832 /*
3833  * Delete the command entry returned on the last lookup.
3834  */
3835
3836 static void delete_cmd_entry(void)
3837 {
3838         struct tblentry *cmdp;
3839
3840         INTOFF;
3841         cmdp = *lastcmdentry;
3842         *lastcmdentry = cmdp->next;
3843         free(cmdp);
3844         INTON;
3845 }
3846
3847
3848
3849
3850
3851 static const unsigned char nodesize[26] = {
3852         ALIGN(sizeof(struct nbinary)),
3853         ALIGN(sizeof(struct ncmd)),
3854         ALIGN(sizeof(struct npipe)),
3855         ALIGN(sizeof(struct nredir)),
3856         ALIGN(sizeof(struct nredir)),
3857         ALIGN(sizeof(struct nredir)),
3858         ALIGN(sizeof(struct nbinary)),
3859         ALIGN(sizeof(struct nbinary)),
3860         ALIGN(sizeof(struct nif)),
3861         ALIGN(sizeof(struct nbinary)),
3862         ALIGN(sizeof(struct nbinary)),
3863         ALIGN(sizeof(struct nfor)),
3864         ALIGN(sizeof(struct ncase)),
3865         ALIGN(sizeof(struct nclist)),
3866         ALIGN(sizeof(struct narg)),
3867         ALIGN(sizeof(struct narg)),
3868         ALIGN(sizeof(struct nfile)),
3869         ALIGN(sizeof(struct nfile)),
3870         ALIGN(sizeof(struct nfile)),
3871         ALIGN(sizeof(struct nfile)),
3872         ALIGN(sizeof(struct nfile)),
3873         ALIGN(sizeof(struct ndup)),
3874         ALIGN(sizeof(struct ndup)),
3875         ALIGN(sizeof(struct nhere)),
3876         ALIGN(sizeof(struct nhere)),
3877         ALIGN(sizeof(struct nnot)),
3878 };
3879
3880
3881
3882 /*
3883  * Delete a function if it exists.
3884  */
3885
3886 static void unsetfunc(char *name)
3887 {
3888         struct tblentry *cmdp;
3889
3890         if ((cmdp = cmdlookup(name, 0)) != NULL && cmdp->cmdtype == CMDFUNCTION) {
3891                 free(cmdp->param.func);
3892                 delete_cmd_entry();
3893         }
3894 }
3895
3896
3897 /*
3898  * Locate and print what a word is...
3899  */
3900
3901 static int typecmd(int argc, char **argv)
3902 {
3903         int i;
3904         int err = 0;
3905         char *argv_a[2];
3906
3907         argv_a[1] = 0;
3908
3909         for (i = 1; i < argc; i++) {
3910                 argv_a[0] = argv[i];
3911                 argptr = argv_a;
3912                 optptr = "v";
3913                 err |= hashcmd(argc, argv);
3914         }
3915         return err;
3916 }
3917
3918 #ifdef CONFIG_ASH_CMDCMD
3919 static int commandcmd(int argc, char **argv)
3920 {
3921         int c;
3922         int default_path = 0;
3923         int verify_only = 0;
3924         int verbose_verify_only = 0;
3925
3926         while ((c = nextopt("pvV")) != '\0')
3927                 switch (c) {
3928                 case 'p':
3929                         default_path = 1;
3930                         break;
3931                 case 'v':
3932                         verify_only = 1;
3933                         break;
3934                 case 'V':
3935                         verbose_verify_only = 1;
3936                         break;
3937                 }
3938
3939         if (default_path + verify_only + verbose_verify_only > 1 || !*argptr) {
3940                 out2str("command [-p] command [arg ...]\n"
3941                                 "command {-v|-V} command\n");
3942                 return EX_USAGE;
3943         }
3944
3945         if (verify_only || verbose_verify_only) {
3946                 char *argv_a[2];
3947
3948                 argv_a[1] = 0;
3949                 argv_a[0] = *argptr;
3950                 argptr = argv_a;
3951                 optptr = verbose_verify_only ? "v" : "V";       /* reverse special */
3952                 return hashcmd(argc, argv);
3953         }
3954
3955         return 0;
3956 }
3957 #endif
3958
3959 static int path_change(const char *newval, int *bltin)
3960 {
3961         const char *old, *new;
3962         int idx;
3963         int firstchange;
3964
3965         old = pathval();
3966         new = newval;
3967         firstchange = 9999;     /* assume no change */
3968         idx = 0;
3969         *bltin = -1;
3970         for (;;) {
3971                 if (*old != *new) {
3972                         firstchange = idx;
3973                         if ((*old == '\0' && *new == ':')
3974                                 || (*old == ':' && *new == '\0'))
3975                                 firstchange++;
3976                         old = new;      /* ignore subsequent differences */
3977                 }
3978                 if (*new == '\0')
3979                         break;
3980                 if (*new == '%' && *bltin < 0 && prefix("builtin", new + 1))
3981                         *bltin = idx;
3982                 if (*new == ':') {
3983                         idx++;
3984                 }
3985                 new++, old++;
3986         }
3987         if (builtinloc >= 0 && *bltin < 0)
3988                 firstchange = 0;
3989         return firstchange;
3990 }
3991
3992 /*
3993  * Routines to expand arguments to commands.  We have to deal with
3994  * backquotes, shell variables, and file metacharacters.
3995  */
3996 /*
3997  * _rmescape() flags
3998  */
3999 #define RMESCAPE_ALLOC  0x1     /* Allocate a new string */
4000 #define RMESCAPE_GLOB   0x2     /* Add backslashes for glob */
4001
4002 /*
4003  * Structure specifying which parts of the string should be searched
4004  * for IFS characters.
4005  */
4006
4007 struct ifsregion {
4008         struct ifsregion *next; /* next region in list */
4009         int begoff;                     /* offset of start of region */
4010         int endoff;                     /* offset of end of region */
4011         int nulonly;            /* search for nul bytes only */
4012 };
4013
4014
4015 static char *expdest;   /* output of current string */
4016 static struct nodelist *argbackq;       /* list of back quote expressions */
4017 static struct ifsregion ifsfirst;       /* first struct in list of ifs regions */
4018 static struct ifsregion *ifslastp;      /* last struct in list */
4019 static struct arglist exparg;   /* holds expanded arg list */
4020
4021 static void argstr(char *, int);
4022 static char *exptilde(char *, int);
4023 static void expbackq(union node *, int, int);
4024 static int subevalvar(char *, char *, int, int, int, int, int);
4025 static int varisset(char *, int);
4026 static void strtodest(const char *, int, int);
4027 static void varvalue(char *, int, int);
4028 static void recordregion(int, int, int);
4029 static void removerecordregions(int);
4030 static void ifsbreakup(char *, struct arglist *);
4031 static void ifsfree(void);
4032 static void expandmeta(struct strlist *, int);
4033
4034 #if defined(__GLIBC__) && __GLIBC__ >= 2 && !defined(FNMATCH_BROKEN)
4035 #define preglob(p) _rmescapes((p), RMESCAPE_ALLOC | RMESCAPE_GLOB)
4036 #if !defined(GLOB_BROKEN)
4037 static void addglob(const glob_t *);
4038 #endif
4039 #endif
4040 #if !(defined(__GLIBC__) && __GLIBC__ >= 2 && !defined(FNMATCH_BROKEN) && !defined(GLOB_BROKEN))
4041 static void expmeta(char *, char *);
4042 #endif
4043 #if !(defined(__GLIBC__) && __GLIBC__ >= 2 && !defined(FNMATCH_BROKEN) && !defined(GLOB_BROKEN))
4044 static struct strlist *expsort(struct strlist *);
4045 static struct strlist *msort(struct strlist *, int);
4046 #endif
4047 static int patmatch(char *, char *, int);
4048
4049 #if defined(__GLIBC__) && __GLIBC__ >= 2 && !defined(FNMATCH_BROKEN)
4050 static int patmatch2(char *, char *, int);
4051 #else
4052 static int pmatch(char *, char *, int);
4053
4054 #define patmatch2 patmatch
4055 #endif
4056 static char *cvtnum(int, char *);
4057
4058 /*
4059  * Expand shell variables and backquotes inside a here document.
4060  */
4061
4062 /* arg: the document, fd: where to write the expanded version */
4063 static inline void expandhere(union node *arg, int fd)
4064 {
4065         herefd = fd;
4066         expandarg(arg, (struct arglist *) NULL, 0);
4067         xwrite(fd, stackblock(), expdest - stackblock());
4068 }
4069
4070
4071 /*
4072  * Perform variable substitution and command substitution on an argument,
4073  * placing the resulting list of arguments in arglist.  If EXP_FULL is true,
4074  * perform splitting and file name expansion.  When arglist is NULL, perform
4075  * here document expansion.
4076  */
4077
4078 static void expandarg(union node *arg, struct arglist *arglist, int flag)
4079 {
4080         struct strlist *sp;
4081         char *p;
4082
4083         argbackq = arg->narg.backquote;
4084         STARTSTACKSTR(expdest);
4085         ifsfirst.next = NULL;
4086         ifslastp = NULL;
4087         argstr(arg->narg.text, flag);
4088         if (arglist == NULL) {
4089                 return;                 /* here document expanded */
4090         }
4091         STPUTC('\0', expdest);
4092         p = grabstackstr(expdest);
4093         exparg.lastp = &exparg.list;
4094         /*
4095          * TODO - EXP_REDIR
4096          */
4097         if (flag & EXP_FULL) {
4098                 ifsbreakup(p, &exparg);
4099                 *exparg.lastp = NULL;
4100                 exparg.lastp = &exparg.list;
4101                 expandmeta(exparg.list, flag);
4102         } else {
4103                 if (flag & EXP_REDIR)   /*XXX - for now, just remove escapes */
4104                         rmescapes(p);
4105                 sp = (struct strlist *) stalloc(sizeof(struct strlist));
4106                 sp->text = p;
4107                 *exparg.lastp = sp;
4108                 exparg.lastp = &sp->next;
4109         }
4110         ifsfree();
4111         *exparg.lastp = NULL;
4112         if (exparg.list) {
4113                 *arglist->lastp = exparg.list;
4114                 arglist->lastp = exparg.lastp;
4115         }
4116 }
4117
4118
4119 /*
4120  * Expand a variable, and return a pointer to the next character in the
4121  * input string.
4122  */
4123
4124 static inline char *evalvar(char *p, int flag)
4125 {
4126         int subtype;
4127         int varflags;
4128         char *var;
4129         const char *val;
4130         int patloc;
4131         int c;
4132         int set;
4133         int special;
4134         int startloc;
4135         int varlen;
4136         int easy;
4137         int quotes = flag & (EXP_FULL | EXP_CASE);
4138
4139         varflags = *p++;
4140         subtype = varflags & VSTYPE;
4141         var = p;
4142         special = 0;
4143         if (!is_name(*p))
4144                 special = 1;
4145         p = strchr(p, '=') + 1;
4146   again:                                /* jump here after setting a variable with ${var=text} */
4147         if (special) {
4148                 set = varisset(var, varflags & VSNUL);
4149                 val = NULL;
4150         } else {
4151                 val = lookupvar(var);
4152                 if (val == NULL || ((varflags & VSNUL) && val[0] == '\0')) {
4153                         val = NULL;
4154                         set = 0;
4155                 } else
4156                         set = 1;
4157         }
4158         varlen = 0;
4159         startloc = expdest - stackblock();
4160         if (set && subtype != VSPLUS) {
4161                 /* insert the value of the variable */
4162                 if (special) {
4163                         varvalue(var, varflags & VSQUOTE, flag);
4164                         if (subtype == VSLENGTH) {
4165                                 varlen = expdest - stackblock() - startloc;
4166                                 STADJUST(-varlen, expdest);
4167                         }
4168                 } else {
4169                         if (subtype == VSLENGTH) {
4170                                 varlen = strlen(val);
4171                         } else {
4172                                 strtodest(val,
4173                                                   varflags & VSQUOTE ? DQSYNTAX : BASESYNTAX, quotes);
4174                         }
4175                 }
4176         }
4177
4178         if (subtype == VSPLUS)
4179                 set = !set;
4180
4181         easy = ((varflags & VSQUOTE) == 0 ||
4182                         (*var == '@' && shellparam.nparam != 1));
4183
4184
4185         switch (subtype) {
4186         case VSLENGTH:
4187                 expdest = cvtnum(varlen, expdest);
4188                 goto record;
4189
4190         case VSNORMAL:
4191                 if (!easy)
4192                         break;
4193           record:
4194                 recordregion(startloc, expdest - stackblock(), varflags & VSQUOTE);
4195                 break;
4196
4197         case VSPLUS:
4198         case VSMINUS:
4199                 if (!set) {
4200                         argstr(p, flag);
4201                         break;
4202                 }
4203                 if (easy)
4204                         goto record;
4205                 break;
4206
4207         case VSTRIMLEFT:
4208         case VSTRIMLEFTMAX:
4209         case VSTRIMRIGHT:
4210         case VSTRIMRIGHTMAX:
4211                 if (!set)
4212                         break;
4213                 /*
4214                  * Terminate the string and start recording the pattern
4215                  * right after it
4216                  */
4217                 STPUTC('\0', expdest);
4218                 patloc = expdest - stackblock();
4219                 if (subevalvar(p, NULL, patloc, subtype,
4220                                            startloc, varflags, quotes) == 0) {
4221                         int amount = (expdest - stackblock() - patloc) + 1;
4222
4223                         STADJUST(-amount, expdest);
4224                 }
4225                 /* Remove any recorded regions beyond start of variable */
4226                 removerecordregions(startloc);
4227                 goto record;
4228
4229         case VSASSIGN:
4230         case VSQUESTION:
4231                 if (!set) {
4232                         if (subevalvar(p, var, 0, subtype, startloc, varflags, quotes)) {
4233                                 varflags &= ~VSNUL;
4234                                 /*
4235                                  * Remove any recorded regions beyond
4236                                  * start of variable
4237                                  */
4238                                 removerecordregions(startloc);
4239                                 goto again;
4240                         }
4241                         break;
4242                 }
4243                 if (easy)
4244                         goto record;
4245                 break;
4246
4247 #ifdef DEBUG
4248         default:
4249                 abort();
4250 #endif
4251         }
4252
4253         if (subtype != VSNORMAL) {      /* skip to end of alternative */
4254                 int nesting = 1;
4255
4256                 for (;;) {
4257                         if ((c = *p++) == CTLESC)
4258                                 p++;
4259                         else if (c == CTLBACKQ || c == (CTLBACKQ | CTLQUOTE)) {
4260                                 if (set)
4261                                         argbackq = argbackq->next;
4262                         } else if (c == CTLVAR) {
4263                                 if ((*p++ & VSTYPE) != VSNORMAL)
4264                                         nesting++;
4265                         } else if (c == CTLENDVAR) {
4266                                 if (--nesting == 0)
4267                                         break;
4268                         }
4269                 }
4270         }
4271         return p;
4272 }
4273
4274
4275 /*
4276  * Perform variable and command substitution.  If EXP_FULL is set, output CTLESC
4277  * characters to allow for further processing.  Otherwise treat
4278  * $@ like $* since no splitting will be performed.
4279  */
4280
4281 static void argstr(char *p, int flag)
4282 {
4283         char c;
4284         int quotes = flag & (EXP_FULL | EXP_CASE);      /* do CTLESC */
4285         int firsteq = 1;
4286
4287         if (*p == '~' && (flag & (EXP_TILDE | EXP_VARTILDE)))
4288                 p = exptilde(p, flag);
4289         for (;;) {
4290                 switch (c = *p++) {
4291                 case '\0':
4292                 case CTLENDVAR: /* ??? */
4293                         return;
4294                 case CTLQUOTEMARK:
4295                         /* "$@" syntax adherence hack */
4296                         if (p[0] == CTLVAR && p[2] == '@' && p[3] == '=')
4297                                 break;
4298                         if ((flag & EXP_FULL) != 0)
4299                                 STPUTC(c, expdest);
4300                         break;
4301                 case CTLESC:
4302                         if (quotes)
4303                                 STPUTC(c, expdest);
4304                         c = *p++;
4305                         STPUTC(c, expdest);
4306                         break;
4307                 case CTLVAR:
4308                         p = evalvar(p, flag);
4309                         break;
4310                 case CTLBACKQ:
4311                 case CTLBACKQ | CTLQUOTE:
4312                         expbackq(argbackq->n, c & CTLQUOTE, flag);
4313                         argbackq = argbackq->next;
4314                         break;
4315 #ifdef CONFIG_ASH_MATH_SUPPORT
4316                 case CTLENDARI:
4317                         expari(flag);
4318                         break;
4319 #endif
4320                 case ':':
4321                 case '=':
4322                         /*
4323                          * sort of a hack - expand tildes in variable
4324                          * assignments (after the first '=' and after ':'s).
4325                          */
4326                         STPUTC(c, expdest);
4327                         if (flag & EXP_VARTILDE && *p == '~') {
4328                                 if (c == '=') {
4329                                         if (firsteq)
4330                                                 firsteq = 0;
4331                                         else
4332                                                 break;
4333                                 }
4334                                 p = exptilde(p, flag);
4335                         }
4336                         break;
4337                 default:
4338                         STPUTC(c, expdest);
4339                 }
4340         }
4341 }
4342
4343 static char *exptilde(char *p, int flag)
4344 {
4345         char c, *startp = p;
4346         struct passwd *pw;
4347         const char *home;
4348         int quotes = flag & (EXP_FULL | EXP_CASE);
4349
4350         while ((c = *p) != '\0') {
4351                 switch (c) {
4352                 case CTLESC:
4353                         return (startp);
4354                 case CTLQUOTEMARK:
4355                         return (startp);
4356                 case ':':
4357                         if (flag & EXP_VARTILDE)
4358                                 goto done;
4359                         break;
4360                 case '/':
4361                         goto done;
4362                 }
4363                 p++;
4364         }
4365   done:
4366         *p = '\0';
4367         if (*(startp + 1) == '\0') {
4368                 if ((home = lookupvar("HOME")) == NULL)
4369                         goto lose;
4370         } else {
4371                 if ((pw = getpwnam(startp + 1)) == NULL)
4372                         goto lose;
4373                 home = pw->pw_dir;
4374         }
4375         if (*home == '\0')
4376                 goto lose;
4377         *p = c;
4378         strtodest(home, SQSYNTAX, quotes);
4379         return (p);
4380   lose:
4381         *p = c;
4382         return (startp);
4383 }
4384
4385
4386 static void removerecordregions(int endoff)
4387 {
4388         if (ifslastp == NULL)
4389                 return;
4390
4391         if (ifsfirst.endoff > endoff) {
4392                 while (ifsfirst.next != NULL) {
4393                         struct ifsregion *ifsp;
4394
4395                         INTOFF;
4396                         ifsp = ifsfirst.next->next;
4397                         free(ifsfirst.next);
4398                         ifsfirst.next = ifsp;
4399                         INTON;
4400                 }
4401                 if (ifsfirst.begoff > endoff)
4402                         ifslastp = NULL;
4403                 else {
4404                         ifslastp = &ifsfirst;
4405                         ifsfirst.endoff = endoff;
4406                 }
4407                 return;
4408         }
4409
4410         ifslastp = &ifsfirst;
4411         while (ifslastp->next && ifslastp->next->begoff < endoff)
4412                 ifslastp = ifslastp->next;
4413         while (ifslastp->next != NULL) {
4414                 struct ifsregion *ifsp;
4415
4416                 INTOFF;
4417                 ifsp = ifslastp->next->next;
4418                 free(ifslastp->next);
4419                 ifslastp->next = ifsp;
4420                 INTON;
4421         }
4422         if (ifslastp->endoff > endoff)
4423                 ifslastp->endoff = endoff;
4424 }
4425
4426
4427 #ifdef CONFIG_ASH_MATH_SUPPORT
4428 /*
4429  * Expand arithmetic expression.  Backup to start of expression,
4430  * evaluate, place result in (backed up) result, adjust string position.
4431  */
4432 static void expari(int flag)
4433 {
4434         char *p, *start;
4435         int errcode;
4436         int result;
4437         int begoff;
4438         int quotes = flag & (EXP_FULL | EXP_CASE);
4439         int quoted;
4440
4441         /*      ifsfree(); */
4442
4443         /*
4444          * This routine is slightly over-complicated for
4445          * efficiency.  First we make sure there is
4446          * enough space for the result, which may be bigger
4447          * than the expression if we add exponentation.  Next we
4448          * scan backwards looking for the start of arithmetic.  If the
4449          * next previous character is a CTLESC character, then we
4450          * have to rescan starting from the beginning since CTLESC
4451          * characters have to be processed left to right.
4452          */
4453         CHECKSTRSPACE(10, expdest);
4454         USTPUTC('\0', expdest);
4455         start = stackblock();
4456         p = expdest - 1;
4457         while (*p != CTLARI && p >= start)
4458                 --p;
4459         if (*p != CTLARI)
4460                 error("missing CTLARI (shouldn't happen)");
4461         if (p > start && *(p - 1) == CTLESC)
4462                 for (p = start; *p != CTLARI; p++)
4463                         if (*p == CTLESC)
4464                                 p++;
4465
4466         if (p[1] == '"')
4467                 quoted = 1;
4468         else
4469                 quoted = 0;
4470         begoff = p - start;
4471         removerecordregions(begoff);
4472         if (quotes)
4473                 rmescapes(p + 2);
4474         result = arith(p + 2, &errcode);
4475         if (errcode < 0) {
4476                 if (errcode == -2)
4477                         error("divide by zero");
4478                 else
4479                         error("syntax error: \"%s\"\n", p + 2);
4480         }
4481         snprintf(p, 12, "%d", result);
4482         while (*p++);
4483
4484         if (quoted == 0)
4485                 recordregion(begoff, p - 1 - start, 0);
4486         result = expdest - p + 1;
4487         STADJUST(-result, expdest);
4488 }
4489 #endif
4490
4491 /*
4492  * Expand stuff in backwards quotes.
4493  */
4494
4495 static void expbackq(union node *cmd, int quoted, int flag)
4496 {
4497         volatile struct backcmd in;
4498         int i;
4499         char buf[128];
4500         char *p;
4501         char *dest = expdest;
4502         volatile struct ifsregion saveifs;
4503         struct ifsregion *volatile savelastp;
4504         struct nodelist *volatile saveargbackq;
4505         char lastc;
4506         int startloc = dest - stackblock();
4507         int syntax = quoted ? DQSYNTAX : BASESYNTAX;
4508         volatile int saveherefd;
4509         int quotes = flag & (EXP_FULL | EXP_CASE);
4510         struct jmploc jmploc;
4511         struct jmploc *volatile savehandler;
4512         int ex;
4513
4514 #if __GNUC__
4515         /* Avoid longjmp clobbering */
4516         (void) &dest;
4517         (void) &syntax;
4518 #endif
4519
4520         in.fd = -1;
4521         in.buf = 0;
4522         in.jp = 0;
4523
4524         INTOFF;
4525         saveifs = ifsfirst;
4526         savelastp = ifslastp;
4527         saveargbackq = argbackq;
4528         saveherefd = herefd;
4529         herefd = -1;
4530         if ((ex = setjmp(jmploc.loc))) {
4531                 goto err1;
4532         }
4533         savehandler = handler;
4534         handler = &jmploc;
4535         INTON;
4536         p = grabstackstr(dest);
4537         evalbackcmd(cmd, (struct backcmd *) &in);
4538         ungrabstackstr(p, dest);
4539   err1:
4540         INTOFF;
4541         ifsfirst = saveifs;
4542         ifslastp = savelastp;
4543         argbackq = saveargbackq;
4544         herefd = saveherefd;
4545         if (ex) {
4546                 goto err2;
4547         }
4548
4549         p = in.buf;
4550         lastc = '\0';
4551         for (;;) {
4552                 if (--in.nleft < 0) {
4553                         if (in.fd < 0)
4554                                 break;
4555                         i = safe_read(in.fd, buf, sizeof buf);
4556                         TRACE(("expbackq: read returns %d\n", i));
4557                         if (i <= 0)
4558                                 break;
4559                         p = buf;
4560                         in.nleft = i - 1;
4561                 }
4562                 lastc = *p++;
4563                 if (lastc != '\0') {
4564                         if (quotes && SIT(lastc, syntax) == CCTL)
4565                                 STPUTC(CTLESC, dest);
4566                         STPUTC(lastc, dest);
4567                 }
4568         }
4569
4570         /* Eat all trailing newlines */
4571         for (; dest > stackblock() && dest[-1] == '\n';)
4572                 STUNPUTC(dest);
4573
4574   err2:
4575         if (in.fd >= 0)
4576                 close(in.fd);
4577         free(in.buf);
4578         if (in.jp)
4579                 exitstatus = waitforjob(in.jp);
4580         handler = savehandler;
4581         if (ex) {
4582                 longjmp(handler->loc, 1);
4583         }
4584         if (quoted == 0)
4585                 recordregion(startloc, dest - stackblock(), 0);
4586         TRACE(("evalbackq: size=%d: \"%.*s\"\n",
4587                    (dest - stackblock()) - startloc,
4588                    (dest - stackblock()) - startloc, stackblock() + startloc));
4589         expdest = dest;
4590         INTON;
4591 }
4592
4593 static int
4594 subevalvar(char *p, char *str, int strloc, int subtype, int startloc,
4595                    int varflags, int quotes)
4596 {
4597         char *startp;
4598         char *loc = NULL;
4599         char *q;
4600         int c = 0;
4601         int saveherefd = herefd;
4602         struct nodelist *saveargbackq = argbackq;
4603         int amount;
4604
4605         herefd = -1;
4606         argstr(p, subtype != VSASSIGN && subtype != VSQUESTION ? EXP_CASE : 0);
4607         STACKSTRNUL(expdest);
4608         herefd = saveherefd;
4609         argbackq = saveargbackq;
4610         startp = stackblock() + startloc;
4611         if (str == NULL)
4612                 str = stackblock() + strloc;
4613
4614         switch (subtype) {
4615         case VSASSIGN:
4616                 setvar(str, startp, 0);
4617                 amount = startp - expdest;
4618                 STADJUST(amount, expdest);
4619                 varflags &= ~VSNUL;
4620                 if (c != 0)
4621                         *loc = c;
4622                 return 1;
4623
4624         case VSQUESTION:
4625                 if (*p != CTLENDVAR) {
4626                         out2fmt(snlfmt, startp);
4627                         error((char *) NULL);
4628                 }
4629                 error("%.*s: parameter %snot set", p - str - 1,
4630                           str, (varflags & VSNUL) ? "null or " : nullstr);
4631                 /* NOTREACHED */
4632
4633         case VSTRIMLEFT:
4634                 for (loc = startp; loc < str; loc++) {
4635                         c = *loc;
4636                         *loc = '\0';
4637                         if (patmatch2(str, startp, quotes))
4638                                 goto recordleft;
4639                         *loc = c;
4640                         if (quotes && *loc == CTLESC)
4641                                 loc++;
4642                 }
4643                 return 0;
4644
4645         case VSTRIMLEFTMAX:
4646                 for (loc = str - 1; loc >= startp;) {
4647                         c = *loc;
4648                         *loc = '\0';
4649                         if (patmatch2(str, startp, quotes))
4650                                 goto recordleft;
4651                         *loc = c;
4652                         loc--;
4653                         if (quotes && loc > startp && *(loc - 1) == CTLESC) {
4654                                 for (q = startp; q < loc; q++)
4655                                         if (*q == CTLESC)
4656                                                 q++;
4657                                 if (q > loc)
4658                                         loc--;
4659                         }
4660                 }
4661                 return 0;
4662
4663         case VSTRIMRIGHT:
4664                 for (loc = str - 1; loc >= startp;) {
4665                         if (patmatch2(str, loc, quotes))
4666                                 goto recordright;
4667                         loc--;
4668                         if (quotes && loc > startp && *(loc - 1) == CTLESC) {
4669                                 for (q = startp; q < loc; q++)
4670                                         if (*q == CTLESC)
4671                                                 q++;
4672                                 if (q > loc)
4673                                         loc--;
4674                         }
4675                 }
4676                 return 0;
4677
4678         case VSTRIMRIGHTMAX:
4679                 for (loc = startp; loc < str - 1; loc++) {
4680                         if (patmatch2(str, loc, quotes))
4681                                 goto recordright;
4682                         if (quotes && *loc == CTLESC)
4683                                 loc++;
4684                 }
4685                 return 0;
4686
4687 #ifdef DEBUG
4688         default:
4689                 abort();
4690 #endif
4691         }
4692
4693   recordleft:
4694         *loc = c;
4695         amount = ((str - 1) - (loc - startp)) - expdest;
4696         STADJUST(amount, expdest);
4697         while (loc != str - 1)
4698                 *startp++ = *loc++;
4699         return 1;
4700
4701   recordright:
4702         amount = loc - expdest;
4703         STADJUST(amount, expdest);
4704         STPUTC('\0', expdest);
4705         STADJUST(-1, expdest);
4706         return 1;
4707 }
4708
4709
4710 /*
4711  * Test whether a specialized variable is set.
4712  */
4713
4714 static int varisset(char *name, int nulok)
4715 {
4716         if (*name == '!')
4717                 return backgndpid != -1;
4718         else if (*name == '@' || *name == '*') {
4719                 if (*shellparam.p == NULL)
4720                         return 0;
4721
4722                 if (nulok) {
4723                         char **av;
4724
4725                         for (av = shellparam.p; *av; av++)
4726                                 if (**av != '\0')
4727                                         return 1;
4728                         return 0;
4729                 }
4730         } else if (is_digit(*name)) {
4731                 char *ap;
4732                 int num = atoi(name);
4733
4734                 if (num > shellparam.nparam)
4735                         return 0;
4736
4737                 if (num == 0)
4738                         ap = arg0;
4739                 else
4740                         ap = shellparam.p[num - 1];
4741
4742                 if (nulok && (ap == NULL || *ap == '\0'))
4743                         return 0;
4744         }
4745         return 1;
4746 }
4747
4748 /*
4749  * Put a string on the stack.
4750  */
4751
4752 static void strtodest(const char *p, int syntax, int quotes)
4753 {
4754         while (*p) {
4755                 if (quotes && SIT(*p, syntax) == CCTL)
4756                         STPUTC(CTLESC, expdest);
4757                 STPUTC(*p++, expdest);
4758         }
4759 }
4760
4761 /*
4762  * Add the value of a specialized variable to the stack string.
4763  */
4764
4765 static void varvalue(char *name, int quoted, int flags)
4766 {
4767         int num;
4768         char *p;
4769         int i;
4770         int sep;
4771         int sepq = 0;
4772         char **ap;
4773         int syntax;
4774         int allow_split = flags & EXP_FULL;
4775         int quotes = flags & (EXP_FULL | EXP_CASE);
4776
4777         syntax = quoted ? DQSYNTAX : BASESYNTAX;
4778         switch (*name) {
4779         case '$':
4780                 num = rootpid;
4781                 goto numvar;
4782         case '?':
4783                 num = oexitstatus;
4784                 goto numvar;
4785         case '#':
4786                 num = shellparam.nparam;
4787                 goto numvar;
4788         case '!':
4789                 num = backgndpid;
4790           numvar:
4791                 expdest = cvtnum(num, expdest);
4792                 break;
4793         case '-':
4794                 for (i = 0; i < NOPTS; i++) {
4795                         if (optent_val(i))
4796                                 STPUTC(optent_letter(optlist[i]), expdest);
4797                 }
4798                 break;
4799         case '@':
4800                 if (allow_split && quoted) {
4801                         sep = 1 << CHAR_BIT;
4802                         goto param;
4803                 }
4804                 /* fall through */
4805         case '*':
4806                 sep = ifsset()? ifsval()[0] : ' ';
4807                 if (quotes) {
4808                         sepq = SIT(sep, syntax) == CCTL;
4809                 }
4810           param:
4811                 for (ap = shellparam.p; (p = *ap++) != NULL;) {
4812                         strtodest(p, syntax, quotes);
4813                         if (*ap && sep) {
4814                                 if (sepq)
4815                                         STPUTC(CTLESC, expdest);
4816                                 STPUTC(sep, expdest);
4817                         }
4818                 }
4819                 break;
4820         case '0':
4821                 strtodest(arg0, syntax, quotes);
4822                 break;
4823         default:
4824                 num = atoi(name);
4825                 if (num > 0 && num <= shellparam.nparam) {
4826                         strtodest(shellparam.p[num - 1], syntax, quotes);
4827                 }
4828                 break;
4829         }
4830 }
4831
4832
4833 /*
4834  * Record the fact that we have to scan this region of the
4835  * string for IFS characters.
4836  */
4837
4838 static void recordregion(int start, int end, int nulonly)
4839 {
4840         struct ifsregion *ifsp;
4841
4842         if (ifslastp == NULL) {
4843                 ifsp = &ifsfirst;
4844         } else {
4845                 INTOFF;
4846                 ifsp = (struct ifsregion *) xmalloc(sizeof(struct ifsregion));
4847                 ifsp->next = NULL;
4848                 ifslastp->next = ifsp;
4849                 INTON;
4850         }
4851         ifslastp = ifsp;
4852         ifslastp->begoff = start;
4853         ifslastp->endoff = end;
4854         ifslastp->nulonly = nulonly;
4855 }
4856
4857
4858
4859 /*
4860  * Break the argument string into pieces based upon IFS and add the
4861  * strings to the argument list.  The regions of the string to be
4862  * searched for IFS characters have been stored by recordregion.
4863  */
4864 static void ifsbreakup(char *string, struct arglist *arglist)
4865 {
4866         struct ifsregion *ifsp;
4867         struct strlist *sp;
4868         char *start;
4869         char *p;
4870         char *q;
4871         const char *ifs, *realifs;
4872         int ifsspc;
4873         int nulonly;
4874
4875
4876         start = string;
4877         ifsspc = 0;
4878         nulonly = 0;
4879         realifs = ifsset()? ifsval() : defifs;
4880         if (ifslastp != NULL) {
4881                 ifsp = &ifsfirst;
4882                 do {
4883                         p = string + ifsp->begoff;
4884                         nulonly = ifsp->nulonly;
4885                         ifs = nulonly ? nullstr : realifs;
4886                         ifsspc = 0;
4887                         while (p < string + ifsp->endoff) {
4888                                 q = p;
4889                                 if (*p == CTLESC)
4890                                         p++;
4891                                 if (strchr(ifs, *p)) {
4892                                         if (!nulonly)
4893                                                 ifsspc = (strchr(defifs, *p) != NULL);
4894                                         /* Ignore IFS whitespace at start */
4895                                         if (q == start && ifsspc) {
4896                                                 p++;
4897                                                 start = p;
4898                                                 continue;
4899                                         }
4900                                         *q = '\0';
4901                                         sp = (struct strlist *) stalloc(sizeof *sp);
4902                                         sp->text = start;
4903                                         *arglist->lastp = sp;
4904                                         arglist->lastp = &sp->next;
4905                                         p++;
4906                                         if (!nulonly) {
4907                                                 for (;;) {
4908                                                         if (p >= string + ifsp->endoff) {
4909                                                                 break;
4910                                                         }
4911                                                         q = p;
4912                                                         if (*p == CTLESC)
4913                                                                 p++;
4914                                                         if (strchr(ifs, *p) == NULL) {
4915                                                                 p = q;
4916                                                                 break;
4917                                                         } else if (strchr(defifs, *p) == NULL) {
4918                                                                 if (ifsspc) {
4919                                                                         p++;
4920                                                                         ifsspc = 0;
4921                                                                 } else {
4922                                                                         p = q;
4923                                                                         break;
4924                                                                 }
4925                                                         } else
4926                                                                 p++;
4927                                                 }
4928                                         }
4929                                         start = p;
4930                                 } else
4931                                         p++;
4932                         }
4933                 } while ((ifsp = ifsp->next) != NULL);
4934                 if (!(*start || (!ifsspc && start > string && nulonly))) {
4935                         return;
4936                 }
4937         }
4938
4939         sp = (struct strlist *) stalloc(sizeof *sp);
4940         sp->text = start;
4941         *arglist->lastp = sp;
4942         arglist->lastp = &sp->next;
4943 }
4944
4945 static void ifsfree(void)
4946 {
4947         while (ifsfirst.next != NULL) {
4948                 struct ifsregion *ifsp;
4949
4950                 INTOFF;
4951                 ifsp = ifsfirst.next->next;
4952                 free(ifsfirst.next);
4953                 ifsfirst.next = ifsp;
4954                 INTON;
4955         }
4956         ifslastp = NULL;
4957         ifsfirst.next = NULL;
4958 }
4959
4960 /*
4961  * Add a file name to the list.
4962  */
4963
4964 static void addfname(const char *name)
4965 {
4966         struct strlist *sp;
4967         size_t len = strlen(name) + 1;
4968
4969         sp = (struct strlist *) stalloc(sizeof *sp);
4970         sp->text = memcpy(stalloc(len), name, len);
4971         *exparg.lastp = sp;
4972         exparg.lastp = &sp->next;
4973 }
4974
4975 /*
4976  * Expand shell metacharacters.  At this point, the only control characters
4977  * should be escapes.  The results are stored in the list exparg.
4978  */
4979
4980 #if defined(__GLIBC__) && __GLIBC__ >= 2 && !defined(FNMATCH_BROKEN) && !defined(GLOB_BROKEN)
4981 static void expandmeta(struct strlist *str, int flag)
4982 {
4983         const char *p;
4984         glob_t pglob;
4985
4986         /* TODO - EXP_REDIR */
4987
4988         while (str) {
4989                 if (fflag)
4990                         goto nometa;
4991                 p = preglob(str->text);
4992                 INTOFF;
4993                 switch (glob(p, 0, 0, &pglob)) {
4994                 case 0:
4995                         if (pglob.gl_pathv[1] == 0 && !strcmp(p, pglob.gl_pathv[0]))
4996                                 goto nometa2;
4997                         addglob(&pglob);
4998                         globfree(&pglob);
4999                         INTON;
5000                         break;
5001                 case GLOB_NOMATCH:
5002                   nometa2:
5003                         globfree(&pglob);
5004                         INTON;
5005                   nometa:
5006                         *exparg.lastp = str;
5007                         rmescapes(str->text);
5008                         exparg.lastp = &str->next;
5009                         break;
5010                 default:                /* GLOB_NOSPACE */
5011                         error("Out of space");
5012                 }
5013                 str = str->next;
5014         }
5015 }
5016
5017
5018 /*
5019  * Add the result of glob(3) to the list.
5020  */
5021
5022 static void addglob(const glob_t * pglob)
5023 {
5024         char **p = pglob->gl_pathv;
5025
5026         do {
5027                 addfname(*p);
5028         } while (*++p);
5029 }
5030
5031
5032 #else                                                   /* defined(__GLIBC__) && !defined(FNMATCH_BROKEN) && !defined(GLOB_BROKEN) */
5033 static char *expdir;
5034
5035
5036 static void expandmeta(struct strlist *str, int flag)
5037 {
5038         char *p;
5039         struct strlist **savelastp;
5040         struct strlist *sp;
5041         char c;
5042
5043         /* TODO - EXP_REDIR */
5044
5045         while (str) {
5046                 if (fflag)
5047                         goto nometa;
5048                 p = str->text;
5049                 for (;;) {              /* fast check for meta chars */
5050                         if ((c = *p++) == '\0')
5051                                 goto nometa;
5052                         if (c == '*' || c == '?' || c == '[' || c == '!')
5053                                 break;
5054                 }
5055                 savelastp = exparg.lastp;
5056                 INTOFF;
5057                 if (expdir == NULL) {
5058                         int i = strlen(str->text);
5059
5060                         expdir = xmalloc(i < 2048 ? 2048 : i);  /* XXX */
5061                 }
5062
5063                 expmeta(expdir, str->text);
5064                 free(expdir);
5065                 expdir = NULL;
5066                 INTON;
5067                 if (exparg.lastp == savelastp) {
5068                         /*
5069                          * no matches
5070                          */
5071                   nometa:
5072                         *exparg.lastp = str;
5073                         rmescapes(str->text);
5074                         exparg.lastp = &str->next;
5075                 } else {
5076                         *exparg.lastp = NULL;
5077                         *savelastp = sp = expsort(*savelastp);
5078                         while (sp->next != NULL)
5079                                 sp = sp->next;
5080                         exparg.lastp = &sp->next;
5081                 }
5082                 str = str->next;
5083         }
5084 }
5085
5086
5087 /*
5088  * Do metacharacter (i.e. *, ?, [...]) expansion.
5089  */
5090
5091 static void expmeta(char *enddir, char *name)
5092 {
5093         char *p;
5094         const char *cp;
5095         char *q;
5096         char *start;
5097         char *endname;
5098         int metaflag;
5099         struct stat statb;
5100         DIR *dirp;
5101         struct dirent *dp;
5102         int atend;
5103         int matchdot;
5104
5105         metaflag = 0;
5106         start = name;
5107         for (p = name;; p++) {
5108                 if (*p == '*' || *p == '?')
5109                         metaflag = 1;
5110                 else if (*p == '[') {
5111                         q = p + 1;
5112                         if (*q == '!')
5113                                 q++;
5114                         for (;;) {
5115                                 while (*q == CTLQUOTEMARK)
5116                                         q++;
5117                                 if (*q == CTLESC)
5118                                         q++;
5119                                 if (*q == '/' || *q == '\0')
5120                                         break;
5121                                 if (*++q == ']') {
5122                                         metaflag = 1;
5123                                         break;
5124                                 }
5125                         }
5126                 } else if (*p == '!' && p[1] == '!' && (p == name || p[-1] == '/')) {
5127                         metaflag = 1;
5128                 } else if (*p == '\0')
5129                         break;
5130                 else if (*p == CTLQUOTEMARK)
5131                         continue;
5132                 else if (*p == CTLESC)
5133                         p++;
5134                 if (*p == '/') {
5135                         if (metaflag)
5136                                 break;
5137                         start = p + 1;
5138                 }
5139         }
5140         if (metaflag == 0) {    /* we've reached the end of the file name */
5141                 if (enddir != expdir)
5142                         metaflag++;
5143                 for (p = name;; p++) {
5144                         if (*p == CTLQUOTEMARK)
5145                                 continue;
5146                         if (*p == CTLESC)
5147                                 p++;
5148                         *enddir++ = *p;
5149                         if (*p == '\0')
5150                                 break;
5151                 }
5152                 if (metaflag == 0 || lstat(expdir, &statb) >= 0)
5153                         addfname(expdir);
5154                 return;
5155         }
5156         endname = p;
5157         if (start != name) {
5158                 p = name;
5159                 while (p < start) {
5160                         while (*p == CTLQUOTEMARK)
5161                                 p++;
5162                         if (*p == CTLESC)
5163                                 p++;
5164                         *enddir++ = *p++;
5165                 }
5166         }
5167         if (enddir == expdir) {
5168                 cp = ".";
5169         } else if (enddir == expdir + 1 && *expdir == '/') {
5170                 cp = "/";
5171         } else {
5172                 cp = expdir;
5173                 enddir[-1] = '\0';
5174         }
5175         if ((dirp = opendir(cp)) == NULL)
5176                 return;
5177         if (enddir != expdir)
5178                 enddir[-1] = '/';
5179         if (*endname == 0) {
5180                 atend = 1;
5181         } else {
5182                 atend = 0;
5183                 *endname++ = '\0';
5184         }
5185         matchdot = 0;
5186         p = start;
5187         while (*p == CTLQUOTEMARK)
5188                 p++;
5189         if (*p == CTLESC)
5190                 p++;
5191         if (*p == '.')
5192                 matchdot++;
5193         while (!int_pending() && (dp = readdir(dirp)) != NULL) {
5194                 if (dp->d_name[0] == '.' && !matchdot)
5195                         continue;
5196                 if (patmatch(start, dp->d_name, 0)) {
5197                         if (atend) {
5198                                 strcpy(enddir, dp->d_name);
5199                                 addfname(expdir);
5200                         } else {
5201                                 for (p = enddir, cp = dp->d_name; (*p++ = *cp++) != '\0';)
5202                                         continue;
5203                                 p[-1] = '/';
5204                                 expmeta(p, endname);
5205                         }
5206                 }
5207         }
5208         closedir(dirp);
5209         if (!atend)
5210                 endname[-1] = '/';
5211 }
5212 #endif                                                  /* defined(__GLIBC__) && !defined(FNMATCH_BROKEN) && !defined(GLOB_BROKEN) */
5213
5214
5215
5216 #if !(defined(__GLIBC__) && __GLIBC__ >= 2 && !defined(FNMATCH_BROKEN) && !defined(GLOB_BROKEN))
5217 /*
5218  * Sort the results of file name expansion.  It calculates the number of
5219  * strings to sort and then calls msort (short for merge sort) to do the
5220  * work.
5221  */
5222
5223 static struct strlist *expsort(struct strlist *str)
5224 {
5225         int len;
5226         struct strlist *sp;
5227
5228         len = 0;
5229         for (sp = str; sp; sp = sp->next)
5230                 len++;
5231         return msort(str, len);
5232 }
5233
5234
5235 static struct strlist *msort(struct strlist *list, int len)
5236 {
5237         struct strlist *p, *q = NULL;
5238         struct strlist **lpp;
5239         int half;
5240         int n;
5241
5242         if (len <= 1)
5243                 return list;
5244         half = len >> 1;
5245         p = list;
5246         for (n = half; --n >= 0;) {
5247                 q = p;
5248                 p = p->next;
5249         }
5250         q->next = NULL;         /* terminate first half of list */
5251         q = msort(list, half);  /* sort first half of list */
5252         p = msort(p, len - half);       /* sort second half */
5253         lpp = &list;
5254         for (;;) {
5255                 if (strcmp(p->text, q->text) < 0) {
5256                         *lpp = p;
5257                         lpp = &p->next;
5258                         if ((p = *lpp) == NULL) {
5259                                 *lpp = q;
5260                                 break;
5261                         }
5262                 } else {
5263                         *lpp = q;
5264                         lpp = &q->next;
5265                         if ((q = *lpp) == NULL) {
5266                                 *lpp = p;
5267                                 break;
5268                         }
5269                 }
5270         }
5271         return list;
5272 }
5273 #endif
5274
5275
5276
5277 /*
5278  * Returns true if the pattern matches the string.
5279  */
5280
5281 #if defined(__GLIBC__) && __GLIBC__ >= 2 && !defined(FNMATCH_BROKEN)
5282 /* squoted: string might have quote chars */
5283 static int patmatch(char *pattern, char *string, int squoted)
5284 {
5285         const char *p;
5286         char *q;
5287
5288         p = preglob(pattern);
5289         q = squoted ? _rmescapes(string, RMESCAPE_ALLOC) : string;
5290
5291         return !fnmatch(p, q, 0);
5292 }
5293
5294
5295 static int patmatch2(char *pattern, char *string, int squoted)
5296 {
5297         char *p;
5298         int res;
5299
5300         sstrnleft--;
5301         p = grabstackstr(expdest);
5302         res = patmatch(pattern, string, squoted);
5303         ungrabstackstr(p, expdest);
5304         return res;
5305 }
5306 #else
5307 static int patmatch(char *pattern, char *string, int squoted)
5308 {
5309         return pmatch(pattern, string, squoted);
5310 }
5311
5312
5313 static int pmatch(char *pattern, char *string, int squoted)
5314 {
5315         char *p, *q;
5316         char c;
5317
5318         p = pattern;
5319         q = string;
5320         for (;;) {
5321                 switch (c = *p++) {
5322                 case '\0':
5323                         goto breakloop;
5324                 case CTLESC:
5325                         if (squoted && *q == CTLESC)
5326                                 q++;
5327                         if (*q++ != *p++)
5328                                 return 0;
5329                         break;
5330                 case CTLQUOTEMARK:
5331                         continue;
5332                 case '?':
5333                         if (squoted && *q == CTLESC)
5334                                 q++;
5335                         if (*q++ == '\0')
5336                                 return 0;
5337                         break;
5338                 case '*':
5339                         c = *p;
5340                         while (c == CTLQUOTEMARK || c == '*')
5341                                 c = *++p;
5342                         if (c != CTLESC && c != CTLQUOTEMARK &&
5343                                 c != '?' && c != '*' && c != '[') {
5344                                 while (*q != c) {
5345                                         if (squoted && *q == CTLESC && q[1] == c)
5346                                                 break;
5347                                         if (*q == '\0')
5348                                                 return 0;
5349                                         if (squoted && *q == CTLESC)
5350                                                 q++;
5351                                         q++;
5352                                 }
5353                         }
5354                         do {
5355                                 if (pmatch(p, q, squoted))
5356                                         return 1;
5357                                 if (squoted && *q == CTLESC)
5358                                         q++;
5359                         } while (*q++ != '\0');
5360                         return 0;
5361                 case '[':{
5362                         char *endp;
5363                         int invert, found;
5364                         char chr;
5365
5366                         endp = p;
5367                         if (*endp == '!')
5368                                 endp++;
5369                         for (;;) {
5370                                 while (*endp == CTLQUOTEMARK)
5371                                         endp++;
5372                                 if (*endp == '\0')
5373                                         goto dft;       /* no matching ] */
5374                                 if (*endp == CTLESC)
5375                                         endp++;
5376                                 if (*++endp == ']')
5377                                         break;
5378                         }
5379                         invert = 0;
5380                         if (*p == '!') {
5381                                 invert++;
5382                                 p++;
5383                         }
5384                         found = 0;
5385                         chr = *q++;
5386                         if (squoted && chr == CTLESC)
5387                                 chr = *q++;
5388                         if (chr == '\0')
5389                                 return 0;
5390                         c = *p++;
5391                         do {
5392                                 if (c == CTLQUOTEMARK)
5393                                         continue;
5394                                 if (c == CTLESC)
5395                                         c = *p++;
5396                                 if (*p == '-' && p[1] != ']') {
5397                                         p++;
5398                                         while (*p == CTLQUOTEMARK)
5399                                                 p++;
5400                                         if (*p == CTLESC)
5401                                                 p++;
5402                                         if (chr >= c && chr <= *p)
5403                                                 found = 1;
5404                                         p++;
5405                                 } else {
5406                                         if (chr == c)
5407                                                 found = 1;
5408                                 }
5409                         } while ((c = *p++) != ']');
5410                         if (found == invert)
5411                                 return 0;
5412                         break;
5413                 }
5414                 dft: default:
5415                         if (squoted && *q == CTLESC)
5416                                 q++;
5417                         if (*q++ != c)
5418                                 return 0;
5419                         break;
5420                 }
5421         }
5422   breakloop:
5423         if (*q != '\0')
5424                 return 0;
5425         return 1;
5426 }
5427 #endif
5428
5429
5430
5431 /*
5432  * Remove any CTLESC characters from a string.
5433  */
5434
5435 #if defined(__GLIBC__) && __GLIBC__ >= 2 && !defined(FNMATCH_BROKEN)
5436 static char *_rmescapes(char *str, int flag)
5437 {
5438         char *p, *q, *r;
5439         static const char qchars[] = { CTLESC, CTLQUOTEMARK, 0 };
5440
5441         p = strpbrk(str, qchars);
5442         if (!p) {
5443                 return str;
5444         }
5445         q = p;
5446         r = str;
5447         if (flag & RMESCAPE_ALLOC) {
5448                 size_t len = p - str;
5449
5450                 q = r = stalloc(strlen(p) + len + 1);
5451                 if (len > 0) {
5452                         memcpy(q, str, len);
5453                         q += len;
5454                 }
5455         }
5456         while (*p) {
5457                 if (*p == CTLQUOTEMARK) {
5458                         p++;
5459                         continue;
5460                 }
5461                 if (*p == CTLESC) {
5462                         p++;
5463                         if (flag & RMESCAPE_GLOB && *p != '/') {
5464                                 *q++ = '\\';
5465                         }
5466                 }
5467                 *q++ = *p++;
5468         }
5469         *q = '\0';
5470         return r;
5471 }
5472 #else
5473 static void rmescapes(char *str)
5474 {
5475         char *p, *q;
5476
5477         p = str;
5478         while (*p != CTLESC && *p != CTLQUOTEMARK) {
5479                 if (*p++ == '\0')
5480                         return;
5481         }
5482         q = p;
5483         while (*p) {
5484                 if (*p == CTLQUOTEMARK) {
5485                         p++;
5486                         continue;
5487                 }
5488                 if (*p == CTLESC)
5489                         p++;
5490                 *q++ = *p++;
5491         }
5492         *q = '\0';
5493 }
5494 #endif
5495
5496
5497
5498 /*
5499  * See if a pattern matches in a case statement.
5500  */
5501
5502 static int casematch(union node *pattern, const char *val)
5503 {
5504         struct stackmark smark;
5505         int result;
5506         char *p;
5507
5508         setstackmark(&smark);
5509         argbackq = pattern->narg.backquote;
5510         STARTSTACKSTR(expdest);
5511         ifslastp = NULL;
5512         argstr(pattern->narg.text, EXP_TILDE | EXP_CASE);
5513         STPUTC('\0', expdest);
5514         p = grabstackstr(expdest);
5515         result = patmatch(p, (char *) val, 0);
5516         popstackmark(&smark);
5517         return result;
5518 }
5519
5520 /*
5521  * Our own itoa().
5522  */
5523
5524 static char *cvtnum(int num, char *buf)
5525 {
5526         int len;
5527
5528         CHECKSTRSPACE(32, buf);
5529         len = sprintf(buf, "%d", num);
5530         STADJUST(len, buf);
5531         return buf;
5532 }
5533
5534 /*
5535  * Editline and history functions (and glue).
5536  */
5537 static int histcmd(int argc, char **argv)
5538 {
5539         error("not compiled with history support");
5540         /* NOTREACHED */
5541 }
5542
5543
5544 struct redirtab {
5545         struct redirtab *next;
5546         short renamed[10];      /* Current ash support only 0-9 descriptors */
5547         /* char on arm (and others) can't be negative */
5548 };
5549
5550 static struct redirtab *redirlist;
5551
5552 extern char **environ;
5553
5554
5555
5556 /*
5557  * Initialization code.
5558  */
5559
5560 static void init(void)
5561 {
5562
5563         /* from cd.c: */
5564         {
5565                 curdir = nullstr;
5566                 setpwd(0, 0);
5567         }
5568
5569         /* from input.c: */
5570         {
5571                 basepf.nextc = basepf.buf = basebuf;
5572         }
5573
5574         /* from var.c: */
5575         {
5576                 char **envp;
5577                 char ppid[32];
5578
5579                 initvar();
5580                 for (envp = environ; *envp; envp++) {
5581                         if (strchr(*envp, '=')) {
5582                                 setvareq(*envp, VEXPORT | VTEXTFIXED);
5583                         }
5584                 }
5585
5586                 snprintf(ppid, sizeof(ppid), "%d", (int) getppid());
5587                 setvar("PPID", ppid, 0);
5588         }
5589 }
5590
5591
5592
5593 /*
5594  * This routine is called when an error or an interrupt occurs in an
5595  * interactive shell and control is returned to the main command loop.
5596  */
5597
5598 /* 1 == check for aliases, 2 == also check for assignments */
5599 static int checkalias;  /* also used in no alias mode for check assignments */
5600
5601 static void reset(void)
5602 {
5603
5604         /* from eval.c: */
5605         {
5606                 evalskip = 0;
5607                 loopnest = 0;
5608                 funcnest = 0;
5609         }
5610
5611         /* from input.c: */
5612         {
5613                 parselleft = parsenleft = 0;    /* clear input buffer */
5614                 popallfiles();
5615         }
5616
5617         /* from parser.c: */
5618         {
5619                 tokpushback = 0;
5620                 checkkwd = 0;
5621                 checkalias = 0;
5622         }
5623
5624         /* from redir.c: */
5625         {
5626                 while (redirlist)
5627                         popredir();
5628         }
5629
5630 }
5631
5632
5633
5634 /*
5635  * This file implements the input routines used by the parser.
5636  */
5637
5638 #ifdef CONFIG_FEATURE_COMMAND_EDITING
5639 static const char *cmdedit_prompt;
5640 static inline void putprompt(const char *s)
5641 {
5642         cmdedit_prompt = s;
5643 }
5644 #else
5645 static inline void putprompt(const char *s)
5646 {
5647         out2str(s);
5648 }
5649 #endif
5650
5651 #define EOF_NLEFT -99   /* value of parsenleft when EOF pushed back */
5652
5653
5654
5655 /*
5656  * Same as pgetc(), but ignores PEOA.
5657  */
5658
5659 #ifdef CONFIG_ASH_ALIAS
5660 static int pgetc2(void)
5661 {
5662         int c;
5663
5664         do {
5665                 c = pgetc_macro();
5666         } while (c == PEOA);
5667         return c;
5668 }
5669 #else
5670 static inline int pgetc2(void)
5671 {
5672         return pgetc_macro();
5673 }
5674 #endif
5675
5676 /*
5677  * Read a line from the script.
5678  */
5679
5680 static inline char *pfgets(char *line, int len)
5681 {
5682         char *p = line;
5683         int nleft = len;
5684         int c;
5685
5686         while (--nleft > 0) {
5687                 c = pgetc2();
5688                 if (c == PEOF) {
5689                         if (p == line)
5690                                 return NULL;
5691                         break;
5692                 }
5693                 *p++ = c;
5694                 if (c == '\n')
5695                         break;
5696         }
5697         *p = '\0';
5698         return line;
5699 }
5700
5701 static inline int preadfd(void)
5702 {
5703         int nr;
5704         char *buf = parsefile->buf;
5705
5706         parsenextc = buf;
5707
5708   retry:
5709 #ifdef CONFIG_FEATURE_COMMAND_EDITING
5710         {
5711                 if (!iflag || parsefile->fd)
5712                         nr = safe_read(parsefile->fd, buf, BUFSIZ - 1);
5713                 else {
5714                         nr = cmdedit_read_input((char *) cmdedit_prompt, buf);
5715                 }
5716         }
5717 #else
5718         nr = safe_read(parsefile->fd, buf, BUFSIZ - 1);
5719 #endif
5720
5721         if (nr < 0) {
5722                 if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
5723                         int flags = fcntl(0, F_GETFL, 0);
5724
5725                         if (flags >= 0 && flags & O_NONBLOCK) {
5726                                 flags &= ~O_NONBLOCK;
5727                                 if (fcntl(0, F_SETFL, flags) >= 0) {
5728                                         out2str("sh: turning off NDELAY mode\n");
5729                                         goto retry;
5730                                 }
5731                         }
5732                 }
5733         }
5734         return nr;
5735 }
5736
5737 static void popstring(void)
5738 {
5739         struct strpush *sp = parsefile->strpush;
5740
5741         INTOFF;
5742 #ifdef CONFIG_ASH_ALIAS
5743         if (sp->ap) {
5744                 if (parsenextc[-1] == ' ' || parsenextc[-1] == '\t') {
5745                         if (!checkalias) {
5746                                 checkalias = 1;
5747                         }
5748                 }
5749                 if (sp->string != sp->ap->val) {
5750                         free(sp->string);
5751                 }
5752
5753                 sp->ap->flag &= ~ALIASINUSE;
5754                 if (sp->ap->flag & ALIASDEAD) {
5755                         unalias(sp->ap->name);
5756                 }
5757         }
5758 #endif
5759         parsenextc = sp->prevstring;
5760         parsenleft = sp->prevnleft;
5761 /*dprintf("*** calling popstring: restoring to '%s'\n", parsenextc);*/
5762         parsefile->strpush = sp->prev;
5763         if (sp != &(parsefile->basestrpush))
5764                 free(sp);
5765         INTON;
5766 }
5767
5768
5769 /*
5770  * Refill the input buffer and return the next input character:
5771  *
5772  * 1) If a string was pushed back on the input, pop it;
5773  * 2) If an EOF was pushed back (parsenleft == EOF_NLEFT) or we are reading
5774  *    from a string so we can't refill the buffer, return EOF.
5775  * 3) If the is more stuff in this buffer, use it else call read to fill it.
5776  * 4) Process input up to the next newline, deleting nul characters.
5777  */
5778
5779 static int preadbuffer(void)
5780 {
5781         char *p, *q;
5782         int more;
5783         char savec;
5784
5785         while (parsefile->strpush) {
5786 #ifdef CONFIG_ASH_ALIAS
5787                 if (parsenleft == -1 && parsefile->strpush->ap &&
5788                         parsenextc[-1] != ' ' && parsenextc[-1] != '\t') {
5789                         return PEOA;
5790                 }
5791 #endif
5792                 popstring();
5793                 if (--parsenleft >= 0)
5794                         return (*parsenextc++);
5795         }
5796         if (parsenleft == EOF_NLEFT || parsefile->buf == NULL)
5797                 return PEOF;
5798         flushall();
5799
5800   again:
5801         if (parselleft <= 0) {
5802                 if ((parselleft = preadfd()) <= 0) {
5803                         parselleft = parsenleft = EOF_NLEFT;
5804                         return PEOF;
5805                 }
5806         }
5807
5808         q = p = parsenextc;
5809
5810         /* delete nul characters */
5811         for (more = 1; more;) {
5812                 switch (*p) {
5813                 case '\0':
5814                         p++;            /* Skip nul */
5815                         goto check;
5816
5817
5818                 case '\n':
5819                         parsenleft = q - parsenextc;
5820                         more = 0;       /* Stop processing here */
5821                         break;
5822                 }
5823
5824                 *q++ = *p++;
5825           check:
5826                 if (--parselleft <= 0 && more) {
5827                         parsenleft = q - parsenextc - 1;
5828                         if (parsenleft < 0)
5829                                 goto again;
5830                         more = 0;
5831                 }
5832         }
5833
5834         savec = *q;
5835         *q = '\0';
5836
5837         if (vflag) {
5838                 out2str(parsenextc);
5839         }
5840
5841         *q = savec;
5842
5843         return *parsenextc++;
5844 }
5845
5846
5847 /*
5848  * Push a string back onto the input at this current parsefile level.
5849  * We handle aliases this way.
5850  */
5851 static void pushstring(char *s, int len, void *ap)
5852 {
5853         struct strpush *sp;
5854
5855         INTOFF;
5856 /*dprintf("*** calling pushstring: %s, %d\n", s, len);*/
5857         if (parsefile->strpush) {
5858                 sp = xmalloc(sizeof(struct strpush));
5859                 sp->prev = parsefile->strpush;
5860                 parsefile->strpush = sp;
5861         } else
5862                 sp = parsefile->strpush = &(parsefile->basestrpush);
5863         sp->prevstring = parsenextc;
5864         sp->prevnleft = parsenleft;
5865 #ifdef CONFIG_ASH_ALIAS
5866         sp->ap = (struct alias *) ap;
5867         if (ap) {
5868                 ((struct alias *) ap)->flag |= ALIASINUSE;
5869                 sp->string = s;
5870         }
5871 #endif
5872         parsenextc = s;
5873         parsenleft = len;
5874         INTON;
5875 }
5876
5877
5878 /*
5879  * Like setinputfile, but takes input from a string.
5880  */
5881
5882 static void setinputstring(char *string)
5883 {
5884         INTOFF;
5885         pushfile();
5886         parsenextc = string;
5887         parsenleft = strlen(string);
5888         parsefile->buf = NULL;
5889         plinno = 1;
5890         INTON;
5891 }
5892
5893
5894
5895 /*
5896  * To handle the "." command, a stack of input files is used.  Pushfile
5897  * adds a new entry to the stack and popfile restores the previous level.
5898  */
5899
5900 static void pushfile(void)
5901 {
5902         struct parsefile *pf;
5903
5904         parsefile->nleft = parsenleft;
5905         parsefile->lleft = parselleft;
5906         parsefile->nextc = parsenextc;
5907         parsefile->linno = plinno;
5908         pf = (struct parsefile *) xmalloc(sizeof(struct parsefile));
5909         pf->prev = parsefile;
5910         pf->fd = -1;
5911         pf->strpush = NULL;
5912         pf->basestrpush.prev = NULL;
5913         parsefile = pf;
5914 }
5915
5916 #ifdef CONFIG_ASH_JOB_CONTROL
5917 static void restartjob(struct job *);
5918 #endif
5919 static void freejob(struct job *);
5920 static struct job *getjob(const char *);
5921 static int dowait(int, struct job *);
5922
5923
5924 /*
5925  * We keep track of whether or not fd0 has been redirected.  This is for
5926  * background commands, where we want to redirect fd0 to /dev/null only
5927  * if it hasn't already been redirected.
5928 */
5929 static int fd0_redirected = 0;
5930
5931 /* Return true if fd 0 has already been redirected at least once.  */
5932 static inline int fd0_redirected_p(void)
5933 {
5934         return fd0_redirected != 0;
5935 }
5936
5937 static void dupredirect(const union node *, int, int fd1dup);
5938
5939 #ifdef CONFIG_ASH_JOB_CONTROL
5940 /*
5941  * Turn job control on and off.
5942  *
5943  * Note:  This code assumes that the third arg to ioctl is a character
5944  * pointer, which is true on Berkeley systems but not System V.  Since
5945  * System V doesn't have job control yet, this isn't a problem now.
5946  */
5947
5948
5949
5950 static void setjobctl(int enable)
5951 {
5952         if (enable == jobctl || rootshell == 0)
5953                 return;
5954         if (enable) {
5955                 do {                    /* while we are in the background */
5956                         initialpgrp = tcgetpgrp(2);
5957                         if (initialpgrp < 0) {
5958                                 out2str("sh: can't access tty; job control turned off\n");
5959                                 mflag = 0;
5960                                 return;
5961                         }
5962                         if (initialpgrp == -1)
5963                                 initialpgrp = getpgrp();
5964                         else if (initialpgrp != getpgrp()) {
5965                                 killpg(initialpgrp, SIGTTIN);
5966                                 continue;
5967                         }
5968                 } while (0);
5969                 setsignal(SIGTSTP);
5970                 setsignal(SIGTTOU);
5971                 setsignal(SIGTTIN);
5972                 setpgid(0, rootpid);
5973                 tcsetpgrp(2, rootpid);
5974         } else {                        /* turning job control off */
5975                 setpgid(0, initialpgrp);
5976                 tcsetpgrp(2, initialpgrp);
5977                 setsignal(SIGTSTP);
5978                 setsignal(SIGTTOU);
5979                 setsignal(SIGTTIN);
5980         }
5981         jobctl = enable;
5982 }
5983 #endif
5984
5985
5986 #ifdef CONFIG_ASH_JOB_CONTROL
5987 static int killcmd(int argc, char **argv)
5988 {
5989         int signo = -1;
5990         int list = 0;
5991         int i;
5992         pid_t pid;
5993         struct job *jp;
5994
5995         if (argc <= 1) {
5996           usage:
5997                 error
5998                         ("Usage: kill [-s sigspec | -signum | -sigspec] [pid | job]... or\n"
5999                          "kill -l [exitstatus]");
6000         }
6001
6002         if (*argv[1] == '-') {
6003                 signo = decode_signal(argv[1] + 1, 1);
6004                 if (signo < 0) {
6005                         int c;
6006
6007                         while ((c = nextopt("ls:")) != '\0')
6008                                 switch (c) {
6009                                 case 'l':
6010                                         list = 1;
6011                                         break;
6012                                 case 's':
6013                                         signo = decode_signal(optionarg, 1);
6014                                         if (signo < 0) {
6015                                                 error("invalid signal number or name: %s", optionarg);
6016                                         }
6017                                         break;
6018 #ifdef DEBUG
6019                                 default:
6020                                         error("nextopt returned character code 0%o", c);
6021 #endif
6022                                 }
6023                 } else
6024                         argptr++;
6025         }
6026
6027         if (!list && signo < 0)
6028                 signo = SIGTERM;
6029
6030         if ((signo < 0 || !*argptr) ^ list) {
6031                 goto usage;
6032         }
6033
6034         if (list) {
6035                 const char *name;
6036
6037                 if (!*argptr) {
6038                         out1str("0\n");
6039                         for (i = 1; i < NSIG; i++) {
6040                                 name = u_signal_names(0, &i, 1);
6041                                 if (name)
6042                                         puts(name);
6043                         }
6044                         return 0;
6045                 }
6046                 name = u_signal_names(*argptr, &signo, -1);
6047                 if (name)
6048                         puts(name);
6049                 else
6050                         error("invalid signal number or exit status: %s", *argptr);
6051                 return 0;
6052         }
6053
6054         do {
6055                 if (**argptr == '%') {
6056                         jp = getjob(*argptr);
6057                         if (jp->jobctl == 0)
6058                                 error("job %s not created under job control", *argptr);
6059                         pid = -jp->ps[0].pid;
6060                 } else
6061                         pid = atoi(*argptr);
6062                 if (kill(pid, signo) != 0)
6063                         error("%s: %m", *argptr);
6064         } while (*++argptr);
6065
6066         return 0;
6067 }
6068
6069 static int fgcmd(int argc, char **argv)
6070 {
6071         struct job *jp;
6072         int pgrp;
6073         int status;
6074
6075         jp = getjob(argv[1]);
6076         if (jp->jobctl == 0)
6077                 error("job not created under job control");
6078         pgrp = jp->ps[0].pid;
6079         ioctl(2, TIOCSPGRP, (char *) &pgrp);
6080         restartjob(jp);
6081         status = waitforjob(jp);
6082         return status;
6083 }
6084
6085
6086 static int bgcmd(int argc, char **argv)
6087 {
6088         struct job *jp;
6089
6090         do {
6091                 jp = getjob(*++argv);
6092                 if (jp->jobctl == 0)
6093                         error("job not created under job control");
6094                 restartjob(jp);
6095         } while (--argc > 1);
6096         return 0;
6097 }
6098
6099
6100 static void restartjob(struct job *jp)
6101 {
6102         struct procstat *ps;
6103         int i;
6104
6105         if (jp->state == JOBDONE)
6106                 return;
6107         INTOFF;
6108         killpg(jp->ps[0].pid, SIGCONT);
6109         for (ps = jp->ps, i = jp->nprocs; --i >= 0; ps++) {
6110                 if (WIFSTOPPED(ps->status)) {
6111                         ps->status = -1;
6112                         jp->state = 0;
6113                 }
6114         }
6115         INTON;
6116 }
6117 #endif
6118
6119 static void showjobs(int change);
6120
6121
6122 static int jobscmd(int argc, char **argv)
6123 {
6124         showjobs(0);
6125         return 0;
6126 }
6127
6128
6129 /*
6130  * Print a list of jobs.  If "change" is nonzero, only print jobs whose
6131  * statuses have changed since the last call to showjobs.
6132  *
6133  * If the shell is interrupted in the process of creating a job, the
6134  * result may be a job structure containing zero processes.  Such structures
6135  * will be freed here.
6136  */
6137
6138 static void showjobs(int change)
6139 {
6140         int jobno;
6141         int procno;
6142         int i;
6143         struct job *jp;
6144         struct procstat *ps;
6145         int col;
6146         char s[64];
6147
6148         TRACE(("showjobs(%d) called\n", change));
6149         while (dowait(0, (struct job *) NULL) > 0);
6150         for (jobno = 1, jp = jobtab; jobno <= njobs; jobno++, jp++) {
6151                 if (!jp->used)
6152                         continue;
6153                 if (jp->nprocs == 0) {
6154                         freejob(jp);
6155                         continue;
6156                 }
6157                 if (change && !jp->changed)
6158                         continue;
6159                 procno = jp->nprocs;
6160                 for (ps = jp->ps;; ps++) {      /* for each process */
6161                         if (ps == jp->ps)
6162                                 snprintf(s, 64, "[%d] %ld ", jobno, (long) ps->pid);
6163                         else
6164                                 snprintf(s, 64, "    %ld ", (long) ps->pid);
6165                         out1str(s);
6166                         col = strlen(s);
6167                         s[0] = '\0';
6168                         if (ps->status == -1) {
6169                                 /* don't print anything */
6170                         } else if (WIFEXITED(ps->status)) {
6171                                 snprintf(s, 64, "Exit %d", WEXITSTATUS(ps->status));
6172                         } else {
6173 #ifdef CONFIG_ASH_JOB_CONTROL
6174                                 if (WIFSTOPPED(ps->status))
6175                                         i = WSTOPSIG(ps->status);
6176                                 else    /* WIFSIGNALED(ps->status) */
6177 #endif
6178                                         i = WTERMSIG(ps->status);
6179                                 if ((i & 0x7F) < NSIG && sys_siglist[i & 0x7F])
6180                                         strcpy(s, sys_siglist[i & 0x7F]);
6181                                 else
6182                                         snprintf(s, 64, "Signal %d", i & 0x7F);
6183                                 if (WCOREDUMP(ps->status))
6184                                         strcat(s, " (core dumped)");
6185                         }
6186                         out1str(s);
6187                         col += strlen(s);
6188                         printf("%*c%s\n", 30 - col >= 0 ? 30 - col : 0, ' ', ps->cmd);
6189                         if (--procno <= 0)
6190                                 break;
6191                 }
6192                 jp->changed = 0;
6193                 if (jp->state == JOBDONE) {
6194                         freejob(jp);
6195                 }
6196         }
6197 }
6198
6199
6200 /*
6201  * Mark a job structure as unused.
6202  */
6203
6204 static void freejob(struct job *jp)
6205 {
6206         const struct procstat *ps;
6207         int i;
6208
6209         INTOFF;
6210         for (i = jp->nprocs, ps = jp->ps; --i >= 0; ps++) {
6211                 if (ps->cmd != nullstr)
6212                         free(ps->cmd);
6213         }
6214         if (jp->ps != &jp->ps0)
6215                 free(jp->ps);
6216         jp->used = 0;
6217 #ifdef CONFIG_ASH_JOB_CONTROL
6218         if (curjob == jp - jobtab + 1)
6219                 curjob = 0;
6220 #endif
6221         INTON;
6222 }
6223
6224
6225
6226 static int waitcmd(int argc, char **argv)
6227 {
6228         struct job *job;
6229         int status, retval;
6230         struct job *jp;
6231
6232         if (--argc > 0) {
6233           start:
6234                 job = getjob(*++argv);
6235         } else {
6236                 job = NULL;
6237         }
6238         for (;;) {                      /* loop until process terminated or stopped */
6239                 if (job != NULL) {
6240                         if (job->state) {
6241                                 status = job->ps[job->nprocs - 1].status;
6242                                 if (!iflag)
6243                                         freejob(job);
6244                                 if (--argc) {
6245                                         goto start;
6246                                 }
6247                                 if (WIFEXITED(status))
6248                                         retval = WEXITSTATUS(status);
6249 #ifdef CONFIG_ASH_JOB_CONTROL
6250                                 else if (WIFSTOPPED(status))
6251                                         retval = WSTOPSIG(status) + 128;
6252 #endif
6253                                 else {
6254                                         /* XXX: limits number of signals */
6255                                         retval = WTERMSIG(status) + 128;
6256                                 }
6257                                 return retval;
6258                         }
6259                 } else {
6260                         for (jp = jobtab;; jp++) {
6261                                 if (jp >= jobtab + njobs) {     /* no running procs */
6262                                         return 0;
6263                                 }
6264                                 if (jp->used && jp->state == 0)
6265                                         break;
6266                         }
6267                 }
6268                 if (dowait(2, 0) < 0 && errno == EINTR) {
6269                         return 129;
6270                 }
6271         }
6272 }
6273
6274
6275
6276 /*
6277  * Convert a job name to a job structure.
6278  */
6279
6280 static struct job *getjob(const char *name)
6281 {
6282         int jobno;
6283         struct job *jp;
6284         int pid;
6285         int i;
6286
6287         if (name == NULL) {
6288 #ifdef CONFIG_ASH_JOB_CONTROL
6289           currentjob:
6290                 if ((jobno = curjob) == 0 || jobtab[jobno - 1].used == 0)
6291                         error("No current job");
6292                 return &jobtab[jobno - 1];
6293 #else
6294                 error("No current job");
6295 #endif
6296         } else if (name[0] == '%') {
6297                 if (is_digit(name[1])) {
6298                         jobno = number(name + 1);
6299                         if (jobno > 0 && jobno <= njobs && jobtab[jobno - 1].used != 0)
6300                                 return &jobtab[jobno - 1];
6301 #ifdef CONFIG_ASH_JOB_CONTROL
6302                 } else if (name[1] == '%' && name[2] == '\0') {
6303                         goto currentjob;
6304 #endif
6305                 } else {
6306                         struct job *found = NULL;
6307
6308                         for (jp = jobtab, i = njobs; --i >= 0; jp++) {
6309                                 if (jp->used && jp->nprocs > 0
6310                                         && prefix(name + 1, jp->ps[0].cmd)) {
6311                                         if (found)
6312                                                 error("%s: ambiguous", name);
6313                                         found = jp;
6314                                 }
6315                         }
6316                         if (found)
6317                                 return found;
6318                 }
6319         } else if (is_number(name, &pid)) {
6320                 for (jp = jobtab, i = njobs; --i >= 0; jp++) {
6321                         if (jp->used && jp->nprocs > 0
6322                                 && jp->ps[jp->nprocs - 1].pid == pid)
6323                                 return jp;
6324                 }
6325         }
6326         error("No such job: %s", name);
6327         /* NOTREACHED */
6328 }
6329
6330
6331
6332 /*
6333  * Return a new job structure,
6334  */
6335
6336 static struct job *makejob(const union node *node, int nprocs)
6337 {
6338         int i;
6339         struct job *jp;
6340
6341         for (i = njobs, jp = jobtab;; jp++) {
6342                 if (--i < 0) {
6343                         INTOFF;
6344                         if (njobs == 0) {
6345                                 jobtab = xmalloc(4 * sizeof jobtab[0]);
6346                         } else {
6347                                 jp = xmalloc((njobs + 4) * sizeof jobtab[0]);
6348                                 memcpy(jp, jobtab, njobs * sizeof jp[0]);
6349                                 /* Relocate `ps' pointers */
6350                                 for (i = 0; i < njobs; i++)
6351                                         if (jp[i].ps == &jobtab[i].ps0)
6352                                                 jp[i].ps = &jp[i].ps0;
6353                                 free(jobtab);
6354                                 jobtab = jp;
6355                         }
6356                         jp = jobtab + njobs;
6357                         for (i = 4; --i >= 0; jobtab[njobs++].used = 0);
6358                         INTON;
6359                         break;
6360                 }
6361                 if (jp->used == 0)
6362                         break;
6363         }
6364         INTOFF;
6365         jp->state = 0;
6366         jp->used = 1;
6367         jp->changed = 0;
6368         jp->nprocs = 0;
6369 #ifdef CONFIG_ASH_JOB_CONTROL
6370         jp->jobctl = jobctl;
6371 #endif
6372         if (nprocs > 1) {
6373                 jp->ps = xmalloc(nprocs * sizeof(struct procstat));
6374         } else {
6375                 jp->ps = &jp->ps0;
6376         }
6377         INTON;
6378         TRACE(("makejob(0x%lx, %d) returns %%%d\n", (long) node, nprocs,
6379                    jp - jobtab + 1));
6380         return jp;
6381 }
6382
6383
6384 /*
6385  * Fork of a subshell.  If we are doing job control, give the subshell its
6386  * own process group.  Jp is a job structure that the job is to be added to.
6387  * N is the command that will be evaluated by the child.  Both jp and n may
6388  * be NULL.  The mode parameter can be one of the following:
6389  *      FORK_FG - Fork off a foreground process.
6390  *      FORK_BG - Fork off a background process.
6391  *      FORK_NOJOB - Like FORK_FG, but don't give the process its own
6392  *                   process group even if job control is on.
6393  *
6394  * When job control is turned off, background processes have their standard
6395  * input redirected to /dev/null (except for the second and later processes
6396  * in a pipeline).
6397  */
6398
6399
6400
6401 static int forkshell(struct job *jp, const union node *n, int mode)
6402 {
6403         int pid;
6404
6405 #ifdef CONFIG_ASH_JOB_CONTROL
6406         int pgrp;
6407 #endif
6408         const char *devnull = _PATH_DEVNULL;
6409         const char *nullerr = "Can't open %s";
6410
6411         TRACE(("forkshell(%%%d, 0x%lx, %d) called\n", jp - jobtab, (long) n,
6412                    mode));
6413         INTOFF;
6414         pid = fork();
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  */