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