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