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