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