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