1 /* vi: set sw=4 ts=4: */
3 * ash shell port for busybox
5 * Copyright (c) 1989, 1991, 1993, 1994
6 * The Regents of the University of California. All rights reserved.
8 * Copyright (c) 1997-2005 Herbert Xu <herbert@gondor.apana.org.au>
9 * was re-ported from NetBSD and debianized.
12 * This code is derived from software contributed to Berkeley by
15 * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
17 * Original BSD copyright notice is retained at the end of this file.
21 * rewrite arith.y to micro stack based cryptic algorithm by
22 * Copyright (c) 2001 Aaron Lehmann <aaronl@vitelus.com>
24 * Modified by Paul Mundt <lethal@linux-sh.org> (c) 2004 to support
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.
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.
41 * When debugging is on, debugging info will be written to ./trace and
42 * a quit signal will generate a core dump.
47 #if ENABLE_ASH_JOB_CONTROL
60 #if JOBS || ENABLE_ASH_READ_NCHARS
64 #if defined(__uClinux__)
65 #error "Do not even bother, ash will not run on uClinux"
69 /* ============ Misc helpers */
71 #define xbarrier() do { __asm__ __volatile__ ("": : :"memory"); } while (0)
73 /* C99 say: "char" declaration may be signed or unsigned default */
74 #define signed_char2int(sc) ((int)((signed char)sc))
77 /* ============ Shell options */
79 static const char *const optletters_optnames[] = {
100 #define optletters(n) optletters_optnames[(n)][0]
101 #define optnames(n) (&optletters_optnames[(n)][1])
103 #define NOPTS (sizeof(optletters_optnames)/sizeof(optletters_optnames[0]))
105 static char optlist[NOPTS];
107 #define eflag optlist[0]
108 #define fflag optlist[1]
109 #define Iflag optlist[2]
110 #define iflag optlist[3]
111 #define mflag optlist[4]
112 #define nflag optlist[5]
113 #define sflag optlist[6]
114 #define xflag optlist[7]
115 #define vflag optlist[8]
116 #define Cflag optlist[9]
117 #define aflag optlist[10]
118 #define bflag optlist[11]
119 #define uflag optlist[12]
120 #define viflag optlist[13]
122 #define nolog optlist[14]
123 #define debug optlist[15]
127 /* ============ Misc data */
131 static int *dash_errno;
133 #define errno (*dash_errno)
136 static char nullstr[1]; /* zero length string */
137 static const char homestr[] = "HOME";
138 static const char snlfmt[] = "%s\n";
139 static const char illnum[] = "Illegal number: %s";
141 static char *minusc; /* argument to -c option */
143 static int isloginsh;
144 /* pid of main shell */
146 /* shell level: 0 for the main shell, 1 for its children, and so on */
148 #define rootshell (!shlvl)
149 /* trap handler commands */
150 static char *trap[NSIG];
151 /* current value of signal */
152 static char sigmode[NSIG - 1];
153 /* indicates specified signal received */
154 static char gotsig[NSIG - 1];
155 static char *arg0; /* value of $0 */
158 /* ============ Interrupts / exceptions */
161 * We enclose jmp_buf in a structure so that we can declare pointers to
162 * jump locations. The global variable handler contains the location to
163 * jump to when an exception occurs, and the global variable exception
164 * contains a code identifying the exception. To implement nested
165 * exception handlers, the user should save the value of handler on entry
166 * to an inner scope, set handler to point to a jmploc structure for the
167 * inner scope, and restore handler on exit from the scope.
172 static struct jmploc *exception_handler;
173 static int exception;
175 #define EXINT 0 /* SIGINT received */
176 #define EXERROR 1 /* a generic error */
177 #define EXSHELLPROC 2 /* execute a shell procedure */
178 #define EXEXEC 3 /* command execution failed */
179 #define EXEXIT 4 /* exit the shell */
180 #define EXSIG 5 /* trapped signal in wait(1) */
181 static volatile int suppressint;
182 static volatile sig_atomic_t intpending;
183 /* do we generate EXSIG events */
185 /* last pending signal */
186 static volatile sig_atomic_t pendingsig;
189 * Sigmode records the current value of the signal handlers for the various
190 * modes. A value of zero means that the current handler is not known.
191 * S_HARD_IGN indicates that the signal was ignored on entry to the shell,
194 #define S_DFL 1 /* default signal handling (SIG_DFL) */
195 #define S_CATCH 2 /* signal is caught */
196 #define S_IGN 3 /* signal is ignored (SIG_IGN) */
197 #define S_HARD_IGN 4 /* signal is ignored permenantly */
198 #define S_RESET 5 /* temporary - to reset a hard ignored sig */
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. :-))
213 * Called to raise an exception. Since C doesn't include exceptions, we
214 * just do a longjmp to the exception handler. The type of exception is
215 * stored in the global variable "exception".
217 static void raise_exception(int) ATTRIBUTE_NORETURN;
219 raise_exception(int e)
222 if (exception_handler == NULL)
227 longjmp(exception_handler->loc, 1);
231 * Called from trap.c when a SIGINT is received. (If the user specifies
232 * that SIGINT is to be trapped or ignored using the trap builtin, then
233 * this routine is not called.) Suppressint is nonzero when interrupts
234 * are held using the INT_OFF macro. (The test for iflag is just
235 * defensive programming.)
237 static void raise_interrupt(void) ATTRIBUTE_NORETURN;
239 raise_interrupt(void)
245 /* Signal is not automatically re-enabled after it is raised,
248 sigprocmask(SIG_SETMASK, &mask, 0);
249 /* pendingsig = 0; - now done in onsig() */
252 if (gotsig[SIGINT - 1] && !trap[SIGINT]) {
253 if (!(rootshell && iflag)) {
254 signal(SIGINT, SIG_DFL);
263 #if ENABLE_ASH_OPTIMIZE_FOR_SIZE
267 if (--suppressint == 0 && intpending) {
271 #define INT_ON int_on()
279 #define FORCE_INT_ON force_int_on()
284 if (--suppressint == 0 && intpending) \
287 #define FORCE_INT_ON \
294 #endif /* ASH_OPTIMIZE_FOR_SIZE */
296 #define SAVE_INT(v) ((v) = suppressint)
298 #define RESTORE_INT(v) \
302 if (suppressint == 0 && intpending) \
311 raise_exception(EXSIG); \
313 /* EXSIG is turned off by evalbltin(). */
316 * Ignore a signal. Only one usage site - in forkchild()
321 if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) {
322 signal(signo, SIG_IGN);
324 sigmode[signo - 1] = S_HARD_IGN;
328 * Signal handler. Only one usage site - in setsignal()
333 gotsig[signo - 1] = 1;
336 if (exsig || (signo == SIGINT && !trap[SIGINT])) {
346 /* ============ Stdout/stderr output */
349 outstr(const char *p, FILE *file)
357 flush_stdout_stderr(void)
374 outcslow(int c, FILE *dest)
382 static int out1fmt(const char *, ...) __attribute__((__format__(__printf__,1,2)));
384 out1fmt(const char *fmt, ...)
391 r = vprintf(fmt, ap);
397 static int fmtstr(char *, size_t, const char *, ...) __attribute__((__format__(__printf__,3,4)));
399 fmtstr(char *outbuf, size_t length, const char *fmt, ...)
406 ret = vsnprintf(outbuf, length, fmt, ap);
413 out1str(const char *p)
419 out2str(const char *p)
426 /* ============ Parser structures */
428 /* control characters in argument strings */
429 #define CTLESC '\201' /* escape next character */
430 #define CTLVAR '\202' /* variable defn */
431 #define CTLENDVAR '\203'
432 #define CTLBACKQ '\204'
433 #define CTLQUOTE 01 /* ored with CTLBACKQ code if in quotes */
434 /* CTLBACKQ | CTLQUOTE == '\205' */
435 #define CTLARI '\206' /* arithmetic expression */
436 #define CTLENDARI '\207'
437 #define CTLQUOTEMARK '\210'
439 /* variable substitution byte (follows CTLVAR) */
440 #define VSTYPE 0x0f /* type of variable substitution */
441 #define VSNUL 0x10 /* colon--treat the empty string as unset */
442 #define VSQUOTE 0x80 /* inside double quotes--suppress splitting */
444 /* values of VSTYPE field */
445 #define VSNORMAL 0x1 /* normal variable: $var or ${var} */
446 #define VSMINUS 0x2 /* ${var-text} */
447 #define VSPLUS 0x3 /* ${var+text} */
448 #define VSQUESTION 0x4 /* ${var?message} */
449 #define VSASSIGN 0x5 /* ${var=text} */
450 #define VSTRIMRIGHT 0x6 /* ${var%pattern} */
451 #define VSTRIMRIGHTMAX 0x7 /* ${var%%pattern} */
452 #define VSTRIMLEFT 0x8 /* ${var#pattern} */
453 #define VSTRIMLEFTMAX 0x9 /* ${var##pattern} */
454 #define VSLENGTH 0xa /* ${#var} */
456 static const char dolatstr[] = { CTLVAR, VSNORMAL|VSQUOTE, '@', '=', '\0' };
491 union node *redirect;
497 struct nodelist *cmdlist;
503 union node *redirect;
516 union node *elsepart;
543 struct nodelist *backquote;
578 struct nredir nredir;
579 struct nbinary nbinary;
583 struct nclist nclist;
592 struct nodelist *next;
605 freefunc(struct funcnode *f)
607 if (f && --f->count < 0)
612 /* ============ Debugging output */
616 static FILE *tracefile;
619 trace_printf(const char *fmt, ...)
626 vfprintf(tracefile, fmt, va);
631 trace_vprintf(const char *fmt, va_list va)
635 vfprintf(tracefile, fmt, va);
639 trace_puts(const char *s)
647 trace_puts_quoted(char *s)
654 putc('"', tracefile);
655 for (p = s; *p; p++) {
657 case '\n': c = 'n'; goto backslash;
658 case '\t': c = 't'; goto backslash;
659 case '\r': c = 'r'; goto backslash;
660 case '"': c = '"'; goto backslash;
661 case '\\': c = '\\'; goto backslash;
662 case CTLESC: c = 'e'; goto backslash;
663 case CTLVAR: c = 'v'; goto backslash;
664 case CTLVAR+CTLQUOTE: c = 'V'; goto backslash;
665 case CTLBACKQ: c = 'q'; goto backslash;
666 case CTLBACKQ+CTLQUOTE: c = 'Q'; goto backslash;
668 putc('\\', tracefile);
672 if (*p >= ' ' && *p <= '~')
675 putc('\\', tracefile);
676 putc(*p >> 6 & 03, tracefile);
677 putc(*p >> 3 & 07, tracefile);
678 putc(*p & 07, tracefile);
683 putc('"', tracefile);
687 trace_puts_args(char **ap)
694 trace_puts_quoted(*ap);
696 putc('\n', tracefile);
699 putc(' ', tracefile);
714 /* leave open because libedit might be using it */
717 strcpy(s, "./trace");
719 if (!freopen(s, "a", tracefile)) {
720 fprintf(stderr, "Can't re-open %s\n", s);
725 tracefile = fopen(s, "a");
726 if (tracefile == NULL) {
727 fprintf(stderr, "Can't open %s\n", s);
733 flags = fcntl(fileno(tracefile), F_GETFL, 0);
735 fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND);
737 setlinebuf(tracefile);
738 fputs("\nTracing started.\n", tracefile);
742 indent(int amount, char *pfx, FILE *fp)
746 for (i = 0; i < amount; i++) {
747 if (pfx && i == amount - 1)
753 /* little circular references here... */
754 static void shtree(union node *n, int ind, char *pfx, FILE *fp);
757 sharg(union node *arg, FILE *fp)
760 struct nodelist *bqlist;
763 if (arg->type != NARG) {
764 out1fmt("<node type %d>\n", arg->type);
767 bqlist = arg->narg.backquote;
768 for (p = arg->narg.text; *p; p++) {
777 if (subtype == VSLENGTH)
786 switch (subtype & VSTYPE) {
819 out1fmt("<subtype %d>", subtype);
826 case CTLBACKQ|CTLQUOTE:
829 shtree(bqlist->n, -1, NULL, fp);
840 shcmd(union node *cmd, FILE *fp)
848 for (np = cmd->ncmd.args; np; np = np->narg.next) {
854 for (np = cmd->ncmd.redirect; np; np = np->nfile.next) {
857 switch (np->nfile.type) {
858 case NTO: s = ">"; dftfd = 1; break;
859 case NCLOBBER: s = ">|"; dftfd = 1; break;
860 case NAPPEND: s = ">>"; dftfd = 1; break;
861 case NTOFD: s = ">&"; dftfd = 1; break;
862 case NFROM: s = "<"; dftfd = 0; break;
863 case NFROMFD: s = "<&"; dftfd = 0; break;
864 case NFROMTO: s = "<>"; dftfd = 0; break;
865 default: s = "*error*"; dftfd = 0; break;
867 if (np->nfile.fd != dftfd)
868 fprintf(fp, "%d", np->nfile.fd);
870 if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) {
871 fprintf(fp, "%d", np->ndup.dupfd);
873 sharg(np->nfile.fname, fp);
880 shtree(union node *n, int ind, char *pfx, FILE *fp)
888 indent(ind, pfx, fp);
899 shtree(n->nbinary.ch1, ind, NULL, fp);
902 shtree(n->nbinary.ch2, ind, NULL, fp);
910 for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
915 if (n->npipe.backgnd)
921 fprintf(fp, "<node type %d>", n->type);
929 showtree(union node *n)
931 trace_puts("showtree called\n");
932 shtree(n, 1, NULL, stdout);
935 #define TRACE(param) trace_printf param
936 #define TRACEV(param) trace_vprintf param
941 #define TRACEV(param)
946 /* ============ Parser data */
949 * ash_vmsg() needs parsefile->fd, hence parsefile definition is moved up.
952 struct strlist *next;
961 struct strpush *prev; /* preceding string on stack */
965 struct alias *ap; /* if push was associated with an alias */
967 char *string; /* remember the string since it may change */
971 struct parsefile *prev; /* preceding file on stack */
972 int linno; /* current line */
973 int fd; /* file descriptor (or -1 if string) */
974 int nleft; /* number of chars left in this line */
975 int lleft; /* number of chars left in this buffer */
976 char *nextc; /* next char in buffer */
977 char *buf; /* input buffer */
978 struct strpush *strpush; /* for pushing strings at this level */
979 struct strpush basestrpush; /* so pushing one is fast */
982 static struct parsefile basepf; /* top level input file */
983 static struct parsefile *parsefile = &basepf; /* current input file */
984 static int startlinno; /* line # where last token started */
985 static char *commandname; /* currently executing command */
986 static struct strlist *cmdenviron; /* environment for builtin command */
987 static int exitstatus; /* exit status of last command */
990 /* ============ Message printing */
993 ash_vmsg(const char *msg, va_list ap)
995 fprintf(stderr, "%s: ", arg0);
997 if (strcmp(arg0, commandname))
998 fprintf(stderr, "%s: ", commandname);
999 if (!iflag || parsefile->fd)
1000 fprintf(stderr, "line %d: ", startlinno);
1002 vfprintf(stderr, msg, ap);
1003 outcslow('\n', stderr);
1007 * Exverror is called to raise the error exception. If the second argument
1008 * is not NULL then error prints an error message using printf style
1009 * formatting. It then raises the error exception.
1011 static void ash_vmsg_and_raise(int, const char *, va_list) ATTRIBUTE_NORETURN;
1013 ash_vmsg_and_raise(int cond, const char *msg, va_list ap)
1017 TRACE(("ash_vmsg_and_raise(%d, \"", cond));
1019 TRACE(("\") pid=%d\n", getpid()));
1021 TRACE(("ash_vmsg_and_raise(%d, NULL) pid=%d\n", cond, getpid()));
1026 flush_stdout_stderr();
1027 raise_exception(cond);
1031 static void ash_msg_and_raise_error(const char *, ...) ATTRIBUTE_NORETURN;
1033 ash_msg_and_raise_error(const char *msg, ...)
1038 ash_vmsg_and_raise(EXERROR, msg, ap);
1043 static void ash_msg_and_raise(int, const char *, ...) ATTRIBUTE_NORETURN;
1045 ash_msg_and_raise(int cond, const char *msg, ...)
1050 ash_vmsg_and_raise(cond, msg, ap);
1056 * error/warning routines for external builtins
1059 ash_msg(const char *fmt, ...)
1069 * Return a string describing an error. The returned string may be a
1070 * pointer to a static buffer that will be overwritten on the next call.
1071 * Action describes the operation that got the error.
1074 errmsg(int e, const char *em)
1076 if (e == ENOENT || e == ENOTDIR) {
1083 /* ============ Memory allocation */
1086 * It appears that grabstackstr() will barf with such alignments
1087 * because stalloc() will return a string allocated in a new stackblock.
1089 #define SHELL_ALIGN(nbytes) (((nbytes) + SHELL_SIZE) & ~SHELL_SIZE)
1091 /* Most machines require the value returned from malloc to be aligned
1092 * in some way. The following macro will get this right
1093 * on many machines. */
1094 SHELL_SIZE = sizeof(union {int i; char *cp; double d; }) - 1,
1095 /* Minimum size of a block */
1096 MINSIZE = SHELL_ALIGN(504),
1099 struct stack_block {
1100 struct stack_block *prev;
1101 char space[MINSIZE];
1105 struct stack_block *stackp;
1108 struct stackmark *marknext;
1111 static struct stack_block stackbase;
1112 static struct stack_block *stackp = &stackbase;
1113 static struct stackmark *markp;
1114 static char *stacknxt = stackbase.space;
1115 static size_t stacknleft = MINSIZE;
1116 static char *sstrend = stackbase.space + MINSIZE;
1117 static int herefd = -1;
1119 #define stackblock() ((void *)stacknxt)
1120 #define stackblocksize() stacknleft
1123 ckrealloc(void * p, size_t nbytes)
1125 p = realloc(p, nbytes);
1127 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1132 ckmalloc(size_t nbytes)
1134 return ckrealloc(NULL, nbytes);
1138 * Make a copy of a string in safe storage.
1141 ckstrdup(const char *s)
1143 char *p = strdup(s);
1145 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1150 * Parse trees for commands are allocated in lifo order, so we use a stack
1151 * to make this more efficient, and also to avoid all sorts of exception
1152 * handling code to handle interrupts in the middle of a parse.
1154 * The size 504 was chosen because the Ultrix malloc handles that size
1158 stalloc(size_t nbytes)
1163 aligned = SHELL_ALIGN(nbytes);
1164 if (aligned > stacknleft) {
1167 struct stack_block *sp;
1169 blocksize = aligned;
1170 if (blocksize < MINSIZE)
1171 blocksize = MINSIZE;
1172 len = sizeof(struct stack_block) - MINSIZE + blocksize;
1173 if (len < blocksize)
1174 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1178 stacknxt = sp->space;
1179 stacknleft = blocksize;
1180 sstrend = stacknxt + blocksize;
1185 stacknxt += aligned;
1186 stacknleft -= aligned;
1194 if (!p || (stacknxt < (char *)p) || ((char *)p < stackp->space)) {
1195 write(2, "stunalloc\n", 10);
1199 stacknleft += stacknxt - (char *)p;
1204 * Like strdup but works with the ash stack.
1207 ststrdup(const char *p)
1209 size_t len = strlen(p) + 1;
1210 return memcpy(stalloc(len), p, len);
1214 setstackmark(struct stackmark *mark)
1216 mark->stackp = stackp;
1217 mark->stacknxt = stacknxt;
1218 mark->stacknleft = stacknleft;
1219 mark->marknext = markp;
1224 popstackmark(struct stackmark *mark)
1226 struct stack_block *sp;
1232 markp = mark->marknext;
1233 while (stackp != mark->stackp) {
1238 stacknxt = mark->stacknxt;
1239 stacknleft = mark->stacknleft;
1240 sstrend = mark->stacknxt + mark->stacknleft;
1245 * When the parser reads in a string, it wants to stick the string on the
1246 * stack and only adjust the stack pointer when it knows how big the
1247 * string is. Stackblock (defined in stack.h) returns a pointer to a block
1248 * of space on top of the stack and stackblocklen returns the length of
1249 * this block. Growstackblock will grow this space by at least one byte,
1250 * possibly moving it (like realloc). Grabstackblock actually allocates the
1251 * part of the block that has been used.
1254 growstackblock(void)
1258 newlen = stacknleft * 2;
1259 if (newlen < stacknleft)
1260 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1264 if (stacknxt == stackp->space && stackp != &stackbase) {
1265 struct stack_block *oldstackp;
1266 struct stackmark *xmark;
1267 struct stack_block *sp;
1268 struct stack_block *prevstackp;
1274 prevstackp = sp->prev;
1275 grosslen = newlen + sizeof(struct stack_block) - MINSIZE;
1276 sp = ckrealloc(sp, grosslen);
1277 sp->prev = prevstackp;
1279 stacknxt = sp->space;
1280 stacknleft = newlen;
1281 sstrend = sp->space + newlen;
1284 * Stack marks pointing to the start of the old block
1285 * must be relocated to point to the new block
1288 while (xmark != NULL && xmark->stackp == oldstackp) {
1289 xmark->stackp = stackp;
1290 xmark->stacknxt = stacknxt;
1291 xmark->stacknleft = stacknleft;
1292 xmark = xmark->marknext;
1296 char *oldspace = stacknxt;
1297 int oldlen = stacknleft;
1298 char *p = stalloc(newlen);
1300 /* free the space we just allocated */
1301 stacknxt = memcpy(p, oldspace, oldlen);
1302 stacknleft += newlen;
1307 grabstackblock(size_t len)
1309 len = SHELL_ALIGN(len);
1315 * The following routines are somewhat easier to use than the above.
1316 * The user declares a variable of type STACKSTR, which may be declared
1317 * to be a register. The macro STARTSTACKSTR initializes things. Then
1318 * the user uses the macro STPUTC to add characters to the string. In
1319 * effect, STPUTC(c, p) is the same as *p++ = c except that the stack is
1320 * grown as necessary. When the user is done, she can just leave the
1321 * string there and refer to it using stackblock(). Or she can allocate
1322 * the space for it using grabstackstr(). If it is necessary to allow
1323 * someone else to use the stack temporarily and then continue to grow
1324 * the string, the user should use grabstack to allocate the space, and
1325 * then call ungrabstr(p) to return to the previous mode of operation.
1327 * USTPUTC is like STPUTC except that it doesn't check for overflow.
1328 * CHECKSTACKSPACE can be called before USTPUTC to ensure that there
1329 * is space for at least one character.
1334 size_t len = stackblocksize();
1335 if (herefd >= 0 && len >= 1024) {
1336 full_write(herefd, stackblock(), len);
1337 return stackblock();
1340 return stackblock() + len;
1344 * Called from CHECKSTRSPACE.
1347 makestrspace(size_t newlen, char *p)
1349 size_t len = p - stacknxt;
1350 size_t size = stackblocksize();
1355 size = stackblocksize();
1357 if (nleft >= newlen)
1361 return stackblock() + len;
1365 stack_nputstr(const char *s, size_t n, char *p)
1367 p = makestrspace(n, p);
1368 p = memcpy(p, s, n) + n;
1373 stack_putstr(const char *s, char *p)
1375 return stack_nputstr(s, strlen(s), p);
1379 _STPUTC(int c, char *p)
1387 #define STARTSTACKSTR(p) ((p) = stackblock())
1388 #define STPUTC(c, p) ((p) = _STPUTC((c), (p)))
1389 #define CHECKSTRSPACE(n, p) \
1393 size_t m = sstrend - q; \
1395 (p) = makestrspace(l, q); \
1397 #define USTPUTC(c, p) (*p++ = (c))
1398 #define STACKSTRNUL(p) \
1400 if ((p) == sstrend) \
1401 p = growstackstr(); \
1404 #define STUNPUTC(p) (--p)
1405 #define STTOPC(p) (p[-1])
1406 #define STADJUST(amount, p) (p += (amount))
1408 #define grabstackstr(p) stalloc((char *)(p) - (char *)stackblock())
1409 #define ungrabstackstr(s, p) stunalloc((s))
1410 #define stackstrend() ((void *)sstrend)
1413 /* ============ String helpers */
1416 * prefix -- see if pfx is a prefix of string.
1419 prefix(const char *string, const char *pfx)
1422 if (*pfx++ != *string++)
1425 return (char *) string;
1429 * Check for a valid number. This should be elsewhere.
1432 is_number(const char *p)
1437 } while (*++p != '\0');
1442 * Convert a string of digits to an integer, printing an error message on
1446 number(const char *s)
1449 ash_msg_and_raise_error(illnum, s);
1454 * Produce a possibly single quoted string suitable as input to the shell.
1455 * The return string is allocated on the stack.
1458 single_quote(const char *s)
1468 len = strchrnul(s, '\'') - s;
1470 q = p = makestrspace(len + 3, p);
1473 q = memcpy(q, s, len) + len;
1479 len = strspn(s, "'");
1483 q = p = makestrspace(len + 3, p);
1486 q = memcpy(q, s, len) + len;
1495 return stackblock();
1499 /* ============ nextopt */
1501 static char **argptr; /* argument list for builtin commands */
1502 static char *optionarg; /* set by nextopt (like getopt) */
1503 static char *optptr; /* used by nextopt */
1506 * XXX - should get rid of. have all builtins use getopt(3). the
1507 * library getopt must have the BSD extension static variable "optreset"
1508 * otherwise it can't be used within the shell safely.
1510 * Standard option processing (a la getopt) for builtin routines. The
1511 * only argument that is passed to nextopt is the option string; the
1512 * other arguments are unnecessary. It return the character, or '\0' on
1516 nextopt(const char *optstring)
1523 if (p == NULL || *p == '\0') {
1525 if (p == NULL || *p != '-' || *++p == '\0')
1528 if (LONE_DASH(p)) /* check for "--" */
1532 for (q = optstring; *q != c; ) {
1534 ash_msg_and_raise_error("illegal option -%c", c);
1539 if (*p == '\0' && (p = *argptr++) == NULL)
1540 ash_msg_and_raise_error("no arg for -%c option", c);
1549 /* ============ Math support definitions */
1551 #if ENABLE_ASH_MATH_SUPPORT_64
1552 typedef int64_t arith_t;
1553 #define arith_t_type long long
1555 typedef long arith_t;
1556 #define arith_t_type long
1559 #if ENABLE_ASH_MATH_SUPPORT
1560 static arith_t dash_arith(const char *);
1561 static arith_t arith(const char *expr, int *perrcode);
1564 #if ENABLE_ASH_RANDOM_SUPPORT
1565 static unsigned long rseed;
1572 /* ============ Shell variables */
1575 #define VEXPORT 0x01 /* variable is exported */
1576 #define VREADONLY 0x02 /* variable cannot be modified */
1577 #define VSTRFIXED 0x04 /* variable struct is statically allocated */
1578 #define VTEXTFIXED 0x08 /* text is statically allocated */
1579 #define VSTACK 0x10 /* text is allocated on the stack */
1580 #define VUNSET 0x20 /* the variable is not set */
1581 #define VNOFUNC 0x40 /* don't call the callback function */
1582 #define VNOSET 0x80 /* do not set variable - just readonly test */
1583 #define VNOSAVE 0x100 /* when text is on the heap before setvareq */
1585 # define VDYNAMIC 0x200 /* dynamic variable */
1590 static const char defpathvar[] = "PATH=/usr/local/bin:/usr/bin:/sbin:/bin";
1592 static const char defifsvar[] = "IFS= \t\n";
1593 #define defifs (defifsvar + 4)
1595 static const char defifs[] = " \t\n";
1599 int nparam; /* # of positional parameters (without $0) */
1600 unsigned char malloc; /* if parameter list dynamically allocated */
1601 char **p; /* parameter list */
1602 #if ENABLE_ASH_GETOPTS
1603 int optind; /* next parameter to be processed by getopts */
1604 int optoff; /* used by getopts */
1608 static struct shparam shellparam; /* $@ current positional parameters */
1611 * Free the list of positional parameters.
1614 freeparam(volatile struct shparam *param)
1618 if (param->malloc) {
1619 for (ap = param->p; *ap; ap++)
1625 #if ENABLE_ASH_GETOPTS
1627 getoptsreset(const char *value)
1629 shellparam.optind = number(value);
1630 shellparam.optoff = -1;
1635 struct var *next; /* next entry in hash list */
1636 int flags; /* flags are defined above */
1637 const char *text; /* name=value */
1638 void (*func)(const char *); /* function to be called when */
1639 /* the variable gets set/unset */
1643 struct localvar *next; /* next local variable in list */
1644 struct var *vp; /* the variable that was made local */
1645 int flags; /* saved flags */
1646 const char *text; /* saved text */
1649 /* Forward decls for varinit[] */
1650 #if ENABLE_LOCALE_SUPPORT
1652 change_lc_all(const char *value)
1654 if (value && *value != '\0')
1655 setlocale(LC_ALL, value);
1658 change_lc_ctype(const char *value)
1660 if (value && *value != '\0')
1661 setlocale(LC_CTYPE, value);
1665 static void chkmail(void);
1666 static void changemail(const char *);
1668 static void changepath(const char *);
1669 #if ENABLE_ASH_RANDOM_SUPPORT
1670 static void change_random(const char *);
1673 static struct var varinit[] = {
1675 { NULL, VSTRFIXED|VTEXTFIXED, defifsvar, NULL },
1677 { NULL, VSTRFIXED|VTEXTFIXED|VUNSET, "IFS\0", NULL },
1680 { NULL, VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL\0", changemail },
1681 { NULL, VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH\0", changemail },
1683 { NULL, VSTRFIXED|VTEXTFIXED, defpathvar, changepath },
1684 { NULL, VSTRFIXED|VTEXTFIXED, "PS1=$ ", NULL },
1685 { NULL, VSTRFIXED|VTEXTFIXED, "PS2=> ", NULL },
1686 { NULL, VSTRFIXED|VTEXTFIXED, "PS4=+ ", NULL },
1687 #if ENABLE_ASH_GETOPTS
1688 { NULL, VSTRFIXED|VTEXTFIXED, "OPTIND=1", getoptsreset },
1690 #if ENABLE_ASH_RANDOM_SUPPORT
1691 { NULL, VSTRFIXED|VTEXTFIXED|VUNSET|VDYNAMIC, "RANDOM\0", change_random },
1693 #if ENABLE_LOCALE_SUPPORT
1694 { NULL, VSTRFIXED | VTEXTFIXED | VUNSET, "LC_ALL\0", change_lc_all },
1695 { NULL, VSTRFIXED | VTEXTFIXED | VUNSET, "LC_CTYPE\0", change_lc_ctype },
1697 #if ENABLE_FEATURE_EDITING_SAVEHISTORY
1698 { NULL, VSTRFIXED | VTEXTFIXED | VUNSET, "HISTFILE\0", NULL },
1702 #define vifs varinit[0]
1704 #define vmail (&vifs)[1]
1705 #define vmpath (&vmail)[1]
1709 #define vpath (&vmpath)[1]
1710 #define vps1 (&vpath)[1]
1711 #define vps2 (&vps1)[1]
1712 #define vps4 (&vps2)[1]
1713 #define voptind (&vps4)[1]
1714 #if ENABLE_ASH_GETOPTS
1715 #define vrandom (&voptind)[1]
1717 #define vrandom (&vps4)[1]
1719 #define defpath (defpathvar + 5)
1722 * The following macros access the values of the above variables.
1723 * They have to skip over the name. They return the null string
1724 * for unset variables.
1726 #define ifsval() (vifs.text + 4)
1727 #define ifsset() ((vifs.flags & VUNSET) == 0)
1728 #define mailval() (vmail.text + 5)
1729 #define mpathval() (vmpath.text + 9)
1730 #define pathval() (vpath.text + 5)
1731 #define ps1val() (vps1.text + 4)
1732 #define ps2val() (vps2.text + 4)
1733 #define ps4val() (vps4.text + 4)
1734 #define optindval() (voptind.text + 7)
1736 #define mpathset() ((vmpath.flags & VUNSET) == 0)
1739 * The parsefile structure pointed to by the global variable parsefile
1740 * contains information about the current file being read.
1743 struct redirtab *next;
1748 static struct redirtab *redirlist;
1749 static int nullredirs;
1750 extern char **environ;
1751 static int preverrout_fd; /* save fd2 before print debug if xflag is set. */
1755 static struct var *vartab[VTABSIZE];
1757 #define is_name(c) ((c) == '_' || isalpha((unsigned char)(c)))
1758 #define is_in_name(c) ((c) == '_' || isalnum((unsigned char)(c)))
1761 * Return of a legal variable name (a letter or underscore followed by zero or
1762 * more letters, underscores, and digits).
1765 endofname(const char *name)
1773 if (!is_in_name(*p))
1780 * Compares two strings up to the first = or '\0'. The first
1781 * string must be terminated by '='; the second may be terminated by
1782 * either '=' or '\0'.
1785 varcmp(const char *p, const char *q)
1789 while ((c = *p) == (d = *q)) {
1804 varequal(const char *a, const char *b)
1806 return !varcmp(a, b);
1810 * Find the appropriate entry in the hash table from the name.
1812 static struct var **
1813 hashvar(const char *p)
1817 hashval = ((unsigned char) *p) << 4;
1818 while (*p && *p != '=')
1819 hashval += (unsigned char) *p++;
1820 return &vartab[hashval % VTABSIZE];
1824 vpcmp(const void *a, const void *b)
1826 return varcmp(*(const char **)a, *(const char **)b);
1830 * This routine initializes the builtin variables.
1840 * PS1 depends on uid
1842 #if ENABLE_FEATURE_EDITING && ENABLE_FEATURE_EDITING_FANCY_PROMPT
1843 vps1.text = "PS1=\\w \\$ ";
1846 vps1.text = "PS1=# ";
1849 end = vp + sizeof(varinit) / sizeof(varinit[0]);
1851 vpp = hashvar(vp->text);
1854 } while (++vp < end);
1857 static struct var **
1858 findvar(struct var **vpp, const char *name)
1860 for (; *vpp; vpp = &(*vpp)->next) {
1861 if (varequal((*vpp)->text, name)) {
1869 * Find the value of a variable. Returns NULL if not set.
1872 lookupvar(const char *name)
1876 v = *findvar(hashvar(name), name);
1880 * Dynamic variables are implemented roughly the same way they are
1881 * in bash. Namely, they're "special" so long as they aren't unset.
1882 * As soon as they're unset, they're no longer dynamic, and dynamic
1883 * lookup will no longer happen at that point. -- PFM.
1885 if ((v->flags & VDYNAMIC))
1888 if (!(v->flags & VUNSET))
1889 return strchrnul(v->text, '=') + 1;
1895 * Search the environment of a builtin command.
1898 bltinlookup(const char *name)
1902 for (sp = cmdenviron; sp; sp = sp->next) {
1903 if (varequal(sp->text, name))
1904 return strchrnul(sp->text, '=') + 1;
1906 return lookupvar(name);
1910 * Same as setvar except that the variable and value are passed in
1911 * the first argument as name=value. Since the first argument will
1912 * be actually stored in the table, it should not be a string that
1914 * Called with interrupts off.
1917 setvareq(char *s, int flags)
1919 struct var *vp, **vpp;
1922 flags |= (VEXPORT & (((unsigned) (1 - aflag)) - 1));
1923 vp = *findvar(vpp, s);
1925 if ((vp->flags & (VREADONLY|VDYNAMIC)) == VREADONLY) {
1928 if (flags & VNOSAVE)
1931 ash_msg_and_raise_error("%.*s: is read only", strchrnul(n, '=') - n, n);
1937 if (vp->func && (flags & VNOFUNC) == 0)
1938 (*vp->func)(strchrnul(s, '=') + 1);
1940 if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
1941 free((char*)vp->text);
1943 flags |= vp->flags & ~(VTEXTFIXED|VSTACK|VNOSAVE|VUNSET);
1948 vp = ckmalloc(sizeof(*vp));
1953 if (!(flags & (VTEXTFIXED|VSTACK|VNOSAVE)))
1960 * Set the value of a variable. The flags argument is ored with the
1961 * flags of the variable. If val is NULL, the variable is unset.
1964 setvar(const char *name, const char *val, int flags)
1971 q = endofname(name);
1972 p = strchrnul(q, '=');
1974 if (!namelen || p != q)
1975 ash_msg_and_raise_error("%.*s: bad variable name", namelen, name);
1980 vallen = strlen(val);
1983 nameeq = ckmalloc(namelen + vallen + 2);
1984 p = memcpy(nameeq, name, namelen) + namelen;
1987 p = memcpy(p, val, vallen) + vallen;
1990 setvareq(nameeq, flags | VNOSAVE);
1994 #if ENABLE_ASH_GETOPTS
1996 * Safe version of setvar, returns 1 on success 0 on failure.
1999 setvarsafe(const char *name, const char *val, int flags)
2002 volatile int saveint;
2003 struct jmploc *volatile savehandler = exception_handler;
2004 struct jmploc jmploc;
2007 if (setjmp(jmploc.loc))
2010 exception_handler = &jmploc;
2011 setvar(name, val, flags);
2014 exception_handler = savehandler;
2015 RESTORE_INT(saveint);
2021 * Unset the specified variable.
2024 unsetvar(const char *s)
2030 vpp = findvar(hashvar(s), s);
2034 int flags = vp->flags;
2037 if (flags & VREADONLY)
2040 vp->flags &= ~VDYNAMIC;
2044 if ((flags & VSTRFIXED) == 0) {
2046 if ((flags & (VTEXTFIXED|VSTACK)) == 0)
2047 free((char*)vp->text);
2053 vp->flags &= ~VEXPORT;
2063 * Process a linked list of variable assignments.
2066 listsetvar(struct strlist *list_set_var, int flags)
2068 struct strlist *lp = list_set_var;
2074 setvareq(lp->text, flags);
2081 * Generate a list of variables satisfying the given conditions.
2084 listvars(int on, int off, char ***end)
2095 for (vp = *vpp; vp; vp = vp->next) {
2096 if ((vp->flags & mask) == on) {
2097 if (ep == stackstrend())
2098 ep = growstackstr();
2099 *ep++ = (char *) vp->text;
2102 } while (++vpp < vartab + VTABSIZE);
2103 if (ep == stackstrend())
2104 ep = growstackstr();
2108 return grabstackstr(ep);
2112 /* ============ Path search helper
2114 * The variable path (passed by reference) should be set to the start
2115 * of the path before the first call; padvance will update
2116 * this value as it proceeds. Successive calls to padvance will return
2117 * the possible path expansions in sequence. If an option (indicated by
2118 * a percent sign) appears in the path entry then the global variable
2119 * pathopt will be set to point to it; otherwise pathopt will be set to
2122 static const char *pathopt; /* set by padvance */
2125 padvance(const char **path, const char *name)
2135 for (p = start; *p && *p != ':' && *p != '%'; p++);
2136 len = p - start + strlen(name) + 2; /* "2" is for '/' and '\0' */
2137 while (stackblocksize() < len)
2141 memcpy(q, start, p - start);
2149 while (*p && *p != ':') p++;
2155 return stalloc(len);
2159 /* ============ Prompt */
2161 static int doprompt; /* if set, prompt the user */
2162 static int needprompt; /* true if interactive and at start of line */
2164 #if ENABLE_FEATURE_EDITING
2165 static line_input_t *line_input_state;
2166 static const char *cmdedit_prompt;
2168 putprompt(const char *s)
2170 if (ENABLE_ASH_EXPAND_PRMT) {
2171 free((char*)cmdedit_prompt);
2172 cmdedit_prompt = ckstrdup(s);
2179 putprompt(const char *s)
2185 #if ENABLE_ASH_EXPAND_PRMT
2186 /* expandstr() needs parsing machinery, so it is far away ahead... */
2187 static const char *expandstr(const char *ps);
2189 #define expandstr(s) s
2193 setprompt(int whichprompt)
2196 #if ENABLE_ASH_EXPAND_PRMT
2197 struct stackmark smark;
2202 switch (whichprompt) {
2212 #if ENABLE_ASH_EXPAND_PRMT
2213 setstackmark(&smark);
2214 stalloc(stackblocksize());
2216 putprompt(expandstr(prompt));
2217 #if ENABLE_ASH_EXPAND_PRMT
2218 popstackmark(&smark);
2223 /* ============ The cd and pwd commands */
2225 #define CD_PHYSICAL 1
2228 static int docd(const char *, int);
2230 static char *curdir = nullstr; /* current working directory */
2231 static char *physdir = nullstr; /* physical working directory */
2240 while ((i = nextopt("LP"))) {
2242 flags ^= CD_PHYSICAL;
2251 * Update curdir (the name of the current directory) in response to a
2255 updatepwd(const char *dir)
2262 cdcomppath = ststrdup(dir);
2265 if (curdir == nullstr)
2267 new = stack_putstr(curdir, new);
2269 new = makestrspace(strlen(dir) + 2, new);
2270 lim = stackblock() + 1;
2274 if (new > lim && *lim == '/')
2279 if (dir[1] == '/' && dir[2] != '/') {
2285 p = strtok(cdcomppath, "/");
2289 if (p[1] == '.' && p[2] == '\0') {
2301 new = stack_putstr(p, new);
2309 return stackblock();
2313 * Find out what the current directory is. If we already know the current
2314 * directory, this routine returns immediately.
2319 char *dir = getcwd(0, 0);
2320 return dir ? dir : nullstr;
2324 setpwd(const char *val, int setold)
2328 oldcur = dir = curdir;
2331 setvar("OLDPWD", oldcur, VEXPORT);
2334 if (physdir != nullstr) {
2335 if (physdir != oldcur)
2339 if (oldcur == val || !val) {
2345 dir = ckstrdup(val);
2346 if (oldcur != dir && oldcur != nullstr) {
2351 setvar("PWD", dir, VEXPORT);
2354 static void hashcd(void);
2357 * Actually do the chdir. We also call hashcd to let the routines in exec.c
2358 * know that the current directory has changed.
2361 docd(const char *dest, int flags)
2363 const char *dir = 0;
2366 TRACE(("docd(\"%s\", %d) called\n", dest, flags));
2369 if (!(flags & CD_PHYSICAL)) {
2370 dir = updatepwd(dest);
2385 cdcmd(int argc, char **argv)
2397 dest = bltinlookup(homestr);
2398 else if (LONE_DASH(dest)) {
2399 dest = bltinlookup("OLDPWD");
2421 path = bltinlookup("CDPATH");
2430 p = padvance(&path, dest);
2431 if (stat(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) {
2435 if (!docd(p, flags))
2440 ash_msg_and_raise_error("can't cd to %s", dest);
2443 if (flags & CD_PRINT)
2444 out1fmt(snlfmt, curdir);
2449 pwdcmd(int argc, char **argv)
2452 const char *dir = curdir;
2456 if (physdir == nullstr)
2460 out1fmt(snlfmt, dir);
2465 /* ============ ... */
2467 #define IBUFSIZ (BUFSIZ + 1)
2468 #define basebuf bb_common_bufsiz1 /* buffer for top level input file */
2470 /* Syntax classes */
2471 #define CWORD 0 /* character is nothing special */
2472 #define CNL 1 /* newline character */
2473 #define CBACK 2 /* a backslash character */
2474 #define CSQUOTE 3 /* single quote */
2475 #define CDQUOTE 4 /* double quote */
2476 #define CENDQUOTE 5 /* a terminating quote */
2477 #define CBQUOTE 6 /* backwards single quote */
2478 #define CVAR 7 /* a dollar sign */
2479 #define CENDVAR 8 /* a '}' character */
2480 #define CLP 9 /* a left paren in arithmetic */
2481 #define CRP 10 /* a right paren in arithmetic */
2482 #define CENDFILE 11 /* end of file */
2483 #define CCTL 12 /* like CWORD, except it must be escaped */
2484 #define CSPCL 13 /* these terminate a word */
2485 #define CIGN 14 /* character should be ignored */
2487 #if ENABLE_ASH_ALIAS
2491 #define PEOA_OR_PEOF PEOA
2495 #define PEOA_OR_PEOF PEOF
2498 /* number syntax index */
2499 #define BASESYNTAX 0 /* not in quotes */
2500 #define DQSYNTAX 1 /* in double quotes */
2501 #define SQSYNTAX 2 /* in single quotes */
2502 #define ARISYNTAX 3 /* in arithmetic */
2504 #if ENABLE_ASH_OPTIMIZE_FOR_SIZE
2505 #define USE_SIT_FUNCTION
2508 #if ENABLE_ASH_MATH_SUPPORT
2509 static const char S_I_T[][4] = {
2510 #if ENABLE_ASH_ALIAS
2511 { CSPCL, CIGN, CIGN, CIGN }, /* 0, PEOA */
2513 { CSPCL, CWORD, CWORD, CWORD }, /* 1, ' ' */
2514 { CNL, CNL, CNL, CNL }, /* 2, \n */
2515 { CWORD, CCTL, CCTL, CWORD }, /* 3, !*-/:=?[]~ */
2516 { CDQUOTE, CENDQUOTE, CWORD, CWORD }, /* 4, '"' */
2517 { CVAR, CVAR, CWORD, CVAR }, /* 5, $ */
2518 { CSQUOTE, CWORD, CENDQUOTE, CWORD }, /* 6, "'" */
2519 { CSPCL, CWORD, CWORD, CLP }, /* 7, ( */
2520 { CSPCL, CWORD, CWORD, CRP }, /* 8, ) */
2521 { CBACK, CBACK, CCTL, CBACK }, /* 9, \ */
2522 { CBQUOTE, CBQUOTE, CWORD, CBQUOTE }, /* 10, ` */
2523 { CENDVAR, CENDVAR, CWORD, CENDVAR }, /* 11, } */
2524 #ifndef USE_SIT_FUNCTION
2525 { CENDFILE, CENDFILE, CENDFILE, CENDFILE }, /* 12, PEOF */
2526 { CWORD, CWORD, CWORD, CWORD }, /* 13, 0-9A-Za-z */
2527 { CCTL, CCTL, CCTL, CCTL } /* 14, CTLESC ... */
2531 static const char S_I_T[][3] = {
2532 #if ENABLE_ASH_ALIAS
2533 { CSPCL, CIGN, CIGN }, /* 0, PEOA */
2535 { CSPCL, CWORD, CWORD }, /* 1, ' ' */
2536 { CNL, CNL, CNL }, /* 2, \n */
2537 { CWORD, CCTL, CCTL }, /* 3, !*-/:=?[]~ */
2538 { CDQUOTE, CENDQUOTE, CWORD }, /* 4, '"' */
2539 { CVAR, CVAR, CWORD }, /* 5, $ */
2540 { CSQUOTE, CWORD, CENDQUOTE }, /* 6, "'" */
2541 { CSPCL, CWORD, CWORD }, /* 7, ( */
2542 { CSPCL, CWORD, CWORD }, /* 8, ) */
2543 { CBACK, CBACK, CCTL }, /* 9, \ */
2544 { CBQUOTE, CBQUOTE, CWORD }, /* 10, ` */
2545 { CENDVAR, CENDVAR, CWORD }, /* 11, } */
2546 #ifndef USE_SIT_FUNCTION
2547 { CENDFILE, CENDFILE, CENDFILE }, /* 12, PEOF */
2548 { CWORD, CWORD, CWORD }, /* 13, 0-9A-Za-z */
2549 { CCTL, CCTL, CCTL } /* 14, CTLESC ... */
2552 #endif /* ASH_MATH_SUPPORT */
2554 #ifdef USE_SIT_FUNCTION
2557 SIT(int c, int syntax)
2559 static const char spec_symbls[] = "\t\n !\"$&'()*-/:;<=>?[\\]`|}~";
2560 #if ENABLE_ASH_ALIAS
2561 static const char syntax_index_table[] = {
2562 1, 2, 1, 3, 4, 5, 1, 6, /* "\t\n !\"$&'" */
2563 7, 8, 3, 3, 3, 3, 1, 1, /* "()*-/:;<" */
2564 3, 1, 3, 3, 9, 3, 10, 1, /* "=>?[\\]`|" */
2568 static const char syntax_index_table[] = {
2569 0, 1, 0, 2, 3, 4, 0, 5, /* "\t\n !\"$&'" */
2570 6, 7, 2, 2, 2, 2, 0, 0, /* "()*-/:;<" */
2571 2, 0, 2, 2, 8, 2, 9, 0, /* "=>?[\\]`|" */
2578 if (c == PEOF) /* 2^8+2 */
2580 #if ENABLE_ASH_ALIAS
2581 if (c == PEOA) /* 2^8+1 */
2585 #define U_C(c) ((unsigned char)(c))
2587 if ((unsigned char)c >= (unsigned char)(CTLESC)
2588 && (unsigned char)c <= (unsigned char)(CTLQUOTEMARK)
2592 s = strchr(spec_symbls, c);
2593 if (s == NULL || *s == '\0')
2595 indx = syntax_index_table[(s - spec_symbls)];
2597 return S_I_T[indx][syntax];
2600 #else /* !USE_SIT_FUNCTION */
2602 #if ENABLE_ASH_ALIAS
2603 #define CSPCL_CIGN_CIGN_CIGN 0
2604 #define CSPCL_CWORD_CWORD_CWORD 1
2605 #define CNL_CNL_CNL_CNL 2
2606 #define CWORD_CCTL_CCTL_CWORD 3
2607 #define CDQUOTE_CENDQUOTE_CWORD_CWORD 4
2608 #define CVAR_CVAR_CWORD_CVAR 5
2609 #define CSQUOTE_CWORD_CENDQUOTE_CWORD 6
2610 #define CSPCL_CWORD_CWORD_CLP 7
2611 #define CSPCL_CWORD_CWORD_CRP 8
2612 #define CBACK_CBACK_CCTL_CBACK 9
2613 #define CBQUOTE_CBQUOTE_CWORD_CBQUOTE 10
2614 #define CENDVAR_CENDVAR_CWORD_CENDVAR 11
2615 #define CENDFILE_CENDFILE_CENDFILE_CENDFILE 12
2616 #define CWORD_CWORD_CWORD_CWORD 13
2617 #define CCTL_CCTL_CCTL_CCTL 14
2619 #define CSPCL_CWORD_CWORD_CWORD 0
2620 #define CNL_CNL_CNL_CNL 1
2621 #define CWORD_CCTL_CCTL_CWORD 2
2622 #define CDQUOTE_CENDQUOTE_CWORD_CWORD 3
2623 #define CVAR_CVAR_CWORD_CVAR 4
2624 #define CSQUOTE_CWORD_CENDQUOTE_CWORD 5
2625 #define CSPCL_CWORD_CWORD_CLP 6
2626 #define CSPCL_CWORD_CWORD_CRP 7
2627 #define CBACK_CBACK_CCTL_CBACK 8
2628 #define CBQUOTE_CBQUOTE_CWORD_CBQUOTE 9
2629 #define CENDVAR_CENDVAR_CWORD_CENDVAR 10
2630 #define CENDFILE_CENDFILE_CENDFILE_CENDFILE 11
2631 #define CWORD_CWORD_CWORD_CWORD 12
2632 #define CCTL_CCTL_CCTL_CCTL 13
2635 static const char syntax_index_table[258] = {
2636 /* BASESYNTAX_DQSYNTAX_SQSYNTAX_ARISYNTAX */
2637 /* 0 PEOF */ CENDFILE_CENDFILE_CENDFILE_CENDFILE,
2638 #if ENABLE_ASH_ALIAS
2639 /* 1 PEOA */ CSPCL_CIGN_CIGN_CIGN,
2641 /* 2 -128 0x80 */ CWORD_CWORD_CWORD_CWORD,
2642 /* 3 -127 CTLESC */ CCTL_CCTL_CCTL_CCTL,
2643 /* 4 -126 CTLVAR */ CCTL_CCTL_CCTL_CCTL,
2644 /* 5 -125 CTLENDVAR */ CCTL_CCTL_CCTL_CCTL,
2645 /* 6 -124 CTLBACKQ */ CCTL_CCTL_CCTL_CCTL,
2646 /* 7 -123 CTLQUOTE */ CCTL_CCTL_CCTL_CCTL,
2647 /* 8 -122 CTLARI */ CCTL_CCTL_CCTL_CCTL,
2648 /* 9 -121 CTLENDARI */ CCTL_CCTL_CCTL_CCTL,
2649 /* 10 -120 CTLQUOTEMARK */ CCTL_CCTL_CCTL_CCTL,
2650 /* 11 -119 */ CWORD_CWORD_CWORD_CWORD,
2651 /* 12 -118 */ CWORD_CWORD_CWORD_CWORD,
2652 /* 13 -117 */ CWORD_CWORD_CWORD_CWORD,
2653 /* 14 -116 */ CWORD_CWORD_CWORD_CWORD,
2654 /* 15 -115 */ CWORD_CWORD_CWORD_CWORD,
2655 /* 16 -114 */ CWORD_CWORD_CWORD_CWORD,
2656 /* 17 -113 */ CWORD_CWORD_CWORD_CWORD,
2657 /* 18 -112 */ CWORD_CWORD_CWORD_CWORD,
2658 /* 19 -111 */ CWORD_CWORD_CWORD_CWORD,
2659 /* 20 -110 */ CWORD_CWORD_CWORD_CWORD,
2660 /* 21 -109 */ CWORD_CWORD_CWORD_CWORD,
2661 /* 22 -108 */ CWORD_CWORD_CWORD_CWORD,
2662 /* 23 -107 */ CWORD_CWORD_CWORD_CWORD,
2663 /* 24 -106 */ CWORD_CWORD_CWORD_CWORD,
2664 /* 25 -105 */ CWORD_CWORD_CWORD_CWORD,
2665 /* 26 -104 */ CWORD_CWORD_CWORD_CWORD,
2666 /* 27 -103 */ CWORD_CWORD_CWORD_CWORD,
2667 /* 28 -102 */ CWORD_CWORD_CWORD_CWORD,
2668 /* 29 -101 */ CWORD_CWORD_CWORD_CWORD,
2669 /* 30 -100 */ CWORD_CWORD_CWORD_CWORD,
2670 /* 31 -99 */ CWORD_CWORD_CWORD_CWORD,
2671 /* 32 -98 */ CWORD_CWORD_CWORD_CWORD,
2672 /* 33 -97 */ CWORD_CWORD_CWORD_CWORD,
2673 /* 34 -96 */ CWORD_CWORD_CWORD_CWORD,
2674 /* 35 -95 */ CWORD_CWORD_CWORD_CWORD,
2675 /* 36 -94 */ CWORD_CWORD_CWORD_CWORD,
2676 /* 37 -93 */ CWORD_CWORD_CWORD_CWORD,
2677 /* 38 -92 */ CWORD_CWORD_CWORD_CWORD,
2678 /* 39 -91 */ CWORD_CWORD_CWORD_CWORD,
2679 /* 40 -90 */ CWORD_CWORD_CWORD_CWORD,
2680 /* 41 -89 */ CWORD_CWORD_CWORD_CWORD,
2681 /* 42 -88 */ CWORD_CWORD_CWORD_CWORD,
2682 /* 43 -87 */ CWORD_CWORD_CWORD_CWORD,
2683 /* 44 -86 */ CWORD_CWORD_CWORD_CWORD,
2684 /* 45 -85 */ CWORD_CWORD_CWORD_CWORD,
2685 /* 46 -84 */ CWORD_CWORD_CWORD_CWORD,
2686 /* 47 -83 */ CWORD_CWORD_CWORD_CWORD,
2687 /* 48 -82 */ CWORD_CWORD_CWORD_CWORD,
2688 /* 49 -81 */ CWORD_CWORD_CWORD_CWORD,
2689 /* 50 -80 */ CWORD_CWORD_CWORD_CWORD,
2690 /* 51 -79 */ CWORD_CWORD_CWORD_CWORD,
2691 /* 52 -78 */ CWORD_CWORD_CWORD_CWORD,
2692 /* 53 -77 */ CWORD_CWORD_CWORD_CWORD,
2693 /* 54 -76 */ CWORD_CWORD_CWORD_CWORD,
2694 /* 55 -75 */ CWORD_CWORD_CWORD_CWORD,
2695 /* 56 -74 */ CWORD_CWORD_CWORD_CWORD,
2696 /* 57 -73 */ CWORD_CWORD_CWORD_CWORD,
2697 /* 58 -72 */ CWORD_CWORD_CWORD_CWORD,
2698 /* 59 -71 */ CWORD_CWORD_CWORD_CWORD,
2699 /* 60 -70 */ CWORD_CWORD_CWORD_CWORD,
2700 /* 61 -69 */ CWORD_CWORD_CWORD_CWORD,
2701 /* 62 -68 */ CWORD_CWORD_CWORD_CWORD,
2702 /* 63 -67 */ CWORD_CWORD_CWORD_CWORD,
2703 /* 64 -66 */ CWORD_CWORD_CWORD_CWORD,
2704 /* 65 -65 */ CWORD_CWORD_CWORD_CWORD,
2705 /* 66 -64 */ CWORD_CWORD_CWORD_CWORD,
2706 /* 67 -63 */ CWORD_CWORD_CWORD_CWORD,
2707 /* 68 -62 */ CWORD_CWORD_CWORD_CWORD,
2708 /* 69 -61 */ CWORD_CWORD_CWORD_CWORD,
2709 /* 70 -60 */ CWORD_CWORD_CWORD_CWORD,
2710 /* 71 -59 */ CWORD_CWORD_CWORD_CWORD,
2711 /* 72 -58 */ CWORD_CWORD_CWORD_CWORD,
2712 /* 73 -57 */ CWORD_CWORD_CWORD_CWORD,
2713 /* 74 -56 */ CWORD_CWORD_CWORD_CWORD,
2714 /* 75 -55 */ CWORD_CWORD_CWORD_CWORD,
2715 /* 76 -54 */ CWORD_CWORD_CWORD_CWORD,
2716 /* 77 -53 */ CWORD_CWORD_CWORD_CWORD,
2717 /* 78 -52 */ CWORD_CWORD_CWORD_CWORD,
2718 /* 79 -51 */ CWORD_CWORD_CWORD_CWORD,
2719 /* 80 -50 */ CWORD_CWORD_CWORD_CWORD,
2720 /* 81 -49 */ CWORD_CWORD_CWORD_CWORD,
2721 /* 82 -48 */ CWORD_CWORD_CWORD_CWORD,
2722 /* 83 -47 */ CWORD_CWORD_CWORD_CWORD,
2723 /* 84 -46 */ CWORD_CWORD_CWORD_CWORD,
2724 /* 85 -45 */ CWORD_CWORD_CWORD_CWORD,
2725 /* 86 -44 */ CWORD_CWORD_CWORD_CWORD,
2726 /* 87 -43 */ CWORD_CWORD_CWORD_CWORD,
2727 /* 88 -42 */ CWORD_CWORD_CWORD_CWORD,
2728 /* 89 -41 */ CWORD_CWORD_CWORD_CWORD,
2729 /* 90 -40 */ CWORD_CWORD_CWORD_CWORD,
2730 /* 91 -39 */ CWORD_CWORD_CWORD_CWORD,
2731 /* 92 -38 */ CWORD_CWORD_CWORD_CWORD,
2732 /* 93 -37 */ CWORD_CWORD_CWORD_CWORD,
2733 /* 94 -36 */ CWORD_CWORD_CWORD_CWORD,
2734 /* 95 -35 */ CWORD_CWORD_CWORD_CWORD,
2735 /* 96 -34 */ CWORD_CWORD_CWORD_CWORD,
2736 /* 97 -33 */ CWORD_CWORD_CWORD_CWORD,
2737 /* 98 -32 */ CWORD_CWORD_CWORD_CWORD,
2738 /* 99 -31 */ CWORD_CWORD_CWORD_CWORD,
2739 /* 100 -30 */ CWORD_CWORD_CWORD_CWORD,
2740 /* 101 -29 */ CWORD_CWORD_CWORD_CWORD,
2741 /* 102 -28 */ CWORD_CWORD_CWORD_CWORD,
2742 /* 103 -27 */ CWORD_CWORD_CWORD_CWORD,
2743 /* 104 -26 */ CWORD_CWORD_CWORD_CWORD,
2744 /* 105 -25 */ CWORD_CWORD_CWORD_CWORD,
2745 /* 106 -24 */ CWORD_CWORD_CWORD_CWORD,
2746 /* 107 -23 */ CWORD_CWORD_CWORD_CWORD,
2747 /* 108 -22 */ CWORD_CWORD_CWORD_CWORD,
2748 /* 109 -21 */ CWORD_CWORD_CWORD_CWORD,
2749 /* 110 -20 */ CWORD_CWORD_CWORD_CWORD,
2750 /* 111 -19 */ CWORD_CWORD_CWORD_CWORD,
2751 /* 112 -18 */ CWORD_CWORD_CWORD_CWORD,
2752 /* 113 -17 */ CWORD_CWORD_CWORD_CWORD,
2753 /* 114 -16 */ CWORD_CWORD_CWORD_CWORD,
2754 /* 115 -15 */ CWORD_CWORD_CWORD_CWORD,
2755 /* 116 -14 */ CWORD_CWORD_CWORD_CWORD,
2756 /* 117 -13 */ CWORD_CWORD_CWORD_CWORD,
2757 /* 118 -12 */ CWORD_CWORD_CWORD_CWORD,
2758 /* 119 -11 */ CWORD_CWORD_CWORD_CWORD,
2759 /* 120 -10 */ CWORD_CWORD_CWORD_CWORD,
2760 /* 121 -9 */ CWORD_CWORD_CWORD_CWORD,
2761 /* 122 -8 */ CWORD_CWORD_CWORD_CWORD,
2762 /* 123 -7 */ CWORD_CWORD_CWORD_CWORD,
2763 /* 124 -6 */ CWORD_CWORD_CWORD_CWORD,
2764 /* 125 -5 */ CWORD_CWORD_CWORD_CWORD,
2765 /* 126 -4 */ CWORD_CWORD_CWORD_CWORD,
2766 /* 127 -3 */ CWORD_CWORD_CWORD_CWORD,
2767 /* 128 -2 */ CWORD_CWORD_CWORD_CWORD,
2768 /* 129 -1 */ CWORD_CWORD_CWORD_CWORD,
2769 /* 130 0 */ CWORD_CWORD_CWORD_CWORD,
2770 /* 131 1 */ CWORD_CWORD_CWORD_CWORD,
2771 /* 132 2 */ CWORD_CWORD_CWORD_CWORD,
2772 /* 133 3 */ CWORD_CWORD_CWORD_CWORD,
2773 /* 134 4 */ CWORD_CWORD_CWORD_CWORD,
2774 /* 135 5 */ CWORD_CWORD_CWORD_CWORD,
2775 /* 136 6 */ CWORD_CWORD_CWORD_CWORD,
2776 /* 137 7 */ CWORD_CWORD_CWORD_CWORD,
2777 /* 138 8 */ CWORD_CWORD_CWORD_CWORD,
2778 /* 139 9 "\t" */ CSPCL_CWORD_CWORD_CWORD,
2779 /* 140 10 "\n" */ CNL_CNL_CNL_CNL,
2780 /* 141 11 */ CWORD_CWORD_CWORD_CWORD,
2781 /* 142 12 */ CWORD_CWORD_CWORD_CWORD,
2782 /* 143 13 */ CWORD_CWORD_CWORD_CWORD,
2783 /* 144 14 */ CWORD_CWORD_CWORD_CWORD,
2784 /* 145 15 */ CWORD_CWORD_CWORD_CWORD,
2785 /* 146 16 */ CWORD_CWORD_CWORD_CWORD,
2786 /* 147 17 */ CWORD_CWORD_CWORD_CWORD,
2787 /* 148 18 */ CWORD_CWORD_CWORD_CWORD,
2788 /* 149 19 */ CWORD_CWORD_CWORD_CWORD,
2789 /* 150 20 */ CWORD_CWORD_CWORD_CWORD,
2790 /* 151 21 */ CWORD_CWORD_CWORD_CWORD,
2791 /* 152 22 */ CWORD_CWORD_CWORD_CWORD,
2792 /* 153 23 */ CWORD_CWORD_CWORD_CWORD,
2793 /* 154 24 */ CWORD_CWORD_CWORD_CWORD,
2794 /* 155 25 */ CWORD_CWORD_CWORD_CWORD,
2795 /* 156 26 */ CWORD_CWORD_CWORD_CWORD,
2796 /* 157 27 */ CWORD_CWORD_CWORD_CWORD,
2797 /* 158 28 */ CWORD_CWORD_CWORD_CWORD,
2798 /* 159 29 */ CWORD_CWORD_CWORD_CWORD,
2799 /* 160 30 */ CWORD_CWORD_CWORD_CWORD,
2800 /* 161 31 */ CWORD_CWORD_CWORD_CWORD,
2801 /* 162 32 " " */ CSPCL_CWORD_CWORD_CWORD,
2802 /* 163 33 "!" */ CWORD_CCTL_CCTL_CWORD,
2803 /* 164 34 """ */ CDQUOTE_CENDQUOTE_CWORD_CWORD,
2804 /* 165 35 "#" */ CWORD_CWORD_CWORD_CWORD,
2805 /* 166 36 "$" */ CVAR_CVAR_CWORD_CVAR,
2806 /* 167 37 "%" */ CWORD_CWORD_CWORD_CWORD,
2807 /* 168 38 "&" */ CSPCL_CWORD_CWORD_CWORD,
2808 /* 169 39 "'" */ CSQUOTE_CWORD_CENDQUOTE_CWORD,
2809 /* 170 40 "(" */ CSPCL_CWORD_CWORD_CLP,
2810 /* 171 41 ")" */ CSPCL_CWORD_CWORD_CRP,
2811 /* 172 42 "*" */ CWORD_CCTL_CCTL_CWORD,
2812 /* 173 43 "+" */ CWORD_CWORD_CWORD_CWORD,
2813 /* 174 44 "," */ CWORD_CWORD_CWORD_CWORD,
2814 /* 175 45 "-" */ CWORD_CCTL_CCTL_CWORD,
2815 /* 176 46 "." */ CWORD_CWORD_CWORD_CWORD,
2816 /* 177 47 "/" */ CWORD_CCTL_CCTL_CWORD,
2817 /* 178 48 "0" */ CWORD_CWORD_CWORD_CWORD,
2818 /* 179 49 "1" */ CWORD_CWORD_CWORD_CWORD,
2819 /* 180 50 "2" */ CWORD_CWORD_CWORD_CWORD,
2820 /* 181 51 "3" */ CWORD_CWORD_CWORD_CWORD,
2821 /* 182 52 "4" */ CWORD_CWORD_CWORD_CWORD,
2822 /* 183 53 "5" */ CWORD_CWORD_CWORD_CWORD,
2823 /* 184 54 "6" */ CWORD_CWORD_CWORD_CWORD,
2824 /* 185 55 "7" */ CWORD_CWORD_CWORD_CWORD,
2825 /* 186 56 "8" */ CWORD_CWORD_CWORD_CWORD,
2826 /* 187 57 "9" */ CWORD_CWORD_CWORD_CWORD,
2827 /* 188 58 ":" */ CWORD_CCTL_CCTL_CWORD,
2828 /* 189 59 ";" */ CSPCL_CWORD_CWORD_CWORD,
2829 /* 190 60 "<" */ CSPCL_CWORD_CWORD_CWORD,
2830 /* 191 61 "=" */ CWORD_CCTL_CCTL_CWORD,
2831 /* 192 62 ">" */ CSPCL_CWORD_CWORD_CWORD,
2832 /* 193 63 "?" */ CWORD_CCTL_CCTL_CWORD,
2833 /* 194 64 "@" */ CWORD_CWORD_CWORD_CWORD,
2834 /* 195 65 "A" */ CWORD_CWORD_CWORD_CWORD,
2835 /* 196 66 "B" */ CWORD_CWORD_CWORD_CWORD,
2836 /* 197 67 "C" */ CWORD_CWORD_CWORD_CWORD,
2837 /* 198 68 "D" */ CWORD_CWORD_CWORD_CWORD,
2838 /* 199 69 "E" */ CWORD_CWORD_CWORD_CWORD,
2839 /* 200 70 "F" */ CWORD_CWORD_CWORD_CWORD,
2840 /* 201 71 "G" */ CWORD_CWORD_CWORD_CWORD,
2841 /* 202 72 "H" */ CWORD_CWORD_CWORD_CWORD,
2842 /* 203 73 "I" */ CWORD_CWORD_CWORD_CWORD,
2843 /* 204 74 "J" */ CWORD_CWORD_CWORD_CWORD,
2844 /* 205 75 "K" */ CWORD_CWORD_CWORD_CWORD,
2845 /* 206 76 "L" */ CWORD_CWORD_CWORD_CWORD,
2846 /* 207 77 "M" */ CWORD_CWORD_CWORD_CWORD,
2847 /* 208 78 "N" */ CWORD_CWORD_CWORD_CWORD,
2848 /* 209 79 "O" */ CWORD_CWORD_CWORD_CWORD,
2849 /* 210 80 "P" */ CWORD_CWORD_CWORD_CWORD,
2850 /* 211 81 "Q" */ CWORD_CWORD_CWORD_CWORD,
2851 /* 212 82 "R" */ CWORD_CWORD_CWORD_CWORD,
2852 /* 213 83 "S" */ CWORD_CWORD_CWORD_CWORD,
2853 /* 214 84 "T" */ CWORD_CWORD_CWORD_CWORD,
2854 /* 215 85 "U" */ CWORD_CWORD_CWORD_CWORD,
2855 /* 216 86 "V" */ CWORD_CWORD_CWORD_CWORD,
2856 /* 217 87 "W" */ CWORD_CWORD_CWORD_CWORD,
2857 /* 218 88 "X" */ CWORD_CWORD_CWORD_CWORD,
2858 /* 219 89 "Y" */ CWORD_CWORD_CWORD_CWORD,
2859 /* 220 90 "Z" */ CWORD_CWORD_CWORD_CWORD,
2860 /* 221 91 "[" */ CWORD_CCTL_CCTL_CWORD,
2861 /* 222 92 "\" */ CBACK_CBACK_CCTL_CBACK,
2862 /* 223 93 "]" */ CWORD_CCTL_CCTL_CWORD,
2863 /* 224 94 "^" */ CWORD_CWORD_CWORD_CWORD,
2864 /* 225 95 "_" */ CWORD_CWORD_CWORD_CWORD,
2865 /* 226 96 "`" */ CBQUOTE_CBQUOTE_CWORD_CBQUOTE,
2866 /* 227 97 "a" */ CWORD_CWORD_CWORD_CWORD,
2867 /* 228 98 "b" */ CWORD_CWORD_CWORD_CWORD,
2868 /* 229 99 "c" */ CWORD_CWORD_CWORD_CWORD,
2869 /* 230 100 "d" */ CWORD_CWORD_CWORD_CWORD,
2870 /* 231 101 "e" */ CWORD_CWORD_CWORD_CWORD,
2871 /* 232 102 "f" */ CWORD_CWORD_CWORD_CWORD,
2872 /* 233 103 "g" */ CWORD_CWORD_CWORD_CWORD,
2873 /* 234 104 "h" */ CWORD_CWORD_CWORD_CWORD,
2874 /* 235 105 "i" */ CWORD_CWORD_CWORD_CWORD,
2875 /* 236 106 "j" */ CWORD_CWORD_CWORD_CWORD,
2876 /* 237 107 "k" */ CWORD_CWORD_CWORD_CWORD,
2877 /* 238 108 "l" */ CWORD_CWORD_CWORD_CWORD,
2878 /* 239 109 "m" */ CWORD_CWORD_CWORD_CWORD,
2879 /* 240 110 "n" */ CWORD_CWORD_CWORD_CWORD,
2880 /* 241 111 "o" */ CWORD_CWORD_CWORD_CWORD,
2881 /* 242 112 "p" */ CWORD_CWORD_CWORD_CWORD,
2882 /* 243 113 "q" */ CWORD_CWORD_CWORD_CWORD,
2883 /* 244 114 "r" */ CWORD_CWORD_CWORD_CWORD,
2884 /* 245 115 "s" */ CWORD_CWORD_CWORD_CWORD,
2885 /* 246 116 "t" */ CWORD_CWORD_CWORD_CWORD,
2886 /* 247 117 "u" */ CWORD_CWORD_CWORD_CWORD,
2887 /* 248 118 "v" */ CWORD_CWORD_CWORD_CWORD,
2888 /* 249 119 "w" */ CWORD_CWORD_CWORD_CWORD,
2889 /* 250 120 "x" */ CWORD_CWORD_CWORD_CWORD,
2890 /* 251 121 "y" */ CWORD_CWORD_CWORD_CWORD,
2891 /* 252 122 "z" */ CWORD_CWORD_CWORD_CWORD,
2892 /* 253 123 "{" */ CWORD_CWORD_CWORD_CWORD,
2893 /* 254 124 "|" */ CSPCL_CWORD_CWORD_CWORD,
2894 /* 255 125 "}" */ CENDVAR_CENDVAR_CWORD_CENDVAR,
2895 /* 256 126 "~" */ CWORD_CCTL_CCTL_CWORD,
2896 /* 257 127 */ CWORD_CWORD_CWORD_CWORD,
2899 #define SIT(c, syntax) (S_I_T[(int)syntax_index_table[((int)c)+SYNBASE]][syntax])
2901 #endif /* USE_SIT_FUNCTION */
2904 /* ============ Alias handling */
2906 #if ENABLE_ASH_ALIAS
2908 #define ALIASINUSE 1
2920 static struct alias *atab[ATABSIZE];
2922 static struct alias **
2923 __lookupalias(const char *name) {
2924 unsigned int hashval;
2931 ch = (unsigned char)*p;
2935 ch = (unsigned char)*++p;
2937 app = &atab[hashval % ATABSIZE];
2939 for (; *app; app = &(*app)->next) {
2940 if (strcmp(name, (*app)->name) == 0) {
2948 static struct alias *
2949 lookupalias(const char *name, int check)
2951 struct alias *ap = *__lookupalias(name);
2953 if (check && ap && (ap->flag & ALIASINUSE))
2958 static struct alias *
2959 freealias(struct alias *ap)
2963 if (ap->flag & ALIASINUSE) {
2964 ap->flag |= ALIASDEAD;
2976 setalias(const char *name, const char *val)
2978 struct alias *ap, **app;
2980 app = __lookupalias(name);
2984 if (!(ap->flag & ALIASINUSE)) {
2987 ap->val = ckstrdup(val);
2988 ap->flag &= ~ALIASDEAD;
2991 ap = ckmalloc(sizeof(struct alias));
2992 ap->name = ckstrdup(name);
2993 ap->val = ckstrdup(val);
3002 unalias(const char *name)
3006 app = __lookupalias(name);
3010 *app = freealias(*app);
3021 struct alias *ap, **app;
3025 for (i = 0; i < ATABSIZE; i++) {
3027 for (ap = *app; ap; ap = *app) {
3028 *app = freealias(*app);
3038 printalias(const struct alias *ap)
3040 out1fmt("%s=%s\n", ap->name, single_quote(ap->val));
3044 * TODO - sort output
3047 aliascmd(int argc, char **argv)
3056 for (i = 0; i < ATABSIZE; i++)
3057 for (ap = atab[i]; ap; ap = ap->next) {
3062 while ((n = *++argv) != NULL) {
3063 v = strchr(n+1, '=');
3064 if (v == NULL) { /* n+1: funny ksh stuff */
3065 ap = *__lookupalias(n);
3067 fprintf(stderr, "%s: %s not found\n", "alias", n);
3081 unaliascmd(int argc, char **argv)
3085 while ((i = nextopt("a")) != '\0') {
3091 for (i = 0; *argptr; argptr++) {
3092 if (unalias(*argptr)) {
3093 fprintf(stderr, "%s: %s not found\n", "unalias", *argptr);
3101 #endif /* ASH_ALIAS */
3104 /* ============ jobs.c */
3106 /* Mode argument to forkshell. Don't change FORK_FG or FORK_BG. */
3109 #define FORK_NOJOB 2
3111 /* mode flags for showjob(s) */
3112 #define SHOW_PGID 0x01 /* only show pgid - for jobs -p */
3113 #define SHOW_PID 0x04 /* include process pid */
3114 #define SHOW_CHANGED 0x08 /* only jobs whose state has changed */
3117 * A job structure contains information about a job. A job is either a
3118 * single process or a set of processes contained in a pipeline. In the
3119 * latter case, pidlist will be non-NULL, and will point to a -1 terminated
3124 pid_t pid; /* process id */
3125 int status; /* last process status from wait() */
3126 char *cmd; /* text of command being run */
3130 struct procstat ps0; /* status of process */
3131 struct procstat *ps; /* status or processes when more than one */
3133 int stopstatus; /* status of a stopped job */
3136 nprocs: 16, /* number of processes */
3138 #define JOBRUNNING 0 /* at least one proc running */
3139 #define JOBSTOPPED 1 /* all procs are stopped */
3140 #define JOBDONE 2 /* all procs are completed */
3142 sigint: 1, /* job was killed by SIGINT */
3143 jobctl: 1, /* job running under job control */
3145 waited: 1, /* true if this entry has been waited for */
3146 used: 1, /* true if this entry is in used */
3147 changed: 1; /* true if status has changed */
3148 struct job *prev_job; /* previous job */
3151 static pid_t backgndpid; /* pid of last background process */
3152 static int job_warning; /* user was warned about stopped jobs */
3154 static int jobctl; /* true if doing job control */
3157 static struct job *makejob(union node *, int);
3158 static int forkshell(struct job *, union node *, int);
3159 static int waitforjob(struct job *);
3162 #define setjobctl(on) /* do nothing */
3164 static void setjobctl(int);
3165 static void showjobs(FILE *, int);
3169 * Set the signal handler for the specified signal. The routine figures
3170 * out what it should be set to.
3173 setsignal(int signo)
3177 struct sigaction act;
3182 else if (*t != '\0')
3186 if (rootshell && action == S_DFL) {
3189 if (iflag || minusc || sflag == 0)
3212 t = &sigmode[signo - 1];
3216 * current setting unknown
3218 if (sigaction(signo, 0, &act) == -1) {
3220 * Pretend it worked; maybe we should give a warning
3221 * here, but other shells don't. We don't alter
3222 * sigmode, so that we retry every time.
3226 if (act.sa_handler == SIG_IGN) {
3228 && (signo == SIGTSTP || signo == SIGTTIN || signo == SIGTTOU)
3230 tsig = S_IGN; /* don't hard ignore these */
3234 tsig = S_RESET; /* force to be set */
3237 if (tsig == S_HARD_IGN || tsig == action)
3241 act.sa_handler = onsig;
3244 act.sa_handler = SIG_IGN;
3247 act.sa_handler = SIG_DFL;
3251 sigfillset(&act.sa_mask);
3252 sigaction(signo, &act, 0);
3255 /* mode flags for set_curjob */
3256 #define CUR_DELETE 2
3257 #define CUR_RUNNING 1
3258 #define CUR_STOPPED 0
3260 /* mode flags for dowait */
3261 #define DOWAIT_NORMAL 0
3262 #define DOWAIT_BLOCK 1
3265 /* pgrp of shell on invocation */
3266 static int initialpgrp;
3267 static int ttyfd = -1;
3270 static struct job *jobtab;
3272 static unsigned njobs;
3274 static struct job *curjob;
3275 /* number of presumed living untracked jobs */
3279 set_curjob(struct job *jp, unsigned mode)
3282 struct job **jpp, **curp;
3284 /* first remove from list */
3285 jpp = curp = &curjob;
3290 jpp = &jp1->prev_job;
3292 *jpp = jp1->prev_job;
3294 /* Then re-insert in correct position */
3302 /* job being deleted */
3305 /* newly created job or backgrounded job,
3306 put after all stopped jobs. */
3310 if (!jp1 || jp1->state != JOBSTOPPED)
3313 jpp = &jp1->prev_job;
3319 /* newly stopped job - becomes curjob */
3320 jp->prev_job = *jpp;
3328 jobno(const struct job *jp)
3330 return jp - jobtab + 1;
3335 * Convert a job name to a job structure.
3338 getjob(const char *name, int getctl)
3342 const char *err_msg = "No such job: %s";
3346 char *(*match)(const char *, const char *);
3361 if (c == '+' || c == '%') {
3363 err_msg = "No current job";
3369 err_msg = "No previous job";
3380 jp = jobtab + num - 1;
3397 if (match(jp->ps[0].cmd, p)) {
3401 err_msg = "%s: ambiguous";
3408 err_msg = "job %s not created under job control";
3409 if (getctl && jp->jobctl == 0)
3414 ash_msg_and_raise_error(err_msg, name);
3418 * Mark a job structure as unused.
3421 freejob(struct job *jp)
3423 struct procstat *ps;
3427 for (i = jp->nprocs, ps = jp->ps; --i >= 0; ps++) {
3428 if (ps->cmd != nullstr)
3431 if (jp->ps != &jp->ps0)
3434 set_curjob(jp, CUR_DELETE);
3440 xtcsetpgrp(int fd, pid_t pgrp)
3442 if (tcsetpgrp(fd, pgrp))
3443 ash_msg_and_raise_error("cannot set tty process group (%m)");
3447 * Turn job control on and off.
3449 * Note: This code assumes that the third arg to ioctl is a character
3450 * pointer, which is true on Berkeley systems but not System V. Since
3451 * System V doesn't have job control yet, this isn't a problem now.
3453 * Called with interrupts off.
3461 if (on == jobctl || rootshell == 0)
3465 ofd = fd = open(_PATH_TTY, O_RDWR);
3467 /* BTW, bash will try to open(ttyname(0)) if open("/dev/tty") fails.
3468 * That sometimes helps to acquire controlling tty.
3469 * Obviously, a workaround for bugs when someone
3470 * failed to provide a controlling tty to bash! :) */
3472 while (!isatty(fd) && --fd >= 0)
3475 fd = fcntl(fd, F_DUPFD, 10);
3479 fcntl(fd, F_SETFD, FD_CLOEXEC);
3480 do { /* while we are in the background */
3481 pgrp = tcgetpgrp(fd);
3484 ash_msg("can't access tty; job control turned off");
3488 if (pgrp == getpgrp())
3499 xtcsetpgrp(fd, pgrp);
3501 /* turning job control off */
3504 /* was xtcsetpgrp, but this can make exiting ash
3505 * with pty already deleted loop forever */
3506 tcsetpgrp(fd, pgrp);
3520 killcmd(int argc, char **argv)
3522 if (argv[1] && strcmp(argv[1], "-l") != 0) {
3525 if (argv[i][0] == '%') {
3526 struct job *jp = getjob(argv[i], 0);
3527 unsigned pid = jp->ps[0].pid;
3528 /* Enough space for ' -NNN<nul>' */
3529 argv[i] = alloca(sizeof(int)*3 + 3);
3530 /* kill_main has matching code to expect
3531 * leading space. Needed to not confuse
3532 * negative pids with "kill -SIGNAL_NO" syntax */
3533 sprintf(argv[i], " -%u", pid);
3535 } while (argv[++i]);
3537 return kill_main(argc, argv);
3541 showpipe(struct job *jp, FILE *out)
3543 struct procstat *sp;
3544 struct procstat *spend;
3546 spend = jp->ps + jp->nprocs;
3547 for (sp = jp->ps + 1; sp < spend; sp++)
3548 fprintf(out, " | %s", sp->cmd);
3549 outcslow('\n', out);
3550 flush_stdout_stderr();
3555 restartjob(struct job *jp, int mode)
3557 struct procstat *ps;
3563 if (jp->state == JOBDONE)
3565 jp->state = JOBRUNNING;
3567 if (mode == FORK_FG)
3568 xtcsetpgrp(ttyfd, pgid);
3569 killpg(pgid, SIGCONT);
3573 if (WIFSTOPPED(ps->status)) {
3579 status = (mode == FORK_FG) ? waitforjob(jp) : 0;
3585 fg_bgcmd(int argc, char **argv)
3592 mode = (**argv == 'f') ? FORK_FG : FORK_BG;
3597 jp = getjob(*argv, 1);
3598 if (mode == FORK_BG) {
3599 set_curjob(jp, CUR_RUNNING);
3600 fprintf(out, "[%d] ", jobno(jp));
3602 outstr(jp->ps->cmd, out);
3604 retval = restartjob(jp, mode);
3605 } while (*argv && *++argv);
3611 sprint_status(char *s, int status, int sigonly)
3617 if (!WIFEXITED(status)) {
3619 if (WIFSTOPPED(status))
3620 st = WSTOPSIG(status);
3623 st = WTERMSIG(status);
3625 if (st == SIGINT || st == SIGPIPE)
3628 if (WIFSTOPPED(status))
3633 col = fmtstr(s, 32, strsignal(st));
3634 if (WCOREDUMP(status)) {
3635 col += fmtstr(s + col, 16, " (core dumped)");
3637 } else if (!sigonly) {
3638 st = WEXITSTATUS(status);
3640 col = fmtstr(s, 16, "Done(%d)", st);
3642 col = fmtstr(s, 16, "Done");
3649 * Do a wait system call. If job control is compiled in, we accept
3650 * stopped processes. If block is zero, we return a value of zero
3651 * rather than blocking.
3653 * System V doesn't have a non-blocking wait system call. It does
3654 * have a SIGCLD signal that is sent to a process when one of it's
3655 * children dies. The obvious way to use SIGCLD would be to install
3656 * a handler for SIGCLD which simply bumped a counter when a SIGCLD
3657 * was received, and have waitproc bump another counter when it got
3658 * the status of a process. Waitproc would then know that a wait
3659 * system call would not block if the two counters were different.
3660 * This approach doesn't work because if a process has children that
3661 * have not been waited for, System V will send it a SIGCLD when it
3662 * installs a signal handler for SIGCLD. What this means is that when
3663 * a child exits, the shell will be sent SIGCLD signals continuously
3664 * until is runs out of stack space, unless it does a wait call before
3665 * restoring the signal handler. The code below takes advantage of
3666 * this (mis)feature by installing a signal handler for SIGCLD and
3667 * then checking to see whether it was called. If there are any
3668 * children to be waited for, it will be.
3670 * If neither SYSV nor BSD is defined, we don't implement nonblocking
3671 * waits at all. In this case, the user will not be informed when
3672 * a background process until the next time she runs a real program
3673 * (as opposed to running a builtin command or just typing return),
3674 * and the jobs command may give out of date information.
3677 waitproc(int block, int *status)
3687 return wait3(status, flags, (struct rusage *)NULL);
3691 * Wait for a process to terminate.
3694 dowait(int block, struct job *job)
3699 struct job *thisjob;
3702 TRACE(("dowait(%d) called\n", block));
3703 pid = waitproc(block, &status);
3704 TRACE(("wait returns pid %d, status=%d\n", pid, status));
3709 for (jp = curjob; jp; jp = jp->prev_job) {
3710 struct procstat *sp;
3711 struct procstat *spend;
3712 if (jp->state == JOBDONE)
3715 spend = jp->ps + jp->nprocs;
3718 if (sp->pid == pid) {
3719 TRACE(("Job %d: changing status of proc %d "
3720 "from 0x%x to 0x%x\n",
3721 jobno(jp), pid, sp->status, status));
3722 sp->status = status;
3725 if (sp->status == -1)
3728 if (state == JOBRUNNING)
3730 if (WIFSTOPPED(sp->status)) {
3731 jp->stopstatus = sp->status;
3735 } while (++sp < spend);
3740 if (!WIFSTOPPED(status))
3747 if (state != JOBRUNNING) {
3748 thisjob->changed = 1;
3750 if (thisjob->state != state) {
3751 TRACE(("Job %d: changing state from %d to %d\n",
3752 jobno(thisjob), thisjob->state, state));
3753 thisjob->state = state;
3755 if (state == JOBSTOPPED) {
3756 set_curjob(thisjob, CUR_STOPPED);
3765 if (thisjob && thisjob == job) {
3769 len = sprint_status(s, status, 1);
3781 showjob(FILE *out, struct job *jp, int mode)
3783 struct procstat *ps;
3784 struct procstat *psend;
3791 if (mode & SHOW_PGID) {
3792 /* just output process (group) id of pipeline */
3793 fprintf(out, "%d\n", ps->pid);
3797 col = fmtstr(s, 16, "[%d] ", jobno(jp));
3802 else if (curjob && jp == curjob->prev_job)
3805 if (mode & SHOW_PID)
3806 col += fmtstr(s + col, 16, "%d ", ps->pid);
3808 psend = ps + jp->nprocs;
3810 if (jp->state == JOBRUNNING) {
3811 strcpy(s + col, "Running");
3812 col += sizeof("Running") - 1;
3814 int status = psend[-1].status;
3815 if (jp->state == JOBSTOPPED)
3816 status = jp->stopstatus;
3817 col += sprint_status(s + col, status, 0);
3823 /* for each process */
3824 col = fmtstr(s, 48, " |\n%*c%d ", indent, ' ', ps->pid) - 3;
3826 fprintf(out, "%s%*c%s",
3827 s, 33 - col >= 0 ? 33 - col : 0, ' ', ps->cmd
3829 if (!(mode & SHOW_PID)) {
3833 if (++ps == psend) {
3834 outcslow('\n', out);
3841 if (jp->state == JOBDONE) {
3842 TRACE(("showjob: freeing job %d\n", jobno(jp)));
3848 jobscmd(int argc, char **argv)
3854 while ((m = nextopt("lp"))) {
3865 showjob(out, getjob(*argv,0), mode);
3868 showjobs(out, mode);
3874 * Print a list of jobs. If "change" is nonzero, only print jobs whose
3875 * statuses have changed since the last call to showjobs.
3878 showjobs(FILE *out, int mode)
3882 TRACE(("showjobs(%x) called\n", mode));
3884 /* If not even one one job changed, there is nothing to do */
3885 while (dowait(DOWAIT_NORMAL, NULL) > 0)
3888 for (jp = curjob; jp; jp = jp->prev_job) {
3889 if (!(mode & SHOW_CHANGED) || jp->changed)
3890 showjob(out, jp, mode);
3896 getstatus(struct job *job)
3901 status = job->ps[job->nprocs - 1].status;
3902 retval = WEXITSTATUS(status);
3903 if (!WIFEXITED(status)) {
3905 retval = WSTOPSIG(status);
3906 if (!WIFSTOPPED(status))
3909 /* XXX: limits number of signals */
3910 retval = WTERMSIG(status);
3912 if (retval == SIGINT)
3918 TRACE(("getstatus: job %d, nproc %d, status %x, retval %x\n",
3919 jobno(job), job->nprocs, status, retval));
3924 waitcmd(int argc, char **argv)
3937 /* wait for all jobs */
3942 /* no running procs */
3945 if (jp->state == JOBRUNNING)
3950 dowait(DOWAIT_BLOCK, 0);
3956 if (**argv != '%') {
3957 pid_t pid = number(*argv);
3961 if (job->ps[job->nprocs - 1].pid == pid)
3963 job = job->prev_job;
3969 job = getjob(*argv, 0);
3970 /* loop until process terminated or stopped */
3971 while (job->state == JOBRUNNING)
3972 dowait(DOWAIT_BLOCK, 0);
3974 retval = getstatus(job);
3988 struct job *jp, *jq;
3990 len = njobs * sizeof(*jp);
3992 jp = ckrealloc(jq, len + 4 * sizeof(*jp));
3994 offset = (char *)jp - (char *)jq;
3996 /* Relocate pointers */
3999 jq = (struct job *)((char *)jq + l);
4003 #define joff(p) ((struct job *)((char *)(p) + l))
4004 #define jmove(p) (p) = (void *)((char *)(p) + offset)
4005 if (joff(jp)->ps == &jq->ps0)
4006 jmove(joff(jp)->ps);
4007 if (joff(jp)->prev_job)
4008 jmove(joff(jp)->prev_job);
4018 jp = (struct job *)((char *)jp + len);
4022 } while (--jq >= jp);
4027 * Return a new job structure.
4028 * Called with interrupts off.
4031 makejob(union node *node, int nprocs)
4036 for (i = njobs, jp = jobtab; ; jp++) {
4043 if (jp->state != JOBDONE || !jp->waited)
4052 memset(jp, 0, sizeof(*jp));
4057 jp->prev_job = curjob;
4062 jp->ps = ckmalloc(nprocs * sizeof(struct procstat));
4064 TRACE(("makejob(0x%lx, %d) returns %%%d\n", (long)node, nprocs,
4071 * Return a string identifying a command (to be printed by the
4074 static char *cmdnextc;
4077 cmdputs(const char *s)
4079 const char *p, *str;
4080 char c, cc[2] = " ";
4084 static const char vstype[VSTYPE + 1][4] = {
4085 "", "}", "-", "+", "?", "=",
4086 "%", "%%", "#", "##"
4089 nextc = makestrspace((strlen(s) + 1) * 8, cmdnextc);
4091 while ((c = *p++) != 0) {
4099 if ((subtype & VSTYPE) == VSLENGTH)
4103 if (!(subtype & VSQUOTE) == !(quoted & 1))
4109 str = "\"}" + !(quoted & 1);
4116 case CTLBACKQ+CTLQUOTE:
4119 #if ENABLE_ASH_MATH_SUPPORT
4134 if ((subtype & VSTYPE) != VSNORMAL)
4136 str = vstype[subtype & VSTYPE];
4137 if (subtype & VSNUL)
4146 /* These can only happen inside quotes */
4159 while ((c = *str++)) {
4164 USTPUTC('"', nextc);
4170 /* cmdtxt() and cmdlist() call each other */
4171 static void cmdtxt(union node *n);
4174 cmdlist(union node *np, int sep)
4176 for (; np; np = np->narg.next) {
4180 if (sep && np->narg.next)
4186 cmdtxt(union node *n)
4189 struct nodelist *lp;
4201 lp = n->npipe.cmdlist;
4219 cmdtxt(n->nbinary.ch1);
4235 cmdtxt(n->nif.test);
4238 if (n->nif.elsepart) {
4241 n = n->nif.elsepart;
4257 cmdtxt(n->nbinary.ch1);
4267 cmdputs(n->nfor.var);
4269 cmdlist(n->nfor.args, 1);
4274 cmdputs(n->narg.text);
4278 cmdlist(n->ncmd.args, 1);
4279 cmdlist(n->ncmd.redirect, 0);
4292 cmdputs(n->ncase.expr->narg.text);
4294 for (np = n->ncase.cases; np; np = np->nclist.next) {
4295 cmdtxt(np->nclist.pattern);
4297 cmdtxt(np->nclist.body);
4323 s[0] = n->nfile.fd + '0';
4327 if (n->type == NTOFD || n->type == NFROMFD) {
4328 s[0] = n->ndup.dupfd + '0';
4338 commandtext(union node *n)
4342 STARTSTACKSTR(cmdnextc);
4344 name = stackblock();
4345 TRACE(("commandtext: name %p, end %p\n\t\"%s\"\n",
4346 name, cmdnextc, cmdnextc));
4347 return ckstrdup(name);
4352 * Fork off a subshell. If we are doing job control, give the subshell its
4353 * own process group. Jp is a job structure that the job is to be added to.
4354 * N is the command that will be evaluated by the child. Both jp and n may
4355 * be NULL. The mode parameter can be one of the following:
4356 * FORK_FG - Fork off a foreground process.
4357 * FORK_BG - Fork off a background process.
4358 * FORK_NOJOB - Like FORK_FG, but don't give the process its own
4359 * process group even if job control is on.
4361 * When job control is turned off, background processes have their standard
4362 * input redirected to /dev/null (except for the second and later processes
4365 * Called with interrupts off.
4368 * Clear traps on a fork.
4375 for (tp = trap; tp < &trap[NSIG]; tp++) {
4376 if (*tp && **tp) { /* trap not NULL or SIG_IGN */
4381 setsignal(tp - trap);
4386 /* lives far away from here, needed for forkchild */
4387 static void closescript(void);
4389 forkchild(struct job *jp, union node *n, int mode)
4393 TRACE(("Child shell %d\n", getpid()));
4400 /* do job control only in root shell */
4402 if (mode != FORK_NOJOB && jp->jobctl && !oldlvl) {
4405 if (jp->nprocs == 0)
4408 pgrp = jp->ps[0].pid;
4409 /* This can fail because we are doing it in the parent also */
4410 (void)setpgid(0, pgrp);
4411 if (mode == FORK_FG)
4412 xtcsetpgrp(ttyfd, pgrp);
4417 if (mode == FORK_BG) {
4420 if (jp->nprocs == 0) {
4422 if (open(bb_dev_null, O_RDONLY) != 0)
4423 ash_msg_and_raise_error("can't open %s", bb_dev_null);
4426 if (!oldlvl && iflag) {
4431 for (jp = curjob; jp; jp = jp->prev_job)
4437 forkparent(struct job *jp, union node *n, int mode, pid_t pid)
4439 TRACE(("In parent shell: child = %d\n", pid));
4441 while (jobless && dowait(DOWAIT_NORMAL, 0) > 0);
4446 if (mode != FORK_NOJOB && jp->jobctl) {
4449 if (jp->nprocs == 0)
4452 pgrp = jp->ps[0].pid;
4453 /* This can fail because we are doing it in the child also */
4457 if (mode == FORK_BG) {
4458 backgndpid = pid; /* set $! */
4459 set_curjob(jp, CUR_RUNNING);
4462 struct procstat *ps = &jp->ps[jp->nprocs++];
4468 ps->cmd = commandtext(n);
4474 forkshell(struct job *jp, union node *n, int mode)
4478 TRACE(("forkshell(%%%d, %p, %d) called\n", jobno(jp), n, mode));
4481 TRACE(("Fork failed, errno=%d", errno));
4484 ash_msg_and_raise_error("cannot fork");
4487 forkchild(jp, n, mode);
4489 forkparent(jp, n, mode, pid);
4494 * Wait for job to finish.
4496 * Under job control we have the problem that while a child process is
4497 * running interrupts generated by the user are sent to the child but not
4498 * to the shell. This means that an infinite loop started by an inter-
4499 * active user may be hard to kill. With job control turned off, an
4500 * interactive user may place an interactive program inside a loop. If
4501 * the interactive program catches interrupts, the user doesn't want
4502 * these interrupts to also abort the loop. The approach we take here
4503 * is to have the shell ignore interrupt signals while waiting for a
4504 * foreground process to terminate, and then send itself an interrupt
4505 * signal if the child process was terminated by an interrupt signal.
4506 * Unfortunately, some programs want to do a bit of cleanup and then
4507 * exit on interrupt; unless these processes terminate themselves by
4508 * sending a signal to themselves (instead of calling exit) they will
4509 * confuse this approach.
4511 * Called with interrupts off.
4514 waitforjob(struct job *jp)
4518 TRACE(("waitforjob(%%%d) called\n", jobno(jp)));
4519 while (jp->state == JOBRUNNING) {
4520 dowait(DOWAIT_BLOCK, jp);
4525 xtcsetpgrp(ttyfd, rootpid);
4527 * This is truly gross.
4528 * If we're doing job control, then we did a TIOCSPGRP which
4529 * caused us (the shell) to no longer be in the controlling
4530 * session -- so we wouldn't have seen any ^C/SIGINT. So, we
4531 * intuit from the subprocess exit status whether a SIGINT
4532 * occurred, and if so interrupt ourselves. Yuck. - mycroft
4537 if (jp->state == JOBDONE)
4544 * return 1 if there are stopped jobs, otherwise 0
4556 if (jp && jp->state == JOBSTOPPED) {
4557 out2str("You have stopped jobs.\n");
4566 /* ============ redir.c
4568 * Code for dealing with input/output redirection.
4571 #define EMPTY -2 /* marks an unused slot in redirtab */
4573 # define PIPESIZE 4096 /* amount of buffering in a pipe */
4575 # define PIPESIZE PIPE_BUF
4579 * Open a file in noclobber mode.
4580 * The code was copied from bash.
4583 noclobberopen(const char *fname)
4586 struct stat finfo, finfo2;
4589 * If the file exists and is a regular file, return an error
4592 r = stat(fname, &finfo);
4593 if (r == 0 && S_ISREG(finfo.st_mode)) {
4599 * If the file was not present (r != 0), make sure we open it
4600 * exclusively so that if it is created before we open it, our open
4601 * will fail. Make sure that we do not truncate an existing file.
4602 * Note that we don't turn on O_EXCL unless the stat failed -- if the
4603 * file was not a regular file, we leave O_EXCL off.
4606 return open(fname, O_WRONLY|O_CREAT|O_EXCL, 0666);
4607 fd = open(fname, O_WRONLY|O_CREAT, 0666);
4609 /* If the open failed, return the file descriptor right away. */
4614 * OK, the open succeeded, but the file may have been changed from a
4615 * non-regular file to a regular file between the stat and the open.
4616 * We are assuming that the O_EXCL open handles the case where FILENAME
4617 * did not exist and is symlinked to an existing file between the stat
4622 * If we can open it and fstat the file descriptor, and neither check
4623 * revealed that it was a regular file, and the file has not been
4624 * replaced, return the file descriptor.
4626 if (fstat(fd, &finfo2) == 0 && !S_ISREG(finfo2.st_mode)
4627 && finfo.st_dev == finfo2.st_dev && finfo.st_ino == finfo2.st_ino)
4630 /* The file has been replaced. badness. */
4637 * Handle here documents. Normally we fork off a process to write the
4638 * data to a pipe. If the document is short, we can stuff the data in
4639 * the pipe without forking.
4641 /* openhere needs this forward reference */
4642 static void expandhere(union node *arg, int fd);
4644 openhere(union node *redir)
4650 ash_msg_and_raise_error("pipe call failed");
4651 if (redir->type == NHERE) {
4652 len = strlen(redir->nhere.doc->narg.text);
4653 if (len <= PIPESIZE) {
4654 full_write(pip[1], redir->nhere.doc->narg.text, len);
4658 if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) {
4660 signal(SIGINT, SIG_IGN);
4661 signal(SIGQUIT, SIG_IGN);
4662 signal(SIGHUP, SIG_IGN);
4664 signal(SIGTSTP, SIG_IGN);
4666 signal(SIGPIPE, SIG_DFL);
4667 if (redir->type == NHERE)
4668 full_write(pip[1], redir->nhere.doc->narg.text, len);
4670 expandhere(redir->nhere.doc, pip[1]);
4679 openredirect(union node *redir)
4684 switch (redir->nfile.type) {
4686 fname = redir->nfile.expfname;
4687 f = open(fname, O_RDONLY);
4692 fname = redir->nfile.expfname;
4693 f = open(fname, O_RDWR|O_CREAT|O_TRUNC, 0666);
4698 /* Take care of noclobber mode. */
4700 fname = redir->nfile.expfname;
4701 f = noclobberopen(fname);
4708 fname = redir->nfile.expfname;
4709 f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666);
4714 fname = redir->nfile.expfname;
4715 f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666);
4723 /* Fall through to eliminate warning. */
4730 f = openhere(redir);
4736 ash_msg_and_raise_error("cannot create %s: %s", fname, errmsg(errno, "nonexistent directory"));
4738 ash_msg_and_raise_error("cannot open %s: %s", fname, errmsg(errno, "no such file"));
4742 * Copy a file descriptor to be >= to. Returns -1
4743 * if the source file descriptor is closed, EMPTY if there are no unused
4744 * file descriptors left.
4747 copyfd(int from, int to)
4751 newfd = fcntl(from, F_DUPFD, to);
4753 if (errno == EMFILE)
4755 ash_msg_and_raise_error("%d: %m", from);
4761 dupredirect(union node *redir, int f)
4763 int fd = redir->nfile.fd;
4765 if (redir->nfile.type == NTOFD || redir->nfile.type == NFROMFD) {
4766 if (redir->ndup.dupfd >= 0) { /* if not ">&-" */
4767 copyfd(redir->ndup.dupfd, fd);
4779 * Process a list of redirection commands. If the REDIR_PUSH flag is set,
4780 * old file descriptors are stashed away so that the redirection can be
4781 * undone by calling popredir. If the REDIR_BACKQ flag is set, then the
4782 * standard output, and the standard error if it becomes a duplicate of
4783 * stdout, is saved in memory.
4785 /* flags passed to redirect */
4786 #define REDIR_PUSH 01 /* save previous values of file descriptors */
4787 #define REDIR_SAVEFD2 03 /* set preverrout */
4789 redirect(union node *redir, int flags)
4792 struct redirtab *sv;
4803 if (flags & REDIR_PUSH) {
4805 q = ckmalloc(sizeof(struct redirtab));
4806 q->next = redirlist;
4808 q->nullredirs = nullredirs - 1;
4809 for (i = 0; i < 10; i++)
4810 q->renamed[i] = EMPTY;
4817 if ((n->nfile.type == NTOFD || n->nfile.type == NFROMFD)
4818 && n->ndup.dupfd == fd)
4819 continue; /* redirect from/to same file descriptor */
4821 newfd = openredirect(n);
4824 if (sv && *(p = &sv->renamed[fd]) == EMPTY) {
4825 i = fcntl(fd, F_DUPFD, 10);
4832 ash_msg_and_raise_error("%d: %m", fd);
4842 dupredirect(n, newfd);
4843 } while ((n = n->nfile.next));
4845 if (flags & REDIR_SAVEFD2 && sv && sv->renamed[2] >= 0)
4846 preverrout_fd = sv->renamed[2];
4850 * Undo the effects of the last redirection.
4855 struct redirtab *rp;
4858 if (--nullredirs >= 0)
4862 for (i = 0; i < 10; i++) {
4863 if (rp->renamed[i] != EMPTY) {
4866 copyfd(rp->renamed[i], i);
4868 close(rp->renamed[i]);
4871 redirlist = rp->next;
4872 nullredirs = rp->nullredirs;
4878 * Undo all redirections. Called on error or interrupt.
4882 * Discard all saved file descriptors.
4885 clearredir(int drop)
4896 redirectsafe(union node *redir, int flags)
4899 volatile int saveint;
4900 struct jmploc *volatile savehandler = exception_handler;
4901 struct jmploc jmploc;
4904 err = setjmp(jmploc.loc) * 2;
4906 exception_handler = &jmploc;
4907 redirect(redir, flags);
4909 exception_handler = savehandler;
4910 if (err && exception != EXERROR)
4911 longjmp(exception_handler->loc, 1);
4912 RESTORE_INT(saveint);
4917 /* ============ Routines to expand arguments to commands
4919 * We have to deal with backquotes, shell variables, and file metacharacters.
4925 #define EXP_FULL 0x1 /* perform word splitting & file globbing */
4926 #define EXP_TILDE 0x2 /* do normal tilde expansion */
4927 #define EXP_VARTILDE 0x4 /* expand tildes in an assignment */
4928 #define EXP_REDIR 0x8 /* file glob for a redirection (1 match only) */
4929 #define EXP_CASE 0x10 /* keeps quotes around for CASE pattern */
4930 #define EXP_RECORD 0x20 /* need to record arguments for ifs breakup */
4931 #define EXP_VARTILDE2 0x40 /* expand tildes after colons only */
4932 #define EXP_WORD 0x80 /* expand word in parameter expansion */
4933 #define EXP_QWORD 0x100 /* expand word in quoted parameter expansion */
4937 #define RMESCAPE_ALLOC 0x1 /* Allocate a new string */
4938 #define RMESCAPE_GLOB 0x2 /* Add backslashes for glob */
4939 #define RMESCAPE_QUOTED 0x4 /* Remove CTLESC unless in quotes */
4940 #define RMESCAPE_GROW 0x8 /* Grow strings instead of stalloc */
4941 #define RMESCAPE_HEAP 0x10 /* Malloc strings instead of stalloc */
4944 * Structure specifying which parts of the string should be searched
4945 * for IFS characters.
4948 struct ifsregion *next; /* next region in list */
4949 int begoff; /* offset of start of region */
4950 int endoff; /* offset of end of region */
4951 int nulonly; /* search for nul bytes only */
4955 struct strlist *list;
4956 struct strlist **lastp;
4959 /* output of current string */
4960 static char *expdest;
4961 /* list of back quote expressions */
4962 static struct nodelist *argbackq;
4963 /* first struct in list of ifs regions */
4964 static struct ifsregion ifsfirst;
4965 /* last struct in list */
4966 static struct ifsregion *ifslastp;
4967 /* holds expanded arg list */
4968 static struct arglist exparg;
4978 expdest = makestrspace(32, expdest);
4979 #if ENABLE_ASH_MATH_SUPPORT_64
4980 len = fmtstr(expdest, 32, "%lld", (long long) num);
4982 len = fmtstr(expdest, 32, "%ld", num);
4984 STADJUST(len, expdest);
4989 esclen(const char *start, const char *p)
4993 while (p > start && *--p == CTLESC) {
5000 * Remove any CTLESC characters from a string.
5003 _rmescapes(char *str, int flag)
5005 static const char qchars[] = { CTLESC, CTLQUOTEMARK, '\0' };
5012 p = strpbrk(str, qchars);
5018 if (flag & RMESCAPE_ALLOC) {
5019 size_t len = p - str;
5020 size_t fulllen = len + strlen(p) + 1;
5022 if (flag & RMESCAPE_GROW) {
5023 r = makestrspace(fulllen, expdest);
5024 } else if (flag & RMESCAPE_HEAP) {
5025 r = ckmalloc(fulllen);
5027 r = stalloc(fulllen);
5031 q = memcpy(q, str, len) + len;
5034 inquotes = (flag & RMESCAPE_QUOTED) ^ RMESCAPE_QUOTED;
5035 globbing = flag & RMESCAPE_GLOB;
5036 notescaped = globbing;
5038 if (*p == CTLQUOTEMARK) {
5039 inquotes = ~inquotes;
5041 notescaped = globbing;
5045 /* naked back slash */
5051 if (notescaped && inquotes && *p != '/') {
5055 notescaped = globbing;
5060 if (flag & RMESCAPE_GROW) {
5062 STADJUST(q - r + 1, expdest);
5066 #define rmescapes(p) _rmescapes((p), 0)
5068 #define pmatch(a, b) !fnmatch((a), (b), 0)
5071 * Prepare a pattern for a expmeta (internal glob(3)) call.
5073 * Returns an stalloced string.
5076 preglob(const char *pattern, int quoted, int flag)
5078 flag |= RMESCAPE_GLOB;
5080 flag |= RMESCAPE_QUOTED;
5082 return _rmescapes((char *)pattern, flag);
5086 * Put a string on the stack.
5089 memtodest(const char *p, size_t len, int syntax, int quotes)
5093 q = makestrspace(len * 2, q);
5096 int c = signed_char2int(*p++);
5099 if (quotes && (SIT(c, syntax) == CCTL || SIT(c, syntax) == CBACK))
5108 strtodest(const char *p, int syntax, int quotes)
5110 memtodest(p, strlen(p), syntax, quotes);
5114 * Record the fact that we have to scan this region of the
5115 * string for IFS characters.
5118 recordregion(int start, int end, int nulonly)
5120 struct ifsregion *ifsp;
5122 if (ifslastp == NULL) {
5126 ifsp = ckmalloc(sizeof(*ifsp));
5128 ifslastp->next = ifsp;
5132 ifslastp->begoff = start;
5133 ifslastp->endoff = end;
5134 ifslastp->nulonly = nulonly;
5138 removerecordregions(int endoff)
5140 if (ifslastp == NULL)
5143 if (ifsfirst.endoff > endoff) {
5144 while (ifsfirst.next != NULL) {
5145 struct ifsregion *ifsp;
5147 ifsp = ifsfirst.next->next;
5148 free(ifsfirst.next);
5149 ifsfirst.next = ifsp;
5152 if (ifsfirst.begoff > endoff)
5155 ifslastp = &ifsfirst;
5156 ifsfirst.endoff = endoff;
5161 ifslastp = &ifsfirst;
5162 while (ifslastp->next && ifslastp->next->begoff < endoff)
5163 ifslastp=ifslastp->next;
5164 while (ifslastp->next != NULL) {
5165 struct ifsregion *ifsp;
5167 ifsp = ifslastp->next->next;
5168 free(ifslastp->next);
5169 ifslastp->next = ifsp;
5172 if (ifslastp->endoff > endoff)
5173 ifslastp->endoff = endoff;
5177 exptilde(char *startp, char *p, int flag)
5183 int quotes = flag & (EXP_FULL | EXP_CASE);
5188 while ((c = *++p) != '\0') {
5195 if (flag & EXP_VARTILDE)
5205 if (*name == '\0') {
5206 home = lookupvar(homestr);
5208 pw = getpwnam(name);
5213 if (!home || !*home)
5216 startloc = expdest - (char *)stackblock();
5217 strtodest(home, SQSYNTAX, quotes);
5218 recordregion(startloc, expdest - (char *)stackblock(), 0);
5226 * Execute a command inside back quotes. If it's a builtin command, we
5227 * want to save its output in a block obtained from malloc. Otherwise
5228 * we fork off a subprocess and get the output of the command via a pipe.
5229 * Should be called with interrupts off.
5231 struct backcmd { /* result of evalbackcmd */
5232 int fd; /* file descriptor to read from */
5233 char *buf; /* buffer */
5234 int nleft; /* number of chars in buffer */
5235 struct job *jp; /* job structure for command */
5238 /* These forward decls are needed to use "eval" code for backticks handling: */
5239 static int back_exitstatus; /* exit status of backquoted command */
5240 #define EV_EXIT 01 /* exit after evaluating tree */
5241 static void evaltree(union node *, int);
5244 evalbackcmd(union node *n, struct backcmd *result)
5256 saveherefd = herefd;
5264 ash_msg_and_raise_error("pipe call failed");
5266 if (forkshell(jp, n, FORK_NOJOB) == 0) {
5275 evaltree(n, EV_EXIT); /* actually evaltreenr... */
5279 result->fd = pip[0];
5282 herefd = saveherefd;
5284 TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n",
5285 result->fd, result->buf, result->nleft, result->jp));
5289 * Expand stuff in backwards quotes.
5292 expbackq(union node *cmd, int quoted, int quotes)
5300 int syntax = quoted? DQSYNTAX : BASESYNTAX;
5301 struct stackmark smark;
5304 setstackmark(&smark);
5306 startloc = dest - (char *)stackblock();
5308 evalbackcmd(cmd, &in);
5309 popstackmark(&smark);
5316 memtodest(p, i, syntax, quotes);
5320 i = safe_read(in.fd, buf, sizeof(buf));
5321 TRACE(("expbackq: read returns %d\n", i));
5331 back_exitstatus = waitforjob(in.jp);
5335 /* Eat all trailing newlines */
5337 for (; dest > (char *)stackblock() && dest[-1] == '\n';)
5342 recordregion(startloc, dest - (char *)stackblock(), 0);
5343 TRACE(("evalbackq: size=%d: \"%.*s\"\n",
5344 (dest - (char *)stackblock()) - startloc,
5345 (dest - (char *)stackblock()) - startloc,
5346 stackblock() + startloc));
5349 #if ENABLE_ASH_MATH_SUPPORT
5351 * Expand arithmetic expression. Backup to start of expression,
5352 * evaluate, place result in (backed up) result, adjust string position.
5365 * This routine is slightly over-complicated for
5366 * efficiency. Next we scan backwards looking for the
5367 * start of arithmetic.
5369 start = stackblock();
5376 while (*p != CTLARI) {
5380 ash_msg_and_raise_error("missing CTLARI (shouldn't happen)");
5385 esc = esclen(start, p);
5395 removerecordregions(begoff);
5404 len = cvtnum(dash_arith(p + 2));
5407 recordregion(begoff, begoff + len, 0);
5411 /* argstr needs it */
5412 static char *evalvar(char *p, int flag);
5415 * Perform variable and command substitution. If EXP_FULL is set, output CTLESC
5416 * characters to allow for further processing. Otherwise treat
5417 * $@ like $* since no splitting will be performed.
5420 argstr(char *p, int flag)
5422 static const char spclchars[] = {
5430 CTLBACKQ | CTLQUOTE,
5431 #if ENABLE_ASH_MATH_SUPPORT
5436 const char *reject = spclchars;
5438 int quotes = flag & (EXP_FULL | EXP_CASE); /* do CTLESC */
5439 int breakall = flag & EXP_WORD;
5444 if (!(flag & EXP_VARTILDE)) {
5446 } else if (flag & EXP_VARTILDE2) {
5451 if (flag & EXP_TILDE) {
5457 if (*q == CTLESC && (flag & EXP_QWORD))
5460 p = exptilde(p, q, flag);
5463 startloc = expdest - (char *)stackblock();
5465 length += strcspn(p + length, reject);
5467 if (c && (!(c & 0x80)
5468 #if ENABLE_ASH_MATH_SUPPORT
5472 /* c == '=' || c == ':' || c == CTLENDARI */
5477 expdest = stack_nputstr(p, length, expdest);
5478 newloc = expdest - (char *)stackblock();
5479 if (breakall && !inquotes && newloc > startloc) {
5480 recordregion(startloc, newloc, 0);
5491 if (flag & EXP_VARTILDE2) {
5495 flag |= EXP_VARTILDE2;
5500 * sort of a hack - expand tildes in variable
5501 * assignments (after the first '=' and after ':'s).
5510 case CTLENDVAR: /* ??? */
5513 /* "$@" syntax adherence hack */
5516 !memcmp(p, dolatstr, 4) &&
5517 (p[4] == CTLQUOTEMARK || (
5518 p[4] == CTLENDVAR &&
5519 p[5] == CTLQUOTEMARK
5522 p = evalvar(p + 1, flag) + 1;
5525 inquotes = !inquotes;
5538 p = evalvar(p, flag);
5542 case CTLBACKQ|CTLQUOTE:
5543 expbackq(argbackq->n, c, quotes);
5544 argbackq = argbackq->next;
5546 #if ENABLE_ASH_MATH_SUPPORT
5559 scanleft(char *startp, char *rmesc, char *rmescend, char *str, int quotes,
5570 const char *s = loc2;
5576 match = pmatch(str, s);
5580 if (quotes && *loc == CTLESC)
5589 scanright(char *startp, char *rmesc, char *rmescend, char *str, int quotes,
5596 for (loc = str - 1, loc2 = rmescend; loc >= startp; loc2--) {
5599 const char *s = loc2;
5604 match = pmatch(str, s);
5611 esc = esclen(startp, loc);
5622 static void varunset(const char *, const char *, const char *, int) ATTRIBUTE_NORETURN;
5624 varunset(const char *end, const char *var, const char *umsg, int varflags)
5630 msg = "parameter not set";
5632 if (*end == CTLENDVAR) {
5633 if (varflags & VSNUL)
5638 ash_msg_and_raise_error("%.*s: %s%s", end - var - 1, var, msg, tail);
5642 subevalvar(char *p, char *str, int strloc, int subtype, int startloc, int varflags, int quotes)
5646 int saveherefd = herefd;
5647 struct nodelist *saveargbackq = argbackq;
5649 char *rmesc, *rmescend;
5651 char *(*scan)(char *, char *, char *, char *, int , int);
5654 argstr(p, subtype != VSASSIGN && subtype != VSQUESTION ? EXP_CASE : 0);
5655 STPUTC('\0', expdest);
5656 herefd = saveherefd;
5657 argbackq = saveargbackq;
5658 startp = stackblock() + startloc;
5662 setvar(str, startp, 0);
5663 amount = startp - expdest;
5664 STADJUST(amount, expdest);
5668 varunset(p, str, startp, varflags);
5672 subtype -= VSTRIMRIGHT;
5674 if (subtype < 0 || subtype > 3)
5679 rmescend = stackblock() + strloc;
5681 rmesc = _rmescapes(startp, RMESCAPE_ALLOC | RMESCAPE_GROW);
5682 if (rmesc != startp) {
5684 startp = stackblock() + startloc;
5688 str = stackblock() + strloc;
5689 preglob(str, varflags & VSQUOTE, 0);
5691 /* zero = subtype == VSTRIMLEFT || subtype == VSTRIMLEFTMAX */
5692 zero = subtype >> 1;
5693 /* VSTRIMLEFT/VSTRIMRIGHTMAX -> scanleft */
5694 scan = (subtype & 1) ^ zero ? scanleft : scanright;
5696 loc = scan(startp, rmesc, rmescend, str, quotes, zero);
5699 memmove(startp, loc, str - loc);
5700 loc = startp + (str - loc) - 1;
5703 amount = loc - expdest;
5704 STADJUST(amount, expdest);
5710 * Add the value of a specialized variable to the stack string.
5713 varvalue(char *name, int varflags, int flags)
5723 int quoted = varflags & VSQUOTE;
5724 int subtype = varflags & VSTYPE;
5725 int quotes = flags & (EXP_FULL | EXP_CASE);
5727 if (quoted && (flags & EXP_FULL))
5728 sep = 1 << CHAR_BIT;
5730 syntax = quoted ? DQSYNTAX : BASESYNTAX;
5739 num = shellparam.nparam;
5749 p = makestrspace(NOPTS, expdest);
5750 for (i = NOPTS - 1; i >= 0; i--) {
5752 USTPUTC(optletters(i), p);
5763 sep = ifsset() ? signed_char2int(ifsval()[0]) : ' ';
5764 if (quotes && (SIT(sep, syntax) == CCTL || SIT(sep, syntax) == CBACK))
5770 while ((p = *ap++)) {
5773 partlen = strlen(p);
5776 if (!(subtype == VSPLUS || subtype == VSLENGTH))
5777 memtodest(p, partlen, syntax, quotes);
5783 if (subtype == VSPLUS || subtype == VSLENGTH) {
5805 if (num < 0 || num > shellparam.nparam)
5807 p = num ? shellparam.p[num - 1] : arg0;
5810 p = lookupvar(name);
5816 if (!(subtype == VSPLUS || subtype == VSLENGTH))
5817 memtodest(p, len, syntax, quotes);
5821 if (subtype == VSPLUS || subtype == VSLENGTH)
5822 STADJUST(-len, expdest);
5827 * Expand a variable, and return a pointer to the next character in the
5831 evalvar(char *p, int flag)
5844 quotes = flag & (EXP_FULL | EXP_CASE);
5846 subtype = varflags & VSTYPE;
5847 quoted = varflags & VSQUOTE;
5849 easy = (!quoted || (*var == '@' && shellparam.nparam));
5850 startloc = expdest - (char *)stackblock();
5851 p = strchr(p, '=') + 1;
5854 varlen = varvalue(var, varflags, flag);
5855 if (varflags & VSNUL)
5858 if (subtype == VSPLUS) {
5859 varlen = -1 - varlen;
5863 if (subtype == VSMINUS) {
5867 p, flag | EXP_TILDE |
5868 (quoted ? EXP_QWORD : EXP_WORD)
5877 if (subtype == VSASSIGN || subtype == VSQUESTION) {
5879 if (subevalvar(p, var, 0, subtype, startloc, varflags, 0)) {
5882 * Remove any recorded regions beyond
5885 removerecordregions(startloc);
5895 if (varlen < 0 && uflag)
5896 varunset(p, var, 0, 0);
5898 if (subtype == VSLENGTH) {
5899 cvtnum(varlen > 0 ? varlen : 0);
5903 if (subtype == VSNORMAL) {
5907 recordregion(startloc, expdest - (char *)stackblock(), quoted);
5916 case VSTRIMRIGHTMAX:
5925 * Terminate the string and start recording the pattern
5928 STPUTC('\0', expdest);
5929 patloc = expdest - (char *)stackblock();
5930 if (subevalvar(p, NULL, patloc, subtype,
5931 startloc, varflags, quotes) == 0) {
5932 int amount = expdest - (
5933 (char *)stackblock() + patloc - 1
5935 STADJUST(-amount, expdest);
5937 /* Remove any recorded regions beyond start of variable */
5938 removerecordregions(startloc);
5943 if (subtype != VSNORMAL) { /* skip to end of alternative */
5949 else if (c == CTLBACKQ || c == (CTLBACKQ|CTLQUOTE)) {
5951 argbackq = argbackq->next;
5952 } else if (c == CTLVAR) {
5953 if ((*p++ & VSTYPE) != VSNORMAL)
5955 } else if (c == CTLENDVAR) {
5965 * Break the argument string into pieces based upon IFS and add the
5966 * strings to the argument list. The regions of the string to be
5967 * searched for IFS characters have been stored by recordregion.
5970 ifsbreakup(char *string, struct arglist *arglist)
5972 struct ifsregion *ifsp;
5977 const char *ifs, *realifs;
5982 if (ifslastp != NULL) {
5985 realifs = ifsset() ? ifsval() : defifs;
5988 p = string + ifsp->begoff;
5989 nulonly = ifsp->nulonly;
5990 ifs = nulonly ? nullstr : realifs;
5992 while (p < string + ifsp->endoff) {
5996 if (!strchr(ifs, *p)) {
6001 ifsspc = (strchr(defifs, *p) != NULL);
6002 /* Ignore IFS whitespace at start */
6003 if (q == start && ifsspc) {
6009 sp = stalloc(sizeof(*sp));
6011 *arglist->lastp = sp;
6012 arglist->lastp = &sp->next;
6016 if (p >= string + ifsp->endoff) {
6022 if (strchr(ifs, *p) == NULL ) {
6025 } else if (strchr(defifs, *p) == NULL) {
6040 } while (ifsp != NULL);
6049 sp = stalloc(sizeof(*sp));
6051 *arglist->lastp = sp;
6052 arglist->lastp = &sp->next;
6058 struct ifsregion *p;
6063 struct ifsregion *ifsp;
6069 ifsfirst.next = NULL;
6074 * Add a file name to the list.
6077 addfname(const char *name)
6081 sp = stalloc(sizeof(*sp));
6082 sp->text = ststrdup(name);
6084 exparg.lastp = &sp->next;
6087 static char *expdir;
6090 * Do metacharacter (i.e. *, ?, [...]) expansion.
6093 expmeta(char *enddir, char *name)
6108 for (p = name; *p; p++) {
6109 if (*p == '*' || *p == '?')
6111 else if (*p == '[') {
6118 if (*q == '/' || *q == '\0')
6125 } else if (*p == '\\')
6127 else if (*p == '/') {
6134 if (metaflag == 0) { /* we've reached the end of the file name */
6135 if (enddir != expdir)
6143 if (metaflag == 0 || lstat(expdir, &statb) >= 0)
6154 } while (p < start);
6156 if (enddir == expdir) {
6158 } else if (enddir == expdir + 1 && *expdir == '/') {
6167 if (enddir != expdir)
6169 if (*endname == 0) {
6181 while (! intpending && (dp = readdir(dirp)) != NULL) {
6182 if (dp->d_name[0] == '.' && ! matchdot)
6184 if (pmatch(start, dp->d_name)) {
6186 strcpy(enddir, dp->d_name);
6189 for (p = enddir, cp = dp->d_name; (*p++ = *cp++) != '\0';)
6192 expmeta(p, endname);
6201 static struct strlist *
6202 msort(struct strlist *list, int len)
6204 struct strlist *p, *q = NULL;
6205 struct strlist **lpp;
6213 for (n = half; --n >= 0; ) {
6217 q->next = NULL; /* terminate first half of list */
6218 q = msort(list, half); /* sort first half of list */
6219 p = msort(p, len - half); /* sort second half */
6222 #if ENABLE_LOCALE_SUPPORT
6223 if (strcoll(p->text, q->text) < 0)
6225 if (strcmp(p->text, q->text) < 0)
6249 * Sort the results of file name expansion. It calculates the number of
6250 * strings to sort and then calls msort (short for merge sort) to do the
6253 static struct strlist *
6254 expsort(struct strlist *str)
6260 for (sp = str; sp; sp = sp->next)
6262 return msort(str, len);
6266 expandmeta(struct strlist *str, int flag)
6268 static const char metachars[] = {
6271 /* TODO - EXP_REDIR */
6274 struct strlist **savelastp;
6280 if (!strpbrk(str->text, metachars))
6282 savelastp = exparg.lastp;
6285 p = preglob(str->text, 0, RMESCAPE_ALLOC | RMESCAPE_HEAP);
6287 int i = strlen(str->text);
6288 expdir = ckmalloc(i < 2048 ? 2048 : i); /* XXX */
6296 if (exparg.lastp == savelastp) {
6301 *exparg.lastp = str;
6302 rmescapes(str->text);
6303 exparg.lastp = &str->next;
6305 *exparg.lastp = NULL;
6306 *savelastp = sp = expsort(*savelastp);
6307 while (sp->next != NULL)
6309 exparg.lastp = &sp->next;
6316 * Perform variable substitution and command substitution on an argument,
6317 * placing the resulting list of arguments in arglist. If EXP_FULL is true,
6318 * perform splitting and file name expansion. When arglist is NULL, perform
6319 * here document expansion.
6322 expandarg(union node *arg, struct arglist *arglist, int flag)
6327 argbackq = arg->narg.backquote;
6328 STARTSTACKSTR(expdest);
6329 ifsfirst.next = NULL;
6331 argstr(arg->narg.text, flag);
6332 p = _STPUTC('\0', expdest);
6334 if (arglist == NULL) {
6335 return; /* here document expanded */
6337 p = grabstackstr(p);
6338 exparg.lastp = &exparg.list;
6342 if (flag & EXP_FULL) {
6343 ifsbreakup(p, &exparg);
6344 *exparg.lastp = NULL;
6345 exparg.lastp = &exparg.list;
6346 expandmeta(exparg.list, flag);
6348 if (flag & EXP_REDIR) /*XXX - for now, just remove escapes */
6350 sp = stalloc(sizeof(*sp));
6353 exparg.lastp = &sp->next;
6357 *exparg.lastp = NULL;
6359 *arglist->lastp = exparg.list;
6360 arglist->lastp = exparg.lastp;
6365 * Expand shell variables and backquotes inside a here document.
6368 expandhere(union node *arg, int fd)
6371 expandarg(arg, (struct arglist *)NULL, 0);
6372 full_write(fd, stackblock(), expdest - (char *)stackblock());
6376 * Returns true if the pattern matches the string.
6379 patmatch(char *pattern, const char *string)
6381 return pmatch(preglob(pattern, 0, 0), string);
6385 * See if a pattern matches in a case statement.
6388 casematch(union node *pattern, char *val)
6390 struct stackmark smark;
6393 setstackmark(&smark);
6394 argbackq = pattern->narg.backquote;
6395 STARTSTACKSTR(expdest);
6397 argstr(pattern->narg.text, EXP_TILDE | EXP_CASE);
6398 STACKSTRNUL(expdest);
6399 result = patmatch(stackblock(), val);
6400 popstackmark(&smark);
6405 /* ============ find_command */
6409 int (*builtin)(int, char **);
6410 /* unsigned flags; */
6412 #define IS_BUILTIN_SPECIAL(b) ((b)->name[0] & 1)
6413 #define IS_BUILTIN_REGULAR(b) ((b)->name[0] & 2)
6414 #define IS_BUILTIN_ASSIGN(b) ((b)->name[0] & 4)
6420 const struct builtincmd *cmd;
6421 struct funcnode *func;
6424 /* values of cmdtype */
6425 #define CMDUNKNOWN -1 /* no entry in table for command */
6426 #define CMDNORMAL 0 /* command is an executable program */
6427 #define CMDFUNCTION 1 /* command is a shell function */
6428 #define CMDBUILTIN 2 /* command is a shell builtin */
6430 /* action to find_command() */
6431 #define DO_ERR 0x01 /* prints errors */
6432 #define DO_ABS 0x02 /* checks absolute paths */
6433 #define DO_NOFUNC 0x04 /* don't return shell functions, for command */
6434 #define DO_ALTPATH 0x08 /* using alternate path */
6435 #define DO_ALTBLTIN 0x20 /* %builtin in alt. path */
6437 static void find_command(char *, struct cmdentry *, int, const char *);
6440 /* ============ Hashing commands */
6443 * When commands are first encountered, they are entered in a hash table.
6444 * This ensures that a full path search will not have to be done for them
6445 * on each invocation.
6447 * We should investigate converting to a linear search, even though that
6448 * would make the command name "hash" a misnomer.
6451 #define CMDTABLESIZE 31 /* should be prime */
6452 #define ARB 1 /* actual size determined at run time */
6455 struct tblentry *next; /* next entry in hash chain */
6456 union param param; /* definition of builtin function */
6457 short cmdtype; /* index identifying command */
6458 char rehash; /* if set, cd done since entry created */
6459 char cmdname[ARB]; /* name of command */
6462 static struct tblentry *cmdtable[CMDTABLESIZE];
6463 static int builtinloc = -1; /* index in path of %builtin, or -1 */
6466 tryexec(char *cmd, char **argv, char **envp)
6470 #if ENABLE_FEATURE_SH_STANDALONE
6471 if (strchr(cmd, '/') == NULL) {
6472 const struct bb_applet *a;
6474 a = find_applet_by_name(cmd);
6478 run_current_applet_and_exit(argv);
6480 /* re-exec ourselves with the new arguments */
6481 execve(CONFIG_BUSYBOX_EXEC_PATH, argv, envp);
6482 /* If they called chroot or otherwise made the binary no longer
6483 * executable, fall through */
6491 execve(cmd, argv, envp);
6492 } while (errno == EINTR);
6494 execve(cmd, argv, envp);
6498 } else if (errno == ENOEXEC) {
6502 for (ap = argv; *ap; ap++)
6504 ap = new = ckmalloc((ap - argv + 2) * sizeof(char *));
6506 ap[0] = cmd = (char *)DEFAULT_SHELL;
6509 while ((*ap++ = *argv++))
6517 * Exec a program. Never returns. If you change this routine, you may
6518 * have to change the find_command routine as well.
6520 #define environment() listvars(VEXPORT, VUNSET, 0)
6521 static void shellexec(char **, const char *, int) ATTRIBUTE_NORETURN;
6523 shellexec(char **argv, const char *path, int idx)
6531 envp = environment();
6532 if (strchr(argv[0], '/')
6533 #if ENABLE_FEATURE_SH_STANDALONE
6534 || find_applet_by_name(argv[0])
6537 tryexec(argv[0], argv, envp);
6541 while ((cmdname = padvance(&path, argv[0])) != NULL) {
6542 if (--idx < 0 && pathopt == NULL) {
6543 tryexec(cmdname, argv, envp);
6544 if (errno != ENOENT && errno != ENOTDIR)
6551 /* Map to POSIX errors */
6563 exitstatus = exerrno;
6564 TRACE(("shellexec failed for %s, errno %d, suppressint %d\n",
6565 argv[0], e, suppressint ));
6566 ash_msg_and_raise(EXEXEC, "%s: %s", argv[0], errmsg(e, "not found"));
6571 printentry(struct tblentry *cmdp)
6577 idx = cmdp->param.index;
6580 name = padvance(&path, cmdp->cmdname);
6582 } while (--idx >= 0);
6583 out1fmt("%s%s\n", name, (cmdp->rehash ? "*" : nullstr));
6587 * Clear out command entries. The argument specifies the first entry in
6588 * PATH which has changed.
6591 clearcmdentry(int firstchange)
6593 struct tblentry **tblp;
6594 struct tblentry **pp;
6595 struct tblentry *cmdp;
6598 for (tblp = cmdtable; tblp < &cmdtable[CMDTABLESIZE]; tblp++) {
6600 while ((cmdp = *pp) != NULL) {
6601 if ((cmdp->cmdtype == CMDNORMAL &&
6602 cmdp->param.index >= firstchange)
6603 || (cmdp->cmdtype == CMDBUILTIN &&
6604 builtinloc >= firstchange)
6617 * Locate a command in the command hash table. If "add" is nonzero,
6618 * add the command to the table if it is not already present. The
6619 * variable "lastcmdentry" is set to point to the address of the link
6620 * pointing to the entry, so that delete_cmd_entry can delete the
6623 * Interrupts must be off if called with add != 0.
6625 static struct tblentry **lastcmdentry;
6627 static struct tblentry *
6628 cmdlookup(const char *name, int add)
6630 unsigned int hashval;
6632 struct tblentry *cmdp;
6633 struct tblentry **pp;
6636 hashval = (unsigned char)*p << 4;
6638 hashval += (unsigned char)*p++;
6640 pp = &cmdtable[hashval % CMDTABLESIZE];
6641 for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
6642 if (strcmp(cmdp->cmdname, name) == 0)
6646 if (add && cmdp == NULL) {
6647 cmdp = *pp = ckmalloc(sizeof(struct tblentry) - ARB
6648 + strlen(name) + 1);
6650 cmdp->cmdtype = CMDUNKNOWN;
6651 strcpy(cmdp->cmdname, name);
6658 * Delete the command entry returned on the last lookup.
6661 delete_cmd_entry(void)
6663 struct tblentry *cmdp;
6666 cmdp = *lastcmdentry;
6667 *lastcmdentry = cmdp->next;
6668 if (cmdp->cmdtype == CMDFUNCTION)
6669 freefunc(cmdp->param.func);
6675 * Add a new command entry, replacing any existing command entry for
6676 * the same name - except special builtins.
6679 addcmdentry(char *name, struct cmdentry *entry)
6681 struct tblentry *cmdp;
6683 cmdp = cmdlookup(name, 1);
6684 if (cmdp->cmdtype == CMDFUNCTION) {
6685 freefunc(cmdp->param.func);
6687 cmdp->cmdtype = entry->cmdtype;
6688 cmdp->param = entry->u;
6693 hashcmd(int argc, char **argv)
6695 struct tblentry **pp;
6696 struct tblentry *cmdp;
6698 struct cmdentry entry;
6701 while ((c = nextopt("r")) != '\0') {
6705 if (*argptr == NULL) {
6706 for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
6707 for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
6708 if (cmdp->cmdtype == CMDNORMAL)
6715 while ((name = *argptr) != NULL) {
6716 cmdp = cmdlookup(name, 0);
6718 && (cmdp->cmdtype == CMDNORMAL
6719 || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0)))
6721 find_command(name, &entry, DO_ERR, pathval());
6722 if (entry.cmdtype == CMDUNKNOWN)
6730 * Called when a cd is done. Marks all commands so the next time they
6731 * are executed they will be rehashed.
6736 struct tblentry **pp;
6737 struct tblentry *cmdp;
6739 for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
6740 for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
6741 if (cmdp->cmdtype == CMDNORMAL || (
6742 cmdp->cmdtype == CMDBUILTIN &&
6743 !(IS_BUILTIN_REGULAR(cmdp->param.cmd)) &&
6752 * Fix command hash table when PATH changed.
6753 * Called before PATH is changed. The argument is the new value of PATH;
6754 * pathval() still returns the old value at this point.
6755 * Called with interrupts off.
6758 changepath(const char *newval)
6760 const char *old, *new;
6767 firstchange = 9999; /* assume no change */
6773 if ((*old == '\0' && *new == ':')
6774 || (*old == ':' && *new == '\0'))
6776 old = new; /* ignore subsequent differences */
6780 if (*new == '%' && idx_bltin < 0 && prefix(new + 1, "builtin"))
6787 if (builtinloc < 0 && idx_bltin >= 0)
6788 builtinloc = idx_bltin; /* zap builtins */
6789 if (builtinloc >= 0 && idx_bltin < 0)
6791 clearcmdentry(firstchange);
6792 builtinloc = idx_bltin;
6807 #define TENDBQUOTE 12
6825 /* first char is indicating which tokens mark the end of a list */
6826 static const char *const tokname_array[] = {
6840 #define KWDOFFSET 13
6841 /* the following are keywords */
6863 static char buf[16];
6866 //if (tok < TSEMI) return tokname_array[tok] + 1;
6867 //sprintf(buf, "\"%s\"", tokname_array[tok] + 1);
6872 sprintf(buf + (tok >= TSEMI), "%s%c",
6873 tokname_array[tok] + 1, (tok >= TSEMI ? '"' : 0));
6877 /* Wrapper around strcmp for qsort/bsearch/... */
6879 pstrcmp(const void *a, const void *b)
6881 return strcmp((char*) a, (*(char**) b) + 1);
6884 static const char *const *
6885 findkwd(const char *s)
6887 return bsearch(s, tokname_array + KWDOFFSET,
6888 (sizeof(tokname_array) / sizeof(char *)) - KWDOFFSET,
6889 sizeof(char *), pstrcmp);
6893 * Locate and print what a word is...
6895 #if ENABLE_ASH_CMDCMD
6897 describe_command(char *command, int describe_command_verbose)
6899 #define describe_command_verbose 1
6901 describe_command(char *command)
6904 struct cmdentry entry;
6905 struct tblentry *cmdp;
6906 #if ENABLE_ASH_ALIAS
6907 const struct alias *ap;
6909 const char *path = pathval();
6911 if (describe_command_verbose) {
6915 /* First look at the keywords */
6916 if (findkwd(command)) {
6917 out1str(describe_command_verbose ? " is a shell keyword" : command);
6921 #if ENABLE_ASH_ALIAS
6922 /* Then look at the aliases */
6923 ap = lookupalias(command, 0);
6925 if (describe_command_verbose) {
6926 out1fmt(" is an alias for %s", ap->val);
6935 /* Then check if it is a tracked alias */
6936 cmdp = cmdlookup(command, 0);
6938 entry.cmdtype = cmdp->cmdtype;
6939 entry.u = cmdp->param;
6941 /* Finally use brute force */
6942 find_command(command, &entry, DO_ABS, path);
6945 switch (entry.cmdtype) {
6947 int j = entry.u.index;
6953 p = padvance(&path, command);
6957 if (describe_command_verbose) {
6959 (cmdp ? " a tracked alias for" : nullstr), p
6968 if (describe_command_verbose) {
6969 out1str(" is a shell function");
6976 if (describe_command_verbose) {
6977 out1fmt(" is a %sshell builtin",
6978 IS_BUILTIN_SPECIAL(entry.u.cmd) ?
6979 "special " : nullstr
6987 if (describe_command_verbose) {
6988 out1str(": not found\n");
6993 outstr("\n", stdout);
6998 typecmd(int argc, char **argv)
7003 for (i = 1; i < argc; i++) {
7004 #if ENABLE_ASH_CMDCMD
7005 err |= describe_command(argv[i], 1);
7007 err |= describe_command(argv[i]);
7013 #if ENABLE_ASH_CMDCMD
7015 commandcmd(int argc, char **argv)
7023 while ((c = nextopt("pvV")) != '\0')
7025 verify |= VERIFY_VERBOSE;
7027 verify |= VERIFY_BRIEF;
7033 return describe_command(*argptr, verify - VERIFY_BRIEF);
7040 /* ============ eval.c */
7042 static int funcblocksize; /* size of structures in function */
7043 static int funcstringsize; /* size of strings in node */
7044 static void *funcblock; /* block to allocate function from */
7045 static char *funcstring; /* block to allocate strings from */
7047 /* flags in argument to evaltree */
7048 #define EV_EXIT 01 /* exit after evaluating tree */
7049 #define EV_TESTED 02 /* exit status is checked; ignore -e flag */
7050 #define EV_BACKCMD 04 /* command executing within back quotes */
7052 static const short nodesize[26] = {
7053 SHELL_ALIGN(sizeof(struct ncmd)),
7054 SHELL_ALIGN(sizeof(struct npipe)),
7055 SHELL_ALIGN(sizeof(struct nredir)),
7056 SHELL_ALIGN(sizeof(struct nredir)),
7057 SHELL_ALIGN(sizeof(struct nredir)),
7058 SHELL_ALIGN(sizeof(struct nbinary)),
7059 SHELL_ALIGN(sizeof(struct nbinary)),
7060 SHELL_ALIGN(sizeof(struct nbinary)),
7061 SHELL_ALIGN(sizeof(struct nif)),
7062 SHELL_ALIGN(sizeof(struct nbinary)),
7063 SHELL_ALIGN(sizeof(struct nbinary)),
7064 SHELL_ALIGN(sizeof(struct nfor)),
7065 SHELL_ALIGN(sizeof(struct ncase)),
7066 SHELL_ALIGN(sizeof(struct nclist)),
7067 SHELL_ALIGN(sizeof(struct narg)),
7068 SHELL_ALIGN(sizeof(struct narg)),
7069 SHELL_ALIGN(sizeof(struct nfile)),
7070 SHELL_ALIGN(sizeof(struct nfile)),
7071 SHELL_ALIGN(sizeof(struct nfile)),
7072 SHELL_ALIGN(sizeof(struct nfile)),
7073 SHELL_ALIGN(sizeof(struct nfile)),
7074 SHELL_ALIGN(sizeof(struct ndup)),
7075 SHELL_ALIGN(sizeof(struct ndup)),
7076 SHELL_ALIGN(sizeof(struct nhere)),
7077 SHELL_ALIGN(sizeof(struct nhere)),
7078 SHELL_ALIGN(sizeof(struct nnot)),
7081 static void calcsize(union node *n);
7084 sizenodelist(struct nodelist *lp)
7087 funcblocksize += SHELL_ALIGN(sizeof(struct nodelist));
7094 calcsize(union node *n)
7098 funcblocksize += nodesize[n->type];
7101 calcsize(n->ncmd.redirect);
7102 calcsize(n->ncmd.args);
7103 calcsize(n->ncmd.assign);
7106 sizenodelist(n->npipe.cmdlist);
7111 calcsize(n->nredir.redirect);
7112 calcsize(n->nredir.n);
7119 calcsize(n->nbinary.ch2);
7120 calcsize(n->nbinary.ch1);
7123 calcsize(n->nif.elsepart);
7124 calcsize(n->nif.ifpart);
7125 calcsize(n->nif.test);
7128 funcstringsize += strlen(n->nfor.var) + 1;
7129 calcsize(n->nfor.body);
7130 calcsize(n->nfor.args);
7133 calcsize(n->ncase.cases);
7134 calcsize(n->ncase.expr);
7137 calcsize(n->nclist.body);
7138 calcsize(n->nclist.pattern);
7139 calcsize(n->nclist.next);
7143 sizenodelist(n->narg.backquote);
7144 funcstringsize += strlen(n->narg.text) + 1;
7145 calcsize(n->narg.next);
7152 calcsize(n->nfile.fname);
7153 calcsize(n->nfile.next);
7157 calcsize(n->ndup.vname);
7158 calcsize(n->ndup.next);
7162 calcsize(n->nhere.doc);
7163 calcsize(n->nhere.next);
7166 calcsize(n->nnot.com);
7172 nodeckstrdup(char *s)
7174 char *rtn = funcstring;
7176 strcpy(funcstring, s);
7177 funcstring += strlen(s) + 1;
7181 static union node *copynode(union node *);
7183 static struct nodelist *
7184 copynodelist(struct nodelist *lp)
7186 struct nodelist *start;
7187 struct nodelist **lpp;
7192 funcblock = (char *) funcblock + SHELL_ALIGN(sizeof(struct nodelist));
7193 (*lpp)->n = copynode(lp->n);
7195 lpp = &(*lpp)->next;
7202 copynode(union node *n)
7209 funcblock = (char *) funcblock + nodesize[n->type];
7213 new->ncmd.redirect = copynode(n->ncmd.redirect);
7214 new->ncmd.args = copynode(n->ncmd.args);
7215 new->ncmd.assign = copynode(n->ncmd.assign);
7218 new->npipe.cmdlist = copynodelist(n->npipe.cmdlist);
7219 new->npipe.backgnd = n->npipe.backgnd;
7224 new->nredir.redirect = copynode(n->nredir.redirect);
7225 new->nredir.n = copynode(n->nredir.n);
7232 new->nbinary.ch2 = copynode(n->nbinary.ch2);
7233 new->nbinary.ch1 = copynode(n->nbinary.ch1);
7236 new->nif.elsepart = copynode(n->nif.elsepart);
7237 new->nif.ifpart = copynode(n->nif.ifpart);
7238 new->nif.test = copynode(n->nif.test);
7241 new->nfor.var = nodeckstrdup(n->nfor.var);
7242 new->nfor.body = copynode(n->nfor.body);
7243 new->nfor.args = copynode(n->nfor.args);
7246 new->ncase.cases = copynode(n->ncase.cases);
7247 new->ncase.expr = copynode(n->ncase.expr);
7250 new->nclist.body = copynode(n->nclist.body);
7251 new->nclist.pattern = copynode(n->nclist.pattern);
7252 new->nclist.next = copynode(n->nclist.next);
7256 new->narg.backquote = copynodelist(n->narg.backquote);
7257 new->narg.text = nodeckstrdup(n->narg.text);
7258 new->narg.next = copynode(n->narg.next);
7265 new->nfile.fname = copynode(n->nfile.fname);
7266 new->nfile.fd = n->nfile.fd;
7267 new->nfile.next = copynode(n->nfile.next);
7271 new->ndup.vname = copynode(n->ndup.vname);
7272 new->ndup.dupfd = n->ndup.dupfd;
7273 new->ndup.fd = n->ndup.fd;
7274 new->ndup.next = copynode(n->ndup.next);
7278 new->nhere.doc = copynode(n->nhere.doc);
7279 new->nhere.fd = n->nhere.fd;
7280 new->nhere.next = copynode(n->nhere.next);
7283 new->nnot.com = copynode(n->nnot.com);
7286 new->type = n->type;
7291 * Make a copy of a parse tree.
7293 static struct funcnode *
7294 copyfunc(union node *n)
7299 funcblocksize = offsetof(struct funcnode, n);
7302 blocksize = funcblocksize;
7303 f = ckmalloc(blocksize + funcstringsize);
7304 funcblock = (char *) f + offsetof(struct funcnode, n);
7305 funcstring = (char *) f + blocksize;
7312 * Define a shell function.
7315 defun(char *name, union node *func)
7317 struct cmdentry entry;
7320 entry.cmdtype = CMDFUNCTION;
7321 entry.u.func = copyfunc(func);
7322 addcmdentry(name, &entry);
7326 static int evalskip; /* set if we are skipping commands */
7327 /* reasons for skipping commands (see comment on breakcmd routine) */
7328 #define SKIPBREAK (1 << 0)
7329 #define SKIPCONT (1 << 1)
7330 #define SKIPFUNC (1 << 2)
7331 #define SKIPFILE (1 << 3)
7332 #define SKIPEVAL (1 << 4)
7333 static int skipcount; /* number of levels to skip */
7334 static int funcnest; /* depth of function calls */
7336 /* forward decl way out to parsing code - dotrap needs it */
7337 static int evalstring(char *s, int mask);
7340 * Called to execute a trap. Perhaps we should avoid entering new trap
7341 * handlers while we are executing a trap handler.
7352 savestatus = exitstatus;
7356 for (i = 0, q = gotsig; i < NSIG - 1; i++, q++) {
7364 skip = evalstring(p, SKIPEVAL);
7365 exitstatus = savestatus;
7373 /* forward declarations - evaluation is fairly recursive business... */
7374 static void evalloop(union node *, int);
7375 static void evalfor(union node *, int);
7376 static void evalcase(union node *, int);
7377 static void evalsubshell(union node *, int);
7378 static void expredir(union node *);
7379 static void evalpipe(union node *, int);
7380 static void evalcommand(union node *, int);
7381 static int evalbltin(const struct builtincmd *, int, char **);
7382 static void prehash(union node *);
7385 * Evaluate a parse tree. The value is left in the global variable
7389 evaltree(union node *n, int flags)
7392 void (*evalfn)(union node *, int);
7396 TRACE(("evaltree(NULL) called\n"));
7399 TRACE(("pid %d, evaltree(%p: %d, %d) called\n",
7400 getpid(), n, n->type, flags));
7404 out1fmt("Node type = %d\n", n->type);
7409 evaltree(n->nnot.com, EV_TESTED);
7410 status = !exitstatus;
7413 expredir(n->nredir.redirect);
7414 status = redirectsafe(n->nredir.redirect, REDIR_PUSH);
7416 evaltree(n->nredir.n, flags & EV_TESTED);
7417 status = exitstatus;
7422 evalfn = evalcommand;
7424 if (eflag && !(flags & EV_TESTED))
7436 evalfn = evalsubshell;
7448 #error NAND + 1 != NOR
7450 #if NOR + 1 != NSEMI
7451 #error NOR + 1 != NSEMI
7453 isor = n->type - NAND;
7456 (flags | ((isor >> 1) - 1)) & EV_TESTED
7458 if (!exitstatus == isor)
7470 evaltree(n->nif.test, EV_TESTED);
7473 if (exitstatus == 0) {
7476 } else if (n->nif.elsepart) {
7477 n = n->nif.elsepart;
7482 defun(n->narg.text, n->narg.next);
7486 exitstatus = status;
7490 if ((checkexit & exitstatus))
7491 evalskip |= SKIPEVAL;
7492 else if (pendingsig && dotrap())
7495 if (flags & EV_EXIT) {
7497 raise_exception(EXEXIT);
7501 #if !defined(__alpha__) || (defined(__GNUC__) && __GNUC__ >= 3)
7504 void evaltreenr(union node *, int) __attribute__ ((alias("evaltree"),__noreturn__));
7506 static int loopnest; /* current loop nesting level */
7509 evalloop(union node *n, int flags)
7519 evaltree(n->nbinary.ch1, EV_TESTED);
7522 if (evalskip == SKIPCONT && --skipcount <= 0) {
7526 if (evalskip == SKIPBREAK && --skipcount <= 0)
7531 if (n->type != NWHILE)
7535 evaltree(n->nbinary.ch2, flags);
7536 status = exitstatus;
7541 exitstatus = status;
7545 evalfor(union node *n, int flags)
7547 struct arglist arglist;
7550 struct stackmark smark;
7552 setstackmark(&smark);
7553 arglist.lastp = &arglist.list;
7554 for (argp = n->nfor.args; argp; argp = argp->narg.next) {
7555 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE | EXP_RECORD);
7560 *arglist.lastp = NULL;
7565 for (sp = arglist.list; sp; sp = sp->next) {
7566 setvar(n->nfor.var, sp->text, 0);
7567 evaltree(n->nfor.body, flags);
7569 if (evalskip == SKIPCONT && --skipcount <= 0) {
7573 if (evalskip == SKIPBREAK && --skipcount <= 0)
7580 popstackmark(&smark);
7584 evalcase(union node *n, int flags)
7588 struct arglist arglist;
7589 struct stackmark smark;
7591 setstackmark(&smark);
7592 arglist.lastp = &arglist.list;
7593 expandarg(n->ncase.expr, &arglist, EXP_TILDE);
7595 for (cp = n->ncase.cases; cp && evalskip == 0; cp = cp->nclist.next) {
7596 for (patp = cp->nclist.pattern; patp; patp = patp->narg.next) {
7597 if (casematch(patp, arglist.list->text)) {
7598 if (evalskip == 0) {
7599 evaltree(cp->nclist.body, flags);
7606 popstackmark(&smark);
7610 * Kick off a subshell to evaluate a tree.
7613 evalsubshell(union node *n, int flags)
7616 int backgnd = (n->type == NBACKGND);
7619 expredir(n->nredir.redirect);
7620 if (!backgnd && flags & EV_EXIT && !trap[0])
7624 if (forkshell(jp, n, backgnd) == 0) {
7628 flags &=~ EV_TESTED;
7630 redirect(n->nredir.redirect, 0);
7631 evaltreenr(n->nredir.n, flags);
7636 status = waitforjob(jp);
7637 exitstatus = status;
7642 * Compute the names of the files in a redirection list.
7644 static void fixredir(union node *, const char *, int);
7646 expredir(union node *n)
7650 for (redir = n; redir; redir = redir->nfile.next) {
7653 memset(&fn, 0, sizeof(fn));
7654 fn.lastp = &fn.list;
7655 switch (redir->type) {
7661 expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
7662 redir->nfile.expfname = fn.list->text;
7666 if (redir->ndup.vname) {
7667 expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE);
7668 if (fn.list == NULL)
7669 ash_msg_and_raise_error("redir error");
7670 fixredir(redir, fn.list->text, 1);
7678 * Evaluate a pipeline. All the processes in the pipeline are children
7679 * of the process creating the pipeline. (This differs from some versions
7680 * of the shell, which make the last process in a pipeline the parent
7684 evalpipe(union node *n, int flags)
7687 struct nodelist *lp;
7692 TRACE(("evalpipe(0x%lx) called\n", (long)n));
7694 for (lp = n->npipe.cmdlist; lp; lp = lp->next)
7698 jp = makejob(n, pipelen);
7700 for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
7704 if (pipe(pip) < 0) {
7706 ash_msg_and_raise_error("pipe call failed");
7709 if (forkshell(jp, lp->n, n->npipe.backgnd) == 0) {
7722 evaltreenr(lp->n, flags);
7730 if (n->npipe.backgnd == 0) {
7731 exitstatus = waitforjob(jp);
7732 TRACE(("evalpipe: job done exit status %d\n", exitstatus));
7738 * Controls whether the shell is interactive or not.
7741 setinteractive(int on)
7743 static int is_interactive;
7745 if (++on == is_interactive)
7747 is_interactive = on;
7751 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
7752 if (is_interactive > 1) {
7753 /* Looks like they want an interactive shell */
7754 static smallint do_banner;
7759 "%s Built-in shell (ash)\n"
7760 "Enter 'help' for a list of built-in commands."
7769 #if ENABLE_FEATURE_EDITING_VI
7770 #define setvimode(on) do { \
7771 if (on) line_input_state->flags |= VI_MODE; \
7772 else line_input_state->flags &= ~VI_MODE; \
7775 #define setvimode(on) viflag = 0 /* forcibly keep the option off */
7784 setinteractive(iflag);
7789 static struct localvar *localvars;
7792 * Called after a function returns.
7793 * Interrupts must be off.
7798 struct localvar *lvp;
7801 while ((lvp = localvars) != NULL) {
7802 localvars = lvp->next;
7804 TRACE(("poplocalvar %s", vp ? vp->text : "-"));
7805 if (vp == NULL) { /* $- saved */
7806 memcpy(optlist, lvp->text, sizeof(optlist));
7807 free((char*)lvp->text);
7809 } else if ((lvp->flags & (VUNSET|VSTRFIXED)) == VUNSET) {
7813 (*vp->func)(strchrnul(lvp->text, '=') + 1);
7814 if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
7815 free((char*)vp->text);
7816 vp->flags = lvp->flags;
7817 vp->text = lvp->text;
7824 evalfun(struct funcnode *func, int argc, char **argv, int flags)
7826 volatile struct shparam saveparam;
7827 struct localvar *volatile savelocalvars;
7828 struct jmploc *volatile savehandler;
7829 struct jmploc jmploc;
7832 saveparam = shellparam;
7833 savelocalvars = localvars;
7834 e = setjmp(jmploc.loc);
7839 savehandler = exception_handler;
7840 exception_handler = &jmploc;
7842 shellparam.malloc = 0;
7846 shellparam.nparam = argc - 1;
7847 shellparam.p = argv + 1;
7848 #if ENABLE_ASH_GETOPTS
7849 shellparam.optind = 1;
7850 shellparam.optoff = -1;
7852 evaltree(&func->n, flags & EV_TESTED);
7858 localvars = savelocalvars;
7859 freeparam(&shellparam);
7860 shellparam = saveparam;
7861 exception_handler = savehandler;
7863 evalskip &= ~SKIPFUNC;
7867 #if ENABLE_ASH_CMDCMD
7869 parse_command_args(char **argv, const char **path)
7882 if (c == '-' && !*cp) {
7892 /* run 'typecmd' for other options */
7903 * Make a variable a local variable. When a variable is made local, it's
7904 * value and flags are saved in a localvar structure. The saved values
7905 * will be restored when the shell function returns. We handle the name
7906 * "-" as a special case.
7911 struct localvar *lvp;
7916 lvp = ckmalloc(sizeof(struct localvar));
7917 if (LONE_DASH(name)) {
7919 p = ckmalloc(sizeof(optlist));
7920 lvp->text = memcpy(p, optlist, sizeof(optlist));
7925 vpp = hashvar(name);
7926 vp = *findvar(vpp, name);
7927 eq = strchr(name, '=');
7930 setvareq(name, VSTRFIXED);
7932 setvar(name, NULL, VSTRFIXED);
7933 vp = *vpp; /* the new variable */
7934 lvp->flags = VUNSET;
7936 lvp->text = vp->text;
7937 lvp->flags = vp->flags;
7938 vp->flags |= VSTRFIXED|VTEXTFIXED;
7944 lvp->next = localvars;
7950 * The "local" command.
7953 localcmd(int argc, char **argv)
7958 while ((name = *argv++) != NULL) {
7965 falsecmd(int argc, char **argv)
7971 truecmd(int argc, char **argv)
7977 execcmd(int argc, char **argv)
7980 iflag = 0; /* exit on error */
7983 shellexec(argv + 1, pathval(), 0);
7989 * The return command.
7992 returncmd(int argc, char **argv)
7995 * If called outside a function, do what ksh does;
7996 * skip the rest of the file.
7998 evalskip = funcnest ? SKIPFUNC : SKIPFILE;
7999 return argv[1] ? number(argv[1]) : exitstatus;
8002 /* Forward declarations for builtintab[] */
8003 static int breakcmd(int, char **);
8004 static int dotcmd(int, char **);
8005 static int evalcmd(int, char **);
8006 #if ENABLE_ASH_BUILTIN_ECHO
8007 static int echocmd(int, char **);
8009 #if ENABLE_ASH_BUILTIN_TEST
8010 static int testcmd(int, char **);
8012 static int exitcmd(int, char **);
8013 static int exportcmd(int, char **);
8014 #if ENABLE_ASH_GETOPTS
8015 static int getoptscmd(int, char **);
8017 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
8018 static int helpcmd(int argc, char **argv);
8020 #if ENABLE_ASH_MATH_SUPPORT
8021 static int letcmd(int, char **);
8023 static int readcmd(int, char **);
8024 static int setcmd(int, char **);
8025 static int shiftcmd(int, char **);
8026 static int timescmd(int, char **);
8027 static int trapcmd(int, char **);
8028 static int umaskcmd(int, char **);
8029 static int unsetcmd(int, char **);
8030 static int ulimitcmd(int, char **);
8032 #define BUILTIN_NOSPEC "0"
8033 #define BUILTIN_SPECIAL "1"
8034 #define BUILTIN_REGULAR "2"
8035 #define BUILTIN_SPEC_REG "3"
8036 #define BUILTIN_ASSIGN "4"
8037 #define BUILTIN_SPEC_ASSG "5"
8038 #define BUILTIN_REG_ASSG "6"
8039 #define BUILTIN_SPEC_REG_ASSG "7"
8041 /* make sure to keep these in proper order since it is searched via bsearch() */
8042 static const struct builtincmd builtintab[] = {
8043 { BUILTIN_SPEC_REG ".", dotcmd },
8044 { BUILTIN_SPEC_REG ":", truecmd },
8045 #if ENABLE_ASH_BUILTIN_TEST
8046 { BUILTIN_REGULAR "[", testcmd },
8047 { BUILTIN_REGULAR "[[", testcmd },
8049 #if ENABLE_ASH_ALIAS
8050 { BUILTIN_REG_ASSG "alias", aliascmd },
8053 { BUILTIN_REGULAR "bg", fg_bgcmd },
8055 { BUILTIN_SPEC_REG "break", breakcmd },
8056 { BUILTIN_REGULAR "cd", cdcmd },
8057 { BUILTIN_NOSPEC "chdir", cdcmd },
8058 #if ENABLE_ASH_CMDCMD
8059 { BUILTIN_REGULAR "command", commandcmd },
8061 { BUILTIN_SPEC_REG "continue", breakcmd },
8062 #if ENABLE_ASH_BUILTIN_ECHO
8063 { BUILTIN_REGULAR "echo", echocmd },
8065 { BUILTIN_SPEC_REG "eval", evalcmd },
8066 { BUILTIN_SPEC_REG "exec", execcmd },
8067 { BUILTIN_SPEC_REG "exit", exitcmd },
8068 { BUILTIN_SPEC_REG_ASSG "export", exportcmd },
8069 { BUILTIN_REGULAR "false", falsecmd },
8071 { BUILTIN_REGULAR "fg", fg_bgcmd },
8073 #if ENABLE_ASH_GETOPTS
8074 { BUILTIN_REGULAR "getopts", getoptscmd },
8076 { BUILTIN_NOSPEC "hash", hashcmd },
8077 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
8078 { BUILTIN_NOSPEC "help", helpcmd },
8081 { BUILTIN_REGULAR "jobs", jobscmd },
8082 { BUILTIN_REGULAR "kill", killcmd },
8084 #if ENABLE_ASH_MATH_SUPPORT
8085 { BUILTIN_NOSPEC "let", letcmd },
8087 { BUILTIN_ASSIGN "local", localcmd },
8088 { BUILTIN_NOSPEC "pwd", pwdcmd },
8089 { BUILTIN_REGULAR "read", readcmd },
8090 { BUILTIN_SPEC_REG_ASSG "readonly", exportcmd },
8091 { BUILTIN_SPEC_REG "return", returncmd },
8092 { BUILTIN_SPEC_REG "set", setcmd },
8093 { BUILTIN_SPEC_REG "shift", shiftcmd },
8094 { BUILTIN_SPEC_REG "source", dotcmd },
8095 #if ENABLE_ASH_BUILTIN_TEST
8096 { BUILTIN_REGULAR "test", testcmd },
8098 { BUILTIN_SPEC_REG "times", timescmd },
8099 { BUILTIN_SPEC_REG "trap", trapcmd },
8100 { BUILTIN_REGULAR "true", truecmd },
8101 { BUILTIN_NOSPEC "type", typecmd },
8102 { BUILTIN_NOSPEC "ulimit", ulimitcmd },
8103 { BUILTIN_REGULAR "umask", umaskcmd },
8104 #if ENABLE_ASH_ALIAS
8105 { BUILTIN_REGULAR "unalias", unaliascmd },
8107 { BUILTIN_SPEC_REG "unset", unsetcmd },
8108 { BUILTIN_REGULAR "wait", waitcmd },
8111 #define NUMBUILTINS (sizeof(builtintab) / sizeof(builtintab[0]))
8113 #define COMMANDCMD (builtintab + 5 + \
8114 2 * ENABLE_ASH_BUILTIN_TEST + \
8115 ENABLE_ASH_ALIAS + \
8116 ENABLE_ASH_JOB_CONTROL)
8117 #define EXECCMD (builtintab + 7 + \
8118 2 * ENABLE_ASH_BUILTIN_TEST + \
8119 ENABLE_ASH_ALIAS + \
8120 ENABLE_ASH_JOB_CONTROL + \
8121 ENABLE_ASH_CMDCMD + \
8122 ENABLE_ASH_BUILTIN_ECHO)
8125 * Search the table of builtin commands.
8127 static struct builtincmd *
8128 find_builtin(const char *name)
8130 struct builtincmd *bp;
8133 name, builtintab, NUMBUILTINS, sizeof(builtintab[0]),
8140 * Execute a simple command.
8142 static int back_exitstatus; /* exit status of backquoted command */
8144 isassignment(const char *p)
8146 const char *q = endofname(p);
8152 bltincmd(int argc, char **argv)
8154 /* Preserve exitstatus of a previous possible redirection
8155 * as POSIX mandates */
8156 return back_exitstatus;
8159 evalcommand(union node *cmd, int flags)
8161 static const struct builtincmd bltin = {
8164 struct stackmark smark;
8166 struct arglist arglist;
8167 struct arglist varlist;
8170 const struct strlist *sp;
8171 struct cmdentry cmdentry;
8179 struct builtincmd *bcmd;
8180 int pseudovarflag = 0;
8182 /* First expand the arguments. */
8183 TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
8184 setstackmark(&smark);
8185 back_exitstatus = 0;
8187 cmdentry.cmdtype = CMDBUILTIN;
8188 cmdentry.u.cmd = &bltin;
8189 varlist.lastp = &varlist.list;
8190 *varlist.lastp = NULL;
8191 arglist.lastp = &arglist.list;
8192 *arglist.lastp = NULL;
8195 if (cmd->ncmd.args) {
8196 bcmd = find_builtin(cmd->ncmd.args->narg.text);
8197 pseudovarflag = bcmd && IS_BUILTIN_ASSIGN(bcmd);
8200 for (argp = cmd->ncmd.args; argp; argp = argp->narg.next) {
8201 struct strlist **spp;
8203 spp = arglist.lastp;
8204 if (pseudovarflag && isassignment(argp->narg.text))
8205 expandarg(argp, &arglist, EXP_VARTILDE);
8207 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
8209 for (sp = *spp; sp; sp = sp->next)
8213 argv = nargv = stalloc(sizeof(char *) * (argc + 1));
8214 for (sp = arglist.list; sp; sp = sp->next) {
8215 TRACE(("evalcommand arg: %s\n", sp->text));
8216 *nargv++ = sp->text;
8221 if (iflag && funcnest == 0 && argc > 0)
8222 lastarg = nargv[-1];
8225 expredir(cmd->ncmd.redirect);
8226 status = redirectsafe(cmd->ncmd.redirect, REDIR_PUSH | REDIR_SAVEFD2);
8229 for (argp = cmd->ncmd.assign; argp; argp = argp->narg.next) {
8230 struct strlist **spp;
8233 spp = varlist.lastp;
8234 expandarg(argp, &varlist, EXP_VARTILDE);
8237 * Modify the command lookup path, if a PATH= assignment
8241 if (varequal(p, path))
8245 /* Print the command if xflag is set. */
8248 const char *p = " %s";
8251 dprintf(preverrout_fd, p, expandstr(ps4val()));
8254 for (n = 0; n < 2; n++) {
8256 dprintf(preverrout_fd, p, sp->text);
8264 full_write(preverrout_fd, "\n", 1);
8270 /* Now locate the command. */
8272 const char *oldpath;
8273 int cmd_flag = DO_ERR;
8278 find_command(argv[0], &cmdentry, cmd_flag, path);
8279 if (cmdentry.cmdtype == CMDUNKNOWN) {
8285 /* implement bltin and command here */
8286 if (cmdentry.cmdtype != CMDBUILTIN)
8289 spclbltin = IS_BUILTIN_SPECIAL(cmdentry.u.cmd);
8290 if (cmdentry.u.cmd == EXECCMD)
8292 #if ENABLE_ASH_CMDCMD
8293 if (cmdentry.u.cmd == COMMANDCMD) {
8295 nargv = parse_command_args(argv, &path);
8298 argc -= nargv - argv;
8300 cmd_flag |= DO_NOFUNC;
8308 /* We have a redirection error. */
8310 raise_exception(EXERROR);
8312 exitstatus = status;
8316 /* Execute the command. */
8317 switch (cmdentry.cmdtype) {
8319 /* Fork off a child process if necessary. */
8320 if (!(flags & EV_EXIT) || trap[0]) {
8322 jp = makejob(cmd, 1);
8323 if (forkshell(jp, cmd, FORK_FG) != 0) {
8324 exitstatus = waitforjob(jp);
8330 listsetvar(varlist.list, VEXPORT|VSTACK);
8331 shellexec(argv, path, cmdentry.u.index);
8335 cmdenviron = varlist.list;
8337 struct strlist *list = cmdenviron;
8339 if (spclbltin > 0 || argc == 0) {
8341 if (cmd_is_exec && argc > 1)
8344 listsetvar(list, i);
8346 if (evalbltin(cmdentry.u.cmd, argc, argv)) {
8361 exit_status = j + 128;
8362 exitstatus = exit_status;
8364 if (i == EXINT || spclbltin > 0) {
8366 longjmp(exception_handler->loc, 1);
8373 listsetvar(varlist.list, 0);
8374 if (evalfun(cmdentry.u.func, argc, argv, flags))
8380 popredir(cmd_is_exec);
8382 /* dsl: I think this is intended to be used to support
8383 * '_' in 'vi' command mode during line editing...
8384 * However I implemented that within libedit itself.
8386 setvar("_", lastarg, 0);
8387 popstackmark(&smark);
8391 evalbltin(const struct builtincmd *cmd, int argc, char **argv)
8393 char *volatile savecmdname;
8394 struct jmploc *volatile savehandler;
8395 struct jmploc jmploc;
8398 savecmdname = commandname;
8399 i = setjmp(jmploc.loc);
8402 savehandler = exception_handler;
8403 exception_handler = &jmploc;
8404 commandname = argv[0];
8406 optptr = NULL; /* initialize nextopt */
8407 exitstatus = (*cmd->builtin)(argc, argv);
8408 flush_stdout_stderr();
8410 exitstatus |= ferror(stdout);
8412 commandname = savecmdname;
8414 exception_handler = savehandler;
8420 goodname(const char *p)
8422 return !*endofname(p);
8427 * Search for a command. This is called before we fork so that the
8428 * location of the command will be available in the parent as well as
8429 * the child. The check for "goodname" is an overly conservative
8430 * check that the name will not be subject to expansion.
8433 prehash(union node *n)
8435 struct cmdentry entry;
8437 if (n->type == NCMD && n->ncmd.args && goodname(n->ncmd.args->narg.text))
8438 find_command(n->ncmd.args->narg.text, &entry, 0, pathval());
8442 /* ============ Builtin commands
8444 * Builtin commands whose functions are closely tied to evaluation
8445 * are implemented here.
8449 * Handle break and continue commands. Break, continue, and return are
8450 * all handled by setting the evalskip flag. The evaluation routines
8451 * above all check this flag, and if it is set they start skipping
8452 * commands rather than executing them. The variable skipcount is
8453 * the number of loops to break/continue, or the number of function
8454 * levels to return. (The latter is always 1.) It should probably
8455 * be an error to break out of more loops than exist, but it isn't
8456 * in the standard shell so we don't make it one here.
8459 breakcmd(int argc, char **argv)
8461 int n = argc > 1 ? number(argv[1]) : 1;
8464 ash_msg_and_raise_error(illnum, argv[1]);
8468 evalskip = (**argv == 'c') ? SKIPCONT : SKIPBREAK;
8475 /* ============ input.c
8477 * This implements the input routines used by the parser.
8480 #define EOF_NLEFT -99 /* value of parsenleft when EOF pushed back */
8483 INPUT_PUSH_FILE = 1,
8484 INPUT_NOFILE_OK = 2,
8488 * NEOF is returned by parsecmd when it encounters an end of file. It
8489 * must be distinct from NULL, so we use the address of a variable that
8490 * happens to be handy.
8492 static int plinno = 1; /* input line number */
8493 /* number of characters left in input buffer */
8494 static int parsenleft; /* copy of parsefile->nleft */
8495 static int parselleft; /* copy of parsefile->lleft */
8496 /* next character in input buffer */
8497 static char *parsenextc; /* copy of parsefile->nextc */
8499 static int checkkwd;
8500 /* values of checkkwd variable */
8501 #define CHKALIAS 0x1
8508 struct strpush *sp = parsefile->strpush;
8511 #if ENABLE_ASH_ALIAS
8513 if (parsenextc[-1] == ' ' || parsenextc[-1] == '\t') {
8514 checkkwd |= CHKALIAS;
8516 if (sp->string != sp->ap->val) {
8519 sp->ap->flag &= ~ALIASINUSE;
8520 if (sp->ap->flag & ALIASDEAD) {
8521 unalias(sp->ap->name);
8525 parsenextc = sp->prevstring;
8526 parsenleft = sp->prevnleft;
8527 /*dprintf("*** calling popstring: restoring to '%s'\n", parsenextc);*/
8528 parsefile->strpush = sp->prev;
8529 if (sp != &(parsefile->basestrpush))
8538 char *buf = parsefile->buf;
8542 #if ENABLE_FEATURE_EDITING
8543 if (!iflag || parsefile->fd)
8544 nr = safe_read(parsefile->fd, buf, BUFSIZ - 1);
8546 #if ENABLE_FEATURE_TAB_COMPLETION
8547 line_input_state->path_lookup = pathval();
8549 nr = read_line_input(cmdedit_prompt, buf, BUFSIZ, line_input_state);
8551 /* Ctrl+C pressed */
8560 if (nr < 0 && errno == 0) {
8561 /* Ctrl+D presend */
8566 nr = safe_read(parsefile->fd, buf, BUFSIZ - 1);
8570 if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
8571 int flags = fcntl(0, F_GETFL, 0);
8572 if (flags >= 0 && flags & O_NONBLOCK) {
8573 flags &=~ O_NONBLOCK;
8574 if (fcntl(0, F_SETFL, flags) >= 0) {
8575 out2str("sh: turning off NDELAY mode\n");
8585 * Refill the input buffer and return the next input character:
8587 * 1) If a string was pushed back on the input, pop it;
8588 * 2) If an EOF was pushed back (parsenleft == EOF_NLEFT) or we are reading
8589 * from a string so we can't refill the buffer, return EOF.
8590 * 3) If the is more stuff in this buffer, use it else call read to fill it.
8591 * 4) Process input up to the next newline, deleting nul characters.
8600 while (parsefile->strpush) {
8601 #if ENABLE_ASH_ALIAS
8602 if (parsenleft == -1 && parsefile->strpush->ap &&
8603 parsenextc[-1] != ' ' && parsenextc[-1] != '\t') {
8608 if (--parsenleft >= 0)
8609 return signed_char2int(*parsenextc++);
8611 if (parsenleft == EOF_NLEFT || parsefile->buf == NULL)
8613 flush_stdout_stderr();
8620 parselleft = parsenleft = EOF_NLEFT;
8627 /* delete nul characters */
8635 memmove(q, q + 1, more);
8639 parsenleft = q - parsenextc - 1;
8645 parsenleft = q - parsenextc - 1;
8657 out2str(parsenextc);
8662 return signed_char2int(*parsenextc++);
8665 #define pgetc_as_macro() (--parsenleft >= 0? signed_char2int(*parsenextc++) : preadbuffer())
8669 return pgetc_as_macro();
8672 #if ENABLE_ASH_OPTIMIZE_FOR_SIZE
8673 #define pgetc_macro() pgetc()
8675 #define pgetc_macro() pgetc_as_macro()
8679 * Same as pgetc(), but ignores PEOA.
8681 #if ENABLE_ASH_ALIAS
8689 } while (c == PEOA);
8696 return pgetc_macro();
8701 * Read a line from the script.
8704 pfgets(char *line, int len)
8710 while (--nleft > 0) {
8726 * Undo the last call to pgetc. Only one character may be pushed back.
8727 * PEOF may be pushed back.
8737 * Push a string back onto the input at this current parsefile level.
8738 * We handle aliases this way.
8741 pushstring(char *s, void *ap)
8748 /*dprintf("*** calling pushstring: %s, %d\n", s, len);*/
8749 if (parsefile->strpush) {
8750 sp = ckmalloc(sizeof(struct strpush));
8751 sp->prev = parsefile->strpush;
8752 parsefile->strpush = sp;
8754 sp = parsefile->strpush = &(parsefile->basestrpush);
8755 sp->prevstring = parsenextc;
8756 sp->prevnleft = parsenleft;
8757 #if ENABLE_ASH_ALIAS
8758 sp->ap = (struct alias *)ap;
8760 ((struct alias *)ap)->flag |= ALIASINUSE;
8770 * To handle the "." command, a stack of input files is used. Pushfile
8771 * adds a new entry to the stack and popfile restores the previous level.
8776 struct parsefile *pf;
8778 parsefile->nleft = parsenleft;
8779 parsefile->lleft = parselleft;
8780 parsefile->nextc = parsenextc;
8781 parsefile->linno = plinno;
8782 pf = ckmalloc(sizeof(*pf));
8783 pf->prev = parsefile;
8786 pf->basestrpush.prev = NULL;
8793 struct parsefile *pf = parsefile;
8802 parsefile = pf->prev;
8804 parsenleft = parsefile->nleft;
8805 parselleft = parsefile->lleft;
8806 parsenextc = parsefile->nextc;
8807 plinno = parsefile->linno;
8812 * Return to top level.
8817 while (parsefile != &basepf)
8822 * Close the file(s) that the shell is reading commands from. Called
8823 * after a fork is done.
8829 if (parsefile->fd > 0) {
8830 close(parsefile->fd);
8836 * Like setinputfile, but takes an open file descriptor. Call this with
8840 setinputfd(int fd, int push)
8842 fcntl(fd, F_SETFD, FD_CLOEXEC);
8848 if (parsefile->buf == NULL)
8849 parsefile->buf = ckmalloc(IBUFSIZ);
8850 parselleft = parsenleft = 0;
8855 * Set the input to take input from a file. If push is set, push the
8856 * old input onto the stack first.
8859 setinputfile(const char *fname, int flags)
8865 fd = open(fname, O_RDONLY);
8867 if (flags & INPUT_NOFILE_OK)
8869 ash_msg_and_raise_error("can't open %s", fname);
8872 fd2 = copyfd(fd, 10);
8875 ash_msg_and_raise_error("out of file descriptors");
8878 setinputfd(fd, flags & INPUT_PUSH_FILE);
8885 * Like setinputfile, but takes input from a string.
8888 setinputstring(char *string)
8892 parsenextc = string;
8893 parsenleft = strlen(string);
8894 parsefile->buf = NULL;
8900 /* ============ mail.c
8902 * Routines to check for mail.
8907 #define MAXMBOXES 10
8909 /* times of mailboxes */
8910 static time_t mailtime[MAXMBOXES];
8911 /* Set if MAIL or MAILPATH is changed. */
8912 static int mail_var_path_changed;
8915 * Print appropriate message(s) if mail has arrived.
8916 * If mail_var_path_changed is set,
8917 * then the value of MAIL has mail_var_path_changed,
8918 * so we just update the values.
8927 struct stackmark smark;
8930 setstackmark(&smark);
8931 mpath = mpathset() ? mpathval() : mailval();
8932 for (mtp = mailtime; mtp < mailtime + MAXMBOXES; mtp++) {
8933 p = padvance(&mpath, nullstr);
8938 for (q = p; *q; q++);
8943 q[-1] = '\0'; /* delete trailing '/' */
8944 if (stat(p, &statb) < 0) {
8948 if (!mail_var_path_changed && statb.st_mtime != *mtp) {
8951 pathopt ? pathopt : "you have mail"
8954 *mtp = statb.st_mtime;
8956 mail_var_path_changed = 0;
8957 popstackmark(&smark);
8961 changemail(const char *val)
8963 mail_var_path_changed++;
8966 #endif /* ASH_MAIL */
8969 /* ============ ??? */
8972 * Set the shell parameters.
8975 setparam(char **argv)
8981 for (nparam = 0; argv[nparam]; nparam++);
8982 ap = newparam = ckmalloc((nparam + 1) * sizeof(*ap));
8984 *ap++ = ckstrdup(*argv++);
8987 freeparam(&shellparam);
8988 shellparam.malloc = 1;
8989 shellparam.nparam = nparam;
8990 shellparam.p = newparam;
8991 #if ENABLE_ASH_GETOPTS
8992 shellparam.optind = 1;
8993 shellparam.optoff = -1;
8998 * Process shell options. The global variable argptr contains a pointer
8999 * to the argument list; we advance it past the options.
9002 minus_o(char *name, int val)
9007 for (i = 0; i < NOPTS; i++) {
9008 if (strcmp(name, optnames(i)) == 0) {
9013 ash_msg_and_raise_error("illegal option -o %s", name);
9015 out1str("Current option settings\n");
9016 for (i = 0; i < NOPTS; i++)
9017 out1fmt("%-16s%s\n", optnames(i),
9018 optlist[i] ? "on" : "off");
9021 setoption(int flag, int val)
9025 for (i = 0; i < NOPTS; i++) {
9026 if (optletters(i) == flag) {
9031 ash_msg_and_raise_error("illegal option -%c", flag);
9035 options(int cmdline)
9043 while ((p = *argptr) != NULL) {
9048 if (p[0] == '\0' || LONE_DASH(p)) {
9050 /* "-" means turn off -x and -v */
9053 /* "--" means reset params */
9054 else if (*argptr == NULL)
9057 break; /* "-" or "--" terminates options */
9059 } else if (c == '+') {
9065 while ((c = *p++) != '\0') {
9066 if (c == 'c' && cmdline) {
9067 minusc = p; /* command is after shell args*/
9068 } else if (c == 'o') {
9069 minus_o(*argptr, val);
9072 } else if (cmdline && (c == '-')) { // long options
9073 if (strcmp(p, "login") == 0)
9084 * The shift builtin command.
9087 shiftcmd(int argc, char **argv)
9094 n = number(argv[1]);
9095 if (n > shellparam.nparam)
9096 ash_msg_and_raise_error("can't shift that many");
9098 shellparam.nparam -= n;
9099 for (ap1 = shellparam.p; --n >= 0; ap1++) {
9100 if (shellparam.malloc)
9104 while ((*ap2++ = *ap1++) != NULL);
9105 #if ENABLE_ASH_GETOPTS
9106 shellparam.optind = 1;
9107 shellparam.optoff = -1;
9114 * POSIX requires that 'set' (but not export or readonly) output the
9115 * variables in lexicographic order - by the locale's collating order (sigh).
9116 * Maybe we could keep them in an ordered balanced binary tree
9117 * instead of hashed lists.
9118 * For now just roll 'em through qsort for printing...
9121 showvars(const char *sep_prefix, int on, int off)
9126 ep = listvars(on, off, &epend);
9127 qsort(ep, epend - ep, sizeof(char *), vpcmp);
9129 sep = *sep_prefix ? " " : sep_prefix;
9131 for (; ep < epend; ep++) {
9135 p = strchrnul(*ep, '=');
9138 q = single_quote(++p);
9139 out1fmt("%s%s%.*s%s\n", sep_prefix, sep, (int)(p - *ep), *ep, q);
9145 * The set command builtin.
9148 setcmd(int argc, char **argv)
9151 return showvars(nullstr, 0, VUNSET);
9155 if (*argptr != NULL) {
9162 #if ENABLE_ASH_RANDOM_SUPPORT
9163 /* Roughly copied from bash.. */
9165 change_random(const char *value)
9167 if (value == NULL) {
9168 /* "get", generate */
9171 rseed = rseed * 1103515245 + 12345;
9172 sprintf(buf, "%d", (unsigned int)((rseed & 32767)));
9173 /* set without recursion */
9174 setvar(vrandom.text, buf, VNOFUNC);
9175 vrandom.flags &= ~VNOFUNC;
9178 rseed = strtoul(value, (char **)NULL, 10);
9183 #if ENABLE_ASH_GETOPTS
9185 getopts(char *optstr, char *optvar, char **optfirst, int *param_optind, int *optoff)
9194 if (*param_optind < 1)
9196 optnext = optfirst + *param_optind - 1;
9198 if (*param_optind <= 1 || *optoff < 0 || strlen(optnext[-1]) < *optoff)
9201 p = optnext[-1] + *optoff;
9202 if (p == NULL || *p == '\0') {
9203 /* Current word is done, advance */
9205 if (p == NULL || *p != '-' || *++p == '\0') {
9212 if (LONE_DASH(p)) /* check for "--" */
9217 for (q = optstr; *q != c; ) {
9219 if (optstr[0] == ':') {
9222 err |= setvarsafe("OPTARG", s, 0);
9224 fprintf(stderr, "Illegal option -%c\n", c);
9235 if (*p == '\0' && (p = *optnext) == NULL) {
9236 if (optstr[0] == ':') {
9239 err |= setvarsafe("OPTARG", s, 0);
9242 fprintf(stderr, "No arg for -%c option\n", c);
9251 err |= setvarsafe("OPTARG", p, 0);
9254 err |= setvarsafe("OPTARG", nullstr, 0);
9256 *optoff = p ? p - *(optnext - 1) : -1;
9257 *param_optind = optnext - optfirst + 1;
9258 fmtstr(s, sizeof(s), "%d", *param_optind);
9259 err |= setvarsafe("OPTIND", s, VNOFUNC);
9262 err |= setvarsafe(optvar, s, 0);
9266 flush_stdout_stderr();
9267 raise_exception(EXERROR);
9273 * The getopts builtin. Shellparam.optnext points to the next argument
9274 * to be processed. Shellparam.optptr points to the next character to
9275 * be processed in the current argument. If shellparam.optnext is NULL,
9276 * then it's the first time getopts has been called.
9279 getoptscmd(int argc, char **argv)
9284 ash_msg_and_raise_error("usage: getopts optstring var [arg]");
9286 optbase = shellparam.p;
9287 if (shellparam.optind > shellparam.nparam + 1) {
9288 shellparam.optind = 1;
9289 shellparam.optoff = -1;
9293 if (shellparam.optind > argc - 2) {
9294 shellparam.optind = 1;
9295 shellparam.optoff = -1;
9299 return getopts(argv[1], argv[2], optbase, &shellparam.optind,
9300 &shellparam.optoff);
9302 #endif /* ASH_GETOPTS */
9305 /* ============ Shell parser */
9307 static int tokpushback; /* last token pushed back */
9308 #define NEOF ((union node *)&tokpushback)
9309 static int parsebackquote; /* nonzero if we are inside backquotes */
9310 static int lasttoken; /* last token read */
9311 static char *wordtext; /* text of last word returned by readtoken */
9312 static struct nodelist *backquotelist;
9313 static union node *redirnode;
9314 static struct heredoc *heredoc;
9315 static int quoteflag; /* set if (part of) last token was quoted */
9317 static void raise_error_syntax(const char *) ATTRIBUTE_NORETURN;
9319 raise_error_syntax(const char *msg)
9321 ash_msg_and_raise_error("syntax error: %s", msg);
9326 * Called when an unexpected token is read during the parse. The argument
9327 * is the token that is expected, or -1 if more than one type of token can
9328 * occur at this point.
9330 static void raise_error_unexpected_syntax(int) ATTRIBUTE_NORETURN;
9332 raise_error_unexpected_syntax(int token)
9337 l = sprintf(msg, "%s unexpected", tokname(lasttoken));
9339 sprintf(msg + l, " (expecting %s)", tokname(token));
9340 raise_error_syntax(msg);
9344 #define EOFMARKLEN 79
9347 struct heredoc *next; /* next here document in list */
9348 union node *here; /* redirection node */
9349 char *eofmark; /* string indicating end of input */
9350 int striptabs; /* if set, strip leading tabs */
9353 static struct heredoc *heredoclist; /* list of here documents to read */
9355 /* parsing is heavily cross-recursive, need these forward decls */
9356 static union node *andor(void);
9357 static union node *pipeline(void);
9358 static union node *parse_command(void);
9359 static void parseheredoc(void);
9360 static char peektoken(void);
9361 static int readtoken(void);
9366 union node *n1, *n2, *n3;
9369 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9370 if (nlflag == 2 && peektoken())
9376 if (tok == TBACKGND) {
9377 if (n2->type == NPIPE) {
9378 n2->npipe.backgnd = 1;
9380 if (n2->type != NREDIR) {
9381 n3 = stalloc(sizeof(struct nredir));
9383 n3->nredir.redirect = NULL;
9386 n2->type = NBACKGND;
9392 n3 = stalloc(sizeof(struct nbinary));
9394 n3->nbinary.ch1 = n1;
9395 n3->nbinary.ch2 = n2;
9411 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9419 pungetc(); /* push back EOF on input */
9423 raise_error_unexpected_syntax(-1);
9433 union node *n1, *n2, *n3;
9441 } else if (t == TOR) {
9447 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9449 n3 = stalloc(sizeof(struct nbinary));
9451 n3->nbinary.ch1 = n1;
9452 n3->nbinary.ch2 = n2;
9460 union node *n1, *n2, *pipenode;
9461 struct nodelist *lp, *prev;
9465 TRACE(("pipeline: entered\n"));
9466 if (readtoken() == TNOT) {
9468 checkkwd = CHKKWD | CHKALIAS;
9471 n1 = parse_command();
9472 if (readtoken() == TPIPE) {
9473 pipenode = stalloc(sizeof(struct npipe));
9474 pipenode->type = NPIPE;
9475 pipenode->npipe.backgnd = 0;
9476 lp = stalloc(sizeof(struct nodelist));
9477 pipenode->npipe.cmdlist = lp;
9481 lp = stalloc(sizeof(struct nodelist));
9482 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9483 lp->n = parse_command();
9485 } while (readtoken() == TPIPE);
9491 n2 = stalloc(sizeof(struct nnot));
9504 n = stalloc(sizeof(struct narg));
9506 n->narg.next = NULL;
9507 n->narg.text = wordtext;
9508 n->narg.backquote = backquotelist;
9513 fixredir(union node *n, const char *text, int err)
9515 TRACE(("Fix redir %s %d\n", text, err));
9517 n->ndup.vname = NULL;
9519 if (isdigit(text[0]) && text[1] == '\0')
9520 n->ndup.dupfd = text[0] - '0';
9521 else if (LONE_DASH(text))
9525 raise_error_syntax("Bad fd number");
9526 n->ndup.vname = makename();
9531 * Returns true if the text contains nothing to expand (no dollar signs
9535 noexpand(char *text)
9541 while ((c = *p++) != '\0') {
9542 if (c == CTLQUOTEMARK)
9546 else if (SIT(c, BASESYNTAX) == CCTL)
9555 union node *n = redirnode;
9557 if (readtoken() != TWORD)
9558 raise_error_unexpected_syntax(-1);
9559 if (n->type == NHERE) {
9560 struct heredoc *here = heredoc;
9566 TRACE(("Here document %d\n", n->type));
9567 if (!noexpand(wordtext) || (i = strlen(wordtext)) == 0 || i > EOFMARKLEN)
9568 raise_error_syntax("Illegal eof marker for << redirection");
9569 rmescapes(wordtext);
9570 here->eofmark = wordtext;
9572 if (heredoclist == NULL)
9575 for (p = heredoclist; p->next; p = p->next);
9578 } else if (n->type == NTOFD || n->type == NFROMFD) {
9579 fixredir(n, wordtext, 0);
9581 n->nfile.fname = makename();
9588 union node *args, **app;
9589 union node *n = NULL;
9590 union node *vars, **vpp;
9591 union node **rpp, *redir;
9601 savecheckkwd = CHKALIAS;
9603 checkkwd = savecheckkwd;
9604 switch (readtoken()) {
9606 n = stalloc(sizeof(struct narg));
9608 n->narg.text = wordtext;
9609 n->narg.backquote = backquotelist;
9610 if (savecheckkwd && isassignment(wordtext)) {
9612 vpp = &n->narg.next;
9615 app = &n->narg.next;
9620 *rpp = n = redirnode;
9621 rpp = &n->nfile.next;
9622 parsefname(); /* read name of redirection file */
9625 if (args && app == &args->narg.next
9628 struct builtincmd *bcmd;
9631 /* We have a function */
9632 if (readtoken() != TRP)
9633 raise_error_unexpected_syntax(TRP);
9634 name = n->narg.text;
9636 || ((bcmd = find_builtin(name)) && IS_BUILTIN_SPECIAL(bcmd))
9638 raise_error_syntax("Bad function name");
9641 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9642 n->narg.next = parse_command();
9655 n = stalloc(sizeof(struct ncmd));
9657 n->ncmd.args = args;
9658 n->ncmd.assign = vars;
9659 n->ncmd.redirect = redir;
9666 union node *n1, *n2;
9667 union node *ap, **app;
9668 union node *cp, **cpp;
9669 union node *redir, **rpp;
9676 switch (readtoken()) {
9678 raise_error_unexpected_syntax(-1);
9681 n1 = stalloc(sizeof(struct nif));
9683 n1->nif.test = list(0);
9684 if (readtoken() != TTHEN)
9685 raise_error_unexpected_syntax(TTHEN);
9686 n1->nif.ifpart = list(0);
9688 while (readtoken() == TELIF) {
9689 n2->nif.elsepart = stalloc(sizeof(struct nif));
9690 n2 = n2->nif.elsepart;
9692 n2->nif.test = list(0);
9693 if (readtoken() != TTHEN)
9694 raise_error_unexpected_syntax(TTHEN);
9695 n2->nif.ifpart = list(0);
9697 if (lasttoken == TELSE)
9698 n2->nif.elsepart = list(0);
9700 n2->nif.elsepart = NULL;
9708 n1 = stalloc(sizeof(struct nbinary));
9709 n1->type = (lasttoken == TWHILE) ? NWHILE : NUNTIL;
9710 n1->nbinary.ch1 = list(0);
9713 TRACE(("expecting DO got %s %s\n", tokname(got),
9714 got == TWORD ? wordtext : ""));
9715 raise_error_unexpected_syntax(TDO);
9717 n1->nbinary.ch2 = list(0);
9722 if (readtoken() != TWORD || quoteflag || ! goodname(wordtext))
9723 raise_error_syntax("Bad for loop variable");
9724 n1 = stalloc(sizeof(struct nfor));
9726 n1->nfor.var = wordtext;
9727 checkkwd = CHKKWD | CHKALIAS;
9728 if (readtoken() == TIN) {
9730 while (readtoken() == TWORD) {
9731 n2 = stalloc(sizeof(struct narg));
9733 n2->narg.text = wordtext;
9734 n2->narg.backquote = backquotelist;
9736 app = &n2->narg.next;
9740 if (lasttoken != TNL && lasttoken != TSEMI)
9741 raise_error_unexpected_syntax(-1);
9743 n2 = stalloc(sizeof(struct narg));
9745 n2->narg.text = (char *)dolatstr;
9746 n2->narg.backquote = NULL;
9747 n2->narg.next = NULL;
9750 * Newline or semicolon here is optional (but note
9751 * that the original Bourne shell only allowed NL).
9753 if (lasttoken != TNL && lasttoken != TSEMI)
9756 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9757 if (readtoken() != TDO)
9758 raise_error_unexpected_syntax(TDO);
9759 n1->nfor.body = list(0);
9763 n1 = stalloc(sizeof(struct ncase));
9765 if (readtoken() != TWORD)
9766 raise_error_unexpected_syntax(TWORD);
9767 n1->ncase.expr = n2 = stalloc(sizeof(struct narg));
9769 n2->narg.text = wordtext;
9770 n2->narg.backquote = backquotelist;
9771 n2->narg.next = NULL;
9773 checkkwd = CHKKWD | CHKALIAS;
9774 } while (readtoken() == TNL);
9775 if (lasttoken != TIN)
9776 raise_error_unexpected_syntax(TIN);
9777 cpp = &n1->ncase.cases;
9779 checkkwd = CHKNL | CHKKWD;
9781 while (t != TESAC) {
9782 if (lasttoken == TLP)
9784 *cpp = cp = stalloc(sizeof(struct nclist));
9786 app = &cp->nclist.pattern;
9788 *app = ap = stalloc(sizeof(struct narg));
9790 ap->narg.text = wordtext;
9791 ap->narg.backquote = backquotelist;
9792 if (readtoken() != TPIPE)
9794 app = &ap->narg.next;
9797 ap->narg.next = NULL;
9798 if (lasttoken != TRP)
9799 raise_error_unexpected_syntax(TRP);
9800 cp->nclist.body = list(2);
9802 cpp = &cp->nclist.next;
9804 checkkwd = CHKNL | CHKKWD;
9808 raise_error_unexpected_syntax(TENDCASE);
9815 n1 = stalloc(sizeof(struct nredir));
9816 n1->type = NSUBSHELL;
9817 n1->nredir.n = list(0);
9818 n1->nredir.redirect = NULL;
9831 if (readtoken() != t)
9832 raise_error_unexpected_syntax(t);
9835 /* Now check for redirection which may follow command */
9836 checkkwd = CHKKWD | CHKALIAS;
9838 while (readtoken() == TREDIR) {
9839 *rpp = n2 = redirnode;
9840 rpp = &n2->nfile.next;
9846 if (n1->type != NSUBSHELL) {
9847 n2 = stalloc(sizeof(struct nredir));
9852 n1->nredir.redirect = redir;
9858 * If eofmark is NULL, read a word or a redirection symbol. If eofmark
9859 * is not NULL, read a here document. In the latter case, eofmark is the
9860 * word which marks the end of the document and striptabs is true if
9861 * leading tabs should be stripped from the document. The argument firstc
9862 * is the first character of the input token or document.
9864 * Because C does not have internal subroutines, I have simulated them
9865 * using goto's to implement the subroutine linkage. The following macros
9866 * will run code that appears at the end of readtoken1.
9869 static int parsebackquote; /* nonzero if we are inside backquotes */
9871 #define CHECKEND() {goto checkend; checkend_return:;}
9872 #define PARSEREDIR() {goto parseredir; parseredir_return:;}
9873 #define PARSESUB() {goto parsesub; parsesub_return:;}
9874 #define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
9875 #define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
9876 #define PARSEARITH() {goto parsearith; parsearith_return:;}
9879 readtoken1(int firstc, int syntax, char *eofmark, int striptabs)
9884 char line[EOFMARKLEN + 1];
9885 struct nodelist *bqlist = 0;
9888 int varnest = 0; /* levels of variables expansion */
9889 int arinest = 0; /* levels of arithmetic expansion */
9890 int parenlevel = 0; /* levels of parens in arithmetic */
9891 int dqvarnest = 0; /* levels of variables expansion within double quotes */
9893 int prevsyntax = 0; /* syntax before arithmetic */
9895 /* Avoid longjmp clobbering */
9908 startlinno = plinno;
9910 if (syntax == DQSYNTAX)
9920 loop: { /* for each line, until end of word */
9921 CHECKEND(); /* set c to PEOF if at end of here document */
9922 for (;;) { /* until end of line or end of word */
9923 CHECKSTRSPACE(4, out); /* permit 4 calls to USTPUTC */
9924 switch (SIT(c, syntax)) {
9925 case CNL: /* '\n' */
9926 if (syntax == BASESYNTAX)
9927 goto endword; /* exit outer loop */
9933 goto loop; /* continue outer loop */
9938 if (eofmark == NULL || dblquote)
9939 USTPUTC(CTLESC, out);
9942 case CBACK: /* backslash */
9945 USTPUTC(CTLESC, out);
9948 } else if (c == '\n') {
9953 c != '\\' && c != '`' &&
9958 USTPUTC(CTLESC, out);
9961 if (SIT(c, SQSYNTAX) == CCTL)
9962 USTPUTC(CTLESC, out);
9970 if (eofmark == NULL) {
9971 USTPUTC(CTLQUOTEMARK, out);
9979 if (eofmark != NULL && arinest == 0
9984 if (dqvarnest == 0) {
9985 syntax = BASESYNTAX;
9992 case CVAR: /* '$' */
9993 PARSESUB(); /* parse substitution */
9995 case CENDVAR: /* '}' */
9998 if (dqvarnest > 0) {
10001 USTPUTC(CTLENDVAR, out);
10006 #if ENABLE_ASH_MATH_SUPPORT
10007 case CLP: /* '(' in arithmetic */
10011 case CRP: /* ')' in arithmetic */
10012 if (parenlevel > 0) {
10016 if (pgetc() == ')') {
10017 if (--arinest == 0) {
10018 USTPUTC(CTLENDARI, out);
10019 syntax = prevsyntax;
10020 if (syntax == DQSYNTAX)
10028 * unbalanced parens
10029 * (don't 2nd guess - no error)
10037 case CBQUOTE: /* '`' */
10041 goto endword; /* exit outer loop */
10046 goto endword; /* exit outer loop */
10047 #if ENABLE_ASH_ALIAS
10057 #if ENABLE_ASH_MATH_SUPPORT
10058 if (syntax == ARISYNTAX)
10059 raise_error_syntax("Missing '))'");
10061 if (syntax != BASESYNTAX && !parsebackquote && eofmark == NULL)
10062 raise_error_syntax("Unterminated quoted string");
10063 if (varnest != 0) {
10064 startlinno = plinno;
10066 raise_error_syntax("Missing '}'");
10068 USTPUTC('\0', out);
10069 len = out - (char *)stackblock();
10070 out = stackblock();
10071 if (eofmark == NULL) {
10072 if ((c == '>' || c == '<')
10075 && (*out == '\0' || isdigit(*out))) {
10077 return lasttoken = TREDIR;
10082 quoteflag = quotef;
10083 backquotelist = bqlist;
10084 grabstackblock(len);
10088 /* end of readtoken routine */
10091 * Check to see whether we are at the end of the here document. When this
10092 * is called, c is set to the first character of the next input line. If
10093 * we are at the end of the here document, this routine sets the c to PEOF.
10097 #if ENABLE_ASH_ALIAS
10103 while (c == '\t') {
10107 if (c == *eofmark) {
10108 if (pfgets(line, sizeof(line)) != NULL) {
10112 for (q = eofmark + 1; *q && *p == *q; p++, q++);
10113 if (*p == '\n' && *q == '\0') {
10116 needprompt = doprompt;
10118 pushstring(line, NULL);
10123 goto checkend_return;
10127 * Parse a redirection operator. The variable "out" points to a string
10128 * specifying the fd to be redirected. The variable "c" contains the
10129 * first character of the redirection operator.
10135 np = stalloc(sizeof(struct nfile));
10140 np->type = NAPPEND;
10142 np->type = NCLOBBER;
10149 } else { /* c == '<' */
10154 if (sizeof(struct nfile) != sizeof(struct nhere)) {
10155 np = stalloc(sizeof(struct nhere));
10159 heredoc = stalloc(sizeof(struct heredoc));
10160 heredoc->here = np;
10163 heredoc->striptabs = 1;
10165 heredoc->striptabs = 0;
10171 np->type = NFROMFD;
10175 np->type = NFROMTO;
10185 np->nfile.fd = fd - '0';
10187 goto parseredir_return;
10191 * Parse a substitution. At this point, we have read the dollar sign
10192 * and nothing else.
10195 /* is_special(c) evaluates to 1 for c in "!#$*-0123456789?@"; 0 otherwise
10196 * (assuming ascii char codes, as the original implementation did) */
10197 #define is_special(c) \
10198 ((((unsigned int)c) - 33 < 32) \
10199 && ((0xc1ff920dUL >> (((unsigned int)c) - 33)) & 1))
10205 static const char types[] = "}-+?=";
10209 c <= PEOA_OR_PEOF ||
10210 (c != '(' && c != '{' && !is_name(c) && !is_special(c))
10214 } else if (c == '(') { /* $(command) or $((arith)) */
10215 if (pgetc() == '(') {
10216 #if ENABLE_ASH_MATH_SUPPORT
10219 raise_error_syntax("We unsupport $((arith))");
10226 USTPUTC(CTLVAR, out);
10227 typeloc = out - (char *)stackblock();
10228 USTPUTC(VSNORMAL, out);
10229 subtype = VSNORMAL;
10237 subtype = VSLENGTH;
10241 if (c > PEOA_OR_PEOF && is_name(c)) {
10245 } while (c > PEOA_OR_PEOF && is_in_name(c));
10246 } else if (isdigit(c)) {
10250 } while (isdigit(c));
10251 } else if (is_special(c)) {
10255 badsub: raise_error_syntax("Bad substitution");
10259 if (subtype == 0) {
10266 p = strchr(types, c);
10269 subtype = p - types + VSNORMAL;
10275 subtype = c == '#' ? VSTRIMLEFT :
10288 if (dblquote || arinest)
10290 *((char *)stackblock() + typeloc) = subtype | flags;
10291 if (subtype != VSNORMAL) {
10293 if (dblquote || arinest) {
10298 goto parsesub_return;
10302 * Called to parse command substitutions. Newstyle is set if the command
10303 * is enclosed inside $(...); nlpp is a pointer to the head of the linked
10304 * list of commands (passed by reference), and savelen is the number of
10305 * characters on the top of the stack which must be preserved.
10308 struct nodelist **nlpp;
10311 char *volatile str;
10312 struct jmploc jmploc;
10313 struct jmploc *volatile savehandler;
10315 int saveprompt = 0;
10317 (void) &saveprompt;
10320 savepbq = parsebackquote;
10321 if (setjmp(jmploc.loc)) {
10324 parsebackquote = 0;
10325 exception_handler = savehandler;
10326 longjmp(exception_handler->loc, 1);
10330 savelen = out - (char *)stackblock();
10332 str = ckmalloc(savelen);
10333 memcpy(str, stackblock(), savelen);
10335 savehandler = exception_handler;
10336 exception_handler = &jmploc;
10339 /* We must read until the closing backquote, giving special
10340 treatment to some slashes, and then push the string and
10341 reread it as input, interpreting it normally. */
10348 STARTSTACKSTR(pout);
10365 * If eating a newline, avoid putting
10366 * the newline into the new character
10367 * stream (via the STPUTC after the
10372 if (pc != '\\' && pc != '`' && pc != '$'
10373 && (!dblquote || pc != '"'))
10374 STPUTC('\\', pout);
10375 if (pc > PEOA_OR_PEOF) {
10381 #if ENABLE_ASH_ALIAS
10384 startlinno = plinno;
10385 raise_error_syntax("EOF in backquote substitution");
10389 needprompt = doprompt;
10398 STPUTC('\0', pout);
10399 psavelen = pout - (char *)stackblock();
10400 if (psavelen > 0) {
10401 pstr = grabstackstr(pout);
10402 setinputstring(pstr);
10407 nlpp = &(*nlpp)->next;
10408 *nlpp = stalloc(sizeof(**nlpp));
10409 (*nlpp)->next = NULL;
10410 parsebackquote = oldstyle;
10413 saveprompt = doprompt;
10420 doprompt = saveprompt;
10421 else if (readtoken() != TRP)
10422 raise_error_unexpected_syntax(TRP);
10427 * Start reading from old file again, ignoring any pushed back
10428 * tokens left from the backquote parsing
10433 while (stackblocksize() <= savelen)
10435 STARTSTACKSTR(out);
10437 memcpy(out, str, savelen);
10438 STADJUST(savelen, out);
10444 parsebackquote = savepbq;
10445 exception_handler = savehandler;
10446 if (arinest || dblquote)
10447 USTPUTC(CTLBACKQ | CTLQUOTE, out);
10449 USTPUTC(CTLBACKQ, out);
10451 goto parsebackq_oldreturn;
10452 goto parsebackq_newreturn;
10455 #if ENABLE_ASH_MATH_SUPPORT
10457 * Parse an arithmetic expansion (indicate start of one and set state)
10460 if (++arinest == 1) {
10461 prevsyntax = syntax;
10462 syntax = ARISYNTAX;
10463 USTPUTC(CTLARI, out);
10470 * we collapse embedded arithmetic expansion to
10471 * parenthesis, which should be equivalent
10475 goto parsearith_return;
10479 } /* end of readtoken */
10482 * Read the next input token.
10483 * If the token is a word, we set backquotelist to the list of cmds in
10484 * backquotes. We set quoteflag to true if any part of the word was
10486 * If the token is TREDIR, then we set redirnode to a structure containing
10488 * In all cases, the variable startlinno is set to the number of the line
10489 * on which the token starts.
10491 * [Change comment: here documents and internal procedures]
10492 * [Readtoken shouldn't have any arguments. Perhaps we should make the
10493 * word parsing code into a separate routine. In this case, readtoken
10494 * doesn't need to have any internal procedures, but parseword does.
10495 * We could also make parseoperator in essence the main routine, and
10496 * have parseword (readtoken1?) handle both words and redirection.]
10498 #define NEW_xxreadtoken
10499 #ifdef NEW_xxreadtoken
10500 /* singles must be first! */
10501 static const char xxreadtoken_chars[7] = { '\n', '(', ')', '&', '|', ';', 0 };
10503 static const char xxreadtoken_tokens[] = {
10504 TNL, TLP, TRP, /* only single occurrence allowed */
10505 TBACKGND, TPIPE, TSEMI, /* if single occurrence */
10506 TEOF, /* corresponds to trailing nul */
10507 TAND, TOR, TENDCASE, /* if double occurrence */
10510 #define xxreadtoken_doubles \
10511 (sizeof(xxreadtoken_tokens) - sizeof(xxreadtoken_chars))
10512 #define xxreadtoken_singles \
10513 (sizeof(xxreadtoken_chars) - xxreadtoken_doubles - 1)
10527 startlinno = plinno;
10528 for (;;) { /* until token or start of word found */
10531 if ((c != ' ') && (c != '\t')
10532 #if ENABLE_ASH_ALIAS
10537 while ((c = pgetc()) != '\n' && c != PEOF);
10539 } else if (c == '\\') {
10540 if (pgetc() != '\n') {
10544 startlinno = ++plinno;
10549 = xxreadtoken_chars + sizeof(xxreadtoken_chars) - 1;
10554 needprompt = doprompt;
10557 p = strchr(xxreadtoken_chars, c);
10560 return readtoken1(c, BASESYNTAX, (char *) NULL, 0);
10563 if (p - xxreadtoken_chars >= xxreadtoken_singles) {
10564 if (pgetc() == *p) { /* double occurrence? */
10565 p += xxreadtoken_doubles + 1;
10571 return lasttoken = xxreadtoken_tokens[p - xxreadtoken_chars];
10577 #define RETURN(token) return lasttoken = token
10590 startlinno = plinno;
10591 for (;;) { /* until token or start of word found */
10594 case ' ': case '\t':
10595 #if ENABLE_ASH_ALIAS
10600 while ((c = pgetc()) != '\n' && c != PEOF);
10604 if (pgetc() == '\n') {
10605 startlinno = ++plinno;
10614 needprompt = doprompt;
10619 if (pgetc() == '&')
10624 if (pgetc() == '|')
10629 if (pgetc() == ';')
10642 return readtoken1(c, BASESYNTAX, (char *)NULL, 0);
10645 #endif /* NEW_xxreadtoken */
10652 int alreadyseen = tokpushback;
10655 #if ENABLE_ASH_ALIAS
10664 if (checkkwd & CHKNL) {
10671 if (t != TWORD || quoteflag) {
10676 * check for keywords
10678 if (checkkwd & CHKKWD) {
10679 const char *const *pp;
10681 pp = findkwd(wordtext);
10683 lasttoken = t = pp - tokname_array;
10684 TRACE(("keyword %s recognized\n", tokname(t)));
10689 if (checkkwd & CHKALIAS) {
10690 #if ENABLE_ASH_ALIAS
10692 ap = lookupalias(wordtext, 1);
10695 pushstring(ap->val, ap);
10705 TRACE(("token %s %s\n", tokname(t), t == TWORD ? wordtext : ""));
10707 TRACE(("reread token %s %s\n", tokname(t), t == TWORD ? wordtext : ""));
10719 return tokname_array[t][0];
10723 * Read and parse a command. Returns NEOF on end of file. (NULL is a
10724 * valid parse tree indicating a blank line.)
10726 static union node *
10727 parsecmd(int interact)
10732 doprompt = interact;
10734 setprompt(doprompt);
10746 * Input any here documents.
10751 struct heredoc *here;
10754 here = heredoclist;
10761 readtoken1(pgetc(), here->here->type == NHERE? SQSYNTAX : DQSYNTAX,
10762 here->eofmark, here->striptabs);
10763 n = stalloc(sizeof(struct narg));
10764 n->narg.type = NARG;
10765 n->narg.next = NULL;
10766 n->narg.text = wordtext;
10767 n->narg.backquote = backquotelist;
10768 here->here->nhere.doc = n;
10775 * called by editline -- any expansions to the prompt should be added here.
10777 #if ENABLE_ASH_EXPAND_PRMT
10778 static const char *
10779 expandstr(const char *ps)
10783 /* XXX Fix (char *) cast. */
10784 setinputstring((char *)ps);
10785 readtoken1(pgetc(), DQSYNTAX, nullstr, 0);
10788 n.narg.type = NARG;
10789 n.narg.next = NULL;
10790 n.narg.text = wordtext;
10791 n.narg.backquote = backquotelist;
10793 expandarg(&n, NULL, 0);
10794 return stackblock();
10799 * Execute a command or commands contained in a string.
10802 evalstring(char *s, int mask)
10805 struct stackmark smark;
10809 setstackmark(&smark);
10812 while ((n = parsecmd(0)) != NEOF) {
10814 popstackmark(&smark);
10827 * The eval command.
10830 evalcmd(int argc, char **argv)
10839 STARTSTACKSTR(concat);
10842 concat = stack_putstr(p, concat);
10846 STPUTC(' ', concat);
10848 STPUTC('\0', concat);
10849 p = grabstackstr(concat);
10851 evalstring(p, ~SKIPEVAL);
10858 * Read and execute commands. "Top" is nonzero for the top level command
10859 * loop; it turns on prompting if the shell is interactive.
10865 struct stackmark smark;
10869 TRACE(("cmdloop(%d) called\n", top));
10873 setstackmark(&smark);
10876 showjobs(stderr, SHOW_CHANGED);
10879 if (iflag && top) {
10881 #if ENABLE_ASH_MAIL
10885 n = parsecmd(inter);
10886 /* showtree(n); DEBUG */
10888 if (!top || numeof >= 50)
10890 if (!stoppedjobs()) {
10893 out2str("\nUse \"exit\" to leave shell.\n");
10896 } else if (nflag == 0) {
10897 job_warning = (job_warning == 2) ? 1 : 0;
10901 popstackmark(&smark);
10906 return skip & SKIPEVAL;
10913 * Take commands from a file. To be compatible we should do a path
10914 * search for the file, which is necessary to find sub-commands.
10917 find_dot_file(char *name)
10920 const char *path = pathval();
10923 /* don't try this for absolute or relative paths */
10924 if (strchr(name, '/'))
10927 while ((fullname = padvance(&path, name)) != NULL) {
10928 if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) {
10930 * Don't bother freeing here, since it will
10931 * be freed by the caller.
10935 stunalloc(fullname);
10938 /* not found in the PATH */
10939 ash_msg_and_raise_error("%s: not found", name);
10944 dotcmd(int argc, char **argv)
10946 struct strlist *sp;
10947 volatile struct shparam saveparam;
10950 for (sp = cmdenviron; sp; sp = sp->next)
10951 setvareq(ckstrdup(sp->text), VSTRFIXED | VTEXTFIXED);
10953 if (argc >= 2) { /* That's what SVR2 does */
10956 fullname = find_dot_file(argv[1]);
10959 saveparam = shellparam;
10960 shellparam.malloc = 0;
10961 shellparam.nparam = argc - 2;
10962 shellparam.p = argv + 2;
10965 setinputfile(fullname, INPUT_PUSH_FILE);
10966 commandname = fullname;
10971 freeparam(&shellparam);
10972 shellparam = saveparam;
10974 status = exitstatus;
10980 exitcmd(int argc, char **argv)
10985 exitstatus = number(argv[1]);
10986 raise_exception(EXEXIT);
10990 #if ENABLE_ASH_BUILTIN_ECHO
10992 echocmd(int argc, char **argv)
10994 return bb_echo(argv);
10998 #if ENABLE_ASH_BUILTIN_TEST
11000 testcmd(int argc, char **argv)
11002 return bb_test(argc, argv);
11007 * Read a file containing shell functions.
11010 readcmdfile(char *name)
11012 setinputfile(name, INPUT_PUSH_FILE);
11018 /* ============ find_command inplementation */
11021 * Resolve a command name. If you change this routine, you may have to
11022 * change the shellexec routine as well.
11025 find_command(char *name, struct cmdentry *entry, int act, const char *path)
11027 struct tblentry *cmdp;
11034 struct builtincmd *bcmd;
11036 /* If name contains a slash, don't use PATH or hash table */
11037 if (strchr(name, '/') != NULL) {
11038 entry->u.index = -1;
11039 if (act & DO_ABS) {
11040 while (stat(name, &statb) < 0) {
11042 if (errno == EINTR)
11045 entry->cmdtype = CMDUNKNOWN;
11049 entry->cmdtype = CMDNORMAL;
11053 /* #if ENABLE_FEATURE_SH_STANDALONE... moved after builtin check */
11055 updatetbl = (path == pathval());
11058 if (strstr(path, "%builtin") != NULL)
11059 act |= DO_ALTBLTIN;
11062 /* If name is in the table, check answer will be ok */
11063 cmdp = cmdlookup(name, 0);
11064 if (cmdp != NULL) {
11067 switch (cmdp->cmdtype) {
11085 } else if (cmdp->rehash == 0)
11086 /* if not invalidated by cd, we're done */
11090 /* If %builtin not in path, check for builtin next */
11091 bcmd = find_builtin(name);
11093 if (IS_BUILTIN_REGULAR(bcmd))
11094 goto builtin_success;
11095 if (act & DO_ALTPATH) {
11096 if (!(act & DO_ALTBLTIN))
11097 goto builtin_success;
11098 } else if (builtinloc <= 0) {
11099 goto builtin_success;
11103 #if ENABLE_FEATURE_SH_STANDALONE
11104 if (find_applet_by_name(name)) {
11105 entry->cmdtype = CMDNORMAL;
11106 entry->u.index = -1;
11111 /* We have to search path. */
11112 prev = -1; /* where to start */
11113 if (cmdp && cmdp->rehash) { /* doing a rehash */
11114 if (cmdp->cmdtype == CMDBUILTIN)
11117 prev = cmdp->param.index;
11123 while ((fullname = padvance(&path, name)) != NULL) {
11124 stunalloc(fullname);
11127 if (prefix(pathopt, "builtin")) {
11129 goto builtin_success;
11131 } else if (!(act & DO_NOFUNC) &&
11132 prefix(pathopt, "func")) {
11133 /* handled below */
11135 /* ignore unimplemented options */
11139 /* if rehash, don't redo absolute path names */
11140 if (fullname[0] == '/' && idx <= prev) {
11143 TRACE(("searchexec \"%s\": no change\n", name));
11146 while (stat(fullname, &statb) < 0) {
11148 if (errno == EINTR)
11151 if (errno != ENOENT && errno != ENOTDIR)
11155 e = EACCES; /* if we fail, this will be the error */
11156 if (!S_ISREG(statb.st_mode))
11158 if (pathopt) { /* this is a %func directory */
11159 stalloc(strlen(fullname) + 1);
11160 readcmdfile(fullname);
11161 cmdp = cmdlookup(name, 0);
11162 if (cmdp == NULL || cmdp->cmdtype != CMDFUNCTION)
11163 ash_msg_and_raise_error("%s not defined in %s", name, fullname);
11164 stunalloc(fullname);
11167 TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
11169 entry->cmdtype = CMDNORMAL;
11170 entry->u.index = idx;
11174 cmdp = cmdlookup(name, 1);
11175 cmdp->cmdtype = CMDNORMAL;
11176 cmdp->param.index = idx;
11181 /* We failed. If there was an entry for this command, delete it */
11182 if (cmdp && updatetbl)
11183 delete_cmd_entry();
11185 ash_msg("%s: %s", name, errmsg(e, "not found"));
11186 entry->cmdtype = CMDUNKNOWN;
11191 entry->cmdtype = CMDBUILTIN;
11192 entry->u.cmd = bcmd;
11196 cmdp = cmdlookup(name, 1);
11197 cmdp->cmdtype = CMDBUILTIN;
11198 cmdp->param.cmd = bcmd;
11202 entry->cmdtype = cmdp->cmdtype;
11203 entry->u = cmdp->param;
11207 /* ============ trap.c */
11210 * The trap builtin.
11213 trapcmd(int argc, char **argv)
11222 for (signo = 0; signo < NSIG; signo++) {
11223 if (trap[signo] != NULL) {
11226 sn = get_signame(signo);
11227 out1fmt("trap -- %s %s\n",
11228 single_quote(trap[signo]), sn);
11238 signo = get_signum(*ap);
11240 ash_msg_and_raise_error("%s: bad trap", *ap);
11243 if (LONE_DASH(action))
11246 action = ckstrdup(action);
11250 trap[signo] = action;
11260 /* ============ Builtins */
11262 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
11264 * Lists available builtins
11267 helpcmd(int argc, char **argv)
11271 out1fmt("\nBuilt-in commands:\n-------------------\n");
11272 for (col = 0, i = 0; i < NUMBUILTINS; i++) {
11273 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '),
11274 builtintab[i].name + 1);
11280 #if ENABLE_FEATURE_SH_STANDALONE
11281 for (i = 0; i < NUM_APPLETS; i++) {
11282 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '), applets[i].name);
11290 return EXIT_SUCCESS;
11292 #endif /* FEATURE_SH_EXTRA_QUIET */
11295 * The export and readonly commands.
11298 exportcmd(int argc, char **argv)
11304 int flag = argv[0][0] == 'r'? VREADONLY : VEXPORT;
11306 if (nextopt("p") != 'p') {
11311 p = strchr(name, '=');
11315 vp = *findvar(hashvar(name), name);
11321 setvar(name, p, flag);
11322 } while ((name = *++aptr) != NULL);
11326 showvars(argv[0], flag, 0);
11331 * Delete a function if it exists.
11334 unsetfunc(const char *name)
11336 struct tblentry *cmdp;
11338 cmdp = cmdlookup(name, 0);
11339 if (cmdp!= NULL && cmdp->cmdtype == CMDFUNCTION)
11340 delete_cmd_entry();
11344 * The unset builtin command. We unset the function before we unset the
11345 * variable to allow a function to be unset when there is a readonly variable
11346 * with the same name.
11349 unsetcmd(int argc, char **argv)
11356 while ((i = nextopt("vf")) != '\0') {
11360 for (ap = argptr; *ap; ap++) {
11376 #include <sys/times.h>
11378 static const unsigned char timescmd_str[] = {
11379 ' ', offsetof(struct tms, tms_utime),
11380 '\n', offsetof(struct tms, tms_stime),
11381 ' ', offsetof(struct tms, tms_cutime),
11382 '\n', offsetof(struct tms, tms_cstime),
11387 timescmd(int ac, char **av)
11389 long clk_tck, s, t;
11390 const unsigned char *p;
11393 clk_tck = sysconf(_SC_CLK_TCK);
11398 t = *(clock_t *)(((char *) &buf) + p[1]);
11400 out1fmt("%ldm%ld.%.3lds%c",
11402 ((t - s * clk_tck) * 1000) / clk_tck,
11404 } while (*(p += 2));
11409 #if ENABLE_ASH_MATH_SUPPORT
11411 dash_arith(const char *s)
11417 result = arith(s, &errcode);
11420 ash_msg_and_raise_error("exponent less than 0");
11422 ash_msg_and_raise_error("divide by zero");
11424 ash_msg_and_raise_error("expression recursion loop detected");
11425 raise_error_syntax(s);
11433 * The let builtin. partial stolen from GNU Bash, the Bourne Again SHell.
11434 * Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
11436 * Copyright (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
11439 letcmd(int argc, char **argv)
11446 ash_msg_and_raise_error("expression expected");
11447 for (ap = argv + 1; *ap; ap++) {
11448 i = dash_arith(*ap);
11453 #endif /* ASH_MATH_SUPPORT */
11456 /* ============ miscbltin.c
11458 * Miscellaneous builtins.
11463 #if defined(__GLIBC__) && __GLIBC__ == 2 && __GLIBC_MINOR__ < 1
11464 typedef enum __rlimit_resource rlim_t;
11468 * The read builtin. The -e option causes backslashes to escape the
11469 * following character.
11471 * This uses unbuffered input, which may be avoidable in some cases.
11474 readcmd(int argc, char **argv)
11486 #if ENABLE_ASH_READ_NCHARS
11490 struct termios tty, old_tty;
11492 #if ENABLE_ASH_READ_TIMEOUT
11496 ts.tv_sec = ts.tv_usec = 0;
11501 #if ENABLE_ASH_READ_NCHARS && ENABLE_ASH_READ_TIMEOUT
11502 while ((i = nextopt("p:rt:n:s")) != '\0')
11503 #elif ENABLE_ASH_READ_NCHARS
11504 while ((i = nextopt("p:rn:s")) != '\0')
11505 #elif ENABLE_ASH_READ_TIMEOUT
11506 while ((i = nextopt("p:rt:")) != '\0')
11508 while ((i = nextopt("p:r")) != '\0')
11513 prompt = optionarg;
11515 #if ENABLE_ASH_READ_NCHARS
11517 nchars = strtol(optionarg, &p, 10);
11519 ash_msg_and_raise_error("invalid count");
11520 nch_flag = (nchars > 0);
11526 #if ENABLE_ASH_READ_TIMEOUT
11528 ts.tv_sec = strtol(optionarg, &p, 10);
11534 ts.tv_usec = strtol(p, &p2, 10);
11536 ash_msg_and_raise_error("invalid timeout");
11538 /* normalize to usec */
11540 ash_msg_and_raise_error("invalid timeout");
11541 while (scale++ < 6)
11545 ash_msg_and_raise_error("invalid timeout");
11547 if ( ! ts.tv_sec && ! ts.tv_usec)
11548 ash_msg_and_raise_error("invalid timeout");
11558 if (prompt && isatty(0)) {
11563 ash_msg_and_raise_error("arg count");
11564 ifs = bltinlookup("IFS");
11567 #if ENABLE_ASH_READ_NCHARS
11568 if (nch_flag || silent) {
11569 tcgetattr(0, &tty);
11572 tty.c_lflag &= ~ICANON;
11573 tty.c_cc[VMIN] = nchars;
11576 tty.c_lflag &= ~(ECHO|ECHOK|ECHONL);
11579 tcsetattr(0, TCSANOW, &tty);
11582 #if ENABLE_ASH_READ_TIMEOUT
11583 if (ts.tv_sec || ts.tv_usec) {
11587 i = select(FD_SETSIZE, &set, NULL, NULL, &ts);
11589 #if ENABLE_ASH_READ_NCHARS
11591 tcsetattr(0, TCSANOW, &old_tty);
11601 #if ENABLE_ASH_READ_NCHARS
11602 while (!nch_flag || nchars--)
11607 if (read(0, &c, 1) != 1) {
11619 if (!rflag && c == '\\') {
11625 if (startword && *ifs == ' ' && strchr(ifs, c)) {
11629 if (ap[1] != NULL && strchr(ifs, c) != NULL) {
11631 setvar(*ap, stackblock(), 0);
11640 #if ENABLE_ASH_READ_NCHARS
11641 if (nch_flag || silent)
11642 tcsetattr(0, TCSANOW, &old_tty);
11646 /* Remove trailing blanks */
11647 while ((char *)stackblock() <= --p && strchr(ifs, *p) != NULL)
11649 setvar(*ap, stackblock(), 0);
11650 while (*++ap != NULL)
11651 setvar(*ap, nullstr, 0);
11656 umaskcmd(int argc, char **argv)
11658 static const char permuser[3] = "ugo";
11659 static const char permmode[3] = "rwx";
11660 static const short int permmask[] = {
11661 S_IRUSR, S_IWUSR, S_IXUSR,
11662 S_IRGRP, S_IWGRP, S_IXGRP,
11663 S_IROTH, S_IWOTH, S_IXOTH
11669 int symbolic_mode = 0;
11671 while (nextopt("S") != '\0') {
11682 if (symbolic_mode) {
11686 for (i = 0; i < 3; i++) {
11689 *p++ = permuser[i];
11691 for (j = 0; j < 3; j++) {
11692 if ((mask & permmask[3 * i + j]) == 0) {
11693 *p++ = permmode[j];
11701 out1fmt("%.4o\n", mask);
11704 if (isdigit((unsigned char) *ap)) {
11707 if (*ap >= '8' || *ap < '0')
11708 ash_msg_and_raise_error(illnum, argv[1]);
11709 mask = (mask << 3) + (*ap - '0');
11710 } while (*++ap != '\0');
11713 mask = ~mask & 0777;
11714 if (!bb_parse_mode(ap, &mask)) {
11715 ash_msg_and_raise_error("illegal mode: %s", ap);
11717 umask(~mask & 0777);
11726 * This code, originally by Doug Gwyn, Doug Kingston, Eric Gisin, and
11727 * Michael Rendell was ripped from pdksh 5.0.8 and hacked for use with
11728 * ash by J.T. Conklin.
11736 int factor; /* multiply by to get rlim_{cur,max} values */
11740 static const struct limits limits[] = {
11742 { "time(seconds)", RLIMIT_CPU, 1, 't' },
11744 #ifdef RLIMIT_FSIZE
11745 { "file(blocks)", RLIMIT_FSIZE, 512, 'f' },
11748 { "data(kbytes)", RLIMIT_DATA, 1024, 'd' },
11750 #ifdef RLIMIT_STACK
11751 { "stack(kbytes)", RLIMIT_STACK, 1024, 's' },
11754 { "coredump(blocks)", RLIMIT_CORE, 512, 'c' },
11757 { "memory(kbytes)", RLIMIT_RSS, 1024, 'm' },
11759 #ifdef RLIMIT_MEMLOCK
11760 { "locked memory(kbytes)", RLIMIT_MEMLOCK, 1024, 'l' },
11762 #ifdef RLIMIT_NPROC
11763 { "process", RLIMIT_NPROC, 1, 'p' },
11765 #ifdef RLIMIT_NOFILE
11766 { "nofiles", RLIMIT_NOFILE, 1, 'n' },
11769 { "vmemory(kbytes)", RLIMIT_AS, 1024, 'v' },
11771 #ifdef RLIMIT_LOCKS
11772 { "locks", RLIMIT_LOCKS, 1, 'w' },
11774 { NULL, 0, 0, '\0' }
11777 enum limtype { SOFT = 0x1, HARD = 0x2 };
11780 printlim(enum limtype how, const struct rlimit *limit,
11781 const struct limits *l)
11785 val = limit->rlim_max;
11787 val = limit->rlim_cur;
11789 if (val == RLIM_INFINITY)
11790 out1fmt("unlimited\n");
11793 out1fmt("%lld\n", (long long) val);
11798 ulimitcmd(int argc, char **argv)
11802 enum limtype how = SOFT | HARD;
11803 const struct limits *l;
11806 struct rlimit limit;
11809 while ((optc = nextopt("HSa"
11813 #ifdef RLIMIT_FSIZE
11819 #ifdef RLIMIT_STACK
11828 #ifdef RLIMIT_MEMLOCK
11831 #ifdef RLIMIT_NPROC
11834 #ifdef RLIMIT_NOFILE
11840 #ifdef RLIMIT_LOCKS
11858 for (l = limits; l->option != what; l++)
11861 set = *argptr ? 1 : 0;
11865 if (all || argptr[1])
11866 ash_msg_and_raise_error("too many arguments");
11867 if (strncmp(p, "unlimited\n", 9) == 0)
11868 val = RLIM_INFINITY;
11872 while ((c = *p++) >= '0' && c <= '9') {
11873 val = (val * 10) + (long)(c - '0');
11874 if (val < (rlim_t) 0)
11878 ash_msg_and_raise_error("bad number");
11883 for (l = limits; l->name; l++) {
11884 getrlimit(l->cmd, &limit);
11885 out1fmt("%-20s ", l->name);
11886 printlim(how, &limit, l);
11891 getrlimit(l->cmd, &limit);
11894 limit.rlim_max = val;
11896 limit.rlim_cur = val;
11897 if (setrlimit(l->cmd, &limit) < 0)
11898 ash_msg_and_raise_error("error setting limit (%m)");
11900 printlim(how, &limit, l);
11906 /* ============ Math support */
11908 #if ENABLE_ASH_MATH_SUPPORT
11910 /* Copyright (c) 2001 Aaron Lehmann <aaronl@vitelus.com>
11912 Permission is hereby granted, free of charge, to any person obtaining
11913 a copy of this software and associated documentation files (the
11914 "Software"), to deal in the Software without restriction, including
11915 without limitation the rights to use, copy, modify, merge, publish,
11916 distribute, sublicense, and/or sell copies of the Software, and to
11917 permit persons to whom the Software is furnished to do so, subject to
11918 the following conditions:
11920 The above copyright notice and this permission notice shall be
11921 included in all copies or substantial portions of the Software.
11923 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
11924 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
11925 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
11926 IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
11927 CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
11928 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
11929 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
11932 /* This is my infix parser/evaluator. It is optimized for size, intended
11933 * as a replacement for yacc-based parsers. However, it may well be faster
11934 * than a comparable parser written in yacc. The supported operators are
11935 * listed in #defines below. Parens, order of operations, and error handling
11936 * are supported. This code is thread safe. The exact expression format should
11937 * be that which POSIX specifies for shells. */
11939 /* The code uses a simple two-stack algorithm. See
11940 * http://www.onthenet.com.au/~grahamis/int2008/week02/lect02.html
11941 * for a detailed explanation of the infix-to-postfix algorithm on which
11942 * this is based (this code differs in that it applies operators immediately
11943 * to the stack instead of adding them to a queue to end up with an
11946 /* To use the routine, call it with an expression string and error return
11950 * Aug 24, 2001 Manuel Novoa III
11952 * Reduced the generated code size by about 30% (i386) and fixed several bugs.
11954 * 1) In arith_apply():
11955 * a) Cached values of *numptr and &(numptr[-1]).
11956 * b) Removed redundant test for zero denominator.
11959 * a) Eliminated redundant code for processing operator tokens by moving
11960 * to a table-based implementation. Also folded handling of parens
11962 * b) Combined all 3 loops which called arith_apply to reduce generated
11963 * code size at the cost of speed.
11965 * 3) The following expressions were treated as valid by the original code:
11966 * 1() , 0! , 1 ( *3 ) .
11967 * These bugs have been fixed by internally enclosing the expression in
11968 * parens and then checking that all binary ops and right parens are
11969 * preceded by a valid expression (NUM_TOKEN).
11971 * Note: It may be desirable to replace Aaron's test for whitespace with
11972 * ctype's isspace() if it is used by another busybox applet or if additional
11973 * whitespace chars should be considered. Look below the "#include"s for a
11974 * precompiler test.
11978 * Aug 26, 2001 Manuel Novoa III
11980 * Return 0 for null expressions. Pointed out by Vladimir Oleynik.
11982 * Merge in Aaron's comments previously posted to the busybox list,
11983 * modified slightly to take account of my changes to the code.
11988 * (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
11990 * - allow access to variable,
11991 * used recursive find value indirection (c=2*2; a="c"; $((a+=2)) produce 6)
11992 * - realize assign syntax (VAR=expr, +=, *= etc)
11993 * - realize exponentiation (** operator)
11994 * - realize comma separated - expr, expr
11995 * - realise ++expr --expr expr++ expr--
11996 * - realise expr ? expr : expr (but, second expr calculate always)
11997 * - allow hexadecimal and octal numbers
11998 * - was restored loses XOR operator
11999 * - remove one goto label, added three ;-)
12000 * - protect $((num num)) as true zero expr (Manuel`s error)
12001 * - always use special isspace(), see comment from bash ;-)
12004 #define arith_isspace(arithval) \
12005 (arithval == ' ' || arithval == '\n' || arithval == '\t')
12007 typedef unsigned char operator;
12009 /* An operator's token id is a bit of a bitfield. The lower 5 bits are the
12010 * precedence, and 3 high bits are an ID unique across operators of that
12011 * precedence. The ID portion is so that multiple operators can have the
12012 * same precedence, ensuring that the leftmost one is evaluated first.
12013 * Consider * and /. */
12015 #define tok_decl(prec,id) (((id)<<5)|(prec))
12016 #define PREC(op) ((op) & 0x1F)
12018 #define TOK_LPAREN tok_decl(0,0)
12020 #define TOK_COMMA tok_decl(1,0)
12022 #define TOK_ASSIGN tok_decl(2,0)
12023 #define TOK_AND_ASSIGN tok_decl(2,1)
12024 #define TOK_OR_ASSIGN tok_decl(2,2)
12025 #define TOK_XOR_ASSIGN tok_decl(2,3)
12026 #define TOK_PLUS_ASSIGN tok_decl(2,4)
12027 #define TOK_MINUS_ASSIGN tok_decl(2,5)
12028 #define TOK_LSHIFT_ASSIGN tok_decl(2,6)
12029 #define TOK_RSHIFT_ASSIGN tok_decl(2,7)
12031 #define TOK_MUL_ASSIGN tok_decl(3,0)
12032 #define TOK_DIV_ASSIGN tok_decl(3,1)
12033 #define TOK_REM_ASSIGN tok_decl(3,2)
12035 /* all assign is right associativity and precedence eq, but (7+3)<<5 > 256 */
12036 #define convert_prec_is_assing(prec) do { if (prec == 3) prec = 2; } while (0)
12038 /* conditional is right associativity too */
12039 #define TOK_CONDITIONAL tok_decl(4,0)
12040 #define TOK_CONDITIONAL_SEP tok_decl(4,1)
12042 #define TOK_OR tok_decl(5,0)
12044 #define TOK_AND tok_decl(6,0)
12046 #define TOK_BOR tok_decl(7,0)
12048 #define TOK_BXOR tok_decl(8,0)
12050 #define TOK_BAND tok_decl(9,0)
12052 #define TOK_EQ tok_decl(10,0)
12053 #define TOK_NE tok_decl(10,1)
12055 #define TOK_LT tok_decl(11,0)
12056 #define TOK_GT tok_decl(11,1)
12057 #define TOK_GE tok_decl(11,2)
12058 #define TOK_LE tok_decl(11,3)
12060 #define TOK_LSHIFT tok_decl(12,0)
12061 #define TOK_RSHIFT tok_decl(12,1)
12063 #define TOK_ADD tok_decl(13,0)
12064 #define TOK_SUB tok_decl(13,1)
12066 #define TOK_MUL tok_decl(14,0)
12067 #define TOK_DIV tok_decl(14,1)
12068 #define TOK_REM tok_decl(14,2)
12070 /* exponent is right associativity */
12071 #define TOK_EXPONENT tok_decl(15,1)
12073 /* For now unary operators. */
12074 #define UNARYPREC 16
12075 #define TOK_BNOT tok_decl(UNARYPREC,0)
12076 #define TOK_NOT tok_decl(UNARYPREC,1)
12078 #define TOK_UMINUS tok_decl(UNARYPREC+1,0)
12079 #define TOK_UPLUS tok_decl(UNARYPREC+1,1)
12081 #define PREC_PRE (UNARYPREC+2)
12083 #define TOK_PRE_INC tok_decl(PREC_PRE, 0)
12084 #define TOK_PRE_DEC tok_decl(PREC_PRE, 1)
12086 #define PREC_POST (UNARYPREC+3)
12088 #define TOK_POST_INC tok_decl(PREC_POST, 0)
12089 #define TOK_POST_DEC tok_decl(PREC_POST, 1)
12091 #define SPEC_PREC (UNARYPREC+4)
12093 #define TOK_NUM tok_decl(SPEC_PREC, 0)
12094 #define TOK_RPAREN tok_decl(SPEC_PREC, 1)
12096 #define NUMPTR (*numstackptr)
12099 tok_have_assign(operator op)
12101 operator prec = PREC(op);
12103 convert_prec_is_assing(prec);
12104 return (prec == PREC(TOK_ASSIGN) ||
12105 prec == PREC_PRE || prec == PREC_POST);
12109 is_right_associativity(operator prec)
12111 return (prec == PREC(TOK_ASSIGN) || prec == PREC(TOK_EXPONENT)
12112 || prec == PREC(TOK_CONDITIONAL));
12115 typedef struct ARITCH_VAR_NUM {
12117 arith_t contidional_second_val;
12118 char contidional_second_val_initialized;
12119 char *var; /* if NULL then is regular number,
12120 else is variable name */
12123 typedef struct CHK_VAR_RECURSIVE_LOOPED {
12125 struct CHK_VAR_RECURSIVE_LOOPED *next;
12126 } chk_var_recursive_looped_t;
12128 static chk_var_recursive_looped_t *prev_chk_var_recursive;
12131 arith_lookup_val(v_n_t *t)
12134 const char * p = lookupvar(t->var);
12139 /* recursive try as expression */
12140 chk_var_recursive_looped_t *cur;
12141 chk_var_recursive_looped_t cur_save;
12143 for (cur = prev_chk_var_recursive; cur; cur = cur->next) {
12144 if (strcmp(cur->var, t->var) == 0) {
12145 /* expression recursion loop detected */
12149 /* save current lookuped var name */
12150 cur = prev_chk_var_recursive;
12151 cur_save.var = t->var;
12152 cur_save.next = cur;
12153 prev_chk_var_recursive = &cur_save;
12155 t->val = arith (p, &errcode);
12156 /* restore previous ptr after recursiving */
12157 prev_chk_var_recursive = cur;
12160 /* allow undefined var as 0 */
12166 /* "applying" a token means performing it on the top elements on the integer
12167 * stack. For a unary operator it will only change the top element, but a
12168 * binary operator will pop two arguments and push a result */
12170 arith_apply(operator op, v_n_t *numstack, v_n_t **numstackptr)
12173 arith_t numptr_val, rez;
12174 int ret_arith_lookup_val;
12176 /* There is no operator that can work without arguments */
12177 if (NUMPTR == numstack) goto err;
12178 numptr_m1 = NUMPTR - 1;
12180 /* check operand is var with noninteger value */
12181 ret_arith_lookup_val = arith_lookup_val(numptr_m1);
12182 if (ret_arith_lookup_val)
12183 return ret_arith_lookup_val;
12185 rez = numptr_m1->val;
12186 if (op == TOK_UMINUS)
12188 else if (op == TOK_NOT)
12190 else if (op == TOK_BNOT)
12192 else if (op == TOK_POST_INC || op == TOK_PRE_INC)
12194 else if (op == TOK_POST_DEC || op == TOK_PRE_DEC)
12196 else if (op != TOK_UPLUS) {
12197 /* Binary operators */
12199 /* check and binary operators need two arguments */
12200 if (numptr_m1 == numstack) goto err;
12202 /* ... and they pop one */
12205 if (op == TOK_CONDITIONAL) {
12206 if (! numptr_m1->contidional_second_val_initialized) {
12207 /* protect $((expr1 ? expr2)) without ": expr" */
12210 rez = numptr_m1->contidional_second_val;
12211 } else if (numptr_m1->contidional_second_val_initialized) {
12212 /* protect $((expr1 : expr2)) without "expr ? " */
12215 numptr_m1 = NUMPTR - 1;
12216 if (op != TOK_ASSIGN) {
12217 /* check operand is var with noninteger value for not '=' */
12218 ret_arith_lookup_val = arith_lookup_val(numptr_m1);
12219 if (ret_arith_lookup_val)
12220 return ret_arith_lookup_val;
12222 if (op == TOK_CONDITIONAL) {
12223 numptr_m1->contidional_second_val = rez;
12225 rez = numptr_m1->val;
12226 if (op == TOK_BOR || op == TOK_OR_ASSIGN)
12228 else if (op == TOK_OR)
12229 rez = numptr_val || rez;
12230 else if (op == TOK_BAND || op == TOK_AND_ASSIGN)
12232 else if (op == TOK_BXOR || op == TOK_XOR_ASSIGN)
12234 else if (op == TOK_AND)
12235 rez = rez && numptr_val;
12236 else if (op == TOK_EQ)
12237 rez = (rez == numptr_val);
12238 else if (op == TOK_NE)
12239 rez = (rez != numptr_val);
12240 else if (op == TOK_GE)
12241 rez = (rez >= numptr_val);
12242 else if (op == TOK_RSHIFT || op == TOK_RSHIFT_ASSIGN)
12243 rez >>= numptr_val;
12244 else if (op == TOK_LSHIFT || op == TOK_LSHIFT_ASSIGN)
12245 rez <<= numptr_val;
12246 else if (op == TOK_GT)
12247 rez = (rez > numptr_val);
12248 else if (op == TOK_LT)
12249 rez = (rez < numptr_val);
12250 else if (op == TOK_LE)
12251 rez = (rez <= numptr_val);
12252 else if (op == TOK_MUL || op == TOK_MUL_ASSIGN)
12254 else if (op == TOK_ADD || op == TOK_PLUS_ASSIGN)
12256 else if (op == TOK_SUB || op == TOK_MINUS_ASSIGN)
12258 else if (op == TOK_ASSIGN || op == TOK_COMMA)
12260 else if (op == TOK_CONDITIONAL_SEP) {
12261 if (numptr_m1 == numstack) {
12262 /* protect $((expr : expr)) without "expr ? " */
12265 numptr_m1->contidional_second_val_initialized = op;
12266 numptr_m1->contidional_second_val = numptr_val;
12267 } else if (op == TOK_CONDITIONAL) {
12269 numptr_val : numptr_m1->contidional_second_val;
12270 } else if (op == TOK_EXPONENT) {
12271 if (numptr_val < 0)
12272 return -3; /* exponent less than 0 */
12277 while (numptr_val--)
12281 } else if (numptr_val==0) /* zero divisor check */
12283 else if (op == TOK_DIV || op == TOK_DIV_ASSIGN)
12285 else if (op == TOK_REM || op == TOK_REM_ASSIGN)
12288 if (tok_have_assign(op)) {
12289 char buf[sizeof(arith_t_type)*3 + 2];
12291 if (numptr_m1->var == NULL) {
12295 /* save to shell variable */
12296 #if ENABLE_ASH_MATH_SUPPORT_64
12297 snprintf(buf, sizeof(buf), "%lld", (arith_t_type) rez);
12299 snprintf(buf, sizeof(buf), "%ld", (arith_t_type) rez);
12301 setvar(numptr_m1->var, buf, 0);
12302 /* after saving, make previous value for v++ or v-- */
12303 if (op == TOK_POST_INC)
12305 else if (op == TOK_POST_DEC)
12308 numptr_m1->val = rez;
12309 /* protect geting var value, is number now */
12310 numptr_m1->var = NULL;
12316 /* longest must be first */
12317 static const char op_tokens[] = {
12318 '<','<','=',0, TOK_LSHIFT_ASSIGN,
12319 '>','>','=',0, TOK_RSHIFT_ASSIGN,
12320 '<','<', 0, TOK_LSHIFT,
12321 '>','>', 0, TOK_RSHIFT,
12322 '|','|', 0, TOK_OR,
12323 '&','&', 0, TOK_AND,
12324 '!','=', 0, TOK_NE,
12325 '<','=', 0, TOK_LE,
12326 '>','=', 0, TOK_GE,
12327 '=','=', 0, TOK_EQ,
12328 '|','=', 0, TOK_OR_ASSIGN,
12329 '&','=', 0, TOK_AND_ASSIGN,
12330 '*','=', 0, TOK_MUL_ASSIGN,
12331 '/','=', 0, TOK_DIV_ASSIGN,
12332 '%','=', 0, TOK_REM_ASSIGN,
12333 '+','=', 0, TOK_PLUS_ASSIGN,
12334 '-','=', 0, TOK_MINUS_ASSIGN,
12335 '-','-', 0, TOK_POST_DEC,
12336 '^','=', 0, TOK_XOR_ASSIGN,
12337 '+','+', 0, TOK_POST_INC,
12338 '*','*', 0, TOK_EXPONENT,
12342 '=', 0, TOK_ASSIGN,
12354 '?', 0, TOK_CONDITIONAL,
12355 ':', 0, TOK_CONDITIONAL_SEP,
12356 ')', 0, TOK_RPAREN,
12357 '(', 0, TOK_LPAREN,
12361 #define endexpression &op_tokens[sizeof(op_tokens)-7]
12364 arith(const char *expr, int *perrcode)
12366 char arithval; /* Current character under analysis */
12367 operator lasttok, op;
12370 const char *p = endexpression;
12373 size_t datasizes = strlen(expr) + 2;
12375 /* Stack of integers */
12376 /* The proof that there can be no more than strlen(startbuf)/2+1 integers
12377 * in any given correct or incorrect expression is left as an exercise to
12379 v_n_t *numstack = alloca(((datasizes)/2)*sizeof(v_n_t)),
12380 *numstackptr = numstack;
12381 /* Stack of operator tokens */
12382 operator *stack = alloca((datasizes) * sizeof(operator)),
12385 *stackptr++ = lasttok = TOK_LPAREN; /* start off with a left paren */
12386 *perrcode = errcode = 0;
12390 if (arithval == 0) {
12391 if (p == endexpression) {
12392 /* Null expression. */
12396 /* This is only reached after all tokens have been extracted from the
12397 * input stream. If there are still tokens on the operator stack, they
12398 * are to be applied in order. At the end, there should be a final
12399 * result on the integer stack */
12401 if (expr != endexpression + 1) {
12402 /* If we haven't done so already, */
12403 /* append a closing right paren */
12404 expr = endexpression;
12405 /* and let the loop process it. */
12408 /* At this point, we're done with the expression. */
12409 if (numstackptr != numstack+1) {
12410 /* ... but if there isn't, it's bad */
12412 return (*perrcode = -1);
12414 if (numstack->var) {
12415 /* expression is $((var)) only, lookup now */
12416 errcode = arith_lookup_val(numstack);
12419 *perrcode = errcode;
12420 return numstack->val;
12423 /* Continue processing the expression. */
12424 if (arith_isspace(arithval)) {
12425 /* Skip whitespace */
12428 p = endofname(expr);
12430 size_t var_name_size = (p-expr) + 1; /* trailing zero */
12432 numstackptr->var = alloca(var_name_size);
12433 safe_strncpy(numstackptr->var, expr, var_name_size);
12436 numstackptr->contidional_second_val_initialized = 0;
12441 if (isdigit(arithval)) {
12442 numstackptr->var = NULL;
12443 #if ENABLE_ASH_MATH_SUPPORT_64
12444 numstackptr->val = strtoll(expr, (char **) &expr, 0);
12446 numstackptr->val = strtol(expr, (char **) &expr, 0);
12450 for (p = op_tokens; ; p++) {
12454 /* strange operator not found */
12457 for (o = expr; *p && *o == *p; p++)
12464 /* skip tail uncompared token */
12467 /* skip zero delim */
12472 /* post grammar: a++ reduce to num */
12473 if (lasttok == TOK_POST_INC || lasttok == TOK_POST_DEC)
12476 /* Plus and minus are binary (not unary) _only_ if the last
12477 * token was as number, or a right paren (which pretends to be
12478 * a number, since it evaluates to one). Think about it.
12479 * It makes sense. */
12480 if (lasttok != TOK_NUM) {
12496 /* We don't want a unary operator to cause recursive descent on the
12497 * stack, because there can be many in a row and it could cause an
12498 * operator to be evaluated before its argument is pushed onto the
12499 * integer stack. */
12500 /* But for binary operators, "apply" everything on the operator
12501 * stack until we find an operator with a lesser priority than the
12502 * one we have just extracted. */
12503 /* Left paren is given the lowest priority so it will never be
12504 * "applied" in this way.
12505 * if associativity is right and priority eq, applied also skip
12508 if ((prec > 0 && prec < UNARYPREC) || prec == SPEC_PREC) {
12509 /* not left paren or unary */
12510 if (lasttok != TOK_NUM) {
12511 /* binary op must be preceded by a num */
12514 while (stackptr != stack) {
12515 if (op == TOK_RPAREN) {
12516 /* The algorithm employed here is simple: while we don't
12517 * hit an open paren nor the bottom of the stack, pop
12518 * tokens and apply them */
12519 if (stackptr[-1] == TOK_LPAREN) {
12521 /* Any operator directly after a */
12523 /* close paren should consider itself binary */
12527 operator prev_prec = PREC(stackptr[-1]);
12529 convert_prec_is_assing(prec);
12530 convert_prec_is_assing(prev_prec);
12531 if (prev_prec < prec)
12533 /* check right assoc */
12534 if (prev_prec == prec && is_right_associativity(prec))
12537 errcode = arith_apply(*--stackptr, numstack, &numstackptr);
12538 if (errcode) goto ret;
12540 if (op == TOK_RPAREN) {
12545 /* Push this operator to the stack and remember it. */
12546 *stackptr++ = lasttok = op;
12551 #endif /* ASH_MATH_SUPPORT */
12554 /* ============ main() and helpers */
12557 * Called to exit the shell.
12559 static void exitshell(void) ATTRIBUTE_NORETURN;
12567 status = exitstatus;
12568 TRACE(("pid %d, exitshell(%d)\n", getpid(), status));
12569 if (setjmp(loc.loc)) {
12570 if (exception == EXEXIT)
12571 /* dash bug: it just does _exit(exitstatus) here
12572 * but we have to do setjobctl(0) first!
12573 * (bug is still not fixed in dash-0.5.3 - if you run dash
12574 * under Midnight Commander, on exit from dash MC is backgrounded) */
12575 status = exitstatus;
12578 exception_handler = &loc;
12584 flush_stdout_stderr();
12594 /* from input.c: */
12595 basepf.nextc = basepf.buf = basebuf;
12598 signal(SIGCHLD, SIG_DFL);
12603 char ppid[sizeof(int)*3 + 1];
12605 struct stat st1, st2;
12608 for (envp = environ; envp && *envp; envp++) {
12609 if (strchr(*envp, '=')) {
12610 setvareq(*envp, VEXPORT|VTEXTFIXED);
12614 snprintf(ppid, sizeof(ppid), "%u", (unsigned) getppid());
12615 setvar("PPID", ppid, 0);
12617 p = lookupvar("PWD");
12619 if (*p != '/' || stat(p, &st1) || stat(".", &st2)
12620 || st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino)
12627 * Process the shell command line arguments.
12630 procargs(int argc, char **argv)
12633 const char *xminusc;
12640 for (i = 0; i < NOPTS; i++)
12646 if (*xargv == NULL) {
12648 ash_msg_and_raise_error(bb_msg_requires_arg, "-c");
12651 if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
12655 for (i = 0; i < NOPTS; i++)
12656 if (optlist[i] == 2)
12661 /* POSIX 1003.2: first arg after -c cmd is $0, remainder $1... */
12666 } else if (!sflag) {
12667 setinputfile(*xargv, 0);
12670 commandname = arg0;
12673 shellparam.p = xargv;
12674 #if ENABLE_ASH_GETOPTS
12675 shellparam.optind = 1;
12676 shellparam.optoff = -1;
12678 /* assert(shellparam.malloc == 0 && shellparam.nparam == 0); */
12680 shellparam.nparam++;
12687 * Read /etc/profile or .profile.
12690 read_profile(const char *name)
12694 if (setinputfile(name, INPUT_PUSH_FILE | INPUT_NOFILE_OK) < 0)
12703 * This routine is called when an error or an interrupt occurs in an
12704 * interactive shell and control is returned to the main command loop.
12712 /* from input.c: */
12713 parselleft = parsenleft = 0; /* clear input buffer */
12715 /* from parser.c: */
12718 /* from redir.c: */
12723 static short profile_buf[16384];
12724 extern int etext();
12728 * Main routine. We initialize things, parse the arguments, execute
12729 * profiles if we're a login shell, and then call cmdloop to execute
12730 * commands. The setjmp call sets up the location to jump to when an
12731 * exception occurs. When an exception occurs the variable "state"
12732 * is used to figure out how far we had gotten.
12734 int ash_main(int argc, char **argv);
12735 int ash_main(int argc, char **argv)
12738 volatile int state;
12739 struct jmploc jmploc;
12740 struct stackmark smark;
12743 dash_errno = __errno_location();
12747 monitor(4, etext, profile_buf, sizeof(profile_buf), 50);
12750 #if ENABLE_FEATURE_EDITING
12751 line_input_state = new_line_input_t(FOR_SHELL | WITH_PATH_LOOKUP);
12754 if (setjmp(jmploc.loc)) {
12764 if (e == EXEXIT || s == 0 || iflag == 0 || shlvl)
12768 outcslow('\n', stderr);
12770 popstackmark(&smark);
12771 FORCE_INT_ON; /* enable interrupts */
12780 exception_handler = &jmploc;
12783 trace_puts("Shell args: ");
12784 trace_puts_args(argv);
12786 rootpid = getpid();
12788 #if ENABLE_ASH_RANDOM_SUPPORT
12789 rseed = rootpid + time(NULL);
12792 setstackmark(&smark);
12793 procargs(argc, argv);
12794 #if ENABLE_FEATURE_EDITING_SAVEHISTORY
12796 const char *hp = lookupvar("HISTFILE");
12799 hp = lookupvar("HOME");
12801 char *defhp = concat_path_file(hp, ".ash_history");
12802 setvar("HISTFILE", defhp, 0);
12808 if (argv[0] && argv[0][0] == '-')
12812 read_profile("/etc/profile");
12815 read_profile(".profile");
12821 getuid() == geteuid() && getgid() == getegid() &&
12825 shinit = lookupvar("ENV");
12826 if (shinit != NULL && *shinit != '\0') {
12827 read_profile(shinit);
12833 evalstring(minusc, 0);
12835 if (sflag || minusc == NULL) {
12836 #if ENABLE_FEATURE_EDITING_SAVEHISTORY
12838 const char *hp = lookupvar("HISTFILE");
12841 line_input_state->hist_file = hp;
12844 state4: /* XXX ??? - why isn't this before the "if" statement */
12852 extern void _mcleanup(void);
12861 const char *applet_name = "debug stuff usage";
12862 int main(int argc, char **argv)
12864 return ash_main(argc, argv);
12870 * Copyright (c) 1989, 1991, 1993, 1994
12871 * The Regents of the University of California. All rights reserved.
12873 * This code is derived from software contributed to Berkeley by
12874 * Kenneth Almquist.
12876 * Redistribution and use in source and binary forms, with or without
12877 * modification, are permitted provided that the following conditions
12879 * 1. Redistributions of source code must retain the above copyright
12880 * notice, this list of conditions and the following disclaimer.
12881 * 2. Redistributions in binary form must reproduce the above copyright
12882 * notice, this list of conditions and the following disclaimer in the
12883 * documentation and/or other materials provided with the distribution.
12884 * 3. Neither the name of the University nor the names of its contributors
12885 * may be used to endorse or promote products derived from this software
12886 * without specific prior written permission.
12888 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
12889 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
12890 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
12891 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
12892 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
12893 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
12894 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
12895 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
12896 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
12897 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF