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