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