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