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