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