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