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