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