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