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