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