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