99d5e7d740e768a6573707257c1d346837f20472
[oweals/busybox.git] / shell / ash.c
1 /* vi: set sw=4 ts=4: */
2 /*
3  * ash shell port for busybox
4  *
5  * Copyright (c) 1989, 1991, 1993, 1994
6  *      The Regents of the University of California.  All rights reserved.
7  *
8  * This code is derived from software contributed to Berkeley by
9  * Kenneth Almquist.
10  *
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2 of the License, or
14  * (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19  * General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24  *
25  * This version of ash is adapted from the source in Debian's ash 0.3.8-5
26  * package.
27  *
28  * Modified by Erik Andersen <andersee@debian.org> and
29  * Vladimir Oleynik <dzo@simtreas.ru> to be used in busybox
30  *
31  *
32  * Original copyright notice is retained at the end of this file.
33  */
34
35
36 /* Enable this to compile in extra debugging noise.  When debugging is
37  * on, debugging info will be written to $HOME/trace and a quit signal
38  * will generate a core dump. */
39 #undef DEBUG
40
41 /* These are here to work with glibc -- Don't change these... */
42 #undef FNMATCH_BROKEN
43 #undef GLOB_BROKEN
44 #define IFS_BROKEN
45
46 #include <assert.h>
47 #include <stddef.h>
48 #include <ctype.h>
49 #include <dirent.h>
50 #include <errno.h>
51 #include <fcntl.h>
52 #include <limits.h>
53 #include <paths.h>
54 #include <setjmp.h>
55 #include <signal.h>
56 #include <stdarg.h>
57 #include <stdio.h>
58 #include <stdlib.h>
59 #include <string.h>
60 #include <sysexits.h>
61 #include <unistd.h>
62 #include <sys/stat.h>
63 #include <sys/cdefs.h>
64 #include <sys/ioctl.h>
65 #include <sys/param.h>
66 #include <sys/resource.h>
67 #include <sys/time.h>
68 #include <sys/times.h>
69 #include <sys/types.h>
70 #include <sys/wait.h>
71 #include "pwd.h"
72
73
74 #if !defined(FNMATCH_BROKEN)
75 #include <fnmatch.h>
76 #endif
77 #if !defined(GLOB_BROKEN)
78 #include <glob.h>
79 #endif
80
81 #ifdef CONFIG_ASH_JOB_CONTROL
82 #include <termios.h>
83 #endif
84
85 #include "busybox.h"
86 #include "cmdedit.h"
87
88 /*
89  * This file was generated by the mksyntax program.
90  */
91
92 /* Syntax classes */
93 #define CWORD 0                 /* character is nothing special */
94 #define CNL 1                   /* newline character */
95 #define CBACK 2                 /* a backslash character */
96 #define CSQUOTE 3               /* single quote */
97 #define CDQUOTE 4               /* double quote */
98 #define CENDQUOTE 5             /* a terminating quote */
99 #define CBQUOTE 6               /* backwards single quote */
100 #define CVAR 7                  /* a dollar sign */
101 #define CENDVAR 8               /* a '}' character */
102 #define CLP 9                   /* a left paren in arithmetic */
103 #define CRP 10                  /* a right paren in arithmetic */
104 #define CENDFILE 11             /* end of file */
105 #define CCTL 12                 /* like CWORD, except it must be escaped */
106 #define CSPCL 13                /* these terminate a word */
107 #define CIGN 14                 /* character should be ignored */
108
109 #define SYNBASE 130
110 #define PEOF -130
111
112 #define PEOA -129
113
114 #define TEOF 0
115 #define TNL 1
116 #define TREDIR 2
117 #define TWORD 3
118 #define TASSIGN 4
119 #define TSEMI 5
120 #define TBACKGND 6
121 #define TAND 7
122 #define TOR 8
123 #define TPIPE 9
124 #define TLP 10
125 #define TRP 11
126 #define TENDCASE 12
127 #define TENDBQUOTE 13
128 #define TNOT 14
129 #define TCASE 15
130 #define TDO 16
131 #define TDONE 17
132 #define TELIF 18
133 #define TELSE 19
134 #define TESAC 20
135 #define TFI 21
136 #define TFOR 22
137 #define TIF 23
138 #define TIN 24
139 #define TTHEN 25
140 #define TUNTIL 26
141 #define TWHILE 27
142 #define TBEGIN 28
143 #define TEND 29
144
145
146
147 /* control characters in argument strings */
148 #define CTLESC '\201'
149 #define CTLVAR '\202'
150 #define CTLENDVAR '\203'
151 #define CTLBACKQ '\204'
152 #define CTLQUOTE 01             /* ored with CTLBACKQ code if in quotes */
153 /*      CTLBACKQ | CTLQUOTE == '\205' */
154 #define CTLARI  '\206'
155 #define CTLENDARI '\207'
156 #define CTLQUOTEMARK '\210'
157
158
159 #define is_digit(c)     ((c)>='0' && (c)<='9')
160 #define is_name(c)      (((c) < CTLESC || (c) > CTLENDARI) && ((c) == '_' || isalpha((unsigned char) (c))))
161 #define is_in_name(c)   (((c) < CTLESC || (c) > CTLENDARI) && ((c) == '_' || isalnum((unsigned char) (c))))
162
163 /*
164  * is_special(c) evaluates to 1 for c in "!#$*-0123456789?@"; 0 otherwise
165  * (assuming ascii char codes, as the original implementation did)
166  */
167 #define is_special(c) \
168     ( (((unsigned int)c) - 33 < 32) \
169                          && ((0xc1ff920dUL >> (((unsigned int)c) - 33)) & 1))
170
171 #define digit_val(c)    ((c) - '0')
172
173
174 #define S_DFL 1                 /* default signal handling (SIG_DFL) */
175 #define S_CATCH 2               /* signal is caught */
176 #define S_IGN 3                 /* signal is ignored (SIG_IGN) */
177 #define S_HARD_IGN 4            /* signal is ignored permenantly */
178 #define S_RESET 5               /* temporary - to reset a hard ignored sig */
179
180
181 /* variable substitution byte (follows CTLVAR) */
182 #define VSTYPE  0x0f            /* type of variable substitution */
183 #define VSNUL   0x10            /* colon--treat the empty string as unset */
184 #define VSQUOTE 0x80            /* inside double quotes--suppress splitting */
185
186 /* values of VSTYPE field */
187 #define VSNORMAL        0x1             /* normal variable:  $var or ${var} */
188 #define VSMINUS         0x2             /* ${var-text} */
189 #define VSPLUS          0x3             /* ${var+text} */
190 #define VSQUESTION      0x4             /* ${var?message} */
191 #define VSASSIGN        0x5             /* ${var=text} */
192 #define VSTRIMLEFT      0x6             /* ${var#pattern} */
193 #define VSTRIMLEFTMAX   0x7             /* ${var##pattern} */
194 #define VSTRIMRIGHT     0x8             /* ${var%pattern} */
195 #define VSTRIMRIGHTMAX  0x9             /* ${var%%pattern} */
196 #define VSLENGTH        0xa             /* ${#var} */
197
198 /* flags passed to redirect */
199 #define REDIR_PUSH 01           /* save previous values of file descriptors */
200 #define REDIR_BACKQ 02          /* save the command output to pipe */
201
202 /*
203  * BSD setjmp saves the signal mask, which violates ANSI C and takes time,
204  * so we use _setjmp instead.
205  */
206
207 #if defined(BSD)
208 #define setjmp(jmploc)  _setjmp(jmploc)
209 #define longjmp(jmploc, val)    _longjmp(jmploc, val)
210 #endif
211
212 /*
213  * Most machines require the value returned from malloc to be aligned
214  * in some way.  The following macro will get this right on many machines.
215  */
216
217 #ifndef ALIGN
218 union align {
219         int i;
220         char *cp;
221 };
222
223 #define ALIGN(nbytes)   (((nbytes) + sizeof(union align) - 1) & ~(sizeof(union align) - 1))
224 #endif
225
226 #ifdef CONFIG_LOCALE_SUPPORT
227 #include <locale.h>
228 static void change_lc_all(const char *value);
229 static void change_lc_ctype(const char *value);
230 #endif
231
232 /*
233  * These macros allow the user to suspend the handling of interrupt signals
234  * over a period of time.  This is similar to SIGHOLD to or sigblock, but
235  * much more efficient and portable.  (But hacking the kernel is so much
236  * more fun than worrying about efficiency and portability. :-))
237  */
238
239 static void onint (void);
240 static volatile int suppressint;
241 static volatile int intpending;
242
243 #define INTOFF suppressint++
244 #ifndef CONFIG_ASH_OPTIMIZE_FOR_SIZE
245 #define INTON { if (--suppressint == 0 && intpending) onint(); }
246 #define FORCEINTON {suppressint = 0; if (intpending) onint();}
247 #else
248 static void __inton (void);
249 static void forceinton (void);
250 #define INTON __inton()
251 #define FORCEINTON forceinton()
252 #endif
253
254 #define CLEAR_PENDING_INT intpending = 0
255 #define int_pending() intpending
256
257
258 typedef void *pointer;
259 #ifndef NULL
260 #define NULL (void *)0
261 #endif
262
263 static pointer stalloc (int);
264 static void stunalloc (pointer);
265 static void ungrabstackstr (char *, char *);
266 static char * growstackstr(void);
267 static char * makestrspace(size_t newlen);
268 static char *sstrdup (const char *);
269
270 /*
271  * Parse trees for commands are allocated in lifo order, so we use a stack
272  * to make this more efficient, and also to avoid all sorts of exception
273  * handling code to handle interrupts in the middle of a parse.
274  *
275  * The size 504 was chosen because the Ultrix malloc handles that size
276  * well.
277  */
278
279 #define MINSIZE 504             /* minimum size of a block */
280
281
282 struct stack_block {
283         struct stack_block *prev;
284         char space[MINSIZE];
285 };
286
287 static struct stack_block stackbase;
288 static struct stack_block *stackp = &stackbase;
289 static struct stackmark *markp;
290 static char *stacknxt = stackbase.space;
291 static int stacknleft = MINSIZE;
292
293
294 #define equal(s1, s2)   (strcmp(s1, s2) == 0)
295
296 #define stackblock() stacknxt
297 #define stackblocksize() stacknleft
298 #define STARTSTACKSTR(p)        p = stackblock(), sstrnleft = stackblocksize()
299
300 #define STPUTC(c, p)    (--sstrnleft >= 0? (*p++ = (c)) : (p = growstackstr(), *p++ = (c)))
301 #define CHECKSTRSPACE(n, p)     { if (sstrnleft < n) p = makestrspace(n); }
302 #define STACKSTRNUL(p)  (sstrnleft == 0? (p = growstackstr(), *p = '\0') : (*p = '\0'))
303
304
305 #define USTPUTC(c, p)   (--sstrnleft, *p++ = (c))
306 #define STUNPUTC(p)     (++sstrnleft, --p)
307 #define STTOPC(p)       p[-1]
308 #define STADJUST(amount, p)     (p += (amount), sstrnleft -= (amount))
309 #define grabstackstr(p) stalloc(stackblocksize() - sstrnleft)
310
311 #define ckfree(p)       free((pointer)(p))
312
313
314 #ifdef DEBUG
315 #define TRACE(param)    trace param
316 typedef union node unode;
317 static void trace (const char *, ...);
318 static void trargs (char **);
319 static void showtree (unode *);
320 static void trputc (int);
321 static void trputs (const char *);
322 static void opentrace (void);
323 #else
324 #define TRACE(param)
325 #endif
326
327 #define NSEMI 0
328 #define NCMD 1
329 #define NPIPE 2
330 #define NREDIR 3
331 #define NBACKGND 4
332 #define NSUBSHELL 5
333 #define NAND 6
334 #define NOR 7
335 #define NIF 8
336 #define NWHILE 9
337 #define NUNTIL 10
338 #define NFOR 11
339 #define NCASE 12
340 #define NCLIST 13
341 #define NDEFUN 14
342 #define NARG 15
343 #define NTO 16
344 #define NFROM 17
345 #define NFROMTO 18
346 #define NAPPEND 19
347 #define NTOOV 20
348 #define NTOFD 21
349 #define NFROMFD 22
350 #define NHERE 23
351 #define NXHERE 24
352 #define NNOT 25
353
354 /*
355  * expandarg() flags
356  */
357 #define EXP_FULL        0x1     /* perform word splitting & file globbing */
358 #define EXP_TILDE       0x2     /* do normal tilde expansion */
359 #define EXP_VARTILDE    0x4     /* expand tildes in an assignment */
360 #define EXP_REDIR       0x8     /* file glob for a redirection (1 match only) */
361 #define EXP_CASE        0x10    /* keeps quotes around for CASE pattern */
362 #define EXP_RECORD      0x20    /* need to record arguments for ifs breakup */
363
364
365 #define NOPTS   16
366
367 static char optet_vals[NOPTS];
368
369 static const char * const optlist[NOPTS] = {
370         "e" "errexit",
371         "f" "noglob",
372         "I" "ignoreeof",
373         "i" "interactive",
374         "m" "monitor",
375         "n" "noexec",
376         "s" "stdin",
377         "x" "xtrace",
378         "v" "verbose",
379         "V" "vi",
380         "E" "emacs",
381         "C" "noclobber",
382         "a" "allexport",
383         "b" "notify",
384         "u" "nounset",
385         "q" "quietprofile"
386 };
387
388 #define optent_name(optent) (optent+1)
389 #define optent_letter(optent) optent[0]
390 #define optent_val(optent) optet_vals[optent]
391
392 #define eflag optent_val(0)
393 #define fflag optent_val(1)
394 #define Iflag optent_val(2)
395 #define iflag optent_val(3)
396 #define mflag optent_val(4)
397 #define nflag optent_val(5)
398 #define sflag optent_val(6)
399 #define xflag optent_val(7)
400 #define vflag optent_val(8)
401 #define Vflag optent_val(9)
402 #define Eflag optent_val(10)
403 #define Cflag optent_val(11)
404 #define aflag optent_val(12)
405 #define bflag optent_val(13)
406 #define uflag optent_val(14)
407 #define qflag optent_val(15)
408
409
410 /* Mode argument to forkshell.  Don't change FORK_FG or FORK_BG. */
411 #define FORK_FG 0
412 #define FORK_BG 1
413 #define FORK_NOJOB 2
414
415
416 struct nbinary {
417       int type;
418       union node *ch1;
419       union node *ch2;
420 };
421
422
423 struct ncmd {
424       int type;
425       int backgnd;
426       union node *assign;
427       union node *args;
428       union node *redirect;
429 };
430
431
432 struct npipe {
433       int type;
434       int backgnd;
435       struct nodelist *cmdlist;
436 };
437
438
439 struct nredir {
440       int type;
441       union node *n;
442       union node *redirect;
443 };
444
445
446 struct nif {
447       int type;
448       union node *test;
449       union node *ifpart;
450       union node *elsepart;
451 };
452
453
454 struct nfor {
455       int type;
456       union node *args;
457       union node *body;
458       char *var;
459 };
460
461
462 struct ncase {
463       int type;
464       union node *expr;
465       union node *cases;
466 };
467
468
469 struct nclist {
470       int type;
471       union node *next;
472       union node *pattern;
473       union node *body;
474 };
475
476
477 struct narg {
478       int type;
479       union node *next;
480       char *text;
481       struct nodelist *backquote;
482 };
483
484
485 struct nfile {
486       int type;
487       union node *next;
488       int fd;
489       union node *fname;
490       char *expfname;
491 };
492
493
494 struct ndup {
495       int type;
496       union node *next;
497       int fd;
498       int dupfd;
499       union node *vname;
500 };
501
502
503 struct nhere {
504       int type;
505       union node *next;
506       int fd;
507       union node *doc;
508 };
509
510
511 struct nnot {
512       int type;
513       union node *com;
514 };
515
516
517 union node {
518       int type;
519       struct nbinary nbinary;
520       struct ncmd ncmd;
521       struct npipe npipe;
522       struct nredir nredir;
523       struct nif nif;
524       struct nfor nfor;
525       struct ncase ncase;
526       struct nclist nclist;
527       struct narg narg;
528       struct nfile nfile;
529       struct ndup ndup;
530       struct nhere nhere;
531       struct nnot nnot;
532 };
533
534
535 struct nodelist {
536         struct nodelist *next;
537         union node *n;
538 };
539
540 struct backcmd {                /* result of evalbackcmd */
541         int fd;                 /* file descriptor to read from */
542         char *buf;              /* buffer */
543         int nleft;              /* number of chars in buffer */
544         struct job *jp;         /* job structure for command */
545 };
546
547 struct cmdentry {
548         int cmdtype;
549         union param {
550                 int index;
551                 union node *func;
552                 const struct builtincmd *cmd;
553         } u;
554 };
555
556 struct strlist {
557         struct strlist *next;
558         char *text;
559 };
560
561
562 struct arglist {
563         struct strlist *list;
564         struct strlist **lastp;
565 };
566
567 struct strpush {
568         struct strpush *prev;   /* preceding string on stack */
569         char *prevstring;
570         int prevnleft;
571 #ifdef CONFIG_ASH_ALIAS
572         struct alias *ap;       /* if push was associated with an alias */
573 #endif
574         char *string;           /* remember the string since it may change */
575 };
576
577 struct parsefile {
578         struct parsefile *prev; /* preceding file on stack */
579         int linno;              /* current line */
580         int fd;                 /* file descriptor (or -1 if string) */
581         int nleft;              /* number of chars left in this line */
582         int lleft;              /* number of chars left in this buffer */
583         char *nextc;            /* next char in buffer */
584         char *buf;              /* input buffer */
585         struct strpush *strpush; /* for pushing strings at this level */
586         struct strpush basestrpush; /* so pushing one is fast */
587 };
588
589 struct stackmark {
590         struct stack_block *stackp;
591         char *stacknxt;
592         int stacknleft;
593         struct stackmark *marknext;
594 };
595
596 struct shparam {
597         int nparam;             /* # of positional parameters (without $0) */
598         unsigned char malloc;   /* if parameter list dynamically allocated */
599         char **p;               /* parameter list */
600         int optind;             /* next parameter to be processed by getopts */
601         int optoff;             /* used by getopts */
602 };
603
604 /*
605  * When commands are first encountered, they are entered in a hash table.
606  * This ensures that a full path search will not have to be done for them
607  * on each invocation.
608  *
609  * We should investigate converting to a linear search, even though that
610  * would make the command name "hash" a misnomer.
611  */
612 #define CMDTABLESIZE 31         /* should be prime */
613 #define ARB 1                   /* actual size determined at run time */
614
615
616
617 struct tblentry {
618         struct tblentry *next;  /* next entry in hash chain */
619         union param param;      /* definition of builtin function */
620         short cmdtype;          /* index identifying command */
621         char rehash;            /* if set, cd done since entry created */
622         char cmdname[ARB];      /* name of command */
623 };
624
625
626 static struct tblentry *cmdtable[CMDTABLESIZE];
627 static int builtinloc = -1;             /* index in path of %builtin, or -1 */
628 static int exerrno = 0;                 /* Last exec error */
629
630
631 static void tryexec (char *, char **, char **);
632 static void printentry (struct tblentry *, int);
633 static void clearcmdentry (int);
634 static struct tblentry *cmdlookup (const char *, int);
635 static void delete_cmd_entry (void);
636 static int path_change (const char *, int *);
637
638
639 static void flushall (void);
640 static void out2fmt (const char *, ...)
641     __attribute__((__format__(__printf__,1,2)));
642 static int xwrite (int, const char *, int);
643
644 static inline void outstr (const char *p, FILE *file) { fputs(p, file); }
645 static void out1str(const char *p) { outstr(p, stdout); }
646 static void out2str(const char *p) { outstr(p, stderr); }
647
648 #ifndef CONFIG_ASH_OPTIMIZE_FOR_SIZE
649 #define out2c(c)        putc((c), stderr)
650 #else
651 static void out2c(int c)           { putc(c, stderr); }
652 #endif
653
654
655 #ifdef CONFIG_ASH_OPTIMIZE_FOR_SIZE
656 #define USE_SIT_FUNCTION
657 #endif
658
659 /* number syntax index */
660 #define  BASESYNTAX  0                  /* not in quotes */
661 #define  DQSYNTAX    1                  /* in double quotes */
662 #define  SQSYNTAX    2                  /* in single quotes */
663 #define  ARISYNTAX   3                  /* in arithmetic */
664
665 static const char S_I_T[][4] = {
666   /*  0 */  { CSPCL,    CIGN,      CIGN,      CIGN     },   /* PEOA */
667   /*  1 */  { CSPCL,    CWORD,     CWORD,     CWORD    },   /* ' ' */
668   /*  2 */  { CNL,      CNL,       CNL,       CNL      },   /* \n */
669   /*  3 */  { CWORD,    CCTL,      CCTL,      CWORD    },   /* !*-/:=?[]~ */
670   /*  4 */  { CDQUOTE,  CENDQUOTE, CWORD,     CDQUOTE  },   /* '"' */
671   /*  5 */  { CVAR,     CVAR,      CWORD,     CVAR     },   /* $ */
672   /*  6 */  { CSQUOTE,  CWORD,     CENDQUOTE, CSQUOTE  },   /* "'" */
673   /*  7 */  { CSPCL,    CWORD,     CWORD,     CLP      },   /* ( */
674   /*  8 */  { CSPCL,    CWORD,     CWORD,     CRP      },   /* ) */
675   /*  9 */  { CBACK,    CBACK,     CCTL,      CBACK    },   /* \ */
676   /* 10 */  { CBQUOTE,  CBQUOTE,   CWORD,     CBQUOTE  },   /* ` */
677   /* 11 */  { CENDVAR,  CENDVAR,   CWORD,     CENDVAR  },   /* } */
678 #ifndef USE_SIT_FUNCTION
679   /* 12 */  { CENDFILE, CENDFILE,  CENDFILE,  CENDFILE },   /* PEOF */
680   /* 13 */  { CWORD,    CWORD,     CWORD,     CWORD    },   /* 0-9A-Za-z */
681   /* 14 */  { CCTL,     CCTL,      CCTL,      CCTL     }    /* CTLESC ... */
682 #endif
683 };
684
685 #ifdef USE_SIT_FUNCTION
686
687 #define U_C(c) ((unsigned char)(c))
688
689 static int SIT(int c, int syntax)
690 {
691         static const char spec_symbls[]="\t\n !\"$&'()*-/:;<=>?[\\]`|}~";
692         static const char syntax_index_table [] = {
693                                 1, 2, 1, 3, 4, 5, 1, 6, /* "\t\n !\"$&'" */
694                                 7, 8, 3, 3, 3, 3, 1, 1, /* "()*-/:;<" */
695                                 3, 1, 3, 3, 9, 3,10, 1, /* "=>?[\\]`|" */
696                                 11,3 }; /* "}~" */
697         const char *s;
698         int indx;
699
700         if(c==PEOF)             /* 2^8+2 */
701                 return CENDFILE;
702         if(c==PEOA)             /* 2^8+1 */
703                 indx = 0;
704          else if(U_C(c)>=U_C(CTLESC) && U_C(c)<=U_C(CTLQUOTEMARK))
705                 return CCTL;
706          else {
707                 s = strchr(spec_symbls, c);
708                 if(s==0)
709                         return CWORD;
710                 indx = syntax_index_table[(s-spec_symbls)];
711         }
712         return S_I_T[indx][syntax];
713 }
714
715 #else  /* USE_SIT_FUNCTION */
716
717 #define SIT(c, syntax) S_I_T[(int)syntax_index_table[((int)c)+SYNBASE]][syntax]
718
719 #define CSPCL_CIGN_CIGN_CIGN                           0
720 #define CSPCL_CWORD_CWORD_CWORD                        1
721 #define CNL_CNL_CNL_CNL                                2
722 #define CWORD_CCTL_CCTL_CWORD                          3
723 #define CDQUOTE_CENDQUOTE_CWORD_CDQUOTE                4
724 #define CVAR_CVAR_CWORD_CVAR                           5
725 #define CSQUOTE_CWORD_CENDQUOTE_CSQUOTE                6
726 #define CSPCL_CWORD_CWORD_CLP                          7
727 #define CSPCL_CWORD_CWORD_CRP                          8
728 #define CBACK_CBACK_CCTL_CBACK                         9
729 #define CBQUOTE_CBQUOTE_CWORD_CBQUOTE                 10
730 #define CENDVAR_CENDVAR_CWORD_CENDVAR                 11
731 #define CENDFILE_CENDFILE_CENDFILE_CENDFILE           12
732 #define CWORD_CWORD_CWORD_CWORD                       13
733 #define CCTL_CCTL_CCTL_CCTL                           14
734
735 static const char syntax_index_table[258] = {
736                  /* BASESYNTAX_DQSYNTAX_SQSYNTAX_ARISYNTAX */
737   /*   0  -130 PEOF */  CENDFILE_CENDFILE_CENDFILE_CENDFILE,
738   /*   1  -129 PEOA */  CSPCL_CIGN_CIGN_CIGN,
739   /*   2  -128 0xff */  CWORD_CWORD_CWORD_CWORD,
740   /*   3  -127      */  CCTL_CCTL_CCTL_CCTL,    /* CTLQUOTEMARK */
741   /*   4  -126      */  CCTL_CCTL_CCTL_CCTL,
742   /*   5  -125      */  CCTL_CCTL_CCTL_CCTL,
743   /*   6  -124      */  CCTL_CCTL_CCTL_CCTL,
744   /*   7  -123      */  CCTL_CCTL_CCTL_CCTL,
745   /*   8  -122      */  CCTL_CCTL_CCTL_CCTL,
746   /*   9  -121      */  CCTL_CCTL_CCTL_CCTL,
747   /*  10  -120      */  CCTL_CCTL_CCTL_CCTL,    /* CTLESC */
748   /*  11  -119      */  CWORD_CWORD_CWORD_CWORD,
749   /*  12  -118      */  CWORD_CWORD_CWORD_CWORD,
750   /*  13  -117      */  CWORD_CWORD_CWORD_CWORD,
751   /*  14  -116      */  CWORD_CWORD_CWORD_CWORD,
752   /*  15  -115      */  CWORD_CWORD_CWORD_CWORD,
753   /*  16  -114      */  CWORD_CWORD_CWORD_CWORD,
754   /*  17  -113      */  CWORD_CWORD_CWORD_CWORD,
755   /*  18  -112      */  CWORD_CWORD_CWORD_CWORD,
756   /*  19  -111      */  CWORD_CWORD_CWORD_CWORD,
757   /*  20  -110      */  CWORD_CWORD_CWORD_CWORD,
758   /*  21  -109      */  CWORD_CWORD_CWORD_CWORD,
759   /*  22  -108      */  CWORD_CWORD_CWORD_CWORD,
760   /*  23  -107      */  CWORD_CWORD_CWORD_CWORD,
761   /*  24  -106      */  CWORD_CWORD_CWORD_CWORD,
762   /*  25  -105      */  CWORD_CWORD_CWORD_CWORD,
763   /*  26  -104      */  CWORD_CWORD_CWORD_CWORD,
764   /*  27  -103      */  CWORD_CWORD_CWORD_CWORD,
765   /*  28  -102      */  CWORD_CWORD_CWORD_CWORD,
766   /*  29  -101      */  CWORD_CWORD_CWORD_CWORD,
767   /*  30  -100      */  CWORD_CWORD_CWORD_CWORD,
768   /*  31   -99      */  CWORD_CWORD_CWORD_CWORD,
769   /*  32   -98      */  CWORD_CWORD_CWORD_CWORD,
770   /*  33   -97      */  CWORD_CWORD_CWORD_CWORD,
771   /*  34   -96      */  CWORD_CWORD_CWORD_CWORD,
772   /*  35   -95      */  CWORD_CWORD_CWORD_CWORD,
773   /*  36   -94      */  CWORD_CWORD_CWORD_CWORD,
774   /*  37   -93      */  CWORD_CWORD_CWORD_CWORD,
775   /*  38   -92      */  CWORD_CWORD_CWORD_CWORD,
776   /*  39   -91      */  CWORD_CWORD_CWORD_CWORD,
777   /*  40   -90      */  CWORD_CWORD_CWORD_CWORD,
778   /*  41   -89      */  CWORD_CWORD_CWORD_CWORD,
779   /*  42   -88      */  CWORD_CWORD_CWORD_CWORD,
780   /*  43   -87      */  CWORD_CWORD_CWORD_CWORD,
781   /*  44   -86      */  CWORD_CWORD_CWORD_CWORD,
782   /*  45   -85      */  CWORD_CWORD_CWORD_CWORD,
783   /*  46   -84      */  CWORD_CWORD_CWORD_CWORD,
784   /*  47   -83      */  CWORD_CWORD_CWORD_CWORD,
785   /*  48   -82      */  CWORD_CWORD_CWORD_CWORD,
786   /*  49   -81      */  CWORD_CWORD_CWORD_CWORD,
787   /*  50   -80      */  CWORD_CWORD_CWORD_CWORD,
788   /*  51   -79      */  CWORD_CWORD_CWORD_CWORD,
789   /*  52   -78      */  CWORD_CWORD_CWORD_CWORD,
790   /*  53   -77      */  CWORD_CWORD_CWORD_CWORD,
791   /*  54   -76      */  CWORD_CWORD_CWORD_CWORD,
792   /*  55   -75      */  CWORD_CWORD_CWORD_CWORD,
793   /*  56   -74      */  CWORD_CWORD_CWORD_CWORD,
794   /*  57   -73      */  CWORD_CWORD_CWORD_CWORD,
795   /*  58   -72      */  CWORD_CWORD_CWORD_CWORD,
796   /*  59   -71      */  CWORD_CWORD_CWORD_CWORD,
797   /*  60   -70      */  CWORD_CWORD_CWORD_CWORD,
798   /*  61   -69      */  CWORD_CWORD_CWORD_CWORD,
799   /*  62   -68      */  CWORD_CWORD_CWORD_CWORD,
800   /*  63   -67      */  CWORD_CWORD_CWORD_CWORD,
801   /*  64   -66      */  CWORD_CWORD_CWORD_CWORD,
802   /*  65   -65      */  CWORD_CWORD_CWORD_CWORD,
803   /*  66   -64      */  CWORD_CWORD_CWORD_CWORD,
804   /*  67   -63      */  CWORD_CWORD_CWORD_CWORD,
805   /*  68   -62      */  CWORD_CWORD_CWORD_CWORD,
806   /*  69   -61      */  CWORD_CWORD_CWORD_CWORD,
807   /*  70   -60      */  CWORD_CWORD_CWORD_CWORD,
808   /*  71   -59      */  CWORD_CWORD_CWORD_CWORD,
809   /*  72   -58      */  CWORD_CWORD_CWORD_CWORD,
810   /*  73   -57      */  CWORD_CWORD_CWORD_CWORD,
811   /*  74   -56      */  CWORD_CWORD_CWORD_CWORD,
812   /*  75   -55      */  CWORD_CWORD_CWORD_CWORD,
813   /*  76   -54      */  CWORD_CWORD_CWORD_CWORD,
814   /*  77   -53      */  CWORD_CWORD_CWORD_CWORD,
815   /*  78   -52      */  CWORD_CWORD_CWORD_CWORD,
816   /*  79   -51      */  CWORD_CWORD_CWORD_CWORD,
817   /*  80   -50      */  CWORD_CWORD_CWORD_CWORD,
818   /*  81   -49      */  CWORD_CWORD_CWORD_CWORD,
819   /*  82   -48      */  CWORD_CWORD_CWORD_CWORD,
820   /*  83   -47      */  CWORD_CWORD_CWORD_CWORD,
821   /*  84   -46      */  CWORD_CWORD_CWORD_CWORD,
822   /*  85   -45      */  CWORD_CWORD_CWORD_CWORD,
823   /*  86   -44      */  CWORD_CWORD_CWORD_CWORD,
824   /*  87   -43      */  CWORD_CWORD_CWORD_CWORD,
825   /*  88   -42      */  CWORD_CWORD_CWORD_CWORD,
826   /*  89   -41      */  CWORD_CWORD_CWORD_CWORD,
827   /*  90   -40      */  CWORD_CWORD_CWORD_CWORD,
828   /*  91   -39      */  CWORD_CWORD_CWORD_CWORD,
829   /*  92   -38      */  CWORD_CWORD_CWORD_CWORD,
830   /*  93   -37      */  CWORD_CWORD_CWORD_CWORD,
831   /*  94   -36      */  CWORD_CWORD_CWORD_CWORD,
832   /*  95   -35      */  CWORD_CWORD_CWORD_CWORD,
833   /*  96   -34      */  CWORD_CWORD_CWORD_CWORD,
834   /*  97   -33      */  CWORD_CWORD_CWORD_CWORD,
835   /*  98   -32      */  CWORD_CWORD_CWORD_CWORD,
836   /*  99   -31      */  CWORD_CWORD_CWORD_CWORD,
837   /* 100   -30      */  CWORD_CWORD_CWORD_CWORD,
838   /* 101   -29      */  CWORD_CWORD_CWORD_CWORD,
839   /* 102   -28      */  CWORD_CWORD_CWORD_CWORD,
840   /* 103   -27      */  CWORD_CWORD_CWORD_CWORD,
841   /* 104   -26      */  CWORD_CWORD_CWORD_CWORD,
842   /* 105   -25      */  CWORD_CWORD_CWORD_CWORD,
843   /* 106   -24      */  CWORD_CWORD_CWORD_CWORD,
844   /* 107   -23      */  CWORD_CWORD_CWORD_CWORD,
845   /* 108   -22      */  CWORD_CWORD_CWORD_CWORD,
846   /* 109   -21      */  CWORD_CWORD_CWORD_CWORD,
847   /* 110   -20      */  CWORD_CWORD_CWORD_CWORD,
848   /* 111   -19      */  CWORD_CWORD_CWORD_CWORD,
849   /* 112   -18      */  CWORD_CWORD_CWORD_CWORD,
850   /* 113   -17      */  CWORD_CWORD_CWORD_CWORD,
851   /* 114   -16      */  CWORD_CWORD_CWORD_CWORD,
852   /* 115   -15      */  CWORD_CWORD_CWORD_CWORD,
853   /* 116   -14      */  CWORD_CWORD_CWORD_CWORD,
854   /* 117   -13      */  CWORD_CWORD_CWORD_CWORD,
855   /* 118   -12      */  CWORD_CWORD_CWORD_CWORD,
856   /* 119   -11      */  CWORD_CWORD_CWORD_CWORD,
857   /* 120   -10      */  CWORD_CWORD_CWORD_CWORD,
858   /* 121    -9      */  CWORD_CWORD_CWORD_CWORD,
859   /* 122    -8      */  CWORD_CWORD_CWORD_CWORD,
860   /* 123    -7      */  CWORD_CWORD_CWORD_CWORD,
861   /* 124    -6      */  CWORD_CWORD_CWORD_CWORD,
862   /* 125    -5      */  CWORD_CWORD_CWORD_CWORD,
863   /* 126    -4      */  CWORD_CWORD_CWORD_CWORD,
864   /* 127    -3      */  CWORD_CWORD_CWORD_CWORD,
865   /* 128    -2      */  CWORD_CWORD_CWORD_CWORD,
866   /* 129    -1      */  CWORD_CWORD_CWORD_CWORD,
867   /* 130     0      */  CWORD_CWORD_CWORD_CWORD,
868   /* 131     1      */  CWORD_CWORD_CWORD_CWORD,
869   /* 132     2      */  CWORD_CWORD_CWORD_CWORD,
870   /* 133     3      */  CWORD_CWORD_CWORD_CWORD,
871   /* 134     4      */  CWORD_CWORD_CWORD_CWORD,
872   /* 135     5      */  CWORD_CWORD_CWORD_CWORD,
873   /* 136     6      */  CWORD_CWORD_CWORD_CWORD,
874   /* 137     7      */  CWORD_CWORD_CWORD_CWORD,
875   /* 138     8      */  CWORD_CWORD_CWORD_CWORD,
876   /* 139     9 "\t" */  CSPCL_CWORD_CWORD_CWORD,
877   /* 140    10 "\n" */  CNL_CNL_CNL_CNL,
878   /* 141    11      */  CWORD_CWORD_CWORD_CWORD,
879   /* 142    12      */  CWORD_CWORD_CWORD_CWORD,
880   /* 143    13      */  CWORD_CWORD_CWORD_CWORD,
881   /* 144    14      */  CWORD_CWORD_CWORD_CWORD,
882   /* 145    15      */  CWORD_CWORD_CWORD_CWORD,
883   /* 146    16      */  CWORD_CWORD_CWORD_CWORD,
884   /* 147    17      */  CWORD_CWORD_CWORD_CWORD,
885   /* 148    18      */  CWORD_CWORD_CWORD_CWORD,
886   /* 149    19      */  CWORD_CWORD_CWORD_CWORD,
887   /* 150    20      */  CWORD_CWORD_CWORD_CWORD,
888   /* 151    21      */  CWORD_CWORD_CWORD_CWORD,
889   /* 152    22      */  CWORD_CWORD_CWORD_CWORD,
890   /* 153    23      */  CWORD_CWORD_CWORD_CWORD,
891   /* 154    24      */  CWORD_CWORD_CWORD_CWORD,
892   /* 155    25      */  CWORD_CWORD_CWORD_CWORD,
893   /* 156    26      */  CWORD_CWORD_CWORD_CWORD,
894   /* 157    27      */  CWORD_CWORD_CWORD_CWORD,
895   /* 158    28      */  CWORD_CWORD_CWORD_CWORD,
896   /* 159    29      */  CWORD_CWORD_CWORD_CWORD,
897   /* 160    30      */  CWORD_CWORD_CWORD_CWORD,
898   /* 161    31      */  CWORD_CWORD_CWORD_CWORD,
899   /* 162    32  " " */  CSPCL_CWORD_CWORD_CWORD,
900   /* 163    33  "!" */  CWORD_CCTL_CCTL_CWORD,
901   /* 164    34  """ */  CDQUOTE_CENDQUOTE_CWORD_CDQUOTE,
902   /* 165    35  "#" */  CWORD_CWORD_CWORD_CWORD,
903   /* 166    36  "$" */  CVAR_CVAR_CWORD_CVAR,
904   /* 167    37  "%" */  CWORD_CWORD_CWORD_CWORD,
905   /* 168    38  "&" */  CSPCL_CWORD_CWORD_CWORD,
906   /* 169    39  "'" */  CSQUOTE_CWORD_CENDQUOTE_CSQUOTE,
907   /* 170    40  "(" */  CSPCL_CWORD_CWORD_CLP,
908   /* 171    41  ")" */  CSPCL_CWORD_CWORD_CRP,
909   /* 172    42  "*" */  CWORD_CCTL_CCTL_CWORD,
910   /* 173    43  "+" */  CWORD_CWORD_CWORD_CWORD,
911   /* 174    44  "," */  CWORD_CWORD_CWORD_CWORD,
912   /* 175    45  "-" */  CWORD_CCTL_CCTL_CWORD,
913   /* 176    46  "." */  CWORD_CWORD_CWORD_CWORD,
914   /* 177    47  "/" */  CWORD_CCTL_CCTL_CWORD,
915   /* 178    48  "0" */  CWORD_CWORD_CWORD_CWORD,
916   /* 179    49  "1" */  CWORD_CWORD_CWORD_CWORD,
917   /* 180    50  "2" */  CWORD_CWORD_CWORD_CWORD,
918   /* 181    51  "3" */  CWORD_CWORD_CWORD_CWORD,
919   /* 182    52  "4" */  CWORD_CWORD_CWORD_CWORD,
920   /* 183    53  "5" */  CWORD_CWORD_CWORD_CWORD,
921   /* 184    54  "6" */  CWORD_CWORD_CWORD_CWORD,
922   /* 185    55  "7" */  CWORD_CWORD_CWORD_CWORD,
923   /* 186    56  "8" */  CWORD_CWORD_CWORD_CWORD,
924   /* 187    57  "9" */  CWORD_CWORD_CWORD_CWORD,
925   /* 188    58  ":" */  CWORD_CCTL_CCTL_CWORD,
926   /* 189    59  ";" */  CSPCL_CWORD_CWORD_CWORD,
927   /* 190    60  "<" */  CSPCL_CWORD_CWORD_CWORD,
928   /* 191    61  "=" */  CWORD_CCTL_CCTL_CWORD,
929   /* 192    62  ">" */  CSPCL_CWORD_CWORD_CWORD,
930   /* 193    63  "?" */  CWORD_CCTL_CCTL_CWORD,
931   /* 194    64  "@" */  CWORD_CWORD_CWORD_CWORD,
932   /* 195    65  "A" */  CWORD_CWORD_CWORD_CWORD,
933   /* 196    66  "B" */  CWORD_CWORD_CWORD_CWORD,
934   /* 197    67  "C" */  CWORD_CWORD_CWORD_CWORD,
935   /* 198    68  "D" */  CWORD_CWORD_CWORD_CWORD,
936   /* 199    69  "E" */  CWORD_CWORD_CWORD_CWORD,
937   /* 200    70  "F" */  CWORD_CWORD_CWORD_CWORD,
938   /* 201    71  "G" */  CWORD_CWORD_CWORD_CWORD,
939   /* 202    72  "H" */  CWORD_CWORD_CWORD_CWORD,
940   /* 203    73  "I" */  CWORD_CWORD_CWORD_CWORD,
941   /* 204    74  "J" */  CWORD_CWORD_CWORD_CWORD,
942   /* 205    75  "K" */  CWORD_CWORD_CWORD_CWORD,
943   /* 206    76  "L" */  CWORD_CWORD_CWORD_CWORD,
944   /* 207    77  "M" */  CWORD_CWORD_CWORD_CWORD,
945   /* 208    78  "N" */  CWORD_CWORD_CWORD_CWORD,
946   /* 209    79  "O" */  CWORD_CWORD_CWORD_CWORD,
947   /* 210    80  "P" */  CWORD_CWORD_CWORD_CWORD,
948   /* 211    81  "Q" */  CWORD_CWORD_CWORD_CWORD,
949   /* 212    82  "R" */  CWORD_CWORD_CWORD_CWORD,
950   /* 213    83  "S" */  CWORD_CWORD_CWORD_CWORD,
951   /* 214    84  "T" */  CWORD_CWORD_CWORD_CWORD,
952   /* 215    85  "U" */  CWORD_CWORD_CWORD_CWORD,
953   /* 216    86  "V" */  CWORD_CWORD_CWORD_CWORD,
954   /* 217    87  "W" */  CWORD_CWORD_CWORD_CWORD,
955   /* 218    88  "X" */  CWORD_CWORD_CWORD_CWORD,
956   /* 219    89  "Y" */  CWORD_CWORD_CWORD_CWORD,
957   /* 220    90  "Z" */  CWORD_CWORD_CWORD_CWORD,
958   /* 221    91  "[" */  CWORD_CCTL_CCTL_CWORD,
959   /* 222    92  "\" */  CBACK_CBACK_CCTL_CBACK,
960   /* 223    93  "]" */  CWORD_CCTL_CCTL_CWORD,
961   /* 224    94  "^" */  CWORD_CWORD_CWORD_CWORD,
962   /* 225    95  "_" */  CWORD_CWORD_CWORD_CWORD,
963   /* 226    96  "`" */  CBQUOTE_CBQUOTE_CWORD_CBQUOTE,
964   /* 227    97  "a" */  CWORD_CWORD_CWORD_CWORD,
965   /* 228    98  "b" */  CWORD_CWORD_CWORD_CWORD,
966   /* 229    99  "c" */  CWORD_CWORD_CWORD_CWORD,
967   /* 230   100  "d" */  CWORD_CWORD_CWORD_CWORD,
968   /* 231   101  "e" */  CWORD_CWORD_CWORD_CWORD,
969   /* 232   102  "f" */  CWORD_CWORD_CWORD_CWORD,
970   /* 233   103  "g" */  CWORD_CWORD_CWORD_CWORD,
971   /* 234   104  "h" */  CWORD_CWORD_CWORD_CWORD,
972   /* 235   105  "i" */  CWORD_CWORD_CWORD_CWORD,
973   /* 236   106  "j" */  CWORD_CWORD_CWORD_CWORD,
974   /* 237   107  "k" */  CWORD_CWORD_CWORD_CWORD,
975   /* 238   108  "l" */  CWORD_CWORD_CWORD_CWORD,
976   /* 239   109  "m" */  CWORD_CWORD_CWORD_CWORD,
977   /* 240   110  "n" */  CWORD_CWORD_CWORD_CWORD,
978   /* 241   111  "o" */  CWORD_CWORD_CWORD_CWORD,
979   /* 242   112  "p" */  CWORD_CWORD_CWORD_CWORD,
980   /* 243   113  "q" */  CWORD_CWORD_CWORD_CWORD,
981   /* 244   114  "r" */  CWORD_CWORD_CWORD_CWORD,
982   /* 245   115  "s" */  CWORD_CWORD_CWORD_CWORD,
983   /* 246   116  "t" */  CWORD_CWORD_CWORD_CWORD,
984   /* 247   117  "u" */  CWORD_CWORD_CWORD_CWORD,
985   /* 248   118  "v" */  CWORD_CWORD_CWORD_CWORD,
986   /* 249   119  "w" */  CWORD_CWORD_CWORD_CWORD,
987   /* 250   120  "x" */  CWORD_CWORD_CWORD_CWORD,
988   /* 251   121  "y" */  CWORD_CWORD_CWORD_CWORD,
989   /* 252   122  "z" */  CWORD_CWORD_CWORD_CWORD,
990   /* 253   123  "{" */  CWORD_CWORD_CWORD_CWORD,
991   /* 254   124  "|" */  CSPCL_CWORD_CWORD_CWORD,
992   /* 255   125  "}" */  CENDVAR_CENDVAR_CWORD_CENDVAR,
993   /* 256   126  "~" */  CWORD_CCTL_CCTL_CWORD,
994   /* 257   127      */  CWORD_CWORD_CWORD_CWORD,
995 };
996
997 #endif  /* USE_SIT_FUNCTION */
998
999
1000 /* first char is indicating which tokens mark the end of a list */
1001 static const char *const tokname_array[] = {
1002         "\1end of file",
1003         "\0newline",
1004         "\0redirection",
1005         "\0word",
1006         "\0assignment",
1007         "\0;",
1008         "\0&",
1009         "\0&&",
1010         "\0||",
1011         "\0|",
1012         "\0(",
1013         "\1)",
1014         "\1;;",
1015         "\1`",
1016 #define KWDOFFSET 14
1017         /* the following are keywords */
1018         "\0!",
1019         "\0case",
1020         "\1do",
1021         "\1done",
1022         "\1elif",
1023         "\1else",
1024         "\1esac",
1025         "\1fi",
1026         "\0for",
1027         "\0if",
1028         "\0in",
1029         "\1then",
1030         "\0until",
1031         "\0while",
1032         "\0{",
1033         "\1}",
1034 };
1035
1036 static const char *tokname(int tok)
1037 {
1038         static char buf[16];
1039
1040         if(tok>=TSEMI)
1041                 buf[0] = '"';
1042         sprintf(buf+(tok>=TSEMI), "%s%c",
1043                         tokname_array[tok]+1, (tok>=TSEMI ? '"' : 0));
1044         return buf;
1045 }
1046
1047 static int plinno = 1;          /* input line number */
1048
1049 static int parselleft;          /* copy of parsefile->lleft */
1050
1051 static struct parsefile basepf; /* top level input file */
1052 static char basebuf[BUFSIZ];    /* buffer for top level input file */
1053 static struct parsefile *parsefile = &basepf;  /* current input file */
1054
1055 /*
1056  * NEOF is returned by parsecmd when it encounters an end of file.  It
1057  * must be distinct from NULL, so we use the address of a variable that
1058  * happens to be handy.
1059  */
1060
1061 static int tokpushback;         /* last token pushed back */
1062 #define NEOF ((union node *)&tokpushback)
1063 static int checkkwd;            /* 1 == check for kwds, 2 == also eat newlines */
1064
1065
1066 static void error (const char *, ...) __attribute__((__noreturn__));
1067 static void exerror (int, const char *, ...) __attribute__((__noreturn__));
1068 static void shellexec (char **, char **, const char *, int)
1069     __attribute__((noreturn));
1070 static void exitshell (int) __attribute__((noreturn));
1071
1072 static int  goodname(const char *);
1073 static void ignoresig (int);
1074 static void onsig (int);
1075 static void dotrap (void);
1076 static int  decode_signal (const char *, int);
1077
1078 static void shprocvar(void);
1079 static void deletefuncs(void);
1080 static void setparam (char **);
1081 static void freeparam (volatile struct shparam *);
1082
1083 static void find_command (const char *, struct cmdentry *, int, const char *);
1084
1085 static inline void hashcd (void);
1086
1087 /* reasons for skipping commands (see comment on breakcmd routine) */
1088 #define SKIPBREAK       1
1089 #define SKIPCONT        2
1090 #define SKIPFUNC        3
1091 #define SKIPFILE        4
1092
1093 /* values of cmdtype */
1094 #define CMDUNKNOWN -1           /* no entry in table for command */
1095 #define CMDNORMAL 0             /* command is an executable program */
1096 #define CMDBUILTIN 1            /* command is a shell builtin */
1097 #define CMDFUNCTION 2           /* command is a shell function */
1098
1099 #define DO_ERR  1               /* find_command prints errors */
1100 #define DO_ABS  2               /* find_command checks absolute paths */
1101 #define DO_NOFUN        4       /* find_command ignores functions */
1102 #define DO_BRUTE        8       /* find_command ignores hash table */
1103
1104 /*
1105  * Shell variables.
1106  */
1107
1108 /* flags */
1109 #define VEXPORT         0x01    /* variable is exported */
1110 #define VREADONLY       0x02    /* variable cannot be modified */
1111 #define VSTRFIXED       0x04    /* variable struct is staticly allocated */
1112 #define VTEXTFIXED      0x08    /* text is staticly allocated */
1113 #define VSTACK          0x10    /* text is allocated on the stack */
1114 #define VUNSET          0x20    /* the variable is not set */
1115 #define VNOFUNC         0x40    /* don't call the callback function */
1116
1117
1118 struct var {
1119         struct var *next;               /* next entry in hash list */
1120         int flags;                      /* flags are defined above */
1121         char *text;                     /* name=value */
1122         void (*func) (const char *);
1123                                         /* function to be called when  */
1124                                         /* the variable gets set/unset */
1125 };
1126
1127 struct localvar {
1128         struct localvar *next;          /* next local variable in list */
1129         struct var *vp;                 /* the variable that was made local */
1130         int flags;                      /* saved flags */
1131         char *text;                     /* saved text */
1132 };
1133
1134
1135 #if defined(__GLIBC__) && __GLIBC__ >= 2 && !defined(FNMATCH_BROKEN)
1136 #define rmescapes(p) _rmescapes((p), 0)
1137 static char *_rmescapes (char *, int);
1138 #else
1139 static void rmescapes (char *);
1140 #endif
1141
1142 static int  casematch (union node *, const char *);
1143 static void clearredir(void);
1144 static void popstring(void);
1145 static void readcmdfile (const char *);
1146
1147 static int number (const char *);
1148 static int is_number (const char *, int *num);
1149 static char *single_quote (const char *);
1150 static int nextopt (const char *);
1151
1152 static void redirect (union node *, int);
1153 static void popredir (void);
1154 static int dup_as_newfd (int, int);
1155
1156 static void changepath(const char *newval);
1157 static void getoptsreset(const char *value);
1158
1159
1160 static int parsenleft;                  /* copy of parsefile->nleft */
1161 static char *parsenextc;                /* copy of parsefile->nextc */
1162 static int rootpid;     /* pid of main shell */
1163 static int rootshell;   /* true if we aren't a child of the main shell */
1164
1165 static const char spcstr[] = " ";
1166 static const char snlfmt[] = "%s\n";
1167
1168 static int sstrnleft;
1169 static int herefd = -1;
1170
1171 static struct localvar *localvars;
1172
1173 static struct var vifs;
1174 static struct var vmail;
1175 static struct var vmpath;
1176 static struct var vpath;
1177 static struct var vps1;
1178 static struct var vps2;
1179 static struct var voptind;
1180 #ifdef CONFIG_LOCALE_SUPPORT
1181 static struct var vlc_all;
1182 static struct var vlc_ctype;
1183 #endif
1184
1185 struct varinit {
1186         struct var *var;
1187         int flags;
1188         const char *text;
1189         void (*func) (const char *);
1190 };
1191
1192 static const char defpathvar[] =
1193         "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin";
1194 #define defpath (defpathvar + 5)
1195
1196 #ifdef IFS_BROKEN
1197 static const char defifsvar[] = "IFS= \t\n";
1198 #define defifs (defifsvar + 4)
1199 #else
1200 static const char defifs[] = " \t\n";
1201 #endif
1202
1203 static const struct varinit varinit[] = {
1204 #ifdef IFS_BROKEN
1205         { &vifs,        VSTRFIXED|VTEXTFIXED,           defifsvar,
1206 #else
1207         { &vifs,        VSTRFIXED|VTEXTFIXED|VUNSET,    "IFS=",
1208 #endif
1209           NULL },
1210         { &vmail,       VSTRFIXED|VTEXTFIXED|VUNSET,    "MAIL=",
1211           NULL },
1212         { &vmpath,      VSTRFIXED|VTEXTFIXED|VUNSET,    "MAILPATH=",
1213           NULL },
1214         { &vpath,       VSTRFIXED|VTEXTFIXED,           defpathvar,
1215           changepath },
1216 #if defined(CONFIG_FEATURE_COMMAND_EDITING) && defined(CONFIG_FEATURE_SH_FANCY_PROMPT)
1217         { &vps1,        VSTRFIXED|VTEXTFIXED,           "PS1=\\w \\$ ",
1218           NULL },
1219 #endif /* else vps1 depends on uid */
1220         { &vps2,        VSTRFIXED|VTEXTFIXED,           "PS2=> ",
1221           NULL },
1222         { &voptind,     VSTRFIXED|VTEXTFIXED,           "OPTIND=1",
1223           getoptsreset },
1224 #ifdef CONFIG_LOCALE_SUPPORT
1225         { &vlc_all,     VSTRFIXED|VTEXTFIXED|VUNSET,    "LC_ALL=",
1226           change_lc_all },
1227         { &vlc_ctype,   VSTRFIXED|VTEXTFIXED|VUNSET,    "LC_CTYPE=",
1228           change_lc_ctype },
1229 #endif
1230         { NULL, 0,                              NULL,
1231           NULL }
1232 };
1233
1234 #define VTABSIZE 39
1235
1236 static struct var *vartab[VTABSIZE];
1237
1238 /*
1239  * The following macros access the values of the above variables.
1240  * They have to skip over the name.  They return the null string
1241  * for unset variables.
1242  */
1243
1244 #define ifsval()        (vifs.text + 4)
1245 #define ifsset()        ((vifs.flags & VUNSET) == 0)
1246 #define mailval()       (vmail.text + 5)
1247 #define mpathval()      (vmpath.text + 9)
1248 #define pathval()       (vpath.text + 5)
1249 #define ps1val()        (vps1.text + 4)
1250 #define ps2val()        (vps2.text + 4)
1251 #define optindval()     (voptind.text + 7)
1252
1253 #define mpathset()      ((vmpath.flags & VUNSET) == 0)
1254
1255 static void initvar (void);
1256 static void setvar (const char *, const char *, int);
1257 static void setvareq (char *, int);
1258 static void listsetvar (struct strlist *);
1259 static const char *lookupvar (const char *);
1260 static const char *bltinlookup (const char *);
1261 static char **environment (void);
1262 static int showvarscmd (int, char **);
1263 static void mklocal (char *);
1264 static void poplocalvars (void);
1265 static int unsetvar (const char *);
1266 static int varequal (const char *, const char *);
1267
1268
1269 static char *arg0;                      /* value of $0 */
1270 static struct shparam shellparam;       /* current positional parameters */
1271 static char **argptr;                   /* argument list for builtin commands */
1272 static char *optionarg;                 /* set by nextopt (like getopt) */
1273 static char *optptr;                    /* used by nextopt */
1274 static char *minusc;                    /* argument to -c option */
1275
1276
1277 #ifdef CONFIG_ASH_ALIAS
1278
1279 #define ALIASINUSE      1
1280 #define ALIASDEAD       2
1281
1282 #define ATABSIZE 39
1283
1284 struct alias {
1285         struct alias *next;
1286         char *name;
1287         char *val;
1288         int flag;
1289 };
1290
1291 static struct alias *atab[ATABSIZE];
1292
1293 static void setalias (char *, char *);
1294 static struct alias **hashalias (const char *);
1295 static struct alias *freealias (struct alias *);
1296 static struct alias **__lookupalias (const char *);
1297
1298 static void
1299 setalias(char *name, char *val)
1300 {
1301         struct alias *ap, **app;
1302
1303         app = __lookupalias(name);
1304         ap = *app;
1305         INTOFF;
1306         if (ap) {
1307                 if (!(ap->flag & ALIASINUSE)) {
1308                         ckfree(ap->val);
1309                 }
1310                 ap->val = xstrdup(val);
1311                 ap->flag &= ~ALIASDEAD;
1312         } else {
1313                 /* not found */
1314                 ap = xmalloc(sizeof (struct alias));
1315                 ap->name = xstrdup(name);
1316                 ap->val = xstrdup(val);
1317                 ap->flag = 0;
1318                 ap->next = 0;
1319                 *app = ap;
1320         }
1321         INTON;
1322 }
1323
1324 static int
1325 unalias(char *name)
1326 {
1327         struct alias **app;
1328
1329         app = __lookupalias(name);
1330
1331         if (*app) {
1332                 INTOFF;
1333                 *app = freealias(*app);
1334                 INTON;
1335                 return (0);
1336         }
1337
1338         return (1);
1339 }
1340
1341 static void
1342 rmaliases(void)
1343 {
1344         struct alias *ap, **app;
1345         int i;
1346
1347         INTOFF;
1348         for (i = 0; i < ATABSIZE; i++) {
1349                 app = &atab[i];
1350                 for (ap = *app; ap; ap = *app) {
1351                         *app = freealias(*app);
1352                         if (ap == *app) {
1353                                 app = &ap->next;
1354                         }
1355                 }
1356         }
1357         INTON;
1358 }
1359
1360 static void
1361 printalias(const struct alias *ap) {
1362         char *p;
1363
1364         p = single_quote(ap->val);
1365         printf("alias %s=%s\n", ap->name, p);
1366         stunalloc(p);
1367 }
1368
1369
1370 /*
1371  * TODO - sort output
1372  */
1373 static int
1374 aliascmd(int argc, char **argv)
1375 {
1376         char *n, *v;
1377         int ret = 0;
1378         struct alias *ap;
1379
1380         if (argc == 1) {
1381                 int i;
1382
1383                 for (i = 0; i < ATABSIZE; i++)
1384                         for (ap = atab[i]; ap; ap = ap->next) {
1385                                 printalias(ap);
1386                         }
1387                 return (0);
1388         }
1389         while ((n = *++argv) != NULL) {
1390                 if ((v = strchr(n+1, '=')) == NULL) { /* n+1: funny ksh stuff */
1391                         if ((ap = *__lookupalias(n)) == NULL) {
1392                                 out2fmt("%s: %s not found\n", "alias", n);
1393                                 ret = 1;
1394                         } else
1395                                 printalias(ap);
1396                 }
1397                 else {
1398                         *v++ = '\0';
1399                         setalias(n, v);
1400                 }
1401         }
1402
1403         return (ret);
1404 }
1405
1406 static int
1407 unaliascmd(int argc, char **argv)
1408 {
1409         int i;
1410
1411         while ((i = nextopt("a")) != '\0') {
1412                 if (i == 'a') {
1413                         rmaliases();
1414                         return (0);
1415                 }
1416         }
1417         for (i = 0; *argptr; argptr++) {
1418                 if (unalias(*argptr)) {
1419                         out2fmt("%s: %s not found\n", "unalias", *argptr);
1420                         i = 1;
1421                 }
1422         }
1423
1424         return (i);
1425 }
1426
1427 static struct alias **
1428 hashalias(const char *p)
1429 {
1430         unsigned int hashval;
1431
1432         hashval = *p << 4;
1433         while (*p)
1434                 hashval+= *p++;
1435         return &atab[hashval % ATABSIZE];
1436 }
1437
1438 static struct alias *
1439 freealias(struct alias *ap)
1440 {
1441         struct alias *next;
1442
1443         if (ap->flag & ALIASINUSE) {
1444                 ap->flag |= ALIASDEAD;
1445                 return ap;
1446         }
1447
1448         next = ap->next;
1449         ckfree(ap->name);
1450         ckfree(ap->val);
1451         ckfree(ap);
1452         return next;
1453 }
1454
1455
1456 static struct alias **
1457 __lookupalias(const char *name)
1458 {
1459         struct alias **app = hashalias(name);
1460
1461         for (; *app; app = &(*app)->next) {
1462                 if (equal(name, (*app)->name)) {
1463                         break;
1464                 }
1465         }
1466
1467         return app;
1468 }
1469 #endif
1470
1471 #ifdef CONFIG_ASH_MATH_SUPPORT
1472 /* The generated file arith.c has been replaced with a custom hand
1473  * written implementation written by Aaron Lehmann <aaronl@vitelus.com>.
1474  * This is now part of libbb, so that it can be used by all the shells
1475  * in busybox. */
1476 static void expari (int);
1477 #endif
1478
1479 static char *trap[NSIG];                /* trap handler commands */
1480 static char sigmode[NSIG - 1];  /* current value of signal */
1481 static char gotsig[NSIG - 1];           /* indicates specified signal received */
1482 static int pendingsigs;                 /* indicates some signal received */
1483
1484 /*
1485  * This file was generated by the mkbuiltins program.
1486  */
1487
1488 #ifdef CONFIG_ASH_JOB_CONTROL
1489 static int bgcmd (int, char **);
1490 static int fgcmd (int, char **);
1491 static int killcmd (int, char **);
1492 #endif
1493 static int bltincmd (int, char **);
1494 static int cdcmd (int, char **);
1495 static int breakcmd (int, char **);
1496 #ifdef CONFIG_ASH_CMDCMD
1497 static int commandcmd (int, char **);
1498 #endif
1499 static int dotcmd (int, char **);
1500 static int evalcmd (int, char **);
1501 static int execcmd (int, char **);
1502 static int exitcmd (int, char **);
1503 static int exportcmd (int, char **);
1504 static int histcmd (int, char **);
1505 static int hashcmd (int, char **);
1506 static int helpcmd (int, char **);
1507 static int jobscmd (int, char **);
1508 static int localcmd (int, char **);
1509 static int pwdcmd (int, char **);
1510 static int readcmd (int, char **);
1511 static int returncmd (int, char **);
1512 static int setcmd (int, char **);
1513 static int setvarcmd (int, char **);
1514 static int shiftcmd (int, char **);
1515 static int trapcmd (int, char **);
1516 static int umaskcmd (int, char **);
1517 #ifdef CONFIG_ASH_ALIAS
1518 static int aliascmd (int, char **);
1519 static int unaliascmd (int, char **);
1520 #endif
1521 static int unsetcmd (int, char **);
1522 static int waitcmd (int, char **);
1523 static int ulimitcmd (int, char **);
1524 static int timescmd (int, char **);
1525 #ifdef CONFIG_ASH_MATH_SUPPORT
1526 static int letcmd (int, char **);
1527 #endif
1528 static int typecmd (int, char **);
1529 #ifdef CONFIG_ASH_GETOPTS
1530 static int getoptscmd (int, char **);
1531 #endif
1532
1533 #ifndef CONFIG_TRUE
1534 static int true_main (int, char **);
1535 #endif
1536 #ifndef CONFIG_FALSE
1537 static int false_main (int, char **);
1538 #endif
1539
1540 static void     setpwd (const char *, int);
1541
1542
1543 #define BUILTIN_NOSPEC  "0"
1544 #define BUILTIN_SPECIAL "1"
1545 #define BUILTIN_REGULAR "2"
1546 #define BUILTIN_ASSIGN  "4"
1547 #define BUILTIN_SPEC_ASSG  "5"
1548 #define BUILTIN_REG_ASSG   "6"
1549
1550 #define IS_BUILTIN_SPECIAL(builtincmd) ((builtincmd)->name[0] & 1)
1551 #define IS_BUILTIN_REGULAR(builtincmd) ((builtincmd)->name[0] & 2)
1552 #define IS_BUILTIN_ASSIGN(builtincmd) ((builtincmd)->name[0] & 4)
1553
1554 struct builtincmd {
1555         const char *name;
1556         int (*const builtinfunc) (int, char **);
1557         //unsigned flags;
1558 };
1559
1560
1561 /* It is CRUCIAL that this listing be kept in ascii order, otherwise
1562  * the binary search in find_builtin() will stop working. If you value
1563  * your kneecaps, you'll be sure to *make sure* that any changes made
1564  * to this array result in the listing remaining in ascii order. You
1565  * have been warned.
1566  */
1567 static const struct builtincmd builtincmds[] = {
1568         { BUILTIN_SPECIAL   ".", dotcmd },    /* first, see declare DOTCMD */
1569         { BUILTIN_SPECIAL   ":", true_main },
1570 #ifdef CONFIG_ASH_ALIAS
1571         { BUILTIN_REG_ASSG  "alias", aliascmd },
1572 #endif
1573 #ifdef CONFIG_ASH_JOB_CONTROL
1574         { BUILTIN_REGULAR   "bg", bgcmd },
1575 #endif
1576         { BUILTIN_SPECIAL   "break", breakcmd },
1577         { BUILTIN_SPECIAL   "builtin", bltincmd },
1578         { BUILTIN_REGULAR   "cd", cdcmd },
1579         { BUILTIN_NOSPEC    "chdir", cdcmd },
1580 #ifdef CONFIG_ASH_CMDCMD
1581         { BUILTIN_REGULAR   "command", commandcmd },
1582 #endif
1583         { BUILTIN_SPECIAL   "continue", breakcmd },
1584         { BUILTIN_SPECIAL   "eval", evalcmd },
1585         { BUILTIN_SPECIAL   "exec", execcmd },
1586         { BUILTIN_SPECIAL   "exit", exitcmd },
1587         { BUILTIN_SPEC_ASSG "export", exportcmd },
1588         { BUILTIN_REGULAR   "false", false_main },
1589         { BUILTIN_REGULAR   "fc", histcmd },
1590 #ifdef CONFIG_ASH_JOB_CONTROL
1591         { BUILTIN_REGULAR   "fg", fgcmd },
1592 #endif
1593 #ifdef CONFIG_ASH_GETOPTS
1594         { BUILTIN_REGULAR   "getopts", getoptscmd },
1595 #endif
1596         { BUILTIN_NOSPEC    "hash", hashcmd },
1597         { BUILTIN_NOSPEC    "help", helpcmd },
1598         { BUILTIN_REGULAR   "jobs", jobscmd },
1599 #ifdef CONFIG_ASH_JOB_CONTROL
1600         { BUILTIN_REGULAR   "kill", killcmd },
1601 #endif
1602 #ifdef CONFIG_ASH_MATH_SUPPORT
1603         { BUILTIN_REGULAR    "let", letcmd },
1604 #endif
1605         { BUILTIN_ASSIGN    "local", localcmd },
1606         { BUILTIN_NOSPEC    "pwd", pwdcmd },
1607         { BUILTIN_REGULAR   "read", readcmd },
1608         { BUILTIN_SPEC_ASSG "readonly", exportcmd },
1609         { BUILTIN_SPECIAL   "return", returncmd },
1610         { BUILTIN_SPECIAL   "set", setcmd },
1611         { BUILTIN_NOSPEC    "setvar", setvarcmd },
1612         { BUILTIN_SPECIAL   "shift", shiftcmd },
1613         { BUILTIN_SPECIAL   "times", timescmd },
1614         { BUILTIN_SPECIAL   "trap", trapcmd },
1615         { BUILTIN_REGULAR   "true", true_main },
1616         { BUILTIN_NOSPEC    "type", typecmd },
1617         { BUILTIN_NOSPEC    "ulimit", ulimitcmd },
1618         { BUILTIN_REGULAR   "umask", umaskcmd },
1619 #ifdef CONFIG_ASH_ALIAS
1620         { BUILTIN_REGULAR   "unalias", unaliascmd },
1621 #endif
1622         { BUILTIN_SPECIAL   "unset", unsetcmd },
1623         { BUILTIN_REGULAR   "wait", waitcmd },
1624 };
1625 #define NUMBUILTINS  (sizeof (builtincmds) / sizeof (struct builtincmd) )
1626
1627 #define DOTCMD &builtincmds[0]
1628 static struct builtincmd *BLTINCMD;
1629 static struct builtincmd *EXECCMD;
1630 static struct builtincmd *EVALCMD;
1631
1632 /* states */
1633 #define CONFIG_ASH_JOB_CONTROLTOPPED 1            /* all procs are stopped */
1634 #define JOBDONE 2               /* all procs are completed */
1635
1636 /*
1637  * A job structure contains information about a job.  A job is either a
1638  * single process or a set of processes contained in a pipeline.  In the
1639  * latter case, pidlist will be non-NULL, and will point to a -1 terminated
1640  * array of pids.
1641  */
1642
1643 struct procstat {
1644         pid_t pid;              /* process id */
1645         int status;             /* status flags (defined above) */
1646         char *cmd;              /* text of command being run */
1647 };
1648
1649
1650 static int job_warning;         /* user was warned about stopped jobs */
1651
1652 #ifdef CONFIG_ASH_JOB_CONTROL
1653 static void setjobctl(int enable);
1654 #else
1655 #define setjobctl(on)   /* do nothing */
1656 #endif
1657
1658
1659 struct job {
1660         struct procstat ps0;    /* status of process */
1661         struct procstat *ps;    /* status or processes when more than one */
1662         short nprocs;           /* number of processes */
1663         short pgrp;             /* process group of this job */
1664         char state;             /* true if job is finished */
1665         char used;              /* true if this entry is in used */
1666         char changed;           /* true if status has changed */
1667 #ifdef CONFIG_ASH_JOB_CONTROL
1668         char jobctl;            /* job running under job control */
1669 #endif
1670 };
1671
1672 static struct job *jobtab;      /* array of jobs */
1673 static int njobs;               /* size of array */
1674 static int backgndpid = -1;     /* pid of last background process */
1675 #ifdef CONFIG_ASH_JOB_CONTROL
1676 static int initialpgrp;         /* pgrp of shell on invocation */
1677 static int curjob;              /* current job */
1678 static int jobctl;
1679 #endif
1680 static int intreceived;
1681
1682 static struct job *makejob (const union node *, int);
1683 static int forkshell (struct job *, const union node *, int);
1684 static int waitforjob (struct job *);
1685
1686 static int docd (char *, int);
1687 static void getpwd (void);
1688
1689 static char *padvance (const char **, const char *);
1690
1691 static char nullstr[1];         /* zero length string */
1692 static char *curdir = nullstr;          /* current working directory */
1693
1694 static int
1695 cdcmd(int argc, char **argv)
1696 {
1697         const char *dest;
1698         const char *path;
1699         char *p;
1700         struct stat statb;
1701         int print = 0;
1702
1703         nextopt(nullstr);
1704         if ((dest = *argptr) == NULL && (dest = bltinlookup("HOME")) == NULL)
1705                 error("HOME not set");
1706         if (*dest == '\0')
1707                 dest = ".";
1708         if (dest[0] == '-' && dest[1] == '\0') {
1709                 dest = bltinlookup("OLDPWD");
1710                 if (!dest || !*dest) {
1711                         dest = curdir;
1712                 }
1713                 print = 1;
1714                 if (dest)
1715                         print = 1;
1716                 else
1717                         dest = ".";
1718         }
1719         if (*dest == '/' || (path = bltinlookup("CDPATH")) == NULL)
1720                 path = nullstr;
1721         while ((p = padvance(&path, dest)) != NULL) {
1722                 if (stat(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) {
1723                         if (!print) {
1724                                 /*
1725                                  * XXX - rethink
1726                                  */
1727                                 if (p[0] == '.' && p[1] == '/' && p[2] != '\0')
1728                                         p += 2;
1729                                 print = strcmp(p, dest);
1730                         }
1731                         if (docd(p, print) >= 0)
1732                                 return 0;
1733
1734                 }
1735         }
1736         error("can't cd to %s", dest);
1737         /* NOTREACHED */
1738 }
1739
1740
1741 /*
1742  * Actually do the chdir.  In an interactive shell, print the
1743  * directory name if "print" is nonzero.
1744  */
1745
1746 static int
1747 docd(char *dest, int print)
1748 {
1749         TRACE(("docd(\"%s\", %d) called\n", dest, print));
1750         INTOFF;
1751         if (chdir(dest) < 0) {
1752                 INTON;
1753                 return -1;
1754         }
1755         hashcd();
1756         /*
1757          * Update curdir (the name of the current directory) in response to a
1758          * cd command.  We also call hashcd to let the routines in exec.c know
1759          * that the current directory has changed.
1760          */
1761         /* If dest is NULL, we don't know the current directory */
1762         if (dest == NULL || curdir == nullstr)
1763                 setpwd(0, 1);
1764         else
1765                 setpwd(dest, 1);
1766
1767         INTON;
1768         if (print && iflag)
1769                 puts(curdir);
1770         return 0;
1771 }
1772
1773
1774 static int
1775 pwdcmd(int argc, char **argv)
1776 {
1777         puts(curdir);
1778         return 0;
1779 }
1780
1781 /* Ask system the current directory */
1782 static void
1783 getpwd(void)
1784 {
1785         curdir = xgetcwd(0);
1786         if(curdir==0)
1787                 curdir = nullstr;
1788 }
1789
1790 static void
1791 setpwd(const char *val, int setold)
1792 {
1793         char *cated = NULL;
1794
1795         if (setold) {
1796                 setvar("OLDPWD", curdir, VEXPORT);
1797         }
1798         INTOFF;
1799         if (curdir != nullstr) {
1800                 if(val!=NULL && *val != '/')
1801                         val = cated = concat_path_file(curdir, val);
1802                 free(curdir);
1803         }
1804         if (!val)
1805                 getpwd();
1806          else
1807                 curdir = simplify_path(val);
1808         free(cated);
1809         INTON;
1810         setvar("PWD", curdir, VEXPORT);
1811 }
1812
1813 /*
1814  * Errors and exceptions.
1815  */
1816
1817 /*
1818  * Code to handle exceptions in C.
1819  */
1820
1821 /*
1822  * We enclose jmp_buf in a structure so that we can declare pointers to
1823  * jump locations.  The global variable handler contains the location to
1824  * jump to when an exception occurs, and the global variable exception
1825  * contains a code identifying the exeception.  To implement nested
1826  * exception handlers, the user should save the value of handler on entry
1827  * to an inner scope, set handler to point to a jmploc structure for the
1828  * inner scope, and restore handler on exit from the scope.
1829  */
1830
1831 struct jmploc {
1832         jmp_buf loc;
1833 };
1834
1835 /* exceptions */
1836 #define EXINT 0         /* SIGINT received */
1837 #define EXERROR 1       /* a generic error */
1838 #define EXSHELLPROC 2   /* execute a shell procedure */
1839 #define EXEXEC 3        /* command execution failed */
1840
1841 static struct jmploc *handler;
1842 static int exception;
1843
1844 static void exverror (int, const char *, va_list)
1845     __attribute__((__noreturn__));
1846
1847 /*
1848  * Called to raise an exception.  Since C doesn't include exceptions, we
1849  * just do a longjmp to the exception handler.  The type of exception is
1850  * stored in the global variable "exception".
1851  */
1852
1853 static void exraise (int) __attribute__((__noreturn__));
1854
1855 static void
1856 exraise(int e)
1857 {
1858 #ifdef DEBUG
1859         if (handler == NULL)
1860                 abort();
1861 #endif
1862         flushall();
1863         exception = e;
1864         longjmp(handler->loc, 1);
1865 }
1866
1867
1868 /*
1869  * Called from trap.c when a SIGINT is received.  (If the user specifies
1870  * that SIGINT is to be trapped or ignored using the trap builtin, then
1871  * this routine is not called.)  Suppressint is nonzero when interrupts
1872  * are held using the INTOFF macro.  The call to _exit is necessary because
1873  * there is a short period after a fork before the signal handlers are
1874  * set to the appropriate value for the child.  (The test for iflag is
1875  * just defensive programming.)
1876  */
1877
1878 static void
1879 onint(void) {
1880         sigset_t mysigset;
1881
1882         if (suppressint) {
1883                 intpending++;
1884                 return;
1885         }
1886         intpending = 0;
1887         sigemptyset(&mysigset);
1888         sigprocmask(SIG_SETMASK, &mysigset, NULL);
1889         if (rootshell && iflag)
1890                 exraise(EXINT);
1891         else {
1892                 signal(SIGINT, SIG_DFL);
1893                 raise(SIGINT);
1894         }
1895         /* NOTREACHED */
1896 }
1897
1898
1899 static char *commandname;       /* currently executing command */
1900
1901 /*
1902  * Exverror is called to raise the error exception.  If the first argument
1903  * is not NULL then error prints an error message using printf style
1904  * formatting.  It then raises the error exception.
1905  */
1906 static void
1907 exverror(int cond, const char *msg, va_list ap)
1908 {
1909         CLEAR_PENDING_INT;
1910         INTOFF;
1911
1912 #ifdef DEBUG
1913         if (msg)
1914                 TRACE(("exverror(%d, \"%s\") pid=%d\n", cond, msg, getpid()));
1915         else
1916                 TRACE(("exverror(%d, NULL) pid=%d\n", cond, getpid()));
1917 #endif
1918         if (msg) {
1919                 if (commandname)
1920                         out2fmt("%s: ", commandname);
1921                 vfprintf(stderr, msg, ap);
1922                 out2c('\n');
1923         }
1924         exraise(cond);
1925         /* NOTREACHED */
1926 }
1927
1928
1929 static void
1930 error(const char *msg, ...)
1931 {
1932         va_list ap;
1933         va_start(ap, msg);
1934         exverror(EXERROR, msg, ap);
1935         /* NOTREACHED */
1936         va_end(ap);
1937 }
1938
1939
1940 static void
1941 exerror(int cond, const char *msg, ...)
1942 {
1943         va_list ap;
1944         va_start(ap, msg);
1945         exverror(cond, msg, ap);
1946         /* NOTREACHED */
1947         va_end(ap);
1948 }
1949
1950
1951
1952 /*
1953  * Table of error messages.
1954  */
1955
1956 struct errname {
1957         short errcode;          /* error number */
1958         short  action;           /* operation which encountered the error */
1959 };
1960
1961 /*
1962  * Types of operations (passed to the errmsg routine).
1963  */
1964
1965 #define E_OPEN 01       /* opening a file */
1966 #define E_CREAT 02      /* creating a file */
1967 #define E_EXEC 04       /* executing a program */
1968
1969 #define ALL (E_OPEN|E_CREAT|E_EXEC)
1970
1971 static const struct errname errormsg[] = {
1972         { EINTR,        ALL     },
1973         { EACCES,       ALL     },
1974         { EIO,          ALL     },
1975         { ENOENT,       E_OPEN  },
1976         { ENOENT,       E_CREAT },
1977         { ENOENT,       E_EXEC  },
1978         { ENOTDIR,      E_OPEN  },
1979         { ENOTDIR,      E_CREAT },
1980         { ENOTDIR,      E_EXEC  },
1981         { EISDIR,       ALL     },
1982         { EEXIST,       E_CREAT },
1983 #ifdef EMFILE
1984         { EMFILE,       ALL     },
1985 #endif
1986         { ENFILE,       ALL     },
1987         { ENOSPC,       ALL     },
1988 #ifdef EDQUOT
1989         { EDQUOT,       ALL     },
1990 #endif
1991 #ifdef ENOSR
1992         { ENOSR,        ALL     },
1993 #endif
1994         { ENXIO,        ALL     },
1995         { EROFS,        ALL     },
1996         { ETXTBSY,      ALL     },
1997 #ifdef EAGAIN
1998         { EAGAIN,       E_EXEC  },
1999 #endif
2000         { ENOMEM,       ALL     },
2001 #ifdef ENOLINK
2002         { ENOLINK,      ALL     },
2003 #endif
2004 #ifdef EMULTIHOP
2005         { EMULTIHOP,    ALL     },
2006 #endif
2007 #ifdef ECOMM
2008         { ECOMM,        ALL     },
2009 #endif
2010 #ifdef ESTALE
2011         { ESTALE,       ALL     },
2012 #endif
2013 #ifdef ETIMEDOUT
2014         { ETIMEDOUT,    ALL     },
2015 #endif
2016 #ifdef ELOOP
2017         { ELOOP,        ALL     },
2018 #endif
2019         { E2BIG,        E_EXEC  },
2020 #ifdef ELIBACC
2021         { ELIBACC,      E_EXEC  },
2022 #endif
2023 };
2024
2025 #define ERRNAME_SIZE (sizeof(errormsg)/sizeof(struct errname))
2026
2027 /*
2028  * Return a string describing an error.  The returned string may be a
2029  * pointer to a static buffer that will be overwritten on the next call.
2030  * Action describes the operation that got the error.
2031  */
2032
2033 static const char *
2034 errmsg(int e, int action)
2035 {
2036         struct errname const *ep;
2037         static char buf[12];
2038
2039         for (ep = errormsg ; ep < errormsg+ERRNAME_SIZE; ep++) {
2040                 if (ep->errcode == e && (ep->action & action) != 0)
2041                         return strerror(e);
2042         }
2043
2044         snprintf(buf, sizeof buf, "error %d", e);
2045         return buf;
2046 }
2047
2048
2049 #ifdef CONFIG_ASH_OPTIMIZE_FOR_SIZE
2050 static void
2051 __inton() {
2052         if (--suppressint == 0 && intpending) {
2053                 onint();
2054         }
2055 }
2056 static void forceinton (void) {
2057         suppressint = 0;
2058         if (intpending)
2059                 onint();
2060 }
2061 #endif
2062
2063 /* flags in argument to evaltree */
2064 #define EV_EXIT 01              /* exit after evaluating tree */
2065 #define EV_TESTED 02            /* exit status is checked; ignore -e flag */
2066 #define EV_BACKCMD 04           /* command executing within back quotes */
2067
2068 static int evalskip;                    /* set if we are skipping commands */
2069 static int skipcount;           /* number of levels to skip */
2070 static int loopnest;            /* current loop nesting level */
2071 static int funcnest;                    /* depth of function calls */
2072
2073
2074 static struct strlist *cmdenviron;      /* environment for builtin command */
2075 static int exitstatus;                  /* exit status of last command */
2076 static int oexitstatus;         /* saved exit status */
2077
2078 static void evalsubshell (const union node *, int);
2079 static void expredir (union node *);
2080 static void eprintlist (struct strlist *);
2081
2082 static union node *parsecmd(int);
2083 /*
2084  * Called to reset things after an exception.
2085  */
2086
2087 /*
2088  * The eval commmand.
2089  */
2090 static void evalstring (char *, int);
2091
2092 static int
2093 evalcmd(int argc, char **argv)
2094 {
2095         char *p;
2096         char *concat;
2097         char **ap;
2098
2099         if (argc > 1) {
2100                 p = argv[1];
2101                 if (argc > 2) {
2102                         STARTSTACKSTR(concat);
2103                         ap = argv + 2;
2104                         for (;;) {
2105                                 while (*p)
2106                                         STPUTC(*p++, concat);
2107                                 if ((p = *ap++) == NULL)
2108                                         break;
2109                                 STPUTC(' ', concat);
2110                         }
2111                         STPUTC('\0', concat);
2112                         p = grabstackstr(concat);
2113                 }
2114                 evalstring(p, EV_TESTED);
2115         }
2116         return exitstatus;
2117 }
2118
2119 /*
2120  * Execute a command or commands contained in a string.
2121  */
2122
2123 static void evaltree (union node *, int);
2124 static void setinputstring (char *);
2125 static void popfile (void);
2126 static void setstackmark(struct stackmark *mark);
2127 static void popstackmark(struct stackmark *mark);
2128
2129
2130 static void
2131 evalstring(char *s, int flag)
2132 {
2133         union node *n;
2134         struct stackmark smark;
2135
2136         setstackmark(&smark);
2137         setinputstring(s);
2138         while ((n = parsecmd(0)) != NEOF) {
2139                 evaltree(n, flag);
2140                 popstackmark(&smark);
2141         }
2142         popfile();
2143         popstackmark(&smark);
2144 }
2145
2146 static struct builtincmd *find_builtin (const char *);
2147 static void expandarg (union node *, struct arglist *, int);
2148 static void calcsize (const union node *);
2149 static union node *copynode (const union node *);
2150
2151 /*
2152  * Make a copy of a parse tree.
2153  */
2154
2155 static int     funcblocksize;           /* size of structures in function */
2156 static int     funcstringsize;          /* size of strings in node */
2157 static pointer funcblock;              /* block to allocate function from */
2158 static char   *funcstring;              /* block to allocate strings from */
2159
2160
2161 static inline union node *
2162 copyfunc(union node *n)
2163 {
2164         if (n == NULL)
2165                 return NULL;
2166         funcblocksize = 0;
2167         funcstringsize = 0;
2168         calcsize(n);
2169         funcblock = xmalloc(funcblocksize + funcstringsize);
2170         funcstring = (char *) funcblock + funcblocksize;
2171         return copynode(n);
2172 }
2173
2174 /*
2175  * Free a parse tree.
2176  */
2177
2178 static void
2179 freefunc(union node *n)
2180 {
2181         if (n)
2182                 ckfree(n);
2183 }
2184
2185
2186 /*
2187  * Add a new command entry, replacing any existing command entry for
2188  * the same name.
2189  */
2190
2191 static inline void
2192 addcmdentry(char *name, struct cmdentry *entry)
2193 {
2194         struct tblentry *cmdp;
2195
2196         INTOFF;
2197         cmdp = cmdlookup(name, 1);
2198         if (cmdp->cmdtype == CMDFUNCTION) {
2199                 freefunc(cmdp->param.func);
2200         }
2201         cmdp->cmdtype = entry->cmdtype;
2202         cmdp->param = entry->u;
2203         INTON;
2204 }
2205
2206 static inline void
2207 evalloop(const union node *n, int flags)
2208 {
2209         int status;
2210
2211         loopnest++;
2212         status = 0;
2213         for (;;) {
2214                 evaltree(n->nbinary.ch1, EV_TESTED);
2215                 if (evalskip) {
2216 skipping:         if (evalskip == SKIPCONT && --skipcount <= 0) {
2217                                 evalskip = 0;
2218                                 continue;
2219                         }
2220                         if (evalskip == SKIPBREAK && --skipcount <= 0)
2221                                 evalskip = 0;
2222                         break;
2223                 }
2224                 if (n->type == NWHILE) {
2225                         if (exitstatus != 0)
2226                                 break;
2227                 } else {
2228                         if (exitstatus == 0)
2229                                 break;
2230                 }
2231                 evaltree(n->nbinary.ch2, flags & EV_TESTED);
2232                 status = exitstatus;
2233                 if (evalskip)
2234                         goto skipping;
2235         }
2236         loopnest--;
2237         exitstatus = status;
2238 }
2239
2240 static void
2241 evalfor(const union node *n, int flags)
2242 {
2243         struct arglist arglist;
2244         union node *argp;
2245         struct strlist *sp;
2246         struct stackmark smark;
2247
2248         setstackmark(&smark);
2249         arglist.lastp = &arglist.list;
2250         for (argp = n->nfor.args ; argp ; argp = argp->narg.next) {
2251                 oexitstatus = exitstatus;
2252                 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE | EXP_RECORD);
2253                 if (evalskip)
2254                         goto out;
2255         }
2256         *arglist.lastp = NULL;
2257
2258         exitstatus = 0;
2259         loopnest++;
2260         for (sp = arglist.list ; sp ; sp = sp->next) {
2261                 setvar(n->nfor.var, sp->text, 0);
2262                 evaltree(n->nfor.body, flags & EV_TESTED);
2263                 if (evalskip) {
2264                         if (evalskip == SKIPCONT && --skipcount <= 0) {
2265                                 evalskip = 0;
2266                                 continue;
2267                         }
2268                         if (evalskip == SKIPBREAK && --skipcount <= 0)
2269                                 evalskip = 0;
2270                         break;
2271                 }
2272         }
2273         loopnest--;
2274 out:
2275         popstackmark(&smark);
2276 }
2277
2278 static inline void
2279 evalcase(const union node *n, int flags)
2280 {
2281         union node *cp;
2282         union node *patp;
2283         struct arglist arglist;
2284         struct stackmark smark;
2285
2286         setstackmark(&smark);
2287         arglist.lastp = &arglist.list;
2288         oexitstatus = exitstatus;
2289         expandarg(n->ncase.expr, &arglist, EXP_TILDE);
2290         for (cp = n->ncase.cases ; cp && evalskip == 0 ; cp = cp->nclist.next) {
2291                 for (patp = cp->nclist.pattern ; patp ; patp = patp->narg.next) {
2292                         if (casematch(patp, arglist.list->text)) {
2293                                 if (evalskip == 0) {
2294                                         evaltree(cp->nclist.body, flags);
2295                                 }
2296                                 goto out;
2297                         }
2298                 }
2299         }
2300 out:
2301         popstackmark(&smark);
2302 }
2303
2304 /*
2305  * Evaluate a pipeline.  All the processes in the pipeline are children
2306  * of the process creating the pipeline.  (This differs from some versions
2307  * of the shell, which make the last process in a pipeline the parent
2308  * of all the rest.)
2309  */
2310
2311 static inline void evalpipe(union node *n)
2312 {
2313         struct job *jp;
2314         struct nodelist *lp;
2315         int pipelen;
2316         int prevfd;
2317         int pip[2];
2318
2319         TRACE(("evalpipe(0x%lx) called\n", (long)n));
2320         pipelen = 0;
2321         for (lp = n->npipe.cmdlist ; lp ; lp = lp->next)
2322                 pipelen++;
2323         INTOFF;
2324         jp = makejob(n, pipelen);
2325         prevfd = -1;
2326         for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {
2327                 /*
2328                  * Search for a command.  This is called before we fork so that the
2329                  * location of the command will be available in the parent as well as
2330                  * the child.  The check for "goodname" is an overly conservative
2331                  * check that the name will not be subject to expansion.
2332                  */
2333
2334                 struct cmdentry entry;
2335                 union node *lpn = lp->n;
2336                 if (lpn->type == NCMD && lpn->ncmd.args && goodname(lpn->ncmd.args->narg.text))
2337                         find_command(lpn->ncmd.args->narg.text, &entry, 0, pathval());
2338
2339                 pip[1] = -1;
2340                 if (lp->next) {
2341                         if (pipe(pip) < 0) {
2342                                 close(prevfd);
2343                                 error("Pipe call failed");
2344                         }
2345                 }
2346                 if (forkshell(jp, lp->n, n->npipe.backgnd) == 0) {
2347                         INTON;
2348                         if (prevfd > 0) {
2349                                 close(0);
2350                                 dup_as_newfd(prevfd, 0);
2351                                 close(prevfd);
2352                                 if (pip[0] == 0) {
2353                                         pip[0] = -1;
2354                                 }
2355                         }
2356                         if (pip[1] >= 0) {
2357                                 if (pip[0] >= 0) {
2358                                         close(pip[0]);
2359                                 }
2360                                 if (pip[1] != 1) {
2361                                         close(1);
2362                                         dup_as_newfd(pip[1], 1);
2363                                         close(pip[1]);
2364                                 }
2365                         }
2366                         evaltree(lp->n, EV_EXIT);
2367                 }
2368                 if (prevfd >= 0)
2369                         close(prevfd);
2370                 prevfd = pip[0];
2371                 close(pip[1]);
2372         }
2373         INTON;
2374         if (n->npipe.backgnd == 0) {
2375                 INTOFF;
2376                 exitstatus = waitforjob(jp);
2377                 TRACE(("evalpipe:  job done exit status %d\n", exitstatus));
2378                 INTON;
2379         }
2380 }
2381
2382 static int
2383 isassignment(const char *word) {
2384         if (!is_name(*word)) {
2385                 return 0;
2386         }
2387         do {
2388                 word++;
2389         } while (is_in_name(*word));
2390         return *word == '=';
2391 }
2392
2393
2394 static void
2395 evalcommand(union node *cmd, int flags)
2396 {
2397         struct stackmark smark;
2398         union node *argp;
2399         struct arglist arglist;
2400         struct arglist varlist;
2401         char **argv;
2402         int argc;
2403         char **envp;
2404         struct strlist *sp;
2405         int mode;
2406         struct cmdentry cmdentry;
2407         struct job *jp;
2408         char *volatile savecmdname;
2409         volatile struct shparam saveparam;
2410         struct localvar *volatile savelocalvars;
2411         volatile int e;
2412         char *lastarg;
2413         const char *path;
2414         const struct builtincmd *firstbltin;
2415         struct jmploc *volatile savehandler;
2416         struct jmploc jmploc;
2417 #if __GNUC__
2418         /* Avoid longjmp clobbering */
2419         (void) &argv;
2420         (void) &argc;
2421         (void) &lastarg;
2422         (void) &flags;
2423 #endif
2424
2425         /* First expand the arguments. */
2426         TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
2427         setstackmark(&smark);
2428         arglist.lastp = &arglist.list;
2429         varlist.lastp = &varlist.list;
2430         arglist.list = 0;
2431         oexitstatus = exitstatus;
2432         exitstatus = 0;
2433         path = pathval();
2434         for (argp = cmd->ncmd.assign; argp; argp = argp->narg.next) {
2435                 expandarg(argp, &varlist, EXP_VARTILDE);
2436         }
2437         for (
2438                 argp = cmd->ncmd.args; argp && !arglist.list;
2439                 argp = argp->narg.next
2440         ) {
2441                 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
2442         }
2443         if (argp) {
2444                 struct builtincmd *bcmd;
2445                 int pseudovarflag;
2446                 bcmd = find_builtin(arglist.list->text);
2447                 pseudovarflag = bcmd && IS_BUILTIN_ASSIGN(bcmd);
2448                 for (; argp; argp = argp->narg.next) {
2449                         if (pseudovarflag && isassignment(argp->narg.text)) {
2450                                 expandarg(argp, &arglist, EXP_VARTILDE);
2451                                 continue;
2452                         }
2453                         expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
2454                 }
2455         }
2456         *arglist.lastp = NULL;
2457         *varlist.lastp = NULL;
2458         expredir(cmd->ncmd.redirect);
2459         argc = 0;
2460         for (sp = arglist.list ; sp ; sp = sp->next)
2461                 argc++;
2462         argv = stalloc(sizeof (char *) * (argc + 1));
2463
2464         for (sp = arglist.list ; sp ; sp = sp->next) {
2465                 TRACE(("evalcommand arg: %s\n", sp->text));
2466                 *argv++ = sp->text;
2467         }
2468         *argv = NULL;
2469         lastarg = NULL;
2470         if (iflag && funcnest == 0 && argc > 0)
2471                 lastarg = argv[-1];
2472         argv -= argc;
2473
2474         /* Print the command if xflag is set. */
2475         if (xflag) {
2476                 out2c('+');
2477                 eprintlist(varlist.list);
2478                 eprintlist(arglist.list);
2479                 out2c('\n');
2480         }
2481
2482         /* Now locate the command. */
2483         if (argc == 0) {
2484                 cmdentry.cmdtype = CMDBUILTIN;
2485                 firstbltin = cmdentry.u.cmd = BLTINCMD;
2486         } else {
2487                 const char *oldpath;
2488                 int findflag = DO_ERR;
2489                 int oldfindflag;
2490
2491                 /*
2492                  * Modify the command lookup path, if a PATH= assignment
2493                  * is present
2494                  */
2495                 for (sp = varlist.list ; sp ; sp = sp->next)
2496                         if (varequal(sp->text, defpathvar)) {
2497                                 path = sp->text + 5;
2498                                 findflag |= DO_BRUTE;
2499                         }
2500                 oldpath = path;
2501                 oldfindflag = findflag;
2502                 firstbltin = 0;
2503                 for(;;) {
2504                         find_command(argv[0], &cmdentry, findflag, path);
2505                         if (cmdentry.cmdtype == CMDUNKNOWN) {   /* command not found */
2506                                 exitstatus = 127;
2507                                 goto out;
2508                         }
2509                         /* implement bltin and command here */
2510                         if (cmdentry.cmdtype != CMDBUILTIN) {
2511                                 break;
2512                         }
2513                         if (!firstbltin) {
2514                                 firstbltin = cmdentry.u.cmd;
2515                         }
2516                         if (cmdentry.u.cmd == BLTINCMD) {
2517                                 for(;;) {
2518                                         struct builtincmd *bcmd;
2519
2520                                         argv++;
2521                                         if (--argc == 0)
2522                                                 goto found;
2523                                         if (!(bcmd = find_builtin(*argv))) {
2524                                                 out2fmt("%s: not found\n", *argv);
2525                                                 exitstatus = 127;
2526                                                 goto out;
2527                                         }
2528                                         cmdentry.u.cmd = bcmd;
2529                                         if (bcmd != BLTINCMD)
2530                                                 break;
2531                                 }
2532                         }
2533                         if (cmdentry.u.cmd == find_builtin("command")) {
2534                                 argv++;
2535                                 if (--argc == 0) {
2536                                         goto found;
2537                                 }
2538                                 if (*argv[0] == '-') {
2539                                         if (!equal(argv[0], "-p")) {
2540                                                 argv--;
2541                                                 argc++;
2542                                                 break;
2543                                         }
2544                                         argv++;
2545                                         if (--argc == 0) {
2546                                                 goto found;
2547                                         }
2548                                         path = defpath;
2549                                         findflag |= DO_BRUTE;
2550                                 } else {
2551                                         path = oldpath;
2552                                         findflag = oldfindflag;
2553                                 }
2554                                 findflag |= DO_NOFUN;
2555                                 continue;
2556                         }
2557 found:
2558                         break;
2559                 }
2560         }
2561
2562         /* Fork off a child process if necessary. */
2563         if (cmd->ncmd.backgnd
2564          || (cmdentry.cmdtype == CMDNORMAL && (flags & EV_EXIT) == 0)
2565         ) {
2566                 jp = makejob(cmd, 1);
2567                 mode = cmd->ncmd.backgnd;
2568                 if (forkshell(jp, cmd, mode) != 0)
2569                         goto parent;    /* at end of routine */
2570                 flags |= EV_EXIT;
2571         }
2572
2573         /* This is the child process if a fork occurred. */
2574         /* Execute the command. */
2575         if (cmdentry.cmdtype == CMDFUNCTION) {
2576 #ifdef DEBUG
2577                 trputs("Shell function:  ");  trargs(argv);
2578 #endif
2579                 exitstatus = oexitstatus;
2580                 redirect(cmd->ncmd.redirect, REDIR_PUSH);
2581                 saveparam = shellparam;
2582                 shellparam.malloc = 0;
2583                 shellparam.nparam = argc - 1;
2584                 shellparam.p = argv + 1;
2585                 INTOFF;
2586                 savelocalvars = localvars;
2587                 localvars = NULL;
2588                 INTON;
2589                 if (setjmp(jmploc.loc)) {
2590                         if (exception == EXSHELLPROC) {
2591                                 freeparam((volatile struct shparam *)
2592                                     &saveparam);
2593                         } else {
2594                                 saveparam.optind = shellparam.optind;
2595                                 saveparam.optoff = shellparam.optoff;
2596                                 freeparam(&shellparam);
2597                                 shellparam = saveparam;
2598                         }
2599                         poplocalvars();
2600                         localvars = savelocalvars;
2601                         handler = savehandler;
2602                         longjmp(handler->loc, 1);
2603                 }
2604                 savehandler = handler;
2605                 handler = &jmploc;
2606                 for (sp = varlist.list ; sp ; sp = sp->next)
2607                         mklocal(sp->text);
2608                 funcnest++;
2609                 evaltree(cmdentry.u.func, flags & EV_TESTED);
2610                 funcnest--;
2611                 INTOFF;
2612                 poplocalvars();
2613                 localvars = savelocalvars;
2614                 saveparam.optind = shellparam.optind;
2615                 saveparam.optoff = shellparam.optoff;
2616                 freeparam(&shellparam);
2617                 shellparam = saveparam;
2618                 handler = savehandler;
2619                 popredir();
2620                 INTON;
2621                 if (evalskip == SKIPFUNC) {
2622                         evalskip = 0;
2623                         skipcount = 0;
2624                 }
2625                 if (flags & EV_EXIT)
2626                         exitshell(exitstatus);
2627         } else if (cmdentry.cmdtype == CMDBUILTIN) {
2628 #ifdef DEBUG
2629                 trputs("builtin command:  ");  trargs(argv);
2630 #endif
2631                 mode = (cmdentry.u.cmd == EXECCMD)? 0 : REDIR_PUSH;
2632                 redirect(cmd->ncmd.redirect, mode);
2633                 savecmdname = commandname;
2634                 if (IS_BUILTIN_SPECIAL(firstbltin)) {
2635                         listsetvar(varlist.list);
2636                 } else {
2637                         cmdenviron = varlist.list;
2638                 }
2639                 e = -1;
2640                 if (setjmp(jmploc.loc)) {
2641                         e = exception;
2642                         exitstatus = (e == EXINT)? SIGINT+128 : 2;
2643                         goto cmddone;
2644                 }
2645                 savehandler = handler;
2646                 handler = &jmploc;
2647                 commandname = argv[0];
2648                 argptr = argv + 1;
2649                 optptr = NULL;                  /* initialize nextopt */
2650                 exitstatus = (*cmdentry.u.cmd->builtinfunc)(argc, argv);
2651                 flushall();
2652 cmddone:
2653                 cmdenviron = NULL;
2654                 if (e != EXSHELLPROC) {
2655                         commandname = savecmdname;
2656                         if (flags & EV_EXIT)
2657                                 exitshell(exitstatus);
2658                 }
2659                 handler = savehandler;
2660                 if (e != -1) {
2661                         if ((e != EXERROR && e != EXEXEC)
2662                            || cmdentry.u.cmd == BLTINCMD
2663                            || cmdentry.u.cmd == DOTCMD
2664                            || cmdentry.u.cmd == EVALCMD
2665                            || cmdentry.u.cmd == EXECCMD)
2666                                 exraise(e);
2667                         FORCEINTON;
2668                 }
2669                 if (cmdentry.u.cmd != EXECCMD)
2670                         popredir();
2671         } else {
2672 #ifdef DEBUG
2673                 trputs("normal command:  ");  trargs(argv);
2674 #endif
2675                 redirect(cmd->ncmd.redirect, 0);
2676                 clearredir();
2677                 for (sp = varlist.list ; sp ; sp = sp->next)
2678                         setvareq(sp->text, VEXPORT|VSTACK);
2679                 envp = environment();
2680                 shellexec(argv, envp, path, cmdentry.u.index);
2681         }
2682         goto out;
2683
2684 parent: /* parent process gets here (if we forked) */
2685         if (mode == 0) {        /* argument to fork */
2686                 INTOFF;
2687                 exitstatus = waitforjob(jp);
2688                 INTON;
2689         }
2690
2691 out:
2692         if (lastarg)
2693                 setvar("_", lastarg, 0);
2694         popstackmark(&smark);
2695 }
2696
2697 /*
2698  * Evaluate a parse tree.  The value is left in the global variable
2699  * exitstatus.
2700  */
2701 static void
2702 evaltree(union node *n, int flags)
2703 {
2704         int checkexit = 0;
2705         if (n == NULL) {
2706                 TRACE(("evaltree(NULL) called\n"));
2707                 goto out;
2708         }
2709         TRACE(("evaltree(0x%lx: %d) called\n", (long)n, n->type));
2710         switch (n->type) {
2711         case NSEMI:
2712                 evaltree(n->nbinary.ch1, flags & EV_TESTED);
2713                 if (evalskip)
2714                         goto out;
2715                 evaltree(n->nbinary.ch2, flags);
2716                 break;
2717         case NAND:
2718                 evaltree(n->nbinary.ch1, EV_TESTED);
2719                 if (evalskip || exitstatus != 0)
2720                         goto out;
2721                 evaltree(n->nbinary.ch2, flags);
2722                 break;
2723         case NOR:
2724                 evaltree(n->nbinary.ch1, EV_TESTED);
2725                 if (evalskip || exitstatus == 0)
2726                         goto out;
2727                 evaltree(n->nbinary.ch2, flags);
2728                 break;
2729         case NREDIR:
2730                 expredir(n->nredir.redirect);
2731                 redirect(n->nredir.redirect, REDIR_PUSH);
2732                 evaltree(n->nredir.n, flags);
2733                 popredir();
2734                 break;
2735         case NSUBSHELL:
2736                 evalsubshell(n, flags);
2737                 break;
2738         case NBACKGND:
2739                 evalsubshell(n, flags);
2740                 break;
2741         case NIF: {
2742                 evaltree(n->nif.test, EV_TESTED);
2743                 if (evalskip)
2744                         goto out;
2745                 if (exitstatus == 0)
2746                         evaltree(n->nif.ifpart, flags);
2747                 else if (n->nif.elsepart)
2748                         evaltree(n->nif.elsepart, flags);
2749                 else
2750                         exitstatus = 0;
2751                 break;
2752         }
2753         case NWHILE:
2754         case NUNTIL:
2755                 evalloop(n, flags);
2756                 break;
2757         case NFOR:
2758                 evalfor(n, flags);
2759                 break;
2760         case NCASE:
2761                 evalcase(n, flags);
2762                 break;
2763         case NDEFUN: {
2764                 struct builtincmd *bcmd;
2765                 struct cmdentry entry;
2766                 if (
2767                         (bcmd = find_builtin(n->narg.text)) &&
2768                         IS_BUILTIN_SPECIAL(bcmd)
2769                 ) {
2770                         out2fmt("%s is a special built-in\n", n->narg.text);
2771                         exitstatus = 1;
2772                         break;
2773                 }
2774                 entry.cmdtype = CMDFUNCTION;
2775                 entry.u.func = copyfunc(n->narg.next);
2776                 addcmdentry(n->narg.text, &entry);
2777                 exitstatus = 0;
2778                 break;
2779         }
2780         case NNOT:
2781                 evaltree(n->nnot.com, EV_TESTED);
2782                 exitstatus = !exitstatus;
2783                 break;
2784
2785         case NPIPE:
2786                 evalpipe(n);
2787                 checkexit = 1;
2788                 break;
2789         case NCMD:
2790                 evalcommand(n, flags);
2791                 checkexit = 1;
2792                 break;
2793 #ifdef DEBUG
2794         default:
2795                 printf("Node type = %d\n", n->type);
2796                 break;
2797 #endif
2798         }
2799 out:
2800         if (pendingsigs)
2801                 dotrap();
2802         if (
2803                 flags & EV_EXIT ||
2804                 (checkexit && eflag && exitstatus && !(flags & EV_TESTED))
2805         )
2806                 exitshell(exitstatus);
2807 }
2808
2809 /*
2810  * Kick off a subshell to evaluate a tree.
2811  */
2812
2813 static void
2814 evalsubshell(const union node *n, int flags)
2815 {
2816         struct job *jp;
2817         int backgnd = (n->type == NBACKGND);
2818
2819         expredir(n->nredir.redirect);
2820         jp = makejob(n, 1);
2821         if (forkshell(jp, n, backgnd) == 0) {
2822                 if (backgnd)
2823                         flags &=~ EV_TESTED;
2824                 redirect(n->nredir.redirect, 0);
2825                 evaltree(n->nredir.n, flags | EV_EXIT); /* never returns */
2826         }
2827         if (! backgnd) {
2828                 INTOFF;
2829                 exitstatus = waitforjob(jp);
2830                 INTON;
2831         }
2832 }
2833
2834 /*
2835  * Compute the names of the files in a redirection list.
2836  */
2837
2838 static void fixredir(union node *n, const char *text, int err);
2839
2840 static void
2841 expredir(union node *n)
2842 {
2843         union node *redir;
2844
2845         for (redir = n ; redir ; redir = redir->nfile.next) {
2846                 struct arglist fn;
2847                 fn.lastp = &fn.list;
2848                 oexitstatus = exitstatus;
2849                 switch (redir->type) {
2850                 case NFROMTO:
2851                 case NFROM:
2852                 case NTO:
2853                 case NAPPEND:
2854                 case NTOOV:
2855                         expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
2856                         redir->nfile.expfname = fn.list->text;
2857                         break;
2858                 case NFROMFD:
2859                 case NTOFD:
2860                         if (redir->ndup.vname) {
2861                                 expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE);
2862                                 fixredir(redir, fn.list->text, 1);
2863                         }
2864                         break;
2865                 }
2866         }
2867 }
2868
2869
2870 /*
2871  * Execute a command inside back quotes.  If it's a builtin command, we
2872  * want to save its output in a block obtained from malloc.  Otherwise
2873  * we fork off a subprocess and get the output of the command via a pipe.
2874  * Should be called with interrupts off.
2875  */
2876
2877 static void
2878 evalbackcmd(union node *n, struct backcmd *result)
2879 {
2880         int pip[2];
2881         struct job *jp;
2882         struct stackmark smark;         /* unnecessary */
2883
2884         setstackmark(&smark);
2885         result->fd = -1;
2886         result->buf = NULL;
2887         result->nleft = 0;
2888         result->jp = NULL;
2889         if (n == NULL) {
2890                 exitstatus = 0;
2891                 goto out;
2892         }
2893         exitstatus = 0;
2894         if (pipe(pip) < 0)
2895                 error("Pipe call failed");
2896         jp = makejob(n, 1);
2897         if (forkshell(jp, n, FORK_NOJOB) == 0) {
2898                 FORCEINTON;
2899                 close(pip[0]);
2900                 if (pip[1] != 1) {
2901                         close(1);
2902                         dup_as_newfd(pip[1], 1);
2903                         close(pip[1]);
2904                 }
2905                 eflag = 0;
2906                 evaltree(n, EV_EXIT);
2907         }
2908         close(pip[1]);
2909         result->fd = pip[0];
2910         result->jp = jp;
2911 out:
2912         popstackmark(&smark);
2913         TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n",
2914                 result->fd, result->buf, result->nleft, result->jp));
2915 }
2916
2917
2918 /*
2919  * Execute a simple command.
2920  */
2921
2922
2923 /*
2924  * Builtin commands.  Builtin commands whose functions are closely
2925  * tied to evaluation are implemented here.
2926  */
2927
2928 /*
2929  * No command given, or a bltin command with no arguments.  Set the
2930  * specified variables.
2931  */
2932
2933 int
2934 bltincmd(int argc, char **argv)
2935 {
2936         /*
2937          * Preserve exitstatus of a previous possible redirection
2938          * as POSIX mandates
2939          */
2940         return exitstatus;
2941 }
2942
2943
2944 /*
2945  * Handle break and continue commands.  Break, continue, and return are
2946  * all handled by setting the evalskip flag.  The evaluation routines
2947  * above all check this flag, and if it is set they start skipping
2948  * commands rather than executing them.  The variable skipcount is
2949  * the number of loops to break/continue, or the number of function
2950  * levels to return.  (The latter is always 1.)  It should probably
2951  * be an error to break out of more loops than exist, but it isn't
2952  * in the standard shell so we don't make it one here.
2953  */
2954
2955 static int
2956 breakcmd(int argc, char **argv)
2957 {
2958         int n = argc > 1 ? number(argv[1]) : 1;
2959
2960         if (n <= 0)
2961                 error("Illegal number: %s", argv[1]);
2962         if (n > loopnest)
2963                 n = loopnest;
2964         if (n > 0) {
2965                 evalskip = (**argv == 'c')? SKIPCONT : SKIPBREAK;
2966                 skipcount = n;
2967         }
2968         return 0;
2969 }
2970
2971
2972 /*
2973  * The return command.
2974  */
2975
2976 static int
2977 returncmd(int argc, char **argv)
2978 {
2979         int ret = argc > 1 ? number(argv[1]) : oexitstatus;
2980
2981         if (funcnest) {
2982                 evalskip = SKIPFUNC;
2983                 skipcount = 1;
2984                 return ret;
2985         }
2986         else {
2987                 /* Do what ksh does; skip the rest of the file */
2988                 evalskip = SKIPFILE;
2989                 skipcount = 1;
2990                 return ret;
2991         }
2992 }
2993
2994
2995 #ifndef CONFIG_FALSE
2996 static int
2997 false_main(int argc, char **argv)
2998 {
2999         return 1;
3000 }
3001 #endif
3002
3003 #ifndef CONFIG_TRUE
3004 static int
3005 true_main(int argc, char **argv)
3006 {
3007         return 0;
3008 }
3009 #endif
3010
3011 /*
3012  * Controls whether the shell is interactive or not.
3013  */
3014
3015 static void setsignal(int signo);
3016
3017 #ifdef CONFIG_ASH_MAIL
3018 static void chkmail(int silent);
3019 #endif
3020
3021 static void
3022 setinteractive(int on)
3023 {
3024         static int is_interactive;
3025         static int do_banner=0;
3026
3027         if (on == is_interactive)
3028                 return;
3029         setsignal(SIGINT);
3030         setsignal(SIGQUIT);
3031         setsignal(SIGTERM);
3032 #ifdef CONFIG_ASH_MAIL
3033         chkmail(1);
3034 #endif
3035         is_interactive = on;
3036         if (do_banner==0 && is_interactive) {
3037                 /* Looks like they want an interactive shell */
3038 #ifndef CONFIG_FEATURE_SH_EXTRA_QUIET 
3039                 printf( "\n\n" BB_BANNER " Built-in shell (ash)\n");
3040                 printf( "Enter 'help' for a list of built-in commands.\n\n");
3041 #endif
3042                 do_banner=1;
3043         }
3044 }
3045
3046 static void
3047 optschanged(void)
3048 {
3049         setinteractive(iflag);
3050         setjobctl(mflag);
3051 }
3052
3053
3054 static int
3055 execcmd(int argc, char **argv)
3056 {
3057         if (argc > 1) {
3058                 struct strlist *sp;
3059
3060                 iflag = 0;              /* exit on error */
3061                 mflag = 0;
3062                 optschanged();
3063                 for (sp = cmdenviron; sp ; sp = sp->next)
3064                         setvareq(sp->text, VEXPORT|VSTACK);
3065                 shellexec(argv + 1, environment(), pathval(), 0);
3066         }
3067         return 0;
3068 }
3069
3070 static void
3071 eprintlist(struct strlist *sp)
3072 {
3073         for (; sp; sp = sp->next) {
3074                 out2fmt(" %s",sp->text);
3075         }
3076 }
3077
3078 /*
3079  * Exec a program.  Never returns.  If you change this routine, you may
3080  * have to change the find_command routine as well.
3081  */
3082
3083 static const char *pathopt;     /* set by padvance */
3084
3085 static void
3086 shellexec(char **argv, char **envp, const char *path, int idx)
3087 {
3088         char *cmdname;
3089         int e;
3090
3091         if (strchr(argv[0], '/') != NULL) {
3092                 tryexec(argv[0], argv, envp);
3093                 e = errno;
3094         } else {
3095                 e = ENOENT;
3096                 while ((cmdname = padvance(&path, argv[0])) != NULL) {
3097                         if (--idx < 0 && pathopt == NULL) {
3098                                 tryexec(cmdname, argv, envp);
3099                                 if (errno != ENOENT && errno != ENOTDIR)
3100                                         e = errno;
3101                         }
3102                         stunalloc(cmdname);
3103                 }
3104         }
3105
3106         /* Map to POSIX errors */
3107         switch (e) {
3108         case EACCES:
3109                 exerrno = 126;
3110                 break;
3111         case ENOENT:
3112                 exerrno = 127;
3113                 break;
3114         default:
3115                 exerrno = 2;
3116                 break;
3117         }
3118         exerror(EXEXEC, "%s: %s", argv[0], errmsg(e, E_EXEC));
3119         /* NOTREACHED */
3120 }
3121
3122 /*
3123  * Clear traps on a fork.
3124  */
3125 static void
3126 clear_traps(void)
3127 {
3128         char **tp;
3129
3130         for (tp = trap ; tp < &trap[NSIG] ; tp++) {
3131                 if (*tp && **tp) {      /* trap not NULL or SIG_IGN */
3132                         INTOFF;
3133                         ckfree(*tp);
3134                         *tp = NULL;
3135                         if (tp != &trap[0])
3136                                 setsignal(tp - trap);
3137                         INTON;
3138                 }
3139         }
3140 }
3141
3142
3143 static void
3144 initshellproc(void)
3145 {
3146
3147 #ifdef CONFIG_ASH_ALIAS
3148       /* from alias.c: */
3149       {
3150               rmaliases();
3151       }
3152 #endif
3153       /* from eval.c: */
3154       {
3155               exitstatus = 0;
3156       }
3157
3158       /* from exec.c: */
3159       {
3160               deletefuncs();
3161       }
3162
3163       /* from jobs.c: */
3164       {
3165               backgndpid = -1;
3166 #ifdef CONFIG_ASH_JOB_CONTROL
3167               jobctl = 0;
3168 #endif
3169       }
3170
3171       /* from options.c: */
3172       {
3173               int i;
3174
3175               for (i = 0; i < NOPTS; i++)
3176                       optent_val(i) = 0;
3177               optschanged();
3178
3179       }
3180
3181       /* from redir.c: */
3182       {
3183               clearredir();
3184       }
3185
3186       /* from trap.c: */
3187       {
3188               char *sm;
3189
3190               clear_traps();
3191               for (sm = sigmode ; sm < sigmode + NSIG - 1; sm++) {
3192                       if (*sm == S_IGN)
3193                               *sm = S_HARD_IGN;
3194               }
3195       }
3196
3197       /* from var.c: */
3198       {
3199               shprocvar();
3200       }
3201 }
3202
3203 static int preadbuffer(void);
3204 static void pushfile (void);
3205
3206 /*
3207  * Read a character from the script, returning PEOF on end of file.
3208  * Nul characters in the input are silently discarded.
3209  */
3210
3211 #ifndef CONFIG_ASH_OPTIMIZE_FOR_SIZE
3212 #define pgetc_macro()   (--parsenleft >= 0? *parsenextc++ : preadbuffer())
3213 static int
3214 pgetc(void)
3215 {
3216         return pgetc_macro();
3217 }
3218 #else
3219 static int
3220 pgetc_macro(void)
3221 {
3222         return --parsenleft >= 0? *parsenextc++ : preadbuffer();
3223 }
3224
3225 static inline int
3226 pgetc(void)
3227 {
3228         return pgetc_macro();
3229 }
3230 #endif
3231
3232
3233 /*
3234  * Undo the last call to pgetc.  Only one character may be pushed back.
3235  * PEOF may be pushed back.
3236  */
3237
3238 static void pungetc(void) 
3239 {
3240         parsenleft++;
3241         parsenextc--;
3242 }
3243
3244
3245 static void
3246 popfile(void)
3247 {
3248         struct parsefile *pf = parsefile;
3249
3250         INTOFF;
3251         if (pf->fd >= 0)
3252                 close(pf->fd);
3253         if (pf->buf)
3254                 ckfree(pf->buf);
3255         while (pf->strpush)
3256                 popstring();
3257         parsefile = pf->prev;
3258         ckfree(pf);
3259         parsenleft = parsefile->nleft;
3260         parselleft = parsefile->lleft;
3261         parsenextc = parsefile->nextc;
3262         plinno = parsefile->linno;
3263         INTON;
3264 }
3265
3266
3267 /*
3268  * Return to top level.
3269  */
3270
3271 static void
3272 popallfiles(void)
3273 {
3274         while (parsefile != &basepf)
3275                 popfile();
3276 }
3277
3278 /*
3279  * Close the file(s) that the shell is reading commands from.  Called
3280  * after a fork is done.
3281  */
3282
3283 static void closescript(void) 
3284 {
3285         popallfiles();
3286         if (parsefile->fd > 0) {
3287                 close(parsefile->fd);
3288                 parsefile->fd = 0;
3289         }
3290 }
3291
3292
3293 /*
3294  * Like setinputfile, but takes an open file descriptor.  Call this with
3295  * interrupts off.
3296  */
3297
3298 static void setinputfd(int fd, int push)
3299 {
3300         (void) fcntl(fd, F_SETFD, FD_CLOEXEC);
3301         if (push) {
3302                 pushfile();
3303                 parsefile->buf = 0;
3304         } else {
3305                 closescript();
3306                 while (parsefile->strpush)
3307                         popstring();
3308         }
3309         parsefile->fd = fd;
3310         if (parsefile->buf == NULL)
3311                 parsefile->buf = xmalloc(BUFSIZ);
3312         parselleft = parsenleft = 0;
3313         plinno = 1;
3314 }
3315
3316
3317 /*
3318  * Set the input to take input from a file.  If push is set, push the
3319  * old input onto the stack first.
3320  */
3321
3322 static void
3323 setinputfile(const char *fname, int push)
3324 {
3325         int fd;
3326         int myfileno2;
3327
3328         INTOFF;
3329         if ((fd = open(fname, O_RDONLY)) < 0)
3330                 error("Can't open %s", fname);
3331         if (fd < 10) {
3332                 myfileno2 = dup_as_newfd(fd, 10);
3333                 close(fd);
3334                 if (myfileno2 < 0)
3335                         error("Out of file descriptors");
3336                 fd = myfileno2;
3337         }
3338         setinputfd(fd, push);
3339         INTON;
3340 }
3341
3342
3343 static void
3344 tryexec(char *cmd, char **argv, char **envp)
3345 {
3346         int e;
3347
3348 #ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL
3349         char *name = cmd;
3350         char** argv_l=argv;
3351         int argc_l;
3352 #ifdef CONFIG_FEATURE_SH_APPLETS_ALWAYS_WIN
3353         name = get_last_path_component(name);
3354 #endif
3355         argv_l=envp;
3356         for(argc_l=0;*argv_l!=NULL; argv_l++, argc_l++)
3357                 putenv(*argv_l);
3358         argv_l=argv;
3359         for(argc_l=0;*argv_l!=NULL; argv_l++, argc_l++)
3360         optind = 1;
3361         run_applet_by_name(name, argc_l, argv);
3362 #endif
3363         execve(cmd, argv, envp);
3364         e = errno;
3365         if (e == ENOEXEC) {
3366                 INTOFF;
3367                 initshellproc();
3368                 setinputfile(cmd, 0);
3369                 commandname = arg0 = xstrdup(argv[0]);
3370                 setparam(argv + 1);
3371                 exraise(EXSHELLPROC);
3372         }
3373         errno = e;
3374 }
3375
3376 static char *commandtext (const union node *);
3377
3378 /*
3379  * Do a path search.  The variable path (passed by reference) should be
3380  * set to the start of the path before the first call; padvance will update
3381  * this value as it proceeds.  Successive calls to padvance will return
3382  * the possible path expansions in sequence.  If an option (indicated by
3383  * a percent sign) appears in the path entry then the global variable
3384  * pathopt will be set to point to it; otherwise pathopt will be set to
3385  * NULL.
3386  */
3387
3388 static const char *pathopt;
3389
3390 static void growstackblock(void);
3391
3392
3393 static char *
3394 padvance(const char **path, const char *name)
3395 {
3396         const char *p;
3397         char *q;
3398         const char *start;
3399         int len;
3400
3401         if (*path == NULL)
3402                 return NULL;
3403         start = *path;
3404         for (p = start ; *p && *p != ':' && *p != '%' ; p++);
3405         len = p - start + strlen(name) + 2;     /* "2" is for '/' and '\0' */
3406         while (stackblocksize() < len)
3407                 growstackblock();
3408         q = stackblock();
3409         if (p != start) {
3410                 memcpy(q, start, p - start);
3411                 q += p - start;
3412                 *q++ = '/';
3413         }
3414         strcpy(q, name);
3415         pathopt = NULL;
3416         if (*p == '%') {
3417                 pathopt = ++p;
3418                 while (*p && *p != ':')  p++;
3419         }
3420         if (*p == ':')
3421                 *path = p + 1;
3422         else
3423                 *path = NULL;
3424         return stalloc(len);
3425 }
3426
3427 /*
3428  * Wrapper around strcmp for qsort/bsearch/...
3429  */
3430 static int
3431 pstrcmp(const void *a, const void *b)
3432 {
3433         return strcmp((const char *) a, (*(const char *const *) b) + 1);
3434 }
3435
3436 /*
3437  * Find a keyword is in a sorted array.
3438  */
3439
3440 static const char *const *
3441 findkwd(const char *s)
3442 {
3443         return  bsearch(s, tokname_array + KWDOFFSET,
3444                                         (sizeof(tokname_array)/sizeof(const char *)) - KWDOFFSET,
3445                                         sizeof(const char *), pstrcmp);
3446 }
3447
3448
3449 /*** Command hashing code ***/
3450
3451
3452 static int
3453 hashcmd(int argc, char **argv)
3454 {
3455         struct tblentry **pp;
3456         struct tblentry *cmdp;
3457         int c;
3458         int verbose;
3459         struct cmdentry entry;
3460         char *name;
3461 #ifdef CONFIG_ASH_ALIAS
3462         const struct alias *ap;
3463 #endif
3464
3465         verbose = 0;
3466         while ((c = nextopt("rvV")) != '\0') {
3467                 if (c == 'r') {
3468                         clearcmdentry(0);
3469                         return 0;
3470                 } else if (c == 'v' || c == 'V') {
3471                         verbose = c;
3472                 }
3473         }
3474         if (*argptr == NULL) {
3475                 for (pp = cmdtable ; pp < &cmdtable[CMDTABLESIZE] ; pp++) {
3476                         for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
3477                                 if (cmdp->cmdtype != CMDBUILTIN) {
3478                                         printentry(cmdp, verbose);
3479                                 }
3480                         }
3481                 }
3482                 return 0;
3483         }
3484         c = 0;
3485         while ((name = *argptr++) != NULL) {
3486                 if ((cmdp = cmdlookup(name, 0)) != NULL
3487                  && (cmdp->cmdtype == CMDNORMAL
3488                      || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0)))
3489                         delete_cmd_entry();
3490 #ifdef CONFIG_ASH_ALIAS
3491         /* Then look at the aliases */
3492                 if ((ap = *__lookupalias(name)) != NULL) {
3493                         if (verbose=='v')
3494                                 printf("%s is an alias for %s\n", name, ap->val);
3495                         else
3496                                 printalias(ap);
3497                         continue;
3498                 }
3499 #endif
3500                         /* First look at the keywords */
3501                 if (findkwd(name)!=0) {
3502                         if (verbose=='v')
3503                                 printf("%s is a shell keyword\n", name);
3504                         else
3505                                 puts(name);
3506                         continue;
3507                 }
3508
3509                 find_command(name, &entry, DO_ERR, pathval());
3510                 if (entry.cmdtype == CMDUNKNOWN) c = 1;
3511                 else if (verbose) {
3512                         cmdp = cmdlookup(name, 0);
3513                         if (cmdp) printentry(cmdp, verbose=='v');
3514                         flushall();
3515                 }
3516         }
3517         return c;
3518 }
3519
3520 static void
3521 printentry(struct tblentry *cmdp, int verbose)
3522 {
3523         int idx;
3524         const char *path;
3525         char *name;
3526
3527         printf("%s%s", cmdp->cmdname, (verbose ? " is " : ""));
3528         if (cmdp->cmdtype == CMDNORMAL) {
3529                 idx = cmdp->param.index;
3530                 path = pathval();
3531                 do {
3532                         name = padvance(&path, cmdp->cmdname);
3533                         stunalloc(name);
3534                 } while (--idx >= 0);
3535                 if(verbose)
3536                         out1str(name);
3537         } else if (cmdp->cmdtype == CMDBUILTIN) {
3538                 if(verbose)
3539                         out1str("a shell builtin");
3540         } else if (cmdp->cmdtype == CMDFUNCTION) {
3541                 if (verbose) {
3542                         INTOFF;
3543                         out1str("a function\n");
3544                         name = commandtext(cmdp->param.func);
3545                         printf("%s() {\n %s\n}", cmdp->cmdname, name);
3546                         ckfree(name);
3547                         INTON;
3548                 }
3549 #ifdef DEBUG
3550         } else {
3551                 error("internal error: cmdtype %d", cmdp->cmdtype);
3552 #endif
3553         }
3554         puts(cmdp->rehash ? "*" : nullstr);
3555 }
3556
3557
3558
3559 /*** List the available builtins ***/
3560
3561
3562 static int helpcmd(int argc, char** argv)
3563 {
3564         int col, i;
3565
3566         printf("\nBuilt-in commands:\n-------------------\n");
3567         for (col=0, i=0; i < NUMBUILTINS; i++) {
3568                 col += printf("%c%s", ((col == 0) ? '\t' : ' '),
3569                                 builtincmds[i].name+1);
3570                 if (col > 60) {
3571                         printf("\n");
3572                         col = 0;
3573                 }
3574         }
3575 #ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL
3576         {
3577                 extern const struct BB_applet applets[];
3578                 extern const size_t NUM_APPLETS;
3579
3580                 for (i=0; i < NUM_APPLETS; i++) {
3581
3582                         col += printf("%c%s", ((col == 0) ? '\t' : ' '),
3583                                         applets[i].name);
3584                         if (col > 60) {
3585                                 printf("\n");
3586                                 col = 0;
3587                         }
3588                 }
3589         }
3590 #endif
3591         printf("\n\n");
3592         return EXIT_SUCCESS;
3593 }
3594
3595 /*
3596  * Resolve a command name.  If you change this routine, you may have to
3597  * change the shellexec routine as well.
3598  */
3599
3600 static int prefix (const char *, const char *);
3601
3602 static void
3603 find_command(const char *name, struct cmdentry *entry, int act, const char *path)
3604 {
3605         struct tblentry *cmdp;
3606         int idx;
3607         int prev;
3608         char *fullname;
3609         struct stat statb;
3610         int e;
3611         int bltin;
3612         int firstchange;
3613         int updatetbl;
3614         int regular;
3615         struct builtincmd *bcmd;
3616
3617         /* If name contains a slash, don't use the hash table */
3618         if (strchr(name, '/') != NULL) {
3619                 if (act & DO_ABS) {
3620                         while (stat(name, &statb) < 0) {
3621                                 if (errno != ENOENT && errno != ENOTDIR)
3622                                         e = errno;
3623                                 entry->cmdtype = CMDUNKNOWN;
3624                                 entry->u.index = -1;
3625                                 return;
3626                         }
3627                         entry->cmdtype = CMDNORMAL;
3628                         entry->u.index = -1;
3629                         return;
3630                 }
3631                 entry->cmdtype = CMDNORMAL;
3632                 entry->u.index = 0;
3633                 return;
3634         }
3635
3636         updatetbl = 1;
3637         if (act & DO_BRUTE) {
3638                 firstchange = path_change(path, &bltin);
3639         } else {
3640                 bltin = builtinloc;
3641                 firstchange = 9999;
3642         }
3643
3644         /* If name is in the table, and not invalidated by cd, we're done */
3645         if ((cmdp = cmdlookup(name, 0)) != NULL && cmdp->rehash == 0) {
3646                 if (cmdp->cmdtype == CMDFUNCTION) {
3647                         if (act & DO_NOFUN) {
3648                                 updatetbl = 0;
3649                         } else {
3650                                 goto success;
3651                         }
3652                 } else if (act & DO_BRUTE) {
3653                         if ((cmdp->cmdtype == CMDNORMAL &&
3654                              cmdp->param.index >= firstchange) ||
3655                             (cmdp->cmdtype == CMDBUILTIN &&
3656                              ((builtinloc < 0 && bltin >= 0) ?
3657                               bltin : builtinloc) >= firstchange)) {
3658                                 /* need to recompute the entry */
3659                         } else {
3660                                 goto success;
3661                         }
3662                 } else {
3663                         goto success;
3664                 }
3665         }
3666
3667         bcmd = find_builtin(name);
3668         regular = bcmd && IS_BUILTIN_REGULAR(bcmd);
3669
3670         if (regular) {
3671                 if (cmdp && (cmdp->cmdtype == CMDBUILTIN)) {
3672                         goto success;
3673                 }
3674         } else if (act & DO_BRUTE) {
3675                 if (firstchange == 0) {
3676                         updatetbl = 0;
3677                 }
3678         }
3679
3680         /* If %builtin not in path, check for builtin next */
3681         if (regular || (bltin < 0 && bcmd)) {
3682 builtin:
3683                 if (!updatetbl) {
3684                         entry->cmdtype = CMDBUILTIN;
3685                         entry->u.cmd = bcmd;
3686                         return;
3687                 }
3688                 INTOFF;
3689                 cmdp = cmdlookup(name, 1);
3690                 cmdp->cmdtype = CMDBUILTIN;
3691                 cmdp->param.cmd = bcmd;
3692                 INTON;
3693                 goto success;
3694         }
3695
3696         /* We have to search path. */
3697         prev = -1;              /* where to start */
3698         if (cmdp && cmdp->rehash) {     /* doing a rehash */
3699                 if (cmdp->cmdtype == CMDBUILTIN)
3700                         prev = builtinloc;
3701                 else
3702                         prev = cmdp->param.index;
3703         }
3704
3705         e = ENOENT;
3706         idx = -1;
3707 loop:
3708         while ((fullname = padvance(&path, name)) != NULL) {
3709                 stunalloc(fullname);
3710                 idx++;
3711                 if (idx >= firstchange) {
3712                         updatetbl = 0;
3713                 }
3714                 if (pathopt) {
3715                         if (prefix("builtin", pathopt)) {
3716                                 if ((bcmd = find_builtin(name))) {
3717                                         goto builtin;
3718                                 }
3719                                 continue;
3720                         } else if (!(act & DO_NOFUN) &&
3721                                    prefix("func", pathopt)) {
3722                                 /* handled below */
3723                         } else {
3724                                 continue;       /* ignore unimplemented options */
3725                         }
3726                 }
3727                 /* if rehash, don't redo absolute path names */
3728                 if (fullname[0] == '/' && idx <= prev &&
3729                     idx < firstchange) {
3730                         if (idx < prev)
3731                                 continue;
3732                         TRACE(("searchexec \"%s\": no change\n", name));
3733                         goto success;
3734                 }
3735                 while (stat(fullname, &statb) < 0) {
3736                         if (errno != ENOENT && errno != ENOTDIR)
3737                                 e = errno;
3738                         goto loop;
3739                 }
3740                 e = EACCES;     /* if we fail, this will be the error */
3741                 if (!S_ISREG(statb.st_mode))
3742                         continue;
3743                 if (pathopt) {          /* this is a %func directory */
3744                         stalloc(strlen(fullname) + 1);
3745                         readcmdfile(fullname);
3746                         if ((cmdp = cmdlookup(name, 0)) == NULL || cmdp->cmdtype != CMDFUNCTION)
3747                                 error("%s not defined in %s", name, fullname);
3748                         stunalloc(fullname);
3749                         goto success;
3750                 }
3751                 TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
3752                 /* If we aren't called with DO_BRUTE and cmdp is set, it must
3753                    be a function and we're being called with DO_NOFUN */
3754                 if (!updatetbl) {
3755                         entry->cmdtype = CMDNORMAL;
3756                         entry->u.index = idx;
3757                         return;
3758                 }
3759                 INTOFF;
3760                 cmdp = cmdlookup(name, 1);
3761                 cmdp->cmdtype = CMDNORMAL;
3762                 cmdp->param.index = idx;
3763                 INTON;
3764                 goto success;
3765         }
3766
3767         /* We failed.  If there was an entry for this command, delete it */
3768         if (cmdp && updatetbl)
3769                 delete_cmd_entry();
3770         if (act & DO_ERR)
3771                 out2fmt("%s: %s\n", name, errmsg(e, E_EXEC));
3772         entry->cmdtype = CMDUNKNOWN;
3773         return;
3774
3775 success:
3776         cmdp->rehash = 0;
3777         entry->cmdtype = cmdp->cmdtype;
3778         entry->u = cmdp->param;
3779 }
3780
3781
3782
3783 /*
3784  * Search the table of builtin commands.
3785  */
3786
3787 static int
3788 bstrcmp(const void *name, const void *b)
3789 {
3790         return strcmp((const char *)name, (*(const char *const *) b)+1);
3791 }
3792
3793 static struct builtincmd *
3794 find_builtin(const char *name)
3795 {
3796         struct builtincmd *bp;
3797
3798         bp = bsearch(name, builtincmds, NUMBUILTINS, sizeof(struct builtincmd),
3799                 bstrcmp
3800         );
3801         return bp;
3802 }
3803
3804
3805 /*
3806  * Called when a cd is done.  Marks all commands so the next time they
3807  * are executed they will be rehashed.
3808  */
3809
3810 static inline void
3811 hashcd(void)
3812 {
3813         struct tblentry **pp;
3814         struct tblentry *cmdp;
3815
3816         for (pp = cmdtable ; pp < &cmdtable[CMDTABLESIZE] ; pp++) {
3817                 for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
3818                         if (cmdp->cmdtype == CMDNORMAL
3819                          || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0))
3820                                 cmdp->rehash = 1;
3821                 }
3822         }
3823 }
3824
3825
3826
3827 /*
3828  * Called before PATH is changed.  The argument is the new value of PATH;
3829  * pathval() still returns the old value at this point.  Called with
3830  * interrupts off.
3831  */
3832
3833 static void
3834 changepath(const char *newval)
3835 {
3836         int firstchange;
3837         int bltin;
3838
3839         firstchange = path_change(newval, &bltin);
3840         if (builtinloc < 0 && bltin >= 0)
3841                 builtinloc = bltin;             /* zap builtins */
3842         clearcmdentry(firstchange);
3843         builtinloc = bltin;
3844 }
3845
3846
3847 /*
3848  * Clear out command entries.  The argument specifies the first entry in
3849  * PATH which has changed.
3850  */
3851
3852 static void
3853 clearcmdentry(int firstchange)
3854 {
3855         struct tblentry **tblp;
3856         struct tblentry **pp;
3857         struct tblentry *cmdp;
3858
3859         INTOFF;
3860         for (tblp = cmdtable ; tblp < &cmdtable[CMDTABLESIZE] ; tblp++) {
3861                 pp = tblp;
3862                 while ((cmdp = *pp) != NULL) {
3863                         if ((cmdp->cmdtype == CMDNORMAL &&
3864                              cmdp->param.index >= firstchange)
3865                          || (cmdp->cmdtype == CMDBUILTIN &&
3866                              builtinloc >= firstchange)) {
3867                                 *pp = cmdp->next;
3868                                 ckfree(cmdp);
3869                         } else {
3870                                 pp = &cmdp->next;
3871                         }
3872                 }
3873         }
3874         INTON;
3875 }
3876
3877
3878 /*
3879  * Delete all functions.
3880  */
3881
3882 static void
3883 deletefuncs(void)
3884 {
3885         struct tblentry **tblp;
3886         struct tblentry **pp;
3887         struct tblentry *cmdp;
3888
3889         INTOFF;
3890         for (tblp = cmdtable ; tblp < &cmdtable[CMDTABLESIZE] ; tblp++) {
3891                 pp = tblp;
3892                 while ((cmdp = *pp) != NULL) {
3893                         if (cmdp->cmdtype == CMDFUNCTION) {
3894                                 *pp = cmdp->next;
3895                                 freefunc(cmdp->param.func);
3896                                 ckfree(cmdp);
3897                         } else {
3898                                 pp = &cmdp->next;
3899                         }
3900                 }
3901         }
3902         INTON;
3903 }
3904
3905
3906
3907 /*
3908  * Locate a command in the command hash table.  If "add" is nonzero,
3909  * add the command to the table if it is not already present.  The
3910  * variable "lastcmdentry" is set to point to the address of the link
3911  * pointing to the entry, so that delete_cmd_entry can delete the
3912  * entry.
3913  */
3914
3915 static struct tblentry **lastcmdentry;
3916
3917 static struct tblentry *
3918 cmdlookup(const char *name, int add)
3919 {
3920         int hashval;
3921         const char *p;
3922         struct tblentry *cmdp;
3923         struct tblentry **pp;
3924
3925         p = name;
3926         hashval = *p << 4;
3927         while (*p)
3928                 hashval += *p++;
3929         hashval &= 0x7FFF;
3930         pp = &cmdtable[hashval % CMDTABLESIZE];
3931         for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
3932                 if (equal(cmdp->cmdname, name))
3933                         break;
3934                 pp = &cmdp->next;
3935         }
3936         if (add && cmdp == NULL) {
3937                 INTOFF;
3938                 cmdp = *pp = xmalloc(sizeof (struct tblentry) - ARB
3939                                         + strlen(name) + 1);
3940                 cmdp->next = NULL;
3941                 cmdp->cmdtype = CMDUNKNOWN;
3942                 cmdp->rehash = 0;
3943                 strcpy(cmdp->cmdname, name);
3944                 INTON;
3945         }
3946         lastcmdentry = pp;
3947         return cmdp;
3948 }
3949
3950 /*
3951  * Delete the command entry returned on the last lookup.
3952  */
3953
3954 static void
3955 delete_cmd_entry()
3956 {
3957         struct tblentry *cmdp;
3958
3959         INTOFF;
3960         cmdp = *lastcmdentry;
3961         *lastcmdentry = cmdp->next;
3962         ckfree(cmdp);
3963         INTON;
3964 }
3965
3966
3967
3968
3969
3970 static const unsigned char nodesize[26] = {
3971       ALIGN(sizeof (struct nbinary)),
3972       ALIGN(sizeof (struct ncmd)),
3973       ALIGN(sizeof (struct npipe)),
3974       ALIGN(sizeof (struct nredir)),
3975       ALIGN(sizeof (struct nredir)),
3976       ALIGN(sizeof (struct nredir)),
3977       ALIGN(sizeof (struct nbinary)),
3978       ALIGN(sizeof (struct nbinary)),
3979       ALIGN(sizeof (struct nif)),
3980       ALIGN(sizeof (struct nbinary)),
3981       ALIGN(sizeof (struct nbinary)),
3982       ALIGN(sizeof (struct nfor)),
3983       ALIGN(sizeof (struct ncase)),
3984       ALIGN(sizeof (struct nclist)),
3985       ALIGN(sizeof (struct narg)),
3986       ALIGN(sizeof (struct narg)),
3987       ALIGN(sizeof (struct nfile)),
3988       ALIGN(sizeof (struct nfile)),
3989       ALIGN(sizeof (struct nfile)),
3990       ALIGN(sizeof (struct nfile)),
3991       ALIGN(sizeof (struct nfile)),
3992       ALIGN(sizeof (struct ndup)),
3993       ALIGN(sizeof (struct ndup)),
3994       ALIGN(sizeof (struct nhere)),
3995       ALIGN(sizeof (struct nhere)),
3996       ALIGN(sizeof (struct nnot)),
3997 };
3998
3999
4000
4001 /*
4002  * Delete a function if it exists.
4003  */
4004
4005 static void
4006 unsetfunc(char *name)
4007 {
4008         struct tblentry *cmdp;
4009
4010         if ((cmdp = cmdlookup(name, 0)) != NULL && cmdp->cmdtype == CMDFUNCTION) {
4011                 freefunc(cmdp->param.func);
4012                 delete_cmd_entry();
4013         }
4014 }
4015
4016
4017 /*
4018  * Locate and print what a word is...
4019  */
4020
4021 static int
4022 typecmd(int argc, char **argv)
4023 {
4024         int i;
4025         int err = 0;
4026         char *argv_a[2];
4027
4028         argv_a[1] = 0;
4029
4030         for (i = 1; i < argc; i++) {
4031                 argv_a[0] = argv[i];
4032                 argptr = argv_a;
4033                 optptr = "v";
4034                 err |= hashcmd(argc, argv);
4035         }
4036         return err;
4037 }
4038
4039 #ifdef CONFIG_ASH_CMDCMD
4040 static int
4041 commandcmd(int argc, char **argv)
4042 {
4043         int c;
4044         int default_path = 0;
4045         int verify_only = 0;
4046         int verbose_verify_only = 0;
4047
4048         while ((c = nextopt("pvV")) != '\0')
4049                 switch (c) {
4050                 case 'p':
4051                         default_path = 1;
4052                         break;
4053                 case 'v':
4054                         verify_only = 1;
4055                         break;
4056                 case 'V':
4057                         verbose_verify_only = 1;
4058                         break;
4059                 }
4060
4061         if (default_path + verify_only + verbose_verify_only > 1 ||
4062             !*argptr) {
4063                         out2str(
4064                                 "command [-p] command [arg ...]\n"
4065                                 "command {-v|-V} command\n");
4066                         return EX_USAGE;
4067         }
4068
4069         if (verify_only || verbose_verify_only) {
4070                 char *argv_a[2];
4071
4072                 argv_a[1] = 0;
4073                 argv_a[0] = *argptr;
4074                 argptr = argv_a;
4075                 optptr = verbose_verify_only ? "v" : "V"; /* reverse special */
4076                 return hashcmd(argc, argv);
4077         }
4078
4079         return 0;
4080 }
4081 #endif
4082
4083 static int
4084 path_change(const char *newval, int *bltin)
4085 {
4086         const char *old, *new;
4087         int idx;
4088         int firstchange;
4089
4090         old = pathval();
4091         new = newval;
4092         firstchange = 9999;     /* assume no change */
4093         idx = 0;
4094         *bltin = -1;
4095         for (;;) {
4096                 if (*old != *new) {
4097                         firstchange = idx;
4098                         if ((*old == '\0' && *new == ':')
4099                          || (*old == ':' && *new == '\0'))
4100                                 firstchange++;
4101                         old = new;      /* ignore subsequent differences */
4102                 }
4103                 if (*new == '\0')
4104                         break;
4105                 if (*new == '%' && *bltin < 0 && prefix("builtin", new + 1))
4106                         *bltin = idx;
4107                 if (*new == ':') {
4108                         idx++;
4109                 }
4110                 new++, old++;
4111         }
4112         if (builtinloc >= 0 && *bltin < 0)
4113                 firstchange = 0;
4114         /* Ensure that getenv("PATH") stays current */
4115         setenv("PATH", newval, 1);
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 void read_profile (const char *);
7445 static void cmdloop (int);
7446 static void options (int);
7447 static void setoption (int, int);
7448 static void procargs (int, char **);
7449
7450
7451 /*
7452  * Main routine.  We initialize things, parse the arguments, execute
7453  * profiles if we're a login shell, and then call cmdloop to execute
7454  * commands.  The setjmp call sets up the location to jump to when an
7455  * exception occurs.  When an exception occurs the variable "state"
7456  * is used to figure out how far we had gotten.
7457  */
7458
7459 int
7460 ash_main(int argc, char **argv)
7461 {
7462         struct jmploc jmploc;
7463         struct stackmark smark;
7464         volatile int state;
7465         const char *shinit;
7466
7467         BLTINCMD = find_builtin("builtin");
7468         EXECCMD = find_builtin("exec");
7469         EVALCMD = find_builtin("eval");
7470
7471 #ifndef CONFIG_FEATURE_SH_FANCY_PROMPT
7472         unsetenv("PS1");
7473         unsetenv("PS2");
7474 #endif
7475
7476 #if PROFILE
7477         monitor(4, etext, profile_buf, sizeof profile_buf, 50);
7478 #endif
7479 #if defined(linux) || defined(__GNU__)
7480         signal(SIGCHLD, SIG_DFL);
7481 #endif
7482         state = 0;
7483         if (setjmp(jmploc.loc)) {
7484                 INTOFF;
7485                 /*
7486                  * When a shell procedure is executed, we raise the
7487                  * exception EXSHELLPROC to clean up before executing
7488                  * the shell procedure.
7489                  */
7490                 if (exception == EXSHELLPROC) {
7491                         rootpid = getpid();
7492                         rootshell = 1;
7493                         minusc = NULL;
7494                         state = 3;
7495                 } else {
7496                         if (exception == EXEXEC) {
7497                                 exitstatus = exerrno;
7498                         } else if (exception == EXERROR) {
7499                                 exitstatus = 2;
7500                         }
7501                     if (state == 0 || iflag == 0 || ! rootshell)
7502                             exitshell(exitstatus);
7503                 }
7504                 reset();
7505                 if (exception == EXINT) {
7506                         out2c('\n');
7507                 }
7508                 popstackmark(&smark);
7509                 FORCEINTON;                             /* enable interrupts */
7510                 if (state == 1)
7511                         goto state1;
7512                 else if (state == 2)
7513                         goto state2;
7514                 else if (state == 3)
7515                         goto state3;
7516                 else
7517                         goto state4;
7518         }
7519         handler = &jmploc;
7520 #ifdef DEBUG
7521         opentrace();
7522         trputs("Shell args:  ");  trargs(argv);
7523 #endif
7524         rootpid = getpid();
7525         rootshell = 1;
7526         init();
7527         setstackmark(&smark);
7528         procargs(argc, argv);
7529         if (argv[0] && argv[0][0] == '-') {
7530                 state = 1;
7531                 read_profile("/etc/profile");
7532 state1:
7533                 state = 2;
7534                 read_profile(".profile");
7535         }
7536 state2:
7537         state = 3;
7538 #ifndef linux
7539         if (getuid() == geteuid() && getgid() == getegid()) {
7540 #endif
7541                 if ((shinit = lookupvar("ENV")) != NULL && *shinit != '\0') {
7542                         state = 3;
7543                         read_profile(shinit);
7544                 }
7545 #ifndef linux
7546         }
7547 #endif
7548 state3:
7549         state = 4;
7550         if (sflag == 0 || minusc) {
7551                 static const char sigs[] =  {
7552                     SIGINT, SIGQUIT, SIGHUP,
7553 #ifdef SIGTSTP
7554                     SIGTSTP,
7555 #endif
7556                     SIGPIPE
7557                 };
7558 #define SIGSSIZE ((sizeof(sigs)/sizeof(sigs[0])) - 1) /* trailing nul */
7559                 int i;
7560
7561                 for (i = 0; i < SIGSSIZE; i++)
7562                     setsignal(sigs[i]);
7563         }
7564
7565         if (minusc)
7566                 evalstring(minusc, 0);
7567
7568         if (sflag || minusc == NULL) {
7569 state4: /* XXX ??? - why isn't this before the "if" statement */
7570                 cmdloop(1);
7571         }
7572 #if PROFILE
7573         monitor(0);
7574 #endif
7575         exitshell(exitstatus);
7576         /* NOTREACHED */
7577 }
7578
7579
7580 /*
7581  * Read and execute commands.  "Top" is nonzero for the top level command
7582  * loop; it turns on prompting if the shell is interactive.
7583  */
7584
7585 static void
7586 cmdloop(int top)
7587 {
7588         union node *n;
7589         struct stackmark smark;
7590         int inter;
7591         int numeof = 0;
7592
7593         TRACE(("cmdloop(%d) called\n", top));
7594         setstackmark(&smark);
7595         for (;;) {
7596                 if (pendingsigs)
7597                         dotrap();
7598                 inter = 0;
7599                 if (iflag && top) {
7600                         inter++;
7601                         showjobs(1);
7602 #ifdef CONFIG_ASH_MAIL
7603                         chkmail(0);
7604 #endif
7605                         flushall();
7606                 }
7607                 n = parsecmd(inter);
7608                 /* showtree(n); DEBUG */
7609                 if (n == NEOF) {
7610                         if (!top || numeof >= 50)
7611                                 break;
7612                         if (!stoppedjobs()) {
7613                                 if (!Iflag)
7614                                         break;
7615                                 out2str("\nUse \"exit\" to leave shell.\n");
7616                         }
7617                         numeof++;
7618                 } else if (n != NULL && nflag == 0) {
7619                         job_warning = (job_warning == 2) ? 1 : 0;
7620                         numeof = 0;
7621                         evaltree(n, 0);
7622                 }
7623                 popstackmark(&smark);
7624                 setstackmark(&smark);
7625                 if (evalskip == SKIPFILE) {
7626                         evalskip = 0;
7627                         break;
7628                 }
7629         }
7630         popstackmark(&smark);
7631 }
7632
7633
7634
7635 /*
7636  * Read /etc/profile or .profile.  Return on error.
7637  */
7638
7639 static void
7640 read_profile(const char *name)
7641 {
7642         int fd;
7643         int xflag_save;
7644         int vflag_save;
7645
7646         INTOFF;
7647         if ((fd = open(name, O_RDONLY)) >= 0)
7648                 setinputfd(fd, 1);
7649         INTON;
7650         if (fd < 0)
7651                 return;
7652         /* -q turns off -x and -v just when executing init files */
7653         /* Note: Might do a little redundant work, but reduces code size. */
7654         xflag_save = xflag;
7655         vflag_save = vflag;
7656         if (qflag)  {
7657                 vflag = xflag = 0;
7658         }
7659         cmdloop(0);
7660         xflag = xflag_save;
7661         vflag = vflag_save;
7662         popfile();
7663 }
7664
7665
7666
7667 /*
7668  * Read a file containing shell functions.
7669  */
7670
7671 static void
7672 readcmdfile(const char *name)
7673 {
7674         int fd;
7675
7676         INTOFF;
7677         if ((fd = open(name, O_RDONLY)) >= 0)
7678                 setinputfd(fd, 1);
7679         else
7680                 error("Can't open %s", name);
7681         INTON;
7682         cmdloop(0);
7683         popfile();
7684 }
7685
7686
7687
7688 /*
7689  * Take commands from a file.  To be compatable we should do a path
7690  * search for the file, which is necessary to find sub-commands.
7691  */
7692
7693 static inline char *
7694 find_dot_file(char *mybasename)
7695 {
7696         char *fullname;
7697         const char *path = pathval();
7698         struct stat statb;
7699
7700         /* don't try this for absolute or relative paths */
7701         if (strchr(mybasename, '/'))
7702                 return mybasename;
7703
7704         while ((fullname = padvance(&path, mybasename)) != NULL) {
7705                 if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) {
7706                         /*
7707                          * Don't bother freeing here, since it will
7708                          * be freed by the caller.
7709                          */
7710                         return fullname;
7711                 }
7712                 stunalloc(fullname);
7713         }
7714
7715         /* not found in the PATH */
7716         error("%s: not found", mybasename);
7717         /* NOTREACHED */
7718 }
7719
7720 static int
7721 dotcmd(int argc, char **argv)
7722 {
7723         struct strlist *sp;
7724         volatile struct shparam saveparam;
7725         exitstatus = 0;
7726
7727         for (sp = cmdenviron; sp ; sp = sp->next)
7728                 setvareq(xstrdup(sp->text), VSTRFIXED|VTEXTFIXED);
7729
7730         if (argc >= 2) {                /* That's what SVR2 does */
7731                 char *fullname;
7732                 struct stackmark smark;
7733
7734                 setstackmark(&smark);
7735                 fullname = find_dot_file(argv[1]);
7736
7737                 if (argc>2) {
7738                         saveparam = shellparam;
7739                         shellparam.malloc = 0;
7740                         shellparam.nparam = argc - 2;
7741                         shellparam.p = argv + 2;
7742                 };
7743
7744                 setinputfile(fullname, 1);
7745                 commandname = fullname;
7746                 cmdloop(0);
7747                 popfile();
7748
7749                 if (argc>2) {
7750                         freeparam(&shellparam);
7751                         shellparam = saveparam;
7752                 };
7753
7754                 popstackmark(&smark);
7755         }
7756         return exitstatus;
7757 }
7758
7759
7760 static int
7761 exitcmd(int argc, char **argv)
7762 {
7763         if (stoppedjobs())
7764                 return 0;
7765         if (argc > 1)
7766                 exitstatus = number(argv[1]);
7767         else
7768                 exitstatus = oexitstatus;
7769         exitshell(exitstatus);
7770         /* NOTREACHED */
7771 }
7772
7773 static pointer
7774 stalloc(int nbytes)
7775 {
7776         char *p;
7777
7778         nbytes = ALIGN(nbytes);
7779         if (nbytes > stacknleft) {
7780                 int blocksize;
7781                 struct stack_block *sp;
7782
7783                 blocksize = nbytes;
7784                 if (blocksize < MINSIZE)
7785                         blocksize = MINSIZE;
7786                 INTOFF;
7787                 sp = xmalloc(sizeof(struct stack_block) - MINSIZE + blocksize);
7788                 sp->prev = stackp;
7789                 stacknxt = sp->space;
7790                 stacknleft = blocksize;
7791                 stackp = sp;
7792                 INTON;
7793         }
7794         p = stacknxt;
7795         stacknxt += nbytes;
7796         stacknleft -= nbytes;
7797         return p;
7798 }
7799
7800
7801 static void
7802 stunalloc(pointer p)
7803 {
7804 #ifdef DEBUG
7805         if (p == NULL) {                /*DEBUG */
7806                 write(2, "stunalloc\n", 10);
7807                 abort();
7808         }
7809 #endif
7810         if (!(stacknxt >= (char *)p && (char *)p >= stackp->space)) {
7811                 p = stackp->space;
7812         }
7813         stacknleft += stacknxt - (char *)p;
7814         stacknxt = p;
7815 }
7816
7817
7818 static void
7819 setstackmark(struct stackmark *mark)
7820 {
7821         mark->stackp = stackp;
7822         mark->stacknxt = stacknxt;
7823         mark->stacknleft = stacknleft;
7824         mark->marknext = markp;
7825         markp = mark;
7826 }
7827
7828
7829 static void
7830 popstackmark(struct stackmark *mark)
7831 {
7832         struct stack_block *sp;
7833
7834         INTOFF;
7835         markp = mark->marknext;
7836         while (stackp != mark->stackp) {
7837                 sp = stackp;
7838                 stackp = sp->prev;
7839                 ckfree(sp);
7840         }
7841         stacknxt = mark->stacknxt;
7842         stacknleft = mark->stacknleft;
7843         INTON;
7844 }
7845
7846
7847 /*
7848  * When the parser reads in a string, it wants to stick the string on the
7849  * stack and only adjust the stack pointer when it knows how big the
7850  * string is.  Stackblock (defined in stack.h) returns a pointer to a block
7851  * of space on top of the stack and stackblocklen returns the length of
7852  * this block.  Growstackblock will grow this space by at least one byte,
7853  * possibly moving it (like realloc).  Grabstackblock actually allocates the
7854  * part of the block that has been used.
7855  */
7856
7857 static void
7858 growstackblock(void) {
7859         char *p;
7860         int newlen = ALIGN(stacknleft * 2 + 100);
7861         char *oldspace = stacknxt;
7862         int oldlen = stacknleft;
7863         struct stack_block *sp;
7864         struct stack_block *oldstackp;
7865
7866         if (stacknxt == stackp->space && stackp != &stackbase) {
7867                 INTOFF;
7868                 oldstackp = stackp;
7869                 sp = stackp;
7870                 stackp = sp->prev;
7871                 sp = xrealloc((pointer)sp, sizeof(struct stack_block) - MINSIZE + newlen);
7872                 sp->prev = stackp;
7873                 stackp = sp;
7874                 stacknxt = sp->space;
7875                 stacknleft = newlen;
7876                 {
7877                   /* Stack marks pointing to the start of the old block
7878                    * must be relocated to point to the new block
7879                    */
7880                   struct stackmark *xmark;
7881                   xmark = markp;
7882                   while (xmark != NULL && xmark->stackp == oldstackp) {
7883                     xmark->stackp = stackp;
7884                     xmark->stacknxt = stacknxt;
7885                     xmark->stacknleft = stacknleft;
7886                     xmark = xmark->marknext;
7887                   }
7888                 }
7889                 INTON;
7890         } else {
7891                 p = stalloc(newlen);
7892                 memcpy(p, oldspace, oldlen);
7893                 stacknxt = p;                   /* free the space */
7894                 stacknleft += newlen;           /* we just allocated */
7895         }
7896 }
7897
7898
7899
7900 static inline void
7901 grabstackblock(int len)
7902 {
7903         len = ALIGN(len);
7904         stacknxt += len;
7905         stacknleft -= len;
7906 }
7907
7908
7909
7910 /*
7911  * The following routines are somewhat easier to use that the above.
7912  * The user declares a variable of type STACKSTR, which may be declared
7913  * to be a register.  The macro STARTSTACKSTR initializes things.  Then
7914  * the user uses the macro STPUTC to add characters to the string.  In
7915  * effect, STPUTC(c, p) is the same as *p++ = c except that the stack is
7916  * grown as necessary.  When the user is done, she can just leave the
7917  * string there and refer to it using stackblock().  Or she can allocate
7918  * the space for it using grabstackstr().  If it is necessary to allow
7919  * someone else to use the stack temporarily and then continue to grow
7920  * the string, the user should use grabstack to allocate the space, and
7921  * then call ungrabstr(p) to return to the previous mode of operation.
7922  *
7923  * USTPUTC is like STPUTC except that it doesn't check for overflow.
7924  * CHECKSTACKSPACE can be called before USTPUTC to ensure that there
7925  * is space for at least one character.
7926  */
7927
7928
7929 static char *
7930 growstackstr(void) {
7931         int len = stackblocksize();
7932         if (herefd >= 0 && len >= 1024) {
7933                 xwrite(herefd, stackblock(), len);
7934                 sstrnleft = len - 1;
7935                 return stackblock();
7936         }
7937         growstackblock();
7938         sstrnleft = stackblocksize() - len - 1;
7939         return stackblock() + len;
7940 }
7941
7942
7943 /*
7944  * Called from CHECKSTRSPACE.
7945  */
7946
7947 static char *
7948 makestrspace(size_t newlen) {
7949         int len = stackblocksize() - sstrnleft;
7950         do {
7951                 growstackblock();
7952                 sstrnleft = stackblocksize() - len;
7953         } while (sstrnleft < newlen);
7954         return stackblock() + len;
7955 }
7956
7957
7958
7959 static void
7960 ungrabstackstr(char *s, char *p)
7961 {
7962         stacknleft += stacknxt - s;
7963         stacknxt = s;
7964         sstrnleft = stacknleft - (p - s);
7965 }
7966 /*
7967  * Miscelaneous builtins.
7968  */
7969
7970
7971 #undef rflag
7972
7973 #if !defined(__GLIBC__) || __GLIBC__ == 2 && __GLIBC_MINOR__ < 1
7974 typedef long rlim_t;
7975 #endif
7976
7977
7978
7979 /*
7980  * The read builtin.  The -e option causes backslashes to escape the
7981  * following character.
7982  *
7983  * This uses unbuffered input, which may be avoidable in some cases.
7984  */
7985
7986 static int
7987 readcmd(int argc, char **argv)
7988 {
7989         char **ap;
7990         int backslash;
7991         char c;
7992         int rflag;
7993         char *prompt;
7994         const char *ifs;
7995         char *p;
7996         int startword;
7997         int status;
7998         int i;
7999
8000         rflag = 0;
8001         prompt = NULL;
8002         while ((i = nextopt("p:r")) != '\0') {
8003                 if (i == 'p')
8004                         prompt = optionarg;
8005                 else
8006                         rflag = 1;
8007         }
8008         if (prompt && isatty(0)) {
8009                 out2str(prompt);     /* read without cmdedit */
8010                 flushall();
8011         }
8012         if (*(ap = argptr) == NULL)
8013                 error("arg count");
8014         if ((ifs = bltinlookup("IFS")) == NULL)
8015                 ifs = defifs;
8016         status = 0;
8017         startword = 1;
8018         backslash = 0;
8019         STARTSTACKSTR(p);
8020         for (;;) {
8021                 if (read(0, &c, 1) != 1) {
8022                         status = 1;
8023                         break;
8024                 }
8025                 if (c == '\0')
8026                         continue;
8027                 if (backslash) {
8028                         backslash = 0;
8029                         if (c != '\n')
8030                                 STPUTC(c, p);
8031                         continue;
8032                 }
8033                 if (!rflag && c == '\\') {
8034                         backslash++;
8035                         continue;
8036                 }
8037                 if (c == '\n')
8038                         break;
8039                 if (startword && *ifs == ' ' && strchr(ifs, c)) {
8040                         continue;
8041                 }
8042                 startword = 0;
8043                 if (backslash && c == '\\') {
8044                         if (read(0, &c, 1) != 1) {
8045                                 status = 1;
8046                                 break;
8047                         }
8048                         STPUTC(c, p);
8049                 } else if (ap[1] != NULL && strchr(ifs, c) != NULL) {
8050                         STACKSTRNUL(p);
8051                         setvar(*ap, stackblock(), 0);
8052                         ap++;
8053                         startword = 1;
8054                         STARTSTACKSTR(p);
8055                 } else {
8056                         STPUTC(c, p);
8057                 }
8058         }
8059         STACKSTRNUL(p);
8060         /* Remove trailing blanks */
8061         while (stackblock() <= --p && strchr(ifs, *p) != NULL)
8062                 *p = '\0';
8063         setvar(*ap, stackblock(), 0);
8064         while (*++ap != NULL)
8065                 setvar(*ap, nullstr, 0);
8066         return status;
8067 }
8068
8069
8070
8071 static int
8072 umaskcmd(int argc, char **argv)
8073 {
8074         static const char permuser[3] = "ugo";
8075         static const char permmode[3] = "rwx";
8076         static const short int permmask[] = {
8077                 S_IRUSR, S_IWUSR, S_IXUSR,
8078                 S_IRGRP, S_IWGRP, S_IXGRP,
8079                 S_IROTH, S_IWOTH, S_IXOTH
8080         };
8081
8082         char *ap;
8083         mode_t mask;
8084         int i;
8085         int symbolic_mode = 0;
8086
8087         while (nextopt("S") != '\0') {
8088                 symbolic_mode = 1;
8089         }
8090
8091         INTOFF;
8092         mask = umask(0);
8093         umask(mask);
8094         INTON;
8095
8096         if ((ap = *argptr) == NULL) {
8097                 if (symbolic_mode) {
8098                         char buf[18];
8099                         char *p = buf;
8100                         for (i=0 ; i<3 ; i++) {
8101                                 int j;
8102                                 *p++ = permuser[i];
8103                                 *p++ = '=';
8104                                 for (j=0 ; j<3 ; j++) {
8105                                         if ((mask & permmask[3*i+j]) == 0) {
8106                                                 *p++ = permmode[j];
8107                                         }
8108                                 }
8109                                 *p++ = ',';
8110                         }
8111                         *--p = 0;
8112                         puts(buf);
8113                 } else {
8114                         printf("%.4o\n", mask);
8115                 }
8116         } else {
8117                 if (is_digit((unsigned char)*ap)) {
8118                         mask = 0;
8119                         do {
8120                                 if (*ap >= '8' || *ap < '0')
8121                                         error("Illegal number: %s", argv[1]);
8122                                 mask = (mask << 3) + (*ap - '0');
8123                         } while (*++ap != '\0');
8124                         umask(mask);
8125                 } else {
8126                         mask = ~mask & 0777;
8127                         if (! parse_mode(ap, &mask)) {
8128                                 error("Illegal mode: %s", ap);
8129                         }
8130                         umask(~mask & 0777);
8131                 }
8132         }
8133         return 0;
8134 }
8135
8136 /*
8137  * ulimit builtin
8138  *
8139  * This code, originally by Doug Gwyn, Doug Kingston, Eric Gisin, and
8140  * Michael Rendell was ripped from pdksh 5.0.8 and hacked for use with
8141  * ash by J.T. Conklin.
8142  *
8143  * Public domain.
8144  */
8145
8146 struct limits {
8147         const char *name;
8148         short   cmd;
8149         short   factor; /* multiply by to get rlim_{cur,max} values */
8150 };
8151
8152 static const struct limits limits[] = {
8153 #ifdef RLIMIT_CPU
8154         { "time(seconds)",             RLIMIT_CPU,        1 },
8155 #endif
8156 #ifdef RLIMIT_FSIZE
8157         { "file(blocks)",              RLIMIT_FSIZE,    512 },
8158 #endif
8159 #ifdef RLIMIT_DATA
8160         { "data(kbytes)",              RLIMIT_DATA,    1024 },
8161 #endif
8162 #ifdef RLIMIT_STACK
8163         { "stack(kbytes)",             RLIMIT_STACK,   1024 },
8164 #endif
8165 #ifdef  RLIMIT_CORE
8166         { "coredump(blocks)",          RLIMIT_CORE,     512 },
8167 #endif
8168 #ifdef RLIMIT_RSS
8169         { "memory(kbytes)",            RLIMIT_RSS,     1024 },
8170 #endif
8171 #ifdef RLIMIT_MEMLOCK
8172         { "locked memory(kbytes)",     RLIMIT_MEMLOCK, 1024 },
8173 #endif
8174 #ifdef RLIMIT_NPROC
8175         { "process(processes)",        RLIMIT_NPROC,      1 },
8176 #endif
8177 #ifdef RLIMIT_NOFILE
8178         { "nofiles(descriptors)",      RLIMIT_NOFILE,     1 },
8179 #endif
8180 #ifdef RLIMIT_VMEM
8181         { "vmemory(kbytes)",           RLIMIT_VMEM,    1024 },
8182 #endif
8183 #ifdef RLIMIT_SWAP
8184         { "swap(kbytes)",              RLIMIT_SWAP,    1024 },
8185 #endif
8186         { NULL,                         0,                 0 }
8187 };
8188
8189 static int
8190 ulimitcmd(int argc, char **argv)
8191 {
8192         static const char unlimited_string[] = "unlimited";
8193         int     c;
8194         rlim_t val = 0;
8195         enum { SOFT = 0x1, HARD = 0x2 }
8196                         how = SOFT | HARD;
8197         const struct limits     *l;
8198         int             set, all = 0;
8199         int             optc, what;
8200         struct rlimit   limit;
8201
8202         what = 'f';
8203
8204         while ((optc = nextopt("HSa"
8205 #ifdef RLIMIT_CPU
8206         "t"
8207 #endif
8208 #ifdef RLIMIT_FSIZE
8209         "f"
8210 #endif
8211 #ifdef RLIMIT_DATA
8212         "d"
8213 #endif
8214 #ifdef RLIMIT_STACK
8215         "s"
8216 #endif
8217 #ifdef  RLIMIT_CORE
8218         "c"
8219 #endif
8220 #ifdef RLIMIT_RSS
8221         "m"
8222 #endif
8223 #ifdef RLIMIT_MEMLOCK
8224         "l"
8225 #endif
8226 #ifdef RLIMIT_NPROC
8227         "p"
8228 #endif
8229 #ifdef RLIMIT_NOFILE
8230         "n"
8231 #endif
8232 #ifdef RLIMIT_VMEM
8233         "v"
8234 #endif
8235 #ifdef RLIMIT_SWAP
8236         "w"
8237 #endif
8238                                         )) != '\0') {
8239                 if (optc == 'H') {
8240                         how = HARD;
8241                 } else if (optc == 'S') {
8242                         how = SOFT;
8243                 } else if (optc == 'a') {
8244                         all = 1;
8245                 } else {
8246                         what = optc;
8247                 }
8248         }
8249
8250         for (l = limits; l->name; l++) {
8251                 if(l->name[0] == what)
8252                         break;
8253                 if(l->name[1]=='w' && what=='w')
8254                         break;
8255         }
8256
8257         set = *argptr ? 1 : 0;
8258         if (set) {
8259                 char *p = *argptr;
8260
8261                 if (all || argptr[1])
8262                         error("too many arguments");
8263                 if (strcmp(p, unlimited_string) == 0)
8264                         val = RLIM_INFINITY;
8265                 else {
8266                         val = (rlim_t) 0;
8267
8268                         while ((c = *p++) >= '0' && c <= '9')
8269                         {
8270                                 val = (val * 10) + (long)(c - '0');
8271                                 if (val < (rlim_t) 0)
8272                                         break;
8273                         }
8274                         if (c)
8275                                 error("bad number");
8276                         val *= l->factor;
8277                 }
8278         }
8279
8280         if (all) {
8281                 for (l = limits; l->name; l++) {
8282                         printf("%-20s ", l->name);
8283                         getrlimit(l->cmd, &limit);
8284                 OUTPUT_LIMIT:
8285                         if (how & SOFT)
8286                                 val = limit.rlim_cur;
8287                         else if (how & HARD)
8288                                 val = limit.rlim_max;
8289
8290                         if (val == RLIM_INFINITY)
8291                                 puts(unlimited_string);
8292                         else
8293                         {
8294                                 val /= l->factor;
8295                                 printf("%lld\n", (long long) val);
8296                         }
8297                         if (!all) {
8298                                 break;
8299                         }
8300                 }
8301                 return 0;
8302         }
8303
8304         if (!set) {
8305                 goto OUTPUT_LIMIT;
8306         }
8307
8308         getrlimit(l->cmd, &limit);
8309         if (how & HARD)
8310                 limit.rlim_max = val;
8311         if (how & SOFT)
8312                 limit.rlim_cur = val;
8313         if (setrlimit(l->cmd, &limit) < 0)
8314                 error("error setting limit (%m)");
8315         return 0;
8316 }
8317 /*
8318  * prefix -- see if pfx is a prefix of string.
8319  */
8320
8321 static int
8322 prefix(char const *pfx, char const *string)
8323 {
8324         while (*pfx) {
8325                 if (*pfx++ != *string++)
8326                         return 0;
8327         }
8328         return 1;
8329 }
8330
8331 /*
8332  * Return true if s is a string of digits, and save munber in intptr
8333  * nagative is bad
8334  */
8335
8336 static int
8337 is_number(const char *p, int *intptr)
8338 {
8339         int ret = 0;
8340
8341         do {
8342                 if (! is_digit(*p))
8343                         return 0;
8344                 ret *= 10;
8345                 ret += digit_val(*p);
8346                 p++;
8347         } while (*p != '\0');
8348
8349         *intptr = ret;
8350         return 1;
8351 }
8352
8353 /*
8354  * Convert a string of digits to an integer, printing an error message on
8355  * failure.
8356  */
8357
8358 static int
8359 number(const char *s)
8360 {
8361         int i;
8362         if (! is_number(s, &i))
8363                 error("Illegal number: %s", s);
8364         return i;
8365 }
8366
8367 /*
8368  * Produce a possibly single quoted string suitable as input to the shell.
8369  * The return string is allocated on the stack.
8370  */
8371
8372 static char *
8373 single_quote(const char *s)
8374 {
8375         char *p;
8376
8377         STARTSTACKSTR(p);
8378
8379         do {
8380                 char *q = p;
8381                 size_t len1, len1p, len2, len2p;
8382
8383                 len1 = strcspn(s, "'");
8384                 len2 = strspn(s + len1, "'");
8385
8386                 len1p = len1 ? len1 + 2 : len1;
8387                 len2p = len2 + ((len2 < 2) ? len2 : 2);
8388
8389                 CHECKSTRSPACE(len1p + len2p + 1, p);
8390
8391                 if (len1) {
8392                         *p = '\'';
8393                         q = p + 1 + len1;
8394                         memcpy(p + 1, s, len1);
8395                         *q++ = '\'';
8396                         s += len1;
8397                 }
8398
8399                 if (len2 > 1) {
8400                         *q = '"';
8401                         q += 1 + len2;
8402                         memcpy(q + 1, s, len2);
8403                         *q = '"';
8404                         s += len2;
8405                 } else if (len2 == 1) {
8406                         *q++ = '\\';
8407                         *q = '\'';
8408                         s++;
8409                 }
8410
8411                 STADJUST(len1p + len2p, p);
8412         } while (*s);
8413
8414         USTPUTC(0, p);
8415
8416         return grabstackstr(p);
8417 }
8418
8419 /*
8420  * Like strdup but works with the ash stack.
8421  */
8422
8423 static char *
8424 sstrdup(const char *p)
8425 {
8426         size_t len = strlen(p) + 1;
8427         return memcpy(stalloc(len), p, len);
8428 }
8429
8430
8431 /*
8432  * Routine for dealing with parsed shell commands.
8433  */
8434
8435
8436 static void sizenodelist (const struct nodelist *);
8437 static struct nodelist *copynodelist (const struct nodelist *);
8438 static char *nodexstrdup (const char *);
8439
8440 #define CALCSIZE_TABLE
8441 #define COPYNODE_TABLE
8442 #if defined(CALCSIZE_TABLE) || defined(COPYNODE_TABLE)
8443 /*
8444  * To collect a lot of redundant code in case statements for copynode()
8445  * and calcsize(), we implement a mini language here.  Each type of node
8446  * struct has an associated instruction sequence that operates on its
8447  * members via their offsets.  The instruction are pack in unsigned chars
8448  * with format   IIDDDDDE   where the bits are
8449  *   I : part of the instruction opcode, which are
8450  *       00 : member is a pointer to another node
8451  *       40 : member is an integer
8452  *       80 : member is a pointer to a nodelist
8453  *       CC : member is a pointer to a char string
8454  *   D : data - the actual offset of the member to operate on in the struct
8455  *              (since we assume bit 0 is set, it is not shifted)
8456  *   E : flag signaling end of instruction sequence
8457  *
8458  * WARNING: In order to handle larger offsets for 64bit archs, this code
8459  *          assumes that no offset can be an odd number and stores the
8460  *          end-of-instructions flag in bit 0.
8461  */
8462
8463 #define NODE_INTEGER    0x40
8464 #define NODE_NODELIST   0x80
8465 #define NODE_CHARPTR    0xC0
8466 #define NODE_NOMORE             0x01    /* Note: no offset should be odd (aligned)*/
8467 #define NODE_MBRMASK    0xC0
8468 #define NODE_OFFSETMASK 0x3E
8469
8470 static const unsigned char copynode_ops[35] = {
8471 #define COPYNODE_OPS0   0
8472         offsetof(union node, nbinary.ch2),
8473         offsetof(union node, nbinary.ch1)|NODE_NOMORE,
8474 #define COPYNODE_OPS1   (COPYNODE_OPS0 + 2)
8475         offsetof(union node, ncmd.redirect),
8476         offsetof(union node, ncmd.args),
8477         offsetof(union node, ncmd.assign),
8478         offsetof(union node, ncmd.backgnd)|NODE_INTEGER|NODE_NOMORE,
8479 #define COPYNODE_OPS2   (COPYNODE_OPS1 + 4)
8480         offsetof(union node, npipe.cmdlist)|NODE_NODELIST,
8481         offsetof(union node, npipe.backgnd)|NODE_INTEGER|NODE_NOMORE,
8482 #define COPYNODE_OPS3   (COPYNODE_OPS2 + 2)
8483         offsetof(union node, nredir.redirect),
8484         offsetof(union node, nredir.n)|NODE_NOMORE,
8485 #define COPYNODE_OPS4   (COPYNODE_OPS3 + 2)
8486         offsetof(union node, nif.elsepart),
8487         offsetof(union node, nif.ifpart),
8488         offsetof(union node, nif.test)|NODE_NOMORE,
8489 #define COPYNODE_OPS5   (COPYNODE_OPS4 + 3)
8490         offsetof(union node, nfor.var)|NODE_CHARPTR,
8491         offsetof(union node, nfor.body),
8492         offsetof(union node, nfor.args)|NODE_NOMORE,
8493 #define COPYNODE_OPS6   (COPYNODE_OPS5 + 3)
8494         offsetof(union node, ncase.cases),
8495         offsetof(union node, ncase.expr)|NODE_NOMORE,
8496 #define COPYNODE_OPS7   (COPYNODE_OPS6 + 2)
8497         offsetof(union node, nclist.body),
8498         offsetof(union node, nclist.pattern),
8499         offsetof(union node, nclist.next)|NODE_NOMORE,
8500 #define COPYNODE_OPS8   (COPYNODE_OPS7 + 3)
8501         offsetof(union node, narg.backquote)|NODE_NODELIST,
8502         offsetof(union node, narg.text)|NODE_CHARPTR,
8503         offsetof(union node, narg.next)|NODE_NOMORE,
8504 #define COPYNODE_OPS9   (COPYNODE_OPS8 + 3)
8505         offsetof(union node, nfile.fname),
8506         offsetof(union node, nfile.fd)|NODE_INTEGER,
8507         offsetof(union node, nfile.next)|NODE_NOMORE,
8508 #define COPYNODE_OPS10   (COPYNODE_OPS9 + 3)
8509         offsetof(union node, ndup.vname),
8510         offsetof(union node, ndup.dupfd)|NODE_INTEGER,
8511         offsetof(union node, ndup.fd)|NODE_INTEGER,
8512         offsetof(union node, ndup.next)|NODE_NOMORE,
8513 #define COPYNODE_OPS11   (COPYNODE_OPS10 + 4)
8514         offsetof(union node, nhere.doc),
8515         offsetof(union node, nhere.fd)|NODE_INTEGER,
8516         offsetof(union node, nhere.next)|NODE_NOMORE,
8517 #define COPYNODE_OPS12   (COPYNODE_OPS11 + 3)
8518         offsetof(union node, nnot.com)|NODE_NOMORE,
8519 };
8520
8521 #if COPYNODE_OPS12 != 34
8522 #error COPYNODE_OPS12 is incorrect
8523 #endif
8524
8525 static const unsigned char copynode_ops_index[26] = {
8526         COPYNODE_OPS0, /* NSEMI */
8527         COPYNODE_OPS1, /* NCMD */
8528         COPYNODE_OPS2, /* NPIPE */
8529         COPYNODE_OPS3, /* NREDIR */
8530         COPYNODE_OPS3, /* NBACKGND */
8531         COPYNODE_OPS3, /* NSUBSHELL */
8532         COPYNODE_OPS0, /* NAND */
8533         COPYNODE_OPS0, /* NOR */
8534         COPYNODE_OPS4, /* NIF */
8535         COPYNODE_OPS0, /* NWHILE */
8536         COPYNODE_OPS0, /* NUNTIL */
8537         COPYNODE_OPS5, /* NFOR */
8538         COPYNODE_OPS6, /* NCASE */
8539         COPYNODE_OPS7, /* NCLIST */
8540         COPYNODE_OPS8, /* NDEFUN */
8541         COPYNODE_OPS8, /* NARG */
8542         COPYNODE_OPS9, /* NTO */
8543         COPYNODE_OPS9, /* NFROM */
8544         COPYNODE_OPS9, /* NFROMTO */
8545         COPYNODE_OPS9, /* NAPPEND */
8546         COPYNODE_OPS9, /* NTOOV */
8547         COPYNODE_OPS10, /* NTOFD */
8548         COPYNODE_OPS10, /* NFROMFD */
8549         COPYNODE_OPS11, /* NHERE */
8550         COPYNODE_OPS11, /* NXHERE */
8551         COPYNODE_OPS12, /* NNOT */
8552 };
8553
8554 #if NODE_CHARPTR != NODE_MBRMASK
8555 #error NODE_CHARPTR != NODE_MBRMASK!!!
8556 #endif
8557 #endif /* defined(CALCSIZE_TABLE) || defined(COPYNODE_TABLE) */
8558
8559 #ifdef COPYNODE_TABLE
8560 static union node *
8561 copynode(const union node *n)
8562 {
8563       union node *new;
8564           const unsigned char *p;
8565
8566       if (n == NULL) {
8567           return NULL;
8568           }
8569       new = funcblock;
8570       new->type = n->type;
8571       funcblock = (char *) funcblock + (int) nodesize[n->type];
8572           p = copynode_ops + (int) copynode_ops_index[n->type];
8573           do {
8574                   char *nn = ((char *) new) + ((int)(*p & NODE_OFFSETMASK));
8575                   const char *no = ((const char *) n) + ((int)(*p & NODE_OFFSETMASK));
8576
8577                   if (!(*p & NODE_MBRMASK)) { /* standard node */
8578                           *((union node **)nn) = copynode(*((const union node **) no));
8579                   } else if ((*p & NODE_MBRMASK) == NODE_CHARPTR) { /* string */
8580                           *((const char **)nn) = nodexstrdup(*((const char **)no));
8581                   } else if (*p & NODE_NODELIST) { /* nodelist */
8582                           *((struct nodelist **)nn)
8583                                   = copynodelist(*((const struct nodelist **) no));
8584                   } else {                              /* integer */
8585                           *((int *) nn) = *((int *) no);
8586                   }
8587           } while (!(*p++ & NODE_NOMORE));
8588       return new;
8589 }
8590 #else  /* COPYNODE_TABLE */
8591 static union node *
8592 copynode(const union node *n)
8593 {
8594       union node *new;
8595
8596       if (n == NULL)
8597         return NULL;
8598       new = funcblock;
8599       funcblock = (char *) funcblock + nodesize[n->type];
8600       switch (n->type) {
8601       case NSEMI:
8602       case NAND:
8603       case NOR:
8604       case NWHILE:
8605       case NUNTIL:
8606             new->nbinary.ch2 = copynode(n->nbinary.ch2);
8607             new->nbinary.ch1 = copynode(n->nbinary.ch1);
8608             break;
8609       case NCMD:
8610             new->ncmd.redirect = copynode(n->ncmd.redirect);
8611             new->ncmd.args = copynode(n->ncmd.args);
8612             new->ncmd.assign = copynode(n->ncmd.assign);
8613             new->ncmd.backgnd = n->ncmd.backgnd;
8614             break;
8615       case NPIPE:
8616             new->npipe.cmdlist = copynodelist(n->npipe.cmdlist);
8617             new->npipe.backgnd = n->npipe.backgnd;
8618             break;
8619       case NREDIR:
8620       case NBACKGND:
8621       case NSUBSHELL:
8622             new->nredir.redirect = copynode(n->nredir.redirect);
8623             new->nredir.n = copynode(n->nredir.n);
8624             break;
8625       case NIF:
8626             new->nif.elsepart = copynode(n->nif.elsepart);
8627             new->nif.ifpart = copynode(n->nif.ifpart);
8628             new->nif.test = copynode(n->nif.test);
8629             break;
8630       case NFOR:
8631             new->nfor.var = nodexstrdup(n->nfor.var);
8632             new->nfor.body = copynode(n->nfor.body);
8633             new->nfor.args = copynode(n->nfor.args);
8634             break;
8635       case NCASE:
8636             new->ncase.cases = copynode(n->ncase.cases);
8637             new->ncase.expr = copynode(n->ncase.expr);
8638             break;
8639       case NCLIST:
8640             new->nclist.body = copynode(n->nclist.body);
8641             new->nclist.pattern = copynode(n->nclist.pattern);
8642             new->nclist.next = copynode(n->nclist.next);
8643             break;
8644       case NDEFUN:
8645       case NARG:
8646             new->narg.backquote = copynodelist(n->narg.backquote);
8647             new->narg.text = nodexstrdup(n->narg.text);
8648             new->narg.next = copynode(n->narg.next);
8649             break;
8650       case NTO:
8651       case NFROM:
8652       case NFROMTO:
8653       case NAPPEND:
8654       case NTOOV:
8655             new->nfile.fname = copynode(n->nfile.fname);
8656             new->nfile.fd = n->nfile.fd;
8657             new->nfile.next = copynode(n->nfile.next);
8658             break;
8659       case NTOFD:
8660       case NFROMFD:
8661             new->ndup.vname = copynode(n->ndup.vname);
8662             new->ndup.dupfd = n->ndup.dupfd;
8663             new->ndup.fd = n->ndup.fd;
8664             new->ndup.next = copynode(n->ndup.next);
8665             break;
8666       case NHERE:
8667       case NXHERE:
8668             new->nhere.doc = copynode(n->nhere.doc);
8669             new->nhere.fd = n->nhere.fd;
8670             new->nhere.next = copynode(n->nhere.next);
8671             break;
8672       case NNOT:
8673             new->nnot.com = copynode(n->nnot.com);
8674             break;
8675       };
8676       new->type = n->type;
8677       return new;
8678 }
8679 #endif /* COPYNODE_TABLE */
8680
8681 #ifdef CALCSIZE_TABLE
8682 static void
8683 calcsize(const union node *n)
8684 {
8685           const unsigned char *p;
8686
8687       if (n == NULL)
8688             return;
8689       funcblocksize += (int) nodesize[n->type];
8690
8691           p = copynode_ops + (int) copynode_ops_index[n->type];
8692           do {
8693                   const char *no = ((const char *) n) + ((int)(*p & NODE_OFFSETMASK));
8694
8695                   if (!(*p & NODE_MBRMASK)) { /* standard node */
8696                           calcsize(*((const union node **) no));
8697                   } else if ((*p & NODE_MBRMASK) == NODE_CHARPTR) { /* string */
8698                           funcstringsize += strlen(*((const char **)no)) + 1;
8699                   } else if (*p & NODE_NODELIST) { /* nodelist */
8700                           sizenodelist(*((const struct nodelist **) no));
8701                   }     /* else integer -- ignore */
8702           } while (!(*p++ & NODE_NOMORE));
8703 }
8704 #else  /* CALCSIZE_TABLE */
8705 static void
8706 calcsize(const union node *n)
8707 {
8708       if (n == NULL)
8709             return;
8710       funcblocksize += nodesize[n->type];
8711       switch (n->type) {
8712       case NSEMI:
8713       case NAND:
8714       case NOR:
8715       case NWHILE:
8716       case NUNTIL:
8717             calcsize(n->nbinary.ch2);
8718             calcsize(n->nbinary.ch1);
8719             break;
8720       case NCMD:
8721             calcsize(n->ncmd.redirect);
8722             calcsize(n->ncmd.args);
8723             calcsize(n->ncmd.assign);
8724             break;
8725       case NPIPE:
8726             sizenodelist(n->npipe.cmdlist);
8727             break;
8728       case NREDIR:
8729       case NBACKGND:
8730       case NSUBSHELL:
8731             calcsize(n->nredir.redirect);
8732             calcsize(n->nredir.n);
8733             break;
8734       case NIF:
8735             calcsize(n->nif.elsepart);
8736             calcsize(n->nif.ifpart);
8737             calcsize(n->nif.test);
8738             break;
8739       case NFOR:
8740             funcstringsize += strlen(n->nfor.var) + 1;
8741             calcsize(n->nfor.body);
8742             calcsize(n->nfor.args);
8743             break;
8744       case NCASE:
8745             calcsize(n->ncase.cases);
8746             calcsize(n->ncase.expr);
8747             break;
8748       case NCLIST:
8749             calcsize(n->nclist.body);
8750             calcsize(n->nclist.pattern);
8751             calcsize(n->nclist.next);
8752             break;
8753       case NDEFUN:
8754       case NARG:
8755             sizenodelist(n->narg.backquote);
8756             funcstringsize += strlen(n->narg.text) + 1;
8757             calcsize(n->narg.next);
8758             break;
8759       case NTO:
8760       case NFROM:
8761       case NFROMTO:
8762       case NAPPEND:
8763       case NTOOV:
8764             calcsize(n->nfile.fname);
8765             calcsize(n->nfile.next);
8766             break;
8767       case NTOFD:
8768       case NFROMFD:
8769             calcsize(n->ndup.vname);
8770             calcsize(n->ndup.next);
8771             break;
8772       case NHERE:
8773       case NXHERE:
8774             calcsize(n->nhere.doc);
8775             calcsize(n->nhere.next);
8776             break;
8777       case NNOT:
8778             calcsize(n->nnot.com);
8779             break;
8780       };
8781 }
8782 #endif /* CALCSIZE_TABLE */
8783
8784 static void
8785 sizenodelist(const struct nodelist *lp)
8786 {
8787         while (lp) {
8788                 funcblocksize += ALIGN(sizeof(struct nodelist));
8789                 calcsize(lp->n);
8790                 lp = lp->next;
8791         }
8792 }
8793
8794
8795 static struct nodelist *
8796 copynodelist(const struct nodelist *lp)
8797 {
8798         struct nodelist *start;
8799         struct nodelist **lpp;
8800
8801         lpp = &start;
8802         while (lp) {
8803                 *lpp = funcblock;
8804                 funcblock = (char *) funcblock + ALIGN(sizeof(struct nodelist));
8805                 (*lpp)->n = copynode(lp->n);
8806                 lp = lp->next;
8807                 lpp = &(*lpp)->next;
8808         }
8809         *lpp = NULL;
8810         return start;
8811 }
8812
8813
8814 static char *
8815 nodexstrdup(const char *s)
8816 {
8817         const char *p = s;
8818         char *q = funcstring;
8819         char   *rtn = funcstring;
8820
8821         while ((*q++ = *p++) != '\0')
8822                 continue;
8823         funcstring = q;
8824         return rtn;
8825 }
8826
8827 #ifdef CONFIG_ASH_GETOPTS
8828 static int getopts (char *, char *, char **, int *, int *);
8829 #endif
8830
8831
8832 /*
8833  * Process the shell command line arguments.
8834  */
8835
8836 static void
8837 procargs(int argc, char **argv)
8838 {
8839         int i;
8840
8841         argptr = argv;
8842         if (argc > 0)
8843                 argptr++;
8844         for (i = 0; i < NOPTS; i++)
8845                 optent_val(i) = 2;
8846         options(1);
8847         if (*argptr == NULL && minusc == NULL)
8848                 sflag = 1;
8849         if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
8850                 iflag = 1;
8851         if (mflag == 2)
8852                 mflag = iflag;
8853         for (i = 0; i < NOPTS; i++)
8854                 if (optent_val(i) == 2)
8855                         optent_val(i) = 0;
8856         arg0 = argv[0];
8857         if (sflag == 0 && minusc == NULL) {
8858                 commandname = argv[0];
8859                 arg0 = *argptr++;
8860                 setinputfile(arg0, 0);
8861                 commandname = arg0;
8862         }
8863         /* POSIX 1003.2: first arg after -c cmd is $0, remainder $1... */
8864         if (argptr && minusc && *argptr)
8865                 arg0 = *argptr++;
8866
8867         shellparam.p = argptr;
8868         shellparam.optind = 1;
8869         shellparam.optoff = -1;
8870         /* assert(shellparam.malloc == 0 && shellparam.nparam == 0); */
8871         while (*argptr) {
8872                 shellparam.nparam++;
8873                 argptr++;
8874         }
8875         optschanged();
8876 }
8877
8878
8879
8880 /*
8881  * Process shell options.  The global variable argptr contains a pointer
8882  * to the argument list; we advance it past the options.
8883  */
8884
8885 static inline void
8886 minus_o(const char *name, int val)
8887 {
8888         int i;
8889
8890         if (name == NULL) {
8891                 out1str("Current option settings\n");
8892                 for (i = 0; i < NOPTS; i++)
8893                         printf("%-16s%s\n", optent_name(optlist[i]),
8894                                 optent_val(i) ? "on" : "off");
8895         } else {
8896                 for (i = 0; i < NOPTS; i++)
8897                         if (equal(name, optent_name(optlist[i]))) {
8898                                 setoption(optent_letter(optlist[i]), val);
8899                                 return;
8900                         }
8901                 error("Illegal option -o %s", name);
8902         }
8903 }
8904
8905
8906 static void
8907 options(int cmdline)
8908 {
8909         char *p;
8910         int val;
8911         int c;
8912
8913         if (cmdline)
8914                 minusc = NULL;
8915         while ((p = *argptr) != NULL) {
8916                 argptr++;
8917                 if ((c = *p++) == '-') {
8918                         val = 1;
8919                         if (p[0] == '\0' || (p[0] == '-' && p[1] == '\0')) {
8920                                 if (!cmdline) {
8921                                         /* "-" means turn off -x and -v */
8922                                         if (p[0] == '\0')
8923                                                 xflag = vflag = 0;
8924                                         /* "--" means reset params */
8925                                         else if (*argptr == NULL)
8926                                                 setparam(argptr);
8927                                 }
8928                                 break;    /* "-" or  "--" terminates options */
8929                         }
8930                 } else if (c == '+') {
8931                         val = 0;
8932                 } else {
8933                         argptr--;
8934                         break;
8935                 }
8936                 while ((c = *p++) != '\0') {
8937                         if (c == 'c' && cmdline) {
8938                                 char *q;
8939 #ifdef NOHACK   /* removing this code allows sh -ce 'foo' for compat */
8940                                 if (*p == '\0')
8941 #endif
8942                                         q = *argptr++;
8943                                 if (q == NULL || minusc != NULL)
8944                                         error("Bad -c option");
8945                                 minusc = q;
8946 #ifdef NOHACK
8947                                 break;
8948 #endif
8949                         } else if (c == 'o') {
8950                                 minus_o(*argptr, val);
8951                                 if (*argptr)
8952                                         argptr++;
8953                         } else {
8954                                 setoption(c, val);
8955                         }
8956                 }
8957         }
8958 }
8959
8960
8961 static void
8962 setoption(int flag, int val)
8963 {
8964         int i;
8965
8966         for (i = 0; i < NOPTS; i++)
8967                 if (optent_letter(optlist[i]) == flag) {
8968                         optent_val(i) = val;
8969                         if (val) {
8970                                 /* #%$ hack for ksh semantics */
8971                                 if (flag == 'V')
8972                                         Eflag = 0;
8973                                 else if (flag == 'E')
8974                                         Vflag = 0;
8975                         }
8976                         return;
8977                 }
8978         error("Illegal option -%c", flag);
8979         /* NOTREACHED */
8980 }
8981
8982
8983
8984 /*
8985  * Set the shell parameters.
8986  */
8987
8988 static void
8989 setparam(char **argv)
8990 {
8991         char **newparam;
8992         char **ap;
8993         int nparam;
8994
8995         for (nparam = 0 ; argv[nparam] ; nparam++);
8996         ap = newparam = xmalloc((nparam + 1) * sizeof *ap);
8997         while (*argv) {
8998                 *ap++ = xstrdup(*argv++);
8999         }
9000         *ap = NULL;
9001         freeparam(&shellparam);
9002         shellparam.malloc = 1;
9003         shellparam.nparam = nparam;
9004         shellparam.p = newparam;
9005         shellparam.optind = 1;
9006         shellparam.optoff = -1;
9007 }
9008
9009
9010 /*
9011  * Free the list of positional parameters.
9012  */
9013
9014 static void
9015 freeparam(volatile struct shparam *param)
9016 {
9017         char **ap;
9018
9019         if (param->malloc) {
9020                 for (ap = param->p ; *ap ; ap++)
9021                         ckfree(*ap);
9022                 ckfree(param->p);
9023         }
9024 }
9025
9026
9027
9028 /*
9029  * The shift builtin command.
9030  */
9031
9032 static int
9033 shiftcmd(int argc, char **argv)
9034 {
9035         int n;
9036         char **ap1, **ap2;
9037
9038         n = 1;
9039         if (argc > 1)
9040                 n = number(argv[1]);
9041         if (n > shellparam.nparam)
9042                 error("can't shift that many");
9043         INTOFF;
9044         shellparam.nparam -= n;
9045         for (ap1 = shellparam.p ; --n >= 0 ; ap1++) {
9046                 if (shellparam.malloc)
9047                         ckfree(*ap1);
9048         }
9049         ap2 = shellparam.p;
9050         while ((*ap2++ = *ap1++) != NULL);
9051         shellparam.optind = 1;
9052         shellparam.optoff = -1;
9053         INTON;
9054         return 0;
9055 }
9056
9057
9058
9059 /*
9060  * The set command builtin.
9061  */
9062
9063 static int
9064 setcmd(int argc, char **argv)
9065 {
9066         if (argc == 1)
9067                 return showvarscmd(argc, argv);
9068         INTOFF;
9069         options(0);
9070         optschanged();
9071         if (*argptr != NULL) {
9072                 setparam(argptr);
9073         }
9074         INTON;
9075         return 0;
9076 }
9077
9078
9079 static void
9080 getoptsreset(const char *value)
9081 {
9082         shellparam.optind = number(value);
9083         shellparam.optoff = -1;
9084 }
9085
9086 #ifdef CONFIG_LOCALE_SUPPORT
9087 static void change_lc_all(const char *value)
9088 {
9089         if(value != 0 && *value != 0)
9090                 setlocale(LC_ALL, value);
9091 }
9092
9093 static void change_lc_ctype(const char *value)
9094 {
9095         if(value != 0 && *value != 0)
9096                 setlocale(LC_CTYPE, value);
9097 }
9098
9099 #endif
9100
9101 #ifdef CONFIG_ASH_GETOPTS
9102 /*
9103  * The getopts builtin.  Shellparam.optnext points to the next argument
9104  * to be processed.  Shellparam.optptr points to the next character to
9105  * be processed in the current argument.  If shellparam.optnext is NULL,
9106  * then it's the first time getopts has been called.
9107  */
9108
9109 static int
9110 getoptscmd(int argc, char **argv)
9111 {
9112         char **optbase;
9113
9114         if (argc < 3)
9115                 error("Usage: getopts optstring var [arg]");
9116         else if (argc == 3) {
9117                 optbase = shellparam.p;
9118                 if (shellparam.optind > shellparam.nparam + 1) {
9119                         shellparam.optind = 1;
9120                         shellparam.optoff = -1;
9121                 }
9122         }
9123         else {
9124                 optbase = &argv[3];
9125                 if (shellparam.optind > argc - 2) {
9126                         shellparam.optind = 1;
9127                         shellparam.optoff = -1;
9128                 }
9129         }
9130
9131         return getopts(argv[1], argv[2], optbase, &shellparam.optind,
9132                        &shellparam.optoff);
9133 }
9134
9135 /*
9136  * Safe version of setvar, returns 1 on success 0 on failure.
9137  */
9138
9139 static int
9140 setvarsafe(const char *name, const char *val, int flags)
9141 {
9142         struct jmploc jmploc;
9143         struct jmploc *volatile savehandler = handler;
9144         int err = 0;
9145 #ifdef __GNUC__
9146         (void) &err;
9147 #endif
9148
9149         if (setjmp(jmploc.loc))
9150                 err = 1;
9151         else {
9152                 handler = &jmploc;
9153                 setvar(name, val, flags);
9154         }
9155         handler = savehandler;
9156         return err;
9157 }
9158
9159 static int
9160 getopts(char *optstr, char *optvar, char **optfirst, int *myoptind, int *optoff)
9161 {
9162         char *p, *q;
9163         char c = '?';
9164         int done = 0;
9165         int err = 0;
9166         char s[10];
9167         char **optnext = optfirst + *myoptind - 1;
9168
9169         if (*myoptind <= 1 || *optoff < 0 || !(*(optnext - 1)) ||
9170             strlen(*(optnext - 1)) < *optoff)
9171                 p = NULL;
9172         else
9173                 p = *(optnext - 1) + *optoff;
9174         if (p == NULL || *p == '\0') {
9175                 /* Current word is done, advance */
9176                 if (optnext == NULL)
9177                         return 1;
9178                 p = *optnext;
9179                 if (p == NULL || *p != '-' || *++p == '\0') {
9180 atend:
9181                         *myoptind = optnext - optfirst + 1;
9182                         p = NULL;
9183                         done = 1;
9184                         goto out;
9185                 }
9186                 optnext++;
9187                 if (p[0] == '-' && p[1] == '\0')        /* check for "--" */
9188                         goto atend;
9189         }
9190
9191         c = *p++;
9192         for (q = optstr; *q != c; ) {
9193                 if (*q == '\0') {
9194                         if (optstr[0] == ':') {
9195                                 s[0] = c;
9196                                 s[1] = '\0';
9197                                 err |= setvarsafe("OPTARG", s, 0);
9198                         }
9199                         else {
9200                                 out2fmt("Illegal option -%c\n", c);
9201                                 (void) unsetvar("OPTARG");
9202                         }
9203                         c = '?';
9204                         goto bad;
9205                 }
9206                 if (*++q == ':')
9207                         q++;
9208         }
9209
9210         if (*++q == ':') {
9211                 if (*p == '\0' && (p = *optnext) == NULL) {
9212                         if (optstr[0] == ':') {
9213                                 s[0] = c;
9214                                 s[1] = '\0';
9215                                 err |= setvarsafe("OPTARG", s, 0);
9216                                 c = ':';
9217                         }
9218                         else {
9219                                 out2fmt("No arg for -%c option\n", c);
9220                                 (void) unsetvar("OPTARG");
9221                                 c = '?';
9222                         }
9223                         goto bad;
9224                 }
9225
9226                 if (p == *optnext)
9227                         optnext++;
9228                 setvarsafe("OPTARG", p, 0);
9229                 p = NULL;
9230         }
9231         else
9232                 setvarsafe("OPTARG", "", 0);
9233         *myoptind = optnext - optfirst + 1;
9234         goto out;
9235
9236 bad:
9237         *myoptind = 1;
9238         p = NULL;
9239 out:
9240         *optoff = p ? p - *(optnext - 1) : -1;
9241         snprintf(s, sizeof(s), "%d", *myoptind);
9242         err |= setvarsafe("OPTIND", s, VNOFUNC);
9243         s[0] = c;
9244         s[1] = '\0';
9245         err |= setvarsafe(optvar, s, 0);
9246         if (err) {
9247                 *myoptind = 1;
9248                 *optoff = -1;
9249                 exraise(EXERROR);
9250         }
9251         return done;
9252 }
9253 #endif
9254
9255 /*
9256  * XXX - should get rid of.  have all builtins use getopt(3).  the
9257  * library getopt must have the BSD extension static variable "optreset"
9258  * otherwise it can't be used within the shell safely.
9259  *
9260  * Standard option processing (a la getopt) for builtin routines.  The
9261  * only argument that is passed to nextopt is the option string; the
9262  * other arguments are unnecessary.  It return the character, or '\0' on
9263  * end of input.
9264  */
9265
9266 static int
9267 nextopt(const char *optstring)
9268 {
9269         char *p;
9270         const char *q;
9271         char c;
9272
9273         if ((p = optptr) == NULL || *p == '\0') {
9274                 p = *argptr;
9275                 if (p == NULL || *p != '-' || *++p == '\0')
9276                         return '\0';
9277                 argptr++;
9278                 if (p[0] == '-' && p[1] == '\0')        /* check for "--" */
9279                         return '\0';
9280         }
9281         c = *p++;
9282         for (q = optstring ; *q != c ; ) {
9283                 if (*q == '\0')
9284                         error("Illegal option -%c", c);
9285                 if (*++q == ':')
9286                         q++;
9287         }
9288         if (*++q == ':') {
9289                 if (*p == '\0' && (p = *argptr++) == NULL)
9290                         error("No arg for -%c option", c);
9291                 optionarg = p;
9292                 p = NULL;
9293         }
9294         optptr = p;
9295         return c;
9296 }
9297
9298 static void
9299 flushall() {
9300         INTOFF;
9301         fflush(stdout);
9302         INTON;
9303 }
9304
9305
9306 static void
9307 out2fmt(const char *fmt, ...)
9308 {
9309         va_list ap;
9310         va_start(ap, fmt);
9311         vfprintf(stderr, fmt, ap);
9312         va_end(ap);
9313 }
9314
9315 /*
9316  * Version of write which resumes after a signal is caught.
9317  */
9318
9319 static int
9320 xwrite(int fd, const char *buf, int nbytes)
9321 {
9322         int ntry;
9323         int i;
9324         int n;
9325
9326         n = nbytes;
9327         ntry = 0;
9328         for (;;) {
9329                 i = write(fd, buf, n);
9330                 if (i > 0) {
9331                         if ((n -= i) <= 0)
9332                                 return nbytes;
9333                         buf += i;
9334                         ntry = 0;
9335                 } else if (i == 0) {
9336                         if (++ntry > 10)
9337                                 return nbytes - n;
9338                 } else if (errno != EINTR) {
9339                         return -1;
9340                 }
9341         }
9342 }
9343
9344
9345 /*
9346  * Shell command parser.
9347  */
9348
9349 #define EOFMARKLEN 79
9350
9351
9352
9353 struct heredoc {
9354         struct heredoc *next;   /* next here document in list */
9355         union node *here;               /* redirection node */
9356         char *eofmark;          /* string indicating end of input */
9357         int striptabs;          /* if set, strip leading tabs */
9358 };
9359
9360 static struct heredoc *heredoclist;     /* list of here documents to read */
9361 static int parsebackquote;              /* nonzero if we are inside backquotes */
9362 static int doprompt;                    /* if set, prompt the user */
9363 static int needprompt;                  /* true if interactive and at start of line */
9364 static int lasttoken;                   /* last token read */
9365
9366 static char *wordtext;                  /* text of last word returned by readtoken */
9367
9368 static struct nodelist *backquotelist;
9369 static union node *redirnode;
9370 static struct heredoc *heredoc;
9371 static int quoteflag;                   /* set if (part of) last token was quoted */
9372 static int startlinno;                  /* line # where last token started */
9373
9374
9375 static union node *list (int);
9376 static union node *andor (void);
9377 static union node *pipeline (void);
9378 static union node *command (void);
9379 static union node *simplecmd(union node **rpp, union node *redir);
9380 static void parsefname (void);
9381 static void parseheredoc (void);
9382 static char peektoken (void);
9383 static int readtoken (void);
9384 static int xxreadtoken (void);
9385 static int readtoken1 (int, int, const char *, int);
9386 static int noexpand (char *);
9387 static void synexpect (int) __attribute__((noreturn));
9388 static void synerror (const char *) __attribute__((noreturn));
9389 static void setprompt (int);
9390
9391
9392 /*
9393  * Read and parse a command.  Returns NEOF on end of file.  (NULL is a
9394  * valid parse tree indicating a blank line.)
9395  */
9396
9397 static union node *
9398 parsecmd(int interact)
9399 {
9400         int t;
9401
9402         tokpushback = 0;
9403         doprompt = interact;
9404         if (doprompt)
9405                 setprompt(1);
9406         else
9407                 setprompt(0);
9408         needprompt = 0;
9409         t = readtoken();
9410         if (t == TEOF)
9411                 return NEOF;
9412         if (t == TNL)
9413                 return NULL;
9414         tokpushback++;
9415         return list(1);
9416 }
9417
9418
9419 static union node *
9420 list(int nlflag)
9421 {
9422         union node *n1, *n2, *n3;
9423         int tok;
9424
9425         checkkwd = 2;
9426         if (nlflag == 0 && peektoken())
9427                 return NULL;
9428         n1 = NULL;
9429         for (;;) {
9430                 n2 = andor();
9431                 tok = readtoken();
9432                 if (tok == TBACKGND) {
9433                         if (n2->type == NCMD || n2->type == NPIPE) {
9434                                 n2->ncmd.backgnd = 1;
9435                         } else if (n2->type == NREDIR) {
9436                                 n2->type = NBACKGND;
9437                         } else {
9438                                 n3 = (union node *)stalloc(sizeof (struct nredir));
9439                                 n3->type = NBACKGND;
9440                                 n3->nredir.n = n2;
9441                                 n3->nredir.redirect = NULL;
9442                                 n2 = n3;
9443                         }
9444                 }
9445                 if (n1 == NULL) {
9446                         n1 = n2;
9447                 }
9448                 else {
9449                         n3 = (union node *)stalloc(sizeof (struct nbinary));
9450                         n3->type = NSEMI;
9451                         n3->nbinary.ch1 = n1;
9452                         n3->nbinary.ch2 = n2;
9453                         n1 = n3;
9454                 }
9455                 switch (tok) {
9456                 case TBACKGND:
9457                 case TSEMI:
9458                         tok = readtoken();
9459                         /* fall through */
9460                 case TNL:
9461                         if (tok == TNL) {
9462                                 parseheredoc();
9463                                 if (nlflag)
9464                                         return n1;
9465                         } else {
9466                                 tokpushback++;
9467                         }
9468                         checkkwd = 2;
9469                         if (peektoken())
9470                                 return n1;
9471                         break;
9472                 case TEOF:
9473                         if (heredoclist)
9474                                 parseheredoc();
9475                         else
9476                                 pungetc();              /* push back EOF on input */
9477                         return n1;
9478                 default:
9479                         if (nlflag)
9480                                 synexpect(-1);
9481                         tokpushback++;
9482                         return n1;
9483                 }
9484         }
9485 }
9486
9487
9488
9489 static union node *
9490 andor() {
9491         union node *n1, *n2, *n3;
9492         int t;
9493
9494         checkkwd = 1;
9495         n1 = pipeline();
9496         for (;;) {
9497                 if ((t = readtoken()) == TAND) {
9498                         t = NAND;
9499                 } else if (t == TOR) {
9500                         t = NOR;
9501                 } else {
9502                         tokpushback++;
9503                         return n1;
9504                 }
9505                 checkkwd = 2;
9506                 n2 = pipeline();
9507                 n3 = (union node *)stalloc(sizeof (struct nbinary));
9508                 n3->type = t;
9509                 n3->nbinary.ch1 = n1;
9510                 n3->nbinary.ch2 = n2;
9511                 n1 = n3;
9512         }
9513 }
9514
9515
9516
9517 static union node *
9518 pipeline() {
9519         union node *n1, *n2, *pipenode;
9520         struct nodelist *lp, *prev;
9521         int negate;
9522
9523         negate = 0;
9524         TRACE(("pipeline: entered\n"));
9525         if (readtoken() == TNOT) {
9526                 negate = !negate;
9527                 checkkwd = 1;
9528         } else
9529                 tokpushback++;
9530         n1 = command();
9531         if (readtoken() == TPIPE) {
9532                 pipenode = (union node *)stalloc(sizeof (struct npipe));
9533                 pipenode->type = NPIPE;
9534                 pipenode->npipe.backgnd = 0;
9535                 lp = (struct nodelist *)stalloc(sizeof (struct nodelist));
9536                 pipenode->npipe.cmdlist = lp;
9537                 lp->n = n1;
9538                 do {
9539                         prev = lp;
9540                         lp = (struct nodelist *)stalloc(sizeof (struct nodelist));
9541                         checkkwd = 2;
9542                         lp->n = command();
9543                         prev->next = lp;
9544                 } while (readtoken() == TPIPE);
9545                 lp->next = NULL;
9546                 n1 = pipenode;
9547         }
9548         tokpushback++;
9549         if (negate) {
9550                 n2 = (union node *)stalloc(sizeof (struct nnot));
9551                 n2->type = NNOT;
9552                 n2->nnot.com = n1;
9553                 return n2;
9554         } else
9555                 return n1;
9556 }
9557
9558
9559
9560 static union node *
9561 command(void) {
9562         union node *n1, *n2;
9563         union node *ap, **app;
9564         union node *cp, **cpp;
9565         union node *redir, **rpp;
9566         int t;
9567
9568         redir = NULL;
9569         n1 = NULL;
9570         rpp = &redir;
9571
9572         /* Check for redirection which may precede command */
9573         while (readtoken() == TREDIR) {
9574                 *rpp = n2 = redirnode;
9575                 rpp = &n2->nfile.next;
9576                 parsefname();
9577         }
9578         tokpushback++;
9579
9580         switch (readtoken()) {
9581         case TIF:
9582                 n1 = (union node *)stalloc(sizeof (struct nif));
9583                 n1->type = NIF;
9584                 n1->nif.test = list(0);
9585                 if (readtoken() != TTHEN)
9586                         synexpect(TTHEN);
9587                 n1->nif.ifpart = list(0);
9588                 n2 = n1;
9589                 while (readtoken() == TELIF) {
9590                         n2->nif.elsepart = (union node *)stalloc(sizeof (struct nif));
9591                         n2 = n2->nif.elsepart;
9592                         n2->type = NIF;
9593                         n2->nif.test = list(0);
9594                         if (readtoken() != TTHEN)
9595                                 synexpect(TTHEN);
9596                         n2->nif.ifpart = list(0);
9597                 }
9598                 if (lasttoken == TELSE)
9599                         n2->nif.elsepart = list(0);
9600                 else {
9601                         n2->nif.elsepart = NULL;
9602                         tokpushback++;
9603                 }
9604                 if (readtoken() != TFI)
9605                         synexpect(TFI);
9606                 checkkwd = 1;
9607                 break;
9608         case TWHILE:
9609         case TUNTIL: {
9610                 int got;
9611                 n1 = (union node *)stalloc(sizeof (struct nbinary));
9612                 n1->type = (lasttoken == TWHILE)? NWHILE : NUNTIL;
9613                 n1->nbinary.ch1 = list(0);
9614                 if ((got=readtoken()) != TDO) {
9615 TRACE(("expecting DO got %s %s\n", tokname(got), got == TWORD ? wordtext : ""));
9616                         synexpect(TDO);
9617                 }
9618                 n1->nbinary.ch2 = list(0);
9619                 if (readtoken() != TDONE)
9620                         synexpect(TDONE);
9621                 checkkwd = 1;
9622                 break;
9623         }
9624         case TFOR:
9625                 if (readtoken() != TWORD || quoteflag || ! goodname(wordtext))
9626                         synerror("Bad for loop variable");
9627                 n1 = (union node *)stalloc(sizeof (struct nfor));
9628                 n1->type = NFOR;
9629                 n1->nfor.var = wordtext;
9630                 checkkwd = 1;
9631                 if (readtoken() == TIN) {
9632                         app = &ap;
9633                         while (readtoken() == TWORD) {
9634                                 n2 = (union node *)stalloc(sizeof (struct narg));
9635                                 n2->type = NARG;
9636                                 n2->narg.text = wordtext;
9637                                 n2->narg.backquote = backquotelist;
9638                                 *app = n2;
9639                                 app = &n2->narg.next;
9640                         }
9641                         *app = NULL;
9642                         n1->nfor.args = ap;
9643                         if (lasttoken != TNL && lasttoken != TSEMI)
9644                                 synexpect(-1);
9645                 } else {
9646                         static char argvars[5] = {CTLVAR, VSNORMAL|VSQUOTE,
9647                                                                    '@', '=', '\0'};
9648                         n2 = (union node *)stalloc(sizeof (struct narg));
9649                         n2->type = NARG;
9650                         n2->narg.text = argvars;
9651                         n2->narg.backquote = NULL;
9652                         n2->narg.next = NULL;
9653                         n1->nfor.args = n2;
9654                         /*
9655                          * Newline or semicolon here is optional (but note
9656                          * that the original Bourne shell only allowed NL).
9657                          */
9658                         if (lasttoken != TNL && lasttoken != TSEMI)
9659                                 tokpushback++;
9660                 }
9661                 checkkwd = 2;
9662                 if (readtoken() != TDO)
9663                         synexpect(TDO);
9664                 n1->nfor.body = list(0);
9665                 if (readtoken() != TDONE)
9666                         synexpect(TDONE);
9667                 checkkwd = 1;
9668                 break;
9669         case TCASE:
9670                 n1 = (union node *)stalloc(sizeof (struct ncase));
9671                 n1->type = NCASE;
9672                 if (readtoken() != TWORD)
9673                         synexpect(TWORD);
9674                 n1->ncase.expr = n2 = (union node *)stalloc(sizeof (struct narg));
9675                 n2->type = NARG;
9676                 n2->narg.text = wordtext;
9677                 n2->narg.backquote = backquotelist;
9678                 n2->narg.next = NULL;
9679                 do {
9680                         checkkwd = 1;
9681                 } while (readtoken() == TNL);
9682                 if (lasttoken != TIN)
9683                         synerror("expecting \"in\"");
9684                 cpp = &n1->ncase.cases;
9685                 checkkwd = 2, readtoken();
9686                 do {
9687                         if (lasttoken == TLP)
9688                                 readtoken();
9689                         *cpp = cp = (union node *)stalloc(sizeof (struct nclist));
9690                         cp->type = NCLIST;
9691                         app = &cp->nclist.pattern;
9692                         for (;;) {
9693                                 *app = ap = (union node *)stalloc(sizeof (struct narg));
9694                                 ap->type = NARG;
9695                                 ap->narg.text = wordtext;
9696                                 ap->narg.backquote = backquotelist;
9697                                 if (checkkwd = 2, readtoken() != TPIPE)
9698                                         break;
9699                                 app = &ap->narg.next;
9700                                 readtoken();
9701                         }
9702                         ap->narg.next = NULL;
9703                         if (lasttoken != TRP)
9704                                 synexpect(TRP);
9705                         cp->nclist.body = list(0);
9706
9707                         checkkwd = 2;
9708                         if ((t = readtoken()) != TESAC) {
9709                                 if (t != TENDCASE)
9710                                         synexpect(TENDCASE);
9711                                 else
9712                                         checkkwd = 2, readtoken();
9713                         }
9714                         cpp = &cp->nclist.next;
9715                 } while(lasttoken != TESAC);
9716                 *cpp = NULL;
9717                 checkkwd = 1;
9718                 break;
9719         case TLP:
9720                 n1 = (union node *)stalloc(sizeof (struct nredir));
9721                 n1->type = NSUBSHELL;
9722                 n1->nredir.n = list(0);
9723                 n1->nredir.redirect = NULL;
9724                 if (readtoken() != TRP)
9725                         synexpect(TRP);
9726                 checkkwd = 1;
9727                 break;
9728         case TBEGIN:
9729                 n1 = list(0);
9730                 if (readtoken() != TEND)
9731                         synexpect(TEND);
9732                 checkkwd = 1;
9733                 break;
9734         /* Handle an empty command like other simple commands.  */
9735         case TSEMI:
9736         case TAND:
9737         case TOR:
9738         case TNL:
9739         case TEOF:
9740         case TRP:
9741         case TBACKGND:
9742                 /*
9743                  * An empty command before a ; doesn't make much sense, and
9744                  * should certainly be disallowed in the case of `if ;'.
9745                  */
9746                 if (!redir)
9747                         synexpect(-1);
9748         case TWORD:
9749                 tokpushback++;
9750                 n1 = simplecmd(rpp, redir);
9751                 return n1;
9752         default:
9753                 synexpect(-1);
9754                 /* NOTREACHED */
9755         }
9756
9757         /* Now check for redirection which may follow command */
9758         while (readtoken() == TREDIR) {
9759                 *rpp = n2 = redirnode;
9760                 rpp = &n2->nfile.next;
9761                 parsefname();
9762         }
9763         tokpushback++;
9764         *rpp = NULL;
9765         if (redir) {
9766                 if (n1->type != NSUBSHELL) {
9767                         n2 = (union node *)stalloc(sizeof (struct nredir));
9768                         n2->type = NREDIR;
9769                         n2->nredir.n = n1;
9770                         n1 = n2;
9771                 }
9772                 n1->nredir.redirect = redir;
9773         }
9774
9775         return n1;
9776 }
9777
9778
9779 static union node *
9780 simplecmd(union node **rpp, union node *redir) {
9781         union node *args, **app;
9782         union node *n = NULL;
9783         union node *vars, **vpp;
9784         union node **orig_rpp;
9785
9786         args = NULL;
9787         app = &args;
9788         vars = NULL;
9789         vpp = &vars;
9790
9791         /* If we don't have any redirections already, then we must reset
9792           rpp to be the address of the local redir variable.  */
9793         if (redir == 0)
9794         rpp = &redir;
9795         /* We save the incoming value, because we need this for shell
9796           functions.  There can not be a redirect or an argument between
9797           the function name and the open parenthesis.  */
9798         orig_rpp = rpp;
9799
9800         checkalias = 2;
9801         for (;;) {
9802                 switch (readtoken()) {
9803                 case TWORD:
9804                 case TASSIGN:
9805                         n = (union node *)stalloc(sizeof (struct narg));
9806                         n->type = NARG;
9807                         n->narg.text = wordtext;
9808                         n->narg.backquote = backquotelist;
9809                         if (lasttoken == TWORD) {
9810                                 *app = n;
9811                                 app = &n->narg.next;
9812                         } else {
9813                                 *vpp = n;
9814                                 vpp = &n->narg.next;
9815                         }
9816                         break;
9817                 case TREDIR:
9818                         *rpp = n = redirnode;
9819                         rpp = &n->nfile.next;
9820                         parsefname();   /* read name of redirection file */
9821                         break;
9822                 case TLP:
9823                         if (
9824                                 args && app == &args->narg.next &&
9825                                 !vars && rpp == orig_rpp
9826                         ) {
9827                                 /* We have a function */
9828                                 if (readtoken() != TRP)
9829                                         synexpect(TRP);
9830                                 n->type = NDEFUN;
9831                                 checkkwd = 2;
9832                                 n->narg.next = command();
9833                                 return n;
9834                         }
9835                         /* fall through */
9836                 default:
9837                         tokpushback++;
9838                         goto out;
9839                 }
9840         }
9841 out:
9842         *app = NULL;
9843         *vpp = NULL;
9844         *rpp = NULL;
9845         n = (union node *)stalloc(sizeof (struct ncmd));
9846         n->type = NCMD;
9847         n->ncmd.backgnd = 0;
9848         n->ncmd.args = args;
9849         n->ncmd.assign = vars;
9850         n->ncmd.redirect = redir;
9851         return n;
9852 }
9853
9854 static union node *
9855 makename(void) {
9856         union node *n;
9857
9858         n = (union node *)stalloc(sizeof (struct narg));
9859         n->type = NARG;
9860         n->narg.next = NULL;
9861         n->narg.text = wordtext;
9862         n->narg.backquote = backquotelist;
9863         return n;
9864 }
9865
9866 static void fixredir(union node *n, const char *text, int err)
9867 {
9868         TRACE(("Fix redir %s %d\n", text, err));
9869         if (!err)
9870                 n->ndup.vname = NULL;
9871
9872         if (is_digit(text[0]) && text[1] == '\0')
9873                 n->ndup.dupfd = digit_val(text[0]);
9874         else if (text[0] == '-' && text[1] == '\0')
9875                 n->ndup.dupfd = -1;
9876         else {
9877
9878                 if (err)
9879                         synerror("Bad fd number");
9880                 else
9881                         n->ndup.vname = makename();
9882         }
9883 }
9884
9885
9886 static void
9887 parsefname(void) {
9888         union node *n = redirnode;
9889
9890         if (readtoken() != TWORD)
9891                 synexpect(-1);
9892         if (n->type == NHERE) {
9893                 struct heredoc *here = heredoc;
9894                 struct heredoc *p;
9895                 int i;
9896
9897                 if (quoteflag == 0)
9898                         n->type = NXHERE;
9899                 TRACE(("Here document %d\n", n->type));
9900                 if (here->striptabs) {
9901                         while (*wordtext == '\t')
9902                                 wordtext++;
9903                 }
9904                 if (! noexpand(wordtext) || (i = strlen(wordtext)) == 0 || i > EOFMARKLEN)
9905                         synerror("Illegal eof marker for << redirection");
9906                 rmescapes(wordtext);
9907                 here->eofmark = wordtext;
9908                 here->next = NULL;
9909                 if (heredoclist == NULL)
9910                         heredoclist = here;
9911                 else {
9912                         for (p = heredoclist ; p->next ; p = p->next);
9913                         p->next = here;
9914                 }
9915         } else if (n->type == NTOFD || n->type == NFROMFD) {
9916                 fixredir(n, wordtext, 0);
9917         } else {
9918                 n->nfile.fname = makename();
9919         }
9920 }
9921
9922
9923 /*
9924  * Input any here documents.
9925  */
9926
9927 static void
9928 parseheredoc() {
9929         struct heredoc *here;
9930         union node *n;
9931
9932         while (heredoclist) {
9933                 here = heredoclist;
9934                 heredoclist = here->next;
9935                 if (needprompt) {
9936                         setprompt(2);
9937                         needprompt = 0;
9938                 }
9939                 readtoken1(pgetc(), here->here->type == NHERE? SQSYNTAX : DQSYNTAX,
9940                                 here->eofmark, here->striptabs);
9941                 n = (union node *)stalloc(sizeof (struct narg));
9942                 n->narg.type = NARG;
9943                 n->narg.next = NULL;
9944                 n->narg.text = wordtext;
9945                 n->narg.backquote = backquotelist;
9946                 here->here->nhere.doc = n;
9947         }
9948 }
9949
9950 static char
9951 peektoken() {
9952         int t;
9953
9954         t = readtoken();
9955         tokpushback++;
9956         return tokname_array[t][0];
9957 }
9958
9959 static int
9960 readtoken() {
9961         int t;
9962
9963 #ifdef CONFIG_ASH_ALIAS
9964         int savecheckalias = checkalias;
9965         int savecheckkwd = checkkwd;
9966         struct alias *ap;
9967 #endif
9968
9969 #ifdef DEBUG
9970         int alreadyseen = tokpushback;
9971 #endif
9972
9973 #ifdef CONFIG_ASH_ALIAS
9974 top:
9975 #endif
9976
9977         t = xxreadtoken();
9978
9979 #ifdef CONFIG_ASH_ALIAS
9980         checkalias = savecheckalias;
9981 #endif
9982
9983         if (checkkwd) {
9984                 /*
9985                  * eat newlines
9986                  */
9987                 if (checkkwd == 2) {
9988                         checkkwd = 0;
9989                         while (t == TNL) {
9990                                 parseheredoc();
9991                                 t = xxreadtoken();
9992                         }
9993                 }
9994                 checkkwd = 0;
9995                 /*
9996                  * check for keywords
9997                  */
9998                 if (t == TWORD && !quoteflag)
9999                 {
10000                         const char *const *pp;
10001
10002                         if ((pp = findkwd(wordtext))) {
10003                                 lasttoken = t = pp - tokname_array;
10004                                 TRACE(("keyword %s recognized\n", tokname(t)));
10005                                 goto out;
10006                         }
10007                 }
10008         }
10009
10010
10011         if (t != TWORD) {
10012                 if (t != TREDIR) {
10013                         checkalias = 0;
10014                 }
10015         } else if (checkalias == 2 && isassignment(wordtext)) {
10016                 lasttoken = t = TASSIGN;
10017 #ifdef CONFIG_ASH_ALIAS
10018         } else if (checkalias) {
10019                 if (!quoteflag && (ap = *__lookupalias(wordtext)) != NULL && !(ap->flag & ALIASINUSE)) {
10020                         if (*ap->val) {
10021                                 pushstring(ap->val, strlen(ap->val), ap);
10022                         }
10023                         checkkwd = savecheckkwd;
10024                         goto top;
10025                 }
10026                 checkalias = 0;
10027 #endif
10028         }
10029 out:
10030 #ifdef DEBUG
10031         if (!alreadyseen)
10032             TRACE(("token %s %s\n", tokname(t), t == TWORD || t == TASSIGN ? wordtext : ""));
10033         else
10034             TRACE(("reread token %s %s\n", tokname(t), t == TWORD || t == TASSIGN ? wordtext : ""));
10035 #endif
10036         return (t);
10037 }
10038
10039
10040 /*
10041  * Read the next input token.
10042  * If the token is a word, we set backquotelist to the list of cmds in
10043  *      backquotes.  We set quoteflag to true if any part of the word was
10044  *      quoted.
10045  * If the token is TREDIR, then we set redirnode to a structure containing
10046  *      the redirection.
10047  * In all cases, the variable startlinno is set to the number of the line
10048  *      on which the token starts.
10049  *
10050  * [Change comment:  here documents and internal procedures]
10051  * [Readtoken shouldn't have any arguments.  Perhaps we should make the
10052  *  word parsing code into a separate routine.  In this case, readtoken
10053  *  doesn't need to have any internal procedures, but parseword does.
10054  *  We could also make parseoperator in essence the main routine, and
10055  *  have parseword (readtoken1?) handle both words and redirection.]
10056  */
10057
10058 #define NEW_xxreadtoken
10059 #ifdef NEW_xxreadtoken
10060
10061 static const char xxreadtoken_chars[] = "\n()&|;"; /* singles must be first! */
10062 static const char xxreadtoken_tokens[] = {
10063         TNL, TLP, TRP,                          /* only single occurrence allowed */
10064         TBACKGND, TPIPE, TSEMI,         /* if single occurrence */
10065         TEOF,                                           /* corresponds to trailing nul */
10066         TAND, TOR, TENDCASE,            /* if double occurrence */
10067 };
10068
10069 #define xxreadtoken_doubles \
10070         (sizeof(xxreadtoken_tokens) - sizeof(xxreadtoken_chars))
10071 #define xxreadtoken_singles \
10072         (sizeof(xxreadtoken_chars) - xxreadtoken_doubles - 1)
10073
10074 static int
10075 xxreadtoken() {
10076         int c;
10077
10078         if (tokpushback) {
10079                 tokpushback = 0;
10080                 return lasttoken;
10081         }
10082         if (needprompt) {
10083                 setprompt(2);
10084                 needprompt = 0;
10085         }
10086         startlinno = plinno;
10087         for (;;) {      /* until token or start of word found */
10088                 c = pgetc_macro();
10089
10090                 if ((c!=' ') && (c!='\t')
10091 #ifdef CONFIG_ASH_ALIAS
10092                         && (c!=PEOA)
10093 #endif
10094                         ) {
10095                         if (c=='#') {
10096                                 while ((c = pgetc()) != '\n' && c != PEOF);
10097                                 pungetc();
10098                         } else if (c=='\\') {
10099                                 if (pgetc() != '\n') {
10100                                         pungetc();
10101                                         goto READTOKEN1;
10102                                 }
10103                                 startlinno = ++plinno;
10104                                 setprompt(doprompt ? 2 : 0);
10105                         } else {
10106                                 const char *p
10107                                         = xxreadtoken_chars + sizeof(xxreadtoken_chars) - 1;
10108
10109                                 if (c!=PEOF) {
10110                                         if (c=='\n') {
10111                                                 plinno++;
10112                                                 needprompt = doprompt;
10113                                         }
10114
10115                                         p = strchr(xxreadtoken_chars, c);
10116                                         if (p == NULL) {
10117                                         READTOKEN1:
10118                                                 return readtoken1(c, BASESYNTAX, (char *)NULL, 0);
10119                                         }
10120                         
10121                                         if (p-xxreadtoken_chars >= xxreadtoken_singles) {
10122                                                 if (pgetc() == *p) { /* double occurrence? */
10123                                                         p += xxreadtoken_doubles + 1;
10124                                                 } else {
10125                                                         pungetc();
10126                                                 }
10127                                         }
10128                                 }
10129
10130                                 return lasttoken = xxreadtoken_tokens[p-xxreadtoken_chars];
10131                         }
10132                 }
10133         }
10134 }
10135
10136
10137 #else
10138 #define RETURN(token)   return lasttoken = token
10139
10140 static int
10141 xxreadtoken() {
10142         int c;
10143
10144         if (tokpushback) {
10145                 tokpushback = 0;
10146                 return lasttoken;
10147         }
10148         if (needprompt) {
10149                 setprompt(2);
10150                 needprompt = 0;
10151         }
10152         startlinno = plinno;
10153         for (;;) {      /* until token or start of word found */
10154                 c = pgetc_macro();
10155                 switch (c) {
10156                 case ' ': case '\t':
10157 #ifdef CONFIG_ASH_ALIAS
10158                 case PEOA:
10159 #endif
10160                         continue;
10161                 case '#':
10162                         while ((c = pgetc()) != '\n' && c != PEOF);
10163                         pungetc();
10164                         continue;
10165                 case '\\':
10166                         if (pgetc() == '\n') {
10167                                 startlinno = ++plinno;
10168                                 if (doprompt)
10169                                         setprompt(2);
10170                                 else
10171                                         setprompt(0);
10172                                 continue;
10173                         }
10174                         pungetc();
10175                         goto breakloop;
10176                 case '\n':
10177                         plinno++;
10178                         needprompt = doprompt;
10179                         RETURN(TNL);
10180                 case PEOF:
10181                         RETURN(TEOF);
10182                 case '&':
10183                         if (pgetc() == '&')
10184                                 RETURN(TAND);
10185                         pungetc();
10186                         RETURN(TBACKGND);
10187                 case '|':
10188                         if (pgetc() == '|')
10189                                 RETURN(TOR);
10190                         pungetc();
10191                         RETURN(TPIPE);
10192                 case ';':
10193                         if (pgetc() == ';')
10194                                 RETURN(TENDCASE);
10195                         pungetc();
10196                         RETURN(TSEMI);
10197                 case '(':
10198                         RETURN(TLP);
10199                 case ')':
10200                         RETURN(TRP);
10201                 default:
10202                         goto breakloop;
10203                 }
10204         }
10205 breakloop:
10206         return readtoken1(c, BASESYNTAX, (char *)NULL, 0);
10207 #undef RETURN
10208 }
10209 #endif
10210
10211 /*
10212  * If eofmark is NULL, read a word or a redirection symbol.  If eofmark
10213  * is not NULL, read a here document.  In the latter case, eofmark is the
10214  * word which marks the end of the document and striptabs is true if
10215  * leading tabs should be stripped from the document.  The argument firstc
10216  * is the first character of the input token or document.
10217  *
10218  * Because C does not have internal subroutines, I have simulated them
10219  * using goto's to implement the subroutine linkage.  The following macros
10220  * will run code that appears at the end of readtoken1.
10221  */
10222
10223 #define CHECKEND()      {goto checkend; checkend_return:;}
10224 #define PARSEREDIR()    {goto parseredir; parseredir_return:;}
10225 #define PARSESUB()      {goto parsesub; parsesub_return:;}
10226 #define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
10227 #define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
10228 #define PARSEARITH()    {goto parsearith; parsearith_return:;}
10229
10230 static int
10231 readtoken1(int firstc, int syntax, const char *eofmark, int striptabs)
10232 {
10233         int c = firstc;
10234         char *out;
10235         int len;
10236         char line[EOFMARKLEN + 1];
10237         struct nodelist *bqlist;
10238         int quotef;
10239         int dblquote;
10240         int varnest;    /* levels of variables expansion */
10241         int arinest;    /* levels of arithmetic expansion */
10242         int parenlevel; /* levels of parens in arithmetic */
10243         int dqvarnest;  /* levels of variables expansion within double quotes */
10244         int oldstyle;
10245         int prevsyntax; /* syntax before arithmetic */
10246 #if __GNUC__
10247         /* Avoid longjmp clobbering */
10248         (void) &out;
10249         (void) &quotef;
10250         (void) &dblquote;
10251         (void) &varnest;
10252         (void) &arinest;
10253         (void) &parenlevel;
10254         (void) &dqvarnest;
10255         (void) &oldstyle;
10256         (void) &prevsyntax;
10257         (void) &syntax;
10258 #endif
10259
10260         startlinno = plinno;
10261         dblquote = 0;
10262         if (syntax == DQSYNTAX)
10263                 dblquote = 1;
10264         quotef = 0;
10265         bqlist = NULL;
10266         varnest = 0;
10267         arinest = 0;
10268         parenlevel = 0;
10269         dqvarnest = 0;
10270
10271         STARTSTACKSTR(out);
10272         loop: { /* for each line, until end of word */
10273                 CHECKEND();     /* set c to PEOF if at end of here document */
10274                 for (;;) {      /* until end of line or end of word */
10275                         CHECKSTRSPACE(3, out);  /* permit 3 calls to USTPUTC */
10276                         switch(SIT(c,syntax)) {
10277                         case CNL:       /* '\n' */
10278                                 if (syntax == BASESYNTAX)
10279                                         goto endword;   /* exit outer loop */
10280                                 USTPUTC(c, out);
10281                                 plinno++;
10282                                 if (doprompt)
10283                                         setprompt(2);
10284                                 else
10285                                         setprompt(0);
10286                                 c = pgetc();
10287                                 goto loop;              /* continue outer loop */
10288                         case CWORD:
10289                                 USTPUTC(c, out);
10290                                 break;
10291                         case CCTL:
10292                                 if ((eofmark == NULL || dblquote) &&
10293                                     dqvarnest == 0)
10294                                         USTPUTC(CTLESC, out);
10295                                 USTPUTC(c, out);
10296                                 break;
10297                         case CBACK:     /* backslash */
10298                                 c = pgetc2();
10299                                 if (c == PEOF) {
10300                                         USTPUTC('\\', out);
10301                                         pungetc();
10302                                 } else if (c == '\n') {
10303                                         if (doprompt)
10304                                                 setprompt(2);
10305                                         else
10306                                                 setprompt(0);
10307                                 } else {
10308                                         if (dblquote && c != '\\' && c != '`' && c != '$'
10309                                                          && (c != '"' || eofmark != NULL))
10310                                                 USTPUTC('\\', out);
10311                                         if (SIT(c,SQSYNTAX) == CCTL)
10312                                                 USTPUTC(CTLESC, out);
10313                                         else if (eofmark == NULL)
10314                                                 USTPUTC(CTLQUOTEMARK, out);
10315                                         USTPUTC(c, out);
10316                                         quotef++;
10317                                 }
10318                                 break;
10319                         case CSQUOTE:
10320                                 if (eofmark == NULL)
10321                                         USTPUTC(CTLQUOTEMARK, out);
10322                                 syntax = SQSYNTAX;
10323                                 break;
10324                         case CDQUOTE:
10325                                 if (eofmark == NULL)
10326                                         USTPUTC(CTLQUOTEMARK, out);
10327                                 syntax = DQSYNTAX;
10328                                 dblquote = 1;
10329                                 break;
10330                         case CENDQUOTE:
10331                                 if (eofmark != NULL && arinest == 0 &&
10332                                     varnest == 0) {
10333                                         USTPUTC(c, out);
10334                                 } else {
10335                                         if (arinest) {
10336                                                 syntax = ARISYNTAX;
10337                                                 dblquote = 0;
10338                                         } else if (eofmark == NULL &&
10339                                                    dqvarnest == 0) {
10340                                                 syntax = BASESYNTAX;
10341                                                 dblquote = 0;
10342                                         }
10343                                         quotef++;
10344                                 }
10345                                 break;
10346                         case CVAR:      /* '$' */
10347                                 PARSESUB();             /* parse substitution */
10348                                 break;
10349                         case CENDVAR:   /* '}' */
10350                                 if (varnest > 0) {
10351                                         varnest--;
10352                                         if (dqvarnest > 0) {
10353                                                 dqvarnest--;
10354                                         }
10355                                         USTPUTC(CTLENDVAR, out);
10356                                 } else {
10357                                         USTPUTC(c, out);
10358                                 }
10359                                 break;
10360 #ifdef CONFIG_ASH_MATH_SUPPORT
10361                         case CLP:       /* '(' in arithmetic */
10362                                 parenlevel++;
10363                                 USTPUTC(c, out);
10364                                 break;
10365                         case CRP:       /* ')' in arithmetic */
10366                                 if (parenlevel > 0) {
10367                                         USTPUTC(c, out);
10368                                         --parenlevel;
10369                                 } else {
10370                                         if (pgetc() == ')') {
10371                                                 if (--arinest == 0) {
10372                                                         USTPUTC(CTLENDARI, out);
10373                                                         syntax = prevsyntax;
10374                                                         if (syntax == DQSYNTAX)
10375                                                                 dblquote = 1;
10376                                                         else
10377                                                                 dblquote = 0;
10378                                                 } else
10379                                                         USTPUTC(')', out);
10380                                         } else {
10381                                                 /*
10382                                                  * unbalanced parens
10383                                                  *  (don't 2nd guess - no error)
10384                                                  */
10385                                                 pungetc();
10386                                                 USTPUTC(')', out);
10387                                         }
10388                                 }
10389                                 break;
10390 #endif
10391                         case CBQUOTE:   /* '`' */
10392                                 PARSEBACKQOLD();
10393                                 break;
10394                         case CENDFILE:
10395                                 goto endword;           /* exit outer loop */
10396                         case CIGN:
10397                                 break;
10398                         default:
10399                                 if (varnest == 0)
10400                                         goto endword;   /* exit outer loop */
10401 #ifdef CONFIG_ASH_ALIAS
10402                                 if (c != PEOA)
10403 #endif
10404                                         USTPUTC(c, out);
10405
10406                         }
10407                         c = pgetc_macro();
10408                 }
10409         }
10410 endword:
10411         if (syntax == ARISYNTAX)
10412                 synerror("Missing '))'");
10413         if (syntax != BASESYNTAX && ! parsebackquote && eofmark == NULL)
10414                 synerror("Unterminated quoted string");
10415         if (varnest != 0) {
10416                 startlinno = plinno;
10417                 synerror("Missing '}'");
10418         }
10419         USTPUTC('\0', out);
10420         len = out - stackblock();
10421         out = stackblock();
10422         if (eofmark == NULL) {
10423                 if ((c == '>' || c == '<')
10424                  && quotef == 0
10425                  && len <= 2
10426                  && (*out == '\0' || is_digit(*out))) {
10427                         PARSEREDIR();
10428                         return lasttoken = TREDIR;
10429                 } else {
10430                         pungetc();
10431                 }
10432         }
10433         quoteflag = quotef;
10434         backquotelist = bqlist;
10435         grabstackblock(len);
10436         wordtext = out;
10437         return lasttoken = TWORD;
10438 /* end of readtoken routine */
10439
10440
10441
10442 /*
10443  * Check to see whether we are at the end of the here document.  When this
10444  * is called, c is set to the first character of the next input line.  If
10445  * we are at the end of the here document, this routine sets the c to PEOF.
10446  */
10447
10448 checkend: {
10449         if (eofmark) {
10450 #ifdef CONFIG_ASH_ALIAS
10451                 if (c == PEOA) {
10452                         c = pgetc2();
10453                 }
10454 #endif
10455                 if (striptabs) {
10456                         while (c == '\t') {
10457                                 c = pgetc2();
10458                         }
10459                 }
10460                 if (c == *eofmark) {
10461                         if (pfgets(line, sizeof line) != NULL) {
10462                                 const char *p, *q;
10463
10464                                 p = line;
10465                                 for (q = eofmark + 1 ; *q && *p == *q ; p++, q++);
10466                                 if (*p == '\n' && *q == '\0') {
10467                                         c = PEOF;
10468                                         plinno++;
10469                                         needprompt = doprompt;
10470                                 } else {
10471                                         pushstring(line, strlen(line), NULL);
10472                                 }
10473                         }
10474                 }
10475         }
10476         goto checkend_return;
10477 }
10478
10479
10480 /*
10481  * Parse a redirection operator.  The variable "out" points to a string
10482  * specifying the fd to be redirected.  The variable "c" contains the
10483  * first character of the redirection operator.
10484  */
10485
10486 parseredir: {
10487         char fd = *out;
10488         union node *np;
10489
10490         np = (union node *)stalloc(sizeof (struct nfile));
10491         if (c == '>') {
10492                 np->nfile.fd = 1;
10493                 c = pgetc();
10494                 if (c == '>')
10495                         np->type = NAPPEND;
10496                 else if (c == '&')
10497                         np->type = NTOFD;
10498                 else if (c == '|')
10499                         np->type = NTOOV;
10500                 else {
10501                         np->type = NTO;
10502                         pungetc();
10503                 }
10504         } else {        /* c == '<' */
10505                 np->nfile.fd = 0;
10506                 switch (c = pgetc()) {
10507                 case '<':
10508                         if (sizeof (struct nfile) != sizeof (struct nhere)) {
10509                                 np = (union node *)stalloc(sizeof (struct nhere));
10510                                 np->nfile.fd = 0;
10511                         }
10512                         np->type = NHERE;
10513                         heredoc = (struct heredoc *)stalloc(sizeof (struct heredoc));
10514                         heredoc->here = np;
10515                         if ((c = pgetc()) == '-') {
10516                                 heredoc->striptabs = 1;
10517                         } else {
10518                                 heredoc->striptabs = 0;
10519                                 pungetc();
10520                         }
10521                         break;
10522
10523                 case '&':
10524                         np->type = NFROMFD;
10525                         break;
10526
10527                 case '>':
10528                         np->type = NFROMTO;
10529                         break;
10530
10531                 default:
10532                         np->type = NFROM;
10533                         pungetc();
10534                         break;
10535                 }
10536         }
10537         if (fd != '\0')
10538                 np->nfile.fd = digit_val(fd);
10539         redirnode = np;
10540         goto parseredir_return;
10541 }
10542
10543
10544 /*
10545  * Parse a substitution.  At this point, we have read the dollar sign
10546  * and nothing else.
10547  */
10548
10549 parsesub: {
10550         int subtype;
10551         int typeloc;
10552         int flags;
10553         char *p;
10554         static const char types[] = "}-+?=";
10555
10556         c = pgetc();
10557         if (
10558                 c <= PEOA  ||
10559                 (c != '(' && c != '{' && !is_name(c) && !is_special(c))
10560         ) {
10561                 USTPUTC('$', out);
10562                 pungetc();
10563         } else if (c == '(') {  /* $(command) or $((arith)) */
10564                 if (pgetc() == '(') {
10565                         PARSEARITH();
10566                 } else {
10567                         pungetc();
10568                         PARSEBACKQNEW();
10569                 }
10570         } else {
10571                 USTPUTC(CTLVAR, out);
10572                 typeloc = out - stackblock();
10573                 USTPUTC(VSNORMAL, out);
10574                 subtype = VSNORMAL;
10575                 if (c == '{') {
10576                         c = pgetc();
10577                         if (c == '#') {
10578                                 if ((c = pgetc()) == '}')
10579                                         c = '#';
10580                                 else
10581                                         subtype = VSLENGTH;
10582                         }
10583                         else
10584                                 subtype = 0;
10585                 }
10586                 if (c > PEOA && is_name(c)) {
10587                         do {
10588                                 STPUTC(c, out);
10589                                 c = pgetc();
10590                         } while (c > PEOA && is_in_name(c));
10591                 } else if (is_digit(c)) {
10592                         do {
10593                                 USTPUTC(c, out);
10594                                 c = pgetc();
10595                         } while (is_digit(c));
10596                 }
10597                 else if (is_special(c)) {
10598                         USTPUTC(c, out);
10599                         c = pgetc();
10600                 }
10601                 else
10602 badsub:                 synerror("Bad substitution");
10603
10604                 STPUTC('=', out);
10605                 flags = 0;
10606                 if (subtype == 0) {
10607                         switch (c) {
10608                         case ':':
10609                                 flags = VSNUL;
10610                                 c = pgetc();
10611                                 /*FALLTHROUGH*/
10612                         default:
10613                                 p = strchr(types, c);
10614                                 if (p == NULL)
10615                                         goto badsub;
10616                                 subtype = p - types + VSNORMAL;
10617                                 break;
10618                         case '%':
10619                         case '#':
10620                                 {
10621                                         int cc = c;
10622                                         subtype = c == '#' ? VSTRIMLEFT :
10623                                                              VSTRIMRIGHT;
10624                                         c = pgetc();
10625                                         if (c == cc)
10626                                                 subtype++;
10627                                         else
10628                                                 pungetc();
10629                                         break;
10630                                 }
10631                         }
10632                 } else {
10633                         pungetc();
10634                 }
10635                 if (dblquote || arinest)
10636                         flags |= VSQUOTE;
10637                 *(stackblock() + typeloc) = subtype | flags;
10638                 if (subtype != VSNORMAL) {
10639                         varnest++;
10640                         if (dblquote) {
10641                                 dqvarnest++;
10642                         }
10643                 }
10644         }
10645         goto parsesub_return;
10646 }
10647
10648
10649 /*
10650  * Called to parse command substitutions.  Newstyle is set if the command
10651  * is enclosed inside $(...); nlpp is a pointer to the head of the linked
10652  * list of commands (passed by reference), and savelen is the number of
10653  * characters on the top of the stack which must be preserved.
10654  */
10655
10656 parsebackq: {
10657         struct nodelist **nlpp;
10658         int savepbq;
10659         union node *n;
10660         char *volatile str;
10661         struct jmploc jmploc;
10662         struct jmploc *volatile savehandler;
10663         int savelen;
10664         int saveprompt;
10665 #ifdef __GNUC__
10666         (void) &saveprompt;
10667 #endif
10668
10669         savepbq = parsebackquote;
10670         if (setjmp(jmploc.loc)) {
10671                 if (str)
10672                         ckfree(str);
10673                 parsebackquote = 0;
10674                 handler = savehandler;
10675                 longjmp(handler->loc, 1);
10676         }
10677         INTOFF;
10678         str = NULL;
10679         savelen = out - stackblock();
10680         if (savelen > 0) {
10681                 str = xmalloc(savelen);
10682                 memcpy(str, stackblock(), savelen);
10683         }
10684         savehandler = handler;
10685         handler = &jmploc;
10686         INTON;
10687         if (oldstyle) {
10688                 /* We must read until the closing backquote, giving special
10689                    treatment to some slashes, and then push the string and
10690                    reread it as input, interpreting it normally.  */
10691                 char *pout;
10692                 int pc;
10693                 int psavelen;
10694                 char *pstr;
10695
10696
10697                 STARTSTACKSTR(pout);
10698                 for (;;) {
10699                         if (needprompt) {
10700                                 setprompt(2);
10701                                 needprompt = 0;
10702                         }
10703                         switch (pc = pgetc()) {
10704                         case '`':
10705                                 goto done;
10706
10707                         case '\\':
10708                                 if ((pc = pgetc()) == '\n') {
10709                                         plinno++;
10710                                         if (doprompt)
10711                                                 setprompt(2);
10712                                         else
10713                                                 setprompt(0);
10714                                         /*
10715                                          * If eating a newline, avoid putting
10716                                          * the newline into the new character
10717                                          * stream (via the STPUTC after the
10718                                          * switch).
10719                                          */
10720                                         continue;
10721                                 }
10722                                 if (pc != '\\' && pc != '`' && pc != '$'
10723                                     && (!dblquote || pc != '"'))
10724                                         STPUTC('\\', pout);
10725                                 if (pc > PEOA) {
10726                                         break;
10727                                 }
10728                                 /* fall through */
10729
10730                         case PEOF:
10731 #ifdef CONFIG_ASH_ALIAS
10732                         case PEOA:
10733 #endif
10734                                 startlinno = plinno;
10735                                 synerror("EOF in backquote substitution");
10736
10737                         case '\n':
10738                                 plinno++;
10739                                 needprompt = doprompt;
10740                                 break;
10741
10742                         default:
10743                                 break;
10744                         }
10745                         STPUTC(pc, pout);
10746                 }
10747 done:
10748                 STPUTC('\0', pout);
10749                 psavelen = pout - stackblock();
10750                 if (psavelen > 0) {
10751                         pstr = grabstackstr(pout);
10752                         setinputstring(pstr);
10753                 }
10754         }
10755         nlpp = &bqlist;
10756         while (*nlpp)
10757                 nlpp = &(*nlpp)->next;
10758         *nlpp = (struct nodelist *)stalloc(sizeof (struct nodelist));
10759         (*nlpp)->next = NULL;
10760         parsebackquote = oldstyle;
10761
10762         if (oldstyle) {
10763                 saveprompt = doprompt;
10764                 doprompt = 0;
10765         }
10766
10767         n = list(0);
10768
10769         if (oldstyle)
10770                 doprompt = saveprompt;
10771         else {
10772                 if (readtoken() != TRP)
10773                         synexpect(TRP);
10774         }
10775
10776         (*nlpp)->n = n;
10777         if (oldstyle) {
10778                 /*
10779                  * Start reading from old file again, ignoring any pushed back
10780                  * tokens left from the backquote parsing
10781                  */
10782                 popfile();
10783                 tokpushback = 0;
10784         }
10785         while (stackblocksize() <= savelen)
10786                 growstackblock();
10787         STARTSTACKSTR(out);
10788         if (str) {
10789                 memcpy(out, str, savelen);
10790                 STADJUST(savelen, out);
10791                 INTOFF;
10792                 ckfree(str);
10793                 str = NULL;
10794                 INTON;
10795         }
10796         parsebackquote = savepbq;
10797         handler = savehandler;
10798         if (arinest || dblquote)
10799                 USTPUTC(CTLBACKQ | CTLQUOTE, out);
10800         else
10801                 USTPUTC(CTLBACKQ, out);
10802         if (oldstyle)
10803                 goto parsebackq_oldreturn;
10804         else
10805                 goto parsebackq_newreturn;
10806 }
10807
10808 /*
10809  * Parse an arithmetic expansion (indicate start of one and set state)
10810  */
10811 parsearith: {
10812
10813         if (++arinest == 1) {
10814                 prevsyntax = syntax;
10815                 syntax = ARISYNTAX;
10816                 USTPUTC(CTLARI, out);
10817                 if (dblquote)
10818                         USTPUTC('"',out);
10819                 else
10820                         USTPUTC(' ',out);
10821         } else {
10822                 /*
10823                  * we collapse embedded arithmetic expansion to
10824                  * parenthesis, which should be equivalent
10825                  */
10826                 USTPUTC('(', out);
10827         }
10828         goto parsearith_return;
10829 }
10830
10831 } /* end of readtoken */
10832
10833
10834 /*
10835  * Returns true if the text contains nothing to expand (no dollar signs
10836  * or backquotes).
10837  */
10838
10839 static int
10840 noexpand(char *text)
10841 {
10842         char *p;
10843         char c;
10844
10845         p = text;
10846         while ((c = *p++) != '\0') {
10847                 if (c == CTLQUOTEMARK)
10848                         continue;
10849                 if (c == CTLESC)
10850                         p++;
10851                 else if (SIT(c,BASESYNTAX) == CCTL)
10852                         return 0;
10853         }
10854         return 1;
10855 }
10856
10857
10858 /*
10859  * Return true if the argument is a legal variable name (a letter or
10860  * underscore followed by zero or more letters, underscores, and digits).
10861  */
10862
10863 static int
10864 goodname(const char *name)
10865 {
10866         const char *p;
10867
10868         p = name;
10869         if (! is_name(*p))
10870                 return 0;
10871         while (*++p) {
10872                 if (! is_in_name(*p))
10873                         return 0;
10874         }
10875         return 1;
10876 }
10877
10878
10879 /*
10880  * Called when an unexpected token is read during the parse.  The argument
10881  * is the token that is expected, or -1 if more than one type of token can
10882  * occur at this point.
10883  */
10884
10885 static void
10886 synexpect(int token)
10887 {
10888         char msg[64];
10889         int l;
10890
10891         l = sprintf(msg, "%s unexpected", tokname(lasttoken));
10892         if (token >= 0)
10893                 sprintf(msg+l, " (expecting %s)", tokname(token));
10894         synerror(msg);
10895         /* NOTREACHED */
10896 }
10897
10898
10899 static void
10900 synerror(const char *msg)
10901 {
10902         if (commandname)
10903                 out2fmt("%s: %d: ", commandname, startlinno);
10904         out2fmt("Syntax error: %s\n", msg);
10905         error((char *)NULL);
10906         /* NOTREACHED */
10907 }
10908
10909
10910 /*
10911  * called by editline -- any expansions to the prompt
10912  *    should be added here.
10913  */
10914 static void
10915 setprompt(int whichprompt)
10916 {
10917     char *prompt;
10918     switch (whichprompt) {
10919         case 1:
10920                 prompt = ps1val();
10921                 break;
10922         case 2:
10923                 prompt = ps2val();
10924                 break;
10925         default:                /* 0 */
10926                 prompt = "";
10927     }
10928     putprompt(prompt);
10929 }
10930
10931
10932 /*
10933  * Code for dealing with input/output redirection.
10934  */
10935
10936 #define EMPTY -2                /* marks an unused slot in redirtab */
10937 #ifndef PIPE_BUF
10938 # define PIPESIZE 4096          /* amount of buffering in a pipe */
10939 #else
10940 # define PIPESIZE PIPE_BUF
10941 #endif
10942
10943
10944 /*
10945  * Open a file in noclobber mode.
10946  * The code was copied from bash.
10947  */
10948 static inline int
10949 noclobberopen(const char *fname)
10950 {
10951         int r, fd;
10952         struct stat finfo, finfo2;
10953
10954         /*
10955          * If the file exists and is a regular file, return an error
10956          * immediately.
10957          */
10958         r = stat(fname, &finfo);
10959         if (r == 0 && S_ISREG(finfo.st_mode)) {
10960                 errno = EEXIST;
10961                 return -1;
10962         }
10963
10964         /*
10965          * If the file was not present (r != 0), make sure we open it
10966          * exclusively so that if it is created before we open it, our open
10967          * will fail.  Make sure that we do not truncate an existing file.
10968          * Note that we don't turn on O_EXCL unless the stat failed -- if the
10969          * file was not a regular file, we leave O_EXCL off.
10970          */
10971         if (r != 0)
10972                 return open(fname, O_WRONLY|O_CREAT|O_EXCL, 0666);
10973         fd = open(fname, O_WRONLY|O_CREAT, 0666);
10974
10975         /* If the open failed, return the file descriptor right away. */
10976         if (fd < 0)
10977                 return fd;
10978
10979         /*
10980          * OK, the open succeeded, but the file may have been changed from a
10981          * non-regular file to a regular file between the stat and the open.
10982          * We are assuming that the O_EXCL open handles the case where FILENAME
10983          * did not exist and is symlinked to an existing file between the stat
10984          * and open.
10985          */
10986
10987         /*
10988          * If we can open it and fstat the file descriptor, and neither check
10989          * revealed that it was a regular file, and the file has not been
10990          * replaced, return the file descriptor.
10991          */
10992          if (fstat(fd, &finfo2) == 0 && !S_ISREG(finfo2.st_mode) &&
10993              finfo.st_dev == finfo2.st_dev && finfo.st_ino == finfo2.st_ino)
10994                 return fd;
10995
10996         /* The file has been replaced.  badness. */
10997         close(fd);
10998         errno = EEXIST;
10999         return -1;
11000 }
11001
11002 /*
11003  * Handle here documents.  Normally we fork off a process to write the
11004  * data to a pipe.  If the document is short, we can stuff the data in
11005  * the pipe without forking.
11006  */
11007
11008 static inline int
11009 openhere(const union node *redir)
11010 {
11011         int pip[2];
11012         int len = 0;
11013
11014         if (pipe(pip) < 0)
11015                 error("Pipe call failed");
11016         if (redir->type == NHERE) {
11017                 len = strlen(redir->nhere.doc->narg.text);
11018                 if (len <= PIPESIZE) {
11019                         xwrite(pip[1], redir->nhere.doc->narg.text, len);
11020                         goto out;
11021                 }
11022         }
11023         if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) {
11024                 close(pip[0]);
11025                 signal(SIGINT, SIG_IGN);
11026                 signal(SIGQUIT, SIG_IGN);
11027                 signal(SIGHUP, SIG_IGN);
11028 #ifdef SIGTSTP
11029                 signal(SIGTSTP, SIG_IGN);
11030 #endif
11031                 signal(SIGPIPE, SIG_DFL);
11032                 if (redir->type == NHERE)
11033                         xwrite(pip[1], redir->nhere.doc->narg.text, len);
11034                 else
11035                         expandhere(redir->nhere.doc, pip[1]);
11036                 _exit(0);
11037         }
11038 out:
11039         close(pip[1]);
11040         return pip[0];
11041 }
11042
11043
11044 static inline int
11045 openredirect(const union node *redir)
11046 {
11047         char *fname;
11048         int f;
11049
11050         switch (redir->nfile.type) {
11051         case NFROM:
11052                 fname = redir->nfile.expfname;
11053                 if ((f = open(fname, O_RDONLY)) < 0)
11054                         goto eopen;
11055                 break;
11056         case NFROMTO:
11057                 fname = redir->nfile.expfname;
11058                 if ((f = open(fname, O_RDWR|O_CREAT|O_TRUNC, 0666)) < 0)
11059                         goto ecreate;
11060                 break;
11061         case NTO:
11062                 /* Take care of noclobber mode. */
11063                 if (Cflag) {
11064                         fname = redir->nfile.expfname;
11065                         if ((f = noclobberopen(fname)) < 0)
11066                                 goto ecreate;
11067                         break;
11068                 }
11069         case NTOOV:
11070                 fname = redir->nfile.expfname;
11071 #ifdef O_CREAT
11072                 if ((f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666)) < 0)
11073                         goto ecreate;
11074 #else
11075                 if ((f = creat(fname, 0666)) < 0)
11076                         goto ecreate;
11077 #endif
11078                 break;
11079         case NAPPEND:
11080                 fname = redir->nfile.expfname;
11081 #ifdef O_APPEND
11082                 if ((f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666)) < 0)
11083                         goto ecreate;
11084 #else
11085                 if ((f = open(fname, O_WRONLY)) < 0
11086                  && (f = creat(fname, 0666)) < 0)
11087                         goto ecreate;
11088                 lseek(f, (off_t)0, 2);
11089 #endif
11090                 break;
11091         default:
11092 #ifdef DEBUG
11093                 abort();
11094 #endif
11095                 /* Fall through to eliminate warning. */
11096         case NTOFD:
11097         case NFROMFD:
11098                 f = -1;
11099                 break;
11100         case NHERE:
11101         case NXHERE:
11102                 f = openhere(redir);
11103                 break;
11104         }
11105
11106         return f;
11107 ecreate:
11108         error("cannot create %s: %s", fname, errmsg(errno, E_CREAT));
11109 eopen:
11110         error("cannot open %s: %s", fname, errmsg(errno, E_OPEN));
11111 }
11112
11113
11114 /*
11115  * Process a list of redirection commands.  If the REDIR_PUSH flag is set,
11116  * old file descriptors are stashed away so that the redirection can be
11117  * undone by calling popredir.  If the REDIR_BACKQ flag is set, then the
11118  * standard output, and the standard error if it becomes a duplicate of
11119  * stdout.
11120  */
11121
11122 static void
11123 redirect(union node *redir, int flags)
11124 {
11125         union node *n;
11126         struct redirtab *sv = NULL;
11127         int i;
11128         int fd;
11129         int newfd;
11130         int try;
11131         int fd1dup = flags & REDIR_BACKQ;; /* stdout `cmd` redir to pipe */
11132
11133         if (flags & REDIR_PUSH) {
11134                 sv = xmalloc(sizeof (struct redirtab));
11135                 for (i = 0 ; i < 10 ; i++)
11136                         sv->renamed[i] = EMPTY;
11137                 sv->next = redirlist;
11138                 redirlist = sv;
11139         }
11140         for (n = redir ; n ; n = n->nfile.next) {
11141                 fd = n->nfile.fd;
11142                 try = 0;
11143                 if ((n->nfile.type == NTOFD || n->nfile.type == NFROMFD) &&
11144                     n->ndup.dupfd == fd)
11145                         continue; /* redirect from/to same file descriptor */
11146
11147                 INTOFF;
11148                 newfd = openredirect(n);
11149                 if ((flags & REDIR_PUSH) && sv->renamed[fd] == EMPTY) {
11150                         if (newfd == fd) {
11151                                 try++;
11152                         } else if ((i = fcntl(fd, F_DUPFD, 10)) == -1) {
11153                                 switch (errno) {
11154                                 case EBADF:
11155                                         if (!try) {
11156                                                 dupredirect(n, newfd, fd1dup);
11157                                                 try++;
11158                                                 break;
11159                                         }
11160                                         /* FALLTHROUGH*/
11161                                 default:
11162                                         if (newfd >= 0) {
11163                                                 close(newfd);
11164                                         }
11165                                         INTON;
11166                                         error("%d: %m", fd);
11167                                         /* NOTREACHED */
11168                                 }
11169                         }
11170                         if (!try) {
11171                                 close(fd);
11172                                 if (flags & REDIR_PUSH) {
11173                                         sv->renamed[fd] = i;
11174                                 }
11175                         }
11176                 } else if (fd != newfd) {
11177                         close(fd);
11178                 }
11179                 if (fd == 0)
11180                         fd0_redirected++;
11181                 if (!try)
11182                         dupredirect(n, newfd, fd1dup);
11183                 INTON;
11184         }
11185 }
11186
11187
11188 static void
11189 dupredirect(const union node *redir, int f, int fd1dup)
11190 {
11191         int fd = redir->nfile.fd;
11192
11193         if(fd==1)
11194                 fd1dup = 0;
11195         if (redir->nfile.type == NTOFD || redir->nfile.type == NFROMFD) {
11196                 if (redir->ndup.dupfd >= 0) {   /* if not ">&-" */
11197                         if (redir->ndup.dupfd!=1 || fd1dup!=1)
11198                                 dup_as_newfd(redir->ndup.dupfd, fd);
11199                 }
11200                 return;
11201         }
11202
11203         if (f != fd) {
11204                 dup_as_newfd(f, fd);
11205                 close(f);
11206         }
11207         return;
11208 }
11209
11210
11211
11212 /*
11213  * Undo the effects of the last redirection.
11214  */
11215
11216 static void
11217 popredir(void)
11218 {
11219         struct redirtab *rp = redirlist;
11220         int i;
11221
11222         INTOFF;
11223         for (i = 0 ; i < 10 ; i++) {
11224                 if (rp->renamed[i] != EMPTY) {
11225                         if (i == 0)
11226                                 fd0_redirected--;
11227                         close(i);
11228                         if (rp->renamed[i] >= 0) {
11229                                 dup_as_newfd(rp->renamed[i], i);
11230                                 close(rp->renamed[i]);
11231                         }
11232                 }
11233         }
11234         redirlist = rp->next;
11235         ckfree(rp);
11236         INTON;
11237 }
11238
11239 /*
11240  * Discard all saved file descriptors.
11241  */
11242
11243 static void
11244 clearredir(void) {
11245         struct redirtab *rp;
11246         int i;
11247
11248         for (rp = redirlist ; rp ; rp = rp->next) {
11249                 for (i = 0 ; i < 10 ; i++) {
11250                         if (rp->renamed[i] >= 0) {
11251                                 close(rp->renamed[i]);
11252                         }
11253                         rp->renamed[i] = EMPTY;
11254                 }
11255         }
11256 }
11257
11258
11259 /*
11260  * Copy a file descriptor to be >= to.  Returns -1
11261  * if the source file descriptor is closed, EMPTY if there are no unused
11262  * file descriptors left.
11263  */
11264
11265 static int
11266 dup_as_newfd(int from, int to)
11267 {
11268         int newfd;
11269
11270         newfd = fcntl(from, F_DUPFD, to);
11271         if (newfd < 0) {
11272                 if (errno == EMFILE)
11273                         return EMPTY;
11274                 else
11275                         error("%d: %m", from);
11276         }
11277         return newfd;
11278 }
11279
11280 #ifdef DEBUG
11281 /*
11282  * Debugging stuff.
11283  */
11284 static void shtree (union node *, int, char *, FILE*);
11285 static void shcmd (union node *, FILE *);
11286 static void sharg (union node *, FILE *);
11287 static void indent (int, char *, FILE *);
11288 static void trstring (char *);
11289
11290
11291 static void
11292 showtree(n)
11293         unode *n;
11294 {
11295         trputs("showtree called\n");
11296         shtree(n, 1, NULL, stdout);
11297 }
11298
11299
11300 static void
11301 shtree(union node *n, int ind, char *pfx, FILE *fp)
11302 {
11303         struct nodelist *lp;
11304         const char *s;
11305
11306         if (n == NULL)
11307                 return;
11308
11309         indent(ind, pfx, fp);
11310         switch(n->type) {
11311         case NSEMI:
11312                 s = "; ";
11313                 goto binop;
11314         case NAND:
11315                 s = " && ";
11316                 goto binop;
11317         case NOR:
11318                 s = " || ";
11319 binop:
11320                 shtree(n->nbinary.ch1, ind, NULL, fp);
11321            /*    if (ind < 0) */
11322                         fputs(s, fp);
11323                 shtree(n->nbinary.ch2, ind, NULL, fp);
11324                 break;
11325         case NCMD:
11326                 shcmd(n, fp);
11327                 if (ind >= 0)
11328                         putc('\n', fp);
11329                 break;
11330         case NPIPE:
11331                 for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {
11332                         shcmd(lp->n, fp);
11333                         if (lp->next)
11334                                 fputs(" | ", fp);
11335                 }
11336                 if (n->npipe.backgnd)
11337                         fputs(" &", fp);
11338                 if (ind >= 0)
11339                         putc('\n', fp);
11340                 break;
11341         default:
11342                 fprintf(fp, "<node type %d>", n->type);
11343                 if (ind >= 0)
11344                         putc('\n', fp);
11345                 break;
11346         }
11347 }
11348
11349
11350
11351 static void
11352 shcmd(union node *cmd, FILE *fp)
11353 {
11354         union node *np;
11355         int first;
11356         const char *s;
11357         int dftfd;
11358
11359         first = 1;
11360         for (np = cmd->ncmd.args ; np ; np = np->narg.next) {
11361                 if (! first)
11362                         putchar(' ');
11363                 sharg(np, fp);
11364                 first = 0;
11365         }
11366         for (np = cmd->ncmd.redirect ; np ; np = np->nfile.next) {
11367                 if (! first)
11368                         putchar(' ');
11369 #if 1
11370                 s = "*error*";
11371                 dftfd = 0;
11372                 if ((np->nfile.type <= NFROMFD) && (np->nfile.type >= NTO)) {
11373                         s = redir_strings[np->nfile.type - NTO];
11374                         if (*s == '>') {
11375                                 dftfd = 1;
11376                         }
11377                 }
11378 #else
11379                 switch (np->nfile.type) {
11380                         case NTO:       s = ">";  dftfd = 1; break;
11381                         case NAPPEND:   s = ">>"; dftfd = 1; break;
11382                         case NTOFD:     s = ">&"; dftfd = 1; break;
11383                         case NTOOV:     s = ">|"; dftfd = 1; break;
11384                         case NFROM:     s = "<";  dftfd = 0; break;
11385                         case NFROMFD:   s = "<&"; dftfd = 0; break;
11386                         case NFROMTO:   s = "<>"; dftfd = 0; break;
11387                         default:        s = "*error*"; dftfd = 0; break;
11388                 }
11389 #endif
11390                 if (np->nfile.fd != dftfd)
11391                         fprintf(fp, "%d", np->nfile.fd);
11392                 fputs(s, fp);
11393                 if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) {
11394                         fprintf(fp, "%d", np->ndup.dupfd);
11395                 } else {
11396                         sharg(np->nfile.fname, fp);
11397                 }
11398                 first = 0;
11399         }
11400 }
11401
11402 static void
11403 sharg(union node *arg, FILE *fp)
11404 {
11405         char *p;
11406         struct nodelist *bqlist;
11407         int subtype;
11408
11409         if (arg->type != NARG) {
11410                 printf("<node type %d>\n", arg->type);
11411                 fflush(stdout);
11412                 abort();
11413         }
11414         bqlist = arg->narg.backquote;
11415         for (p = arg->narg.text ; *p ; p++) {
11416                 switch (*p) {
11417                 case CTLESC:
11418                         putc(*++p, fp);
11419                         break;
11420                 case CTLVAR:
11421                         putc('$', fp);
11422                         putc('{', fp);
11423                         subtype = *++p;
11424                         if (subtype == VSLENGTH)
11425                                 putc('#', fp);
11426
11427                         while (*p != '=')
11428                                 putc(*p++, fp);
11429
11430                         if (subtype & VSNUL)
11431                                 putc(':', fp);
11432
11433                         switch (subtype & VSTYPE) {
11434                         case VSNORMAL:
11435                                 putc('}', fp);
11436                                 break;
11437                         case VSMINUS:
11438                                 putc('-', fp);
11439                                 break;
11440                         case VSPLUS:
11441                                 putc('+', fp);
11442                                 break;
11443                         case VSQUESTION:
11444                                 putc('?', fp);
11445                                 break;
11446                         case VSASSIGN:
11447                                 putc('=', fp);
11448                                 break;
11449                         case VSTRIMLEFT:
11450                                 putc('#', fp);
11451                                 break;
11452                         case VSTRIMLEFTMAX:
11453                                 putc('#', fp);
11454                                 putc('#', fp);
11455                                 break;
11456                         case VSTRIMRIGHT:
11457                                 putc('%', fp);
11458                                 break;
11459                         case VSTRIMRIGHTMAX:
11460                                 putc('%', fp);
11461                                 putc('%', fp);
11462                                 break;
11463                         case VSLENGTH:
11464                                 break;
11465                         default:
11466                                 printf("<subtype %d>", subtype);
11467                         }
11468                         break;
11469                 case CTLENDVAR:
11470                      putc('}', fp);
11471                      break;
11472                 case CTLBACKQ:
11473                 case CTLBACKQ|CTLQUOTE:
11474                         putc('$', fp);
11475                         putc('(', fp);
11476                         shtree(bqlist->n, -1, NULL, fp);
11477                         putc(')', fp);
11478                         break;
11479                 default:
11480                         putc(*p, fp);
11481                         break;
11482                 }
11483         }
11484 }
11485
11486
11487 static void
11488 indent(int amount, char *pfx, FILE *fp)
11489 {
11490         int i;
11491
11492         for (i = 0 ; i < amount ; i++) {
11493                 if (pfx && i == amount - 1)
11494                         fputs(pfx, fp);
11495                 putc('\t', fp);
11496         }
11497 }
11498
11499
11500 FILE *tracefile;
11501
11502 #if DEBUG == 2
11503 static int debug = 1;
11504 #else
11505 static int debug = 0;
11506 #endif
11507
11508
11509 static void
11510 trputc(int c)
11511 {
11512         if (tracefile == NULL)
11513                 return;
11514         putc(c, tracefile);
11515         if (c == '\n')
11516                 fflush(tracefile);
11517 }
11518
11519 static void
11520 trace(const char *fmt, ...)
11521 {
11522         va_list va;
11523         va_start(va, fmt);
11524         if (tracefile != NULL) {
11525                 (void) vfprintf(tracefile, fmt, va);
11526                 if (strchr(fmt, '\n'))
11527                         (void) fflush(tracefile);
11528         }
11529         va_end(va);
11530 }
11531
11532
11533 static void
11534 trputs(const char *s)
11535 {
11536         if (tracefile == NULL)
11537                 return;
11538         fputs(s, tracefile);
11539         if (strchr(s, '\n'))
11540                 fflush(tracefile);
11541 }
11542
11543
11544 static void
11545 trstring(char *s)
11546 {
11547         char *p;
11548         char c;
11549
11550         if (tracefile == NULL)
11551                 return;
11552         putc('"', tracefile);
11553         for (p = s ; *p ; p++) {
11554                 switch (*p) {
11555                 case '\n':  c = 'n';  goto backslash;
11556                 case '\t':  c = 't';  goto backslash;
11557                 case '\r':  c = 'r';  goto backslash;
11558                 case '"':  c = '"';  goto backslash;
11559                 case '\\':  c = '\\';  goto backslash;
11560                 case CTLESC:  c = 'e';  goto backslash;
11561                 case CTLVAR:  c = 'v';  goto backslash;
11562                 case CTLVAR+CTLQUOTE:  c = 'V';  goto backslash;
11563                 case CTLBACKQ:  c = 'q';  goto backslash;
11564                 case CTLBACKQ+CTLQUOTE:  c = 'Q';  goto backslash;
11565 backslash:        putc('\\', tracefile);
11566                         putc(c, tracefile);
11567                         break;
11568                 default:
11569                         if (*p >= ' ' && *p <= '~')
11570                                 putc(*p, tracefile);
11571                         else {
11572                                 putc('\\', tracefile);
11573                                 putc(*p >> 6 & 03, tracefile);
11574                                 putc(*p >> 3 & 07, tracefile);
11575                                 putc(*p & 07, tracefile);
11576                         }
11577                         break;
11578                 }
11579         }
11580         putc('"', tracefile);
11581 }
11582
11583
11584 static void
11585 trargs(char **ap)
11586 {
11587         if (tracefile == NULL)
11588                 return;
11589         while (*ap) {
11590                 trstring(*ap++);
11591                 if (*ap)
11592                         putc(' ', tracefile);
11593                 else
11594                         putc('\n', tracefile);
11595         }
11596         fflush(tracefile);
11597 }
11598
11599
11600 static void
11601 opentrace()
11602 {
11603         char s[100];
11604 #ifdef O_APPEND
11605         int flags;
11606 #endif
11607
11608         if (!debug)
11609                 return;
11610 #ifdef not_this_way
11611         {
11612                 char *p;
11613                 if ((p = getenv("HOME")) == NULL) {
11614                         if (geteuid() == 0)
11615                                 p = "/";
11616                         else
11617                                 p = "/tmp";
11618                 }
11619                 strcpy(s, p);
11620                 strcat(s, "/trace");
11621         }
11622 #else
11623         strcpy(s, "./trace");
11624 #endif /* not_this_way */
11625         if ((tracefile = wfopen(s, "a")) == NULL)
11626                 return;
11627 #ifdef O_APPEND
11628         if ((flags = fcntl(fileno(tracefile), F_GETFL, 0)) >= 0)
11629                 fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND);
11630 #endif
11631         fputs("\nTracing started.\n", tracefile);
11632         fflush(tracefile);
11633 }
11634 #endif /* DEBUG */
11635
11636
11637 /*
11638  * The trap builtin.
11639  */
11640
11641 static int
11642 trapcmd(int argc, char **argv)
11643 {
11644         char *action;
11645         char **ap;
11646         int signo;
11647
11648         if (argc <= 1) {
11649                 for (signo = 0 ; signo < NSIG ; signo++) {
11650                         if (trap[signo] != NULL) {
11651                                 char *p;
11652                                 const char *sn;
11653
11654                                 p = single_quote(trap[signo]);
11655                                 sn = sys_siglist[signo];
11656                                 if(sn==NULL)
11657                                         sn = u_signal_names(0, &signo, 0);
11658                                 if(sn==NULL)
11659                                         sn = "???";
11660                                 printf("trap -- %s %s\n", p, sn);
11661                                 stunalloc(p);
11662                         }
11663                 }
11664                 return 0;
11665         }
11666         ap = argv + 1;
11667         if (argc == 2)
11668                 action = NULL;
11669         else
11670                 action = *ap++;
11671         while (*ap) {
11672                 if ((signo = decode_signal(*ap, 0)) < 0)
11673                         error("%s: bad trap", *ap);
11674                 INTOFF;
11675                 if (action) {
11676                         if (action[0] == '-' && action[1] == '\0')
11677                                 action = NULL;
11678                         else
11679                                 action = xstrdup(action);
11680                 }
11681                 if (trap[signo])
11682                         ckfree(trap[signo]);
11683                 trap[signo] = action;
11684                 if (signo != 0)
11685                         setsignal(signo);
11686                 INTON;
11687                 ap++;
11688         }
11689         return 0;
11690 }
11691
11692
11693
11694
11695
11696
11697 /*
11698  * Set the signal handler for the specified signal.  The routine figures
11699  * out what it should be set to.
11700  */
11701
11702 static void
11703 setsignal(int signo)
11704 {
11705         int action;
11706         char *t;
11707         struct sigaction act;
11708
11709         if ((t = trap[signo]) == NULL)
11710                 action = S_DFL;
11711         else if (*t != '\0')
11712                 action = S_CATCH;
11713         else
11714                 action = S_IGN;
11715         if (rootshell && action == S_DFL) {
11716                 switch (signo) {
11717                 case SIGINT:
11718                         if (iflag || minusc || sflag == 0)
11719                                 action = S_CATCH;
11720                         break;
11721                 case SIGQUIT:
11722 #ifdef DEBUG
11723                         {
11724
11725                         if (debug)
11726                                 break;
11727                         }
11728 #endif
11729                         /* FALLTHROUGH */
11730                 case SIGTERM:
11731                         if (iflag)
11732                                 action = S_IGN;
11733                         break;
11734 #ifdef CONFIG_ASH_JOB_CONTROL
11735                 case SIGTSTP:
11736                 case SIGTTOU:
11737                         if (mflag)
11738                                 action = S_IGN;
11739                         break;
11740 #endif
11741                 }
11742         }
11743
11744         t = &sigmode[signo - 1];
11745         if (*t == 0) {
11746                 /*
11747                  * current setting unknown
11748                  */
11749                 if (sigaction(signo, 0, &act) == -1) {
11750                         /*
11751                          * Pretend it worked; maybe we should give a warning
11752                          * here, but other shells don't. We don't alter
11753                          * sigmode, so that we retry every time.
11754                          */
11755                         return;
11756                 }
11757                 if (act.sa_handler == SIG_IGN) {
11758                         if (mflag && (signo == SIGTSTP ||
11759                              signo == SIGTTIN || signo == SIGTTOU)) {
11760                                 *t = S_IGN;     /* don't hard ignore these */
11761                         } else
11762                                 *t = S_HARD_IGN;
11763                 } else {
11764                         *t = S_RESET;   /* force to be set */
11765                 }
11766         }
11767         if (*t == S_HARD_IGN || *t == action)
11768                 return;
11769         act.sa_handler = ((action == S_CATCH) ? onsig
11770                                           : ((action == S_IGN) ? SIG_IGN : SIG_DFL));
11771         *t = action;
11772         act.sa_flags = 0;
11773         sigemptyset(&act.sa_mask);
11774         sigaction(signo, &act, 0);
11775 }
11776
11777 /*
11778  * Ignore a signal.
11779  */
11780
11781 static void
11782 ignoresig(int signo)
11783 {
11784         if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) {
11785                 signal(signo, SIG_IGN);
11786         }
11787         sigmode[signo - 1] = S_HARD_IGN;
11788 }
11789
11790
11791 /*
11792  * Signal handler.
11793  */
11794
11795 static void
11796 onsig(int signo)
11797 {
11798         if (signo == SIGINT && trap[SIGINT] == NULL) {
11799                 onint();
11800                 return;
11801         }
11802         gotsig[signo - 1] = 1;
11803         pendingsigs++;
11804 }
11805
11806
11807 /*
11808  * Called to execute a trap.  Perhaps we should avoid entering new trap
11809  * handlers while we are executing a trap handler.
11810  */
11811
11812 static void
11813 dotrap(void)
11814 {
11815         int i;
11816         int savestatus;
11817
11818         for (;;) {
11819                 for (i = 1 ; ; i++) {
11820                         if (gotsig[i - 1])
11821                                 break;
11822                         if (i >= NSIG - 1)
11823                                 goto done;
11824                 }
11825                 gotsig[i - 1] = 0;
11826                 savestatus=exitstatus;
11827                 evalstring(trap[i], 0);
11828                 exitstatus=savestatus;
11829         }
11830 done:
11831         pendingsigs = 0;
11832 }
11833
11834 /*
11835  * Called to exit the shell.
11836  */
11837
11838 static void
11839 exitshell(int status)
11840 {
11841         struct jmploc loc1, loc2;
11842         char *p;
11843
11844         TRACE(("exitshell(%d) pid=%d\n", status, getpid()));
11845         if (setjmp(loc1.loc)) {
11846                 goto l1;
11847         }
11848         if (setjmp(loc2.loc)) {
11849                 goto l2;
11850         }
11851         handler = &loc1;
11852         if ((p = trap[0]) != NULL && *p != '\0') {
11853                 trap[0] = NULL;
11854                 evalstring(p, 0);
11855         }
11856 l1:   handler = &loc2;                  /* probably unnecessary */
11857         flushall();
11858 #ifdef CONFIG_ASH_JOB_CONTROL
11859         setjobctl(0);
11860 #endif
11861 l2:   _exit(status);
11862         /* NOTREACHED */
11863 }
11864
11865 static int decode_signal(const char *string, int minsig)
11866 {
11867         int signo;
11868         const char *name = u_signal_names(string, &signo, minsig);
11869
11870         return name ? signo : -1;
11871 }
11872
11873 static struct var **hashvar (const char *);
11874 static void showvars (const char *, int, int);
11875 static struct var **findvar (struct var **, const char *);
11876
11877 /*
11878  * Initialize the varable symbol tables and import the environment
11879  */
11880
11881 /*
11882  * This routine initializes the builtin variables.  It is called when the
11883  * shell is initialized and again when a shell procedure is spawned.
11884  */
11885
11886 static void
11887 initvar() {
11888         const struct varinit *ip;
11889         struct var *vp;
11890         struct var **vpp;
11891
11892         for (ip = varinit ; (vp = ip->var) != NULL ; ip++) {
11893                 if ((vp->flags & VEXPORT) == 0) {
11894                         vpp = hashvar(ip->text);
11895                         vp->next = *vpp;
11896                         *vpp = vp;
11897                         vp->text = xstrdup(ip->text);
11898                         vp->flags = ip->flags;
11899                         vp->func = ip->func;
11900                 }
11901         }
11902 #if !defined(CONFIG_FEATURE_COMMAND_EDITING) || !defined(CONFIG_FEATURE_SH_FANCY_PROMPT)
11903         /*
11904          * PS1 depends on uid
11905          */
11906         if ((vps1.flags & VEXPORT) == 0) {
11907                 vpp = hashvar("PS1=$");
11908                 vps1.next = *vpp;
11909                 *vpp = &vps1;
11910                 vps1.text = xstrdup(geteuid() ? "PS1=$ " : "PS1=# ");
11911                 vps1.flags = VSTRFIXED|VTEXTFIXED;
11912         }
11913 #endif
11914 }
11915
11916 /*
11917  * Set the value of a variable.  The flags argument is ored with the
11918  * flags of the variable.  If val is NULL, the variable is unset.
11919  */
11920
11921 static void
11922 setvar(const char *name, const char *val, int flags)
11923 {
11924         const char *p;
11925         int len;
11926         int namelen;
11927         char *nameeq;
11928         int isbad;
11929         int vallen = 0;
11930
11931         isbad = 0;
11932         p = name;
11933         if (! is_name(*p))
11934                 isbad = 1;
11935         p++;
11936         for (;;) {
11937                 if (! is_in_name(*p)) {
11938                         if (*p == '\0' || *p == '=')
11939                                 break;
11940                         isbad = 1;
11941                 }
11942                 p++;
11943         }
11944         namelen = p - name;
11945         if (isbad)
11946                 error("%.*s: bad variable name", namelen, name);
11947         len = namelen + 2;              /* 2 is space for '=' and '\0' */
11948         if (val == NULL) {
11949                 flags |= VUNSET;
11950         } else {
11951                 len += vallen = strlen(val);
11952         }
11953         INTOFF;
11954         nameeq = xmalloc(len);
11955         memcpy(nameeq, name, namelen);
11956         nameeq[namelen] = '=';
11957         if (val) {
11958                 memcpy(nameeq + namelen + 1, val, vallen + 1);
11959         } else {
11960                 nameeq[namelen + 1] = '\0';
11961         }
11962         setvareq(nameeq, flags);
11963         INTON;
11964 }
11965
11966
11967
11968 /*
11969  * Same as setvar except that the variable and value are passed in
11970  * the first argument as name=value.  Since the first argument will
11971  * be actually stored in the table, it should not be a string that
11972  * will go away.
11973  */
11974
11975 static void
11976 setvareq(char *s, int flags)
11977 {
11978         struct var *vp, **vpp;
11979
11980         vpp = hashvar(s);
11981         flags |= (VEXPORT & (((unsigned) (1 - aflag)) - 1));
11982         if ((vp = *findvar(vpp, s))) {
11983                 if (vp->flags & VREADONLY) {
11984                         size_t len = strchr(s, '=') - s;
11985                         error("%.*s: is read only", len, s);
11986                 }
11987                 INTOFF;
11988
11989                 if (vp->func && (flags & VNOFUNC) == 0)
11990                         (*vp->func)(strchr(s, '=') + 1);
11991
11992                 if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
11993                         ckfree(vp->text);
11994
11995                 vp->flags &= ~(VTEXTFIXED|VSTACK|VUNSET);
11996                 vp->flags |= flags;
11997                 vp->text = s;
11998
11999 #ifdef CONFIG_ASH_MAIL
12000                 /*
12001                  * We could roll this to a function, to handle it as
12002                  * a regular variable function callback, but why bother?
12003                  */
12004                 if (iflag && (vp == &vmpath || (vp == &vmail && !mpathset())))
12005                         chkmail(1);
12006 #endif
12007                 INTON;
12008                 return;
12009         }
12010         /* not found */
12011         vp = xmalloc(sizeof (*vp));
12012         vp->flags = flags;
12013         vp->text = s;
12014         vp->next = *vpp;
12015         vp->func = NULL;
12016         *vpp = vp;
12017 }
12018
12019
12020
12021 /*
12022  * Process a linked list of variable assignments.
12023  */
12024
12025 static void
12026 listsetvar(struct strlist *mylist)
12027 {
12028         struct strlist *lp;
12029
12030         INTOFF;
12031         for (lp = mylist ; lp ; lp = lp->next) {
12032                 setvareq(xstrdup(lp->text), 0);
12033         }
12034         INTON;
12035 }
12036
12037
12038
12039 /*
12040  * Find the value of a variable.  Returns NULL if not set.
12041  */
12042
12043 static const char *
12044 lookupvar(const char *name)
12045 {
12046         struct var *v;
12047
12048         if ((v = *findvar(hashvar(name), name)) && !(v->flags & VUNSET)) {
12049                 return strchr(v->text, '=') + 1;
12050         }
12051         return NULL;
12052 }
12053
12054
12055
12056 /*
12057  * Search the environment of a builtin command.
12058  */
12059
12060 static const char *
12061 bltinlookup(const char *name)
12062 {
12063         const struct strlist *sp;
12064
12065         for (sp = cmdenviron ; sp ; sp = sp->next) {
12066                 if (varequal(sp->text, name))
12067                         return strchr(sp->text, '=') + 1;
12068         }
12069         return lookupvar(name);
12070 }
12071
12072
12073
12074 /*
12075  * Generate a list of exported variables.  This routine is used to construct
12076  * the third argument to execve when executing a program.
12077  */
12078
12079 static char **
12080 environment() {
12081         int nenv;
12082         struct var **vpp;
12083         struct var *vp;
12084         char **env;
12085         char **ep;
12086
12087         nenv = 0;
12088         for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) {
12089                 for (vp = *vpp ; vp ; vp = vp->next)
12090                         if (vp->flags & VEXPORT)
12091                                 nenv++;
12092         }
12093         ep = env = stalloc((nenv + 1) * sizeof *env);
12094         for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) {
12095                 for (vp = *vpp ; vp ; vp = vp->next)
12096                         if (vp->flags & VEXPORT)
12097                                 *ep++ = vp->text;
12098         }
12099         *ep = NULL;
12100         return env;
12101 }
12102
12103
12104 /*
12105  * Called when a shell procedure is invoked to clear out nonexported
12106  * variables.  It is also necessary to reallocate variables of with
12107  * VSTACK set since these are currently allocated on the stack.
12108  */
12109
12110 static void
12111 shprocvar(void) {
12112         struct var **vpp;
12113         struct var *vp, **prev;
12114
12115         for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) {
12116                 for (prev = vpp ; (vp = *prev) != NULL ; ) {
12117                         if ((vp->flags & VEXPORT) == 0) {
12118                                 *prev = vp->next;
12119                                 if ((vp->flags & VTEXTFIXED) == 0)
12120                                         ckfree(vp->text);
12121                                 if ((vp->flags & VSTRFIXED) == 0)
12122                                         ckfree(vp);
12123                         } else {
12124                                 if (vp->flags & VSTACK) {
12125                                         vp->text = xstrdup(vp->text);
12126                                         vp->flags &=~ VSTACK;
12127                                 }
12128                                 prev = &vp->next;
12129                         }
12130                 }
12131         }
12132         initvar();
12133 }
12134
12135
12136
12137 /*
12138  * Command to list all variables which are set.  Currently this command
12139  * is invoked from the set command when the set command is called without
12140  * any variables.
12141  */
12142
12143 static int
12144 showvarscmd(int argc, char **argv)
12145 {
12146         showvars(nullstr, VUNSET, VUNSET);
12147         return 0;
12148 }
12149
12150
12151
12152 /*
12153  * The export and readonly commands.
12154  */
12155
12156 static int
12157 exportcmd(int argc, char **argv)
12158 {
12159         struct var *vp;
12160         char *name;
12161         const char *p;
12162         int flag = argv[0][0] == 'r'? VREADONLY : VEXPORT;
12163         int pflag;
12164
12165         listsetvar(cmdenviron);
12166         pflag = (nextopt("p") == 'p');
12167         if (argc > 1 && !pflag) {
12168                 while ((name = *argptr++) != NULL) {
12169                         if ((p = strchr(name, '=')) != NULL) {
12170                                 p++;
12171                         } else {
12172                                 if ((vp = *findvar(hashvar(name), name))) {
12173                                         vp->flags |= flag;
12174                                         goto found;
12175                                 }
12176                         }
12177                         setvar(name, p, flag);
12178 found:;
12179                 }
12180         } else {
12181                 showvars(argv[0], flag, 0);
12182         }
12183         return 0;
12184 }
12185
12186
12187 /*
12188  * The "local" command.
12189  */
12190
12191 /* funcnest nonzero if we are currently evaluating a function */
12192
12193 static int
12194 localcmd(int argc, char **argv)
12195 {
12196         char *name;
12197
12198         if (! funcnest)
12199                 error("Not in a function");
12200         while ((name = *argptr++) != NULL) {
12201                 mklocal(name);
12202         }
12203         return 0;
12204 }
12205
12206
12207 /*
12208  * Make a variable a local variable.  When a variable is made local, it's
12209  * value and flags are saved in a localvar structure.  The saved values
12210  * will be restored when the shell function returns.  We handle the name
12211  * "-" as a special case.
12212  */
12213
12214 static void
12215 mklocal(char *name)
12216 {
12217         struct localvar *lvp;
12218         struct var **vpp;
12219         struct var *vp;
12220
12221         INTOFF;
12222         lvp = xmalloc(sizeof (struct localvar));
12223         if (name[0] == '-' && name[1] == '\0') {
12224                 char *p;
12225                 p = xmalloc(sizeof optet_vals);
12226                 lvp->text = memcpy(p, optet_vals, sizeof optet_vals);
12227                 vp = NULL;
12228         } else {
12229                 vpp = hashvar(name);
12230                 vp = *findvar(vpp, name);
12231                 if (vp == NULL) {
12232                         if (strchr(name, '='))
12233                                 setvareq(xstrdup(name), VSTRFIXED);
12234                         else
12235                                 setvar(name, NULL, VSTRFIXED);
12236                         vp = *vpp;      /* the new variable */
12237                         lvp->text = NULL;
12238                         lvp->flags = VUNSET;
12239                 } else {
12240                         lvp->text = vp->text;
12241                         lvp->flags = vp->flags;
12242                         vp->flags |= VSTRFIXED|VTEXTFIXED;
12243                         if (strchr(name, '='))
12244                                 setvareq(xstrdup(name), 0);
12245                 }
12246         }
12247         lvp->vp = vp;
12248         lvp->next = localvars;
12249         localvars = lvp;
12250         INTON;
12251 }
12252
12253
12254 /*
12255  * Called after a function returns.
12256  */
12257
12258 static void
12259 poplocalvars() {
12260         struct localvar *lvp;
12261         struct var *vp;
12262
12263         while ((lvp = localvars) != NULL) {
12264                 localvars = lvp->next;
12265                 vp = lvp->vp;
12266                 if (vp == NULL) {       /* $- saved */
12267                         memcpy(optet_vals, lvp->text, sizeof optet_vals);
12268                         ckfree(lvp->text);
12269                 } else if ((lvp->flags & (VUNSET|VSTRFIXED)) == VUNSET) {
12270                         (void)unsetvar(vp->text);
12271                 } else {
12272                         if ((vp->flags & VTEXTFIXED) == 0)
12273                                 ckfree(vp->text);
12274                         vp->flags = lvp->flags;
12275                         vp->text = lvp->text;
12276                 }
12277                 ckfree(lvp);
12278         }
12279 }
12280
12281
12282 static int
12283 setvarcmd(int argc, char **argv)
12284 {
12285         if (argc <= 2)
12286                 return unsetcmd(argc, argv);
12287         else if (argc == 3)
12288                 setvar(argv[1], argv[2], 0);
12289         else
12290                 error("List assignment not implemented");
12291         return 0;
12292 }
12293
12294
12295 /*
12296  * The unset builtin command.  We unset the function before we unset the
12297  * variable to allow a function to be unset when there is a readonly variable
12298  * with the same name.
12299  */
12300
12301 static int
12302 unsetcmd(int argc, char **argv)
12303 {
12304         char **ap;
12305         int i;
12306         int flg_func = 0;
12307         int flg_var = 0;
12308         int ret = 0;
12309
12310         while ((i = nextopt("vf")) != '\0') {
12311                 if (i == 'f')
12312                         flg_func = 1;
12313                 else
12314                         flg_var = 1;
12315         }
12316         if (flg_func == 0 && flg_var == 0)
12317                 flg_var = 1;
12318
12319         for (ap = argptr; *ap ; ap++) {
12320                 if (flg_func)
12321                         unsetfunc(*ap);
12322                 if (flg_var)
12323                         ret |= unsetvar(*ap);
12324         }
12325         return ret;
12326 }
12327
12328
12329 /*
12330  * Unset the specified variable.
12331  */
12332
12333 static int
12334 unsetvar(const char *s)
12335 {
12336         struct var **vpp;
12337         struct var *vp;
12338
12339         vpp = findvar(hashvar(s), s);
12340         vp = *vpp;
12341         if (vp) {
12342                 if (vp->flags & VREADONLY)
12343                         return (1);
12344                 INTOFF;
12345                 if (*(strchr(vp->text, '=') + 1) != '\0')
12346                         setvar(s, nullstr, 0);
12347                 vp->flags &= ~VEXPORT;
12348                 vp->flags |= VUNSET;
12349                 if ((vp->flags & VSTRFIXED) == 0) {
12350                         if ((vp->flags & VTEXTFIXED) == 0)
12351                                 ckfree(vp->text);
12352                         *vpp = vp->next;
12353                         ckfree(vp);
12354                 }
12355                 INTON;
12356                 return (0);
12357         }
12358
12359         return (0);
12360 }
12361
12362
12363
12364 /*
12365  * Find the appropriate entry in the hash table from the name.
12366  */
12367
12368 static struct var **
12369 hashvar(const char *p)
12370 {
12371         unsigned int hashval;
12372
12373         hashval = ((unsigned char) *p) << 4;
12374         while (*p && *p != '=')
12375                 hashval += (unsigned char) *p++;
12376         return &vartab[hashval % VTABSIZE];
12377 }
12378
12379
12380
12381 /*
12382  * Returns true if the two strings specify the same varable.  The first
12383  * variable name is terminated by '='; the second may be terminated by
12384  * either '=' or '\0'.
12385  */
12386
12387 static int
12388 varequal(const char *p, const char *q)
12389 {
12390         while (*p == *q++) {
12391                 if (*p++ == '=')
12392                         return 1;
12393         }
12394         if (*p == '=' && *(q - 1) == '\0')
12395                 return 1;
12396         return 0;
12397 }
12398
12399 static void
12400 showvars(const char *myprefix, int mask, int xor)
12401 {
12402         struct var **vpp;
12403         struct var *vp;
12404         const char *sep = myprefix == nullstr ? myprefix : spcstr;
12405
12406         for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) {
12407                 for (vp = *vpp ; vp ; vp = vp->next) {
12408                         if ((vp->flags & mask) ^ xor) {
12409                                 char *p;
12410                                 int len;
12411
12412                                 p = strchr(vp->text, '=') + 1;
12413                                 len = p - vp->text;
12414                                 p = single_quote(p);
12415
12416                                 printf("%s%s%.*s%s\n", myprefix, sep, len,
12417                                         vp->text, p);
12418                                 stunalloc(p);
12419                         }
12420                 }
12421         }
12422 }
12423
12424 static struct var **
12425 findvar(struct var **vpp, const char *name)
12426 {
12427         for (; *vpp; vpp = &(*vpp)->next) {
12428                 if (varequal((*vpp)->text, name)) {
12429                         break;
12430                 }
12431         }
12432         return vpp;
12433 }
12434
12435 /*
12436  * Copyright (c) 1999 Herbert Xu <herbert@debian.org>
12437  * This file contains code for the times builtin.
12438  * $Id: ash.c,v 1.49 2002/04/26 23:39:48 andersen Exp $
12439  */
12440 static int timescmd (int argc, char **argv)
12441 {
12442         struct tms buf;
12443         long int clk_tck = sysconf(_SC_CLK_TCK);
12444
12445         times(&buf);
12446         printf("%dm%fs %dm%fs\n%dm%fs %dm%fs\n",
12447                (int) (buf.tms_utime / clk_tck / 60),
12448                ((double) buf.tms_utime) / clk_tck,
12449                (int) (buf.tms_stime / clk_tck / 60),
12450                ((double) buf.tms_stime) / clk_tck,
12451                (int) (buf.tms_cutime / clk_tck / 60),
12452                ((double) buf.tms_cutime) / clk_tck,
12453                (int) (buf.tms_cstime / clk_tck / 60),
12454                ((double) buf.tms_cstime) / clk_tck);
12455         return 0;
12456 }
12457
12458 #ifdef CONFIG_ASH_MATH_SUPPORT
12459 /* The let builtin.  */
12460 int letcmd(int argc, char **argv)
12461 {
12462         int errcode;
12463         long result=0;
12464         if (argc == 2) {
12465                 char *tmp, *expression, p[13];
12466                 expression = strchr(argv[1], '=');
12467                 if (!expression) {
12468                         /* Cannot use 'error()' here, or the return code
12469                          * will be incorrect */
12470                         out2fmt("sh: let: syntax error: \"%s\"\n", argv[1]);
12471                         return 0;
12472                 }
12473                 *expression = '\0';
12474                 tmp = ++expression;
12475                 result = arith(tmp, &errcode);
12476                 if (errcode < 0) {
12477                         /* Cannot use 'error()' here, or the return code
12478                          * will be incorrect */
12479                         out2fmt("sh: let: ");
12480                         if(errcode == -2)
12481                                 out2fmt("divide by zero");
12482                         else
12483                                 out2fmt("syntax error: \"%s=%s\"\n", argv[1], expression);
12484                         return 0;
12485                 }
12486                 snprintf(p, 12, "%ld", result);
12487                 setvar(argv[1], xstrdup(p), 0);
12488         } else if (argc >= 3)
12489                 synerror("invalid operand");
12490         return !result;
12491 }
12492 #endif
12493
12494
12495
12496 /*-
12497  * Copyright (c) 1989, 1991, 1993, 1994
12498  *      The Regents of the University of California.  All rights reserved.
12499  *
12500  * This code is derived from software contributed to Berkeley by
12501  * Kenneth Almquist.
12502  *
12503  * Redistribution and use in source and binary forms, with or without
12504  * modification, are permitted provided that the following conditions
12505  * are met:
12506  * 1. Redistributions of source code must retain the above copyright
12507  *    notice, this list of conditions and the following disclaimer.
12508  * 2. Redistributions in binary form must reproduce the above copyright
12509  *    notice, this list of conditions and the following disclaimer in the
12510  *    documentation and/or other materials provided with the distribution.
12511  *
12512  * 3. <BSD Advertising Clause omitted per the July 22, 1999 licensing change
12513  *              ftp://ftp.cs.berkeley.edu/pub/4bsd/README.Impt.License.Change>
12514  *
12515  * 4. Neither the name of the University nor the names of its contributors
12516  *    may be used to endorse or promote products derived from this software
12517  *    without specific prior written permission.
12518  *
12519  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
12520  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
12521  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
12522  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
12523  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
12524  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
12525  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
12526  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
12527  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
12528  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
12529  * SUCH DAMAGE.
12530  */