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