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