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