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