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