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