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