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