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