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