f218a88d51a3877d76f662a944ad33e7ba0f1579
[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 /* Check for new mail on interactive shells? */
71 #undef ASH_MAIL
72
73 /* Optimize size vs speed as size */
74 #define ASH_OPTIMIZE_FOR_SIZE
75
76 /* Enable this to compile in extra debugging noise.  When debugging is
77  * on, debugging info will be written to $HOME/trace and a quit signal
78  * will generate a core dump. */
79 #undef DEBUG
80
81 /* These are here to work with glibc -- Don't change these... */
82 #undef FNMATCH_BROKEN
83 #undef GLOB_BROKEN
84 #define IFS_BROKEN
85
86 #include <assert.h>
87 #include <stddef.h>
88 #include <ctype.h>
89 #include <dirent.h>
90 #include <errno.h>
91 #include <fcntl.h>
92 #include <limits.h>
93 #include <paths.h>
94 #include <setjmp.h>
95 #include <signal.h>
96 #include <stdarg.h>
97 #include <stdio.h>
98 #include <stdlib.h>
99 #include <string.h>
100 #include <sysexits.h>
101 #include <unistd.h>
102 #include <sys/stat.h>
103 #include <sys/cdefs.h>
104 #include <sys/ioctl.h>
105 #include <sys/param.h>
106 #include <sys/resource.h>
107 #include <sys/time.h>
108 #include <sys/times.h>
109 #include <sys/types.h>
110 #include <sys/wait.h>
111 #include "pwd.h"
112
113
114 #if !defined(FNMATCH_BROKEN)
115 #include <fnmatch.h>
116 #endif
117 #if !defined(GLOB_BROKEN)
118 #include <glob.h>
119 #endif
120
121 #ifdef JOBS
122 #include <termios.h>
123 #endif
124
125 #include "busybox.h"
126 #include "cmdedit.h"
127
128 /*
129  * This file was generated by the mksyntax program.
130  */
131
132 /* Syntax classes */
133 #define CWORD 0                 /* character is nothing special */
134 #define CNL 1                   /* newline character */
135 #define CBACK 2                 /* a backslash character */
136 #define CSQUOTE 3               /* single quote */
137 #define CDQUOTE 4               /* double quote */
138 #define CENDQUOTE 5             /* a terminating quote */
139 #define CBQUOTE 6               /* backwards single quote */
140 #define CVAR 7                  /* a dollar sign */
141 #define CENDVAR 8               /* a '}' character */
142 #define CLP 9                   /* a left paren in arithmetic */
143 #define CRP 10                  /* a right paren in arithmetic */
144 #define CENDFILE 11             /* end of file */
145 #define CCTL 12                 /* like CWORD, except it must be escaped */
146 #define CSPCL 13                /* these terminate a word */
147 #define CIGN 14                 /* character should be ignored */
148
149 #define SYNBASE 130
150 #define PEOF -130
151
152 #define PEOA -129
153
154 #define TEOF 0
155 #define TNL 1
156 #define TREDIR 2
157 #define TWORD 3
158 #define TASSIGN 4
159 #define TSEMI 5
160 #define TBACKGND 6
161 #define TAND 7
162 #define TOR 8
163 #define TPIPE 9
164 #define TLP 10
165 #define TRP 11
166 #define TENDCASE 12
167 #define TENDBQUOTE 13
168 #define TNOT 14
169 #define TCASE 15
170 #define TDO 16
171 #define TDONE 17
172 #define TELIF 18
173 #define TELSE 19
174 #define TESAC 20
175 #define TFI 21
176 #define TFOR 22
177 #define TIF 23
178 #define TIN 24
179 #define TTHEN 25
180 #define TUNTIL 26
181 #define TWHILE 27
182 #define TBEGIN 28
183 #define TEND 29
184
185
186
187 /* control characters in argument strings */
188 #define CTLESC '\201'
189 #define CTLVAR '\202'
190 #define CTLENDVAR '\203'
191 #define CTLBACKQ '\204'
192 #define CTLQUOTE 01             /* ored with CTLBACKQ code if in quotes */
193 /*      CTLBACKQ | CTLQUOTE == '\205' */
194 #define CTLARI  '\206'
195 #define CTLENDARI '\207'
196 #define CTLQUOTEMARK '\210'
197
198
199 #define is_digit(c)     ((c)>='0' && (c)<='9')
200 #define is_name(c)      (((c) < CTLESC || (c) > CTLENDARI) && ((c) == '_' || isalpha((unsigned char) (c))))
201 #define is_in_name(c)   (((c) < CTLESC || (c) > CTLENDARI) && ((c) == '_' || isalnum((unsigned char) (c))))
202
203 /*
204  * is_special(c) evaluates to 1 for c in "!#$*-0123456789?@"; 0 otherwise
205  * (assuming ascii char codes, as the original implementation did)
206  */
207 #define is_special(c) \
208     ( (((unsigned int)c) - 33 < 32) \
209                          && ((0xc1ff920dUL >> (((unsigned int)c) - 33)) & 1))
210
211 #define digit_val(c)    ((c) - '0')
212
213
214 #define _DIAGASSERT(x)
215
216
217
218 #define S_DFL 1                 /* default signal handling (SIG_DFL) */
219 #define S_CATCH 2               /* signal is caught */
220 #define S_IGN 3                 /* signal is ignored (SIG_IGN) */
221 #define S_HARD_IGN 4            /* signal is ignored permenantly */
222 #define S_RESET 5               /* temporary - to reset a hard ignored sig */
223
224
225 /* variable substitution byte (follows CTLVAR) */
226 #define VSTYPE  0x0f            /* type of variable substitution */
227 #define VSNUL   0x10            /* colon--treat the empty string as unset */
228 #define VSQUOTE 0x80            /* inside double quotes--suppress splitting */
229
230 /* values of VSTYPE field */
231 #define VSNORMAL        0x1             /* normal variable:  $var or ${var} */
232 #define VSMINUS         0x2             /* ${var-text} */
233 #define VSPLUS          0x3             /* ${var+text} */
234 #define VSQUESTION      0x4             /* ${var?message} */
235 #define VSASSIGN        0x5             /* ${var=text} */
236 #define VSTRIMLEFT      0x6             /* ${var#pattern} */
237 #define VSTRIMLEFTMAX   0x7             /* ${var##pattern} */
238 #define VSTRIMRIGHT     0x8             /* ${var%pattern} */
239 #define VSTRIMRIGHTMAX  0x9             /* ${var%%pattern} */
240 #define VSLENGTH        0xa             /* ${#var} */
241
242 /* flags passed to redirect */
243 #define REDIR_PUSH 01           /* save previous values of file descriptors */
244 #define REDIR_BACKQ 02          /* save the command output to pipe */
245
246 /*
247  * BSD setjmp saves the signal mask, which violates ANSI C and takes time,
248  * so we use _setjmp instead.
249  */
250
251 #if defined(BSD)
252 #define setjmp(jmploc)  _setjmp(jmploc)
253 #define longjmp(jmploc, val)    _longjmp(jmploc, val)
254 #endif
255
256 /*
257  * Most machines require the value returned from malloc to be aligned
258  * in some way.  The following macro will get this right on many machines.
259  */
260
261 #ifndef ALIGN
262 union align {
263         int i;
264         char *cp;
265 };
266
267 #define ALIGN(nbytes)   (((nbytes) + sizeof(union align) - 1) & ~(sizeof(union align) - 1))
268 #endif
269
270 #ifdef CONFIG_LOCALE_SUPPORT
271 #include <locale.h>
272 static void change_lc_all(const char *value);
273 static void change_lc_ctype(const char *value);
274 #endif
275
276 /*
277  * These macros allow the user to suspend the handling of interrupt signals
278  * over a period of time.  This is similar to SIGHOLD to or sigblock, but
279  * much more efficient and portable.  (But hacking the kernel is so much
280  * more fun than worrying about efficiency and portability. :-))
281  */
282
283 static void onint (void);
284 static volatile int suppressint;
285 static volatile int intpending;
286
287 #define INTOFF suppressint++
288 #ifndef ASH_OPTIMIZE_FOR_SIZE
289 #define INTON { if (--suppressint == 0 && intpending) onint(); }
290 #define FORCEINTON {suppressint = 0; if (intpending) onint();}
291 #else
292 static void __inton (void);
293 static void forceinton (void);
294 #define INTON __inton()
295 #define FORCEINTON forceinton()
296 #endif
297
298 #define CLEAR_PENDING_INT intpending = 0
299 #define int_pending() intpending
300
301
302 typedef void *pointer;
303 #ifndef NULL
304 #define NULL (void *)0
305 #endif
306
307 static inline pointer  ckmalloc (int sz)          { return xmalloc(sz);     }
308 static inline pointer  ckrealloc(void *p, int sz) { return xrealloc(p, sz); }
309 static inline char *   savestr  (const char *s)   { return xstrdup(s);      }
310
311 static pointer stalloc (int);
312 static void stunalloc (pointer);
313 static void ungrabstackstr (char *, char *);
314 static char * growstackstr(void);
315 static char * makestrspace(size_t newlen);
316 static char *sstrdup (const char *);
317
318 /*
319  * Parse trees for commands are allocated in lifo order, so we use a stack
320  * to make this more efficient, and also to avoid all sorts of exception
321  * handling code to handle interrupts in the middle of a parse.
322  *
323  * The size 504 was chosen because the Ultrix malloc handles that size
324  * well.
325  */
326
327 #define MINSIZE 504             /* minimum size of a block */
328
329
330 struct stack_block {
331         struct stack_block *prev;
332         char space[MINSIZE];
333 };
334
335 static struct stack_block stackbase;
336 static struct stack_block *stackp = &stackbase;
337 static struct stackmark *markp;
338 static char *stacknxt = stackbase.space;
339 static int stacknleft = MINSIZE;
340
341
342 #define equal(s1, s2)   (strcmp(s1, s2) == 0)
343
344 #define stackblock() stacknxt
345 #define stackblocksize() stacknleft
346 #define STARTSTACKSTR(p)        p = stackblock(), sstrnleft = stackblocksize()
347
348 #define STPUTC(c, p)    (--sstrnleft >= 0? (*p++ = (c)) : (p = growstackstr(), *p++ = (c)))
349 #define CHECKSTRSPACE(n, p)     { if (sstrnleft < n) p = makestrspace(n); }
350 #define STACKSTRNUL(p)  (sstrnleft == 0? (p = growstackstr(), *p = '\0') : (*p = '\0'))
351
352
353 #define USTPUTC(c, p)   (--sstrnleft, *p++ = (c))
354 #define STUNPUTC(p)     (++sstrnleft, --p)
355 #define STTOPC(p)       p[-1]
356 #define STADJUST(amount, p)     (p += (amount), sstrnleft -= (amount))
357 #define grabstackstr(p) stalloc(stackblocksize() - sstrnleft)
358
359 #define ckfree(p)       free((pointer)(p))
360
361
362 #ifdef DEBUG
363 #define TRACE(param)    trace param
364 typedef union node unode;
365 static void trace (const char *, ...);
366 static void trargs (char **);
367 static void showtree (unode *);
368 static void trputc (int);
369 static void trputs (const char *);
370 static void opentrace (void);
371 #else
372 #define TRACE(param)
373 #endif
374
375 #define NSEMI 0
376 #define NCMD 1
377 #define NPIPE 2
378 #define NREDIR 3
379 #define NBACKGND 4
380 #define NSUBSHELL 5
381 #define NAND 6
382 #define NOR 7
383 #define NIF 8
384 #define NWHILE 9
385 #define NUNTIL 10
386 #define NFOR 11
387 #define NCASE 12
388 #define NCLIST 13
389 #define NDEFUN 14
390 #define NARG 15
391 #define NTO 16
392 #define NFROM 17
393 #define NFROMTO 18
394 #define NAPPEND 19
395 #define NTOOV 20
396 #define NTOFD 21
397 #define NFROMFD 22
398 #define NHERE 23
399 #define NXHERE 24
400 #define NNOT 25
401
402 /*
403  * expandarg() flags
404  */
405 #define EXP_FULL        0x1     /* perform word splitting & file globbing */
406 #define EXP_TILDE       0x2     /* do normal tilde expansion */
407 #define EXP_VARTILDE    0x4     /* expand tildes in an assignment */
408 #define EXP_REDIR       0x8     /* file glob for a redirection (1 match only) */
409 #define EXP_CASE        0x10    /* keeps quotes around for CASE pattern */
410 #define EXP_RECORD      0x20    /* need to record arguments for ifs breakup */
411
412
413 #define NOPTS   16
414
415 static char optet_vals[NOPTS];
416
417 static const char * const optlist[NOPTS] = {
418         "e" "errexit",
419         "f" "noglob",
420         "I" "ignoreeof",
421         "i" "interactive",
422         "m" "monitor",
423         "n" "noexec",
424         "s" "stdin",
425         "x" "xtrace",
426         "v" "verbose",
427         "V" "vi",
428         "E" "emacs",
429         "C" "noclobber",
430         "a" "allexport",
431         "b" "notify",
432         "u" "nounset",
433         "q" "quietprofile"
434 };
435
436 #define optent_name(optent) (optent+1)
437 #define optent_letter(optent) optent[0]
438 #define optent_val(optent) optet_vals[optent]
439
440 #define eflag optent_val(0)
441 #define fflag optent_val(1)
442 #define Iflag optent_val(2)
443 #define iflag optent_val(3)
444 #define mflag optent_val(4)
445 #define nflag optent_val(5)
446 #define sflag optent_val(6)
447 #define xflag optent_val(7)
448 #define vflag optent_val(8)
449 #define Vflag optent_val(9)
450 #define Eflag optent_val(10)
451 #define Cflag optent_val(11)
452 #define aflag optent_val(12)
453 #define bflag optent_val(13)
454 #define uflag optent_val(14)
455 #define qflag optent_val(15)
456
457
458 /* Mode argument to forkshell.  Don't change FORK_FG or FORK_BG. */
459 #define FORK_FG 0
460 #define FORK_BG 1
461 #define FORK_NOJOB 2
462
463
464 struct nbinary {
465       int type;
466       union node *ch1;
467       union node *ch2;
468 };
469
470
471 struct ncmd {
472       int type;
473       int backgnd;
474       union node *assign;
475       union node *args;
476       union node *redirect;
477 };
478
479
480 struct npipe {
481       int type;
482       int backgnd;
483       struct nodelist *cmdlist;
484 };
485
486
487 struct nredir {
488       int type;
489       union node *n;
490       union node *redirect;
491 };
492
493
494 struct nif {
495       int type;
496       union node *test;
497       union node *ifpart;
498       union node *elsepart;
499 };
500
501
502 struct nfor {
503       int type;
504       union node *args;
505       union node *body;
506       char *var;
507 };
508
509
510 struct ncase {
511       int type;
512       union node *expr;
513       union node *cases;
514 };
515
516
517 struct nclist {
518       int type;
519       union node *next;
520       union node *pattern;
521       union node *body;
522 };
523
524
525 struct narg {
526       int type;
527       union node *next;
528       char *text;
529       struct nodelist *backquote;
530 };
531
532
533 struct nfile {
534       int type;
535       union node *next;
536       int fd;
537       union node *fname;
538       char *expfname;
539 };
540
541
542 struct ndup {
543       int type;
544       union node *next;
545       int fd;
546       int dupfd;
547       union node *vname;
548 };
549
550
551 struct nhere {
552       int type;
553       union node *next;
554       int fd;
555       union node *doc;
556 };
557
558
559 struct nnot {
560       int type;
561       union node *com;
562 };
563
564
565 union node {
566       int type;
567       struct nbinary nbinary;
568       struct ncmd ncmd;
569       struct npipe npipe;
570       struct nredir nredir;
571       struct nif nif;
572       struct nfor nfor;
573       struct ncase ncase;
574       struct nclist nclist;
575       struct narg narg;
576       struct nfile nfile;
577       struct ndup ndup;
578       struct nhere nhere;
579       struct nnot nnot;
580 };
581
582
583 struct nodelist {
584         struct nodelist *next;
585         union node *n;
586 };
587
588 struct backcmd {                /* result of evalbackcmd */
589         int fd;                 /* file descriptor to read from */
590         char *buf;              /* buffer */
591         int nleft;              /* number of chars in buffer */
592         struct job *jp;         /* job structure for command */
593 };
594
595 struct cmdentry {
596         int cmdtype;
597         union param {
598                 int index;
599                 union node *func;
600                 const struct builtincmd *cmd;
601         } u;
602 };
603
604 struct strlist {
605         struct strlist *next;
606         char *text;
607 };
608
609
610 struct arglist {
611         struct strlist *list;
612         struct strlist **lastp;
613 };
614
615 struct strpush {
616         struct strpush *prev;   /* preceding string on stack */
617         char *prevstring;
618         int prevnleft;
619 #ifdef ASH_ALIAS
620         struct alias *ap;       /* if push was associated with an alias */
621 #endif
622         char *string;           /* remember the string since it may change */
623 };
624
625 struct parsefile {
626         struct parsefile *prev; /* preceding file on stack */
627         int linno;              /* current line */
628         int fd;                 /* file descriptor (or -1 if string) */
629         int nleft;              /* number of chars left in this line */
630         int lleft;              /* number of chars left in this buffer */
631         char *nextc;            /* next char in buffer */
632         char *buf;              /* input buffer */
633         struct strpush *strpush; /* for pushing strings at this level */
634         struct strpush basestrpush; /* so pushing one is fast */
635 };
636
637 struct stackmark {
638         struct stack_block *stackp;
639         char *stacknxt;
640         int stacknleft;
641         struct stackmark *marknext;
642 };
643
644 struct shparam {
645         int nparam;             /* # of positional parameters (without $0) */
646         unsigned char malloc;   /* if parameter list dynamically allocated */
647         char **p;               /* parameter list */
648         int optind;             /* next parameter to be processed by getopts */
649         int optoff;             /* used by getopts */
650 };
651
652 /*
653  * When commands are first encountered, they are entered in a hash table.
654  * This ensures that a full path search will not have to be done for them
655  * on each invocation.
656  *
657  * We should investigate converting to a linear search, even though that
658  * would make the command name "hash" a misnomer.
659  */
660 #define CMDTABLESIZE 31         /* should be prime */
661 #define ARB 1                   /* actual size determined at run time */
662
663
664
665 struct tblentry {
666         struct tblentry *next;  /* next entry in hash chain */
667         union param param;      /* definition of builtin function */
668         short cmdtype;          /* index identifying command */
669         char rehash;            /* if set, cd done since entry created */
670         char cmdname[ARB];      /* name of command */
671 };
672
673
674 static struct tblentry *cmdtable[CMDTABLESIZE];
675 static int builtinloc = -1;             /* index in path of %builtin, or -1 */
676 static int exerrno = 0;                 /* Last exec error */
677
678
679 static void tryexec (char *, char **, char **);
680 static void printentry (struct tblentry *, int);
681 static void clearcmdentry (int);
682 static struct tblentry *cmdlookup (const char *, int);
683 static void delete_cmd_entry (void);
684 static int path_change (const char *, int *);
685
686
687 static void flushall (void);
688 static void out2fmt (const char *, ...)
689     __attribute__((__format__(__printf__,1,2)));
690 static int xwrite (int, const char *, int);
691
692 static inline void outstr (const char *p, FILE *file) { fputs(p, file); }
693 static void out1str(const char *p) { outstr(p, stdout); }
694 static void out2str(const char *p) { outstr(p, stderr); }
695
696 #ifndef ASH_OPTIMIZE_FOR_SIZE
697 #define out2c(c)        putc((c), stderr)
698 #else
699 static void out2c(int c)           { putc(c, stderr); }
700 #endif
701
702
703 #ifdef ASH_OPTIMIZE_FOR_SIZE
704 #define USE_SIT_FUNCTION
705 #endif
706
707 /* number syntax index */
708 #define  BASESYNTAX  0                  /* not in quotes */
709 #define  DQSYNTAX    1                  /* in double quotes */
710 #define  SQSYNTAX    2                  /* in single quotes */
711 #define  ARISYNTAX   3                  /* in arithmetic */
712
713 static const char S_I_T[][4] = {
714   /*  0 */  { CSPCL,    CIGN,      CIGN,      CIGN     },   /* PEOA */
715   /*  1 */  { CSPCL,    CWORD,     CWORD,     CWORD    },   /* ' ' */
716   /*  2 */  { CNL,      CNL,       CNL,       CNL      },   /* \n */
717   /*  3 */  { CWORD,    CCTL,      CCTL,      CWORD    },   /* !*-/:=?[]~ */
718   /*  4 */  { CDQUOTE,  CENDQUOTE, CWORD,     CDQUOTE  },   /* '"' */
719   /*  5 */  { CVAR,     CVAR,      CWORD,     CVAR     },   /* $ */
720   /*  6 */  { CSQUOTE,  CWORD,     CENDQUOTE, CSQUOTE  },   /* "'" */
721   /*  7 */  { CSPCL,    CWORD,     CWORD,     CLP      },   /* ( */
722   /*  8 */  { CSPCL,    CWORD,     CWORD,     CRP      },   /* ) */
723   /*  9 */  { CBACK,    CBACK,     CCTL,      CBACK    },   /* \ */
724   /* 10 */  { CBQUOTE,  CBQUOTE,   CWORD,     CBQUOTE  },   /* ` */
725   /* 11 */  { CENDVAR,  CENDVAR,   CWORD,     CENDVAR  },   /* } */
726 #ifndef USE_SIT_FUNCTION
727   /* 12 */  { CENDFILE, CENDFILE,  CENDFILE,  CENDFILE },   /* PEOF */
728   /* 13 */  { CWORD,    CWORD,     CWORD,     CWORD    },   /* 0-9A-Za-z */
729   /* 14 */  { CCTL,     CCTL,      CCTL,      CCTL     }    /* CTLESC ... */
730 #endif
731 };
732
733 #ifdef USE_SIT_FUNCTION
734
735 #define U_C(c) ((unsigned char)(c))
736
737 static int SIT(int c, int syntax)
738 {
739         static const char spec_symbls[]="\t\n !\"$&'()*-/:;<=>?[\\]`|}~";
740         static const char syntax_index_table [] = {
741                                 1, 2, 1, 3, 4, 5, 1, 6, /* "\t\n !\"$&'" */
742                                 7, 8, 3, 3, 3, 3, 1, 1, /* "()*-/:;<" */
743                                 3, 1, 3, 3, 9, 3,10, 1, /* "=>?[\\]`|" */
744                                 11,3 }; /* "}~" */
745         const char *s;
746         int indx;
747
748         if(c==PEOF)             /* 2^8+2 */
749                 return CENDFILE;
750         if(c==PEOA)             /* 2^8+1 */
751                 indx = 0;
752          else if(U_C(c)>=U_C(CTLESC) && U_C(c)<=U_C(CTLQUOTEMARK))
753                 return CCTL;
754          else {
755                 s = strchr(spec_symbls, c);
756                 if(s==0)
757                         return CWORD;
758                 indx = syntax_index_table[(s-spec_symbls)];
759         }
760         return S_I_T[indx][syntax];
761 }
762
763 #else  /* USE_SIT_FUNCTION */
764
765 #define SIT(c, syntax) S_I_T[(int)syntax_index_table[((int)c)+SYNBASE]][syntax]
766
767 #define CSPCL_CIGN_CIGN_CIGN                           0
768 #define CSPCL_CWORD_CWORD_CWORD                        1
769 #define CNL_CNL_CNL_CNL                                2
770 #define CWORD_CCTL_CCTL_CWORD                          3
771 #define CDQUOTE_CENDQUOTE_CWORD_CDQUOTE                4
772 #define CVAR_CVAR_CWORD_CVAR                           5
773 #define CSQUOTE_CWORD_CENDQUOTE_CSQUOTE                6
774 #define CSPCL_CWORD_CWORD_CLP                          7
775 #define CSPCL_CWORD_CWORD_CRP                          8
776 #define CBACK_CBACK_CCTL_CBACK                         9
777 #define CBQUOTE_CBQUOTE_CWORD_CBQUOTE                 10
778 #define CENDVAR_CENDVAR_CWORD_CENDVAR                 11
779 #define CENDFILE_CENDFILE_CENDFILE_CENDFILE           12
780 #define CWORD_CWORD_CWORD_CWORD                       13
781 #define CCTL_CCTL_CCTL_CCTL                           14
782
783 static const char syntax_index_table[258] = {
784                  /* BASESYNTAX_DQSYNTAX_SQSYNTAX_ARISYNTAX */
785   /*   0  -130 PEOF */  CENDFILE_CENDFILE_CENDFILE_CENDFILE,
786   /*   1  -129 PEOA */  CSPCL_CIGN_CIGN_CIGN,
787   /*   2  -128 0xff */  CWORD_CWORD_CWORD_CWORD,
788   /*   3  -127      */  CCTL_CCTL_CCTL_CCTL,    /* CTLQUOTEMARK */
789   /*   4  -126      */  CCTL_CCTL_CCTL_CCTL,
790   /*   5  -125      */  CCTL_CCTL_CCTL_CCTL,
791   /*   6  -124      */  CCTL_CCTL_CCTL_CCTL,
792   /*   7  -123      */  CCTL_CCTL_CCTL_CCTL,
793   /*   8  -122      */  CCTL_CCTL_CCTL_CCTL,
794   /*   9  -121      */  CCTL_CCTL_CCTL_CCTL,
795   /*  10  -120      */  CCTL_CCTL_CCTL_CCTL,    /* CTLESC */
796   /*  11  -119      */  CWORD_CWORD_CWORD_CWORD,
797   /*  12  -118      */  CWORD_CWORD_CWORD_CWORD,
798   /*  13  -117      */  CWORD_CWORD_CWORD_CWORD,
799   /*  14  -116      */  CWORD_CWORD_CWORD_CWORD,
800   /*  15  -115      */  CWORD_CWORD_CWORD_CWORD,
801   /*  16  -114      */  CWORD_CWORD_CWORD_CWORD,
802   /*  17  -113      */  CWORD_CWORD_CWORD_CWORD,
803   /*  18  -112      */  CWORD_CWORD_CWORD_CWORD,
804   /*  19  -111      */  CWORD_CWORD_CWORD_CWORD,
805   /*  20  -110      */  CWORD_CWORD_CWORD_CWORD,
806   /*  21  -109      */  CWORD_CWORD_CWORD_CWORD,
807   /*  22  -108      */  CWORD_CWORD_CWORD_CWORD,
808   /*  23  -107      */  CWORD_CWORD_CWORD_CWORD,
809   /*  24  -106      */  CWORD_CWORD_CWORD_CWORD,
810   /*  25  -105      */  CWORD_CWORD_CWORD_CWORD,
811   /*  26  -104      */  CWORD_CWORD_CWORD_CWORD,
812   /*  27  -103      */  CWORD_CWORD_CWORD_CWORD,
813   /*  28  -102      */  CWORD_CWORD_CWORD_CWORD,
814   /*  29  -101      */  CWORD_CWORD_CWORD_CWORD,
815   /*  30  -100      */  CWORD_CWORD_CWORD_CWORD,
816   /*  31   -99      */  CWORD_CWORD_CWORD_CWORD,
817   /*  32   -98      */  CWORD_CWORD_CWORD_CWORD,
818   /*  33   -97      */  CWORD_CWORD_CWORD_CWORD,
819   /*  34   -96      */  CWORD_CWORD_CWORD_CWORD,
820   /*  35   -95      */  CWORD_CWORD_CWORD_CWORD,
821   /*  36   -94      */  CWORD_CWORD_CWORD_CWORD,
822   /*  37   -93      */  CWORD_CWORD_CWORD_CWORD,
823   /*  38   -92      */  CWORD_CWORD_CWORD_CWORD,
824   /*  39   -91      */  CWORD_CWORD_CWORD_CWORD,
825   /*  40   -90      */  CWORD_CWORD_CWORD_CWORD,
826   /*  41   -89      */  CWORD_CWORD_CWORD_CWORD,
827   /*  42   -88      */  CWORD_CWORD_CWORD_CWORD,
828   /*  43   -87      */  CWORD_CWORD_CWORD_CWORD,
829   /*  44   -86      */  CWORD_CWORD_CWORD_CWORD,
830   /*  45   -85      */  CWORD_CWORD_CWORD_CWORD,
831   /*  46   -84      */  CWORD_CWORD_CWORD_CWORD,
832   /*  47   -83      */  CWORD_CWORD_CWORD_CWORD,
833   /*  48   -82      */  CWORD_CWORD_CWORD_CWORD,
834   /*  49   -81      */  CWORD_CWORD_CWORD_CWORD,
835   /*  50   -80      */  CWORD_CWORD_CWORD_CWORD,
836   /*  51   -79      */  CWORD_CWORD_CWORD_CWORD,
837   /*  52   -78      */  CWORD_CWORD_CWORD_CWORD,
838   /*  53   -77      */  CWORD_CWORD_CWORD_CWORD,
839   /*  54   -76      */  CWORD_CWORD_CWORD_CWORD,
840   /*  55   -75      */  CWORD_CWORD_CWORD_CWORD,
841   /*  56   -74      */  CWORD_CWORD_CWORD_CWORD,
842   /*  57   -73      */  CWORD_CWORD_CWORD_CWORD,
843   /*  58   -72      */  CWORD_CWORD_CWORD_CWORD,
844   /*  59   -71      */  CWORD_CWORD_CWORD_CWORD,
845   /*  60   -70      */  CWORD_CWORD_CWORD_CWORD,
846   /*  61   -69      */  CWORD_CWORD_CWORD_CWORD,
847   /*  62   -68      */  CWORD_CWORD_CWORD_CWORD,
848   /*  63   -67      */  CWORD_CWORD_CWORD_CWORD,
849   /*  64   -66      */  CWORD_CWORD_CWORD_CWORD,
850   /*  65   -65      */  CWORD_CWORD_CWORD_CWORD,
851   /*  66   -64      */  CWORD_CWORD_CWORD_CWORD,
852   /*  67   -63      */  CWORD_CWORD_CWORD_CWORD,
853   /*  68   -62      */  CWORD_CWORD_CWORD_CWORD,
854   /*  69   -61      */  CWORD_CWORD_CWORD_CWORD,
855   /*  70   -60      */  CWORD_CWORD_CWORD_CWORD,
856   /*  71   -59      */  CWORD_CWORD_CWORD_CWORD,
857   /*  72   -58      */  CWORD_CWORD_CWORD_CWORD,
858   /*  73   -57      */  CWORD_CWORD_CWORD_CWORD,
859   /*  74   -56      */  CWORD_CWORD_CWORD_CWORD,
860   /*  75   -55      */  CWORD_CWORD_CWORD_CWORD,
861   /*  76   -54      */  CWORD_CWORD_CWORD_CWORD,
862   /*  77   -53      */  CWORD_CWORD_CWORD_CWORD,
863   /*  78   -52      */  CWORD_CWORD_CWORD_CWORD,
864   /*  79   -51      */  CWORD_CWORD_CWORD_CWORD,
865   /*  80   -50      */  CWORD_CWORD_CWORD_CWORD,
866   /*  81   -49      */  CWORD_CWORD_CWORD_CWORD,
867   /*  82   -48      */  CWORD_CWORD_CWORD_CWORD,
868   /*  83   -47      */  CWORD_CWORD_CWORD_CWORD,
869   /*  84   -46      */  CWORD_CWORD_CWORD_CWORD,
870   /*  85   -45      */  CWORD_CWORD_CWORD_CWORD,
871   /*  86   -44      */  CWORD_CWORD_CWORD_CWORD,
872   /*  87   -43      */  CWORD_CWORD_CWORD_CWORD,
873   /*  88   -42      */  CWORD_CWORD_CWORD_CWORD,
874   /*  89   -41      */  CWORD_CWORD_CWORD_CWORD,
875   /*  90   -40      */  CWORD_CWORD_CWORD_CWORD,
876   /*  91   -39      */  CWORD_CWORD_CWORD_CWORD,
877   /*  92   -38      */  CWORD_CWORD_CWORD_CWORD,
878   /*  93   -37      */  CWORD_CWORD_CWORD_CWORD,
879   /*  94   -36      */  CWORD_CWORD_CWORD_CWORD,
880   /*  95   -35      */  CWORD_CWORD_CWORD_CWORD,
881   /*  96   -34      */  CWORD_CWORD_CWORD_CWORD,
882   /*  97   -33      */  CWORD_CWORD_CWORD_CWORD,
883   /*  98   -32      */  CWORD_CWORD_CWORD_CWORD,
884   /*  99   -31      */  CWORD_CWORD_CWORD_CWORD,
885   /* 100   -30      */  CWORD_CWORD_CWORD_CWORD,
886   /* 101   -29      */  CWORD_CWORD_CWORD_CWORD,
887   /* 102   -28      */  CWORD_CWORD_CWORD_CWORD,
888   /* 103   -27      */  CWORD_CWORD_CWORD_CWORD,
889   /* 104   -26      */  CWORD_CWORD_CWORD_CWORD,
890   /* 105   -25      */  CWORD_CWORD_CWORD_CWORD,
891   /* 106   -24      */  CWORD_CWORD_CWORD_CWORD,
892   /* 107   -23      */  CWORD_CWORD_CWORD_CWORD,
893   /* 108   -22      */  CWORD_CWORD_CWORD_CWORD,
894   /* 109   -21      */  CWORD_CWORD_CWORD_CWORD,
895   /* 110   -20      */  CWORD_CWORD_CWORD_CWORD,
896   /* 111   -19      */  CWORD_CWORD_CWORD_CWORD,
897   /* 112   -18      */  CWORD_CWORD_CWORD_CWORD,
898   /* 113   -17      */  CWORD_CWORD_CWORD_CWORD,
899   /* 114   -16      */  CWORD_CWORD_CWORD_CWORD,
900   /* 115   -15      */  CWORD_CWORD_CWORD_CWORD,
901   /* 116   -14      */  CWORD_CWORD_CWORD_CWORD,
902   /* 117   -13      */  CWORD_CWORD_CWORD_CWORD,
903   /* 118   -12      */  CWORD_CWORD_CWORD_CWORD,
904   /* 119   -11      */  CWORD_CWORD_CWORD_CWORD,
905   /* 120   -10      */  CWORD_CWORD_CWORD_CWORD,
906   /* 121    -9      */  CWORD_CWORD_CWORD_CWORD,
907   /* 122    -8      */  CWORD_CWORD_CWORD_CWORD,
908   /* 123    -7      */  CWORD_CWORD_CWORD_CWORD,
909   /* 124    -6      */  CWORD_CWORD_CWORD_CWORD,
910   /* 125    -5      */  CWORD_CWORD_CWORD_CWORD,
911   /* 126    -4      */  CWORD_CWORD_CWORD_CWORD,
912   /* 127    -3      */  CWORD_CWORD_CWORD_CWORD,
913   /* 128    -2      */  CWORD_CWORD_CWORD_CWORD,
914   /* 129    -1      */  CWORD_CWORD_CWORD_CWORD,
915   /* 130     0      */  CWORD_CWORD_CWORD_CWORD,
916   /* 131     1      */  CWORD_CWORD_CWORD_CWORD,
917   /* 132     2      */  CWORD_CWORD_CWORD_CWORD,
918   /* 133     3      */  CWORD_CWORD_CWORD_CWORD,
919   /* 134     4      */  CWORD_CWORD_CWORD_CWORD,
920   /* 135     5      */  CWORD_CWORD_CWORD_CWORD,
921   /* 136     6      */  CWORD_CWORD_CWORD_CWORD,
922   /* 137     7      */  CWORD_CWORD_CWORD_CWORD,
923   /* 138     8      */  CWORD_CWORD_CWORD_CWORD,
924   /* 139     9 "\t" */  CSPCL_CWORD_CWORD_CWORD,
925   /* 140    10 "\n" */  CNL_CNL_CNL_CNL,
926   /* 141    11      */  CWORD_CWORD_CWORD_CWORD,
927   /* 142    12      */  CWORD_CWORD_CWORD_CWORD,
928   /* 143    13      */  CWORD_CWORD_CWORD_CWORD,
929   /* 144    14      */  CWORD_CWORD_CWORD_CWORD,
930   /* 145    15      */  CWORD_CWORD_CWORD_CWORD,
931   /* 146    16      */  CWORD_CWORD_CWORD_CWORD,
932   /* 147    17      */  CWORD_CWORD_CWORD_CWORD,
933   /* 148    18      */  CWORD_CWORD_CWORD_CWORD,
934   /* 149    19      */  CWORD_CWORD_CWORD_CWORD,
935   /* 150    20      */  CWORD_CWORD_CWORD_CWORD,
936   /* 151    21      */  CWORD_CWORD_CWORD_CWORD,
937   /* 152    22      */  CWORD_CWORD_CWORD_CWORD,
938   /* 153    23      */  CWORD_CWORD_CWORD_CWORD,
939   /* 154    24      */  CWORD_CWORD_CWORD_CWORD,
940   /* 155    25      */  CWORD_CWORD_CWORD_CWORD,
941   /* 156    26      */  CWORD_CWORD_CWORD_CWORD,
942   /* 157    27      */  CWORD_CWORD_CWORD_CWORD,
943   /* 158    28      */  CWORD_CWORD_CWORD_CWORD,
944   /* 159    29      */  CWORD_CWORD_CWORD_CWORD,
945   /* 160    30      */  CWORD_CWORD_CWORD_CWORD,
946   /* 161    31      */  CWORD_CWORD_CWORD_CWORD,
947   /* 162    32  " " */  CSPCL_CWORD_CWORD_CWORD,
948   /* 163    33  "!" */  CWORD_CCTL_CCTL_CWORD,
949   /* 164    34  """ */  CDQUOTE_CENDQUOTE_CWORD_CDQUOTE,
950   /* 165    35  "#" */  CWORD_CWORD_CWORD_CWORD,
951   /* 166    36  "$" */  CVAR_CVAR_CWORD_CVAR,
952   /* 167    37  "%" */  CWORD_CWORD_CWORD_CWORD,
953   /* 168    38  "&" */  CSPCL_CWORD_CWORD_CWORD,
954   /* 169    39  "'" */  CSQUOTE_CWORD_CENDQUOTE_CSQUOTE,
955   /* 170    40  "(" */  CSPCL_CWORD_CWORD_CLP,
956   /* 171    41  ")" */  CSPCL_CWORD_CWORD_CRP,
957   /* 172    42  "*" */  CWORD_CCTL_CCTL_CWORD,
958   /* 173    43  "+" */  CWORD_CWORD_CWORD_CWORD,
959   /* 174    44  "," */  CWORD_CWORD_CWORD_CWORD,
960   /* 175    45  "-" */  CWORD_CCTL_CCTL_CWORD,
961   /* 176    46  "." */  CWORD_CWORD_CWORD_CWORD,
962   /* 177    47  "/" */  CWORD_CCTL_CCTL_CWORD,
963   /* 178    48  "0" */  CWORD_CWORD_CWORD_CWORD,
964   /* 179    49  "1" */  CWORD_CWORD_CWORD_CWORD,
965   /* 180    50  "2" */  CWORD_CWORD_CWORD_CWORD,
966   /* 181    51  "3" */  CWORD_CWORD_CWORD_CWORD,
967   /* 182    52  "4" */  CWORD_CWORD_CWORD_CWORD,
968   /* 183    53  "5" */  CWORD_CWORD_CWORD_CWORD,
969   /* 184    54  "6" */  CWORD_CWORD_CWORD_CWORD,
970   /* 185    55  "7" */  CWORD_CWORD_CWORD_CWORD,
971   /* 186    56  "8" */  CWORD_CWORD_CWORD_CWORD,
972   /* 187    57  "9" */  CWORD_CWORD_CWORD_CWORD,
973   /* 188    58  ":" */  CWORD_CCTL_CCTL_CWORD,
974   /* 189    59  ";" */  CSPCL_CWORD_CWORD_CWORD,
975   /* 190    60  "<" */  CSPCL_CWORD_CWORD_CWORD,
976   /* 191    61  "=" */  CWORD_CCTL_CCTL_CWORD,
977   /* 192    62  ">" */  CSPCL_CWORD_CWORD_CWORD,
978   /* 193    63  "?" */  CWORD_CCTL_CCTL_CWORD,
979   /* 194    64  "@" */  CWORD_CWORD_CWORD_CWORD,
980   /* 195    65  "A" */  CWORD_CWORD_CWORD_CWORD,
981   /* 196    66  "B" */  CWORD_CWORD_CWORD_CWORD,
982   /* 197    67  "C" */  CWORD_CWORD_CWORD_CWORD,
983   /* 198    68  "D" */  CWORD_CWORD_CWORD_CWORD,
984   /* 199    69  "E" */  CWORD_CWORD_CWORD_CWORD,
985   /* 200    70  "F" */  CWORD_CWORD_CWORD_CWORD,
986   /* 201    71  "G" */  CWORD_CWORD_CWORD_CWORD,
987   /* 202    72  "H" */  CWORD_CWORD_CWORD_CWORD,
988   /* 203    73  "I" */  CWORD_CWORD_CWORD_CWORD,
989   /* 204    74  "J" */  CWORD_CWORD_CWORD_CWORD,
990   /* 205    75  "K" */  CWORD_CWORD_CWORD_CWORD,
991   /* 206    76  "L" */  CWORD_CWORD_CWORD_CWORD,
992   /* 207    77  "M" */  CWORD_CWORD_CWORD_CWORD,
993   /* 208    78  "N" */  CWORD_CWORD_CWORD_CWORD,
994   /* 209    79  "O" */  CWORD_CWORD_CWORD_CWORD,
995   /* 210    80  "P" */  CWORD_CWORD_CWORD_CWORD,
996   /* 211    81  "Q" */  CWORD_CWORD_CWORD_CWORD,
997   /* 212    82  "R" */  CWORD_CWORD_CWORD_CWORD,
998   /* 213    83  "S" */  CWORD_CWORD_CWORD_CWORD,
999   /* 214    84  "T" */  CWORD_CWORD_CWORD_CWORD,
1000   /* 215    85  "U" */  CWORD_CWORD_CWORD_CWORD,
1001   /* 216    86  "V" */  CWORD_CWORD_CWORD_CWORD,
1002   /* 217    87  "W" */  CWORD_CWORD_CWORD_CWORD,
1003   /* 218    88  "X" */  CWORD_CWORD_CWORD_CWORD,
1004   /* 219    89  "Y" */  CWORD_CWORD_CWORD_CWORD,
1005   /* 220    90  "Z" */  CWORD_CWORD_CWORD_CWORD,
1006   /* 221    91  "[" */  CWORD_CCTL_CCTL_CWORD,
1007   /* 222    92  "\" */  CBACK_CBACK_CCTL_CBACK,
1008   /* 223    93  "]" */  CWORD_CCTL_CCTL_CWORD,
1009   /* 224    94  "^" */  CWORD_CWORD_CWORD_CWORD,
1010   /* 225    95  "_" */  CWORD_CWORD_CWORD_CWORD,
1011   /* 226    96  "`" */  CBQUOTE_CBQUOTE_CWORD_CBQUOTE,
1012   /* 227    97  "a" */  CWORD_CWORD_CWORD_CWORD,
1013   /* 228    98  "b" */  CWORD_CWORD_CWORD_CWORD,
1014   /* 229    99  "c" */  CWORD_CWORD_CWORD_CWORD,
1015   /* 230   100  "d" */  CWORD_CWORD_CWORD_CWORD,
1016   /* 231   101  "e" */  CWORD_CWORD_CWORD_CWORD,
1017   /* 232   102  "f" */  CWORD_CWORD_CWORD_CWORD,
1018   /* 233   103  "g" */  CWORD_CWORD_CWORD_CWORD,
1019   /* 234   104  "h" */  CWORD_CWORD_CWORD_CWORD,
1020   /* 235   105  "i" */  CWORD_CWORD_CWORD_CWORD,
1021   /* 236   106  "j" */  CWORD_CWORD_CWORD_CWORD,
1022   /* 237   107  "k" */  CWORD_CWORD_CWORD_CWORD,
1023   /* 238   108  "l" */  CWORD_CWORD_CWORD_CWORD,
1024   /* 239   109  "m" */  CWORD_CWORD_CWORD_CWORD,
1025   /* 240   110  "n" */  CWORD_CWORD_CWORD_CWORD,
1026   /* 241   111  "o" */  CWORD_CWORD_CWORD_CWORD,
1027   /* 242   112  "p" */  CWORD_CWORD_CWORD_CWORD,
1028   /* 243   113  "q" */  CWORD_CWORD_CWORD_CWORD,
1029   /* 244   114  "r" */  CWORD_CWORD_CWORD_CWORD,
1030   /* 245   115  "s" */  CWORD_CWORD_CWORD_CWORD,
1031   /* 246   116  "t" */  CWORD_CWORD_CWORD_CWORD,
1032   /* 247   117  "u" */  CWORD_CWORD_CWORD_CWORD,
1033   /* 248   118  "v" */  CWORD_CWORD_CWORD_CWORD,
1034   /* 249   119  "w" */  CWORD_CWORD_CWORD_CWORD,
1035   /* 250   120  "x" */  CWORD_CWORD_CWORD_CWORD,
1036   /* 251   121  "y" */  CWORD_CWORD_CWORD_CWORD,
1037   /* 252   122  "z" */  CWORD_CWORD_CWORD_CWORD,
1038   /* 253   123  "{" */  CWORD_CWORD_CWORD_CWORD,
1039   /* 254   124  "|" */  CSPCL_CWORD_CWORD_CWORD,
1040   /* 255   125  "}" */  CENDVAR_CENDVAR_CWORD_CENDVAR,
1041   /* 256   126  "~" */  CWORD_CCTL_CCTL_CWORD,
1042   /* 257   127      */  CWORD_CWORD_CWORD_CWORD,
1043 };
1044
1045 #endif  /* USE_SIT_FUNCTION */
1046
1047
1048 /* first char is indicating which tokens mark the end of a list */
1049 static const char *const tokname_array[] = {
1050         "\1end of file",
1051         "\0newline",
1052         "\0redirection",
1053         "\0word",
1054         "\0assignment",
1055         "\0;",
1056         "\0&",
1057         "\0&&",
1058         "\0||",
1059         "\0|",
1060         "\0(",
1061         "\1)",
1062         "\1;;",
1063         "\1`",
1064 #define KWDOFFSET 14
1065         /* the following are keywords */
1066         "\0!",
1067         "\0case",
1068         "\1do",
1069         "\1done",
1070         "\1elif",
1071         "\1else",
1072         "\1esac",
1073         "\1fi",
1074         "\0for",
1075         "\0if",
1076         "\0in",
1077         "\1then",
1078         "\0until",
1079         "\0while",
1080         "\0{",
1081         "\1}",
1082 };
1083
1084 static const char *tokname(int tok)
1085 {
1086         static char buf[16];
1087
1088         if(tok>=TSEMI)
1089                 buf[0] = '"';
1090         sprintf(buf+(tok>=TSEMI), "%s%c",
1091                         tokname_array[tok]+1, (tok>=TSEMI ? '"' : 0));
1092         return buf;
1093 }
1094
1095 static int plinno = 1;          /* input line number */
1096
1097 static int parselleft;          /* copy of parsefile->lleft */
1098
1099 static struct parsefile basepf; /* top level input file */
1100 static char basebuf[BUFSIZ];    /* buffer for top level input file */
1101 static struct parsefile *parsefile = &basepf;  /* current input file */
1102
1103 /*
1104  * NEOF is returned by parsecmd when it encounters an end of file.  It
1105  * must be distinct from NULL, so we use the address of a variable that
1106  * happens to be handy.
1107  */
1108
1109 static int tokpushback;         /* last token pushed back */
1110 #define NEOF ((union node *)&tokpushback)
1111 static int checkkwd;            /* 1 == check for kwds, 2 == also eat newlines */
1112
1113
1114 static void error (const char *, ...) __attribute__((__noreturn__));
1115 static void exerror (int, const char *, ...) __attribute__((__noreturn__));
1116 static void shellexec (char **, char **, const char *, int)
1117     __attribute__((noreturn));
1118 static void exitshell (int) __attribute__((noreturn));
1119
1120 static int  goodname(const char *);
1121 static void ignoresig (int);
1122 static void onsig (int);
1123 static void dotrap (void);
1124 static int  decode_signal (const char *, int);
1125
1126 static void shprocvar(void);
1127 static void deletefuncs(void);
1128 static void setparam (char **);
1129 static void freeparam (volatile struct shparam *);
1130
1131 /* reasons for skipping commands (see comment on breakcmd routine) */
1132 #define SKIPBREAK       1
1133 #define SKIPCONT        2
1134 #define SKIPFUNC        3
1135 #define SKIPFILE        4
1136
1137 /* values of cmdtype */
1138 #define CMDUNKNOWN -1           /* no entry in table for command */
1139 #define CMDNORMAL 0             /* command is an executable program */
1140 #define CMDBUILTIN 1            /* command is a shell builtin */
1141 #define CMDFUNCTION 2           /* command is a shell function */
1142
1143 #define DO_ERR  1               /* find_command prints errors */
1144 #define DO_ABS  2               /* find_command checks absolute paths */
1145 #define DO_NOFUN        4       /* find_command ignores functions */
1146 #define DO_BRUTE        8       /* find_command ignores hash table */
1147
1148 /*
1149  * Shell variables.
1150  */
1151
1152 /* flags */
1153 #define VEXPORT         0x01    /* variable is exported */
1154 #define VREADONLY       0x02    /* variable cannot be modified */
1155 #define VSTRFIXED       0x04    /* variable struct is staticly allocated */
1156 #define VTEXTFIXED      0x08    /* text is staticly allocated */
1157 #define VSTACK          0x10    /* text is allocated on the stack */
1158 #define VUNSET          0x20    /* the variable is not set */
1159 #define VNOFUNC         0x40    /* don't call the callback function */
1160
1161
1162 struct var {
1163         struct var *next;               /* next entry in hash list */
1164         int flags;                      /* flags are defined above */
1165         char *text;                     /* name=value */
1166         void (*func) (const char *);
1167                                         /* function to be called when  */
1168                                         /* the variable gets set/unset */
1169 };
1170
1171 struct localvar {
1172         struct localvar *next;          /* next local variable in list */
1173         struct var *vp;                 /* the variable that was made local */
1174         int flags;                      /* saved flags */
1175         char *text;                     /* saved text */
1176 };
1177
1178
1179 #if defined(__GLIBC__) && __GLIBC__ >= 2 && !defined(FNMATCH_BROKEN)
1180 #define rmescapes(p) _rmescapes((p), 0)
1181 static char *_rmescapes (char *, int);
1182 #else
1183 static void rmescapes (char *);
1184 #endif
1185
1186 static int  casematch (union node *, const char *);
1187 static void clearredir(void);
1188 static void popstring(void);
1189 static void readcmdfile (const char *);
1190
1191 static int number (const char *);
1192 static int is_number (const char *, int *num);
1193 static char *single_quote (const char *);
1194 static int nextopt (const char *);
1195
1196 static void redirect (union node *, int);
1197 static void popredir (void);
1198 static int dup_as_newfd (int, int);
1199
1200 static void changepath(const char *newval);
1201 static void getoptsreset(const char *value);
1202
1203
1204 static int parsenleft;                  /* copy of parsefile->nleft */
1205 static char *parsenextc;                /* copy of parsefile->nextc */
1206 static int rootpid;     /* pid of main shell */
1207 static int rootshell;   /* true if we aren't a child of the main shell */
1208
1209 static const char spcstr[] = " ";
1210 static const char snlfmt[] = "%s\n";
1211
1212 static int sstrnleft;
1213 static int herefd = -1;
1214
1215 static struct localvar *localvars;
1216
1217 static struct var vifs;
1218 static struct var vmail;
1219 static struct var vmpath;
1220 static struct var vpath;
1221 static struct var vps1;
1222 static struct var vps2;
1223 static struct var voptind;
1224 #ifdef CONFIG_LOCALE_SUPPORT
1225 static struct var vlc_all;
1226 static struct var vlc_ctype;
1227 #endif
1228
1229 struct varinit {
1230         struct var *var;
1231         int flags;
1232         const char *text;
1233         void (*func) (const char *);
1234 };
1235
1236 static const char defpathvar[] =
1237         "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin";
1238 #define defpath (defpathvar + 5)
1239
1240 #ifdef IFS_BROKEN
1241 static const char defifsvar[] = "IFS= \t\n";
1242 #define defifs (defifsvar + 4)
1243 #else
1244 static const char defifs[] = " \t\n";
1245 #endif
1246
1247 static const struct varinit varinit[] = {
1248 #ifdef IFS_BROKEN
1249         { &vifs,        VSTRFIXED|VTEXTFIXED,           defifsvar,
1250 #else
1251         { &vifs,        VSTRFIXED|VTEXTFIXED|VUNSET,    "IFS=",
1252 #endif
1253           NULL },
1254         { &vmail,       VSTRFIXED|VTEXTFIXED|VUNSET,    "MAIL=",
1255           NULL },
1256         { &vmpath,      VSTRFIXED|VTEXTFIXED|VUNSET,    "MAILPATH=",
1257           NULL },
1258         { &vpath,       VSTRFIXED|VTEXTFIXED,           defpathvar,
1259           changepath },
1260         /*
1261          * vps1 depends on uid
1262          */
1263         { &vps2,        VSTRFIXED|VTEXTFIXED,           "PS2=> ",
1264           NULL },
1265         { &voptind,     VSTRFIXED|VTEXTFIXED,           "OPTIND=1",
1266           getoptsreset },
1267 #ifdef CONFIG_LOCALE_SUPPORT
1268         { &vlc_all,     VSTRFIXED|VTEXTFIXED|VUNSET,    "LC_ALL=",
1269           change_lc_all },
1270         { &vlc_ctype,   VSTRFIXED|VTEXTFIXED|VUNSET,    "LC_CTYPE=",
1271           change_lc_ctype },
1272 #endif
1273         { NULL, 0,                              NULL,
1274           NULL }
1275 };
1276
1277 #define VTABSIZE 39
1278
1279 static struct var *vartab[VTABSIZE];
1280
1281 /*
1282  * The following macros access the values of the above variables.
1283  * They have to skip over the name.  They return the null string
1284  * for unset variables.
1285  */
1286
1287 #define ifsval()        (vifs.text + 4)
1288 #define ifsset()        ((vifs.flags & VUNSET) == 0)
1289 #define mailval()       (vmail.text + 5)
1290 #define mpathval()      (vmpath.text + 9)
1291 #define pathval()       (vpath.text + 5)
1292 #define ps1val()        (vps1.text + 4)
1293 #define ps2val()        (vps2.text + 4)
1294 #define optindval()     (voptind.text + 7)
1295
1296 #define mpathset()      ((vmpath.flags & VUNSET) == 0)
1297
1298 static void initvar (void);
1299 static void setvar (const char *, const char *, int);
1300 static void setvareq (char *, int);
1301 static void listsetvar (struct strlist *);
1302 static const char *lookupvar (const char *);
1303 static const char *bltinlookup (const char *);
1304 static char **environment (void);
1305 static int showvarscmd (int, char **);
1306 static void mklocal (char *);
1307 static void poplocalvars (void);
1308 static int unsetvar (const char *);
1309 static int varequal (const char *, const char *);
1310
1311
1312 static char *arg0;                      /* value of $0 */
1313 static struct shparam shellparam;       /* current positional parameters */
1314 static char **argptr;                   /* argument list for builtin commands */
1315 static char *optionarg;                 /* set by nextopt (like getopt) */
1316 static char *optptr;                    /* used by nextopt */
1317 static char *minusc;                    /* argument to -c option */
1318
1319
1320 #ifdef ASH_ALIAS
1321
1322 #define ALIASINUSE      1
1323 #define ALIASDEAD       2
1324
1325 #define ATABSIZE 39
1326
1327 struct alias {
1328         struct alias *next;
1329         char *name;
1330         char *val;
1331         int flag;
1332 };
1333
1334 static struct alias *atab[ATABSIZE];
1335
1336 static void setalias (char *, char *);
1337 static struct alias **hashalias (const char *);
1338 static struct alias *freealias (struct alias *);
1339 static struct alias **__lookupalias (const char *);
1340
1341 static void
1342 setalias(name, val)
1343         char *name, *val;
1344 {
1345         struct alias *ap, **app;
1346
1347         app = __lookupalias(name);
1348         ap = *app;
1349         INTOFF;
1350         if (ap) {
1351                 if (!(ap->flag & ALIASINUSE)) {
1352                         ckfree(ap->val);
1353                 }
1354                 ap->val = savestr(val);
1355                 ap->flag &= ~ALIASDEAD;
1356         } else {
1357                 /* not found */
1358                 ap = ckmalloc(sizeof (struct alias));
1359                 ap->name = savestr(name);
1360                 ap->val = savestr(val);
1361                 ap->flag = 0;
1362                 ap->next = 0;
1363                 *app = ap;
1364         }
1365         INTON;
1366 }
1367
1368 static int
1369 unalias(char *name)
1370 {
1371         struct alias **app;
1372
1373         app = __lookupalias(name);
1374
1375         if (*app) {
1376                 INTOFF;
1377                 *app = freealias(*app);
1378                 INTON;
1379                 return (0);
1380         }
1381
1382         return (1);
1383 }
1384
1385 static void
1386 rmaliases(void)
1387 {
1388         struct alias *ap, **app;
1389         int i;
1390
1391         INTOFF;
1392         for (i = 0; i < ATABSIZE; i++) {
1393                 app = &atab[i];
1394                 for (ap = *app; ap; ap = *app) {
1395                         *app = freealias(*app);
1396                         if (ap == *app) {
1397                                 app = &ap->next;
1398                         }
1399                 }
1400         }
1401         INTON;
1402 }
1403
1404 static void
1405 printalias(const struct alias *ap) {
1406         char *p;
1407
1408         p = single_quote(ap->val);
1409         printf("alias %s=%s\n", ap->name, p);
1410         stunalloc(p);
1411 }
1412
1413
1414 /*
1415  * TODO - sort output
1416  */
1417 static int
1418 aliascmd(int argc, char **argv)
1419 {
1420         char *n, *v;
1421         int ret = 0;
1422         struct alias *ap;
1423
1424         if (argc == 1) {
1425                 int i;
1426
1427                 for (i = 0; i < ATABSIZE; i++)
1428                         for (ap = atab[i]; ap; ap = ap->next) {
1429                                 printalias(ap);
1430                         }
1431                 return (0);
1432         }
1433         while ((n = *++argv) != NULL) {
1434                 if ((v = strchr(n+1, '=')) == NULL) { /* n+1: funny ksh stuff */
1435                         if ((ap = *__lookupalias(n)) == NULL) {
1436                                 out2fmt("%s: %s not found\n", "alias", n);
1437                                 ret = 1;
1438                         } else
1439                                 printalias(ap);
1440                 }
1441                 else {
1442                         *v++ = '\0';
1443                         setalias(n, v);
1444                 }
1445         }
1446
1447         return (ret);
1448 }
1449
1450 static int
1451 unaliascmd(int argc, char **argv)
1452 {
1453         int i;
1454
1455         while ((i = nextopt("a")) != '\0') {
1456                 if (i == 'a') {
1457                         rmaliases();
1458                         return (0);
1459                 }
1460         }
1461         for (i = 0; *argptr; argptr++) {
1462                 if (unalias(*argptr)) {
1463                         out2fmt("%s: %s not found\n", "unalias", *argptr);
1464                         i = 1;
1465                 }
1466         }
1467
1468         return (i);
1469 }
1470
1471 static struct alias **
1472 hashalias(p)
1473         const char *p;
1474         {
1475         unsigned int hashval;
1476
1477         hashval = *p << 4;
1478         while (*p)
1479                 hashval+= *p++;
1480         return &atab[hashval % ATABSIZE];
1481 }
1482
1483 static struct alias *
1484 freealias(struct alias *ap) {
1485         struct alias *next;
1486
1487         if (ap->flag & ALIASINUSE) {
1488                 ap->flag |= ALIASDEAD;
1489                 return ap;
1490         }
1491
1492         next = ap->next;
1493         ckfree(ap->name);
1494         ckfree(ap->val);
1495         ckfree(ap);
1496         return next;
1497 }
1498
1499
1500 static struct alias **
1501 __lookupalias(const char *name) {
1502         struct alias **app = hashalias(name);
1503
1504         for (; *app; app = &(*app)->next) {
1505                 if (equal(name, (*app)->name)) {
1506                         break;
1507                 }
1508         }
1509
1510         return app;
1511 }
1512 #endif
1513
1514 #ifdef ASH_MATH_SUPPORT
1515 /* The generated file arith.c has been replaced with a custom hand
1516  * written implementation written by Aaron Lehmann <aaronl@vitelus.com>.
1517  * This is now part of libbb, so that it can be used by all the shells
1518  * in busybox. */
1519 static void expari (int);
1520 #endif
1521
1522 static char *trap[NSIG];                /* trap handler commands */
1523 static char sigmode[NSIG - 1];  /* current value of signal */
1524 static char gotsig[NSIG - 1];           /* indicates specified signal received */
1525 static int pendingsigs;                 /* indicates some signal received */
1526
1527 /*
1528  * This file was generated by the mkbuiltins program.
1529  */
1530
1531 #ifdef JOBS
1532 static int bgcmd (int, char **);
1533 static int fgcmd (int, char **);
1534 static int killcmd (int, char **);
1535 #endif
1536 static int bltincmd (int, char **);
1537 static int cdcmd (int, char **);
1538 static int breakcmd (int, char **);
1539 #ifdef ASH_CMDCMD
1540 static int commandcmd (int, char **);
1541 #endif
1542 static int dotcmd (int, char **);
1543 static int evalcmd (int, char **);
1544 static int execcmd (int, char **);
1545 static int exitcmd (int, char **);
1546 static int exportcmd (int, char **);
1547 static int histcmd (int, char **);
1548 static int hashcmd (int, char **);
1549 static int helpcmd (int, char **);
1550 static int jobscmd (int, char **);
1551 static int localcmd (int, char **);
1552 static int pwdcmd (int, char **);
1553 static int readcmd (int, char **);
1554 static int returncmd (int, char **);
1555 static int setcmd (int, char **);
1556 static int setvarcmd (int, char **);
1557 static int shiftcmd (int, char **);
1558 static int trapcmd (int, char **);
1559 static int umaskcmd (int, char **);
1560 #ifdef ASH_ALIAS
1561 static int aliascmd (int, char **);
1562 static int unaliascmd (int, char **);
1563 #endif
1564 static int unsetcmd (int, char **);
1565 static int waitcmd (int, char **);
1566 static int ulimitcmd (int, char **);
1567 static int timescmd (int, char **);
1568 #ifdef ASH_MATH_SUPPORT
1569 static int letcmd (int, char **);
1570 #endif
1571 static int typecmd (int, char **);
1572 #ifdef ASH_GETOPTS
1573 static int getoptscmd (int, char **);
1574 #endif
1575
1576 #ifndef CONFIG_TRUE
1577 static int true_main (int, char **);
1578 #endif
1579 #ifndef CONFIG_FALSE
1580 static int false_main (int, char **);
1581 #endif
1582
1583 static void     setpwd (const char *, int);
1584
1585
1586 #define BUILTIN_NOSPEC  "0"
1587 #define BUILTIN_SPECIAL "1"
1588 #define BUILTIN_REGULAR "2"
1589 #define BUILTIN_ASSIGN  "4"
1590 #define BUILTIN_SPEC_ASSG  "5"
1591 #define BUILTIN_REG_ASSG   "6"
1592
1593 #define IS_BUILTIN_SPECIAL(builtincmd) ((builtincmd)->name[0] & 1)
1594 #define IS_BUILTIN_REGULAR(builtincmd) ((builtincmd)->name[0] & 2)
1595 #define IS_BUILTIN_ASSIGN(builtincmd) ((builtincmd)->name[0] & 4)
1596
1597 struct builtincmd {
1598         const char *name;
1599         int (*const builtinfunc) (int, char **);
1600         //unsigned flags;
1601 };
1602
1603
1604 /* It is CRUCIAL that this listing be kept in ascii order, otherwise
1605  * the binary search in find_builtin() will stop working. If you value
1606  * your kneecaps, you'll be sure to *make sure* that any changes made
1607  * to this array result in the listing remaining in ascii order. You
1608  * have been warned.
1609  */
1610 static const struct builtincmd builtincmds[] = {
1611         { BUILTIN_SPECIAL   ".", dotcmd },    /* first, see declare DOTCMD */
1612         { BUILTIN_SPECIAL   ":", true_main },
1613 #ifdef ASH_ALIAS
1614         { BUILTIN_REG_ASSG  "alias", aliascmd },
1615 #endif
1616 #ifdef JOBS
1617         { BUILTIN_REGULAR   "bg", bgcmd },
1618 #endif
1619         { BUILTIN_SPECIAL   "break", breakcmd },
1620         { BUILTIN_SPECIAL   "builtin", bltincmd },
1621         { BUILTIN_REGULAR   "cd", cdcmd },
1622         { BUILTIN_NOSPEC    "chdir", cdcmd },
1623 #ifdef ASH_CMDCMD
1624         { BUILTIN_REGULAR   "command", commandcmd },
1625 #endif
1626         { BUILTIN_SPECIAL   "continue", breakcmd },
1627         { BUILTIN_SPECIAL   "eval", evalcmd },
1628         { BUILTIN_SPECIAL   "exec", execcmd },
1629         { BUILTIN_SPECIAL   "exit", exitcmd },
1630         { BUILTIN_SPEC_ASSG "export", exportcmd },
1631         { BUILTIN_REGULAR   "false", false_main },
1632         { BUILTIN_REGULAR   "fc", histcmd },
1633 #ifdef JOBS
1634         { BUILTIN_REGULAR   "fg", fgcmd },
1635 #endif
1636 #ifdef ASH_GETOPTS
1637         { BUILTIN_REGULAR   "getopts", getoptscmd },
1638 #endif
1639         { BUILTIN_NOSPEC    "hash", hashcmd },
1640         { BUILTIN_NOSPEC    "help", helpcmd },
1641         { BUILTIN_REGULAR   "jobs", jobscmd },
1642 #ifdef JOBS
1643         { BUILTIN_REGULAR   "kill", killcmd },
1644 #endif
1645 #ifdef ASH_MATH_SUPPORT
1646         { BUILTIN_REGULAR    "let", letcmd },
1647 #endif
1648         { BUILTIN_ASSIGN    "local", localcmd },
1649         { BUILTIN_NOSPEC    "pwd", pwdcmd },
1650         { BUILTIN_REGULAR   "read", readcmd },
1651         { BUILTIN_SPEC_ASSG "readonly", exportcmd },
1652         { BUILTIN_SPECIAL   "return", returncmd },
1653         { BUILTIN_SPECIAL   "set", setcmd },
1654         { BUILTIN_NOSPEC    "setvar", setvarcmd },
1655         { BUILTIN_SPECIAL   "shift", shiftcmd },
1656         { BUILTIN_SPECIAL   "times", timescmd },
1657         { BUILTIN_SPECIAL   "trap", trapcmd },
1658         { BUILTIN_REGULAR   "true", true_main },
1659         { BUILTIN_NOSPEC    "type", typecmd },
1660         { BUILTIN_NOSPEC    "ulimit", ulimitcmd },
1661         { BUILTIN_REGULAR   "umask", umaskcmd },
1662 #ifdef ASH_ALIAS
1663         { BUILTIN_REGULAR   "unalias", unaliascmd },
1664 #endif
1665         { BUILTIN_SPECIAL   "unset", unsetcmd },
1666         { BUILTIN_REGULAR   "wait", waitcmd },
1667 };
1668 #define NUMBUILTINS  (sizeof (builtincmds) / sizeof (struct builtincmd) )
1669
1670 #define DOTCMD &builtincmds[0]
1671 static struct builtincmd *BLTINCMD;
1672 static struct builtincmd *EXECCMD;
1673 static struct builtincmd *EVALCMD;
1674
1675 /* states */
1676 #define JOBSTOPPED 1            /* all procs are stopped */
1677 #define JOBDONE 2               /* all procs are completed */
1678
1679 /*
1680  * A job structure contains information about a job.  A job is either a
1681  * single process or a set of processes contained in a pipeline.  In the
1682  * latter case, pidlist will be non-NULL, and will point to a -1 terminated
1683  * array of pids.
1684  */
1685
1686 struct procstat {
1687         pid_t pid;              /* process id */
1688         int status;             /* status flags (defined above) */
1689         char *cmd;              /* text of command being run */
1690 };
1691
1692
1693 static int job_warning;         /* user was warned about stopped jobs */
1694
1695 #ifdef JOBS
1696 static void setjobctl(int enable);
1697 #else
1698 #define setjobctl(on)   /* do nothing */
1699 #endif
1700
1701
1702 struct job {
1703         struct procstat ps0;    /* status of process */
1704         struct procstat *ps;    /* status or processes when more than one */
1705         short nprocs;           /* number of processes */
1706         short pgrp;             /* process group of this job */
1707         char state;             /* true if job is finished */
1708         char used;              /* true if this entry is in used */
1709         char changed;           /* true if status has changed */
1710 #ifdef JOBS
1711         char jobctl;            /* job running under job control */
1712 #endif
1713 };
1714
1715 static struct job *jobtab;      /* array of jobs */
1716 static int njobs;               /* size of array */
1717 static int backgndpid = -1;     /* pid of last background process */
1718 #ifdef JOBS
1719 static int initialpgrp;         /* pgrp of shell on invocation */
1720 static int curjob;              /* current job */
1721 static int jobctl;
1722 #endif
1723 static int intreceived;
1724
1725 static struct job *makejob (const union node *, int);
1726 static int forkshell (struct job *, const union node *, int);
1727 static int waitforjob (struct job *);
1728
1729 static int docd (char *, int);
1730 static void updatepwd (const char *);
1731 static void getpwd (void);
1732
1733 static char *padvance (const char **, const char *);
1734
1735 static char nullstr[1];         /* zero length string */
1736 static char *curdir = nullstr;          /* current working directory */
1737
1738 static int
1739 cdcmd(argc, argv)
1740         int argc;
1741         char **argv;
1742 {
1743         const char *dest;
1744         const char *path;
1745         char *p;
1746         struct stat statb;
1747         int print = 0;
1748
1749         nextopt(nullstr);
1750         if ((dest = *argptr) == NULL && (dest = bltinlookup("HOME")) == NULL)
1751                 error("HOME not set");
1752         if (*dest == '\0')
1753                 dest = ".";
1754         if (dest[0] == '-' && dest[1] == '\0') {
1755                 dest = bltinlookup("OLDPWD");
1756                 if (!dest || !*dest) {
1757                         dest = curdir;
1758                 }
1759                 print = 1;
1760                 if (dest)
1761                         print = 1;
1762                 else
1763                         dest = ".";
1764         }
1765         if (*dest == '/' || (path = bltinlookup("CDPATH")) == NULL)
1766                 path = nullstr;
1767         while ((p = padvance(&path, dest)) != NULL) {
1768                 if (stat(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) {
1769                         if (!print) {
1770                                 /*
1771                                  * XXX - rethink
1772                                  */
1773                                 if (p[0] == '.' && p[1] == '/' && p[2] != '\0')
1774                                         p += 2;
1775                                 print = strcmp(p, dest);
1776                         }
1777                         if (docd(p, print) >= 0)
1778                                 return 0;
1779
1780                 }
1781         }
1782         error("can't cd to %s", dest);
1783         /* NOTREACHED */
1784 }
1785
1786
1787 /*
1788  * Actually do the chdir.  In an interactive shell, print the
1789  * directory name if "print" is nonzero.
1790  */
1791
1792 static int
1793 docd(char *dest, int print)
1794 {
1795         TRACE(("docd(\"%s\", %d) called\n", dest, print));
1796         INTOFF;
1797         if (chdir(dest) < 0) {
1798                 INTON;
1799                 return -1;
1800         }
1801         updatepwd(dest);
1802         INTON;
1803         if (print && iflag)
1804                 printf(snlfmt, curdir);
1805         return 0;
1806 }
1807
1808
1809 /*
1810  * Update curdir (the name of the current directory) in response to a
1811  * cd command.  We also call hashcd to let the routines in exec.c know
1812  * that the current directory has changed.
1813  */
1814
1815 static void hashcd (void);
1816
1817 static void
1818 updatepwd(const char *dir)
1819 {
1820         hashcd();                               /* update command hash table */
1821
1822         /* If our argument is NULL, we don't know the current directory */
1823         if (dir == NULL || curdir == nullstr)  {
1824                 setpwd(0, 1);
1825                 return;
1826         }
1827         setpwd(dir, 1);
1828 }
1829
1830
1831 static int
1832 pwdcmd(int argc, char **argv)
1833 {
1834         printf(snlfmt, curdir);
1835         return 0;
1836 }
1837
1838 /* Ask system the current directory */
1839 static void
1840 getpwd(void)
1841 {
1842         curdir = xgetcwd(0);
1843         if(curdir==0)
1844                 curdir = nullstr;
1845 }
1846
1847 static void
1848 setpwd(const char *val, int setold)
1849 {
1850         char *cated = NULL;
1851
1852         if (setold) {
1853                 setvar("OLDPWD", curdir, VEXPORT);
1854         }
1855         INTOFF;
1856         if (curdir != nullstr) {
1857                 if(val!=NULL && *val != '/')
1858                         val = cated = concat_path_file(curdir, val);
1859                 free(curdir);
1860         }
1861         if (!val)
1862                 getpwd();
1863          else
1864                 curdir = simplify_path(val);
1865         free(cated);
1866         INTON;
1867         setvar("PWD", curdir, VEXPORT);
1868 }
1869
1870 /*
1871  * Errors and exceptions.
1872  */
1873
1874 /*
1875  * Code to handle exceptions in C.
1876  */
1877
1878 /*
1879  * We enclose jmp_buf in a structure so that we can declare pointers to
1880  * jump locations.  The global variable handler contains the location to
1881  * jump to when an exception occurs, and the global variable exception
1882  * contains a code identifying the exeception.  To implement nested
1883  * exception handlers, the user should save the value of handler on entry
1884  * to an inner scope, set handler to point to a jmploc structure for the
1885  * inner scope, and restore handler on exit from the scope.
1886  */
1887
1888 struct jmploc {
1889         jmp_buf loc;
1890 };
1891
1892 /* exceptions */
1893 #define EXINT 0         /* SIGINT received */
1894 #define EXERROR 1       /* a generic error */
1895 #define EXSHELLPROC 2   /* execute a shell procedure */
1896 #define EXEXEC 3        /* command execution failed */
1897
1898 static struct jmploc *handler;
1899 static int exception;
1900
1901 static void exverror (int, const char *, va_list)
1902     __attribute__((__noreturn__));
1903
1904 /*
1905  * Called to raise an exception.  Since C doesn't include exceptions, we
1906  * just do a longjmp to the exception handler.  The type of exception is
1907  * stored in the global variable "exception".
1908  */
1909
1910 static void exraise (int) __attribute__((__noreturn__));
1911
1912 static void
1913 exraise(int e)
1914 {
1915 #ifdef DEBUG
1916         if (handler == NULL)
1917                 abort();
1918 #endif
1919         flushall();
1920         exception = e;
1921         longjmp(handler->loc, 1);
1922 }
1923
1924
1925 /*
1926  * Called from trap.c when a SIGINT is received.  (If the user specifies
1927  * that SIGINT is to be trapped or ignored using the trap builtin, then
1928  * this routine is not called.)  Suppressint is nonzero when interrupts
1929  * are held using the INTOFF macro.  The call to _exit is necessary because
1930  * there is a short period after a fork before the signal handlers are
1931  * set to the appropriate value for the child.  (The test for iflag is
1932  * just defensive programming.)
1933  */
1934
1935 static void
1936 onint(void) {
1937         sigset_t mysigset;
1938
1939         if (suppressint) {
1940                 intpending++;
1941                 return;
1942         }
1943         intpending = 0;
1944         sigemptyset(&mysigset);
1945         sigprocmask(SIG_SETMASK, &mysigset, NULL);
1946         if (rootshell && iflag)
1947                 exraise(EXINT);
1948         else {
1949                 signal(SIGINT, SIG_DFL);
1950                 raise(SIGINT);
1951         }
1952         /* NOTREACHED */
1953 }
1954
1955
1956 static char *commandname;       /* currently executing command */
1957
1958 /*
1959  * Exverror is called to raise the error exception.  If the first argument
1960  * is not NULL then error prints an error message using printf style
1961  * formatting.  It then raises the error exception.
1962  */
1963 static void
1964 exverror(int cond, const char *msg, va_list ap)
1965 {
1966         CLEAR_PENDING_INT;
1967         INTOFF;
1968
1969 #ifdef DEBUG
1970         if (msg)
1971                 TRACE(("exverror(%d, \"%s\") pid=%d\n", cond, msg, getpid()));
1972         else
1973                 TRACE(("exverror(%d, NULL) pid=%d\n", cond, getpid()));
1974 #endif
1975         if (msg) {
1976                 if (commandname)
1977                         out2fmt("%s: ", commandname);
1978                 vfprintf(stderr, msg, ap);
1979                 out2c('\n');
1980         }
1981         exraise(cond);
1982         /* NOTREACHED */
1983 }
1984
1985
1986 static void
1987 error(const char *msg, ...)
1988 {
1989         va_list ap;
1990         va_start(ap, msg);
1991         exverror(EXERROR, msg, ap);
1992         /* NOTREACHED */
1993         va_end(ap);
1994 }
1995
1996
1997 static void
1998 exerror(int cond, const char *msg, ...)
1999 {
2000         va_list ap;
2001         va_start(ap, msg);
2002         exverror(cond, msg, ap);
2003         /* NOTREACHED */
2004         va_end(ap);
2005 }
2006
2007
2008
2009 /*
2010  * Table of error messages.
2011  */
2012
2013 struct errname {
2014         short errcode;          /* error number */
2015         char  action;           /* operation which encountered the error */
2016 };
2017
2018 /*
2019  * Types of operations (passed to the errmsg routine).
2020  */
2021
2022 #define E_OPEN 01       /* opening a file */
2023 #define E_CREAT 02      /* creating a file */
2024 #define E_EXEC 04       /* executing a program */
2025
2026 #define ALL (E_OPEN|E_CREAT|E_EXEC)
2027
2028 static const struct errname errormsg[] = {
2029         { EINTR,        ALL     },
2030         { EACCES,       ALL     },
2031         { EIO,          ALL     },
2032         { ENOENT,       E_OPEN  },
2033         { ENOENT,       E_CREAT },
2034         { ENOENT,       E_EXEC  },
2035         { ENOTDIR,      E_OPEN  },
2036         { ENOTDIR,      E_CREAT },
2037         { ENOTDIR,      E_EXEC  },
2038         { EISDIR,       ALL     },
2039         { EEXIST,       E_CREAT },
2040 #ifdef EMFILE
2041         { EMFILE,       ALL     },
2042 #endif
2043         { ENFILE,       ALL     },
2044         { ENOSPC,       ALL     },
2045 #ifdef EDQUOT
2046         { EDQUOT,       ALL     },
2047 #endif
2048 #ifdef ENOSR
2049         { ENOSR,        ALL     },
2050 #endif
2051         { ENXIO,        ALL     },
2052         { EROFS,        ALL     },
2053         { ETXTBSY,      ALL     },
2054 #ifdef EAGAIN
2055         { EAGAIN,       E_EXEC  },
2056 #endif
2057         { ENOMEM,       ALL     },
2058 #ifdef ENOLINK
2059         { ENOLINK,      ALL     },
2060 #endif
2061 #ifdef EMULTIHOP
2062         { EMULTIHOP,    ALL     },
2063 #endif
2064 #ifdef ECOMM
2065         { ECOMM,        ALL     },
2066 #endif
2067 #ifdef ESTALE
2068         { ESTALE,       ALL     },
2069 #endif
2070 #ifdef ETIMEDOUT
2071         { ETIMEDOUT,    ALL     },
2072 #endif
2073 #ifdef ELOOP
2074         { ELOOP,        ALL     },
2075 #endif
2076         { E2BIG,        E_EXEC  },
2077 #ifdef ELIBACC
2078         { ELIBACC,      E_EXEC  },
2079 #endif
2080 };
2081
2082 #define ERRNAME_SIZE (sizeof(errormsg)/sizeof(struct errname))
2083
2084 /*
2085  * Return a string describing an error.  The returned string may be a
2086  * pointer to a static buffer that will be overwritten on the next call.
2087  * Action describes the operation that got the error.
2088  */
2089
2090 static const char *
2091 errmsg(int e, int action)
2092 {
2093         struct errname const *ep;
2094         static char buf[12];
2095
2096         for (ep = errormsg ; ep < errormsg+ERRNAME_SIZE; ep++) {
2097                 if (ep->errcode == e && (ep->action & action) != 0)
2098                         return strerror(e);
2099         }
2100
2101         snprintf(buf, sizeof buf, "error %d", e);
2102         return buf;
2103 }
2104
2105
2106 #ifdef ASH_OPTIMIZE_FOR_SIZE
2107 static void
2108 __inton() {
2109         if (--suppressint == 0 && intpending) {
2110                 onint();
2111         }
2112 }
2113 static void forceinton (void) {
2114         suppressint = 0;
2115         if (intpending)
2116                 onint();
2117 }
2118 #endif
2119
2120 /* flags in argument to evaltree */
2121 #define EV_EXIT 01              /* exit after evaluating tree */
2122 #define EV_TESTED 02            /* exit status is checked; ignore -e flag */
2123 #define EV_BACKCMD 04           /* command executing within back quotes */
2124
2125 static int evalskip;                    /* set if we are skipping commands */
2126 static int skipcount;           /* number of levels to skip */
2127 static int loopnest;            /* current loop nesting level */
2128 static int funcnest;                    /* depth of function calls */
2129
2130
2131 static struct strlist *cmdenviron;      /* environment for builtin command */
2132 static int exitstatus;                  /* exit status of last command */
2133 static int oexitstatus;         /* saved exit status */
2134
2135 static void evalsubshell (const union node *, int);
2136 static void expredir (union node *);
2137 static void prehash (union node *);
2138 static void eprintlist (struct strlist *);
2139
2140 static union node *parsecmd(int);
2141 /*
2142  * Called to reset things after an exception.
2143  */
2144
2145 /*
2146  * The eval commmand.
2147  */
2148 static void evalstring (char *, int);
2149
2150 static int
2151 evalcmd(argc, argv)
2152         int argc;
2153         char **argv;
2154 {
2155         char *p;
2156         char *concat;
2157         char **ap;
2158
2159         if (argc > 1) {
2160                 p = argv[1];
2161                 if (argc > 2) {
2162                         STARTSTACKSTR(concat);
2163                         ap = argv + 2;
2164                         for (;;) {
2165                                 while (*p)
2166                                         STPUTC(*p++, concat);
2167                                 if ((p = *ap++) == NULL)
2168                                         break;
2169                                 STPUTC(' ', concat);
2170                         }
2171                         STPUTC('\0', concat);
2172                         p = grabstackstr(concat);
2173                 }
2174                 evalstring(p, EV_TESTED);
2175         }
2176         return exitstatus;
2177 }
2178
2179 /*
2180  * Execute a command or commands contained in a string.
2181  */
2182
2183 static void evaltree (union node *, int);
2184 static void setinputstring (char *);
2185 static void popfile (void);
2186 static void setstackmark(struct stackmark *mark);
2187 static void popstackmark(struct stackmark *mark);
2188
2189
2190 static void
2191 evalstring(char *s, int flag)
2192 {
2193         union node *n;
2194         struct stackmark smark;
2195
2196         setstackmark(&smark);
2197         setinputstring(s);
2198         while ((n = parsecmd(0)) != NEOF) {
2199                 evaltree(n, flag);
2200                 popstackmark(&smark);
2201         }
2202         popfile();
2203         popstackmark(&smark);
2204 }
2205
2206 static struct builtincmd *find_builtin (const char *);
2207 static void expandarg (union node *, struct arglist *, int);
2208 static void calcsize (const union node *);
2209 static union node *copynode (const union node *);
2210
2211 /*
2212  * Make a copy of a parse tree.
2213  */
2214
2215 static int     funcblocksize;           /* size of structures in function */
2216 static int     funcstringsize;          /* size of strings in node */
2217 static pointer funcblock;              /* block to allocate function from */
2218 static char   *funcstring;              /* block to allocate strings from */
2219
2220
2221 static inline union node *
2222 copyfunc(union node *n)
2223 {
2224         if (n == NULL)
2225                 return NULL;
2226         funcblocksize = 0;
2227         funcstringsize = 0;
2228         calcsize(n);
2229         funcblock = ckmalloc(funcblocksize + funcstringsize);
2230         funcstring = (char *) funcblock + funcblocksize;
2231         return copynode(n);
2232 }
2233
2234 /*
2235  * Free a parse tree.
2236  */
2237
2238 static void
2239 freefunc(union node *n)
2240 {
2241         if (n)
2242                 ckfree(n);
2243 }
2244
2245
2246 /*
2247  * Add a new command entry, replacing any existing command entry for
2248  * the same name.
2249  */
2250
2251 static inline void
2252 addcmdentry(char *name, struct cmdentry *entry)
2253 {
2254         struct tblentry *cmdp;
2255
2256         INTOFF;
2257         cmdp = cmdlookup(name, 1);
2258         if (cmdp->cmdtype == CMDFUNCTION) {
2259                 freefunc(cmdp->param.func);
2260         }
2261         cmdp->cmdtype = entry->cmdtype;
2262         cmdp->param = entry->u;
2263         INTON;
2264 }
2265
2266 static inline void
2267 evalloop(const union node *n, int flags)
2268 {
2269         int status;
2270
2271         loopnest++;
2272         status = 0;
2273         for (;;) {
2274                 evaltree(n->nbinary.ch1, EV_TESTED);
2275                 if (evalskip) {
2276 skipping:         if (evalskip == SKIPCONT && --skipcount <= 0) {
2277                                 evalskip = 0;
2278                                 continue;
2279                         }
2280                         if (evalskip == SKIPBREAK && --skipcount <= 0)
2281                                 evalskip = 0;
2282                         break;
2283                 }
2284                 if (n->type == NWHILE) {
2285                         if (exitstatus != 0)
2286                                 break;
2287                 } else {
2288                         if (exitstatus == 0)
2289                                 break;
2290                 }
2291                 evaltree(n->nbinary.ch2, flags & EV_TESTED);
2292                 status = exitstatus;
2293                 if (evalskip)
2294                         goto skipping;
2295         }
2296         loopnest--;
2297         exitstatus = status;
2298 }
2299
2300 static void
2301 evalfor(const union node *n, int flags)
2302 {
2303         struct arglist arglist;
2304         union node *argp;
2305         struct strlist *sp;
2306         struct stackmark smark;
2307
2308         setstackmark(&smark);
2309         arglist.lastp = &arglist.list;
2310         for (argp = n->nfor.args ; argp ; argp = argp->narg.next) {
2311                 oexitstatus = exitstatus;
2312                 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE | EXP_RECORD);
2313                 if (evalskip)
2314                         goto out;
2315         }
2316         *arglist.lastp = NULL;
2317
2318         exitstatus = 0;
2319         loopnest++;
2320         for (sp = arglist.list ; sp ; sp = sp->next) {
2321                 setvar(n->nfor.var, sp->text, 0);
2322                 evaltree(n->nfor.body, flags & EV_TESTED);
2323                 if (evalskip) {
2324                         if (evalskip == SKIPCONT && --skipcount <= 0) {
2325                                 evalskip = 0;
2326                                 continue;
2327                         }
2328                         if (evalskip == SKIPBREAK && --skipcount <= 0)
2329                                 evalskip = 0;
2330                         break;
2331                 }
2332         }
2333         loopnest--;
2334 out:
2335         popstackmark(&smark);
2336 }
2337
2338 static inline void
2339 evalcase(const union node *n, int flags)
2340 {
2341         union node *cp;
2342         union node *patp;
2343         struct arglist arglist;
2344         struct stackmark smark;
2345
2346         setstackmark(&smark);
2347         arglist.lastp = &arglist.list;
2348         oexitstatus = exitstatus;
2349         expandarg(n->ncase.expr, &arglist, EXP_TILDE);
2350         for (cp = n->ncase.cases ; cp && evalskip == 0 ; cp = cp->nclist.next) {
2351                 for (patp = cp->nclist.pattern ; patp ; patp = patp->narg.next) {
2352                         if (casematch(patp, arglist.list->text)) {
2353                                 if (evalskip == 0) {
2354                                         evaltree(cp->nclist.body, flags);
2355                                 }
2356                                 goto out;
2357                         }
2358                 }
2359         }
2360 out:
2361         popstackmark(&smark);
2362 }
2363
2364 /*
2365  * Evaluate a pipeline.  All the processes in the pipeline are children
2366  * of the process creating the pipeline.  (This differs from some versions
2367  * of the shell, which make the last process in a pipeline the parent
2368  * of all the rest.)
2369  */
2370
2371 static inline void evalpipe(union node *n)
2372 {
2373         struct job *jp;
2374         struct nodelist *lp;
2375         int pipelen;
2376         int prevfd;
2377         int pip[2];
2378
2379         TRACE(("evalpipe(0x%lx) called\n", (long)n));
2380         pipelen = 0;
2381         for (lp = n->npipe.cmdlist ; lp ; lp = lp->next)
2382                 pipelen++;
2383         INTOFF;
2384         jp = makejob(n, pipelen);
2385         prevfd = -1;
2386         for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {
2387                 prehash(lp->n);
2388                 pip[1] = -1;
2389                 if (lp->next) {
2390                         if (pipe(pip) < 0) {
2391                                 close(prevfd);
2392                                 error("Pipe call failed");
2393                         }
2394                 }
2395                 if (forkshell(jp, lp->n, n->npipe.backgnd) == 0) {
2396                         INTON;
2397                         if (prevfd > 0) {
2398                                 close(0);
2399                                 dup_as_newfd(prevfd, 0);
2400                                 close(prevfd);
2401                                 if (pip[0] == 0) {
2402                                         pip[0] = -1;
2403                                 }
2404                         }
2405                         if (pip[1] >= 0) {
2406                                 if (pip[0] >= 0) {
2407                                         close(pip[0]);
2408                                 }
2409                                 if (pip[1] != 1) {
2410                                         close(1);
2411                                         dup_as_newfd(pip[1], 1);
2412                                         close(pip[1]);
2413                                 }
2414                         }
2415                         evaltree(lp->n, EV_EXIT);
2416                 }
2417                 if (prevfd >= 0)
2418                         close(prevfd);
2419                 prevfd = pip[0];
2420                 close(pip[1]);
2421         }
2422         INTON;
2423         if (n->npipe.backgnd == 0) {
2424                 INTOFF;
2425                 exitstatus = waitforjob(jp);
2426                 TRACE(("evalpipe:  job done exit status %d\n", exitstatus));
2427                 INTON;
2428         }
2429 }
2430
2431 static void find_command (const char *, struct cmdentry *, int, const char *);
2432
2433 static int
2434 isassignment(const char *word) {
2435         if (!is_name(*word)) {
2436                 return 0;
2437         }
2438         do {
2439                 word++;
2440         } while (is_in_name(*word));
2441         return *word == '=';
2442 }
2443
2444
2445 static void
2446 evalcommand(union node *cmd, int flags)
2447 {
2448         struct stackmark smark;
2449         union node *argp;
2450         struct arglist arglist;
2451         struct arglist varlist;
2452         char **argv;
2453         int argc;
2454         char **envp;
2455         struct strlist *sp;
2456         int mode;
2457         struct cmdentry cmdentry;
2458         struct job *jp;
2459         char *volatile savecmdname;
2460         volatile struct shparam saveparam;
2461         struct localvar *volatile savelocalvars;
2462         volatile int e;
2463         char *lastarg;
2464         const char *path;
2465         const struct builtincmd *firstbltin;
2466         struct jmploc *volatile savehandler;
2467         struct jmploc jmploc;
2468 #if __GNUC__
2469         /* Avoid longjmp clobbering */
2470         (void) &argv;
2471         (void) &argc;
2472         (void) &lastarg;
2473         (void) &flags;
2474 #endif
2475
2476         /* First expand the arguments. */
2477         TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
2478         setstackmark(&smark);
2479         arglist.lastp = &arglist.list;
2480         varlist.lastp = &varlist.list;
2481         arglist.list = 0;
2482         oexitstatus = exitstatus;
2483         exitstatus = 0;
2484         path = pathval();
2485         for (argp = cmd->ncmd.assign; argp; argp = argp->narg.next) {
2486                 expandarg(argp, &varlist, EXP_VARTILDE);
2487         }
2488         for (
2489                 argp = cmd->ncmd.args; argp && !arglist.list;
2490                 argp = argp->narg.next
2491         ) {
2492                 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
2493         }
2494         if (argp) {
2495                 struct builtincmd *bcmd;
2496                 int pseudovarflag;
2497                 bcmd = find_builtin(arglist.list->text);
2498                 pseudovarflag = bcmd && IS_BUILTIN_ASSIGN(bcmd);
2499                 for (; argp; argp = argp->narg.next) {
2500                         if (pseudovarflag && isassignment(argp->narg.text)) {
2501                                 expandarg(argp, &arglist, EXP_VARTILDE);
2502                                 continue;
2503                         }
2504                         expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
2505                 }
2506         }
2507         *arglist.lastp = NULL;
2508         *varlist.lastp = NULL;
2509         expredir(cmd->ncmd.redirect);
2510         argc = 0;
2511         for (sp = arglist.list ; sp ; sp = sp->next)
2512                 argc++;
2513         argv = stalloc(sizeof (char *) * (argc + 1));
2514
2515         for (sp = arglist.list ; sp ; sp = sp->next) {
2516                 TRACE(("evalcommand arg: %s\n", sp->text));
2517                 *argv++ = sp->text;
2518         }
2519         *argv = NULL;
2520         lastarg = NULL;
2521         if (iflag && funcnest == 0 && argc > 0)
2522                 lastarg = argv[-1];
2523         argv -= argc;
2524
2525         /* Print the command if xflag is set. */
2526         if (xflag) {
2527                 out2c('+');
2528                 eprintlist(varlist.list);
2529                 eprintlist(arglist.list);
2530                 out2c('\n');
2531         }
2532
2533         /* Now locate the command. */
2534         if (argc == 0) {
2535                 cmdentry.cmdtype = CMDBUILTIN;
2536                 firstbltin = cmdentry.u.cmd = BLTINCMD;
2537         } else {
2538                 const char *oldpath;
2539                 int findflag = DO_ERR;
2540                 int oldfindflag;
2541
2542                 /*
2543                  * Modify the command lookup path, if a PATH= assignment
2544                  * is present
2545                  */
2546                 for (sp = varlist.list ; sp ; sp = sp->next)
2547                         if (varequal(sp->text, defpathvar)) {
2548                                 path = sp->text + 5;
2549                                 findflag |= DO_BRUTE;
2550                         }
2551                 oldpath = path;
2552                 oldfindflag = findflag;
2553                 firstbltin = 0;
2554                 for(;;) {
2555                         find_command(argv[0], &cmdentry, findflag, path);
2556                         if (cmdentry.cmdtype == CMDUNKNOWN) {   /* command not found */
2557                                 exitstatus = 127;
2558                                 goto out;
2559                         }
2560                         /* implement bltin and command here */
2561                         if (cmdentry.cmdtype != CMDBUILTIN) {
2562                                 break;
2563                         }
2564                         if (!firstbltin) {
2565                                 firstbltin = cmdentry.u.cmd;
2566                         }
2567                         if (cmdentry.u.cmd == BLTINCMD) {
2568                                 for(;;) {
2569                                         struct builtincmd *bcmd;
2570
2571                                         argv++;
2572                                         if (--argc == 0)
2573                                                 goto found;
2574                                         if (!(bcmd = find_builtin(*argv))) {
2575                                                 out2fmt("%s: not found\n", *argv);
2576                                                 exitstatus = 127;
2577                                                 goto out;
2578                                         }
2579                                         cmdentry.u.cmd = bcmd;
2580                                         if (bcmd != BLTINCMD)
2581                                                 break;
2582                                 }
2583                         }
2584                         if (cmdentry.u.cmd == find_builtin("command")) {
2585                                 argv++;
2586                                 if (--argc == 0) {
2587                                         goto found;
2588                                 }
2589                                 if (*argv[0] == '-') {
2590                                         if (!equal(argv[0], "-p")) {
2591                                                 argv--;
2592                                                 argc++;
2593                                                 break;
2594                                         }
2595                                         argv++;
2596                                         if (--argc == 0) {
2597                                                 goto found;
2598                                         }
2599                                         path = defpath;
2600                                         findflag |= DO_BRUTE;
2601                                 } else {
2602                                         path = oldpath;
2603                                         findflag = oldfindflag;
2604                                 }
2605                                 findflag |= DO_NOFUN;
2606                                 continue;
2607                         }
2608 found:
2609                         break;
2610                 }
2611         }
2612
2613         /* Fork off a child process if necessary. */
2614         if (cmd->ncmd.backgnd
2615          || (cmdentry.cmdtype == CMDNORMAL && (flags & EV_EXIT) == 0)
2616         ) {
2617                 jp = makejob(cmd, 1);
2618                 mode = cmd->ncmd.backgnd;
2619                 if (forkshell(jp, cmd, mode) != 0)
2620                         goto parent;    /* at end of routine */
2621                 flags |= EV_EXIT;
2622         }
2623
2624         /* This is the child process if a fork occurred. */
2625         /* Execute the command. */
2626         if (cmdentry.cmdtype == CMDFUNCTION) {
2627 #ifdef DEBUG
2628                 trputs("Shell function:  ");  trargs(argv);
2629 #endif
2630                 exitstatus = oexitstatus;
2631                 redirect(cmd->ncmd.redirect, REDIR_PUSH);
2632                 saveparam = shellparam;
2633                 shellparam.malloc = 0;
2634                 shellparam.nparam = argc - 1;
2635                 shellparam.p = argv + 1;
2636                 INTOFF;
2637                 savelocalvars = localvars;
2638                 localvars = NULL;
2639                 INTON;
2640                 if (setjmp(jmploc.loc)) {
2641                         if (exception == EXSHELLPROC) {
2642                                 freeparam((volatile struct shparam *)
2643                                     &saveparam);
2644                         } else {
2645                                 saveparam.optind = shellparam.optind;
2646                                 saveparam.optoff = shellparam.optoff;
2647                                 freeparam(&shellparam);
2648                                 shellparam = saveparam;
2649                         }
2650                         poplocalvars();
2651                         localvars = savelocalvars;
2652                         handler = savehandler;
2653                         longjmp(handler->loc, 1);
2654                 }
2655                 savehandler = handler;
2656                 handler = &jmploc;
2657                 for (sp = varlist.list ; sp ; sp = sp->next)
2658                         mklocal(sp->text);
2659                 funcnest++;
2660                 evaltree(cmdentry.u.func, flags & EV_TESTED);
2661                 funcnest--;
2662                 INTOFF;
2663                 poplocalvars();
2664                 localvars = savelocalvars;
2665                 saveparam.optind = shellparam.optind;
2666                 saveparam.optoff = shellparam.optoff;
2667                 freeparam(&shellparam);
2668                 shellparam = saveparam;
2669                 handler = savehandler;
2670                 popredir();
2671                 INTON;
2672                 if (evalskip == SKIPFUNC) {
2673                         evalskip = 0;
2674                         skipcount = 0;
2675                 }
2676                 if (flags & EV_EXIT)
2677                         exitshell(exitstatus);
2678         } else if (cmdentry.cmdtype == CMDBUILTIN) {
2679 #ifdef DEBUG
2680                 trputs("builtin command:  ");  trargs(argv);
2681 #endif
2682                 mode = (cmdentry.u.cmd == EXECCMD)? 0 : REDIR_PUSH;
2683                 redirect(cmd->ncmd.redirect, mode);
2684                 savecmdname = commandname;
2685                 if (IS_BUILTIN_SPECIAL(firstbltin)) {
2686                         listsetvar(varlist.list);
2687                 } else {
2688                         cmdenviron = varlist.list;
2689                 }
2690                 e = -1;
2691                 if (setjmp(jmploc.loc)) {
2692                         e = exception;
2693                         exitstatus = (e == EXINT)? SIGINT+128 : 2;
2694                         goto cmddone;
2695                 }
2696                 savehandler = handler;
2697                 handler = &jmploc;
2698                 commandname = argv[0];
2699                 argptr = argv + 1;
2700                 optptr = NULL;                  /* initialize nextopt */
2701                 exitstatus = (*cmdentry.u.cmd->builtinfunc)(argc, argv);
2702                 flushall();
2703 cmddone:
2704                 cmdenviron = NULL;
2705                 if (e != EXSHELLPROC) {
2706                         commandname = savecmdname;
2707                         if (flags & EV_EXIT)
2708                                 exitshell(exitstatus);
2709                 }
2710                 handler = savehandler;
2711                 if (e != -1) {
2712                         if ((e != EXERROR && e != EXEXEC)
2713                            || cmdentry.u.cmd == BLTINCMD
2714                            || cmdentry.u.cmd == DOTCMD
2715                            || cmdentry.u.cmd == EVALCMD
2716                            || cmdentry.u.cmd == EXECCMD)
2717                                 exraise(e);
2718                         FORCEINTON;
2719                 }
2720                 if (cmdentry.u.cmd != EXECCMD)
2721                         popredir();
2722         } else {
2723 #ifdef DEBUG
2724                 trputs("normal command:  ");  trargs(argv);
2725 #endif
2726                 redirect(cmd->ncmd.redirect, 0);
2727                 clearredir();
2728                 for (sp = varlist.list ; sp ; sp = sp->next)
2729                         setvareq(sp->text, VEXPORT|VSTACK);
2730                 envp = environment();
2731                 shellexec(argv, envp, path, cmdentry.u.index);
2732         }
2733         goto out;
2734
2735 parent: /* parent process gets here (if we forked) */
2736         if (mode == 0) {        /* argument to fork */
2737                 INTOFF;
2738                 exitstatus = waitforjob(jp);
2739                 INTON;
2740         }
2741
2742 out:
2743         if (lastarg)
2744                 setvar("_", lastarg, 0);
2745         popstackmark(&smark);
2746 }
2747
2748 /*
2749  * Evaluate a parse tree.  The value is left in the global variable
2750  * exitstatus.
2751  */
2752 static void
2753 evaltree(n, flags)
2754         union node *n;
2755         int flags;
2756 {
2757         int checkexit = 0;
2758         if (n == NULL) {
2759                 TRACE(("evaltree(NULL) called\n"));
2760                 goto out;
2761         }
2762         TRACE(("evaltree(0x%lx: %d) called\n", (long)n, n->type));
2763         switch (n->type) {
2764         case NSEMI:
2765                 evaltree(n->nbinary.ch1, flags & EV_TESTED);
2766                 if (evalskip)
2767                         goto out;
2768                 evaltree(n->nbinary.ch2, flags);
2769                 break;
2770         case NAND:
2771                 evaltree(n->nbinary.ch1, EV_TESTED);
2772                 if (evalskip || exitstatus != 0)
2773                         goto out;
2774                 evaltree(n->nbinary.ch2, flags);
2775                 break;
2776         case NOR:
2777                 evaltree(n->nbinary.ch1, EV_TESTED);
2778                 if (evalskip || exitstatus == 0)
2779                         goto out;
2780                 evaltree(n->nbinary.ch2, flags);
2781                 break;
2782         case NREDIR:
2783                 expredir(n->nredir.redirect);
2784                 redirect(n->nredir.redirect, REDIR_PUSH);
2785                 evaltree(n->nredir.n, flags);
2786                 popredir();
2787                 break;
2788         case NSUBSHELL:
2789                 evalsubshell(n, flags);
2790                 break;
2791         case NBACKGND:
2792                 evalsubshell(n, flags);
2793                 break;
2794         case NIF: {
2795                 evaltree(n->nif.test, EV_TESTED);
2796                 if (evalskip)
2797                         goto out;
2798                 if (exitstatus == 0)
2799                         evaltree(n->nif.ifpart, flags);
2800                 else if (n->nif.elsepart)
2801                         evaltree(n->nif.elsepart, flags);
2802                 else
2803                         exitstatus = 0;
2804                 break;
2805         }
2806         case NWHILE:
2807         case NUNTIL:
2808                 evalloop(n, flags);
2809                 break;
2810         case NFOR:
2811                 evalfor(n, flags);
2812                 break;
2813         case NCASE:
2814                 evalcase(n, flags);
2815                 break;
2816         case NDEFUN: {
2817                 struct builtincmd *bcmd;
2818                 struct cmdentry entry;
2819                 if (
2820                         (bcmd = find_builtin(n->narg.text)) &&
2821                         IS_BUILTIN_SPECIAL(bcmd)
2822                 ) {
2823                         out2fmt("%s is a special built-in\n", n->narg.text);
2824                         exitstatus = 1;
2825                         break;
2826                 }
2827                 entry.cmdtype = CMDFUNCTION;
2828                 entry.u.func = copyfunc(n->narg.next);
2829                 addcmdentry(n->narg.text, &entry);
2830                 exitstatus = 0;
2831                 break;
2832         }
2833         case NNOT:
2834                 evaltree(n->nnot.com, EV_TESTED);
2835                 exitstatus = !exitstatus;
2836                 break;
2837
2838         case NPIPE:
2839                 evalpipe(n);
2840                 checkexit = 1;
2841                 break;
2842         case NCMD:
2843                 evalcommand(n, flags);
2844                 checkexit = 1;
2845                 break;
2846 #ifdef DEBUG
2847         default:
2848                 printf("Node type = %d\n", n->type);
2849                 break;
2850 #endif
2851         }
2852 out:
2853         if (pendingsigs)
2854                 dotrap();
2855         if (
2856                 flags & EV_EXIT ||
2857                 (checkexit && eflag && exitstatus && !(flags & EV_TESTED))
2858         )
2859                 exitshell(exitstatus);
2860 }
2861
2862 /*
2863  * Kick off a subshell to evaluate a tree.
2864  */
2865
2866 static void
2867 evalsubshell(const union node *n, int flags)
2868 {
2869         struct job *jp;
2870         int backgnd = (n->type == NBACKGND);
2871
2872         expredir(n->nredir.redirect);
2873         jp = makejob(n, 1);
2874         if (forkshell(jp, n, backgnd) == 0) {
2875                 if (backgnd)
2876                         flags &=~ EV_TESTED;
2877                 redirect(n->nredir.redirect, 0);
2878                 evaltree(n->nredir.n, flags | EV_EXIT); /* never returns */
2879         }
2880         if (! backgnd) {
2881                 INTOFF;
2882                 exitstatus = waitforjob(jp);
2883                 INTON;
2884         }
2885 }
2886
2887 /*
2888  * Compute the names of the files in a redirection list.
2889  */
2890
2891 static void fixredir(union node *n, const char *text, int err);
2892
2893 static void
2894 expredir(union node *n)
2895 {
2896         union node *redir;
2897
2898         for (redir = n ; redir ; redir = redir->nfile.next) {
2899                 struct arglist fn;
2900                 fn.lastp = &fn.list;
2901                 oexitstatus = exitstatus;
2902                 switch (redir->type) {
2903                 case NFROMTO:
2904                 case NFROM:
2905                 case NTO:
2906                 case NAPPEND:
2907                 case NTOOV:
2908                         expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
2909                         redir->nfile.expfname = fn.list->text;
2910                         break;
2911                 case NFROMFD:
2912                 case NTOFD:
2913                         if (redir->ndup.vname) {
2914                                 expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE);
2915                                 fixredir(redir, fn.list->text, 1);
2916                         }
2917                         break;
2918                 }
2919         }
2920 }
2921
2922
2923 /*
2924  * Execute a command inside back quotes.  If it's a builtin command, we
2925  * want to save its output in a block obtained from malloc.  Otherwise
2926  * we fork off a subprocess and get the output of the command via a pipe.
2927  * Should be called with interrupts off.
2928  */
2929
2930 static void
2931 evalbackcmd(union node *n, struct backcmd *result)
2932 {
2933         int pip[2];
2934         struct job *jp;
2935         struct stackmark smark;         /* unnecessary */
2936
2937         setstackmark(&smark);
2938         result->fd = -1;
2939         result->buf = NULL;
2940         result->nleft = 0;
2941         result->jp = NULL;
2942         if (n == NULL) {
2943                 exitstatus = 0;
2944                 goto out;
2945         }
2946         exitstatus = 0;
2947         if (pipe(pip) < 0)
2948                 error("Pipe call failed");
2949         jp = makejob(n, 1);
2950         if (forkshell(jp, n, FORK_NOJOB) == 0) {
2951                 FORCEINTON;
2952                 close(pip[0]);
2953                 if (pip[1] != 1) {
2954                         close(1);
2955                         dup_as_newfd(pip[1], 1);
2956                         close(pip[1]);
2957                 }
2958                 eflag = 0;
2959                 evaltree(n, EV_EXIT);
2960         }
2961         close(pip[1]);
2962         result->fd = pip[0];
2963         result->jp = jp;
2964 out:
2965         popstackmark(&smark);
2966         TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n",
2967                 result->fd, result->buf, result->nleft, result->jp));
2968 }
2969
2970
2971 /*
2972  * Execute a simple command.
2973  */
2974
2975 /*
2976  * Search for a command.  This is called before we fork so that the
2977  * location of the command will be available in the parent as well as
2978  * the child.  The check for "goodname" is an overly conservative
2979  * check that the name will not be subject to expansion.
2980  */
2981
2982 static void
2983 prehash(n)
2984         union node *n;
2985 {
2986         struct cmdentry entry;
2987
2988         if (n->type == NCMD && n->ncmd.args)
2989                 if (goodname(n->ncmd.args->narg.text))
2990                         find_command(n->ncmd.args->narg.text, &entry, 0,
2991                                      pathval());
2992 }
2993
2994
2995 /*
2996  * Builtin commands.  Builtin commands whose functions are closely
2997  * tied to evaluation are implemented here.
2998  */
2999
3000 /*
3001  * No command given, or a bltin command with no arguments.  Set the
3002  * specified variables.
3003  */
3004
3005 int
3006 bltincmd(argc, argv)
3007         int argc;
3008         char **argv;
3009 {
3010         /*
3011          * Preserve exitstatus of a previous possible redirection
3012          * as POSIX mandates
3013          */
3014         return exitstatus;
3015 }
3016
3017
3018 /*
3019  * Handle break and continue commands.  Break, continue, and return are
3020  * all handled by setting the evalskip flag.  The evaluation routines
3021  * above all check this flag, and if it is set they start skipping
3022  * commands rather than executing them.  The variable skipcount is
3023  * the number of loops to break/continue, or the number of function
3024  * levels to return.  (The latter is always 1.)  It should probably
3025  * be an error to break out of more loops than exist, but it isn't
3026  * in the standard shell so we don't make it one here.
3027  */
3028
3029 static int
3030 breakcmd(argc, argv)
3031         int argc;
3032         char **argv;
3033 {
3034         int n = argc > 1 ? number(argv[1]) : 1;
3035
3036         if (n > loopnest)
3037                 n = loopnest;
3038         if (n > 0) {
3039                 evalskip = (**argv == 'c')? SKIPCONT : SKIPBREAK;
3040                 skipcount = n;
3041         }
3042         return 0;
3043 }
3044
3045
3046 /*
3047  * The return command.
3048  */
3049
3050 static int
3051 returncmd(argc, argv)
3052         int argc;
3053         char **argv;
3054 {
3055         int ret = argc > 1 ? number(argv[1]) : oexitstatus;
3056
3057         if (funcnest) {
3058                 evalskip = SKIPFUNC;
3059                 skipcount = 1;
3060                 return ret;
3061         }
3062         else {
3063                 /* Do what ksh does; skip the rest of the file */
3064                 evalskip = SKIPFILE;
3065                 skipcount = 1;
3066                 return ret;
3067         }
3068 }
3069
3070
3071 #ifndef CONFIG_FALSE
3072 static int
3073 false_main(argc, argv)
3074         int argc;
3075         char **argv;
3076 {
3077         return 1;
3078 }
3079 #endif
3080
3081 #ifndef CONFIG_TRUE
3082 static int
3083 true_main(argc, argv)
3084         int argc;
3085         char **argv;
3086 {
3087         return 0;
3088 }
3089 #endif
3090
3091 /*
3092  * Controls whether the shell is interactive or not.
3093  */
3094
3095 static void setsignal(int signo);
3096
3097 #ifdef ASH_MAIL
3098 static void chkmail(int silent);
3099 #endif
3100
3101 static void
3102 setinteractive(int on)
3103 {
3104         static int is_interactive;
3105         static int do_banner=0;
3106
3107         if (on == is_interactive)
3108                 return;
3109         setsignal(SIGINT);
3110         setsignal(SIGQUIT);
3111         setsignal(SIGTERM);
3112 #ifdef ASH_MAIL
3113         chkmail(1);
3114 #endif
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)) != 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 #ifdef ASH_MAIL
7524
7525 /*
7526  * Routines to check for mail.
7527  */
7528
7529
7530 #define MAXMBOXES 10
7531
7532
7533 static int nmboxes;                     /* number of mailboxes */
7534 static time_t mailtime[MAXMBOXES];      /* times of mailboxes */
7535
7536
7537
7538 /*
7539  * Print appropriate message(s) if mail has arrived.  If the argument is
7540  * nozero, then the value of MAIL has changed, so we just update the
7541  * values.
7542  */
7543
7544 static void
7545 chkmail(int silent)
7546 {
7547         int i;
7548         const char *mpath;
7549         char *p;
7550         char *q;
7551         struct stackmark smark;
7552         struct stat statb;
7553
7554         if (silent)
7555                 nmboxes = 10;
7556         if (nmboxes == 0)
7557                 return;
7558         setstackmark(&smark);
7559         mpath = mpathset()? mpathval() : mailval();
7560         for (i = 0 ; i < nmboxes ; i++) {
7561                 p = padvance(&mpath, nullstr);
7562                 if (p == NULL)
7563                         break;
7564                 if (*p == '\0')
7565                         continue;
7566                 for (q = p ; *q ; q++);
7567 #ifdef DEBUG
7568                 if (q[-1] != '/')
7569                         abort();
7570 #endif
7571                 q[-1] = '\0';                   /* delete trailing '/' */
7572                 if (stat(p, &statb) < 0)
7573                         statb.st_size = 0;
7574                 if (statb.st_size > mailtime[i] && ! silent) {
7575                         out2fmt(snlfmt,
7576                                 pathopt? pathopt : "you have mail");
7577                 }
7578                 mailtime[i] = statb.st_size;
7579         }
7580         nmboxes = i;
7581         popstackmark(&smark);
7582 }
7583
7584 #endif /* ASH_MAIL */
7585
7586 #define PROFILE 0
7587
7588 #if PROFILE
7589 static short profile_buf[16384];
7590 extern int etext();
7591 #endif
7592
7593 static void read_profile (const char *);
7594 static void cmdloop (int);
7595 static void options (int);
7596 static void setoption (int, int);
7597 static void procargs (int, char **);
7598
7599
7600 /*
7601  * Main routine.  We initialize things, parse the arguments, execute
7602  * profiles if we're a login shell, and then call cmdloop to execute
7603  * commands.  The setjmp call sets up the location to jump to when an
7604  * exception occurs.  When an exception occurs the variable "state"
7605  * is used to figure out how far we had gotten.
7606  */
7607
7608 int
7609 ash_main(argc, argv)
7610         int argc;
7611         char **argv;
7612 {
7613         struct jmploc jmploc;
7614         struct stackmark smark;
7615         volatile int state;
7616         const char *shinit;
7617
7618         BLTINCMD = find_builtin("builtin");
7619         EXECCMD = find_builtin("exec");
7620         EVALCMD = find_builtin("eval");
7621
7622 #ifndef CONFIG_FEATURE_SH_FANCY_PROMPT
7623         unsetenv("PS1");
7624         unsetenv("PS2");
7625 #endif
7626
7627 #if PROFILE
7628         monitor(4, etext, profile_buf, sizeof profile_buf, 50);
7629 #endif
7630 #if defined(linux) || defined(__GNU__)
7631         signal(SIGCHLD, SIG_DFL);
7632 #endif
7633         state = 0;
7634         if (setjmp(jmploc.loc)) {
7635                 INTOFF;
7636                 /*
7637                  * When a shell procedure is executed, we raise the
7638                  * exception EXSHELLPROC to clean up before executing
7639                  * the shell procedure.
7640                  */
7641                 if (exception == EXSHELLPROC) {
7642                         rootpid = getpid();
7643                         rootshell = 1;
7644                         minusc = NULL;
7645                         state = 3;
7646                 } else {
7647                         if (exception == EXEXEC) {
7648                                 exitstatus = exerrno;
7649                         } else if (exception == EXERROR) {
7650                                 exitstatus = 2;
7651                         }
7652                     if (state == 0 || iflag == 0 || ! rootshell)
7653                             exitshell(exitstatus);
7654                 }
7655                 reset();
7656                 if (exception == EXINT) {
7657                         out2c('\n');
7658                 }
7659                 popstackmark(&smark);
7660                 FORCEINTON;                             /* enable interrupts */
7661                 if (state == 1)
7662                         goto state1;
7663                 else if (state == 2)
7664                         goto state2;
7665                 else if (state == 3)
7666                         goto state3;
7667                 else
7668                         goto state4;
7669         }
7670         handler = &jmploc;
7671 #ifdef DEBUG
7672         opentrace();
7673         trputs("Shell args:  ");  trargs(argv);
7674 #endif
7675         rootpid = getpid();
7676         rootshell = 1;
7677         init();
7678         setstackmark(&smark);
7679         procargs(argc, argv);
7680         if (argv[0] && argv[0][0] == '-') {
7681                 state = 1;
7682                 read_profile("/etc/profile");
7683 state1:
7684                 state = 2;
7685                 read_profile(".profile");
7686         }
7687 state2:
7688         state = 3;
7689 #ifndef linux
7690         if (getuid() == geteuid() && getgid() == getegid()) {
7691 #endif
7692                 if ((shinit = lookupvar("ENV")) != NULL && *shinit != '\0') {
7693                         state = 3;
7694                         read_profile(shinit);
7695                 }
7696 #ifndef linux
7697         }
7698 #endif
7699 state3:
7700         state = 4;
7701         if (sflag == 0 || minusc) {
7702                 static const char sigs[] =  {
7703                     SIGINT, SIGQUIT, SIGHUP,
7704 #ifdef SIGTSTP
7705                     SIGTSTP,
7706 #endif
7707                     SIGPIPE
7708                 };
7709 #define SIGSSIZE ((sizeof(sigs)/sizeof(sigs[0])) - 1) /* trailing nul */
7710                 int i;
7711
7712                 for (i = 0; i < SIGSSIZE; i++)
7713                     setsignal(sigs[i]);
7714         }
7715
7716         if (minusc)
7717                 evalstring(minusc, 0);
7718
7719         if (sflag || minusc == NULL) {
7720 state4: /* XXX ??? - why isn't this before the "if" statement */
7721                 cmdloop(1);
7722         }
7723 #if PROFILE
7724         monitor(0);
7725 #endif
7726         exitshell(exitstatus);
7727         /* NOTREACHED */
7728 }
7729
7730
7731 /*
7732  * Read and execute commands.  "Top" is nonzero for the top level command
7733  * loop; it turns on prompting if the shell is interactive.
7734  */
7735
7736 static void
7737 cmdloop(int top)
7738 {
7739         union node *n;
7740         struct stackmark smark;
7741         int inter;
7742         int numeof = 0;
7743
7744         TRACE(("cmdloop(%d) called\n", top));
7745         setstackmark(&smark);
7746         for (;;) {
7747                 if (pendingsigs)
7748                         dotrap();
7749                 inter = 0;
7750                 if (iflag && top) {
7751                         inter++;
7752                         showjobs(1);
7753 #ifdef ASH_MAIL
7754                         chkmail(0);
7755 #endif
7756                         flushall();
7757                 }
7758                 n = parsecmd(inter);
7759                 /* showtree(n); DEBUG */
7760                 if (n == NEOF) {
7761                         if (!top || numeof >= 50)
7762                                 break;
7763                         if (!stoppedjobs()) {
7764                                 if (!Iflag)
7765                                         break;
7766                                 out2str("\nUse \"exit\" to leave shell.\n");
7767                         }
7768                         numeof++;
7769                 } else if (n != NULL && nflag == 0) {
7770                         job_warning = (job_warning == 2) ? 1 : 0;
7771                         numeof = 0;
7772                         evaltree(n, 0);
7773                 }
7774                 popstackmark(&smark);
7775                 setstackmark(&smark);
7776                 if (evalskip == SKIPFILE) {
7777                         evalskip = 0;
7778                         break;
7779                 }
7780         }
7781         popstackmark(&smark);
7782 }
7783
7784
7785
7786 /*
7787  * Read /etc/profile or .profile.  Return on error.
7788  */
7789
7790 static void
7791 read_profile(name)
7792         const char *name;
7793 {
7794         int fd;
7795         int xflag_save;
7796         int vflag_save;
7797
7798         INTOFF;
7799         if ((fd = open(name, O_RDONLY)) >= 0)
7800                 setinputfd(fd, 1);
7801         INTON;
7802         if (fd < 0)
7803                 return;
7804         /* -q turns off -x and -v just when executing init files */
7805         /* Note: Might do a little redundant work, but reduces code size. */
7806         xflag_save = xflag;
7807         vflag_save = vflag;
7808         if (qflag)  {
7809                 vflag = xflag = 0;
7810         }
7811         cmdloop(0);
7812         xflag = xflag_save;
7813         vflag = vflag_save;
7814         popfile();
7815 }
7816
7817
7818
7819 /*
7820  * Read a file containing shell functions.
7821  */
7822
7823 static void
7824 readcmdfile(const char *name)
7825 {
7826         int fd;
7827
7828         INTOFF;
7829         if ((fd = open(name, O_RDONLY)) >= 0)
7830                 setinputfd(fd, 1);
7831         else
7832                 error("Can't open %s", name);
7833         INTON;
7834         cmdloop(0);
7835         popfile();
7836 }
7837
7838
7839
7840 /*
7841  * Take commands from a file.  To be compatable we should do a path
7842  * search for the file, which is necessary to find sub-commands.
7843  */
7844
7845 static inline char *
7846 find_dot_file(char *mybasename)
7847 {
7848         char *fullname;
7849         const char *path = pathval();
7850         struct stat statb;
7851
7852         /* don't try this for absolute or relative paths */
7853         if (strchr(mybasename, '/'))
7854                 return mybasename;
7855
7856         while ((fullname = padvance(&path, mybasename)) != NULL) {
7857                 if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) {
7858                         /*
7859                          * Don't bother freeing here, since it will
7860                          * be freed by the caller.
7861                          */
7862                         return fullname;
7863                 }
7864                 stunalloc(fullname);
7865         }
7866
7867         /* not found in the PATH */
7868         error("%s: not found", mybasename);
7869         /* NOTREACHED */
7870 }
7871
7872 static int
7873 dotcmd(argc, argv)
7874         int argc;
7875         char **argv;
7876 {
7877         struct strlist *sp;
7878         volatile struct shparam saveparam;
7879         exitstatus = 0;
7880
7881         for (sp = cmdenviron; sp ; sp = sp->next)
7882                 setvareq(savestr(sp->text), VSTRFIXED|VTEXTFIXED);
7883
7884         if (argc >= 2) {                /* That's what SVR2 does */
7885                 char *fullname;
7886                 struct stackmark smark;
7887
7888                 setstackmark(&smark);
7889                 fullname = find_dot_file(argv[1]);
7890
7891                 if (argc>2) {
7892                         saveparam = shellparam;
7893                         shellparam.malloc = 0;
7894                         shellparam.nparam = argc - 2;
7895                         shellparam.p = argv + 2;
7896                 };
7897
7898                 setinputfile(fullname, 1);
7899                 commandname = fullname;
7900                 cmdloop(0);
7901                 popfile();
7902
7903                 if (argc>2) {
7904                         freeparam(&shellparam);
7905                         shellparam = saveparam;
7906                 };
7907
7908                 popstackmark(&smark);
7909         }
7910         return exitstatus;
7911 }
7912
7913
7914 static int
7915 exitcmd(argc, argv)
7916         int argc;
7917         char **argv;
7918 {
7919         if (stoppedjobs())
7920                 return 0;
7921         if (argc > 1)
7922                 exitstatus = number(argv[1]);
7923         else
7924                 exitstatus = oexitstatus;
7925         exitshell(exitstatus);
7926         /* NOTREACHED */
7927 }
7928
7929 static pointer
7930 stalloc(int nbytes)
7931 {
7932         char *p;
7933
7934         nbytes = ALIGN(nbytes);
7935         if (nbytes > stacknleft) {
7936                 int blocksize;
7937                 struct stack_block *sp;
7938
7939                 blocksize = nbytes;
7940                 if (blocksize < MINSIZE)
7941                         blocksize = MINSIZE;
7942                 INTOFF;
7943                 sp = ckmalloc(sizeof(struct stack_block) - MINSIZE + blocksize);
7944                 sp->prev = stackp;
7945                 stacknxt = sp->space;
7946                 stacknleft = blocksize;
7947                 stackp = sp;
7948                 INTON;
7949         }
7950         p = stacknxt;
7951         stacknxt += nbytes;
7952         stacknleft -= nbytes;
7953         return p;
7954 }
7955
7956
7957 static void
7958 stunalloc(pointer p)
7959 {
7960 #ifdef DEBUG
7961         if (p == NULL) {                /*DEBUG */
7962                 write(2, "stunalloc\n", 10);
7963                 abort();
7964         }
7965 #endif
7966         if (!(stacknxt >= (char *)p && (char *)p >= stackp->space)) {
7967                 p = stackp->space;
7968         }
7969         stacknleft += stacknxt - (char *)p;
7970         stacknxt = p;
7971 }
7972
7973
7974 static void
7975 setstackmark(struct stackmark *mark)
7976 {
7977         mark->stackp = stackp;
7978         mark->stacknxt = stacknxt;
7979         mark->stacknleft = stacknleft;
7980         mark->marknext = markp;
7981         markp = mark;
7982 }
7983
7984
7985 static void
7986 popstackmark(struct stackmark *mark)
7987 {
7988         struct stack_block *sp;
7989
7990         INTOFF;
7991         markp = mark->marknext;
7992         while (stackp != mark->stackp) {
7993                 sp = stackp;
7994                 stackp = sp->prev;
7995                 ckfree(sp);
7996         }
7997         stacknxt = mark->stacknxt;
7998         stacknleft = mark->stacknleft;
7999         INTON;
8000 }
8001
8002
8003 /*
8004  * When the parser reads in a string, it wants to stick the string on the
8005  * stack and only adjust the stack pointer when it knows how big the
8006  * string is.  Stackblock (defined in stack.h) returns a pointer to a block
8007  * of space on top of the stack and stackblocklen returns the length of
8008  * this block.  Growstackblock will grow this space by at least one byte,
8009  * possibly moving it (like realloc).  Grabstackblock actually allocates the
8010  * part of the block that has been used.
8011  */
8012
8013 static void
8014 growstackblock(void) {
8015         char *p;
8016         int newlen = ALIGN(stacknleft * 2 + 100);
8017         char *oldspace = stacknxt;
8018         int oldlen = stacknleft;
8019         struct stack_block *sp;
8020         struct stack_block *oldstackp;
8021
8022         if (stacknxt == stackp->space && stackp != &stackbase) {
8023                 INTOFF;
8024                 oldstackp = stackp;
8025                 sp = stackp;
8026                 stackp = sp->prev;
8027                 sp = ckrealloc((pointer)sp, sizeof(struct stack_block) - MINSIZE + newlen);
8028                 sp->prev = stackp;
8029                 stackp = sp;
8030                 stacknxt = sp->space;
8031                 stacknleft = newlen;
8032                 {
8033                   /* Stack marks pointing to the start of the old block
8034                    * must be relocated to point to the new block
8035                    */
8036                   struct stackmark *xmark;
8037                   xmark = markp;
8038                   while (xmark != NULL && xmark->stackp == oldstackp) {
8039                     xmark->stackp = stackp;
8040                     xmark->stacknxt = stacknxt;
8041                     xmark->stacknleft = stacknleft;
8042                     xmark = xmark->marknext;
8043                   }
8044                 }
8045                 INTON;
8046         } else {
8047                 p = stalloc(newlen);
8048                 memcpy(p, oldspace, oldlen);
8049                 stacknxt = p;                   /* free the space */
8050                 stacknleft += newlen;           /* we just allocated */
8051         }
8052 }
8053
8054
8055
8056 static inline void
8057 grabstackblock(int len)
8058 {
8059         len = ALIGN(len);
8060         stacknxt += len;
8061         stacknleft -= len;
8062 }
8063
8064
8065
8066 /*
8067  * The following routines are somewhat easier to use that the above.
8068  * The user declares a variable of type STACKSTR, which may be declared
8069  * to be a register.  The macro STARTSTACKSTR initializes things.  Then
8070  * the user uses the macro STPUTC to add characters to the string.  In
8071  * effect, STPUTC(c, p) is the same as *p++ = c except that the stack is
8072  * grown as necessary.  When the user is done, she can just leave the
8073  * string there and refer to it using stackblock().  Or she can allocate
8074  * the space for it using grabstackstr().  If it is necessary to allow
8075  * someone else to use the stack temporarily and then continue to grow
8076  * the string, the user should use grabstack to allocate the space, and
8077  * then call ungrabstr(p) to return to the previous mode of operation.
8078  *
8079  * USTPUTC is like STPUTC except that it doesn't check for overflow.
8080  * CHECKSTACKSPACE can be called before USTPUTC to ensure that there
8081  * is space for at least one character.
8082  */
8083
8084
8085 static char *
8086 growstackstr(void) {
8087         int len = stackblocksize();
8088         if (herefd >= 0 && len >= 1024) {
8089                 xwrite(herefd, stackblock(), len);
8090                 sstrnleft = len - 1;
8091                 return stackblock();
8092         }
8093         growstackblock();
8094         sstrnleft = stackblocksize() - len - 1;
8095         return stackblock() + len;
8096 }
8097
8098
8099 /*
8100  * Called from CHECKSTRSPACE.
8101  */
8102
8103 static char *
8104 makestrspace(size_t newlen) {
8105         int len = stackblocksize() - sstrnleft;
8106         do {
8107                 growstackblock();
8108                 sstrnleft = stackblocksize() - len;
8109         } while (sstrnleft < newlen);
8110         return stackblock() + len;
8111 }
8112
8113
8114
8115 static void
8116 ungrabstackstr(char *s, char *p)
8117 {
8118         stacknleft += stacknxt - s;
8119         stacknxt = s;
8120         sstrnleft = stacknleft - (p - s);
8121 }
8122 /*
8123  * Miscelaneous builtins.
8124  */
8125
8126
8127 #undef rflag
8128
8129 #if !defined(__GLIBC__) || __GLIBC__ == 2 && __GLIBC_MINOR__ < 1
8130 typedef long rlim_t;
8131 #endif
8132
8133
8134
8135 /*
8136  * The read builtin.  The -e option causes backslashes to escape the
8137  * following character.
8138  *
8139  * This uses unbuffered input, which may be avoidable in some cases.
8140  */
8141
8142 static int
8143 readcmd(int argc, char **argv)
8144 {
8145         char **ap;
8146         int backslash;
8147         char c;
8148         int rflag;
8149         char *prompt;
8150         const char *ifs;
8151         char *p;
8152         int startword;
8153         int status;
8154         int i;
8155
8156         rflag = 0;
8157         prompt = NULL;
8158         while ((i = nextopt("p:r")) != '\0') {
8159                 if (i == 'p')
8160                         prompt = optionarg;
8161                 else
8162                         rflag = 1;
8163         }
8164         if (prompt && isatty(0)) {
8165                 out2str(prompt);     /* read without cmdedit */
8166                 flushall();
8167         }
8168         if (*(ap = argptr) == NULL)
8169                 error("arg count");
8170         if ((ifs = bltinlookup("IFS")) == NULL)
8171                 ifs = defifs;
8172         status = 0;
8173         startword = 1;
8174         backslash = 0;
8175         STARTSTACKSTR(p);
8176         for (;;) {
8177                 if (read(0, &c, 1) != 1) {
8178                         status = 1;
8179                         break;
8180                 }
8181                 if (c == '\0')
8182                         continue;
8183                 if (backslash) {
8184                         backslash = 0;
8185                         if (c != '\n')
8186                                 STPUTC(c, p);
8187                         continue;
8188                 }
8189                 if (!rflag && c == '\\') {
8190                         backslash++;
8191                         continue;
8192                 }
8193                 if (c == '\n')
8194                         break;
8195                 if (startword && *ifs == ' ' && strchr(ifs, c)) {
8196                         continue;
8197                 }
8198                 startword = 0;
8199                 if (backslash && c == '\\') {
8200                         if (read(0, &c, 1) != 1) {
8201                                 status = 1;
8202                                 break;
8203                         }
8204                         STPUTC(c, p);
8205                 } else if (ap[1] != NULL && strchr(ifs, c) != NULL) {
8206                         STACKSTRNUL(p);
8207                         setvar(*ap, stackblock(), 0);
8208                         ap++;
8209                         startword = 1;
8210                         STARTSTACKSTR(p);
8211                 } else {
8212                         STPUTC(c, p);
8213                 }
8214         }
8215         STACKSTRNUL(p);
8216         /* Remove trailing blanks */
8217         while (stackblock() <= --p && strchr(ifs, *p) != NULL)
8218                 *p = '\0';
8219         setvar(*ap, stackblock(), 0);
8220         while (*++ap != NULL)
8221                 setvar(*ap, nullstr, 0);
8222         return status;
8223 }
8224
8225
8226
8227 static int
8228 umaskcmd(argc, argv)
8229         int argc;
8230         char **argv;
8231 {
8232         static const char permuser[3] = "ugo";
8233         static const char permmode[3] = "rwx";
8234         static const short int permmask[] = {
8235                 S_IRUSR, S_IWUSR, S_IXUSR,
8236                 S_IRGRP, S_IWGRP, S_IXGRP,
8237                 S_IROTH, S_IWOTH, S_IXOTH
8238         };
8239
8240         char *ap;
8241         mode_t mask;
8242         int i;
8243         int symbolic_mode = 0;
8244
8245         while (nextopt("S") != '\0') {
8246                 symbolic_mode = 1;
8247         }
8248
8249         INTOFF;
8250         mask = umask(0);
8251         umask(mask);
8252         INTON;
8253
8254         if ((ap = *argptr) == NULL) {
8255                 if (symbolic_mode) {
8256                         char buf[18];
8257                         char *p = buf;
8258                         for (i=0 ; i<3 ; i++) {
8259                                 int j;
8260                                 *p++ = permuser[i];
8261                                 *p++ = '=';
8262                                 for (j=0 ; j<3 ; j++) {
8263                                         if ((mask & permmask[3*i+j]) == 0) {
8264                                                 *p++ = permmode[j];
8265                                         }
8266                                 }
8267                                 *p++ = ',';
8268                         }
8269                         *--p = 0;
8270                         puts(buf);
8271                 } else {
8272                         printf("%.4o\n", mask);
8273                 }
8274         } else {
8275                 if (is_digit((unsigned char)*ap)) {
8276                         mask = 0;
8277                         do {
8278                                 if (*ap >= '8' || *ap < '0')
8279                                         error("Illegal number: %s", argv[1]);
8280                                 mask = (mask << 3) + (*ap - '0');
8281                         } while (*++ap != '\0');
8282                         umask(mask);
8283                 } else {
8284                         mask = ~mask & 0777;
8285                         if (parse_mode(ap, &mask) == FALSE) {
8286                                 error("Illegal mode: %s", ap);
8287                         }
8288                         umask(~mask & 0777);
8289                 }
8290         }
8291         return 0;
8292 }
8293
8294 /*
8295  * ulimit builtin
8296  *
8297  * This code, originally by Doug Gwyn, Doug Kingston, Eric Gisin, and
8298  * Michael Rendell was ripped from pdksh 5.0.8 and hacked for use with
8299  * ash by J.T. Conklin.
8300  *
8301  * Public domain.
8302  */
8303
8304 struct limits {
8305         const char *name;
8306         short   cmd;
8307         short   factor; /* multiply by to get rlim_{cur,max} values */
8308 };
8309
8310 static const struct limits limits[] = {
8311 #ifdef RLIMIT_CPU
8312         { "time(seconds)",             RLIMIT_CPU,        1 },
8313 #endif
8314 #ifdef RLIMIT_FSIZE
8315         { "file(blocks)",              RLIMIT_FSIZE,    512 },
8316 #endif
8317 #ifdef RLIMIT_DATA
8318         { "data(kbytes)",              RLIMIT_DATA,    1024 },
8319 #endif
8320 #ifdef RLIMIT_STACK
8321         { "stack(kbytes)",             RLIMIT_STACK,   1024 },
8322 #endif
8323 #ifdef  RLIMIT_CORE
8324         { "coredump(blocks)",          RLIMIT_CORE,     512 },
8325 #endif
8326 #ifdef RLIMIT_RSS
8327         { "memory(kbytes)",            RLIMIT_RSS,     1024 },
8328 #endif
8329 #ifdef RLIMIT_MEMLOCK
8330         { "locked memory(kbytes)",     RLIMIT_MEMLOCK, 1024 },
8331 #endif
8332 #ifdef RLIMIT_NPROC
8333         { "process(processes)",        RLIMIT_NPROC,      1 },
8334 #endif
8335 #ifdef RLIMIT_NOFILE
8336         { "nofiles(descriptors)",      RLIMIT_NOFILE,     1 },
8337 #endif
8338 #ifdef RLIMIT_VMEM
8339         { "vmemory(kbytes)",           RLIMIT_VMEM,    1024 },
8340 #endif
8341 #ifdef RLIMIT_SWAP
8342         { "swap(kbytes)",              RLIMIT_SWAP,    1024 },
8343 #endif
8344         { NULL,                         0,                 0 }
8345 };
8346
8347 static int
8348 ulimitcmd(argc, argv)
8349         int argc;
8350         char **argv;
8351 {
8352         static const char unlimited_string[] = "unlimited";
8353         int     c;
8354         rlim_t val = 0;
8355         enum { SOFT = 0x1, HARD = 0x2 }
8356                         how = SOFT | HARD;
8357         const struct limits     *l;
8358         int             set, all = 0;
8359         int             optc, what;
8360         struct rlimit   limit;
8361
8362         what = 'f';
8363
8364         while ((optc = nextopt("HSa"
8365 #ifdef RLIMIT_CPU
8366         "t"
8367 #endif
8368 #ifdef RLIMIT_FSIZE
8369         "f"
8370 #endif
8371 #ifdef RLIMIT_DATA
8372         "d"
8373 #endif
8374 #ifdef RLIMIT_STACK
8375         "s"
8376 #endif
8377 #ifdef  RLIMIT_CORE
8378         "c"
8379 #endif
8380 #ifdef RLIMIT_RSS
8381         "m"
8382 #endif
8383 #ifdef RLIMIT_MEMLOCK
8384         "l"
8385 #endif
8386 #ifdef RLIMIT_NPROC
8387         "p"
8388 #endif
8389 #ifdef RLIMIT_NOFILE
8390         "n"
8391 #endif
8392 #ifdef RLIMIT_VMEM
8393         "v"
8394 #endif
8395 #ifdef RLIMIT_SWAP
8396         "w"
8397 #endif
8398                                         )) != '\0') {
8399                 if (optc == 'H') {
8400                         how = HARD;
8401                 } else if (optc == 'S') {
8402                         how = SOFT;
8403                 } else if (optc == 'a') {
8404                         all = 1;
8405                 } else {
8406                         what = optc;
8407                 }
8408         }
8409
8410         for (l = limits; l->name; l++) {
8411                 if(l->name[0] == what)
8412                         break;
8413                 if(l->name[1]=='w' && what=='w')
8414                         break;
8415         }
8416
8417         set = *argptr ? 1 : 0;
8418         if (set) {
8419                 char *p = *argptr;
8420
8421                 if (all || argptr[1])
8422                         error("too many arguments");
8423                 if (strcmp(p, unlimited_string) == 0)
8424                         val = RLIM_INFINITY;
8425                 else {
8426                         val = (rlim_t) 0;
8427
8428                         while ((c = *p++) >= '0' && c <= '9')
8429                         {
8430                                 val = (val * 10) + (long)(c - '0');
8431                                 if (val < (rlim_t) 0)
8432                                         break;
8433                         }
8434                         if (c)
8435                                 error("bad number");
8436                         val *= l->factor;
8437                 }
8438         }
8439
8440         if (all) {
8441                 for (l = limits; l->name; l++) {
8442                         printf("%-20s ", l->name);
8443                         getrlimit(l->cmd, &limit);
8444                 OUTPUT_LIMIT:
8445                         if (how & SOFT)
8446                                 val = limit.rlim_cur;
8447                         else if (how & HARD)
8448                                 val = limit.rlim_max;
8449
8450                         if (val == RLIM_INFINITY)
8451                                 puts(unlimited_string);
8452                         else
8453                         {
8454                                 val /= l->factor;
8455                                 printf("%lld\n", (long long) val);
8456                         }
8457                         if (!all) {
8458                                 break;
8459                         }
8460                 }
8461                 return 0;
8462         }
8463
8464         if (!set) {
8465                 goto OUTPUT_LIMIT;
8466         }
8467
8468         getrlimit(l->cmd, &limit);
8469         if (how & HARD)
8470                 limit.rlim_max = val;
8471         if (how & SOFT)
8472                 limit.rlim_cur = val;
8473         if (setrlimit(l->cmd, &limit) < 0)
8474                 error("error setting limit (%m)");
8475         return 0;
8476 }
8477 /*
8478  * prefix -- see if pfx is a prefix of string.
8479  */
8480
8481 static int
8482 prefix(char const *pfx, char const *string)
8483 {
8484         while (*pfx) {
8485                 if (*pfx++ != *string++)
8486                         return 0;
8487         }
8488         return 1;
8489 }
8490
8491 /*
8492  * Return true if s is a string of digits, and save munber in intptr
8493  * nagative is bad
8494  */
8495
8496 static int
8497 is_number(const char *p, int *intptr)
8498 {
8499         int ret = 0;
8500
8501         do {
8502                 if (! is_digit(*p))
8503                         return 0;
8504                 ret *= 10;
8505                 ret += digit_val(*p);
8506                 p++;
8507         } while (*p != '\0');
8508
8509         *intptr = ret;
8510         return 1;
8511 }
8512
8513 /*
8514  * Convert a string of digits to an integer, printing an error message on
8515  * failure.
8516  */
8517
8518 static int
8519 number(const char *s)
8520 {
8521         int i;
8522         if (! is_number(s, &i))
8523                 error("Illegal number: %s", s);
8524         return i;
8525 }
8526
8527 /*
8528  * Produce a possibly single quoted string suitable as input to the shell.
8529  * The return string is allocated on the stack.
8530  */
8531
8532 static char *
8533 single_quote(const char *s) {
8534         char *p;
8535
8536         STARTSTACKSTR(p);
8537
8538         do {
8539                 char *q = p;
8540                 size_t len1, len1p, len2, len2p;
8541
8542                 len1 = strcspn(s, "'");
8543                 len2 = strspn(s + len1, "'");
8544
8545                 len1p = len1 ? len1 + 2 : len1;
8546                 len2p = len2 + ((len2 < 2) ? len2 : 2);
8547
8548                 CHECKSTRSPACE(len1p + len2p + 1, p);
8549
8550                 if (len1) {
8551                         *p = '\'';
8552                         q = p + 1 + len1;
8553                         memcpy(p + 1, s, len1);
8554                         *q++ = '\'';
8555                         s += len1;
8556                 }
8557
8558                 if (len2 > 1) {
8559                         *q = '"';
8560                         q += 1 + len2;
8561                         memcpy(q + 1, s, len2);
8562                         *q = '"';
8563                         s += len2;
8564                 } else if (len2 == 1) {
8565                         *q++ = '\\';
8566                         *q = '\'';
8567                         s++;
8568                 }
8569
8570                 STADJUST(len1p + len2p, p);
8571         } while (*s);
8572
8573         USTPUTC(0, p);
8574
8575         return grabstackstr(p);
8576 }
8577
8578 /*
8579  * Like strdup but works with the ash stack.
8580  */
8581
8582 static char *
8583 sstrdup(const char *p)
8584 {
8585         size_t len = strlen(p) + 1;
8586         return memcpy(stalloc(len), p, len);
8587 }
8588
8589
8590 /*
8591  * Routine for dealing with parsed shell commands.
8592  */
8593
8594
8595 static void sizenodelist (const struct nodelist *);
8596 static struct nodelist *copynodelist (const struct nodelist *);
8597 static char *nodesavestr (const char *);
8598
8599 #define CALCSIZE_TABLE
8600 #define COPYNODE_TABLE
8601 #if defined(CALCSIZE_TABLE) || defined(COPYNODE_TABLE)
8602 /*
8603  * To collect a lot of redundant code in case statements for copynode()
8604  * and calcsize(), we implement a mini language here.  Each type of node
8605  * struct has an associated instruction sequence that operates on its
8606  * members via their offsets.  The instruction are pack in unsigned chars
8607  * with format   IIDDDDDE   where the bits are
8608  *   I : part of the instruction opcode, which are
8609  *       00 : member is a pointer to another node
8610  *       40 : member is an integer
8611  *       80 : member is a pointer to a nodelist
8612  *       CC : member is a pointer to a char string
8613  *   D : data - the actual offset of the member to operate on in the struct
8614  *              (since we assume bit 0 is set, it is not shifted)
8615  *   E : flag signaling end of instruction sequence
8616  *
8617  * WARNING: In order to handle larger offsets for 64bit archs, this code
8618  *          assumes that no offset can be an odd number and stores the
8619  *          end-of-instructions flag in bit 0.
8620  */
8621
8622 #define NODE_INTEGER    0x40
8623 #define NODE_NODELIST   0x80
8624 #define NODE_CHARPTR    0xC0
8625 #define NODE_NOMORE             0x01    /* Note: no offset should be odd (aligned)*/
8626 #define NODE_MBRMASK    0xC0
8627 #define NODE_OFFSETMASK 0x3E
8628
8629 static const unsigned char copynode_ops[35] = {
8630 #define COPYNODE_OPS0   0
8631         offsetof(union node, nbinary.ch2),
8632         offsetof(union node, nbinary.ch1)|NODE_NOMORE,
8633 #define COPYNODE_OPS1   (COPYNODE_OPS0 + 2)
8634         offsetof(union node, ncmd.redirect),
8635         offsetof(union node, ncmd.args),
8636         offsetof(union node, ncmd.assign),
8637         offsetof(union node, ncmd.backgnd)|NODE_INTEGER|NODE_NOMORE,
8638 #define COPYNODE_OPS2   (COPYNODE_OPS1 + 4)
8639         offsetof(union node, npipe.cmdlist)|NODE_NODELIST,
8640         offsetof(union node, npipe.backgnd)|NODE_INTEGER|NODE_NOMORE,
8641 #define COPYNODE_OPS3   (COPYNODE_OPS2 + 2)
8642         offsetof(union node, nredir.redirect),
8643         offsetof(union node, nredir.n)|NODE_NOMORE,
8644 #define COPYNODE_OPS4   (COPYNODE_OPS3 + 2)
8645         offsetof(union node, nif.elsepart),
8646         offsetof(union node, nif.ifpart),
8647         offsetof(union node, nif.test)|NODE_NOMORE,
8648 #define COPYNODE_OPS5   (COPYNODE_OPS4 + 3)
8649         offsetof(union node, nfor.var)|NODE_CHARPTR,
8650         offsetof(union node, nfor.body),
8651         offsetof(union node, nfor.args)|NODE_NOMORE,
8652 #define COPYNODE_OPS6   (COPYNODE_OPS5 + 3)
8653         offsetof(union node, ncase.cases),
8654         offsetof(union node, ncase.expr)|NODE_NOMORE,
8655 #define COPYNODE_OPS7   (COPYNODE_OPS6 + 2)
8656         offsetof(union node, nclist.body),
8657         offsetof(union node, nclist.pattern),
8658         offsetof(union node, nclist.next)|NODE_NOMORE,
8659 #define COPYNODE_OPS8   (COPYNODE_OPS7 + 3)
8660         offsetof(union node, narg.backquote)|NODE_NODELIST,
8661         offsetof(union node, narg.text)|NODE_CHARPTR,
8662         offsetof(union node, narg.next)|NODE_NOMORE,
8663 #define COPYNODE_OPS9   (COPYNODE_OPS8 + 3)
8664         offsetof(union node, nfile.fname),
8665         offsetof(union node, nfile.fd)|NODE_INTEGER,
8666         offsetof(union node, nfile.next)|NODE_NOMORE,
8667 #define COPYNODE_OPS10   (COPYNODE_OPS9 + 3)
8668         offsetof(union node, ndup.vname),
8669         offsetof(union node, ndup.dupfd)|NODE_INTEGER,
8670         offsetof(union node, ndup.fd)|NODE_INTEGER,
8671         offsetof(union node, ndup.next)|NODE_NOMORE,
8672 #define COPYNODE_OPS11   (COPYNODE_OPS10 + 4)
8673         offsetof(union node, nhere.doc),
8674         offsetof(union node, nhere.fd)|NODE_INTEGER,
8675         offsetof(union node, nhere.next)|NODE_NOMORE,
8676 #define COPYNODE_OPS12   (COPYNODE_OPS11 + 3)
8677         offsetof(union node, nnot.com)|NODE_NOMORE,
8678 };
8679
8680 #if COPYNODE_OPS12 != 34
8681 #error COPYNODE_OPS12 is incorrect
8682 #endif
8683
8684 static const unsigned char copynode_ops_index[26] = {
8685         COPYNODE_OPS0, /* NSEMI */
8686         COPYNODE_OPS1, /* NCMD */
8687         COPYNODE_OPS2, /* NPIPE */
8688         COPYNODE_OPS3, /* NREDIR */
8689         COPYNODE_OPS3, /* NBACKGND */
8690         COPYNODE_OPS3, /* NSUBSHELL */
8691         COPYNODE_OPS0, /* NAND */
8692         COPYNODE_OPS0, /* NOR */
8693         COPYNODE_OPS4, /* NIF */
8694         COPYNODE_OPS0, /* NWHILE */
8695         COPYNODE_OPS0, /* NUNTIL */
8696         COPYNODE_OPS5, /* NFOR */
8697         COPYNODE_OPS6, /* NCASE */
8698         COPYNODE_OPS7, /* NCLIST */
8699         COPYNODE_OPS8, /* NDEFUN */
8700         COPYNODE_OPS8, /* NARG */
8701         COPYNODE_OPS9, /* NTO */
8702         COPYNODE_OPS9, /* NFROM */
8703         COPYNODE_OPS9, /* NFROMTO */
8704         COPYNODE_OPS9, /* NAPPEND */
8705         COPYNODE_OPS9, /* NTOOV */
8706         COPYNODE_OPS10, /* NTOFD */
8707         COPYNODE_OPS10, /* NFROMFD */
8708         COPYNODE_OPS11, /* NHERE */
8709         COPYNODE_OPS11, /* NXHERE */
8710         COPYNODE_OPS12, /* NNOT */
8711 };
8712
8713 #if NODE_CHARPTR != NODE_MBRMASK
8714 #error NODE_CHARPTR != NODE_MBRMASK!!!
8715 #endif
8716 #endif /* defined(CALCSIZE_TABLE) || defined(COPYNODE_TABLE) */
8717
8718 #ifdef COPYNODE_TABLE
8719 static union node *
8720 copynode(const union node *n)
8721 {
8722       union node *new;
8723           const unsigned char *p;
8724
8725       if (n == NULL) {
8726           return NULL;
8727           }
8728       new = funcblock;
8729       new->type = n->type;
8730       funcblock = (char *) funcblock + (int) nodesize[n->type];
8731           p = copynode_ops + (int) copynode_ops_index[n->type];
8732           do {
8733                   char *nn = ((char *) new) + ((int)(*p & NODE_OFFSETMASK));
8734                   const char *no = ((const char *) n) + ((int)(*p & NODE_OFFSETMASK));
8735
8736                   if (!(*p & NODE_MBRMASK)) { /* standard node */
8737                           *((union node **)nn) = copynode(*((const union node **) no));
8738                   } else if ((*p & NODE_MBRMASK) == NODE_CHARPTR) { /* string */
8739                           *((const char **)nn) = nodesavestr(*((const char **)no));
8740                   } else if (*p & NODE_NODELIST) { /* nodelist */
8741                           *((struct nodelist **)nn)
8742                                   = copynodelist(*((const struct nodelist **) no));
8743                   } else {                              /* integer */
8744                           *((int *) nn) = *((int *) no);
8745                   }
8746           } while (!(*p++ & NODE_NOMORE));
8747       return new;
8748 }
8749 #else  /* COPYNODE_TABLE */
8750 static union node *
8751 copynode(const union node *n)
8752 {
8753       union node *new;
8754
8755       if (n == NULL)
8756         return NULL;
8757       new = funcblock;
8758       funcblock = (char *) funcblock + nodesize[n->type];
8759       switch (n->type) {
8760       case NSEMI:
8761       case NAND:
8762       case NOR:
8763       case NWHILE:
8764       case NUNTIL:
8765             new->nbinary.ch2 = copynode(n->nbinary.ch2);
8766             new->nbinary.ch1 = copynode(n->nbinary.ch1);
8767             break;
8768       case NCMD:
8769             new->ncmd.redirect = copynode(n->ncmd.redirect);
8770             new->ncmd.args = copynode(n->ncmd.args);
8771             new->ncmd.assign = copynode(n->ncmd.assign);
8772             new->ncmd.backgnd = n->ncmd.backgnd;
8773             break;
8774       case NPIPE:
8775             new->npipe.cmdlist = copynodelist(n->npipe.cmdlist);
8776             new->npipe.backgnd = n->npipe.backgnd;
8777             break;
8778       case NREDIR:
8779       case NBACKGND:
8780       case NSUBSHELL:
8781             new->nredir.redirect = copynode(n->nredir.redirect);
8782             new->nredir.n = copynode(n->nredir.n);
8783             break;
8784       case NIF:
8785             new->nif.elsepart = copynode(n->nif.elsepart);
8786             new->nif.ifpart = copynode(n->nif.ifpart);
8787             new->nif.test = copynode(n->nif.test);
8788             break;
8789       case NFOR:
8790             new->nfor.var = nodesavestr(n->nfor.var);
8791             new->nfor.body = copynode(n->nfor.body);
8792             new->nfor.args = copynode(n->nfor.args);
8793             break;
8794       case NCASE:
8795             new->ncase.cases = copynode(n->ncase.cases);
8796             new->ncase.expr = copynode(n->ncase.expr);
8797             break;
8798       case NCLIST:
8799             new->nclist.body = copynode(n->nclist.body);
8800             new->nclist.pattern = copynode(n->nclist.pattern);
8801             new->nclist.next = copynode(n->nclist.next);
8802             break;
8803       case NDEFUN:
8804       case NARG:
8805             new->narg.backquote = copynodelist(n->narg.backquote);
8806             new->narg.text = nodesavestr(n->narg.text);
8807             new->narg.next = copynode(n->narg.next);
8808             break;
8809       case NTO:
8810       case NFROM:
8811       case NFROMTO:
8812       case NAPPEND:
8813       case NTOOV:
8814             new->nfile.fname = copynode(n->nfile.fname);
8815             new->nfile.fd = n->nfile.fd;
8816             new->nfile.next = copynode(n->nfile.next);
8817             break;
8818       case NTOFD:
8819       case NFROMFD:
8820             new->ndup.vname = copynode(n->ndup.vname);
8821             new->ndup.dupfd = n->ndup.dupfd;
8822             new->ndup.fd = n->ndup.fd;
8823             new->ndup.next = copynode(n->ndup.next);
8824             break;
8825       case NHERE:
8826       case NXHERE:
8827             new->nhere.doc = copynode(n->nhere.doc);
8828             new->nhere.fd = n->nhere.fd;
8829             new->nhere.next = copynode(n->nhere.next);
8830             break;
8831       case NNOT:
8832             new->nnot.com = copynode(n->nnot.com);
8833             break;
8834       };
8835       new->type = n->type;
8836       return new;
8837 }
8838 #endif /* COPYNODE_TABLE */
8839
8840 #ifdef CALCSIZE_TABLE
8841 static void
8842 calcsize(const union node *n)
8843 {
8844           const unsigned char *p;
8845
8846       if (n == NULL)
8847             return;
8848       funcblocksize += (int) nodesize[n->type];
8849
8850           p = copynode_ops + (int) copynode_ops_index[n->type];
8851           do {
8852                   const char *no = ((const char *) n) + ((int)(*p & NODE_OFFSETMASK));
8853
8854                   if (!(*p & NODE_MBRMASK)) { /* standard node */
8855                           calcsize(*((const union node **) no));
8856                   } else if ((*p & NODE_MBRMASK) == NODE_CHARPTR) { /* string */
8857                           funcstringsize += strlen(*((const char **)no)) + 1;
8858                   } else if (*p & NODE_NODELIST) { /* nodelist */
8859                           sizenodelist(*((const struct nodelist **) no));
8860                   }     /* else integer -- ignore */
8861           } while (!(*p++ & NODE_NOMORE));
8862 }
8863 #else  /* CALCSIZE_TABLE */
8864 static void
8865 calcsize(const union node *n)
8866 {
8867       if (n == NULL)
8868             return;
8869       funcblocksize += nodesize[n->type];
8870       switch (n->type) {
8871       case NSEMI:
8872       case NAND:
8873       case NOR:
8874       case NWHILE:
8875       case NUNTIL:
8876             calcsize(n->nbinary.ch2);
8877             calcsize(n->nbinary.ch1);
8878             break;
8879       case NCMD:
8880             calcsize(n->ncmd.redirect);
8881             calcsize(n->ncmd.args);
8882             calcsize(n->ncmd.assign);
8883             break;
8884       case NPIPE:
8885             sizenodelist(n->npipe.cmdlist);
8886             break;
8887       case NREDIR:
8888       case NBACKGND:
8889       case NSUBSHELL:
8890             calcsize(n->nredir.redirect);
8891             calcsize(n->nredir.n);
8892             break;
8893       case NIF:
8894             calcsize(n->nif.elsepart);
8895             calcsize(n->nif.ifpart);
8896             calcsize(n->nif.test);
8897             break;
8898       case NFOR:
8899             funcstringsize += strlen(n->nfor.var) + 1;
8900             calcsize(n->nfor.body);
8901             calcsize(n->nfor.args);
8902             break;
8903       case NCASE:
8904             calcsize(n->ncase.cases);
8905             calcsize(n->ncase.expr);
8906             break;
8907       case NCLIST:
8908             calcsize(n->nclist.body);
8909             calcsize(n->nclist.pattern);
8910             calcsize(n->nclist.next);
8911             break;
8912       case NDEFUN:
8913       case NARG:
8914             sizenodelist(n->narg.backquote);
8915             funcstringsize += strlen(n->narg.text) + 1;
8916             calcsize(n->narg.next);
8917             break;
8918       case NTO:
8919       case NFROM:
8920       case NFROMTO:
8921       case NAPPEND:
8922       case NTOOV:
8923             calcsize(n->nfile.fname);
8924             calcsize(n->nfile.next);
8925             break;
8926       case NTOFD:
8927       case NFROMFD:
8928             calcsize(n->ndup.vname);
8929             calcsize(n->ndup.next);
8930             break;
8931       case NHERE:
8932       case NXHERE:
8933             calcsize(n->nhere.doc);
8934             calcsize(n->nhere.next);
8935             break;
8936       case NNOT:
8937             calcsize(n->nnot.com);
8938             break;
8939       };
8940 }
8941 #endif /* CALCSIZE_TABLE */
8942
8943 static void
8944 sizenodelist(const struct nodelist *lp)
8945 {
8946         while (lp) {
8947                 funcblocksize += ALIGN(sizeof(struct nodelist));
8948                 calcsize(lp->n);
8949                 lp = lp->next;
8950         }
8951 }
8952
8953
8954 static struct nodelist *
8955 copynodelist(const struct nodelist *lp)
8956 {
8957         struct nodelist *start;
8958         struct nodelist **lpp;
8959
8960         lpp = &start;
8961         while (lp) {
8962                 *lpp = funcblock;
8963                 funcblock = (char *) funcblock + ALIGN(sizeof(struct nodelist));
8964                 (*lpp)->n = copynode(lp->n);
8965                 lp = lp->next;
8966                 lpp = &(*lpp)->next;
8967         }
8968         *lpp = NULL;
8969         return start;
8970 }
8971
8972
8973 static char *
8974 nodesavestr(const char *s)
8975 {
8976         const char *p = s;
8977         char *q = funcstring;
8978         char   *rtn = funcstring;
8979
8980         while ((*q++ = *p++) != '\0')
8981                 continue;
8982         funcstring = q;
8983         return rtn;
8984 }
8985
8986 #ifdef ASH_GETOPTS
8987 static int getopts (char *, char *, char **, int *, int *);
8988 #endif
8989
8990
8991 /*
8992  * Process the shell command line arguments.
8993  */
8994
8995 static void
8996 procargs(argc, argv)
8997         int argc;
8998         char **argv;
8999 {
9000         int i;
9001
9002         argptr = argv;
9003         if (argc > 0)
9004                 argptr++;
9005         for (i = 0; i < NOPTS; i++)
9006                 optent_val(i) = 2;
9007         options(1);
9008         if (*argptr == NULL && minusc == NULL)
9009                 sflag = 1;
9010         if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
9011                 iflag = 1;
9012         if (mflag == 2)
9013                 mflag = iflag;
9014         for (i = 0; i < NOPTS; i++)
9015                 if (optent_val(i) == 2)
9016                         optent_val(i) = 0;
9017         arg0 = argv[0];
9018         if (sflag == 0 && minusc == NULL) {
9019                 commandname = argv[0];
9020                 arg0 = *argptr++;
9021                 setinputfile(arg0, 0);
9022                 commandname = arg0;
9023         }
9024         /* POSIX 1003.2: first arg after -c cmd is $0, remainder $1... */
9025         if (argptr && minusc && *argptr)
9026                 arg0 = *argptr++;
9027
9028         shellparam.p = argptr;
9029         shellparam.optind = 1;
9030         shellparam.optoff = -1;
9031         /* assert(shellparam.malloc == 0 && shellparam.nparam == 0); */
9032         while (*argptr) {
9033                 shellparam.nparam++;
9034                 argptr++;
9035         }
9036         optschanged();
9037 }
9038
9039
9040
9041 /*
9042  * Process shell options.  The global variable argptr contains a pointer
9043  * to the argument list; we advance it past the options.
9044  */
9045
9046 static inline void
9047 minus_o(const char *name, int val)
9048 {
9049         int i;
9050
9051         if (name == NULL) {
9052                 out1str("Current option settings\n");
9053                 for (i = 0; i < NOPTS; i++)
9054                         printf("%-16s%s\n", optent_name(optlist[i]),
9055                                 optent_val(i) ? "on" : "off");
9056         } else {
9057                 for (i = 0; i < NOPTS; i++)
9058                         if (equal(name, optent_name(optlist[i]))) {
9059                                 setoption(optent_letter(optlist[i]), val);
9060                                 return;
9061                         }
9062                 error("Illegal option -o %s", name);
9063         }
9064 }
9065
9066
9067 static void
9068 options(int cmdline)
9069 {
9070         char *p;
9071         int val;
9072         int c;
9073
9074         if (cmdline)
9075                 minusc = NULL;
9076         while ((p = *argptr) != NULL) {
9077                 argptr++;
9078                 if ((c = *p++) == '-') {
9079                         val = 1;
9080                         if (p[0] == '\0' || (p[0] == '-' && p[1] == '\0')) {
9081                                 if (!cmdline) {
9082                                         /* "-" means turn off -x and -v */
9083                                         if (p[0] == '\0')
9084                                                 xflag = vflag = 0;
9085                                         /* "--" means reset params */
9086                                         else if (*argptr == NULL)
9087                                                 setparam(argptr);
9088                                 }
9089                                 break;    /* "-" or  "--" terminates options */
9090                         }
9091                 } else if (c == '+') {
9092                         val = 0;
9093                 } else {
9094                         argptr--;
9095                         break;
9096                 }
9097                 while ((c = *p++) != '\0') {
9098                         if (c == 'c' && cmdline) {
9099                                 char *q;
9100 #ifdef NOHACK   /* removing this code allows sh -ce 'foo' for compat */
9101                                 if (*p == '\0')
9102 #endif
9103                                         q = *argptr++;
9104                                 if (q == NULL || minusc != NULL)
9105                                         error("Bad -c option");
9106                                 minusc = q;
9107 #ifdef NOHACK
9108                                 break;
9109 #endif
9110                         } else if (c == 'o') {
9111                                 minus_o(*argptr, val);
9112                                 if (*argptr)
9113                                         argptr++;
9114                         } else {
9115                                 setoption(c, val);
9116                         }
9117                 }
9118         }
9119 }
9120
9121
9122 static void
9123 setoption(int flag, int val)
9124 {
9125         int i;
9126
9127         for (i = 0; i < NOPTS; i++)
9128                 if (optent_letter(optlist[i]) == flag) {
9129                         optent_val(i) = val;
9130                         if (val) {
9131                                 /* #%$ hack for ksh semantics */
9132                                 if (flag == 'V')
9133                                         Eflag = 0;
9134                                 else if (flag == 'E')
9135                                         Vflag = 0;
9136                         }
9137                         return;
9138                 }
9139         error("Illegal option -%c", flag);
9140         /* NOTREACHED */
9141 }
9142
9143
9144
9145 /*
9146  * Set the shell parameters.
9147  */
9148
9149 static void
9150 setparam(char **argv)
9151 {
9152         char **newparam;
9153         char **ap;
9154         int nparam;
9155
9156         for (nparam = 0 ; argv[nparam] ; nparam++);
9157         ap = newparam = ckmalloc((nparam + 1) * sizeof *ap);
9158         while (*argv) {
9159                 *ap++ = savestr(*argv++);
9160         }
9161         *ap = NULL;
9162         freeparam(&shellparam);
9163         shellparam.malloc = 1;
9164         shellparam.nparam = nparam;
9165         shellparam.p = newparam;
9166         shellparam.optind = 1;
9167         shellparam.optoff = -1;
9168 }
9169
9170
9171 /*
9172  * Free the list of positional parameters.
9173  */
9174
9175 static void
9176 freeparam(volatile struct shparam *param)
9177 {
9178         char **ap;
9179
9180         if (param->malloc) {
9181                 for (ap = param->p ; *ap ; ap++)
9182                         ckfree(*ap);
9183                 ckfree(param->p);
9184         }
9185 }
9186
9187
9188
9189 /*
9190  * The shift builtin command.
9191  */
9192
9193 static int
9194 shiftcmd(argc, argv)
9195         int argc;
9196         char **argv;
9197 {
9198         int n;
9199         char **ap1, **ap2;
9200
9201         n = 1;
9202         if (argc > 1)
9203                 n = number(argv[1]);
9204         if (n > shellparam.nparam)
9205                 error("can't shift that many");
9206         INTOFF;
9207         shellparam.nparam -= n;
9208         for (ap1 = shellparam.p ; --n >= 0 ; ap1++) {
9209                 if (shellparam.malloc)
9210                         ckfree(*ap1);
9211         }
9212         ap2 = shellparam.p;
9213         while ((*ap2++ = *ap1++) != NULL);
9214         shellparam.optind = 1;
9215         shellparam.optoff = -1;
9216         INTON;
9217         return 0;
9218 }
9219
9220
9221
9222 /*
9223  * The set command builtin.
9224  */
9225
9226 static int
9227 setcmd(argc, argv)
9228         int argc;
9229         char **argv;
9230 {
9231         if (argc == 1)
9232                 return showvarscmd(argc, argv);
9233         INTOFF;
9234         options(0);
9235         optschanged();
9236         if (*argptr != NULL) {
9237                 setparam(argptr);
9238         }
9239         INTON;
9240         return 0;
9241 }
9242
9243
9244 static void
9245 getoptsreset(const char *value)
9246 {
9247         shellparam.optind = number(value);
9248         shellparam.optoff = -1;
9249 }
9250
9251 #ifdef CONFIG_LOCALE_SUPPORT
9252 static void change_lc_all(const char *value)
9253 {
9254         if(value != 0 && *value != 0)
9255                 setlocale(LC_ALL, value);
9256 }
9257
9258 static void change_lc_ctype(const char *value)
9259 {
9260         if(value != 0 && *value != 0)
9261                 setlocale(LC_CTYPE, value);
9262 }
9263
9264 #endif
9265
9266 #ifdef ASH_GETOPTS
9267 /*
9268  * The getopts builtin.  Shellparam.optnext points to the next argument
9269  * to be processed.  Shellparam.optptr points to the next character to
9270  * be processed in the current argument.  If shellparam.optnext is NULL,
9271  * then it's the first time getopts has been called.
9272  */
9273
9274 static int
9275 getoptscmd(argc, argv)
9276         int argc;
9277         char **argv;
9278 {
9279         char **optbase;
9280
9281         if (argc < 3)
9282                 error("Usage: getopts optstring var [arg]");
9283         else if (argc == 3) {
9284                 optbase = shellparam.p;
9285                 if (shellparam.optind > shellparam.nparam + 1) {
9286                         shellparam.optind = 1;
9287                         shellparam.optoff = -1;
9288                 }
9289         }
9290         else {
9291                 optbase = &argv[3];
9292                 if (shellparam.optind > argc - 2) {
9293                         shellparam.optind = 1;
9294                         shellparam.optoff = -1;
9295                 }
9296         }
9297
9298         return getopts(argv[1], argv[2], optbase, &shellparam.optind,
9299                        &shellparam.optoff);
9300 }
9301
9302 /*
9303  * Safe version of setvar, returns 1 on success 0 on failure.
9304  */
9305
9306 static int
9307 setvarsafe(name, val, flags)
9308         const char *name, *val;
9309         int flags;
9310 {
9311         struct jmploc jmploc;
9312         struct jmploc *volatile savehandler = handler;
9313         int err = 0;
9314 #ifdef __GNUC__
9315         (void) &err;
9316 #endif
9317
9318         if (setjmp(jmploc.loc))
9319                 err = 1;
9320         else {
9321                 handler = &jmploc;
9322                 setvar(name, val, flags);
9323         }
9324         handler = savehandler;
9325         return err;
9326 }
9327
9328 static int
9329 getopts(optstr, optvar, optfirst, myoptind, optoff)
9330         char *optstr;
9331         char *optvar;
9332         char **optfirst;
9333         int *myoptind;
9334         int *optoff;
9335 {
9336         char *p, *q;
9337         char c = '?';
9338         int done = 0;
9339         int err = 0;
9340         char s[10];
9341         char **optnext = optfirst + *myoptind - 1;
9342
9343         if (*myoptind <= 1 || *optoff < 0 || !(*(optnext - 1)) ||
9344             strlen(*(optnext - 1)) < *optoff)
9345                 p = NULL;
9346         else
9347                 p = *(optnext - 1) + *optoff;
9348         if (p == NULL || *p == '\0') {
9349                 /* Current word is done, advance */
9350                 if (optnext == NULL)
9351                         return 1;
9352                 p = *optnext;
9353                 if (p == NULL || *p != '-' || *++p == '\0') {
9354 atend:
9355                         *myoptind = optnext - optfirst + 1;
9356                         p = NULL;
9357                         done = 1;
9358                         goto out;
9359                 }
9360                 optnext++;
9361                 if (p[0] == '-' && p[1] == '\0')        /* check for "--" */
9362                         goto atend;
9363         }
9364
9365         c = *p++;
9366         for (q = optstr; *q != c; ) {
9367                 if (*q == '\0') {
9368                         if (optstr[0] == ':') {
9369                                 s[0] = c;
9370                                 s[1] = '\0';
9371                                 err |= setvarsafe("OPTARG", s, 0);
9372                         }
9373                         else {
9374                                 out2fmt("Illegal option -%c\n", c);
9375                                 (void) unsetvar("OPTARG");
9376                         }
9377                         c = '?';
9378                         goto bad;
9379                 }
9380                 if (*++q == ':')
9381                         q++;
9382         }
9383
9384         if (*++q == ':') {
9385                 if (*p == '\0' && (p = *optnext) == NULL) {
9386                         if (optstr[0] == ':') {
9387                                 s[0] = c;
9388                                 s[1] = '\0';
9389                                 err |= setvarsafe("OPTARG", s, 0);
9390                                 c = ':';
9391                         }
9392                         else {
9393                                 out2fmt("No arg for -%c option\n", c);
9394                                 (void) unsetvar("OPTARG");
9395                                 c = '?';
9396                         }
9397                         goto bad;
9398                 }
9399
9400                 if (p == *optnext)
9401                         optnext++;
9402                 setvarsafe("OPTARG", p, 0);
9403                 p = NULL;
9404         }
9405         else
9406                 setvarsafe("OPTARG", "", 0);
9407         *myoptind = optnext - optfirst + 1;
9408         goto out;
9409
9410 bad:
9411         *myoptind = 1;
9412         p = NULL;
9413 out:
9414         *optoff = p ? p - *(optnext - 1) : -1;
9415         snprintf(s, sizeof(s), "%d", *myoptind);
9416         err |= setvarsafe("OPTIND", s, VNOFUNC);
9417         s[0] = c;
9418         s[1] = '\0';
9419         err |= setvarsafe(optvar, s, 0);
9420         if (err) {
9421                 *myoptind = 1;
9422                 *optoff = -1;
9423                 exraise(EXERROR);
9424         }
9425         return done;
9426 }
9427 #endif
9428
9429 /*
9430  * XXX - should get rid of.  have all builtins use getopt(3).  the
9431  * library getopt must have the BSD extension static variable "optreset"
9432  * otherwise it can't be used within the shell safely.
9433  *
9434  * Standard option processing (a la getopt) for builtin routines.  The
9435  * only argument that is passed to nextopt is the option string; the
9436  * other arguments are unnecessary.  It return the character, or '\0' on
9437  * end of input.
9438  */
9439
9440 static int
9441 nextopt(const char *optstring)
9442 {
9443         char *p;
9444         const char *q;
9445         char c;
9446
9447         if ((p = optptr) == NULL || *p == '\0') {
9448                 p = *argptr;
9449                 if (p == NULL || *p != '-' || *++p == '\0')
9450                         return '\0';
9451                 argptr++;
9452                 if (p[0] == '-' && p[1] == '\0')        /* check for "--" */
9453                         return '\0';
9454         }
9455         c = *p++;
9456         for (q = optstring ; *q != c ; ) {
9457                 if (*q == '\0')
9458                         error("Illegal option -%c", c);
9459                 if (*++q == ':')
9460                         q++;
9461         }
9462         if (*++q == ':') {
9463                 if (*p == '\0' && (p = *argptr++) == NULL)
9464                         error("No arg for -%c option", c);
9465                 optionarg = p;
9466                 p = NULL;
9467         }
9468         optptr = p;
9469         return c;
9470 }
9471
9472 static void
9473 flushall() {
9474         INTOFF;
9475         fflush(stdout);
9476         INTON;
9477 }
9478
9479
9480 static void
9481 out2fmt(const char *fmt, ...)
9482 {
9483         va_list ap;
9484         va_start(ap, fmt);
9485         vfprintf(stderr, fmt, ap);
9486         va_end(ap);
9487 }
9488
9489 /*
9490  * Version of write which resumes after a signal is caught.
9491  */
9492
9493 static int
9494 xwrite(int fd, const char *buf, int nbytes)
9495 {
9496         int ntry;
9497         int i;
9498         int n;
9499
9500         n = nbytes;
9501         ntry = 0;
9502         for (;;) {
9503                 i = write(fd, buf, n);
9504                 if (i > 0) {
9505                         if ((n -= i) <= 0)
9506                                 return nbytes;
9507                         buf += i;
9508                         ntry = 0;
9509                 } else if (i == 0) {
9510                         if (++ntry > 10)
9511                                 return nbytes - n;
9512                 } else if (errno != EINTR) {
9513                         return -1;
9514                 }
9515         }
9516 }
9517
9518
9519 /*
9520  * Shell command parser.
9521  */
9522
9523 #define EOFMARKLEN 79
9524
9525
9526
9527 struct heredoc {
9528         struct heredoc *next;   /* next here document in list */
9529         union node *here;               /* redirection node */
9530         char *eofmark;          /* string indicating end of input */
9531         int striptabs;          /* if set, strip leading tabs */
9532 };
9533
9534 static struct heredoc *heredoclist;     /* list of here documents to read */
9535 static int parsebackquote;              /* nonzero if we are inside backquotes */
9536 static int doprompt;                    /* if set, prompt the user */
9537 static int needprompt;                  /* true if interactive and at start of line */
9538 static int lasttoken;                   /* last token read */
9539
9540 static char *wordtext;                  /* text of last word returned by readtoken */
9541
9542 static struct nodelist *backquotelist;
9543 static union node *redirnode;
9544 static struct heredoc *heredoc;
9545 static int quoteflag;                   /* set if (part of) last token was quoted */
9546 static int startlinno;                  /* line # where last token started */
9547
9548
9549 static union node *list (int);
9550 static union node *andor (void);
9551 static union node *pipeline (void);
9552 static union node *command (void);
9553 static union node *simplecmd(union node **rpp, union node *redir);
9554 static void parsefname (void);
9555 static void parseheredoc (void);
9556 static char peektoken (void);
9557 static int readtoken (void);
9558 static int xxreadtoken (void);
9559 static int readtoken1 (int, int, const char *, int);
9560 static int noexpand (char *);
9561 static void synexpect (int) __attribute__((noreturn));
9562 static void synerror (const char *) __attribute__((noreturn));
9563 static void setprompt (int);
9564
9565
9566 /*
9567  * Read and parse a command.  Returns NEOF on end of file.  (NULL is a
9568  * valid parse tree indicating a blank line.)
9569  */
9570
9571 static union node *
9572 parsecmd(int interact)
9573 {
9574         int t;
9575
9576         tokpushback = 0;
9577         doprompt = interact;
9578         if (doprompt)
9579                 setprompt(1);
9580         else
9581                 setprompt(0);
9582         needprompt = 0;
9583         t = readtoken();
9584         if (t == TEOF)
9585                 return NEOF;
9586         if (t == TNL)
9587                 return NULL;
9588         tokpushback++;
9589         return list(1);
9590 }
9591
9592
9593 static union node *
9594 list(nlflag)
9595         int nlflag;
9596 {
9597         union node *n1, *n2, *n3;
9598         int tok;
9599
9600         checkkwd = 2;
9601         if (nlflag == 0 && peektoken())
9602                 return NULL;
9603         n1 = NULL;
9604         for (;;) {
9605                 n2 = andor();
9606                 tok = readtoken();
9607                 if (tok == TBACKGND) {
9608                         if (n2->type == NCMD || n2->type == NPIPE) {
9609                                 n2->ncmd.backgnd = 1;
9610                         } else if (n2->type == NREDIR) {
9611                                 n2->type = NBACKGND;
9612                         } else {
9613                                 n3 = (union node *)stalloc(sizeof (struct nredir));
9614                                 n3->type = NBACKGND;
9615                                 n3->nredir.n = n2;
9616                                 n3->nredir.redirect = NULL;
9617                                 n2 = n3;
9618                         }
9619                 }
9620                 if (n1 == NULL) {
9621                         n1 = n2;
9622                 }
9623                 else {
9624                         n3 = (union node *)stalloc(sizeof (struct nbinary));
9625                         n3->type = NSEMI;
9626                         n3->nbinary.ch1 = n1;
9627                         n3->nbinary.ch2 = n2;
9628                         n1 = n3;
9629                 }
9630                 switch (tok) {
9631                 case TBACKGND:
9632                 case TSEMI:
9633                         tok = readtoken();
9634                         /* fall through */
9635                 case TNL:
9636                         if (tok == TNL) {
9637                                 parseheredoc();
9638                                 if (nlflag)
9639                                         return n1;
9640                         } else {
9641                                 tokpushback++;
9642                         }
9643                         checkkwd = 2;
9644                         if (peektoken())
9645                                 return n1;
9646                         break;
9647                 case TEOF:
9648                         if (heredoclist)
9649                                 parseheredoc();
9650                         else
9651                                 pungetc();              /* push back EOF on input */
9652                         return n1;
9653                 default:
9654                         if (nlflag)
9655                                 synexpect(-1);
9656                         tokpushback++;
9657                         return n1;
9658                 }
9659         }
9660 }
9661
9662
9663
9664 static union node *
9665 andor() {
9666         union node *n1, *n2, *n3;
9667         int t;
9668
9669         checkkwd = 1;
9670         n1 = pipeline();
9671         for (;;) {
9672                 if ((t = readtoken()) == TAND) {
9673                         t = NAND;
9674                 } else if (t == TOR) {
9675                         t = NOR;
9676                 } else {
9677                         tokpushback++;
9678                         return n1;
9679                 }
9680                 checkkwd = 2;
9681                 n2 = pipeline();
9682                 n3 = (union node *)stalloc(sizeof (struct nbinary));
9683                 n3->type = t;
9684                 n3->nbinary.ch1 = n1;
9685                 n3->nbinary.ch2 = n2;
9686                 n1 = n3;
9687         }
9688 }
9689
9690
9691
9692 static union node *
9693 pipeline() {
9694         union node *n1, *n2, *pipenode;
9695         struct nodelist *lp, *prev;
9696         int negate;
9697
9698         negate = 0;
9699         TRACE(("pipeline: entered\n"));
9700         if (readtoken() == TNOT) {
9701                 negate = !negate;
9702                 checkkwd = 1;
9703         } else
9704                 tokpushback++;
9705         n1 = command();
9706         if (readtoken() == TPIPE) {
9707                 pipenode = (union node *)stalloc(sizeof (struct npipe));
9708                 pipenode->type = NPIPE;
9709                 pipenode->npipe.backgnd = 0;
9710                 lp = (struct nodelist *)stalloc(sizeof (struct nodelist));
9711                 pipenode->npipe.cmdlist = lp;
9712                 lp->n = n1;
9713                 do {
9714                         prev = lp;
9715                         lp = (struct nodelist *)stalloc(sizeof (struct nodelist));
9716                         checkkwd = 2;
9717                         lp->n = command();
9718                         prev->next = lp;
9719                 } while (readtoken() == TPIPE);
9720                 lp->next = NULL;
9721                 n1 = pipenode;
9722         }
9723         tokpushback++;
9724         if (negate) {
9725                 n2 = (union node *)stalloc(sizeof (struct nnot));
9726                 n2->type = NNOT;
9727                 n2->nnot.com = n1;
9728                 return n2;
9729         } else
9730                 return n1;
9731 }
9732
9733
9734
9735 static union node *
9736 command(void) {
9737         union node *n1, *n2;
9738         union node *ap, **app;
9739         union node *cp, **cpp;
9740         union node *redir, **rpp;
9741         int t;
9742
9743         redir = NULL;
9744         n1 = NULL;
9745         rpp = &redir;
9746
9747         /* Check for redirection which may precede command */
9748         while (readtoken() == TREDIR) {
9749                 *rpp = n2 = redirnode;
9750                 rpp = &n2->nfile.next;
9751                 parsefname();
9752         }
9753         tokpushback++;
9754
9755         switch (readtoken()) {
9756         case TIF:
9757                 n1 = (union node *)stalloc(sizeof (struct nif));
9758                 n1->type = NIF;
9759                 n1->nif.test = list(0);
9760                 if (readtoken() != TTHEN)
9761                         synexpect(TTHEN);
9762                 n1->nif.ifpart = list(0);
9763                 n2 = n1;
9764                 while (readtoken() == TELIF) {
9765                         n2->nif.elsepart = (union node *)stalloc(sizeof (struct nif));
9766                         n2 = n2->nif.elsepart;
9767                         n2->type = NIF;
9768                         n2->nif.test = list(0);
9769                         if (readtoken() != TTHEN)
9770                                 synexpect(TTHEN);
9771                         n2->nif.ifpart = list(0);
9772                 }
9773                 if (lasttoken == TELSE)
9774                         n2->nif.elsepart = list(0);
9775                 else {
9776                         n2->nif.elsepart = NULL;
9777                         tokpushback++;
9778                 }
9779                 if (readtoken() != TFI)
9780                         synexpect(TFI);
9781                 checkkwd = 1;
9782                 break;
9783         case TWHILE:
9784         case TUNTIL: {
9785                 int got;
9786                 n1 = (union node *)stalloc(sizeof (struct nbinary));
9787                 n1->type = (lasttoken == TWHILE)? NWHILE : NUNTIL;
9788                 n1->nbinary.ch1 = list(0);
9789                 if ((got=readtoken()) != TDO) {
9790 TRACE(("expecting DO got %s %s\n", tokname(got), got == TWORD ? wordtext : ""));
9791                         synexpect(TDO);
9792                 }
9793                 n1->nbinary.ch2 = list(0);
9794                 if (readtoken() != TDONE)
9795                         synexpect(TDONE);
9796                 checkkwd = 1;
9797                 break;
9798         }
9799         case TFOR:
9800                 if (readtoken() != TWORD || quoteflag || ! goodname(wordtext))
9801                         synerror("Bad for loop variable");
9802                 n1 = (union node *)stalloc(sizeof (struct nfor));
9803                 n1->type = NFOR;
9804                 n1->nfor.var = wordtext;
9805                 checkkwd = 1;
9806                 if (readtoken() == TIN) {
9807                         app = &ap;
9808                         while (readtoken() == TWORD) {
9809                                 n2 = (union node *)stalloc(sizeof (struct narg));
9810                                 n2->type = NARG;
9811                                 n2->narg.text = wordtext;
9812                                 n2->narg.backquote = backquotelist;
9813                                 *app = n2;
9814                                 app = &n2->narg.next;
9815                         }
9816                         *app = NULL;
9817                         n1->nfor.args = ap;
9818                         if (lasttoken != TNL && lasttoken != TSEMI)
9819                                 synexpect(-1);
9820                 } else {
9821                         static char argvars[5] = {CTLVAR, VSNORMAL|VSQUOTE,
9822                                                                    '@', '=', '\0'};
9823                         n2 = (union node *)stalloc(sizeof (struct narg));
9824                         n2->type = NARG;
9825                         n2->narg.text = argvars;
9826                         n2->narg.backquote = NULL;
9827                         n2->narg.next = NULL;
9828                         n1->nfor.args = n2;
9829                         /*
9830                          * Newline or semicolon here is optional (but note
9831                          * that the original Bourne shell only allowed NL).
9832                          */
9833                         if (lasttoken != TNL && lasttoken != TSEMI)
9834                                 tokpushback++;
9835                 }
9836                 checkkwd = 2;
9837                 if (readtoken() != TDO)
9838                         synexpect(TDO);
9839                 n1->nfor.body = list(0);
9840                 if (readtoken() != TDONE)
9841                         synexpect(TDONE);
9842                 checkkwd = 1;
9843                 break;
9844         case TCASE:
9845                 n1 = (union node *)stalloc(sizeof (struct ncase));
9846                 n1->type = NCASE;
9847                 if (readtoken() != TWORD)
9848                         synexpect(TWORD);
9849                 n1->ncase.expr = n2 = (union node *)stalloc(sizeof (struct narg));
9850                 n2->type = NARG;
9851                 n2->narg.text = wordtext;
9852                 n2->narg.backquote = backquotelist;
9853                 n2->narg.next = NULL;
9854                 do {
9855                         checkkwd = 1;
9856                 } while (readtoken() == TNL);
9857                 if (lasttoken != TIN)
9858                         synerror("expecting \"in\"");
9859                 cpp = &n1->ncase.cases;
9860                 checkkwd = 2, readtoken();
9861                 do {
9862                         if (lasttoken == TLP)
9863                                 readtoken();
9864                         *cpp = cp = (union node *)stalloc(sizeof (struct nclist));
9865                         cp->type = NCLIST;
9866                         app = &cp->nclist.pattern;
9867                         for (;;) {
9868                                 *app = ap = (union node *)stalloc(sizeof (struct narg));
9869                                 ap->type = NARG;
9870                                 ap->narg.text = wordtext;
9871                                 ap->narg.backquote = backquotelist;
9872                                 if (checkkwd = 2, readtoken() != TPIPE)
9873                                         break;
9874                                 app = &ap->narg.next;
9875                                 readtoken();
9876                         }
9877                         ap->narg.next = NULL;
9878                         if (lasttoken != TRP)
9879                                 synexpect(TRP);
9880                         cp->nclist.body = list(0);
9881
9882                         checkkwd = 2;
9883                         if ((t = readtoken()) != TESAC) {
9884                                 if (t != TENDCASE)
9885                                         synexpect(TENDCASE);
9886                                 else
9887                                         checkkwd = 2, readtoken();
9888                         }
9889                         cpp = &cp->nclist.next;
9890                 } while(lasttoken != TESAC);
9891                 *cpp = NULL;
9892                 checkkwd = 1;
9893                 break;
9894         case TLP:
9895                 n1 = (union node *)stalloc(sizeof (struct nredir));
9896                 n1->type = NSUBSHELL;
9897                 n1->nredir.n = list(0);
9898                 n1->nredir.redirect = NULL;
9899                 if (readtoken() != TRP)
9900                         synexpect(TRP);
9901                 checkkwd = 1;
9902                 break;
9903         case TBEGIN:
9904                 n1 = list(0);
9905                 if (readtoken() != TEND)
9906                         synexpect(TEND);
9907                 checkkwd = 1;
9908                 break;
9909         /* Handle an empty command like other simple commands.  */
9910         case TSEMI:
9911         case TAND:
9912         case TOR:
9913         case TNL:
9914         case TEOF:
9915         case TRP:
9916         case TBACKGND:
9917                 /*
9918                  * An empty command before a ; doesn't make much sense, and
9919                  * should certainly be disallowed in the case of `if ;'.
9920                  */
9921                 if (!redir)
9922                         synexpect(-1);
9923         case TWORD:
9924                 tokpushback++;
9925                 n1 = simplecmd(rpp, redir);
9926                 return n1;
9927         default:
9928                 synexpect(-1);
9929                 /* NOTREACHED */
9930         }
9931
9932         /* Now check for redirection which may follow command */
9933         while (readtoken() == TREDIR) {
9934                 *rpp = n2 = redirnode;
9935                 rpp = &n2->nfile.next;
9936                 parsefname();
9937         }
9938         tokpushback++;
9939         *rpp = NULL;
9940         if (redir) {
9941                 if (n1->type != NSUBSHELL) {
9942                         n2 = (union node *)stalloc(sizeof (struct nredir));
9943                         n2->type = NREDIR;
9944                         n2->nredir.n = n1;
9945                         n1 = n2;
9946                 }
9947                 n1->nredir.redirect = redir;
9948         }
9949
9950         return n1;
9951 }
9952
9953
9954 static union node *
9955 simplecmd(union node **rpp, union node *redir) {
9956         union node *args, **app;
9957         union node *n = NULL;
9958         union node *vars, **vpp;
9959         union node **orig_rpp;
9960
9961         args = NULL;
9962         app = &args;
9963         vars = NULL;
9964         vpp = &vars;
9965
9966         /* If we don't have any redirections already, then we must reset
9967           rpp to be the address of the local redir variable.  */
9968         if (redir == 0)
9969         rpp = &redir;
9970         /* We save the incoming value, because we need this for shell
9971           functions.  There can not be a redirect or an argument between
9972           the function name and the open parenthesis.  */
9973         orig_rpp = rpp;
9974
9975         checkalias = 2;
9976         for (;;) {
9977                 switch (readtoken()) {
9978                 case TWORD:
9979                 case TASSIGN:
9980                         n = (union node *)stalloc(sizeof (struct narg));
9981                         n->type = NARG;
9982                         n->narg.text = wordtext;
9983                         n->narg.backquote = backquotelist;
9984                         if (lasttoken == TWORD) {
9985                                 *app = n;
9986                                 app = &n->narg.next;
9987                         } else {
9988                                 *vpp = n;
9989                                 vpp = &n->narg.next;
9990                         }
9991                         break;
9992                 case TREDIR:
9993                         *rpp = n = redirnode;
9994                         rpp = &n->nfile.next;
9995                         parsefname();   /* read name of redirection file */
9996                         break;
9997                 case TLP:
9998                         if (
9999                                 args && app == &args->narg.next &&
10000                                 !vars && rpp == orig_rpp
10001                         ) {
10002                                 /* We have a function */
10003                                 if (readtoken() != TRP)
10004                                         synexpect(TRP);
10005                                 n->type = NDEFUN;
10006                                 checkkwd = 2;
10007                                 n->narg.next = command();
10008                                 return n;
10009                         }
10010                         /* fall through */
10011                 default:
10012                         tokpushback++;
10013                         goto out;
10014                 }
10015         }
10016 out:
10017         *app = NULL;
10018         *vpp = NULL;
10019         *rpp = NULL;
10020         n = (union node *)stalloc(sizeof (struct ncmd));
10021         n->type = NCMD;
10022         n->ncmd.backgnd = 0;
10023         n->ncmd.args = args;
10024         n->ncmd.assign = vars;
10025         n->ncmd.redirect = redir;
10026         return n;
10027 }
10028
10029 static union node *
10030 makename(void) {
10031         union node *n;
10032
10033         n = (union node *)stalloc(sizeof (struct narg));
10034         n->type = NARG;
10035         n->narg.next = NULL;
10036         n->narg.text = wordtext;
10037         n->narg.backquote = backquotelist;
10038         return n;
10039 }
10040
10041 static void fixredir(union node *n, const char *text, int err)
10042 {
10043         TRACE(("Fix redir %s %d\n", text, err));
10044         if (!err)
10045                 n->ndup.vname = NULL;
10046
10047         if (is_digit(text[0]) && text[1] == '\0')
10048                 n->ndup.dupfd = digit_val(text[0]);
10049         else if (text[0] == '-' && text[1] == '\0')
10050                 n->ndup.dupfd = -1;
10051         else {
10052
10053                 if (err)
10054                         synerror("Bad fd number");
10055                 else
10056                         n->ndup.vname = makename();
10057         }
10058 }
10059
10060
10061 static void
10062 parsefname(void) {
10063         union node *n = redirnode;
10064
10065         if (readtoken() != TWORD)
10066                 synexpect(-1);
10067         if (n->type == NHERE) {
10068                 struct heredoc *here = heredoc;
10069                 struct heredoc *p;
10070                 int i;
10071
10072                 if (quoteflag == 0)
10073                         n->type = NXHERE;
10074                 TRACE(("Here document %d\n", n->type));
10075                 if (here->striptabs) {
10076                         while (*wordtext == '\t')
10077                                 wordtext++;
10078                 }
10079                 if (! noexpand(wordtext) || (i = strlen(wordtext)) == 0 || i > EOFMARKLEN)
10080                         synerror("Illegal eof marker for << redirection");
10081                 rmescapes(wordtext);
10082                 here->eofmark = wordtext;
10083                 here->next = NULL;
10084                 if (heredoclist == NULL)
10085                         heredoclist = here;
10086                 else {
10087                         for (p = heredoclist ; p->next ; p = p->next);
10088                         p->next = here;
10089                 }
10090         } else if (n->type == NTOFD || n->type == NFROMFD) {
10091                 fixredir(n, wordtext, 0);
10092         } else {
10093                 n->nfile.fname = makename();
10094         }
10095 }
10096
10097
10098 /*
10099  * Input any here documents.
10100  */
10101
10102 static void
10103 parseheredoc() {
10104         struct heredoc *here;
10105         union node *n;
10106
10107         while (heredoclist) {
10108                 here = heredoclist;
10109                 heredoclist = here->next;
10110                 if (needprompt) {
10111                         setprompt(2);
10112                         needprompt = 0;
10113                 }
10114                 readtoken1(pgetc(), here->here->type == NHERE? SQSYNTAX : DQSYNTAX,
10115                                 here->eofmark, here->striptabs);
10116                 n = (union node *)stalloc(sizeof (struct narg));
10117                 n->narg.type = NARG;
10118                 n->narg.next = NULL;
10119                 n->narg.text = wordtext;
10120                 n->narg.backquote = backquotelist;
10121                 here->here->nhere.doc = n;
10122         }
10123 }
10124
10125 static char
10126 peektoken() {
10127         int t;
10128
10129         t = readtoken();
10130         tokpushback++;
10131         return tokname_array[t][0];
10132 }
10133
10134 static int
10135 readtoken() {
10136         int t;
10137
10138 #ifdef ASH_ALIAS
10139         int savecheckalias = checkalias;
10140         int savecheckkwd = checkkwd;
10141         struct alias *ap;
10142 #endif
10143
10144 #ifdef DEBUG
10145         int alreadyseen = tokpushback;
10146 #endif
10147
10148 #ifdef ASH_ALIAS
10149 top:
10150 #endif
10151
10152         t = xxreadtoken();
10153
10154 #ifdef ASH_ALIAS
10155         checkalias = savecheckalias;
10156 #endif
10157
10158         if (checkkwd) {
10159                 /*
10160                  * eat newlines
10161                  */
10162                 if (checkkwd == 2) {
10163                         checkkwd = 0;
10164                         while (t == TNL) {
10165                                 parseheredoc();
10166                                 t = xxreadtoken();
10167                         }
10168                 }
10169                 checkkwd = 0;
10170                 /*
10171                  * check for keywords
10172                  */
10173                 if (t == TWORD && !quoteflag)
10174                 {
10175                         const char *const *pp;
10176
10177                         if ((pp = findkwd(wordtext))) {
10178                                 lasttoken = t = pp - tokname_array;
10179                                 TRACE(("keyword %s recognized\n", tokname(t)));
10180                                 goto out;
10181                         }
10182                 }
10183         }
10184
10185
10186         if (t != TWORD) {
10187                 if (t != TREDIR) {
10188                         checkalias = 0;
10189                 }
10190         } else if (checkalias == 2 && isassignment(wordtext)) {
10191                 lasttoken = t = TASSIGN;
10192 #ifdef ASH_ALIAS
10193         } else if (checkalias) {
10194                 if (!quoteflag && (ap = *__lookupalias(wordtext)) != NULL && !(ap->flag & ALIASINUSE)) {
10195                         if (*ap->val) {
10196                                 pushstring(ap->val, strlen(ap->val), ap);
10197                         }
10198                         checkkwd = savecheckkwd;
10199                         goto top;
10200                 }
10201                 checkalias = 0;
10202 #endif
10203         }
10204 out:
10205 #ifdef DEBUG
10206         if (!alreadyseen)
10207             TRACE(("token %s %s\n", tokname(t), t == TWORD || t == TASSIGN ? wordtext : ""));
10208         else
10209             TRACE(("reread token %s %s\n", tokname(t), t == TWORD || t == TASSIGN ? wordtext : ""));
10210 #endif
10211         return (t);
10212 }
10213
10214
10215 /*
10216  * Read the next input token.
10217  * If the token is a word, we set backquotelist to the list of cmds in
10218  *      backquotes.  We set quoteflag to true if any part of the word was
10219  *      quoted.
10220  * If the token is TREDIR, then we set redirnode to a structure containing
10221  *      the redirection.
10222  * In all cases, the variable startlinno is set to the number of the line
10223  *      on which the token starts.
10224  *
10225  * [Change comment:  here documents and internal procedures]
10226  * [Readtoken shouldn't have any arguments.  Perhaps we should make the
10227  *  word parsing code into a separate routine.  In this case, readtoken
10228  *  doesn't need to have any internal procedures, but parseword does.
10229  *  We could also make parseoperator in essence the main routine, and
10230  *  have parseword (readtoken1?) handle both words and redirection.]
10231  */
10232
10233 #define NEW_xxreadtoken
10234 #ifdef NEW_xxreadtoken
10235
10236 static const char xxreadtoken_chars[] = "\n()&|;"; /* singles must be first! */
10237 static const char xxreadtoken_tokens[] = {
10238         TNL, TLP, TRP,                          /* only single occurrence allowed */
10239         TBACKGND, TPIPE, TSEMI,         /* if single occurrence */
10240         TEOF,                                           /* corresponds to trailing nul */
10241         TAND, TOR, TENDCASE,            /* if double occurrence */
10242 };
10243
10244 #define xxreadtoken_doubles \
10245         (sizeof(xxreadtoken_tokens) - sizeof(xxreadtoken_chars))
10246 #define xxreadtoken_singles \
10247         (sizeof(xxreadtoken_chars) - xxreadtoken_doubles - 1)
10248
10249 static int
10250 xxreadtoken() {
10251         int c;
10252
10253         if (tokpushback) {
10254                 tokpushback = 0;
10255                 return lasttoken;
10256         }
10257         if (needprompt) {
10258                 setprompt(2);
10259                 needprompt = 0;
10260         }
10261         startlinno = plinno;
10262         for (;;) {      /* until token or start of word found */
10263                 c = pgetc_macro();
10264
10265                 if ((c!=' ') && (c!='\t')
10266 #ifdef ASH_ALIAS
10267                         && (c!=PEOA)
10268 #endif
10269                         ) {
10270                         if (c=='#') {
10271                                 while ((c = pgetc()) != '\n' && c != PEOF);
10272                                 pungetc();
10273                         } else if (c=='\\') {
10274                                 if (pgetc() != '\n') {
10275                                         pungetc();
10276                                         goto READTOKEN1;
10277                                 }
10278                                 startlinno = ++plinno;
10279                                 setprompt(doprompt ? 2 : 0);
10280                         } else {
10281                                 const char *p
10282                                         = xxreadtoken_chars + sizeof(xxreadtoken_chars) - 1;
10283
10284                                 if (c!=PEOF) {
10285                                         if (c=='\n') {
10286                                                 plinno++;
10287                                                 needprompt = doprompt;
10288                                         }
10289
10290                                         p = strchr(xxreadtoken_chars, c);
10291                                         if (p == NULL) {
10292                                         READTOKEN1:
10293                                                 return readtoken1(c, BASESYNTAX, (char *)NULL, 0);
10294                                         }
10295                         
10296                                         if (p-xxreadtoken_chars >= xxreadtoken_singles) {
10297                                                 if (pgetc() == *p) { /* double occurrence? */
10298                                                         p += xxreadtoken_doubles + 1;
10299                                                 } else {
10300                                                         pungetc();
10301                                                 }
10302                                         }
10303                                 }
10304
10305                                 return lasttoken = xxreadtoken_tokens[p-xxreadtoken_chars];
10306                         }
10307                 }
10308         }
10309 }
10310
10311
10312 #else
10313 #define RETURN(token)   return lasttoken = token
10314
10315 static int
10316 xxreadtoken() {
10317         int c;
10318
10319         if (tokpushback) {
10320                 tokpushback = 0;
10321                 return lasttoken;
10322         }
10323         if (needprompt) {
10324                 setprompt(2);
10325                 needprompt = 0;
10326         }
10327         startlinno = plinno;
10328         for (;;) {      /* until token or start of word found */
10329                 c = pgetc_macro();
10330                 switch (c) {
10331                 case ' ': case '\t':
10332 #ifdef ASH_ALIAS
10333                 case PEOA:
10334 #endif
10335                         continue;
10336                 case '#':
10337                         while ((c = pgetc()) != '\n' && c != PEOF);
10338                         pungetc();
10339                         continue;
10340                 case '\\':
10341                         if (pgetc() == '\n') {
10342                                 startlinno = ++plinno;
10343                                 if (doprompt)
10344                                         setprompt(2);
10345                                 else
10346                                         setprompt(0);
10347                                 continue;
10348                         }
10349                         pungetc();
10350                         goto breakloop;
10351                 case '\n':
10352                         plinno++;
10353                         needprompt = doprompt;
10354                         RETURN(TNL);
10355                 case PEOF:
10356                         RETURN(TEOF);
10357                 case '&':
10358                         if (pgetc() == '&')
10359                                 RETURN(TAND);
10360                         pungetc();
10361                         RETURN(TBACKGND);
10362                 case '|':
10363                         if (pgetc() == '|')
10364                                 RETURN(TOR);
10365                         pungetc();
10366                         RETURN(TPIPE);
10367                 case ';':
10368                         if (pgetc() == ';')
10369                                 RETURN(TENDCASE);
10370                         pungetc();
10371                         RETURN(TSEMI);
10372                 case '(':
10373                         RETURN(TLP);
10374                 case ')':
10375                         RETURN(TRP);
10376                 default:
10377                         goto breakloop;
10378                 }
10379         }
10380 breakloop:
10381         return readtoken1(c, BASESYNTAX, (char *)NULL, 0);
10382 #undef RETURN
10383 }
10384 #endif
10385
10386 /*
10387  * If eofmark is NULL, read a word or a redirection symbol.  If eofmark
10388  * is not NULL, read a here document.  In the latter case, eofmark is the
10389  * word which marks the end of the document and striptabs is true if
10390  * leading tabs should be stripped from the document.  The argument firstc
10391  * is the first character of the input token or document.
10392  *
10393  * Because C does not have internal subroutines, I have simulated them
10394  * using goto's to implement the subroutine linkage.  The following macros
10395  * will run code that appears at the end of readtoken1.
10396  */
10397
10398 #define CHECKEND()      {goto checkend; checkend_return:;}
10399 #define PARSEREDIR()    {goto parseredir; parseredir_return:;}
10400 #define PARSESUB()      {goto parsesub; parsesub_return:;}
10401 #define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
10402 #define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
10403 #define PARSEARITH()    {goto parsearith; parsearith_return:;}
10404
10405 static int
10406 readtoken1(int firstc, int syntax, const char *eofmark, int striptabs)
10407 {
10408         int c = firstc;
10409         char *out;
10410         int len;
10411         char line[EOFMARKLEN + 1];
10412         struct nodelist *bqlist;
10413         int quotef;
10414         int dblquote;
10415         int varnest;    /* levels of variables expansion */
10416         int arinest;    /* levels of arithmetic expansion */
10417         int parenlevel; /* levels of parens in arithmetic */
10418         int dqvarnest;  /* levels of variables expansion within double quotes */
10419         int oldstyle;
10420         int prevsyntax; /* syntax before arithmetic */
10421 #if __GNUC__
10422         /* Avoid longjmp clobbering */
10423         (void) &out;
10424         (void) &quotef;
10425         (void) &dblquote;
10426         (void) &varnest;
10427         (void) &arinest;
10428         (void) &parenlevel;
10429         (void) &dqvarnest;
10430         (void) &oldstyle;
10431         (void) &prevsyntax;
10432         (void) &syntax;
10433 #endif
10434
10435         startlinno = plinno;
10436         dblquote = 0;
10437         if (syntax == DQSYNTAX)
10438                 dblquote = 1;
10439         quotef = 0;
10440         bqlist = NULL;
10441         varnest = 0;
10442         arinest = 0;
10443         parenlevel = 0;
10444         dqvarnest = 0;
10445
10446         STARTSTACKSTR(out);
10447         loop: { /* for each line, until end of word */
10448                 CHECKEND();     /* set c to PEOF if at end of here document */
10449                 for (;;) {      /* until end of line or end of word */
10450                         CHECKSTRSPACE(3, out);  /* permit 3 calls to USTPUTC */
10451                         switch(SIT(c,syntax)) {
10452                         case CNL:       /* '\n' */
10453                                 if (syntax == BASESYNTAX)
10454                                         goto endword;   /* exit outer loop */
10455                                 USTPUTC(c, out);
10456                                 plinno++;
10457                                 if (doprompt)
10458                                         setprompt(2);
10459                                 else
10460                                         setprompt(0);
10461                                 c = pgetc();
10462                                 goto loop;              /* continue outer loop */
10463                         case CWORD:
10464                                 USTPUTC(c, out);
10465                                 break;
10466                         case CCTL:
10467                                 if ((eofmark == NULL || dblquote) &&
10468                                     dqvarnest == 0)
10469                                         USTPUTC(CTLESC, out);
10470                                 USTPUTC(c, out);
10471                                 break;
10472                         case CBACK:     /* backslash */
10473                                 c = pgetc2();
10474                                 if (c == PEOF) {
10475                                         USTPUTC('\\', out);
10476                                         pungetc();
10477                                 } else if (c == '\n') {
10478                                         if (doprompt)
10479                                                 setprompt(2);
10480                                         else
10481                                                 setprompt(0);
10482                                 } else {
10483                                         if (dblquote && c != '\\' && c != '`' && c != '$'
10484                                                          && (c != '"' || eofmark != NULL))
10485                                                 USTPUTC('\\', out);
10486                                         if (SIT(c,SQSYNTAX) == CCTL)
10487                                                 USTPUTC(CTLESC, out);
10488                                         else if (eofmark == NULL)
10489                                                 USTPUTC(CTLQUOTEMARK, out);
10490                                         USTPUTC(c, out);
10491                                         quotef++;
10492                                 }
10493                                 break;
10494                         case CSQUOTE:
10495                                 if (eofmark == NULL)
10496                                         USTPUTC(CTLQUOTEMARK, out);
10497                                 syntax = SQSYNTAX;
10498                                 break;
10499                         case CDQUOTE:
10500                                 if (eofmark == NULL)
10501                                         USTPUTC(CTLQUOTEMARK, out);
10502                                 syntax = DQSYNTAX;
10503                                 dblquote = 1;
10504                                 break;
10505                         case CENDQUOTE:
10506                                 if (eofmark != NULL && arinest == 0 &&
10507                                     varnest == 0) {
10508                                         USTPUTC(c, out);
10509                                 } else {
10510                                         if (arinest) {
10511                                                 syntax = ARISYNTAX;
10512                                                 dblquote = 0;
10513                                         } else if (eofmark == NULL &&
10514                                                    dqvarnest == 0) {
10515                                                 syntax = BASESYNTAX;
10516                                                 dblquote = 0;
10517                                         }
10518                                         quotef++;
10519                                 }
10520                                 break;
10521                         case CVAR:      /* '$' */
10522                                 PARSESUB();             /* parse substitution */
10523                                 break;
10524                         case CENDVAR:   /* '}' */
10525                                 if (varnest > 0) {
10526                                         varnest--;
10527                                         if (dqvarnest > 0) {
10528                                                 dqvarnest--;
10529                                         }
10530                                         USTPUTC(CTLENDVAR, out);
10531                                 } else {
10532                                         USTPUTC(c, out);
10533                                 }
10534                                 break;
10535 #ifdef ASH_MATH_SUPPORT
10536                         case CLP:       /* '(' in arithmetic */
10537                                 parenlevel++;
10538                                 USTPUTC(c, out);
10539                                 break;
10540                         case CRP:       /* ')' in arithmetic */
10541                                 if (parenlevel > 0) {
10542                                         USTPUTC(c, out);
10543                                         --parenlevel;
10544                                 } else {
10545                                         if (pgetc() == ')') {
10546                                                 if (--arinest == 0) {
10547                                                         USTPUTC(CTLENDARI, out);
10548                                                         syntax = prevsyntax;
10549                                                         if (syntax == DQSYNTAX)
10550                                                                 dblquote = 1;
10551                                                         else
10552                                                                 dblquote = 0;
10553                                                 } else
10554                                                         USTPUTC(')', out);
10555                                         } else {
10556                                                 /*
10557                                                  * unbalanced parens
10558                                                  *  (don't 2nd guess - no error)
10559                                                  */
10560                                                 pungetc();
10561                                                 USTPUTC(')', out);
10562                                         }
10563                                 }
10564                                 break;
10565 #endif
10566                         case CBQUOTE:   /* '`' */
10567                                 PARSEBACKQOLD();
10568                                 break;
10569                         case CENDFILE:
10570                                 goto endword;           /* exit outer loop */
10571                         case CIGN:
10572                                 break;
10573                         default:
10574                                 if (varnest == 0)
10575                                         goto endword;   /* exit outer loop */
10576 #ifdef ASH_ALIAS
10577                                 if (c != PEOA)
10578 #endif
10579                                         USTPUTC(c, out);
10580
10581                         }
10582                         c = pgetc_macro();
10583                 }
10584         }
10585 endword:
10586         if (syntax == ARISYNTAX)
10587                 synerror("Missing '))'");
10588         if (syntax != BASESYNTAX && ! parsebackquote && eofmark == NULL)
10589                 synerror("Unterminated quoted string");
10590         if (varnest != 0) {
10591                 startlinno = plinno;
10592                 synerror("Missing '}'");
10593         }
10594         USTPUTC('\0', out);
10595         len = out - stackblock();
10596         out = stackblock();
10597         if (eofmark == NULL) {
10598                 if ((c == '>' || c == '<')
10599                  && quotef == 0
10600                  && len <= 2
10601                  && (*out == '\0' || is_digit(*out))) {
10602                         PARSEREDIR();
10603                         return lasttoken = TREDIR;
10604                 } else {
10605                         pungetc();
10606                 }
10607         }
10608         quoteflag = quotef;
10609         backquotelist = bqlist;
10610         grabstackblock(len);
10611         wordtext = out;
10612         return lasttoken = TWORD;
10613 /* end of readtoken routine */
10614
10615
10616
10617 /*
10618  * Check to see whether we are at the end of the here document.  When this
10619  * is called, c is set to the first character of the next input line.  If
10620  * we are at the end of the here document, this routine sets the c to PEOF.
10621  */
10622
10623 checkend: {
10624         if (eofmark) {
10625 #ifdef ASH_ALIAS
10626                 if (c == PEOA) {
10627                         c = pgetc2();
10628                 }
10629 #endif
10630                 if (striptabs) {
10631                         while (c == '\t') {
10632                                 c = pgetc2();
10633                         }
10634                 }
10635                 if (c == *eofmark) {
10636                         if (pfgets(line, sizeof line) != NULL) {
10637                                 const char *p, *q;
10638
10639                                 p = line;
10640                                 for (q = eofmark + 1 ; *q && *p == *q ; p++, q++);
10641                                 if (*p == '\n' && *q == '\0') {
10642                                         c = PEOF;
10643                                         plinno++;
10644                                         needprompt = doprompt;
10645                                 } else {
10646                                         pushstring(line, strlen(line), NULL);
10647                                 }
10648                         }
10649                 }
10650         }
10651         goto checkend_return;
10652 }
10653
10654
10655 /*
10656  * Parse a redirection operator.  The variable "out" points to a string
10657  * specifying the fd to be redirected.  The variable "c" contains the
10658  * first character of the redirection operator.
10659  */
10660
10661 parseredir: {
10662         char fd = *out;
10663         union node *np;
10664
10665         np = (union node *)stalloc(sizeof (struct nfile));
10666         if (c == '>') {
10667                 np->nfile.fd = 1;
10668                 c = pgetc();
10669                 if (c == '>')
10670                         np->type = NAPPEND;
10671                 else if (c == '&')
10672                         np->type = NTOFD;
10673                 else if (c == '|')
10674                         np->type = NTOOV;
10675                 else {
10676                         np->type = NTO;
10677                         pungetc();
10678                 }
10679         } else {        /* c == '<' */
10680                 np->nfile.fd = 0;
10681                 switch (c = pgetc()) {
10682                 case '<':
10683                         if (sizeof (struct nfile) != sizeof (struct nhere)) {
10684                                 np = (union node *)stalloc(sizeof (struct nhere));
10685                                 np->nfile.fd = 0;
10686                         }
10687                         np->type = NHERE;
10688                         heredoc = (struct heredoc *)stalloc(sizeof (struct heredoc));
10689                         heredoc->here = np;
10690                         if ((c = pgetc()) == '-') {
10691                                 heredoc->striptabs = 1;
10692                         } else {
10693                                 heredoc->striptabs = 0;
10694                                 pungetc();
10695                         }
10696                         break;
10697
10698                 case '&':
10699                         np->type = NFROMFD;
10700                         break;
10701
10702                 case '>':
10703                         np->type = NFROMTO;
10704                         break;
10705
10706                 default:
10707                         np->type = NFROM;
10708                         pungetc();
10709                         break;
10710                 }
10711         }
10712         if (fd != '\0')
10713                 np->nfile.fd = digit_val(fd);
10714         redirnode = np;
10715         goto parseredir_return;
10716 }
10717
10718
10719 /*
10720  * Parse a substitution.  At this point, we have read the dollar sign
10721  * and nothing else.
10722  */
10723
10724 parsesub: {
10725         int subtype;
10726         int typeloc;
10727         int flags;
10728         char *p;
10729         static const char types[] = "}-+?=";
10730
10731         c = pgetc();
10732         if (
10733                 c <= PEOA  ||
10734                 (c != '(' && c != '{' && !is_name(c) && !is_special(c))
10735         ) {
10736                 USTPUTC('$', out);
10737                 pungetc();
10738         } else if (c == '(') {  /* $(command) or $((arith)) */
10739                 if (pgetc() == '(') {
10740                         PARSEARITH();
10741                 } else {
10742                         pungetc();
10743                         PARSEBACKQNEW();
10744                 }
10745         } else {
10746                 USTPUTC(CTLVAR, out);
10747                 typeloc = out - stackblock();
10748                 USTPUTC(VSNORMAL, out);
10749                 subtype = VSNORMAL;
10750                 if (c == '{') {
10751                         c = pgetc();
10752                         if (c == '#') {
10753                                 if ((c = pgetc()) == '}')
10754                                         c = '#';
10755                                 else
10756                                         subtype = VSLENGTH;
10757                         }
10758                         else
10759                                 subtype = 0;
10760                 }
10761                 if (c > PEOA && is_name(c)) {
10762                         do {
10763                                 STPUTC(c, out);
10764                                 c = pgetc();
10765                         } while (c > PEOA && is_in_name(c));
10766                 } else if (is_digit(c)) {
10767                         do {
10768                                 USTPUTC(c, out);
10769                                 c = pgetc();
10770                         } while (is_digit(c));
10771                 }
10772                 else if (is_special(c)) {
10773                         USTPUTC(c, out);
10774                         c = pgetc();
10775                 }
10776                 else
10777 badsub:                 synerror("Bad substitution");
10778
10779                 STPUTC('=', out);
10780                 flags = 0;
10781                 if (subtype == 0) {
10782                         switch (c) {
10783                         case ':':
10784                                 flags = VSNUL;
10785                                 c = pgetc();
10786                                 /*FALLTHROUGH*/
10787                         default:
10788                                 p = strchr(types, c);
10789                                 if (p == NULL)
10790                                         goto badsub;
10791                                 subtype = p - types + VSNORMAL;
10792                                 break;
10793                         case '%':
10794                         case '#':
10795                                 {
10796                                         int cc = c;
10797                                         subtype = c == '#' ? VSTRIMLEFT :
10798                                                              VSTRIMRIGHT;
10799                                         c = pgetc();
10800                                         if (c == cc)
10801                                                 subtype++;
10802                                         else
10803                                                 pungetc();
10804                                         break;
10805                                 }
10806                         }
10807                 } else {
10808                         pungetc();
10809                 }
10810                 if (dblquote || arinest)
10811                         flags |= VSQUOTE;
10812                 *(stackblock() + typeloc) = subtype | flags;
10813                 if (subtype != VSNORMAL) {
10814                         varnest++;
10815                         if (dblquote) {
10816                                 dqvarnest++;
10817                         }
10818                 }
10819         }
10820         goto parsesub_return;
10821 }
10822
10823
10824 /*
10825  * Called to parse command substitutions.  Newstyle is set if the command
10826  * is enclosed inside $(...); nlpp is a pointer to the head of the linked
10827  * list of commands (passed by reference), and savelen is the number of
10828  * characters on the top of the stack which must be preserved.
10829  */
10830
10831 parsebackq: {
10832         struct nodelist **nlpp;
10833         int savepbq;
10834         union node *n;
10835         char *volatile str;
10836         struct jmploc jmploc;
10837         struct jmploc *volatile savehandler;
10838         int savelen;
10839         int saveprompt;
10840 #ifdef __GNUC__
10841         (void) &saveprompt;
10842 #endif
10843
10844         savepbq = parsebackquote;
10845         if (setjmp(jmploc.loc)) {
10846                 if (str)
10847                         ckfree(str);
10848                 parsebackquote = 0;
10849                 handler = savehandler;
10850                 longjmp(handler->loc, 1);
10851         }
10852         INTOFF;
10853         str = NULL;
10854         savelen = out - stackblock();
10855         if (savelen > 0) {
10856                 str = ckmalloc(savelen);
10857                 memcpy(str, stackblock(), savelen);
10858         }
10859         savehandler = handler;
10860         handler = &jmploc;
10861         INTON;
10862         if (oldstyle) {
10863                 /* We must read until the closing backquote, giving special
10864                    treatment to some slashes, and then push the string and
10865                    reread it as input, interpreting it normally.  */
10866                 char *pout;
10867                 int pc;
10868                 int psavelen;
10869                 char *pstr;
10870
10871
10872                 STARTSTACKSTR(pout);
10873                 for (;;) {
10874                         if (needprompt) {
10875                                 setprompt(2);
10876                                 needprompt = 0;
10877                         }
10878                         switch (pc = pgetc()) {
10879                         case '`':
10880                                 goto done;
10881
10882                         case '\\':
10883                                 if ((pc = pgetc()) == '\n') {
10884                                         plinno++;
10885                                         if (doprompt)
10886                                                 setprompt(2);
10887                                         else
10888                                                 setprompt(0);
10889                                         /*
10890                                          * If eating a newline, avoid putting
10891                                          * the newline into the new character
10892                                          * stream (via the STPUTC after the
10893                                          * switch).
10894                                          */
10895                                         continue;
10896                                 }
10897                                 if (pc != '\\' && pc != '`' && pc != '$'
10898                                     && (!dblquote || pc != '"'))
10899                                         STPUTC('\\', pout);
10900                                 if (pc > PEOA) {
10901                                         break;
10902                                 }
10903                                 /* fall through */
10904
10905                         case PEOF:
10906 #ifdef ASH_ALIAS
10907                         case PEOA:
10908 #endif
10909                                 startlinno = plinno;
10910                                 synerror("EOF in backquote substitution");
10911
10912                         case '\n':
10913                                 plinno++;
10914                                 needprompt = doprompt;
10915                                 break;
10916
10917                         default:
10918                                 break;
10919                         }
10920                         STPUTC(pc, pout);
10921                 }
10922 done:
10923                 STPUTC('\0', pout);
10924                 psavelen = pout - stackblock();
10925                 if (psavelen > 0) {
10926                         pstr = grabstackstr(pout);
10927                         setinputstring(pstr);
10928                 }
10929         }
10930         nlpp = &bqlist;
10931         while (*nlpp)
10932                 nlpp = &(*nlpp)->next;
10933         *nlpp = (struct nodelist *)stalloc(sizeof (struct nodelist));
10934         (*nlpp)->next = NULL;
10935         parsebackquote = oldstyle;
10936
10937         if (oldstyle) {
10938                 saveprompt = doprompt;
10939                 doprompt = 0;
10940         }
10941
10942         n = list(0);
10943
10944         if (oldstyle)
10945                 doprompt = saveprompt;
10946         else {
10947                 if (readtoken() != TRP)
10948                         synexpect(TRP);
10949         }
10950
10951         (*nlpp)->n = n;
10952         if (oldstyle) {
10953                 /*
10954                  * Start reading from old file again, ignoring any pushed back
10955                  * tokens left from the backquote parsing
10956                  */
10957                 popfile();
10958                 tokpushback = 0;
10959         }
10960         while (stackblocksize() <= savelen)
10961                 growstackblock();
10962         STARTSTACKSTR(out);
10963         if (str) {
10964                 memcpy(out, str, savelen);
10965                 STADJUST(savelen, out);
10966                 INTOFF;
10967                 ckfree(str);
10968                 str = NULL;
10969                 INTON;
10970         }
10971         parsebackquote = savepbq;
10972         handler = savehandler;
10973         if (arinest || dblquote)
10974                 USTPUTC(CTLBACKQ | CTLQUOTE, out);
10975         else
10976                 USTPUTC(CTLBACKQ, out);
10977         if (oldstyle)
10978                 goto parsebackq_oldreturn;
10979         else
10980                 goto parsebackq_newreturn;
10981 }
10982
10983 /*
10984  * Parse an arithmetic expansion (indicate start of one and set state)
10985  */
10986 parsearith: {
10987
10988         if (++arinest == 1) {
10989                 prevsyntax = syntax;
10990                 syntax = ARISYNTAX;
10991                 USTPUTC(CTLARI, out);
10992                 if (dblquote)
10993                         USTPUTC('"',out);
10994                 else
10995                         USTPUTC(' ',out);
10996         } else {
10997                 /*
10998                  * we collapse embedded arithmetic expansion to
10999                  * parenthesis, which should be equivalent
11000                  */
11001                 USTPUTC('(', out);
11002         }
11003         goto parsearith_return;
11004 }
11005
11006 } /* end of readtoken */
11007
11008
11009 /*
11010  * Returns true if the text contains nothing to expand (no dollar signs
11011  * or backquotes).
11012  */
11013
11014 static int
11015 noexpand(text)
11016         char *text;
11017         {
11018         char *p;
11019         char c;
11020
11021         p = text;
11022         while ((c = *p++) != '\0') {
11023                 if (c == CTLQUOTEMARK)
11024                         continue;
11025                 if (c == CTLESC)
11026                         p++;
11027                 else if (SIT(c,BASESYNTAX) == CCTL)
11028                         return 0;
11029         }
11030         return 1;
11031 }
11032
11033
11034 /*
11035  * Return true if the argument is a legal variable name (a letter or
11036  * underscore followed by zero or more letters, underscores, and digits).
11037  */
11038
11039 static int
11040 goodname(const char *name)
11041 {
11042         const char *p;
11043
11044         p = name;
11045         if (! is_name(*p))
11046                 return 0;
11047         while (*++p) {
11048                 if (! is_in_name(*p))
11049                         return 0;
11050         }
11051         return 1;
11052 }
11053
11054
11055 /*
11056  * Called when an unexpected token is read during the parse.  The argument
11057  * is the token that is expected, or -1 if more than one type of token can
11058  * occur at this point.
11059  */
11060
11061 static void
11062 synexpect(token)
11063         int token;
11064 {
11065         char msg[64];
11066         int l;
11067
11068         l = sprintf(msg, "%s unexpected", tokname(lasttoken));
11069         if (token >= 0)
11070                 sprintf(msg+l, " (expecting %s)", tokname(token));
11071         synerror(msg);
11072         /* NOTREACHED */
11073 }
11074
11075
11076 static void
11077 synerror(const char *msg)
11078 {
11079         if (commandname)
11080                 out2fmt("%s: %d: ", commandname, startlinno);
11081         out2fmt("Syntax error: %s\n", msg);
11082         error((char *)NULL);
11083         /* NOTREACHED */
11084 }
11085
11086
11087 /*
11088  * called by editline -- any expansions to the prompt
11089  *    should be added here.
11090  */
11091 static void
11092 setprompt(int whichprompt)
11093 {
11094     char *prompt;
11095     switch (whichprompt) {
11096         case 1:
11097                 prompt = ps1val();
11098                 break;
11099         case 2:
11100                 prompt = ps2val();
11101                 break;
11102         default:                /* 0 */
11103                 prompt = "";
11104     }
11105     putprompt(prompt);
11106 }
11107
11108
11109 /*
11110  * Code for dealing with input/output redirection.
11111  */
11112
11113 #define EMPTY -2                /* marks an unused slot in redirtab */
11114 #ifndef PIPE_BUF
11115 # define PIPESIZE 4096          /* amount of buffering in a pipe */
11116 #else
11117 # define PIPESIZE PIPE_BUF
11118 #endif
11119
11120
11121 /*
11122  * Open a file in noclobber mode.
11123  * The code was copied from bash.
11124  */
11125 static inline int
11126 noclobberopen(const char *fname)
11127 {
11128         int r, fd;
11129         struct stat finfo, finfo2;
11130
11131         /*
11132          * If the file exists and is a regular file, return an error
11133          * immediately.
11134          */
11135         r = stat(fname, &finfo);
11136         if (r == 0 && S_ISREG(finfo.st_mode)) {
11137                 errno = EEXIST;
11138                 return -1;
11139         }
11140
11141         /*
11142          * If the file was not present (r != 0), make sure we open it
11143          * exclusively so that if it is created before we open it, our open
11144          * will fail.  Make sure that we do not truncate an existing file.
11145          * Note that we don't turn on O_EXCL unless the stat failed -- if the
11146          * file was not a regular file, we leave O_EXCL off.
11147          */
11148         if (r != 0)
11149                 return open(fname, O_WRONLY|O_CREAT|O_EXCL, 0666);
11150         fd = open(fname, O_WRONLY|O_CREAT, 0666);
11151
11152         /* If the open failed, return the file descriptor right away. */
11153         if (fd < 0)
11154                 return fd;
11155
11156         /*
11157          * OK, the open succeeded, but the file may have been changed from a
11158          * non-regular file to a regular file between the stat and the open.
11159          * We are assuming that the O_EXCL open handles the case where FILENAME
11160          * did not exist and is symlinked to an existing file between the stat
11161          * and open.
11162          */
11163
11164         /*
11165          * If we can open it and fstat the file descriptor, and neither check
11166          * revealed that it was a regular file, and the file has not been
11167          * replaced, return the file descriptor.
11168          */
11169          if (fstat(fd, &finfo2) == 0 && !S_ISREG(finfo2.st_mode) &&
11170              finfo.st_dev == finfo2.st_dev && finfo.st_ino == finfo2.st_ino)
11171                 return fd;
11172
11173         /* The file has been replaced.  badness. */
11174         close(fd);
11175         errno = EEXIST;
11176         return -1;
11177 }
11178
11179 /*
11180  * Handle here documents.  Normally we fork off a process to write the
11181  * data to a pipe.  If the document is short, we can stuff the data in
11182  * the pipe without forking.
11183  */
11184
11185 static inline int
11186 openhere(const union node *redir)
11187 {
11188         int pip[2];
11189         int len = 0;
11190
11191         if (pipe(pip) < 0)
11192                 error("Pipe call failed");
11193         if (redir->type == NHERE) {
11194                 len = strlen(redir->nhere.doc->narg.text);
11195                 if (len <= PIPESIZE) {
11196                         xwrite(pip[1], redir->nhere.doc->narg.text, len);
11197                         goto out;
11198                 }
11199         }
11200         if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) {
11201                 close(pip[0]);
11202                 signal(SIGINT, SIG_IGN);
11203                 signal(SIGQUIT, SIG_IGN);
11204                 signal(SIGHUP, SIG_IGN);
11205 #ifdef SIGTSTP
11206                 signal(SIGTSTP, SIG_IGN);
11207 #endif
11208                 signal(SIGPIPE, SIG_DFL);
11209                 if (redir->type == NHERE)
11210                         xwrite(pip[1], redir->nhere.doc->narg.text, len);
11211                 else
11212                         expandhere(redir->nhere.doc, pip[1]);
11213                 _exit(0);
11214         }
11215 out:
11216         close(pip[1]);
11217         return pip[0];
11218 }
11219
11220
11221 static inline int
11222 openredirect(const union node *redir)
11223 {
11224         char *fname;
11225         int f;
11226
11227         switch (redir->nfile.type) {
11228         case NFROM:
11229                 fname = redir->nfile.expfname;
11230                 if ((f = open(fname, O_RDONLY)) < 0)
11231                         goto eopen;
11232                 break;
11233         case NFROMTO:
11234                 fname = redir->nfile.expfname;
11235                 if ((f = open(fname, O_RDWR|O_CREAT|O_TRUNC, 0666)) < 0)
11236                         goto ecreate;
11237                 break;
11238         case NTO:
11239                 /* Take care of noclobber mode. */
11240                 if (Cflag) {
11241                         fname = redir->nfile.expfname;
11242                         if ((f = noclobberopen(fname)) < 0)
11243                                 goto ecreate;
11244                         break;
11245                 }
11246         case NTOOV:
11247                 fname = redir->nfile.expfname;
11248 #ifdef O_CREAT
11249                 if ((f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666)) < 0)
11250                         goto ecreate;
11251 #else
11252                 if ((f = creat(fname, 0666)) < 0)
11253                         goto ecreate;
11254 #endif
11255                 break;
11256         case NAPPEND:
11257                 fname = redir->nfile.expfname;
11258 #ifdef O_APPEND
11259                 if ((f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666)) < 0)
11260                         goto ecreate;
11261 #else
11262                 if ((f = open(fname, O_WRONLY)) < 0
11263                  && (f = creat(fname, 0666)) < 0)
11264                         goto ecreate;
11265                 lseek(f, (off_t)0, 2);
11266 #endif
11267                 break;
11268         default:
11269 #ifdef DEBUG
11270                 abort();
11271 #endif
11272                 /* Fall through to eliminate warning. */
11273         case NTOFD:
11274         case NFROMFD:
11275                 f = -1;
11276                 break;
11277         case NHERE:
11278         case NXHERE:
11279                 f = openhere(redir);
11280                 break;
11281         }
11282
11283         return f;
11284 ecreate:
11285         error("cannot create %s: %s", fname, errmsg(errno, E_CREAT));
11286 eopen:
11287         error("cannot open %s: %s", fname, errmsg(errno, E_OPEN));
11288 }
11289
11290
11291 /*
11292  * Process a list of redirection commands.  If the REDIR_PUSH flag is set,
11293  * old file descriptors are stashed away so that the redirection can be
11294  * undone by calling popredir.  If the REDIR_BACKQ flag is set, then the
11295  * standard output, and the standard error if it becomes a duplicate of
11296  * stdout.
11297  */
11298
11299 static void
11300 redirect(union node *redir, int flags)
11301 {
11302         union node *n;
11303         struct redirtab *sv = NULL;
11304         int i;
11305         int fd;
11306         int newfd;
11307         int try;
11308         int fd1dup = flags & REDIR_BACKQ;; /* stdout `cmd` redir to pipe */
11309
11310         if (flags & REDIR_PUSH) {
11311                 sv = ckmalloc(sizeof (struct redirtab));
11312                 for (i = 0 ; i < 10 ; i++)
11313                         sv->renamed[i] = EMPTY;
11314                 sv->next = redirlist;
11315                 redirlist = sv;
11316         }
11317         for (n = redir ; n ; n = n->nfile.next) {
11318                 fd = n->nfile.fd;
11319                 try = 0;
11320                 if ((n->nfile.type == NTOFD || n->nfile.type == NFROMFD) &&
11321                     n->ndup.dupfd == fd)
11322                         continue; /* redirect from/to same file descriptor */
11323
11324                 INTOFF;
11325                 newfd = openredirect(n);
11326                 if ((flags & REDIR_PUSH) && sv->renamed[fd] == EMPTY) {
11327                         if (newfd == fd) {
11328                                 try++;
11329                         } else if ((i = fcntl(fd, F_DUPFD, 10)) == -1) {
11330                                 switch (errno) {
11331                                 case EBADF:
11332                                         if (!try) {
11333                                                 dupredirect(n, newfd, fd1dup);
11334                                                 try++;
11335                                                 break;
11336                                         }
11337                                         /* FALLTHROUGH*/
11338                                 default:
11339                                         if (newfd >= 0) {
11340                                                 close(newfd);
11341                                         }
11342                                         INTON;
11343                                         error("%d: %m", fd);
11344                                         /* NOTREACHED */
11345                                 }
11346                         }
11347                         if (!try) {
11348                                 close(fd);
11349                                 if (flags & REDIR_PUSH) {
11350                                         sv->renamed[fd] = i;
11351                                 }
11352                         }
11353                 } else if (fd != newfd) {
11354                         close(fd);
11355                 }
11356                 if (fd == 0)
11357                         fd0_redirected++;
11358                 if (!try)
11359                         dupredirect(n, newfd, fd1dup);
11360                 INTON;
11361         }
11362 }
11363
11364
11365 static void
11366 dupredirect(const union node *redir, int f, int fd1dup)
11367 {
11368         int fd = redir->nfile.fd;
11369
11370         if(fd==1)
11371                 fd1dup = 0;
11372         if (redir->nfile.type == NTOFD || redir->nfile.type == NFROMFD) {
11373                 if (redir->ndup.dupfd >= 0) {   /* if not ">&-" */
11374                         if (redir->ndup.dupfd!=1 || fd1dup!=1)
11375                                 dup_as_newfd(redir->ndup.dupfd, fd);
11376                 }
11377                 return;
11378         }
11379
11380         if (f != fd) {
11381                 dup_as_newfd(f, fd);
11382                 close(f);
11383         }
11384         return;
11385 }
11386
11387
11388
11389 /*
11390  * Undo the effects of the last redirection.
11391  */
11392
11393 static void
11394 popredir(void)
11395 {
11396         struct redirtab *rp = redirlist;
11397         int i;
11398
11399         INTOFF;
11400         for (i = 0 ; i < 10 ; i++) {
11401                 if (rp->renamed[i] != EMPTY) {
11402                         if (i == 0)
11403                                 fd0_redirected--;
11404                         close(i);
11405                         if (rp->renamed[i] >= 0) {
11406                                 dup_as_newfd(rp->renamed[i], i);
11407                                 close(rp->renamed[i]);
11408                         }
11409                 }
11410         }
11411         redirlist = rp->next;
11412         ckfree(rp);
11413         INTON;
11414 }
11415
11416 /*
11417  * Discard all saved file descriptors.
11418  */
11419
11420 static void
11421 clearredir(void) {
11422         struct redirtab *rp;
11423         int i;
11424
11425         for (rp = redirlist ; rp ; rp = rp->next) {
11426                 for (i = 0 ; i < 10 ; i++) {
11427                         if (rp->renamed[i] >= 0) {
11428                                 close(rp->renamed[i]);
11429                         }
11430                         rp->renamed[i] = EMPTY;
11431                 }
11432         }
11433 }
11434
11435
11436 /*
11437  * Copy a file descriptor to be >= to.  Returns -1
11438  * if the source file descriptor is closed, EMPTY if there are no unused
11439  * file descriptors left.
11440  */
11441
11442 static int
11443 dup_as_newfd(from, to)
11444         int from;
11445         int to;
11446 {
11447         int newfd;
11448
11449         newfd = fcntl(from, F_DUPFD, to);
11450         if (newfd < 0) {
11451                 if (errno == EMFILE)
11452                         return EMPTY;
11453                 else
11454                         error("%d: %m", from);
11455         }
11456         return newfd;
11457 }
11458
11459 #ifdef DEBUG
11460 /*
11461  * Debugging stuff.
11462  */
11463 static void shtree (union node *, int, char *, FILE*);
11464 static void shcmd (union node *, FILE *);
11465 static void sharg (union node *, FILE *);
11466 static void indent (int, char *, FILE *);
11467 static void trstring (char *);
11468
11469
11470 static void
11471 showtree(n)
11472         unode *n;
11473 {
11474         trputs("showtree called\n");
11475         shtree(n, 1, NULL, stdout);
11476 }
11477
11478
11479 static void
11480 shtree(n, ind, pfx, fp)
11481         union node *n;
11482         int ind;
11483         char *pfx;
11484         FILE *fp;
11485 {
11486         struct nodelist *lp;
11487         const char *s;
11488
11489         if (n == NULL)
11490                 return;
11491
11492         indent(ind, pfx, fp);
11493         switch(n->type) {
11494         case NSEMI:
11495                 s = "; ";
11496                 goto binop;
11497         case NAND:
11498                 s = " && ";
11499                 goto binop;
11500         case NOR:
11501                 s = " || ";
11502 binop:
11503                 shtree(n->nbinary.ch1, ind, NULL, fp);
11504            /*    if (ind < 0) */
11505                         fputs(s, fp);
11506                 shtree(n->nbinary.ch2, ind, NULL, fp);
11507                 break;
11508         case NCMD:
11509                 shcmd(n, fp);
11510                 if (ind >= 0)
11511                         putc('\n', fp);
11512                 break;
11513         case NPIPE:
11514                 for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {
11515                         shcmd(lp->n, fp);
11516                         if (lp->next)
11517                                 fputs(" | ", fp);
11518                 }
11519                 if (n->npipe.backgnd)
11520                         fputs(" &", fp);
11521                 if (ind >= 0)
11522                         putc('\n', fp);
11523                 break;
11524         default:
11525                 fprintf(fp, "<node type %d>", n->type);
11526                 if (ind >= 0)
11527                         putc('\n', fp);
11528                 break;
11529         }
11530 }
11531
11532
11533
11534 static void
11535 shcmd(cmd, fp)
11536         union node *cmd;
11537         FILE *fp;
11538 {
11539         union node *np;
11540         int first;
11541         const char *s;
11542         int dftfd;
11543
11544         first = 1;
11545         for (np = cmd->ncmd.args ; np ; np = np->narg.next) {
11546                 if (! first)
11547                         putchar(' ');
11548                 sharg(np, fp);
11549                 first = 0;
11550         }
11551         for (np = cmd->ncmd.redirect ; np ; np = np->nfile.next) {
11552                 if (! first)
11553                         putchar(' ');
11554 #if 1
11555                 s = "*error*";
11556                 dftfd = 0;
11557                 if ((np->nfile.type <= NFROMFD) && (np->nfile.type >= NTO)) {
11558                         s = redir_strings[np->nfile.type - NTO];
11559                         if (*s == '>') {
11560                                 dftfd = 1;
11561                         }
11562                 }
11563 #else
11564                 switch (np->nfile.type) {
11565                         case NTO:       s = ">";  dftfd = 1; break;
11566                         case NAPPEND:   s = ">>"; dftfd = 1; break;
11567                         case NTOFD:     s = ">&"; dftfd = 1; break;
11568                         case NTOOV:     s = ">|"; dftfd = 1; break;
11569                         case NFROM:     s = "<";  dftfd = 0; break;
11570                         case NFROMFD:   s = "<&"; dftfd = 0; break;
11571                         case NFROMTO:   s = "<>"; dftfd = 0; break;
11572                         default:        s = "*error*"; dftfd = 0; break;
11573                 }
11574 #endif
11575                 if (np->nfile.fd != dftfd)
11576                         fprintf(fp, "%d", np->nfile.fd);
11577                 fputs(s, fp);
11578                 if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) {
11579                         fprintf(fp, "%d", np->ndup.dupfd);
11580                 } else {
11581                         sharg(np->nfile.fname, fp);
11582                 }
11583                 first = 0;
11584         }
11585 }
11586
11587 static void
11588 sharg(arg, fp)
11589         union node *arg;
11590         FILE *fp;
11591         {
11592         char *p;
11593         struct nodelist *bqlist;
11594         int subtype;
11595
11596         if (arg->type != NARG) {
11597                 printf("<node type %d>\n", arg->type);
11598                 fflush(stdout);
11599                 abort();
11600         }
11601         bqlist = arg->narg.backquote;
11602         for (p = arg->narg.text ; *p ; p++) {
11603                 switch (*p) {
11604                 case CTLESC:
11605                         putc(*++p, fp);
11606                         break;
11607                 case CTLVAR:
11608                         putc('$', fp);
11609                         putc('{', fp);
11610                         subtype = *++p;
11611                         if (subtype == VSLENGTH)
11612                                 putc('#', fp);
11613
11614                         while (*p != '=')
11615                                 putc(*p++, fp);
11616
11617                         if (subtype & VSNUL)
11618                                 putc(':', fp);
11619
11620                         switch (subtype & VSTYPE) {
11621                         case VSNORMAL:
11622                                 putc('}', fp);
11623                                 break;
11624                         case VSMINUS:
11625                                 putc('-', fp);
11626                                 break;
11627                         case VSPLUS:
11628                                 putc('+', fp);
11629                                 break;
11630                         case VSQUESTION:
11631                                 putc('?', fp);
11632                                 break;
11633                         case VSASSIGN:
11634                                 putc('=', fp);
11635                                 break;
11636                         case VSTRIMLEFT:
11637                                 putc('#', fp);
11638                                 break;
11639                         case VSTRIMLEFTMAX:
11640                                 putc('#', fp);
11641                                 putc('#', fp);
11642                                 break;
11643                         case VSTRIMRIGHT:
11644                                 putc('%', fp);
11645                                 break;
11646                         case VSTRIMRIGHTMAX:
11647                                 putc('%', fp);
11648                                 putc('%', fp);
11649                                 break;
11650                         case VSLENGTH:
11651                                 break;
11652                         default:
11653                                 printf("<subtype %d>", subtype);
11654                         }
11655                         break;
11656                 case CTLENDVAR:
11657                      putc('}', fp);
11658                      break;
11659                 case CTLBACKQ:
11660                 case CTLBACKQ|CTLQUOTE:
11661                         putc('$', fp);
11662                         putc('(', fp);
11663                         shtree(bqlist->n, -1, NULL, fp);
11664                         putc(')', fp);
11665                         break;
11666                 default:
11667                         putc(*p, fp);
11668                         break;
11669                 }
11670         }
11671 }
11672
11673
11674 static void
11675 indent(amount, pfx, fp)
11676         int amount;
11677         char *pfx;
11678         FILE *fp;
11679 {
11680         int i;
11681
11682         for (i = 0 ; i < amount ; i++) {
11683                 if (pfx && i == amount - 1)
11684                         fputs(pfx, fp);
11685                 putc('\t', fp);
11686         }
11687 }
11688
11689
11690 FILE *tracefile;
11691
11692 #if DEBUG == 2
11693 static int debug = 1;
11694 #else
11695 static int debug = 0;
11696 #endif
11697
11698
11699 static void
11700 trputc(c)
11701         int c;
11702 {
11703         if (tracefile == NULL)
11704                 return;
11705         putc(c, tracefile);
11706         if (c == '\n')
11707                 fflush(tracefile);
11708 }
11709
11710 static void
11711 trace(const char *fmt, ...)
11712 {
11713         va_list va;
11714         va_start(va, fmt);
11715         if (tracefile != NULL) {
11716                 (void) vfprintf(tracefile, fmt, va);
11717                 if (strchr(fmt, '\n'))
11718                         (void) fflush(tracefile);
11719         }
11720         va_end(va);
11721 }
11722
11723
11724 static void
11725 trputs(s)
11726         const char *s;
11727 {
11728         if (tracefile == NULL)
11729                 return;
11730         fputs(s, tracefile);
11731         if (strchr(s, '\n'))
11732                 fflush(tracefile);
11733 }
11734
11735
11736 static void
11737 trstring(s)
11738         char *s;
11739 {
11740         char *p;
11741         char c;
11742
11743         if (tracefile == NULL)
11744                 return;
11745         putc('"', tracefile);
11746         for (p = s ; *p ; p++) {
11747                 switch (*p) {
11748                 case '\n':  c = 'n';  goto backslash;
11749                 case '\t':  c = 't';  goto backslash;
11750                 case '\r':  c = 'r';  goto backslash;
11751                 case '"':  c = '"';  goto backslash;
11752                 case '\\':  c = '\\';  goto backslash;
11753                 case CTLESC:  c = 'e';  goto backslash;
11754                 case CTLVAR:  c = 'v';  goto backslash;
11755                 case CTLVAR+CTLQUOTE:  c = 'V';  goto backslash;
11756                 case CTLBACKQ:  c = 'q';  goto backslash;
11757                 case CTLBACKQ+CTLQUOTE:  c = 'Q';  goto backslash;
11758 backslash:        putc('\\', tracefile);
11759                         putc(c, tracefile);
11760                         break;
11761                 default:
11762                         if (*p >= ' ' && *p <= '~')
11763                                 putc(*p, tracefile);
11764                         else {
11765                                 putc('\\', tracefile);
11766                                 putc(*p >> 6 & 03, tracefile);
11767                                 putc(*p >> 3 & 07, tracefile);
11768                                 putc(*p & 07, tracefile);
11769                         }
11770                         break;
11771                 }
11772         }
11773         putc('"', tracefile);
11774 }
11775
11776
11777 static void
11778 trargs(ap)
11779         char **ap;
11780 {
11781         if (tracefile == NULL)
11782                 return;
11783         while (*ap) {
11784                 trstring(*ap++);
11785                 if (*ap)
11786                         putc(' ', tracefile);
11787                 else
11788                         putc('\n', tracefile);
11789         }
11790         fflush(tracefile);
11791 }
11792
11793
11794 static void
11795 opentrace() {
11796         char s[100];
11797 #ifdef O_APPEND
11798         int flags;
11799 #endif
11800
11801         if (!debug)
11802                 return;
11803 #ifdef not_this_way
11804         {
11805                 char *p;
11806                 if ((p = getenv("HOME")) == NULL) {
11807                         if (geteuid() == 0)
11808                                 p = "/";
11809                         else
11810                                 p = "/tmp";
11811                 }
11812                 strcpy(s, p);
11813                 strcat(s, "/trace");
11814         }
11815 #else
11816         strcpy(s, "./trace");
11817 #endif /* not_this_way */
11818         if ((tracefile = wfopen(s, "a")) == NULL)
11819                 return;
11820 #ifdef O_APPEND
11821         if ((flags = fcntl(fileno(tracefile), F_GETFL, 0)) >= 0)
11822                 fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND);
11823 #endif
11824         fputs("\nTracing started.\n", tracefile);
11825         fflush(tracefile);
11826 }
11827 #endif /* DEBUG */
11828
11829
11830 /*
11831  * The trap builtin.
11832  */
11833
11834 static int
11835 trapcmd(argc, argv)
11836         int argc;
11837         char **argv;
11838 {
11839         char *action;
11840         char **ap;
11841         int signo;
11842
11843         if (argc <= 1) {
11844                 for (signo = 0 ; signo < NSIG ; signo++) {
11845                         if (trap[signo] != NULL) {
11846                                 char *p;
11847                                 const char *sn;
11848
11849                                 p = single_quote(trap[signo]);
11850                                 sn = sys_siglist[signo];
11851                                 if(sn==NULL)
11852                                         sn = u_signal_names(0, &signo, 0);
11853                                 if(sn==NULL)
11854                                         sn = "???";
11855                                 printf("trap -- %s %s\n", p, sn);
11856                                 stunalloc(p);
11857                         }
11858                 }
11859                 return 0;
11860         }
11861         ap = argv + 1;
11862         if (argc == 2)
11863                 action = NULL;
11864         else
11865                 action = *ap++;
11866         while (*ap) {
11867                 if ((signo = decode_signal(*ap, 0)) < 0)
11868                         error("%s: bad trap", *ap);
11869                 INTOFF;
11870                 if (action) {
11871                         if (action[0] == '-' && action[1] == '\0')
11872                                 action = NULL;
11873                         else
11874                                 action = savestr(action);
11875                 }
11876                 if (trap[signo])
11877                         ckfree(trap[signo]);
11878                 trap[signo] = action;
11879                 if (signo != 0)
11880                         setsignal(signo);
11881                 INTON;
11882                 ap++;
11883         }
11884         return 0;
11885 }
11886
11887
11888
11889
11890
11891
11892 /*
11893  * Set the signal handler for the specified signal.  The routine figures
11894  * out what it should be set to.
11895  */
11896
11897 static void
11898 setsignal(int signo)
11899 {
11900         int action;
11901         char *t;
11902         struct sigaction act;
11903
11904         if ((t = trap[signo]) == NULL)
11905                 action = S_DFL;
11906         else if (*t != '\0')
11907                 action = S_CATCH;
11908         else
11909                 action = S_IGN;
11910         if (rootshell && action == S_DFL) {
11911                 switch (signo) {
11912                 case SIGINT:
11913                         if (iflag || minusc || sflag == 0)
11914                                 action = S_CATCH;
11915                         break;
11916                 case SIGQUIT:
11917 #ifdef DEBUG
11918                         {
11919
11920                         if (debug)
11921                                 break;
11922                         }
11923 #endif
11924                         /* FALLTHROUGH */
11925                 case SIGTERM:
11926                         if (iflag)
11927                                 action = S_IGN;
11928                         break;
11929 #ifdef JOBS
11930                 case SIGTSTP:
11931                 case SIGTTOU:
11932                         if (mflag)
11933                                 action = S_IGN;
11934                         break;
11935 #endif
11936                 }
11937         }
11938
11939         t = &sigmode[signo - 1];
11940         if (*t == 0) {
11941                 /*
11942                  * current setting unknown
11943                  */
11944                 if (sigaction(signo, 0, &act) == -1) {
11945                         /*
11946                          * Pretend it worked; maybe we should give a warning
11947                          * here, but other shells don't. We don't alter
11948                          * sigmode, so that we retry every time.
11949                          */
11950                         return;
11951                 }
11952                 if (act.sa_handler == SIG_IGN) {
11953                         if (mflag && (signo == SIGTSTP ||
11954                              signo == SIGTTIN || signo == SIGTTOU)) {
11955                                 *t = S_IGN;     /* don't hard ignore these */
11956                         } else
11957                                 *t = S_HARD_IGN;
11958                 } else {
11959                         *t = S_RESET;   /* force to be set */
11960                 }
11961         }
11962         if (*t == S_HARD_IGN || *t == action)
11963                 return;
11964         act.sa_handler = ((action == S_CATCH) ? onsig
11965                                           : ((action == S_IGN) ? SIG_IGN : SIG_DFL));
11966         *t = action;
11967         act.sa_flags = 0;
11968         sigemptyset(&act.sa_mask);
11969         sigaction(signo, &act, 0);
11970 }
11971
11972 /*
11973  * Ignore a signal.
11974  */
11975
11976 static void
11977 ignoresig(signo)
11978         int signo;
11979 {
11980         if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) {
11981                 signal(signo, SIG_IGN);
11982         }
11983         sigmode[signo - 1] = S_HARD_IGN;
11984 }
11985
11986
11987 /*
11988  * Signal handler.
11989  */
11990
11991 static void
11992 onsig(int signo)
11993 {
11994         if (signo == SIGINT && trap[SIGINT] == NULL) {
11995                 onint();
11996                 return;
11997         }
11998         gotsig[signo - 1] = 1;
11999         pendingsigs++;
12000 }
12001
12002
12003 /*
12004  * Called to execute a trap.  Perhaps we should avoid entering new trap
12005  * handlers while we are executing a trap handler.
12006  */
12007
12008 static void
12009 dotrap(void)
12010 {
12011         int i;
12012         int savestatus;
12013
12014         for (;;) {
12015                 for (i = 1 ; ; i++) {
12016                         if (gotsig[i - 1])
12017                                 break;
12018                         if (i >= NSIG - 1)
12019                                 goto done;
12020                 }
12021                 gotsig[i - 1] = 0;
12022                 savestatus=exitstatus;
12023                 evalstring(trap[i], 0);
12024                 exitstatus=savestatus;
12025         }
12026 done:
12027         pendingsigs = 0;
12028 }
12029
12030 /*
12031  * Called to exit the shell.
12032  */
12033
12034 static void
12035 exitshell(int status)
12036 {
12037         struct jmploc loc1, loc2;
12038         char *p;
12039
12040         TRACE(("exitshell(%d) pid=%d\n", status, getpid()));
12041         if (setjmp(loc1.loc)) {
12042                 goto l1;
12043         }
12044         if (setjmp(loc2.loc)) {
12045                 goto l2;
12046         }
12047         handler = &loc1;
12048         if ((p = trap[0]) != NULL && *p != '\0') {
12049                 trap[0] = NULL;
12050                 evalstring(p, 0);
12051         }
12052 l1:   handler = &loc2;                  /* probably unnecessary */
12053         flushall();
12054 #ifdef JOBS
12055         setjobctl(0);
12056 #endif
12057 l2:   _exit(status);
12058         /* NOTREACHED */
12059 }
12060
12061 static int decode_signal(const char *string, int minsig)
12062 {
12063         int signo;
12064         const char *name = u_signal_names(string, &signo, minsig);
12065
12066         return name ? signo : -1;
12067 }
12068
12069 static struct var **hashvar (const char *);
12070 static void showvars (const char *, int, int);
12071 static struct var **findvar (struct var **, const char *);
12072
12073 /*
12074  * Initialize the varable symbol tables and import the environment
12075  */
12076
12077 /*
12078  * This routine initializes the builtin variables.  It is called when the
12079  * shell is initialized and again when a shell procedure is spawned.
12080  */
12081
12082 static void
12083 initvar() {
12084         const struct varinit *ip;
12085         struct var *vp;
12086         struct var **vpp;
12087
12088         for (ip = varinit ; (vp = ip->var) != NULL ; ip++) {
12089                 if ((vp->flags & VEXPORT) == 0) {
12090                         vpp = hashvar(ip->text);
12091                         vp->next = *vpp;
12092                         *vpp = vp;
12093                         vp->text = strdup(ip->text);
12094                         vp->flags = ip->flags;
12095                         vp->func = ip->func;
12096                 }
12097         }
12098         /*
12099          * PS1 depends on uid
12100          */
12101         if ((vps1.flags & VEXPORT) == 0) {
12102                 vpp = hashvar("PS1=");
12103                 vps1.next = *vpp;
12104                 *vpp = &vps1;
12105                 vps1.text = strdup(geteuid() ? "PS1=$ " : "PS1=# ");
12106                 vps1.flags = VSTRFIXED|VTEXTFIXED;
12107         }
12108 }
12109
12110 /*
12111  * Set the value of a variable.  The flags argument is ored with the
12112  * flags of the variable.  If val is NULL, the variable is unset.
12113  */
12114
12115 static void
12116 setvar(name, val, flags)
12117         const char *name, *val;
12118         int flags;
12119 {
12120         const char *p;
12121         int len;
12122         int namelen;
12123         char *nameeq;
12124         int isbad;
12125         int vallen = 0;
12126
12127         isbad = 0;
12128         p = name;
12129         if (! is_name(*p))
12130                 isbad = 1;
12131         p++;
12132         for (;;) {
12133                 if (! is_in_name(*p)) {
12134                         if (*p == '\0' || *p == '=')
12135                                 break;
12136                         isbad = 1;
12137                 }
12138                 p++;
12139         }
12140         namelen = p - name;
12141         if (isbad)
12142                 error("%.*s: bad variable name", namelen, name);
12143         len = namelen + 2;              /* 2 is space for '=' and '\0' */
12144         if (val == NULL) {
12145                 flags |= VUNSET;
12146         } else {
12147                 len += vallen = strlen(val);
12148         }
12149         INTOFF;
12150         nameeq = ckmalloc(len);
12151         memcpy(nameeq, name, namelen);
12152         nameeq[namelen] = '=';
12153         if (val) {
12154                 memcpy(nameeq + namelen + 1, val, vallen + 1);
12155         } else {
12156                 nameeq[namelen + 1] = '\0';
12157         }
12158         setvareq(nameeq, flags);
12159         INTON;
12160 }
12161
12162
12163
12164 /*
12165  * Same as setvar except that the variable and value are passed in
12166  * the first argument as name=value.  Since the first argument will
12167  * be actually stored in the table, it should not be a string that
12168  * will go away.
12169  */
12170
12171 static void
12172 setvareq(s, flags)
12173         char *s;
12174         int flags;
12175 {
12176         struct var *vp, **vpp;
12177
12178         vpp = hashvar(s);
12179         flags |= (VEXPORT & (((unsigned) (1 - aflag)) - 1));
12180         if ((vp = *findvar(vpp, s))) {
12181                 if (vp->flags & VREADONLY) {
12182                         size_t len = strchr(s, '=') - s;
12183                         error("%.*s: is read only", len, s);
12184                 }
12185                 INTOFF;
12186
12187                 if (vp->func && (flags & VNOFUNC) == 0)
12188                         (*vp->func)(strchr(s, '=') + 1);
12189
12190                 if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
12191                         ckfree(vp->text);
12192
12193                 vp->flags &= ~(VTEXTFIXED|VSTACK|VUNSET);
12194                 vp->flags |= flags;
12195                 vp->text = s;
12196
12197 #ifdef ASH_MAIL
12198                 /*
12199                  * We could roll this to a function, to handle it as
12200                  * a regular variable function callback, but why bother?
12201                  */
12202                 if (iflag && (vp == &vmpath || (vp == &vmail && !mpathset())))
12203                         chkmail(1);
12204 #endif
12205                 INTON;
12206                 return;
12207         }
12208         /* not found */
12209         vp = ckmalloc(sizeof (*vp));
12210         vp->flags = flags;
12211         vp->text = s;
12212         vp->next = *vpp;
12213         vp->func = NULL;
12214         *vpp = vp;
12215 }
12216
12217
12218
12219 /*
12220  * Process a linked list of variable assignments.
12221  */
12222
12223 static void
12224 listsetvar(mylist)
12225         struct strlist *mylist;
12226         {
12227         struct strlist *lp;
12228
12229         INTOFF;
12230         for (lp = mylist ; lp ; lp = lp->next) {
12231                 setvareq(savestr(lp->text), 0);
12232         }
12233         INTON;
12234 }
12235
12236
12237
12238 /*
12239  * Find the value of a variable.  Returns NULL if not set.
12240  */
12241
12242 static const char *
12243 lookupvar(name)
12244         const char *name;
12245 {
12246         struct var *v;
12247
12248         if ((v = *findvar(hashvar(name), name)) && !(v->flags & VUNSET)) {
12249                 return strchr(v->text, '=') + 1;
12250         }
12251         return NULL;
12252 }
12253
12254
12255
12256 /*
12257  * Search the environment of a builtin command.
12258  */
12259
12260 static const char *
12261 bltinlookup(const char *name)
12262 {
12263         const struct strlist *sp;
12264
12265         for (sp = cmdenviron ; sp ; sp = sp->next) {
12266                 if (varequal(sp->text, name))
12267                         return strchr(sp->text, '=') + 1;
12268         }
12269         return lookupvar(name);
12270 }
12271
12272
12273
12274 /*
12275  * Generate a list of exported variables.  This routine is used to construct
12276  * the third argument to execve when executing a program.
12277  */
12278
12279 static char **
12280 environment() {
12281         int nenv;
12282         struct var **vpp;
12283         struct var *vp;
12284         char **env;
12285         char **ep;
12286
12287         nenv = 0;
12288         for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) {
12289                 for (vp = *vpp ; vp ; vp = vp->next)
12290                         if (vp->flags & VEXPORT)
12291                                 nenv++;
12292         }
12293         ep = env = stalloc((nenv + 1) * sizeof *env);
12294         for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) {
12295                 for (vp = *vpp ; vp ; vp = vp->next)
12296                         if (vp->flags & VEXPORT)
12297                                 *ep++ = vp->text;
12298         }
12299         *ep = NULL;
12300         return env;
12301 }
12302
12303
12304 /*
12305  * Called when a shell procedure is invoked to clear out nonexported
12306  * variables.  It is also necessary to reallocate variables of with
12307  * VSTACK set since these are currently allocated on the stack.
12308  */
12309
12310 static void
12311 shprocvar(void) {
12312         struct var **vpp;
12313         struct var *vp, **prev;
12314
12315         for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) {
12316                 for (prev = vpp ; (vp = *prev) != NULL ; ) {
12317                         if ((vp->flags & VEXPORT) == 0) {
12318                                 *prev = vp->next;
12319                                 if ((vp->flags & VTEXTFIXED) == 0)
12320                                         ckfree(vp->text);
12321                                 if ((vp->flags & VSTRFIXED) == 0)
12322                                         ckfree(vp);
12323                         } else {
12324                                 if (vp->flags & VSTACK) {
12325                                         vp->text = savestr(vp->text);
12326                                         vp->flags &=~ VSTACK;
12327                                 }
12328                                 prev = &vp->next;
12329                         }
12330                 }
12331         }
12332         initvar();
12333 }
12334
12335
12336
12337 /*
12338  * Command to list all variables which are set.  Currently this command
12339  * is invoked from the set command when the set command is called without
12340  * any variables.
12341  */
12342
12343 static int
12344 showvarscmd(argc, argv)
12345         int argc;
12346         char **argv;
12347 {
12348         showvars(nullstr, VUNSET, VUNSET);
12349         return 0;
12350 }
12351
12352
12353
12354 /*
12355  * The export and readonly commands.
12356  */
12357
12358 static int
12359 exportcmd(argc, argv)
12360         int argc;
12361         char **argv;
12362 {
12363         struct var *vp;
12364         char *name;
12365         const char *p;
12366         int flag = argv[0][0] == 'r'? VREADONLY : VEXPORT;
12367         int pflag;
12368
12369         listsetvar(cmdenviron);
12370         pflag = (nextopt("p") == 'p');
12371         if (argc > 1 && !pflag) {
12372                 while ((name = *argptr++) != NULL) {
12373                         if ((p = strchr(name, '=')) != NULL) {
12374                                 p++;
12375                         } else {
12376                                 if ((vp = *findvar(hashvar(name), name))) {
12377                                         vp->flags |= flag;
12378                                         goto found;
12379                                 }
12380                         }
12381                         setvar(name, p, flag);
12382 found:;
12383                 }
12384         } else {
12385                 showvars(argv[0], flag, 0);
12386         }
12387         return 0;
12388 }
12389
12390
12391 /*
12392  * The "local" command.
12393  */
12394
12395 /* funcnest nonzero if we are currently evaluating a function */
12396
12397 static int
12398 localcmd(argc, argv)
12399         int argc;
12400         char **argv;
12401 {
12402         char *name;
12403
12404         if (! funcnest)
12405                 error("Not in a function");
12406         while ((name = *argptr++) != NULL) {
12407                 mklocal(name);
12408         }
12409         return 0;
12410 }
12411
12412
12413 /*
12414  * Make a variable a local variable.  When a variable is made local, it's
12415  * value and flags are saved in a localvar structure.  The saved values
12416  * will be restored when the shell function returns.  We handle the name
12417  * "-" as a special case.
12418  */
12419
12420 static void
12421 mklocal(name)
12422         char *name;
12423         {
12424         struct localvar *lvp;
12425         struct var **vpp;
12426         struct var *vp;
12427
12428         INTOFF;
12429         lvp = ckmalloc(sizeof (struct localvar));
12430         if (name[0] == '-' && name[1] == '\0') {
12431                 char *p;
12432                 p = ckmalloc(sizeof optet_vals);
12433                 lvp->text = memcpy(p, optet_vals, sizeof optet_vals);
12434                 vp = NULL;
12435         } else {
12436                 vpp = hashvar(name);
12437                 vp = *findvar(vpp, name);
12438                 if (vp == NULL) {
12439                         if (strchr(name, '='))
12440                                 setvareq(savestr(name), VSTRFIXED);
12441                         else
12442                                 setvar(name, NULL, VSTRFIXED);
12443                         vp = *vpp;      /* the new variable */
12444                         lvp->text = NULL;
12445                         lvp->flags = VUNSET;
12446                 } else {
12447                         lvp->text = vp->text;
12448                         lvp->flags = vp->flags;
12449                         vp->flags |= VSTRFIXED|VTEXTFIXED;
12450                         if (strchr(name, '='))
12451                                 setvareq(savestr(name), 0);
12452                 }
12453         }
12454         lvp->vp = vp;
12455         lvp->next = localvars;
12456         localvars = lvp;
12457         INTON;
12458 }
12459
12460
12461 /*
12462  * Called after a function returns.
12463  */
12464
12465 static void
12466 poplocalvars() {
12467         struct localvar *lvp;
12468         struct var *vp;
12469
12470         while ((lvp = localvars) != NULL) {
12471                 localvars = lvp->next;
12472                 vp = lvp->vp;
12473                 if (vp == NULL) {       /* $- saved */
12474                         memcpy(optet_vals, lvp->text, sizeof optet_vals);
12475                         ckfree(lvp->text);
12476                 } else if ((lvp->flags & (VUNSET|VSTRFIXED)) == VUNSET) {
12477                         (void)unsetvar(vp->text);
12478                 } else {
12479                         if ((vp->flags & VTEXTFIXED) == 0)
12480                                 ckfree(vp->text);
12481                         vp->flags = lvp->flags;
12482                         vp->text = lvp->text;
12483                 }
12484                 ckfree(lvp);
12485         }
12486 }
12487
12488
12489 static int
12490 setvarcmd(argc, argv)
12491         int argc;
12492         char **argv;
12493 {
12494         if (argc <= 2)
12495                 return unsetcmd(argc, argv);
12496         else if (argc == 3)
12497                 setvar(argv[1], argv[2], 0);
12498         else
12499                 error("List assignment not implemented");
12500         return 0;
12501 }
12502
12503
12504 /*
12505  * The unset builtin command.  We unset the function before we unset the
12506  * variable to allow a function to be unset when there is a readonly variable
12507  * with the same name.
12508  */
12509
12510 static int
12511 unsetcmd(argc, argv)
12512         int argc;
12513         char **argv;
12514 {
12515         char **ap;
12516         int i;
12517         int flg_func = 0;
12518         int flg_var = 0;
12519         int ret = 0;
12520
12521         while ((i = nextopt("vf")) != '\0') {
12522                 if (i == 'f')
12523                         flg_func = 1;
12524                 else
12525                         flg_var = 1;
12526         }
12527         if (flg_func == 0 && flg_var == 0)
12528                 flg_var = 1;
12529
12530         for (ap = argptr; *ap ; ap++) {
12531                 if (flg_func)
12532                         unsetfunc(*ap);
12533                 if (flg_var)
12534                         ret |= unsetvar(*ap);
12535         }
12536         return ret;
12537 }
12538
12539
12540 /*
12541  * Unset the specified variable.
12542  */
12543
12544 static int
12545 unsetvar(const char *s)
12546 {
12547         struct var **vpp;
12548         struct var *vp;
12549
12550         vpp = findvar(hashvar(s), s);
12551         vp = *vpp;
12552         if (vp) {
12553                 if (vp->flags & VREADONLY)
12554                         return (1);
12555                 INTOFF;
12556                 if (*(strchr(vp->text, '=') + 1) != '\0')
12557                         setvar(s, nullstr, 0);
12558                 vp->flags &= ~VEXPORT;
12559                 vp->flags |= VUNSET;
12560                 if ((vp->flags & VSTRFIXED) == 0) {
12561                         if ((vp->flags & VTEXTFIXED) == 0)
12562                                 ckfree(vp->text);
12563                         *vpp = vp->next;
12564                         ckfree(vp);
12565                 }
12566                 INTON;
12567                 return (0);
12568         }
12569
12570         return (0);
12571 }
12572
12573
12574
12575 /*
12576  * Find the appropriate entry in the hash table from the name.
12577  */
12578
12579 static struct var **
12580 hashvar(const char *p)
12581 {
12582         unsigned int hashval;
12583
12584         hashval = ((unsigned char) *p) << 4;
12585         while (*p && *p != '=')
12586                 hashval += (unsigned char) *p++;
12587         return &vartab[hashval % VTABSIZE];
12588 }
12589
12590
12591
12592 /*
12593  * Returns true if the two strings specify the same varable.  The first
12594  * variable name is terminated by '='; the second may be terminated by
12595  * either '=' or '\0'.
12596  */
12597
12598 static int
12599 varequal(const char *p, const char *q)
12600 {
12601         while (*p == *q++) {
12602                 if (*p++ == '=')
12603                         return 1;
12604         }
12605         if (*p == '=' && *(q - 1) == '\0')
12606                 return 1;
12607         return 0;
12608 }
12609
12610 static void
12611 showvars(const char *myprefix, int mask, int xor)
12612 {
12613         struct var **vpp;
12614         struct var *vp;
12615         const char *sep = myprefix == nullstr ? myprefix : spcstr;
12616
12617         for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) {
12618                 for (vp = *vpp ; vp ; vp = vp->next) {
12619                         if ((vp->flags & mask) ^ xor) {
12620                                 char *p;
12621                                 int len;
12622
12623                                 p = strchr(vp->text, '=') + 1;
12624                                 len = p - vp->text;
12625                                 p = single_quote(p);
12626
12627                                 printf("%s%s%.*s%s\n", myprefix, sep, len,
12628                                         vp->text, p);
12629                                 stunalloc(p);
12630                         }
12631                 }
12632         }
12633 }
12634
12635 static struct var **
12636 findvar(struct var **vpp, const char *name)
12637 {
12638         for (; *vpp; vpp = &(*vpp)->next) {
12639                 if (varequal((*vpp)->text, name)) {
12640                         break;
12641                 }
12642         }
12643         return vpp;
12644 }
12645
12646 /*
12647  * Copyright (c) 1999 Herbert Xu <herbert@debian.org>
12648  * This file contains code for the times builtin.
12649  * $Id: ash.c,v 1.35 2001/11/12 16:44:55 kraai Exp $
12650  */
12651 static int timescmd (int argc, char **argv)
12652 {
12653         struct tms buf;
12654         long int clk_tck = sysconf(_SC_CLK_TCK);
12655
12656         times(&buf);
12657         printf("%dm%fs %dm%fs\n%dm%fs %dm%fs\n",
12658                (int) (buf.tms_utime / clk_tck / 60),
12659                ((double) buf.tms_utime) / clk_tck,
12660                (int) (buf.tms_stime / clk_tck / 60),
12661                ((double) buf.tms_stime) / clk_tck,
12662                (int) (buf.tms_cutime / clk_tck / 60),
12663                ((double) buf.tms_cutime) / clk_tck,
12664                (int) (buf.tms_cstime / clk_tck / 60),
12665                ((double) buf.tms_cstime) / clk_tck);
12666         return 0;
12667 }
12668
12669 #ifdef ASH_MATH_SUPPORT
12670 /* The let builtin.  */
12671 int letcmd(int argc, char **argv)
12672 {
12673         int errcode;
12674         long result=0;
12675         if (argc == 2) {
12676                 char *tmp, *expression, p[13];
12677                 expression = strchr(argv[1], '=');
12678                 if (!expression) {
12679                         /* Cannot use 'error()' here, or the return code
12680                          * will be incorrect */
12681                         out2fmt("sh: let: syntax error: \"%s\"\n", argv[1]);
12682                         return 0;
12683                 }
12684                 *expression = '\0';
12685                 tmp = ++expression;
12686                 result = arith(tmp, &errcode);
12687                 if (errcode < 0) {
12688                         /* Cannot use 'error()' here, or the return code
12689                          * will be incorrect */
12690                         out2fmt("sh: let: ");
12691                         if(errcode == -2)
12692                                 out2fmt("divide by zero");
12693                         else
12694                                 out2fmt("syntax error: \"%s=%s\"\n", argv[1], expression);
12695                         return 0;
12696                 }
12697                 snprintf(p, 12, "%ld", result);
12698                 setvar(argv[1], savestr(p), 0);
12699         } else if (argc >= 3)
12700                 synerror("invalid operand");
12701         return !result;
12702 }
12703 #endif
12704
12705
12706
12707 /*-
12708  * Copyright (c) 1989, 1991, 1993, 1994
12709  *      The Regents of the University of California.  All rights reserved.
12710  *
12711  * This code is derived from software contributed to Berkeley by
12712  * Kenneth Almquist.
12713  *
12714  * Redistribution and use in source and binary forms, with or without
12715  * modification, are permitted provided that the following conditions
12716  * are met:
12717  * 1. Redistributions of source code must retain the above copyright
12718  *    notice, this list of conditions and the following disclaimer.
12719  * 2. Redistributions in binary form must reproduce the above copyright
12720  *    notice, this list of conditions and the following disclaimer in the
12721  *    documentation and/or other materials provided with the distribution.
12722  *
12723  * 3. <BSD Advertising Clause omitted per the July 22, 1999 licensing change
12724  *              ftp://ftp.cs.berkeley.edu/pub/4bsd/README.Impt.License.Change>
12725  *
12726  * 4. Neither the name of the University nor the names of its contributors
12727  *    may be used to endorse or promote products derived from this software
12728  *    without specific prior written permission.
12729  *
12730  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
12731  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
12732  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
12733  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
12734  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
12735  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
12736  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
12737  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
12738  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
12739  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
12740  * SUCH DAMAGE.
12741  */