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