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