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