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
63 extern char **environ;
65 #if defined(__uClinux__)
66 #error "Do not even bother, ash will not run on uClinux"
70 /* ============ Misc helpers */
72 #define xbarrier() do { __asm__ __volatile__ ("": : :"memory"); } while (0)
74 /* C99 say: "char" declaration may be signed or unsigned default */
75 #define signed_char2int(sc) ((int)((signed char)sc))
78 /* ============ Shell options */
80 static const char *const optletters_optnames[] = {
101 #define optletters(n) optletters_optnames[(n)][0]
102 #define optnames(n) (&optletters_optnames[(n)][1])
104 #define NOPTS (sizeof(optletters_optnames)/sizeof(optletters_optnames[0]))
106 static char optlist[NOPTS];
108 #define eflag optlist[0]
109 #define fflag optlist[1]
110 #define Iflag optlist[2]
111 #define iflag optlist[3]
112 #define mflag optlist[4]
113 #define nflag optlist[5]
114 #define sflag optlist[6]
115 #define xflag optlist[7]
116 #define vflag optlist[8]
117 #define Cflag optlist[9]
118 #define aflag optlist[10]
119 #define bflag optlist[11]
120 #define uflag optlist[12]
121 #define viflag optlist[13]
123 #define nolog optlist[14]
124 #define debug optlist[15]
128 /* ============ Misc data */
132 static int *dash_errno;
134 #define errno (*dash_errno)
137 static char nullstr[1]; /* zero length string */
138 static const char homestr[] = "HOME";
139 static const char snlfmt[] = "%s\n";
140 static const char illnum[] = "Illegal number: %s";
142 static char *minusc; /* argument to -c option */
144 static int isloginsh;
145 /* pid of main shell */
147 /* shell level: 0 for the main shell, 1 for its children, and so on */
149 #define rootshell (!shlvl)
150 /* trap handler commands */
151 static char *trap[NSIG];
152 /* current value of signal */
153 static char sigmode[NSIG - 1];
154 /* indicates specified signal received */
155 static char gotsig[NSIG - 1];
156 static char *arg0; /* value of $0 */
159 /* ============ Interrupts / exceptions */
162 * We enclose jmp_buf in a structure so that we can declare pointers to
163 * jump locations. The global variable handler contains the location to
164 * jump to when an exception occurs, and the global variable exception
165 * contains a code identifying the exception. To implement nested
166 * exception handlers, the user should save the value of handler on entry
167 * to an inner scope, set handler to point to a jmploc structure for the
168 * inner scope, and restore handler on exit from the scope.
173 static struct jmploc *exception_handler;
174 static int exception;
176 #define EXINT 0 /* SIGINT received */
177 #define EXERROR 1 /* a generic error */
178 #define EXSHELLPROC 2 /* execute a shell procedure */
179 #define EXEXEC 3 /* command execution failed */
180 #define EXEXIT 4 /* exit the shell */
181 #define EXSIG 5 /* trapped signal in wait(1) */
182 static volatile int suppressint;
183 static volatile sig_atomic_t intpending;
184 /* do we generate EXSIG events */
186 /* last pending signal */
187 static volatile sig_atomic_t pendingsig;
190 * Sigmode records the current value of the signal handlers for the various
191 * modes. A value of zero means that the current handler is not known.
192 * S_HARD_IGN indicates that the signal was ignored on entry to the shell,
195 #define S_DFL 1 /* default signal handling (SIG_DFL) */
196 #define S_CATCH 2 /* signal is caught */
197 #define S_IGN 3 /* signal is ignored (SIG_IGN) */
198 #define S_HARD_IGN 4 /* signal is ignored permenantly */
199 #define S_RESET 5 /* temporary - to reset a hard ignored sig */
202 * These macros allow the user to suspend the handling of interrupt signals
203 * over a period of time. This is similar to SIGHOLD to or sigblock, but
204 * much more efficient and portable. (But hacking the kernel is so much
205 * more fun than worrying about efficiency and portability. :-))
214 * Called to raise an exception. Since C doesn't include exceptions, we
215 * just do a longjmp to the exception handler. The type of exception is
216 * stored in the global variable "exception".
218 static void raise_exception(int) ATTRIBUTE_NORETURN;
220 raise_exception(int e)
223 if (exception_handler == NULL)
228 longjmp(exception_handler->loc, 1);
232 * Called from trap.c when a SIGINT is received. (If the user specifies
233 * that SIGINT is to be trapped or ignored using the trap builtin, then
234 * this routine is not called.) Suppressint is nonzero when interrupts
235 * are held using the INT_OFF macro. (The test for iflag is just
236 * defensive programming.)
238 static void raise_interrupt(void) ATTRIBUTE_NORETURN;
240 raise_interrupt(void)
246 /* Signal is not automatically re-enabled after it is raised,
249 sigprocmask(SIG_SETMASK, &mask, 0);
250 /* pendingsig = 0; - now done in onsig() */
253 if (gotsig[SIGINT - 1] && !trap[SIGINT]) {
254 if (!(rootshell && iflag)) {
255 signal(SIGINT, SIG_DFL);
264 #if ENABLE_ASH_OPTIMIZE_FOR_SIZE
268 if (--suppressint == 0 && intpending) {
272 #define INT_ON int_on()
280 #define FORCE_INT_ON force_int_on()
285 if (--suppressint == 0 && intpending) \
288 #define FORCE_INT_ON \
295 #endif /* ASH_OPTIMIZE_FOR_SIZE */
297 #define SAVE_INT(v) ((v) = suppressint)
299 #define RESTORE_INT(v) \
303 if (suppressint == 0 && intpending) \
312 raise_exception(EXSIG); \
314 /* EXSIG is turned off by evalbltin(). */
317 * Ignore a signal. Only one usage site - in forkchild()
322 if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) {
323 signal(signo, SIG_IGN);
325 sigmode[signo - 1] = S_HARD_IGN;
329 * Signal handler. Only one usage site - in setsignal()
334 gotsig[signo - 1] = 1;
337 if (exsig || (signo == SIGINT && !trap[SIGINT])) {
347 /* ============ Stdout/stderr output */
350 outstr(const char *p, FILE *file)
358 flush_stdout_stderr(void)
375 outcslow(int c, FILE *dest)
383 static int out1fmt(const char *, ...) __attribute__((__format__(__printf__,1,2)));
385 out1fmt(const char *fmt, ...)
392 r = vprintf(fmt, ap);
398 static int fmtstr(char *, size_t, const char *, ...) __attribute__((__format__(__printf__,3,4)));
400 fmtstr(char *outbuf, size_t length, const char *fmt, ...)
407 ret = vsnprintf(outbuf, length, fmt, ap);
414 out1str(const char *p)
420 out2str(const char *p)
427 /* ============ Parser structures */
429 /* control characters in argument strings */
430 #define CTLESC '\201' /* escape next character */
431 #define CTLVAR '\202' /* variable defn */
432 #define CTLENDVAR '\203'
433 #define CTLBACKQ '\204'
434 #define CTLQUOTE 01 /* ored with CTLBACKQ code if in quotes */
435 /* CTLBACKQ | CTLQUOTE == '\205' */
436 #define CTLARI '\206' /* arithmetic expression */
437 #define CTLENDARI '\207'
438 #define CTLQUOTEMARK '\210'
440 /* variable substitution byte (follows CTLVAR) */
441 #define VSTYPE 0x0f /* type of variable substitution */
442 #define VSNUL 0x10 /* colon--treat the empty string as unset */
443 #define VSQUOTE 0x80 /* inside double quotes--suppress splitting */
445 /* values of VSTYPE field */
446 #define VSNORMAL 0x1 /* normal variable: $var or ${var} */
447 #define VSMINUS 0x2 /* ${var-text} */
448 #define VSPLUS 0x3 /* ${var+text} */
449 #define VSQUESTION 0x4 /* ${var?message} */
450 #define VSASSIGN 0x5 /* ${var=text} */
451 #define VSTRIMRIGHT 0x6 /* ${var%pattern} */
452 #define VSTRIMRIGHTMAX 0x7 /* ${var%%pattern} */
453 #define VSTRIMLEFT 0x8 /* ${var#pattern} */
454 #define VSTRIMLEFTMAX 0x9 /* ${var##pattern} */
455 #define VSLENGTH 0xa /* ${#var} */
457 static const char dolatstr[] = { CTLVAR, VSNORMAL|VSQUOTE, '@', '=', '\0' };
492 union node *redirect;
498 struct nodelist *cmdlist;
504 union node *redirect;
517 union node *elsepart;
544 struct nodelist *backquote;
579 struct nredir nredir;
580 struct nbinary nbinary;
584 struct nclist nclist;
593 struct nodelist *next;
606 freefunc(struct funcnode *f)
608 if (f && --f->count < 0)
613 /* ============ Debugging output */
617 static FILE *tracefile;
620 trace_printf(const char *fmt, ...)
627 vfprintf(tracefile, fmt, va);
632 trace_vprintf(const char *fmt, va_list va)
636 vfprintf(tracefile, fmt, va);
640 trace_puts(const char *s)
648 trace_puts_quoted(char *s)
655 putc('"', tracefile);
656 for (p = s; *p; p++) {
658 case '\n': c = 'n'; goto backslash;
659 case '\t': c = 't'; goto backslash;
660 case '\r': c = 'r'; goto backslash;
661 case '"': c = '"'; goto backslash;
662 case '\\': c = '\\'; goto backslash;
663 case CTLESC: c = 'e'; goto backslash;
664 case CTLVAR: c = 'v'; goto backslash;
665 case CTLVAR+CTLQUOTE: c = 'V'; goto backslash;
666 case CTLBACKQ: c = 'q'; goto backslash;
667 case CTLBACKQ+CTLQUOTE: c = 'Q'; goto backslash;
669 putc('\\', tracefile);
673 if (*p >= ' ' && *p <= '~')
676 putc('\\', tracefile);
677 putc(*p >> 6 & 03, tracefile);
678 putc(*p >> 3 & 07, tracefile);
679 putc(*p & 07, tracefile);
684 putc('"', tracefile);
688 trace_puts_args(char **ap)
695 trace_puts_quoted(*ap);
697 putc('\n', tracefile);
700 putc(' ', tracefile);
715 /* leave open because libedit might be using it */
718 strcpy(s, "./trace");
720 if (!freopen(s, "a", tracefile)) {
721 fprintf(stderr, "Can't re-open %s\n", s);
726 tracefile = fopen(s, "a");
727 if (tracefile == NULL) {
728 fprintf(stderr, "Can't open %s\n", s);
734 flags = fcntl(fileno(tracefile), F_GETFL, 0);
736 fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND);
738 setlinebuf(tracefile);
739 fputs("\nTracing started.\n", tracefile);
743 indent(int amount, char *pfx, FILE *fp)
747 for (i = 0; i < amount; i++) {
748 if (pfx && i == amount - 1)
754 /* little circular references here... */
755 static void shtree(union node *n, int ind, char *pfx, FILE *fp);
758 sharg(union node *arg, FILE *fp)
761 struct nodelist *bqlist;
764 if (arg->type != NARG) {
765 out1fmt("<node type %d>\n", arg->type);
768 bqlist = arg->narg.backquote;
769 for (p = arg->narg.text; *p; p++) {
778 if (subtype == VSLENGTH)
787 switch (subtype & VSTYPE) {
820 out1fmt("<subtype %d>", subtype);
827 case CTLBACKQ|CTLQUOTE:
830 shtree(bqlist->n, -1, NULL, fp);
841 shcmd(union node *cmd, FILE *fp)
849 for (np = cmd->ncmd.args; np; np = np->narg.next) {
855 for (np = cmd->ncmd.redirect; np; np = np->nfile.next) {
858 switch (np->nfile.type) {
859 case NTO: s = ">"; dftfd = 1; break;
860 case NCLOBBER: s = ">|"; dftfd = 1; break;
861 case NAPPEND: s = ">>"; dftfd = 1; break;
862 case NTOFD: s = ">&"; dftfd = 1; break;
863 case NFROM: s = "<"; dftfd = 0; break;
864 case NFROMFD: s = "<&"; dftfd = 0; break;
865 case NFROMTO: s = "<>"; dftfd = 0; break;
866 default: s = "*error*"; dftfd = 0; break;
868 if (np->nfile.fd != dftfd)
869 fprintf(fp, "%d", np->nfile.fd);
871 if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) {
872 fprintf(fp, "%d", np->ndup.dupfd);
874 sharg(np->nfile.fname, fp);
881 shtree(union node *n, int ind, char *pfx, FILE *fp)
889 indent(ind, pfx, fp);
900 shtree(n->nbinary.ch1, ind, NULL, fp);
903 shtree(n->nbinary.ch2, ind, NULL, fp);
911 for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
916 if (n->npipe.backgnd)
922 fprintf(fp, "<node type %d>", n->type);
930 showtree(union node *n)
932 trace_puts("showtree called\n");
933 shtree(n, 1, NULL, stdout);
936 #define TRACE(param) trace_printf param
937 #define TRACEV(param) trace_vprintf param
942 #define TRACEV(param)
947 /* ============ Parser data */
950 * ash_vmsg() needs parsefile->fd, hence parsefile definition is moved up.
953 struct strlist *next;
962 struct strpush *prev; /* preceding string on stack */
966 struct alias *ap; /* if push was associated with an alias */
968 char *string; /* remember the string since it may change */
972 struct parsefile *prev; /* preceding file on stack */
973 int linno; /* current line */
974 int fd; /* file descriptor (or -1 if string) */
975 int nleft; /* number of chars left in this line */
976 int lleft; /* number of chars left in this buffer */
977 char *nextc; /* next char in buffer */
978 char *buf; /* input buffer */
979 struct strpush *strpush; /* for pushing strings at this level */
980 struct strpush basestrpush; /* so pushing one is fast */
983 static struct parsefile basepf; /* top level input file */
984 static struct parsefile *parsefile = &basepf; /* current input file */
985 static int startlinno; /* line # where last token started */
986 static char *commandname; /* currently executing command */
987 static struct strlist *cmdenviron; /* environment for builtin command */
988 static int exitstatus; /* exit status of last command */
991 /* ============ Message printing */
994 ash_vmsg(const char *msg, va_list ap)
996 fprintf(stderr, "%s: ", arg0);
998 if (strcmp(arg0, commandname))
999 fprintf(stderr, "%s: ", commandname);
1000 if (!iflag || parsefile->fd)
1001 fprintf(stderr, "line %d: ", startlinno);
1003 vfprintf(stderr, msg, ap);
1004 outcslow('\n', stderr);
1008 * Exverror is called to raise the error exception. If the second argument
1009 * is not NULL then error prints an error message using printf style
1010 * formatting. It then raises the error exception.
1012 static void ash_vmsg_and_raise(int, const char *, va_list) ATTRIBUTE_NORETURN;
1014 ash_vmsg_and_raise(int cond, const char *msg, va_list ap)
1018 TRACE(("ash_vmsg_and_raise(%d, \"", cond));
1020 TRACE(("\") pid=%d\n", getpid()));
1022 TRACE(("ash_vmsg_and_raise(%d, NULL) pid=%d\n", cond, getpid()));
1027 flush_stdout_stderr();
1028 raise_exception(cond);
1032 static void ash_msg_and_raise_error(const char *, ...) ATTRIBUTE_NORETURN;
1034 ash_msg_and_raise_error(const char *msg, ...)
1039 ash_vmsg_and_raise(EXERROR, msg, ap);
1044 static void ash_msg_and_raise(int, const char *, ...) ATTRIBUTE_NORETURN;
1046 ash_msg_and_raise(int cond, const char *msg, ...)
1051 ash_vmsg_and_raise(cond, msg, ap);
1057 * error/warning routines for external builtins
1060 ash_msg(const char *fmt, ...)
1070 * Return a string describing an error. The returned string may be a
1071 * pointer to a static buffer that will be overwritten on the next call.
1072 * Action describes the operation that got the error.
1075 errmsg(int e, const char *em)
1077 if (e == ENOENT || e == ENOTDIR) {
1084 /* ============ Memory allocation */
1087 * It appears that grabstackstr() will barf with such alignments
1088 * because stalloc() will return a string allocated in a new stackblock.
1090 #define SHELL_ALIGN(nbytes) (((nbytes) + SHELL_SIZE) & ~SHELL_SIZE)
1092 /* Most machines require the value returned from malloc to be aligned
1093 * in some way. The following macro will get this right
1094 * on many machines. */
1095 SHELL_SIZE = sizeof(union {int i; char *cp; double d; }) - 1,
1096 /* Minimum size of a block */
1097 MINSIZE = SHELL_ALIGN(504),
1100 struct stack_block {
1101 struct stack_block *prev;
1102 char space[MINSIZE];
1106 struct stack_block *stackp;
1109 struct stackmark *marknext;
1112 static struct stack_block stackbase;
1113 static struct stack_block *stackp = &stackbase;
1114 static struct stackmark *markp;
1115 static char *stacknxt = stackbase.space;
1116 static size_t stacknleft = MINSIZE;
1117 static char *sstrend = stackbase.space + MINSIZE;
1118 static int herefd = -1;
1120 #define stackblock() ((void *)stacknxt)
1121 #define stackblocksize() stacknleft
1124 ckrealloc(void * p, size_t nbytes)
1126 p = realloc(p, nbytes);
1128 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1133 ckmalloc(size_t nbytes)
1135 return ckrealloc(NULL, nbytes);
1139 * Make a copy of a string in safe storage.
1142 ckstrdup(const char *s)
1144 char *p = strdup(s);
1146 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1151 * Parse trees for commands are allocated in lifo order, so we use a stack
1152 * to make this more efficient, and also to avoid all sorts of exception
1153 * handling code to handle interrupts in the middle of a parse.
1155 * The size 504 was chosen because the Ultrix malloc handles that size
1159 stalloc(size_t nbytes)
1164 aligned = SHELL_ALIGN(nbytes);
1165 if (aligned > stacknleft) {
1168 struct stack_block *sp;
1170 blocksize = aligned;
1171 if (blocksize < MINSIZE)
1172 blocksize = MINSIZE;
1173 len = sizeof(struct stack_block) - MINSIZE + blocksize;
1174 if (len < blocksize)
1175 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1179 stacknxt = sp->space;
1180 stacknleft = blocksize;
1181 sstrend = stacknxt + blocksize;
1186 stacknxt += aligned;
1187 stacknleft -= aligned;
1195 if (!p || (stacknxt < (char *)p) || ((char *)p < stackp->space)) {
1196 write(2, "stunalloc\n", 10);
1200 stacknleft += stacknxt - (char *)p;
1205 * Like strdup but works with the ash stack.
1208 ststrdup(const char *p)
1210 size_t len = strlen(p) + 1;
1211 return memcpy(stalloc(len), p, len);
1215 setstackmark(struct stackmark *mark)
1217 mark->stackp = stackp;
1218 mark->stacknxt = stacknxt;
1219 mark->stacknleft = stacknleft;
1220 mark->marknext = markp;
1225 popstackmark(struct stackmark *mark)
1227 struct stack_block *sp;
1233 markp = mark->marknext;
1234 while (stackp != mark->stackp) {
1239 stacknxt = mark->stacknxt;
1240 stacknleft = mark->stacknleft;
1241 sstrend = mark->stacknxt + mark->stacknleft;
1246 * When the parser reads in a string, it wants to stick the string on the
1247 * stack and only adjust the stack pointer when it knows how big the
1248 * string is. Stackblock (defined in stack.h) returns a pointer to a block
1249 * of space on top of the stack and stackblocklen returns the length of
1250 * this block. Growstackblock will grow this space by at least one byte,
1251 * possibly moving it (like realloc). Grabstackblock actually allocates the
1252 * part of the block that has been used.
1255 growstackblock(void)
1259 newlen = stacknleft * 2;
1260 if (newlen < stacknleft)
1261 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1265 if (stacknxt == stackp->space && stackp != &stackbase) {
1266 struct stack_block *oldstackp;
1267 struct stackmark *xmark;
1268 struct stack_block *sp;
1269 struct stack_block *prevstackp;
1275 prevstackp = sp->prev;
1276 grosslen = newlen + sizeof(struct stack_block) - MINSIZE;
1277 sp = ckrealloc(sp, grosslen);
1278 sp->prev = prevstackp;
1280 stacknxt = sp->space;
1281 stacknleft = newlen;
1282 sstrend = sp->space + newlen;
1285 * Stack marks pointing to the start of the old block
1286 * must be relocated to point to the new block
1289 while (xmark != NULL && xmark->stackp == oldstackp) {
1290 xmark->stackp = stackp;
1291 xmark->stacknxt = stacknxt;
1292 xmark->stacknleft = stacknleft;
1293 xmark = xmark->marknext;
1297 char *oldspace = stacknxt;
1298 int oldlen = stacknleft;
1299 char *p = stalloc(newlen);
1301 /* free the space we just allocated */
1302 stacknxt = memcpy(p, oldspace, oldlen);
1303 stacknleft += newlen;
1308 grabstackblock(size_t len)
1310 len = SHELL_ALIGN(len);
1316 * The following routines are somewhat easier to use than the above.
1317 * The user declares a variable of type STACKSTR, which may be declared
1318 * to be a register. The macro STARTSTACKSTR initializes things. Then
1319 * the user uses the macro STPUTC to add characters to the string. In
1320 * effect, STPUTC(c, p) is the same as *p++ = c except that the stack is
1321 * grown as necessary. When the user is done, she can just leave the
1322 * string there and refer to it using stackblock(). Or she can allocate
1323 * the space for it using grabstackstr(). If it is necessary to allow
1324 * someone else to use the stack temporarily and then continue to grow
1325 * the string, the user should use grabstack to allocate the space, and
1326 * then call ungrabstr(p) to return to the previous mode of operation.
1328 * USTPUTC is like STPUTC except that it doesn't check for overflow.
1329 * CHECKSTACKSPACE can be called before USTPUTC to ensure that there
1330 * is space for at least one character.
1335 size_t len = stackblocksize();
1336 if (herefd >= 0 && len >= 1024) {
1337 full_write(herefd, stackblock(), len);
1338 return stackblock();
1341 return stackblock() + len;
1345 * Called from CHECKSTRSPACE.
1348 makestrspace(size_t newlen, char *p)
1350 size_t len = p - stacknxt;
1351 size_t size = stackblocksize();
1356 size = stackblocksize();
1358 if (nleft >= newlen)
1362 return stackblock() + len;
1366 stack_nputstr(const char *s, size_t n, char *p)
1368 p = makestrspace(n, p);
1369 p = memcpy(p, s, n) + n;
1374 stack_putstr(const char *s, char *p)
1376 return stack_nputstr(s, strlen(s), p);
1380 _STPUTC(int c, char *p)
1388 #define STARTSTACKSTR(p) ((p) = stackblock())
1389 #define STPUTC(c, p) ((p) = _STPUTC((c), (p)))
1390 #define CHECKSTRSPACE(n, p) \
1394 size_t m = sstrend - q; \
1396 (p) = makestrspace(l, q); \
1398 #define USTPUTC(c, p) (*p++ = (c))
1399 #define STACKSTRNUL(p) \
1401 if ((p) == sstrend) \
1402 p = growstackstr(); \
1405 #define STUNPUTC(p) (--p)
1406 #define STTOPC(p) (p[-1])
1407 #define STADJUST(amount, p) (p += (amount))
1409 #define grabstackstr(p) stalloc((char *)(p) - (char *)stackblock())
1410 #define ungrabstackstr(s, p) stunalloc((s))
1411 #define stackstrend() ((void *)sstrend)
1414 /* ============ String helpers */
1417 * prefix -- see if pfx is a prefix of string.
1420 prefix(const char *string, const char *pfx)
1423 if (*pfx++ != *string++)
1426 return (char *) string;
1430 * Check for a valid number. This should be elsewhere.
1433 is_number(const char *p)
1438 } while (*++p != '\0');
1443 * Convert a string of digits to an integer, printing an error message on
1447 number(const char *s)
1450 ash_msg_and_raise_error(illnum, s);
1455 * Produce a possibly single quoted string suitable as input to the shell.
1456 * The return string is allocated on the stack.
1459 single_quote(const char *s)
1469 len = strchrnul(s, '\'') - s;
1471 q = p = makestrspace(len + 3, p);
1474 q = memcpy(q, s, len) + len;
1480 len = strspn(s, "'");
1484 q = p = makestrspace(len + 3, p);
1487 q = memcpy(q, s, len) + len;
1496 return stackblock();
1500 /* ============ nextopt */
1502 static char **argptr; /* argument list for builtin commands */
1503 static char *optionarg; /* set by nextopt (like getopt) */
1504 static char *optptr; /* used by nextopt */
1507 * XXX - should get rid of. have all builtins use getopt(3). the
1508 * library getopt must have the BSD extension static variable "optreset"
1509 * otherwise it can't be used within the shell safely.
1511 * Standard option processing (a la getopt) for builtin routines. The
1512 * only argument that is passed to nextopt is the option string; the
1513 * other arguments are unnecessary. It return the character, or '\0' on
1517 nextopt(const char *optstring)
1524 if (p == NULL || *p == '\0') {
1526 if (p == NULL || *p != '-' || *++p == '\0')
1529 if (LONE_DASH(p)) /* check for "--" */
1533 for (q = optstring; *q != c; ) {
1535 ash_msg_and_raise_error("illegal option -%c", c);
1540 if (*p == '\0' && (p = *argptr++) == NULL)
1541 ash_msg_and_raise_error("no arg for -%c option", c);
1550 /* ============ Math support definitions */
1552 #if ENABLE_ASH_MATH_SUPPORT_64
1553 typedef int64_t arith_t;
1554 #define arith_t_type long long
1556 typedef long arith_t;
1557 #define arith_t_type long
1560 #if ENABLE_ASH_MATH_SUPPORT
1561 static arith_t dash_arith(const char *);
1562 static arith_t arith(const char *expr, int *perrcode);
1565 #if ENABLE_ASH_RANDOM_SUPPORT
1566 static unsigned long rseed;
1573 /* ============ Shell variables */
1576 #define VEXPORT 0x01 /* variable is exported */
1577 #define VREADONLY 0x02 /* variable cannot be modified */
1578 #define VSTRFIXED 0x04 /* variable struct is statically allocated */
1579 #define VTEXTFIXED 0x08 /* text is statically allocated */
1580 #define VSTACK 0x10 /* text is allocated on the stack */
1581 #define VUNSET 0x20 /* the variable is not set */
1582 #define VNOFUNC 0x40 /* don't call the callback function */
1583 #define VNOSET 0x80 /* do not set variable - just readonly test */
1584 #define VNOSAVE 0x100 /* when text is on the heap before setvareq */
1586 # define VDYNAMIC 0x200 /* dynamic variable */
1591 static const char defpathvar[] = "PATH=/usr/local/bin:/usr/bin:/sbin:/bin";
1593 static const char defifsvar[] = "IFS= \t\n";
1594 #define defifs (defifsvar + 4)
1596 static const char defifs[] = " \t\n";
1600 int nparam; /* # of positional parameters (without $0) */
1601 unsigned char malloc; /* if parameter list dynamically allocated */
1602 char **p; /* parameter list */
1603 #if ENABLE_ASH_GETOPTS
1604 int optind; /* next parameter to be processed by getopts */
1605 int optoff; /* used by getopts */
1609 static struct shparam shellparam; /* $@ current positional parameters */
1612 * Free the list of positional parameters.
1615 freeparam(volatile struct shparam *param)
1619 if (param->malloc) {
1620 for (ap = param->p; *ap; ap++)
1626 #if ENABLE_ASH_GETOPTS
1628 getoptsreset(const char *value)
1630 shellparam.optind = number(value);
1631 shellparam.optoff = -1;
1636 struct var *next; /* next entry in hash list */
1637 int flags; /* flags are defined above */
1638 const char *text; /* name=value */
1639 void (*func)(const char *); /* function to be called when */
1640 /* the variable gets set/unset */
1644 struct localvar *next; /* next local variable in list */
1645 struct var *vp; /* the variable that was made local */
1646 int flags; /* saved flags */
1647 const char *text; /* saved text */
1650 /* Forward decls for varinit[] */
1651 #if ENABLE_LOCALE_SUPPORT
1653 change_lc_all(const char *value)
1655 if (value && *value != '\0')
1656 setlocale(LC_ALL, value);
1659 change_lc_ctype(const char *value)
1661 if (value && *value != '\0')
1662 setlocale(LC_CTYPE, value);
1666 static void chkmail(void);
1667 static void changemail(const char *);
1669 static void changepath(const char *);
1670 #if ENABLE_ASH_RANDOM_SUPPORT
1671 static void change_random(const char *);
1674 static struct var varinit[] = {
1676 { NULL, VSTRFIXED|VTEXTFIXED, defifsvar, NULL },
1678 { NULL, VSTRFIXED|VTEXTFIXED|VUNSET, "IFS\0", NULL },
1681 { NULL, VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL\0", changemail },
1682 { NULL, VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH\0", changemail },
1684 { NULL, VSTRFIXED|VTEXTFIXED, defpathvar, changepath },
1685 { NULL, VSTRFIXED|VTEXTFIXED, "PS1=$ ", NULL },
1686 { NULL, VSTRFIXED|VTEXTFIXED, "PS2=> ", NULL },
1687 { NULL, VSTRFIXED|VTEXTFIXED, "PS4=+ ", NULL },
1688 #if ENABLE_ASH_GETOPTS
1689 { NULL, VSTRFIXED|VTEXTFIXED, "OPTIND=1", getoptsreset },
1691 #if ENABLE_ASH_RANDOM_SUPPORT
1692 { NULL, VSTRFIXED|VTEXTFIXED|VUNSET|VDYNAMIC, "RANDOM\0", change_random },
1694 #if ENABLE_LOCALE_SUPPORT
1695 { NULL, VSTRFIXED | VTEXTFIXED | VUNSET, "LC_ALL\0", change_lc_all },
1696 { NULL, VSTRFIXED | VTEXTFIXED | VUNSET, "LC_CTYPE\0", change_lc_ctype },
1698 #if ENABLE_FEATURE_EDITING_SAVEHISTORY
1699 { NULL, VSTRFIXED | VTEXTFIXED | VUNSET, "HISTFILE\0", NULL },
1703 #define vifs varinit[0]
1705 #define vmail (&vifs)[1]
1706 #define vmpath (&vmail)[1]
1710 #define vpath (&vmpath)[1]
1711 #define vps1 (&vpath)[1]
1712 #define vps2 (&vps1)[1]
1713 #define vps4 (&vps2)[1]
1714 #define voptind (&vps4)[1]
1715 #if ENABLE_ASH_GETOPTS
1716 #define vrandom (&voptind)[1]
1718 #define vrandom (&vps4)[1]
1720 #define defpath (defpathvar + 5)
1723 * The following macros access the values of the above variables.
1724 * They have to skip over the name. They return the null string
1725 * for unset variables.
1727 #define ifsval() (vifs.text + 4)
1728 #define ifsset() ((vifs.flags & VUNSET) == 0)
1729 #define mailval() (vmail.text + 5)
1730 #define mpathval() (vmpath.text + 9)
1731 #define pathval() (vpath.text + 5)
1732 #define ps1val() (vps1.text + 4)
1733 #define ps2val() (vps2.text + 4)
1734 #define ps4val() (vps4.text + 4)
1735 #define optindval() (voptind.text + 7)
1737 #define mpathset() ((vmpath.flags & VUNSET) == 0)
1740 * The parsefile structure pointed to by the global variable parsefile
1741 * contains information about the current file being read.
1744 struct redirtab *next;
1749 static struct redirtab *redirlist;
1750 static int nullredirs;
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...
6896 describe_command(char *command, int describe_command_verbose)
6898 struct cmdentry entry;
6899 struct tblentry *cmdp;
6900 #if ENABLE_ASH_ALIAS
6901 const struct alias *ap;
6903 const char *path = pathval();
6905 if (describe_command_verbose) {
6909 /* First look at the keywords */
6910 if (findkwd(command)) {
6911 out1str(describe_command_verbose ? " is a shell keyword" : command);
6915 #if ENABLE_ASH_ALIAS
6916 /* Then look at the aliases */
6917 ap = lookupalias(command, 0);
6919 if (!describe_command_verbose) {
6924 out1fmt(" is an alias for %s", ap->val);
6928 /* Then check if it is a tracked alias */
6929 cmdp = cmdlookup(command, 0);
6931 entry.cmdtype = cmdp->cmdtype;
6932 entry.u = cmdp->param;
6934 /* Finally use brute force */
6935 find_command(command, &entry, DO_ABS, path);
6938 switch (entry.cmdtype) {
6940 int j = entry.u.index;
6946 p = padvance(&path, command);
6950 if (describe_command_verbose) {
6952 (cmdp ? " a tracked alias for" : nullstr), p
6961 if (describe_command_verbose) {
6962 out1str(" is a shell function");
6969 if (describe_command_verbose) {
6970 out1fmt(" is a %sshell builtin",
6971 IS_BUILTIN_SPECIAL(entry.u.cmd) ?
6972 "special " : nullstr
6980 if (describe_command_verbose) {
6981 out1str(": not found\n");
6986 outstr("\n", stdout);
6991 typecmd(int argc, char **argv)
6997 /* type -p ... ? (we don't bother checking for 'p') */
6998 if (argv[1][0] == '-') {
7003 err |= describe_command(argv[i++], verbose);
7008 #if ENABLE_ASH_CMDCMD
7010 commandcmd(int argc, char **argv)
7018 while ((c = nextopt("pvV")) != '\0')
7020 verify |= VERIFY_VERBOSE;
7022 verify |= VERIFY_BRIEF;
7028 return describe_command(*argptr, verify - VERIFY_BRIEF);
7035 /* ============ eval.c */
7037 static int funcblocksize; /* size of structures in function */
7038 static int funcstringsize; /* size of strings in node */
7039 static void *funcblock; /* block to allocate function from */
7040 static char *funcstring; /* block to allocate strings from */
7042 /* flags in argument to evaltree */
7043 #define EV_EXIT 01 /* exit after evaluating tree */
7044 #define EV_TESTED 02 /* exit status is checked; ignore -e flag */
7045 #define EV_BACKCMD 04 /* command executing within back quotes */
7047 static const short nodesize[26] = {
7048 SHELL_ALIGN(sizeof(struct ncmd)),
7049 SHELL_ALIGN(sizeof(struct npipe)),
7050 SHELL_ALIGN(sizeof(struct nredir)),
7051 SHELL_ALIGN(sizeof(struct nredir)),
7052 SHELL_ALIGN(sizeof(struct nredir)),
7053 SHELL_ALIGN(sizeof(struct nbinary)),
7054 SHELL_ALIGN(sizeof(struct nbinary)),
7055 SHELL_ALIGN(sizeof(struct nbinary)),
7056 SHELL_ALIGN(sizeof(struct nif)),
7057 SHELL_ALIGN(sizeof(struct nbinary)),
7058 SHELL_ALIGN(sizeof(struct nbinary)),
7059 SHELL_ALIGN(sizeof(struct nfor)),
7060 SHELL_ALIGN(sizeof(struct ncase)),
7061 SHELL_ALIGN(sizeof(struct nclist)),
7062 SHELL_ALIGN(sizeof(struct narg)),
7063 SHELL_ALIGN(sizeof(struct narg)),
7064 SHELL_ALIGN(sizeof(struct nfile)),
7065 SHELL_ALIGN(sizeof(struct nfile)),
7066 SHELL_ALIGN(sizeof(struct nfile)),
7067 SHELL_ALIGN(sizeof(struct nfile)),
7068 SHELL_ALIGN(sizeof(struct nfile)),
7069 SHELL_ALIGN(sizeof(struct ndup)),
7070 SHELL_ALIGN(sizeof(struct ndup)),
7071 SHELL_ALIGN(sizeof(struct nhere)),
7072 SHELL_ALIGN(sizeof(struct nhere)),
7073 SHELL_ALIGN(sizeof(struct nnot)),
7076 static void calcsize(union node *n);
7079 sizenodelist(struct nodelist *lp)
7082 funcblocksize += SHELL_ALIGN(sizeof(struct nodelist));
7089 calcsize(union node *n)
7093 funcblocksize += nodesize[n->type];
7096 calcsize(n->ncmd.redirect);
7097 calcsize(n->ncmd.args);
7098 calcsize(n->ncmd.assign);
7101 sizenodelist(n->npipe.cmdlist);
7106 calcsize(n->nredir.redirect);
7107 calcsize(n->nredir.n);
7114 calcsize(n->nbinary.ch2);
7115 calcsize(n->nbinary.ch1);
7118 calcsize(n->nif.elsepart);
7119 calcsize(n->nif.ifpart);
7120 calcsize(n->nif.test);
7123 funcstringsize += strlen(n->nfor.var) + 1;
7124 calcsize(n->nfor.body);
7125 calcsize(n->nfor.args);
7128 calcsize(n->ncase.cases);
7129 calcsize(n->ncase.expr);
7132 calcsize(n->nclist.body);
7133 calcsize(n->nclist.pattern);
7134 calcsize(n->nclist.next);
7138 sizenodelist(n->narg.backquote);
7139 funcstringsize += strlen(n->narg.text) + 1;
7140 calcsize(n->narg.next);
7147 calcsize(n->nfile.fname);
7148 calcsize(n->nfile.next);
7152 calcsize(n->ndup.vname);
7153 calcsize(n->ndup.next);
7157 calcsize(n->nhere.doc);
7158 calcsize(n->nhere.next);
7161 calcsize(n->nnot.com);
7167 nodeckstrdup(char *s)
7169 char *rtn = funcstring;
7171 strcpy(funcstring, s);
7172 funcstring += strlen(s) + 1;
7176 static union node *copynode(union node *);
7178 static struct nodelist *
7179 copynodelist(struct nodelist *lp)
7181 struct nodelist *start;
7182 struct nodelist **lpp;
7187 funcblock = (char *) funcblock + SHELL_ALIGN(sizeof(struct nodelist));
7188 (*lpp)->n = copynode(lp->n);
7190 lpp = &(*lpp)->next;
7197 copynode(union node *n)
7204 funcblock = (char *) funcblock + nodesize[n->type];
7208 new->ncmd.redirect = copynode(n->ncmd.redirect);
7209 new->ncmd.args = copynode(n->ncmd.args);
7210 new->ncmd.assign = copynode(n->ncmd.assign);
7213 new->npipe.cmdlist = copynodelist(n->npipe.cmdlist);
7214 new->npipe.backgnd = n->npipe.backgnd;
7219 new->nredir.redirect = copynode(n->nredir.redirect);
7220 new->nredir.n = copynode(n->nredir.n);
7227 new->nbinary.ch2 = copynode(n->nbinary.ch2);
7228 new->nbinary.ch1 = copynode(n->nbinary.ch1);
7231 new->nif.elsepart = copynode(n->nif.elsepart);
7232 new->nif.ifpart = copynode(n->nif.ifpart);
7233 new->nif.test = copynode(n->nif.test);
7236 new->nfor.var = nodeckstrdup(n->nfor.var);
7237 new->nfor.body = copynode(n->nfor.body);
7238 new->nfor.args = copynode(n->nfor.args);
7241 new->ncase.cases = copynode(n->ncase.cases);
7242 new->ncase.expr = copynode(n->ncase.expr);
7245 new->nclist.body = copynode(n->nclist.body);
7246 new->nclist.pattern = copynode(n->nclist.pattern);
7247 new->nclist.next = copynode(n->nclist.next);
7251 new->narg.backquote = copynodelist(n->narg.backquote);
7252 new->narg.text = nodeckstrdup(n->narg.text);
7253 new->narg.next = copynode(n->narg.next);
7260 new->nfile.fname = copynode(n->nfile.fname);
7261 new->nfile.fd = n->nfile.fd;
7262 new->nfile.next = copynode(n->nfile.next);
7266 new->ndup.vname = copynode(n->ndup.vname);
7267 new->ndup.dupfd = n->ndup.dupfd;
7268 new->ndup.fd = n->ndup.fd;
7269 new->ndup.next = copynode(n->ndup.next);
7273 new->nhere.doc = copynode(n->nhere.doc);
7274 new->nhere.fd = n->nhere.fd;
7275 new->nhere.next = copynode(n->nhere.next);
7278 new->nnot.com = copynode(n->nnot.com);
7281 new->type = n->type;
7286 * Make a copy of a parse tree.
7288 static struct funcnode *
7289 copyfunc(union node *n)
7294 funcblocksize = offsetof(struct funcnode, n);
7297 blocksize = funcblocksize;
7298 f = ckmalloc(blocksize + funcstringsize);
7299 funcblock = (char *) f + offsetof(struct funcnode, n);
7300 funcstring = (char *) f + blocksize;
7307 * Define a shell function.
7310 defun(char *name, union node *func)
7312 struct cmdentry entry;
7315 entry.cmdtype = CMDFUNCTION;
7316 entry.u.func = copyfunc(func);
7317 addcmdentry(name, &entry);
7321 static int evalskip; /* set if we are skipping commands */
7322 /* reasons for skipping commands (see comment on breakcmd routine) */
7323 #define SKIPBREAK (1 << 0)
7324 #define SKIPCONT (1 << 1)
7325 #define SKIPFUNC (1 << 2)
7326 #define SKIPFILE (1 << 3)
7327 #define SKIPEVAL (1 << 4)
7328 static int skipcount; /* number of levels to skip */
7329 static int funcnest; /* depth of function calls */
7331 /* forward decl way out to parsing code - dotrap needs it */
7332 static int evalstring(char *s, int mask);
7335 * Called to execute a trap. Perhaps we should avoid entering new trap
7336 * handlers while we are executing a trap handler.
7347 savestatus = exitstatus;
7351 for (i = 0, q = gotsig; i < NSIG - 1; i++, q++) {
7359 skip = evalstring(p, SKIPEVAL);
7360 exitstatus = savestatus;
7368 /* forward declarations - evaluation is fairly recursive business... */
7369 static void evalloop(union node *, int);
7370 static void evalfor(union node *, int);
7371 static void evalcase(union node *, int);
7372 static void evalsubshell(union node *, int);
7373 static void expredir(union node *);
7374 static void evalpipe(union node *, int);
7375 static void evalcommand(union node *, int);
7376 static int evalbltin(const struct builtincmd *, int, char **);
7377 static void prehash(union node *);
7380 * Evaluate a parse tree. The value is left in the global variable
7384 evaltree(union node *n, int flags)
7387 void (*evalfn)(union node *, int);
7391 TRACE(("evaltree(NULL) called\n"));
7394 TRACE(("pid %d, evaltree(%p: %d, %d) called\n",
7395 getpid(), n, n->type, flags));
7399 out1fmt("Node type = %d\n", n->type);
7404 evaltree(n->nnot.com, EV_TESTED);
7405 status = !exitstatus;
7408 expredir(n->nredir.redirect);
7409 status = redirectsafe(n->nredir.redirect, REDIR_PUSH);
7411 evaltree(n->nredir.n, flags & EV_TESTED);
7412 status = exitstatus;
7417 evalfn = evalcommand;
7419 if (eflag && !(flags & EV_TESTED))
7431 evalfn = evalsubshell;
7443 #error NAND + 1 != NOR
7445 #if NOR + 1 != NSEMI
7446 #error NOR + 1 != NSEMI
7448 isor = n->type - NAND;
7451 (flags | ((isor >> 1) - 1)) & EV_TESTED
7453 if (!exitstatus == isor)
7465 evaltree(n->nif.test, EV_TESTED);
7468 if (exitstatus == 0) {
7471 } else if (n->nif.elsepart) {
7472 n = n->nif.elsepart;
7477 defun(n->narg.text, n->narg.next);
7481 exitstatus = status;
7485 if ((checkexit & exitstatus))
7486 evalskip |= SKIPEVAL;
7487 else if (pendingsig && dotrap())
7490 if (flags & EV_EXIT) {
7492 raise_exception(EXEXIT);
7496 #if !defined(__alpha__) || (defined(__GNUC__) && __GNUC__ >= 3)
7499 void evaltreenr(union node *, int) __attribute__ ((alias("evaltree"),__noreturn__));
7501 static int loopnest; /* current loop nesting level */
7504 evalloop(union node *n, int flags)
7514 evaltree(n->nbinary.ch1, EV_TESTED);
7517 if (evalskip == SKIPCONT && --skipcount <= 0) {
7521 if (evalskip == SKIPBREAK && --skipcount <= 0)
7526 if (n->type != NWHILE)
7530 evaltree(n->nbinary.ch2, flags);
7531 status = exitstatus;
7536 exitstatus = status;
7540 evalfor(union node *n, int flags)
7542 struct arglist arglist;
7545 struct stackmark smark;
7547 setstackmark(&smark);
7548 arglist.lastp = &arglist.list;
7549 for (argp = n->nfor.args; argp; argp = argp->narg.next) {
7550 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE | EXP_RECORD);
7555 *arglist.lastp = NULL;
7560 for (sp = arglist.list; sp; sp = sp->next) {
7561 setvar(n->nfor.var, sp->text, 0);
7562 evaltree(n->nfor.body, flags);
7564 if (evalskip == SKIPCONT && --skipcount <= 0) {
7568 if (evalskip == SKIPBREAK && --skipcount <= 0)
7575 popstackmark(&smark);
7579 evalcase(union node *n, int flags)
7583 struct arglist arglist;
7584 struct stackmark smark;
7586 setstackmark(&smark);
7587 arglist.lastp = &arglist.list;
7588 expandarg(n->ncase.expr, &arglist, EXP_TILDE);
7590 for (cp = n->ncase.cases; cp && evalskip == 0; cp = cp->nclist.next) {
7591 for (patp = cp->nclist.pattern; patp; patp = patp->narg.next) {
7592 if (casematch(patp, arglist.list->text)) {
7593 if (evalskip == 0) {
7594 evaltree(cp->nclist.body, flags);
7601 popstackmark(&smark);
7605 * Kick off a subshell to evaluate a tree.
7608 evalsubshell(union node *n, int flags)
7611 int backgnd = (n->type == NBACKGND);
7614 expredir(n->nredir.redirect);
7615 if (!backgnd && flags & EV_EXIT && !trap[0])
7619 if (forkshell(jp, n, backgnd) == 0) {
7623 flags &=~ EV_TESTED;
7625 redirect(n->nredir.redirect, 0);
7626 evaltreenr(n->nredir.n, flags);
7631 status = waitforjob(jp);
7632 exitstatus = status;
7637 * Compute the names of the files in a redirection list.
7639 static void fixredir(union node *, const char *, int);
7641 expredir(union node *n)
7645 for (redir = n; redir; redir = redir->nfile.next) {
7648 memset(&fn, 0, sizeof(fn));
7649 fn.lastp = &fn.list;
7650 switch (redir->type) {
7656 expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
7657 redir->nfile.expfname = fn.list->text;
7661 if (redir->ndup.vname) {
7662 expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE);
7663 if (fn.list == NULL)
7664 ash_msg_and_raise_error("redir error");
7665 fixredir(redir, fn.list->text, 1);
7673 * Evaluate a pipeline. All the processes in the pipeline are children
7674 * of the process creating the pipeline. (This differs from some versions
7675 * of the shell, which make the last process in a pipeline the parent
7679 evalpipe(union node *n, int flags)
7682 struct nodelist *lp;
7687 TRACE(("evalpipe(0x%lx) called\n", (long)n));
7689 for (lp = n->npipe.cmdlist; lp; lp = lp->next)
7693 jp = makejob(n, pipelen);
7695 for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
7699 if (pipe(pip) < 0) {
7701 ash_msg_and_raise_error("pipe call failed");
7704 if (forkshell(jp, lp->n, n->npipe.backgnd) == 0) {
7717 evaltreenr(lp->n, flags);
7725 if (n->npipe.backgnd == 0) {
7726 exitstatus = waitforjob(jp);
7727 TRACE(("evalpipe: job done exit status %d\n", exitstatus));
7733 * Controls whether the shell is interactive or not.
7736 setinteractive(int on)
7738 static int is_interactive;
7740 if (++on == is_interactive)
7742 is_interactive = on;
7746 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
7747 if (is_interactive > 1) {
7748 /* Looks like they want an interactive shell */
7749 static smallint do_banner;
7754 "%s Built-in shell (ash)\n"
7755 "Enter 'help' for a list of built-in commands."
7764 #if ENABLE_FEATURE_EDITING_VI
7765 #define setvimode(on) do { \
7766 if (on) line_input_state->flags |= VI_MODE; \
7767 else line_input_state->flags &= ~VI_MODE; \
7770 #define setvimode(on) viflag = 0 /* forcibly keep the option off */
7779 setinteractive(iflag);
7784 static struct localvar *localvars;
7787 * Called after a function returns.
7788 * Interrupts must be off.
7793 struct localvar *lvp;
7796 while ((lvp = localvars) != NULL) {
7797 localvars = lvp->next;
7799 TRACE(("poplocalvar %s", vp ? vp->text : "-"));
7800 if (vp == NULL) { /* $- saved */
7801 memcpy(optlist, lvp->text, sizeof(optlist));
7802 free((char*)lvp->text);
7804 } else if ((lvp->flags & (VUNSET|VSTRFIXED)) == VUNSET) {
7808 (*vp->func)(strchrnul(lvp->text, '=') + 1);
7809 if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
7810 free((char*)vp->text);
7811 vp->flags = lvp->flags;
7812 vp->text = lvp->text;
7819 evalfun(struct funcnode *func, int argc, char **argv, int flags)
7821 volatile struct shparam saveparam;
7822 struct localvar *volatile savelocalvars;
7823 struct jmploc *volatile savehandler;
7824 struct jmploc jmploc;
7827 saveparam = shellparam;
7828 savelocalvars = localvars;
7829 e = setjmp(jmploc.loc);
7834 savehandler = exception_handler;
7835 exception_handler = &jmploc;
7837 shellparam.malloc = 0;
7841 shellparam.nparam = argc - 1;
7842 shellparam.p = argv + 1;
7843 #if ENABLE_ASH_GETOPTS
7844 shellparam.optind = 1;
7845 shellparam.optoff = -1;
7847 evaltree(&func->n, flags & EV_TESTED);
7853 localvars = savelocalvars;
7854 freeparam(&shellparam);
7855 shellparam = saveparam;
7856 exception_handler = savehandler;
7858 evalskip &= ~SKIPFUNC;
7862 #if ENABLE_ASH_CMDCMD
7864 parse_command_args(char **argv, const char **path)
7877 if (c == '-' && !*cp) {
7887 /* run 'typecmd' for other options */
7898 * Make a variable a local variable. When a variable is made local, it's
7899 * value and flags are saved in a localvar structure. The saved values
7900 * will be restored when the shell function returns. We handle the name
7901 * "-" as a special case.
7906 struct localvar *lvp;
7911 lvp = ckmalloc(sizeof(struct localvar));
7912 if (LONE_DASH(name)) {
7914 p = ckmalloc(sizeof(optlist));
7915 lvp->text = memcpy(p, optlist, sizeof(optlist));
7920 vpp = hashvar(name);
7921 vp = *findvar(vpp, name);
7922 eq = strchr(name, '=');
7925 setvareq(name, VSTRFIXED);
7927 setvar(name, NULL, VSTRFIXED);
7928 vp = *vpp; /* the new variable */
7929 lvp->flags = VUNSET;
7931 lvp->text = vp->text;
7932 lvp->flags = vp->flags;
7933 vp->flags |= VSTRFIXED|VTEXTFIXED;
7939 lvp->next = localvars;
7945 * The "local" command.
7948 localcmd(int argc, char **argv)
7953 while ((name = *argv++) != NULL) {
7960 falsecmd(int argc, char **argv)
7966 truecmd(int argc, char **argv)
7972 execcmd(int argc, char **argv)
7975 iflag = 0; /* exit on error */
7978 shellexec(argv + 1, pathval(), 0);
7984 * The return command.
7987 returncmd(int argc, char **argv)
7990 * If called outside a function, do what ksh does;
7991 * skip the rest of the file.
7993 evalskip = funcnest ? SKIPFUNC : SKIPFILE;
7994 return argv[1] ? number(argv[1]) : exitstatus;
7997 /* Forward declarations for builtintab[] */
7998 static int breakcmd(int, char **);
7999 static int dotcmd(int, char **);
8000 static int evalcmd(int, char **);
8001 #if ENABLE_ASH_BUILTIN_ECHO
8002 static int echocmd(int, char **);
8004 #if ENABLE_ASH_BUILTIN_TEST
8005 static int testcmd(int, char **);
8007 static int exitcmd(int, char **);
8008 static int exportcmd(int, char **);
8009 #if ENABLE_ASH_GETOPTS
8010 static int getoptscmd(int, char **);
8012 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
8013 static int helpcmd(int argc, char **argv);
8015 #if ENABLE_ASH_MATH_SUPPORT
8016 static int letcmd(int, char **);
8018 static int readcmd(int, char **);
8019 static int setcmd(int, char **);
8020 static int shiftcmd(int, char **);
8021 static int timescmd(int, char **);
8022 static int trapcmd(int, char **);
8023 static int umaskcmd(int, char **);
8024 static int unsetcmd(int, char **);
8025 static int ulimitcmd(int, char **);
8027 #define BUILTIN_NOSPEC "0"
8028 #define BUILTIN_SPECIAL "1"
8029 #define BUILTIN_REGULAR "2"
8030 #define BUILTIN_SPEC_REG "3"
8031 #define BUILTIN_ASSIGN "4"
8032 #define BUILTIN_SPEC_ASSG "5"
8033 #define BUILTIN_REG_ASSG "6"
8034 #define BUILTIN_SPEC_REG_ASSG "7"
8036 /* make sure to keep these in proper order since it is searched via bsearch() */
8037 static const struct builtincmd builtintab[] = {
8038 { BUILTIN_SPEC_REG ".", dotcmd },
8039 { BUILTIN_SPEC_REG ":", truecmd },
8040 #if ENABLE_ASH_BUILTIN_TEST
8041 { BUILTIN_REGULAR "[", testcmd },
8042 { BUILTIN_REGULAR "[[", testcmd },
8044 #if ENABLE_ASH_ALIAS
8045 { BUILTIN_REG_ASSG "alias", aliascmd },
8048 { BUILTIN_REGULAR "bg", fg_bgcmd },
8050 { BUILTIN_SPEC_REG "break", breakcmd },
8051 { BUILTIN_REGULAR "cd", cdcmd },
8052 { BUILTIN_NOSPEC "chdir", cdcmd },
8053 #if ENABLE_ASH_CMDCMD
8054 { BUILTIN_REGULAR "command", commandcmd },
8056 { BUILTIN_SPEC_REG "continue", breakcmd },
8057 #if ENABLE_ASH_BUILTIN_ECHO
8058 { BUILTIN_REGULAR "echo", echocmd },
8060 { BUILTIN_SPEC_REG "eval", evalcmd },
8061 { BUILTIN_SPEC_REG "exec", execcmd },
8062 { BUILTIN_SPEC_REG "exit", exitcmd },
8063 { BUILTIN_SPEC_REG_ASSG "export", exportcmd },
8064 { BUILTIN_REGULAR "false", falsecmd },
8066 { BUILTIN_REGULAR "fg", fg_bgcmd },
8068 #if ENABLE_ASH_GETOPTS
8069 { BUILTIN_REGULAR "getopts", getoptscmd },
8071 { BUILTIN_NOSPEC "hash", hashcmd },
8072 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
8073 { BUILTIN_NOSPEC "help", helpcmd },
8076 { BUILTIN_REGULAR "jobs", jobscmd },
8077 { BUILTIN_REGULAR "kill", killcmd },
8079 #if ENABLE_ASH_MATH_SUPPORT
8080 { BUILTIN_NOSPEC "let", letcmd },
8082 { BUILTIN_ASSIGN "local", localcmd },
8083 { BUILTIN_NOSPEC "pwd", pwdcmd },
8084 { BUILTIN_REGULAR "read", readcmd },
8085 { BUILTIN_SPEC_REG_ASSG "readonly", exportcmd },
8086 { BUILTIN_SPEC_REG "return", returncmd },
8087 { BUILTIN_SPEC_REG "set", setcmd },
8088 { BUILTIN_SPEC_REG "shift", shiftcmd },
8089 { BUILTIN_SPEC_REG "source", dotcmd },
8090 #if ENABLE_ASH_BUILTIN_TEST
8091 { BUILTIN_REGULAR "test", testcmd },
8093 { BUILTIN_SPEC_REG "times", timescmd },
8094 { BUILTIN_SPEC_REG "trap", trapcmd },
8095 { BUILTIN_REGULAR "true", truecmd },
8096 { BUILTIN_NOSPEC "type", typecmd },
8097 { BUILTIN_NOSPEC "ulimit", ulimitcmd },
8098 { BUILTIN_REGULAR "umask", umaskcmd },
8099 #if ENABLE_ASH_ALIAS
8100 { BUILTIN_REGULAR "unalias", unaliascmd },
8102 { BUILTIN_SPEC_REG "unset", unsetcmd },
8103 { BUILTIN_REGULAR "wait", waitcmd },
8106 #define NUMBUILTINS (sizeof(builtintab) / sizeof(builtintab[0]))
8108 #define COMMANDCMD (builtintab + 5 + \
8109 2 * ENABLE_ASH_BUILTIN_TEST + \
8110 ENABLE_ASH_ALIAS + \
8111 ENABLE_ASH_JOB_CONTROL)
8112 #define EXECCMD (builtintab + 7 + \
8113 2 * ENABLE_ASH_BUILTIN_TEST + \
8114 ENABLE_ASH_ALIAS + \
8115 ENABLE_ASH_JOB_CONTROL + \
8116 ENABLE_ASH_CMDCMD + \
8117 ENABLE_ASH_BUILTIN_ECHO)
8120 * Search the table of builtin commands.
8122 static struct builtincmd *
8123 find_builtin(const char *name)
8125 struct builtincmd *bp;
8128 name, builtintab, NUMBUILTINS, sizeof(builtintab[0]),
8135 * Execute a simple command.
8137 static int back_exitstatus; /* exit status of backquoted command */
8139 isassignment(const char *p)
8141 const char *q = endofname(p);
8147 bltincmd(int argc, char **argv)
8149 /* Preserve exitstatus of a previous possible redirection
8150 * as POSIX mandates */
8151 return back_exitstatus;
8154 evalcommand(union node *cmd, int flags)
8156 static const struct builtincmd bltin = {
8159 struct stackmark smark;
8161 struct arglist arglist;
8162 struct arglist varlist;
8165 const struct strlist *sp;
8166 struct cmdentry cmdentry;
8174 struct builtincmd *bcmd;
8175 int pseudovarflag = 0;
8177 /* First expand the arguments. */
8178 TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
8179 setstackmark(&smark);
8180 back_exitstatus = 0;
8182 cmdentry.cmdtype = CMDBUILTIN;
8183 cmdentry.u.cmd = &bltin;
8184 varlist.lastp = &varlist.list;
8185 *varlist.lastp = NULL;
8186 arglist.lastp = &arglist.list;
8187 *arglist.lastp = NULL;
8190 if (cmd->ncmd.args) {
8191 bcmd = find_builtin(cmd->ncmd.args->narg.text);
8192 pseudovarflag = bcmd && IS_BUILTIN_ASSIGN(bcmd);
8195 for (argp = cmd->ncmd.args; argp; argp = argp->narg.next) {
8196 struct strlist **spp;
8198 spp = arglist.lastp;
8199 if (pseudovarflag && isassignment(argp->narg.text))
8200 expandarg(argp, &arglist, EXP_VARTILDE);
8202 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
8204 for (sp = *spp; sp; sp = sp->next)
8208 argv = nargv = stalloc(sizeof(char *) * (argc + 1));
8209 for (sp = arglist.list; sp; sp = sp->next) {
8210 TRACE(("evalcommand arg: %s\n", sp->text));
8211 *nargv++ = sp->text;
8216 if (iflag && funcnest == 0 && argc > 0)
8217 lastarg = nargv[-1];
8220 expredir(cmd->ncmd.redirect);
8221 status = redirectsafe(cmd->ncmd.redirect, REDIR_PUSH | REDIR_SAVEFD2);
8224 for (argp = cmd->ncmd.assign; argp; argp = argp->narg.next) {
8225 struct strlist **spp;
8228 spp = varlist.lastp;
8229 expandarg(argp, &varlist, EXP_VARTILDE);
8232 * Modify the command lookup path, if a PATH= assignment
8236 if (varequal(p, path))
8240 /* Print the command if xflag is set. */
8243 const char *p = " %s";
8246 dprintf(preverrout_fd, p, expandstr(ps4val()));
8249 for (n = 0; n < 2; n++) {
8251 dprintf(preverrout_fd, p, sp->text);
8259 full_write(preverrout_fd, "\n", 1);
8265 /* Now locate the command. */
8267 const char *oldpath;
8268 int cmd_flag = DO_ERR;
8273 find_command(argv[0], &cmdentry, cmd_flag, path);
8274 if (cmdentry.cmdtype == CMDUNKNOWN) {
8280 /* implement bltin and command here */
8281 if (cmdentry.cmdtype != CMDBUILTIN)
8284 spclbltin = IS_BUILTIN_SPECIAL(cmdentry.u.cmd);
8285 if (cmdentry.u.cmd == EXECCMD)
8287 #if ENABLE_ASH_CMDCMD
8288 if (cmdentry.u.cmd == COMMANDCMD) {
8290 nargv = parse_command_args(argv, &path);
8293 argc -= nargv - argv;
8295 cmd_flag |= DO_NOFUNC;
8303 /* We have a redirection error. */
8305 raise_exception(EXERROR);
8307 exitstatus = status;
8311 /* Execute the command. */
8312 switch (cmdentry.cmdtype) {
8314 /* Fork off a child process if necessary. */
8315 if (!(flags & EV_EXIT) || trap[0]) {
8317 jp = makejob(cmd, 1);
8318 if (forkshell(jp, cmd, FORK_FG) != 0) {
8319 exitstatus = waitforjob(jp);
8325 listsetvar(varlist.list, VEXPORT|VSTACK);
8326 shellexec(argv, path, cmdentry.u.index);
8330 cmdenviron = varlist.list;
8332 struct strlist *list = cmdenviron;
8334 if (spclbltin > 0 || argc == 0) {
8336 if (cmd_is_exec && argc > 1)
8339 listsetvar(list, i);
8341 if (evalbltin(cmdentry.u.cmd, argc, argv)) {
8356 exit_status = j + 128;
8357 exitstatus = exit_status;
8359 if (i == EXINT || spclbltin > 0) {
8361 longjmp(exception_handler->loc, 1);
8368 listsetvar(varlist.list, 0);
8369 if (evalfun(cmdentry.u.func, argc, argv, flags))
8375 popredir(cmd_is_exec);
8377 /* dsl: I think this is intended to be used to support
8378 * '_' in 'vi' command mode during line editing...
8379 * However I implemented that within libedit itself.
8381 setvar("_", lastarg, 0);
8382 popstackmark(&smark);
8386 evalbltin(const struct builtincmd *cmd, int argc, char **argv)
8388 char *volatile savecmdname;
8389 struct jmploc *volatile savehandler;
8390 struct jmploc jmploc;
8393 savecmdname = commandname;
8394 i = setjmp(jmploc.loc);
8397 savehandler = exception_handler;
8398 exception_handler = &jmploc;
8399 commandname = argv[0];
8401 optptr = NULL; /* initialize nextopt */
8402 exitstatus = (*cmd->builtin)(argc, argv);
8403 flush_stdout_stderr();
8405 exitstatus |= ferror(stdout);
8407 commandname = savecmdname;
8409 exception_handler = savehandler;
8415 goodname(const char *p)
8417 return !*endofname(p);
8422 * Search for a command. This is called before we fork so that the
8423 * location of the command will be available in the parent as well as
8424 * the child. The check for "goodname" is an overly conservative
8425 * check that the name will not be subject to expansion.
8428 prehash(union node *n)
8430 struct cmdentry entry;
8432 if (n->type == NCMD && n->ncmd.args && goodname(n->ncmd.args->narg.text))
8433 find_command(n->ncmd.args->narg.text, &entry, 0, pathval());
8437 /* ============ Builtin commands
8439 * Builtin commands whose functions are closely tied to evaluation
8440 * are implemented here.
8444 * Handle break and continue commands. Break, continue, and return are
8445 * all handled by setting the evalskip flag. The evaluation routines
8446 * above all check this flag, and if it is set they start skipping
8447 * commands rather than executing them. The variable skipcount is
8448 * the number of loops to break/continue, or the number of function
8449 * levels to return. (The latter is always 1.) It should probably
8450 * be an error to break out of more loops than exist, but it isn't
8451 * in the standard shell so we don't make it one here.
8454 breakcmd(int argc, char **argv)
8456 int n = argc > 1 ? number(argv[1]) : 1;
8459 ash_msg_and_raise_error(illnum, argv[1]);
8463 evalskip = (**argv == 'c') ? SKIPCONT : SKIPBREAK;
8470 /* ============ input.c
8472 * This implements the input routines used by the parser.
8475 #define EOF_NLEFT -99 /* value of parsenleft when EOF pushed back */
8478 INPUT_PUSH_FILE = 1,
8479 INPUT_NOFILE_OK = 2,
8483 * NEOF is returned by parsecmd when it encounters an end of file. It
8484 * must be distinct from NULL, so we use the address of a variable that
8485 * happens to be handy.
8487 static int plinno = 1; /* input line number */
8488 /* number of characters left in input buffer */
8489 static int parsenleft; /* copy of parsefile->nleft */
8490 static int parselleft; /* copy of parsefile->lleft */
8491 /* next character in input buffer */
8492 static char *parsenextc; /* copy of parsefile->nextc */
8494 static int checkkwd;
8495 /* values of checkkwd variable */
8496 #define CHKALIAS 0x1
8503 struct strpush *sp = parsefile->strpush;
8506 #if ENABLE_ASH_ALIAS
8508 if (parsenextc[-1] == ' ' || parsenextc[-1] == '\t') {
8509 checkkwd |= CHKALIAS;
8511 if (sp->string != sp->ap->val) {
8514 sp->ap->flag &= ~ALIASINUSE;
8515 if (sp->ap->flag & ALIASDEAD) {
8516 unalias(sp->ap->name);
8520 parsenextc = sp->prevstring;
8521 parsenleft = sp->prevnleft;
8522 /*dprintf("*** calling popstring: restoring to '%s'\n", parsenextc);*/
8523 parsefile->strpush = sp->prev;
8524 if (sp != &(parsefile->basestrpush))
8533 char *buf = parsefile->buf;
8537 #if ENABLE_FEATURE_EDITING
8538 if (!iflag || parsefile->fd)
8539 nr = safe_read(parsefile->fd, buf, BUFSIZ - 1);
8541 #if ENABLE_FEATURE_TAB_COMPLETION
8542 line_input_state->path_lookup = pathval();
8544 nr = read_line_input(cmdedit_prompt, buf, BUFSIZ, line_input_state);
8546 /* Ctrl+C pressed */
8555 if (nr < 0 && errno == 0) {
8556 /* Ctrl+D presend */
8561 nr = safe_read(parsefile->fd, buf, BUFSIZ - 1);
8565 if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
8566 int flags = fcntl(0, F_GETFL, 0);
8567 if (flags >= 0 && flags & O_NONBLOCK) {
8568 flags &=~ O_NONBLOCK;
8569 if (fcntl(0, F_SETFL, flags) >= 0) {
8570 out2str("sh: turning off NDELAY mode\n");
8580 * Refill the input buffer and return the next input character:
8582 * 1) If a string was pushed back on the input, pop it;
8583 * 2) If an EOF was pushed back (parsenleft == EOF_NLEFT) or we are reading
8584 * from a string so we can't refill the buffer, return EOF.
8585 * 3) If the is more stuff in this buffer, use it else call read to fill it.
8586 * 4) Process input up to the next newline, deleting nul characters.
8595 while (parsefile->strpush) {
8596 #if ENABLE_ASH_ALIAS
8597 if (parsenleft == -1 && parsefile->strpush->ap &&
8598 parsenextc[-1] != ' ' && parsenextc[-1] != '\t') {
8603 if (--parsenleft >= 0)
8604 return signed_char2int(*parsenextc++);
8606 if (parsenleft == EOF_NLEFT || parsefile->buf == NULL)
8608 flush_stdout_stderr();
8615 parselleft = parsenleft = EOF_NLEFT;
8622 /* delete nul characters */
8630 memmove(q, q + 1, more);
8634 parsenleft = q - parsenextc - 1;
8640 parsenleft = q - parsenextc - 1;
8652 out2str(parsenextc);
8657 return signed_char2int(*parsenextc++);
8660 #define pgetc_as_macro() (--parsenleft >= 0? signed_char2int(*parsenextc++) : preadbuffer())
8664 return pgetc_as_macro();
8667 #if ENABLE_ASH_OPTIMIZE_FOR_SIZE
8668 #define pgetc_macro() pgetc()
8670 #define pgetc_macro() pgetc_as_macro()
8674 * Same as pgetc(), but ignores PEOA.
8676 #if ENABLE_ASH_ALIAS
8684 } while (c == PEOA);
8691 return pgetc_macro();
8696 * Read a line from the script.
8699 pfgets(char *line, int len)
8705 while (--nleft > 0) {
8721 * Undo the last call to pgetc. Only one character may be pushed back.
8722 * PEOF may be pushed back.
8732 * Push a string back onto the input at this current parsefile level.
8733 * We handle aliases this way.
8736 pushstring(char *s, void *ap)
8743 /*dprintf("*** calling pushstring: %s, %d\n", s, len);*/
8744 if (parsefile->strpush) {
8745 sp = ckmalloc(sizeof(struct strpush));
8746 sp->prev = parsefile->strpush;
8747 parsefile->strpush = sp;
8749 sp = parsefile->strpush = &(parsefile->basestrpush);
8750 sp->prevstring = parsenextc;
8751 sp->prevnleft = parsenleft;
8752 #if ENABLE_ASH_ALIAS
8753 sp->ap = (struct alias *)ap;
8755 ((struct alias *)ap)->flag |= ALIASINUSE;
8765 * To handle the "." command, a stack of input files is used. Pushfile
8766 * adds a new entry to the stack and popfile restores the previous level.
8771 struct parsefile *pf;
8773 parsefile->nleft = parsenleft;
8774 parsefile->lleft = parselleft;
8775 parsefile->nextc = parsenextc;
8776 parsefile->linno = plinno;
8777 pf = ckmalloc(sizeof(*pf));
8778 pf->prev = parsefile;
8781 pf->basestrpush.prev = NULL;
8788 struct parsefile *pf = parsefile;
8797 parsefile = pf->prev;
8799 parsenleft = parsefile->nleft;
8800 parselleft = parsefile->lleft;
8801 parsenextc = parsefile->nextc;
8802 plinno = parsefile->linno;
8807 * Return to top level.
8812 while (parsefile != &basepf)
8817 * Close the file(s) that the shell is reading commands from. Called
8818 * after a fork is done.
8824 if (parsefile->fd > 0) {
8825 close(parsefile->fd);
8831 * Like setinputfile, but takes an open file descriptor. Call this with
8835 setinputfd(int fd, int push)
8837 fcntl(fd, F_SETFD, FD_CLOEXEC);
8843 if (parsefile->buf == NULL)
8844 parsefile->buf = ckmalloc(IBUFSIZ);
8845 parselleft = parsenleft = 0;
8850 * Set the input to take input from a file. If push is set, push the
8851 * old input onto the stack first.
8854 setinputfile(const char *fname, int flags)
8860 fd = open(fname, O_RDONLY);
8862 if (flags & INPUT_NOFILE_OK)
8864 ash_msg_and_raise_error("can't open %s", fname);
8867 fd2 = copyfd(fd, 10);
8870 ash_msg_and_raise_error("out of file descriptors");
8873 setinputfd(fd, flags & INPUT_PUSH_FILE);
8880 * Like setinputfile, but takes input from a string.
8883 setinputstring(char *string)
8887 parsenextc = string;
8888 parsenleft = strlen(string);
8889 parsefile->buf = NULL;
8895 /* ============ mail.c
8897 * Routines to check for mail.
8902 #define MAXMBOXES 10
8904 /* times of mailboxes */
8905 static time_t mailtime[MAXMBOXES];
8906 /* Set if MAIL or MAILPATH is changed. */
8907 static int mail_var_path_changed;
8910 * Print appropriate message(s) if mail has arrived.
8911 * If mail_var_path_changed is set,
8912 * then the value of MAIL has mail_var_path_changed,
8913 * so we just update the values.
8922 struct stackmark smark;
8925 setstackmark(&smark);
8926 mpath = mpathset() ? mpathval() : mailval();
8927 for (mtp = mailtime; mtp < mailtime + MAXMBOXES; mtp++) {
8928 p = padvance(&mpath, nullstr);
8933 for (q = p; *q; q++);
8938 q[-1] = '\0'; /* delete trailing '/' */
8939 if (stat(p, &statb) < 0) {
8943 if (!mail_var_path_changed && statb.st_mtime != *mtp) {
8946 pathopt ? pathopt : "you have mail"
8949 *mtp = statb.st_mtime;
8951 mail_var_path_changed = 0;
8952 popstackmark(&smark);
8956 changemail(const char *val)
8958 mail_var_path_changed++;
8961 #endif /* ASH_MAIL */
8964 /* ============ ??? */
8967 * Set the shell parameters.
8970 setparam(char **argv)
8976 for (nparam = 0; argv[nparam]; nparam++);
8977 ap = newparam = ckmalloc((nparam + 1) * sizeof(*ap));
8979 *ap++ = ckstrdup(*argv++);
8982 freeparam(&shellparam);
8983 shellparam.malloc = 1;
8984 shellparam.nparam = nparam;
8985 shellparam.p = newparam;
8986 #if ENABLE_ASH_GETOPTS
8987 shellparam.optind = 1;
8988 shellparam.optoff = -1;
8993 * Process shell options. The global variable argptr contains a pointer
8994 * to the argument list; we advance it past the options.
8997 minus_o(char *name, int val)
9002 for (i = 0; i < NOPTS; i++) {
9003 if (strcmp(name, optnames(i)) == 0) {
9008 ash_msg_and_raise_error("illegal option -o %s", name);
9010 out1str("Current option settings\n");
9011 for (i = 0; i < NOPTS; i++)
9012 out1fmt("%-16s%s\n", optnames(i),
9013 optlist[i] ? "on" : "off");
9016 setoption(int flag, int val)
9020 for (i = 0; i < NOPTS; i++) {
9021 if (optletters(i) == flag) {
9026 ash_msg_and_raise_error("illegal option -%c", flag);
9030 options(int cmdline)
9038 while ((p = *argptr) != NULL) {
9043 if (p[0] == '\0' || LONE_DASH(p)) {
9045 /* "-" means turn off -x and -v */
9048 /* "--" means reset params */
9049 else if (*argptr == NULL)
9052 break; /* "-" or "--" terminates options */
9054 } else if (c == '+') {
9060 while ((c = *p++) != '\0') {
9061 if (c == 'c' && cmdline) {
9062 minusc = p; /* command is after shell args*/
9063 } else if (c == 'o') {
9064 minus_o(*argptr, val);
9067 } else if (cmdline && (c == '-')) { // long options
9068 if (strcmp(p, "login") == 0)
9079 * The shift builtin command.
9082 shiftcmd(int argc, char **argv)
9089 n = number(argv[1]);
9090 if (n > shellparam.nparam)
9091 ash_msg_and_raise_error("can't shift that many");
9093 shellparam.nparam -= n;
9094 for (ap1 = shellparam.p; --n >= 0; ap1++) {
9095 if (shellparam.malloc)
9099 while ((*ap2++ = *ap1++) != NULL);
9100 #if ENABLE_ASH_GETOPTS
9101 shellparam.optind = 1;
9102 shellparam.optoff = -1;
9109 * POSIX requires that 'set' (but not export or readonly) output the
9110 * variables in lexicographic order - by the locale's collating order (sigh).
9111 * Maybe we could keep them in an ordered balanced binary tree
9112 * instead of hashed lists.
9113 * For now just roll 'em through qsort for printing...
9116 showvars(const char *sep_prefix, int on, int off)
9121 ep = listvars(on, off, &epend);
9122 qsort(ep, epend - ep, sizeof(char *), vpcmp);
9124 sep = *sep_prefix ? " " : sep_prefix;
9126 for (; ep < epend; ep++) {
9130 p = strchrnul(*ep, '=');
9133 q = single_quote(++p);
9134 out1fmt("%s%s%.*s%s\n", sep_prefix, sep, (int)(p - *ep), *ep, q);
9140 * The set command builtin.
9143 setcmd(int argc, char **argv)
9146 return showvars(nullstr, 0, VUNSET);
9150 if (*argptr != NULL) {
9157 #if ENABLE_ASH_RANDOM_SUPPORT
9158 /* Roughly copied from bash.. */
9160 change_random(const char *value)
9162 if (value == NULL) {
9163 /* "get", generate */
9166 rseed = rseed * 1103515245 + 12345;
9167 sprintf(buf, "%d", (unsigned int)((rseed & 32767)));
9168 /* set without recursion */
9169 setvar(vrandom.text, buf, VNOFUNC);
9170 vrandom.flags &= ~VNOFUNC;
9173 rseed = strtoul(value, (char **)NULL, 10);
9178 #if ENABLE_ASH_GETOPTS
9180 getopts(char *optstr, char *optvar, char **optfirst, int *param_optind, int *optoff)
9189 if (*param_optind < 1)
9191 optnext = optfirst + *param_optind - 1;
9193 if (*param_optind <= 1 || *optoff < 0 || strlen(optnext[-1]) < *optoff)
9196 p = optnext[-1] + *optoff;
9197 if (p == NULL || *p == '\0') {
9198 /* Current word is done, advance */
9200 if (p == NULL || *p != '-' || *++p == '\0') {
9207 if (LONE_DASH(p)) /* check for "--" */
9212 for (q = optstr; *q != c; ) {
9214 if (optstr[0] == ':') {
9217 err |= setvarsafe("OPTARG", s, 0);
9219 fprintf(stderr, "Illegal option -%c\n", c);
9230 if (*p == '\0' && (p = *optnext) == NULL) {
9231 if (optstr[0] == ':') {
9234 err |= setvarsafe("OPTARG", s, 0);
9237 fprintf(stderr, "No arg for -%c option\n", c);
9246 err |= setvarsafe("OPTARG", p, 0);
9249 err |= setvarsafe("OPTARG", nullstr, 0);
9251 *optoff = p ? p - *(optnext - 1) : -1;
9252 *param_optind = optnext - optfirst + 1;
9253 fmtstr(s, sizeof(s), "%d", *param_optind);
9254 err |= setvarsafe("OPTIND", s, VNOFUNC);
9257 err |= setvarsafe(optvar, s, 0);
9261 flush_stdout_stderr();
9262 raise_exception(EXERROR);
9268 * The getopts builtin. Shellparam.optnext points to the next argument
9269 * to be processed. Shellparam.optptr points to the next character to
9270 * be processed in the current argument. If shellparam.optnext is NULL,
9271 * then it's the first time getopts has been called.
9274 getoptscmd(int argc, char **argv)
9279 ash_msg_and_raise_error("usage: getopts optstring var [arg]");
9281 optbase = shellparam.p;
9282 if (shellparam.optind > shellparam.nparam + 1) {
9283 shellparam.optind = 1;
9284 shellparam.optoff = -1;
9288 if (shellparam.optind > argc - 2) {
9289 shellparam.optind = 1;
9290 shellparam.optoff = -1;
9294 return getopts(argv[1], argv[2], optbase, &shellparam.optind,
9295 &shellparam.optoff);
9297 #endif /* ASH_GETOPTS */
9300 /* ============ Shell parser */
9302 static int tokpushback; /* last token pushed back */
9303 #define NEOF ((union node *)&tokpushback)
9304 static int parsebackquote; /* nonzero if we are inside backquotes */
9305 static int lasttoken; /* last token read */
9306 static char *wordtext; /* text of last word returned by readtoken */
9307 static struct nodelist *backquotelist;
9308 static union node *redirnode;
9309 static struct heredoc *heredoc;
9310 static int quoteflag; /* set if (part of) last token was quoted */
9312 static void raise_error_syntax(const char *) ATTRIBUTE_NORETURN;
9314 raise_error_syntax(const char *msg)
9316 ash_msg_and_raise_error("syntax error: %s", msg);
9321 * Called when an unexpected token is read during the parse. The argument
9322 * is the token that is expected, or -1 if more than one type of token can
9323 * occur at this point.
9325 static void raise_error_unexpected_syntax(int) ATTRIBUTE_NORETURN;
9327 raise_error_unexpected_syntax(int token)
9332 l = sprintf(msg, "%s unexpected", tokname(lasttoken));
9334 sprintf(msg + l, " (expecting %s)", tokname(token));
9335 raise_error_syntax(msg);
9339 #define EOFMARKLEN 79
9342 struct heredoc *next; /* next here document in list */
9343 union node *here; /* redirection node */
9344 char *eofmark; /* string indicating end of input */
9345 int striptabs; /* if set, strip leading tabs */
9348 static struct heredoc *heredoclist; /* list of here documents to read */
9350 /* parsing is heavily cross-recursive, need these forward decls */
9351 static union node *andor(void);
9352 static union node *pipeline(void);
9353 static union node *parse_command(void);
9354 static void parseheredoc(void);
9355 static char peektoken(void);
9356 static int readtoken(void);
9361 union node *n1, *n2, *n3;
9364 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9365 if (nlflag == 2 && peektoken())
9371 if (tok == TBACKGND) {
9372 if (n2->type == NPIPE) {
9373 n2->npipe.backgnd = 1;
9375 if (n2->type != NREDIR) {
9376 n3 = stalloc(sizeof(struct nredir));
9378 n3->nredir.redirect = NULL;
9381 n2->type = NBACKGND;
9387 n3 = stalloc(sizeof(struct nbinary));
9389 n3->nbinary.ch1 = n1;
9390 n3->nbinary.ch2 = n2;
9406 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9414 pungetc(); /* push back EOF on input */
9418 raise_error_unexpected_syntax(-1);
9428 union node *n1, *n2, *n3;
9436 } else if (t == TOR) {
9442 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9444 n3 = stalloc(sizeof(struct nbinary));
9446 n3->nbinary.ch1 = n1;
9447 n3->nbinary.ch2 = n2;
9455 union node *n1, *n2, *pipenode;
9456 struct nodelist *lp, *prev;
9460 TRACE(("pipeline: entered\n"));
9461 if (readtoken() == TNOT) {
9463 checkkwd = CHKKWD | CHKALIAS;
9466 n1 = parse_command();
9467 if (readtoken() == TPIPE) {
9468 pipenode = stalloc(sizeof(struct npipe));
9469 pipenode->type = NPIPE;
9470 pipenode->npipe.backgnd = 0;
9471 lp = stalloc(sizeof(struct nodelist));
9472 pipenode->npipe.cmdlist = lp;
9476 lp = stalloc(sizeof(struct nodelist));
9477 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9478 lp->n = parse_command();
9480 } while (readtoken() == TPIPE);
9486 n2 = stalloc(sizeof(struct nnot));
9499 n = stalloc(sizeof(struct narg));
9501 n->narg.next = NULL;
9502 n->narg.text = wordtext;
9503 n->narg.backquote = backquotelist;
9508 fixredir(union node *n, const char *text, int err)
9510 TRACE(("Fix redir %s %d\n", text, err));
9512 n->ndup.vname = NULL;
9514 if (isdigit(text[0]) && text[1] == '\0')
9515 n->ndup.dupfd = text[0] - '0';
9516 else if (LONE_DASH(text))
9520 raise_error_syntax("Bad fd number");
9521 n->ndup.vname = makename();
9526 * Returns true if the text contains nothing to expand (no dollar signs
9530 noexpand(char *text)
9536 while ((c = *p++) != '\0') {
9537 if (c == CTLQUOTEMARK)
9541 else if (SIT(c, BASESYNTAX) == CCTL)
9550 union node *n = redirnode;
9552 if (readtoken() != TWORD)
9553 raise_error_unexpected_syntax(-1);
9554 if (n->type == NHERE) {
9555 struct heredoc *here = heredoc;
9561 TRACE(("Here document %d\n", n->type));
9562 if (!noexpand(wordtext) || (i = strlen(wordtext)) == 0 || i > EOFMARKLEN)
9563 raise_error_syntax("Illegal eof marker for << redirection");
9564 rmescapes(wordtext);
9565 here->eofmark = wordtext;
9567 if (heredoclist == NULL)
9570 for (p = heredoclist; p->next; p = p->next);
9573 } else if (n->type == NTOFD || n->type == NFROMFD) {
9574 fixredir(n, wordtext, 0);
9576 n->nfile.fname = makename();
9583 union node *args, **app;
9584 union node *n = NULL;
9585 union node *vars, **vpp;
9586 union node **rpp, *redir;
9596 savecheckkwd = CHKALIAS;
9598 checkkwd = savecheckkwd;
9599 switch (readtoken()) {
9601 n = stalloc(sizeof(struct narg));
9603 n->narg.text = wordtext;
9604 n->narg.backquote = backquotelist;
9605 if (savecheckkwd && isassignment(wordtext)) {
9607 vpp = &n->narg.next;
9610 app = &n->narg.next;
9615 *rpp = n = redirnode;
9616 rpp = &n->nfile.next;
9617 parsefname(); /* read name of redirection file */
9620 if (args && app == &args->narg.next
9623 struct builtincmd *bcmd;
9626 /* We have a function */
9627 if (readtoken() != TRP)
9628 raise_error_unexpected_syntax(TRP);
9629 name = n->narg.text;
9631 || ((bcmd = find_builtin(name)) && IS_BUILTIN_SPECIAL(bcmd))
9633 raise_error_syntax("Bad function name");
9636 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9637 n->narg.next = parse_command();
9650 n = stalloc(sizeof(struct ncmd));
9652 n->ncmd.args = args;
9653 n->ncmd.assign = vars;
9654 n->ncmd.redirect = redir;
9661 union node *n1, *n2;
9662 union node *ap, **app;
9663 union node *cp, **cpp;
9664 union node *redir, **rpp;
9671 switch (readtoken()) {
9673 raise_error_unexpected_syntax(-1);
9676 n1 = stalloc(sizeof(struct nif));
9678 n1->nif.test = list(0);
9679 if (readtoken() != TTHEN)
9680 raise_error_unexpected_syntax(TTHEN);
9681 n1->nif.ifpart = list(0);
9683 while (readtoken() == TELIF) {
9684 n2->nif.elsepart = stalloc(sizeof(struct nif));
9685 n2 = n2->nif.elsepart;
9687 n2->nif.test = list(0);
9688 if (readtoken() != TTHEN)
9689 raise_error_unexpected_syntax(TTHEN);
9690 n2->nif.ifpart = list(0);
9692 if (lasttoken == TELSE)
9693 n2->nif.elsepart = list(0);
9695 n2->nif.elsepart = NULL;
9703 n1 = stalloc(sizeof(struct nbinary));
9704 n1->type = (lasttoken == TWHILE) ? NWHILE : NUNTIL;
9705 n1->nbinary.ch1 = list(0);
9708 TRACE(("expecting DO got %s %s\n", tokname(got),
9709 got == TWORD ? wordtext : ""));
9710 raise_error_unexpected_syntax(TDO);
9712 n1->nbinary.ch2 = list(0);
9717 if (readtoken() != TWORD || quoteflag || ! goodname(wordtext))
9718 raise_error_syntax("Bad for loop variable");
9719 n1 = stalloc(sizeof(struct nfor));
9721 n1->nfor.var = wordtext;
9722 checkkwd = CHKKWD | CHKALIAS;
9723 if (readtoken() == TIN) {
9725 while (readtoken() == TWORD) {
9726 n2 = stalloc(sizeof(struct narg));
9728 n2->narg.text = wordtext;
9729 n2->narg.backquote = backquotelist;
9731 app = &n2->narg.next;
9735 if (lasttoken != TNL && lasttoken != TSEMI)
9736 raise_error_unexpected_syntax(-1);
9738 n2 = stalloc(sizeof(struct narg));
9740 n2->narg.text = (char *)dolatstr;
9741 n2->narg.backquote = NULL;
9742 n2->narg.next = NULL;
9745 * Newline or semicolon here is optional (but note
9746 * that the original Bourne shell only allowed NL).
9748 if (lasttoken != TNL && lasttoken != TSEMI)
9751 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9752 if (readtoken() != TDO)
9753 raise_error_unexpected_syntax(TDO);
9754 n1->nfor.body = list(0);
9758 n1 = stalloc(sizeof(struct ncase));
9760 if (readtoken() != TWORD)
9761 raise_error_unexpected_syntax(TWORD);
9762 n1->ncase.expr = n2 = stalloc(sizeof(struct narg));
9764 n2->narg.text = wordtext;
9765 n2->narg.backquote = backquotelist;
9766 n2->narg.next = NULL;
9768 checkkwd = CHKKWD | CHKALIAS;
9769 } while (readtoken() == TNL);
9770 if (lasttoken != TIN)
9771 raise_error_unexpected_syntax(TIN);
9772 cpp = &n1->ncase.cases;
9774 checkkwd = CHKNL | CHKKWD;
9776 while (t != TESAC) {
9777 if (lasttoken == TLP)
9779 *cpp = cp = stalloc(sizeof(struct nclist));
9781 app = &cp->nclist.pattern;
9783 *app = ap = stalloc(sizeof(struct narg));
9785 ap->narg.text = wordtext;
9786 ap->narg.backquote = backquotelist;
9787 if (readtoken() != TPIPE)
9789 app = &ap->narg.next;
9792 ap->narg.next = NULL;
9793 if (lasttoken != TRP)
9794 raise_error_unexpected_syntax(TRP);
9795 cp->nclist.body = list(2);
9797 cpp = &cp->nclist.next;
9799 checkkwd = CHKNL | CHKKWD;
9803 raise_error_unexpected_syntax(TENDCASE);
9810 n1 = stalloc(sizeof(struct nredir));
9811 n1->type = NSUBSHELL;
9812 n1->nredir.n = list(0);
9813 n1->nredir.redirect = NULL;
9826 if (readtoken() != t)
9827 raise_error_unexpected_syntax(t);
9830 /* Now check for redirection which may follow command */
9831 checkkwd = CHKKWD | CHKALIAS;
9833 while (readtoken() == TREDIR) {
9834 *rpp = n2 = redirnode;
9835 rpp = &n2->nfile.next;
9841 if (n1->type != NSUBSHELL) {
9842 n2 = stalloc(sizeof(struct nredir));
9847 n1->nredir.redirect = redir;
9853 * If eofmark is NULL, read a word or a redirection symbol. If eofmark
9854 * is not NULL, read a here document. In the latter case, eofmark is the
9855 * word which marks the end of the document and striptabs is true if
9856 * leading tabs should be stripped from the document. The argument firstc
9857 * is the first character of the input token or document.
9859 * Because C does not have internal subroutines, I have simulated them
9860 * using goto's to implement the subroutine linkage. The following macros
9861 * will run code that appears at the end of readtoken1.
9864 static int parsebackquote; /* nonzero if we are inside backquotes */
9866 #define CHECKEND() {goto checkend; checkend_return:;}
9867 #define PARSEREDIR() {goto parseredir; parseredir_return:;}
9868 #define PARSESUB() {goto parsesub; parsesub_return:;}
9869 #define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
9870 #define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
9871 #define PARSEARITH() {goto parsearith; parsearith_return:;}
9874 readtoken1(int firstc, int syntax, char *eofmark, int striptabs)
9879 char line[EOFMARKLEN + 1];
9880 struct nodelist *bqlist = 0;
9883 int varnest = 0; /* levels of variables expansion */
9884 int arinest = 0; /* levels of arithmetic expansion */
9885 int parenlevel = 0; /* levels of parens in arithmetic */
9886 int dqvarnest = 0; /* levels of variables expansion within double quotes */
9888 int prevsyntax = 0; /* syntax before arithmetic */
9890 /* Avoid longjmp clobbering */
9903 startlinno = plinno;
9905 if (syntax == DQSYNTAX)
9915 loop: { /* for each line, until end of word */
9916 CHECKEND(); /* set c to PEOF if at end of here document */
9917 for (;;) { /* until end of line or end of word */
9918 CHECKSTRSPACE(4, out); /* permit 4 calls to USTPUTC */
9919 switch (SIT(c, syntax)) {
9920 case CNL: /* '\n' */
9921 if (syntax == BASESYNTAX)
9922 goto endword; /* exit outer loop */
9928 goto loop; /* continue outer loop */
9933 if (eofmark == NULL || dblquote)
9934 USTPUTC(CTLESC, out);
9937 case CBACK: /* backslash */
9940 USTPUTC(CTLESC, out);
9943 } else if (c == '\n') {
9948 c != '\\' && c != '`' &&
9953 USTPUTC(CTLESC, out);
9956 if (SIT(c, SQSYNTAX) == CCTL)
9957 USTPUTC(CTLESC, out);
9965 if (eofmark == NULL) {
9966 USTPUTC(CTLQUOTEMARK, out);
9974 if (eofmark != NULL && arinest == 0
9979 if (dqvarnest == 0) {
9980 syntax = BASESYNTAX;
9987 case CVAR: /* '$' */
9988 PARSESUB(); /* parse substitution */
9990 case CENDVAR: /* '}' */
9993 if (dqvarnest > 0) {
9996 USTPUTC(CTLENDVAR, out);
10001 #if ENABLE_ASH_MATH_SUPPORT
10002 case CLP: /* '(' in arithmetic */
10006 case CRP: /* ')' in arithmetic */
10007 if (parenlevel > 0) {
10011 if (pgetc() == ')') {
10012 if (--arinest == 0) {
10013 USTPUTC(CTLENDARI, out);
10014 syntax = prevsyntax;
10015 if (syntax == DQSYNTAX)
10023 * unbalanced parens
10024 * (don't 2nd guess - no error)
10032 case CBQUOTE: /* '`' */
10036 goto endword; /* exit outer loop */
10041 goto endword; /* exit outer loop */
10042 #if ENABLE_ASH_ALIAS
10052 #if ENABLE_ASH_MATH_SUPPORT
10053 if (syntax == ARISYNTAX)
10054 raise_error_syntax("Missing '))'");
10056 if (syntax != BASESYNTAX && !parsebackquote && eofmark == NULL)
10057 raise_error_syntax("Unterminated quoted string");
10058 if (varnest != 0) {
10059 startlinno = plinno;
10061 raise_error_syntax("Missing '}'");
10063 USTPUTC('\0', out);
10064 len = out - (char *)stackblock();
10065 out = stackblock();
10066 if (eofmark == NULL) {
10067 if ((c == '>' || c == '<')
10070 && (*out == '\0' || isdigit(*out))) {
10072 return lasttoken = TREDIR;
10077 quoteflag = quotef;
10078 backquotelist = bqlist;
10079 grabstackblock(len);
10083 /* end of readtoken routine */
10086 * Check to see whether we are at the end of the here document. When this
10087 * is called, c is set to the first character of the next input line. If
10088 * we are at the end of the here document, this routine sets the c to PEOF.
10092 #if ENABLE_ASH_ALIAS
10098 while (c == '\t') {
10102 if (c == *eofmark) {
10103 if (pfgets(line, sizeof(line)) != NULL) {
10107 for (q = eofmark + 1; *q && *p == *q; p++, q++);
10108 if (*p == '\n' && *q == '\0') {
10111 needprompt = doprompt;
10113 pushstring(line, NULL);
10118 goto checkend_return;
10122 * Parse a redirection operator. The variable "out" points to a string
10123 * specifying the fd to be redirected. The variable "c" contains the
10124 * first character of the redirection operator.
10130 np = stalloc(sizeof(struct nfile));
10135 np->type = NAPPEND;
10137 np->type = NCLOBBER;
10144 } else { /* c == '<' */
10149 if (sizeof(struct nfile) != sizeof(struct nhere)) {
10150 np = stalloc(sizeof(struct nhere));
10154 heredoc = stalloc(sizeof(struct heredoc));
10155 heredoc->here = np;
10158 heredoc->striptabs = 1;
10160 heredoc->striptabs = 0;
10166 np->type = NFROMFD;
10170 np->type = NFROMTO;
10180 np->nfile.fd = fd - '0';
10182 goto parseredir_return;
10186 * Parse a substitution. At this point, we have read the dollar sign
10187 * and nothing else.
10190 /* is_special(c) evaluates to 1 for c in "!#$*-0123456789?@"; 0 otherwise
10191 * (assuming ascii char codes, as the original implementation did) */
10192 #define is_special(c) \
10193 ((((unsigned int)c) - 33 < 32) \
10194 && ((0xc1ff920dUL >> (((unsigned int)c) - 33)) & 1))
10200 static const char types[] = "}-+?=";
10204 c <= PEOA_OR_PEOF ||
10205 (c != '(' && c != '{' && !is_name(c) && !is_special(c))
10209 } else if (c == '(') { /* $(command) or $((arith)) */
10210 if (pgetc() == '(') {
10211 #if ENABLE_ASH_MATH_SUPPORT
10214 raise_error_syntax("We unsupport $((arith))");
10221 USTPUTC(CTLVAR, out);
10222 typeloc = out - (char *)stackblock();
10223 USTPUTC(VSNORMAL, out);
10224 subtype = VSNORMAL;
10232 subtype = VSLENGTH;
10236 if (c > PEOA_OR_PEOF && is_name(c)) {
10240 } while (c > PEOA_OR_PEOF && is_in_name(c));
10241 } else if (isdigit(c)) {
10245 } while (isdigit(c));
10246 } else if (is_special(c)) {
10250 badsub: raise_error_syntax("Bad substitution");
10254 if (subtype == 0) {
10261 p = strchr(types, c);
10264 subtype = p - types + VSNORMAL;
10270 subtype = c == '#' ? VSTRIMLEFT :
10283 if (dblquote || arinest)
10285 *((char *)stackblock() + typeloc) = subtype | flags;
10286 if (subtype != VSNORMAL) {
10288 if (dblquote || arinest) {
10293 goto parsesub_return;
10297 * Called to parse command substitutions. Newstyle is set if the command
10298 * is enclosed inside $(...); nlpp is a pointer to the head of the linked
10299 * list of commands (passed by reference), and savelen is the number of
10300 * characters on the top of the stack which must be preserved.
10303 struct nodelist **nlpp;
10306 char *volatile str;
10307 struct jmploc jmploc;
10308 struct jmploc *volatile savehandler;
10310 int saveprompt = 0;
10312 (void) &saveprompt;
10315 savepbq = parsebackquote;
10316 if (setjmp(jmploc.loc)) {
10319 parsebackquote = 0;
10320 exception_handler = savehandler;
10321 longjmp(exception_handler->loc, 1);
10325 savelen = out - (char *)stackblock();
10327 str = ckmalloc(savelen);
10328 memcpy(str, stackblock(), savelen);
10330 savehandler = exception_handler;
10331 exception_handler = &jmploc;
10334 /* We must read until the closing backquote, giving special
10335 treatment to some slashes, and then push the string and
10336 reread it as input, interpreting it normally. */
10343 STARTSTACKSTR(pout);
10360 * If eating a newline, avoid putting
10361 * the newline into the new character
10362 * stream (via the STPUTC after the
10367 if (pc != '\\' && pc != '`' && pc != '$'
10368 && (!dblquote || pc != '"'))
10369 STPUTC('\\', pout);
10370 if (pc > PEOA_OR_PEOF) {
10376 #if ENABLE_ASH_ALIAS
10379 startlinno = plinno;
10380 raise_error_syntax("EOF in backquote substitution");
10384 needprompt = doprompt;
10393 STPUTC('\0', pout);
10394 psavelen = pout - (char *)stackblock();
10395 if (psavelen > 0) {
10396 pstr = grabstackstr(pout);
10397 setinputstring(pstr);
10402 nlpp = &(*nlpp)->next;
10403 *nlpp = stalloc(sizeof(**nlpp));
10404 (*nlpp)->next = NULL;
10405 parsebackquote = oldstyle;
10408 saveprompt = doprompt;
10415 doprompt = saveprompt;
10416 else if (readtoken() != TRP)
10417 raise_error_unexpected_syntax(TRP);
10422 * Start reading from old file again, ignoring any pushed back
10423 * tokens left from the backquote parsing
10428 while (stackblocksize() <= savelen)
10430 STARTSTACKSTR(out);
10432 memcpy(out, str, savelen);
10433 STADJUST(savelen, out);
10439 parsebackquote = savepbq;
10440 exception_handler = savehandler;
10441 if (arinest || dblquote)
10442 USTPUTC(CTLBACKQ | CTLQUOTE, out);
10444 USTPUTC(CTLBACKQ, out);
10446 goto parsebackq_oldreturn;
10447 goto parsebackq_newreturn;
10450 #if ENABLE_ASH_MATH_SUPPORT
10452 * Parse an arithmetic expansion (indicate start of one and set state)
10455 if (++arinest == 1) {
10456 prevsyntax = syntax;
10457 syntax = ARISYNTAX;
10458 USTPUTC(CTLARI, out);
10465 * we collapse embedded arithmetic expansion to
10466 * parenthesis, which should be equivalent
10470 goto parsearith_return;
10474 } /* end of readtoken */
10477 * Read the next input token.
10478 * If the token is a word, we set backquotelist to the list of cmds in
10479 * backquotes. We set quoteflag to true if any part of the word was
10481 * If the token is TREDIR, then we set redirnode to a structure containing
10483 * In all cases, the variable startlinno is set to the number of the line
10484 * on which the token starts.
10486 * [Change comment: here documents and internal procedures]
10487 * [Readtoken shouldn't have any arguments. Perhaps we should make the
10488 * word parsing code into a separate routine. In this case, readtoken
10489 * doesn't need to have any internal procedures, but parseword does.
10490 * We could also make parseoperator in essence the main routine, and
10491 * have parseword (readtoken1?) handle both words and redirection.]
10493 #define NEW_xxreadtoken
10494 #ifdef NEW_xxreadtoken
10495 /* singles must be first! */
10496 static const char xxreadtoken_chars[7] = { '\n', '(', ')', '&', '|', ';', 0 };
10498 static const char xxreadtoken_tokens[] = {
10499 TNL, TLP, TRP, /* only single occurrence allowed */
10500 TBACKGND, TPIPE, TSEMI, /* if single occurrence */
10501 TEOF, /* corresponds to trailing nul */
10502 TAND, TOR, TENDCASE, /* if double occurrence */
10505 #define xxreadtoken_doubles \
10506 (sizeof(xxreadtoken_tokens) - sizeof(xxreadtoken_chars))
10507 #define xxreadtoken_singles \
10508 (sizeof(xxreadtoken_chars) - xxreadtoken_doubles - 1)
10522 startlinno = plinno;
10523 for (;;) { /* until token or start of word found */
10526 if ((c != ' ') && (c != '\t')
10527 #if ENABLE_ASH_ALIAS
10532 while ((c = pgetc()) != '\n' && c != PEOF);
10534 } else if (c == '\\') {
10535 if (pgetc() != '\n') {
10539 startlinno = ++plinno;
10544 = xxreadtoken_chars + sizeof(xxreadtoken_chars) - 1;
10549 needprompt = doprompt;
10552 p = strchr(xxreadtoken_chars, c);
10555 return readtoken1(c, BASESYNTAX, (char *) NULL, 0);
10558 if (p - xxreadtoken_chars >= xxreadtoken_singles) {
10559 if (pgetc() == *p) { /* double occurrence? */
10560 p += xxreadtoken_doubles + 1;
10566 return lasttoken = xxreadtoken_tokens[p - xxreadtoken_chars];
10572 #define RETURN(token) return lasttoken = token
10585 startlinno = plinno;
10586 for (;;) { /* until token or start of word found */
10589 case ' ': case '\t':
10590 #if ENABLE_ASH_ALIAS
10595 while ((c = pgetc()) != '\n' && c != PEOF);
10599 if (pgetc() == '\n') {
10600 startlinno = ++plinno;
10609 needprompt = doprompt;
10614 if (pgetc() == '&')
10619 if (pgetc() == '|')
10624 if (pgetc() == ';')
10637 return readtoken1(c, BASESYNTAX, (char *)NULL, 0);
10640 #endif /* NEW_xxreadtoken */
10647 int alreadyseen = tokpushback;
10650 #if ENABLE_ASH_ALIAS
10659 if (checkkwd & CHKNL) {
10666 if (t != TWORD || quoteflag) {
10671 * check for keywords
10673 if (checkkwd & CHKKWD) {
10674 const char *const *pp;
10676 pp = findkwd(wordtext);
10678 lasttoken = t = pp - tokname_array;
10679 TRACE(("keyword %s recognized\n", tokname(t)));
10684 if (checkkwd & CHKALIAS) {
10685 #if ENABLE_ASH_ALIAS
10687 ap = lookupalias(wordtext, 1);
10690 pushstring(ap->val, ap);
10700 TRACE(("token %s %s\n", tokname(t), t == TWORD ? wordtext : ""));
10702 TRACE(("reread token %s %s\n", tokname(t), t == TWORD ? wordtext : ""));
10714 return tokname_array[t][0];
10718 * Read and parse a command. Returns NEOF on end of file. (NULL is a
10719 * valid parse tree indicating a blank line.)
10721 static union node *
10722 parsecmd(int interact)
10727 doprompt = interact;
10729 setprompt(doprompt);
10741 * Input any here documents.
10746 struct heredoc *here;
10749 here = heredoclist;
10756 readtoken1(pgetc(), here->here->type == NHERE? SQSYNTAX : DQSYNTAX,
10757 here->eofmark, here->striptabs);
10758 n = stalloc(sizeof(struct narg));
10759 n->narg.type = NARG;
10760 n->narg.next = NULL;
10761 n->narg.text = wordtext;
10762 n->narg.backquote = backquotelist;
10763 here->here->nhere.doc = n;
10770 * called by editline -- any expansions to the prompt should be added here.
10772 #if ENABLE_ASH_EXPAND_PRMT
10773 static const char *
10774 expandstr(const char *ps)
10778 /* XXX Fix (char *) cast. */
10779 setinputstring((char *)ps);
10780 readtoken1(pgetc(), DQSYNTAX, nullstr, 0);
10783 n.narg.type = NARG;
10784 n.narg.next = NULL;
10785 n.narg.text = wordtext;
10786 n.narg.backquote = backquotelist;
10788 expandarg(&n, NULL, 0);
10789 return stackblock();
10794 * Execute a command or commands contained in a string.
10797 evalstring(char *s, int mask)
10800 struct stackmark smark;
10804 setstackmark(&smark);
10807 while ((n = parsecmd(0)) != NEOF) {
10809 popstackmark(&smark);
10822 * The eval command.
10825 evalcmd(int argc, char **argv)
10834 STARTSTACKSTR(concat);
10837 concat = stack_putstr(p, concat);
10841 STPUTC(' ', concat);
10843 STPUTC('\0', concat);
10844 p = grabstackstr(concat);
10846 evalstring(p, ~SKIPEVAL);
10853 * Read and execute commands. "Top" is nonzero for the top level command
10854 * loop; it turns on prompting if the shell is interactive.
10860 struct stackmark smark;
10864 TRACE(("cmdloop(%d) called\n", top));
10868 setstackmark(&smark);
10871 showjobs(stderr, SHOW_CHANGED);
10874 if (iflag && top) {
10876 #if ENABLE_ASH_MAIL
10880 n = parsecmd(inter);
10881 /* showtree(n); DEBUG */
10883 if (!top || numeof >= 50)
10885 if (!stoppedjobs()) {
10888 out2str("\nUse \"exit\" to leave shell.\n");
10891 } else if (nflag == 0) {
10892 job_warning = (job_warning == 2) ? 1 : 0;
10896 popstackmark(&smark);
10901 return skip & SKIPEVAL;
10908 * Take commands from a file. To be compatible we should do a path
10909 * search for the file, which is necessary to find sub-commands.
10912 find_dot_file(char *name)
10915 const char *path = pathval();
10918 /* don't try this for absolute or relative paths */
10919 if (strchr(name, '/'))
10922 while ((fullname = padvance(&path, name)) != NULL) {
10923 if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) {
10925 * Don't bother freeing here, since it will
10926 * be freed by the caller.
10930 stunalloc(fullname);
10933 /* not found in the PATH */
10934 ash_msg_and_raise_error("%s: not found", name);
10939 dotcmd(int argc, char **argv)
10941 struct strlist *sp;
10942 volatile struct shparam saveparam;
10945 for (sp = cmdenviron; sp; sp = sp->next)
10946 setvareq(ckstrdup(sp->text), VSTRFIXED | VTEXTFIXED);
10948 if (argc >= 2) { /* That's what SVR2 does */
10951 fullname = find_dot_file(argv[1]);
10954 saveparam = shellparam;
10955 shellparam.malloc = 0;
10956 shellparam.nparam = argc - 2;
10957 shellparam.p = argv + 2;
10960 setinputfile(fullname, INPUT_PUSH_FILE);
10961 commandname = fullname;
10966 freeparam(&shellparam);
10967 shellparam = saveparam;
10969 status = exitstatus;
10975 exitcmd(int argc, char **argv)
10980 exitstatus = number(argv[1]);
10981 raise_exception(EXEXIT);
10985 #if ENABLE_ASH_BUILTIN_ECHO
10987 echocmd(int argc, char **argv)
10989 return bb_echo(argv);
10993 #if ENABLE_ASH_BUILTIN_TEST
10995 testcmd(int argc, char **argv)
10997 return bb_test(argc, argv);
11002 * Read a file containing shell functions.
11005 readcmdfile(char *name)
11007 setinputfile(name, INPUT_PUSH_FILE);
11013 /* ============ find_command inplementation */
11016 * Resolve a command name. If you change this routine, you may have to
11017 * change the shellexec routine as well.
11020 find_command(char *name, struct cmdentry *entry, int act, const char *path)
11022 struct tblentry *cmdp;
11029 struct builtincmd *bcmd;
11031 /* If name contains a slash, don't use PATH or hash table */
11032 if (strchr(name, '/') != NULL) {
11033 entry->u.index = -1;
11034 if (act & DO_ABS) {
11035 while (stat(name, &statb) < 0) {
11037 if (errno == EINTR)
11040 entry->cmdtype = CMDUNKNOWN;
11044 entry->cmdtype = CMDNORMAL;
11048 /* #if ENABLE_FEATURE_SH_STANDALONE... moved after builtin check */
11050 updatetbl = (path == pathval());
11053 if (strstr(path, "%builtin") != NULL)
11054 act |= DO_ALTBLTIN;
11057 /* If name is in the table, check answer will be ok */
11058 cmdp = cmdlookup(name, 0);
11059 if (cmdp != NULL) {
11062 switch (cmdp->cmdtype) {
11080 } else if (cmdp->rehash == 0)
11081 /* if not invalidated by cd, we're done */
11085 /* If %builtin not in path, check for builtin next */
11086 bcmd = find_builtin(name);
11088 if (IS_BUILTIN_REGULAR(bcmd))
11089 goto builtin_success;
11090 if (act & DO_ALTPATH) {
11091 if (!(act & DO_ALTBLTIN))
11092 goto builtin_success;
11093 } else if (builtinloc <= 0) {
11094 goto builtin_success;
11098 #if ENABLE_FEATURE_SH_STANDALONE
11099 if (find_applet_by_name(name)) {
11100 entry->cmdtype = CMDNORMAL;
11101 entry->u.index = -1;
11106 /* We have to search path. */
11107 prev = -1; /* where to start */
11108 if (cmdp && cmdp->rehash) { /* doing a rehash */
11109 if (cmdp->cmdtype == CMDBUILTIN)
11112 prev = cmdp->param.index;
11118 while ((fullname = padvance(&path, name)) != NULL) {
11119 stunalloc(fullname);
11122 if (prefix(pathopt, "builtin")) {
11124 goto builtin_success;
11126 } else if (!(act & DO_NOFUNC) &&
11127 prefix(pathopt, "func")) {
11128 /* handled below */
11130 /* ignore unimplemented options */
11134 /* if rehash, don't redo absolute path names */
11135 if (fullname[0] == '/' && idx <= prev) {
11138 TRACE(("searchexec \"%s\": no change\n", name));
11141 while (stat(fullname, &statb) < 0) {
11143 if (errno == EINTR)
11146 if (errno != ENOENT && errno != ENOTDIR)
11150 e = EACCES; /* if we fail, this will be the error */
11151 if (!S_ISREG(statb.st_mode))
11153 if (pathopt) { /* this is a %func directory */
11154 stalloc(strlen(fullname) + 1);
11155 readcmdfile(fullname);
11156 cmdp = cmdlookup(name, 0);
11157 if (cmdp == NULL || cmdp->cmdtype != CMDFUNCTION)
11158 ash_msg_and_raise_error("%s not defined in %s", name, fullname);
11159 stunalloc(fullname);
11162 TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
11164 entry->cmdtype = CMDNORMAL;
11165 entry->u.index = idx;
11169 cmdp = cmdlookup(name, 1);
11170 cmdp->cmdtype = CMDNORMAL;
11171 cmdp->param.index = idx;
11176 /* We failed. If there was an entry for this command, delete it */
11177 if (cmdp && updatetbl)
11178 delete_cmd_entry();
11180 ash_msg("%s: %s", name, errmsg(e, "not found"));
11181 entry->cmdtype = CMDUNKNOWN;
11186 entry->cmdtype = CMDBUILTIN;
11187 entry->u.cmd = bcmd;
11191 cmdp = cmdlookup(name, 1);
11192 cmdp->cmdtype = CMDBUILTIN;
11193 cmdp->param.cmd = bcmd;
11197 entry->cmdtype = cmdp->cmdtype;
11198 entry->u = cmdp->param;
11202 /* ============ trap.c */
11205 * The trap builtin.
11208 trapcmd(int argc, char **argv)
11217 for (signo = 0; signo < NSIG; signo++) {
11218 if (trap[signo] != NULL) {
11221 sn = get_signame(signo);
11222 out1fmt("trap -- %s %s\n",
11223 single_quote(trap[signo]), sn);
11233 signo = get_signum(*ap);
11235 ash_msg_and_raise_error("%s: bad trap", *ap);
11238 if (LONE_DASH(action))
11241 action = ckstrdup(action);
11245 trap[signo] = action;
11255 /* ============ Builtins */
11257 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
11259 * Lists available builtins
11262 helpcmd(int argc, char **argv)
11266 out1fmt("\nBuilt-in commands:\n-------------------\n");
11267 for (col = 0, i = 0; i < NUMBUILTINS; i++) {
11268 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '),
11269 builtintab[i].name + 1);
11275 #if ENABLE_FEATURE_SH_STANDALONE
11276 for (i = 0; i < NUM_APPLETS; i++) {
11277 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '), applets[i].name);
11285 return EXIT_SUCCESS;
11287 #endif /* FEATURE_SH_EXTRA_QUIET */
11290 * The export and readonly commands.
11293 exportcmd(int argc, char **argv)
11299 int flag = argv[0][0] == 'r'? VREADONLY : VEXPORT;
11301 if (nextopt("p") != 'p') {
11306 p = strchr(name, '=');
11310 vp = *findvar(hashvar(name), name);
11316 setvar(name, p, flag);
11317 } while ((name = *++aptr) != NULL);
11321 showvars(argv[0], flag, 0);
11326 * Delete a function if it exists.
11329 unsetfunc(const char *name)
11331 struct tblentry *cmdp;
11333 cmdp = cmdlookup(name, 0);
11334 if (cmdp!= NULL && cmdp->cmdtype == CMDFUNCTION)
11335 delete_cmd_entry();
11339 * The unset builtin command. We unset the function before we unset the
11340 * variable to allow a function to be unset when there is a readonly variable
11341 * with the same name.
11344 unsetcmd(int argc, char **argv)
11351 while ((i = nextopt("vf")) != '\0') {
11355 for (ap = argptr; *ap; ap++) {
11371 #include <sys/times.h>
11373 static const unsigned char timescmd_str[] = {
11374 ' ', offsetof(struct tms, tms_utime),
11375 '\n', offsetof(struct tms, tms_stime),
11376 ' ', offsetof(struct tms, tms_cutime),
11377 '\n', offsetof(struct tms, tms_cstime),
11382 timescmd(int ac, char **av)
11384 long clk_tck, s, t;
11385 const unsigned char *p;
11388 clk_tck = sysconf(_SC_CLK_TCK);
11393 t = *(clock_t *)(((char *) &buf) + p[1]);
11395 out1fmt("%ldm%ld.%.3lds%c",
11397 ((t - s * clk_tck) * 1000) / clk_tck,
11399 } while (*(p += 2));
11404 #if ENABLE_ASH_MATH_SUPPORT
11406 dash_arith(const char *s)
11412 result = arith(s, &errcode);
11415 ash_msg_and_raise_error("exponent less than 0");
11417 ash_msg_and_raise_error("divide by zero");
11419 ash_msg_and_raise_error("expression recursion loop detected");
11420 raise_error_syntax(s);
11428 * The let builtin. partial stolen from GNU Bash, the Bourne Again SHell.
11429 * Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
11431 * Copyright (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
11434 letcmd(int argc, char **argv)
11441 ash_msg_and_raise_error("expression expected");
11442 for (ap = argv + 1; *ap; ap++) {
11443 i = dash_arith(*ap);
11448 #endif /* ASH_MATH_SUPPORT */
11451 /* ============ miscbltin.c
11453 * Miscellaneous builtins.
11458 #if defined(__GLIBC__) && __GLIBC__ == 2 && __GLIBC_MINOR__ < 1
11459 typedef enum __rlimit_resource rlim_t;
11463 * The read builtin. The -e option causes backslashes to escape the
11464 * following character.
11466 * This uses unbuffered input, which may be avoidable in some cases.
11469 readcmd(int argc, char **argv)
11481 #if ENABLE_ASH_READ_NCHARS
11485 struct termios tty, old_tty;
11487 #if ENABLE_ASH_READ_TIMEOUT
11491 ts.tv_sec = ts.tv_usec = 0;
11496 #if ENABLE_ASH_READ_NCHARS && ENABLE_ASH_READ_TIMEOUT
11497 while ((i = nextopt("p:rt:n:s")) != '\0')
11498 #elif ENABLE_ASH_READ_NCHARS
11499 while ((i = nextopt("p:rn:s")) != '\0')
11500 #elif ENABLE_ASH_READ_TIMEOUT
11501 while ((i = nextopt("p:rt:")) != '\0')
11503 while ((i = nextopt("p:r")) != '\0')
11508 prompt = optionarg;
11510 #if ENABLE_ASH_READ_NCHARS
11512 nchars = strtol(optionarg, &p, 10);
11514 ash_msg_and_raise_error("invalid count");
11515 nch_flag = (nchars > 0);
11521 #if ENABLE_ASH_READ_TIMEOUT
11523 ts.tv_sec = strtol(optionarg, &p, 10);
11529 ts.tv_usec = strtol(p, &p2, 10);
11531 ash_msg_and_raise_error("invalid timeout");
11533 /* normalize to usec */
11535 ash_msg_and_raise_error("invalid timeout");
11536 while (scale++ < 6)
11540 ash_msg_and_raise_error("invalid timeout");
11542 if ( ! ts.tv_sec && ! ts.tv_usec)
11543 ash_msg_and_raise_error("invalid timeout");
11553 if (prompt && isatty(0)) {
11558 ash_msg_and_raise_error("arg count");
11559 ifs = bltinlookup("IFS");
11562 #if ENABLE_ASH_READ_NCHARS
11563 if (nch_flag || silent) {
11564 tcgetattr(0, &tty);
11567 tty.c_lflag &= ~ICANON;
11568 tty.c_cc[VMIN] = nchars;
11571 tty.c_lflag &= ~(ECHO|ECHOK|ECHONL);
11574 tcsetattr(0, TCSANOW, &tty);
11577 #if ENABLE_ASH_READ_TIMEOUT
11578 if (ts.tv_sec || ts.tv_usec) {
11582 i = select(FD_SETSIZE, &set, NULL, NULL, &ts);
11584 #if ENABLE_ASH_READ_NCHARS
11586 tcsetattr(0, TCSANOW, &old_tty);
11596 #if ENABLE_ASH_READ_NCHARS
11597 while (!nch_flag || nchars--)
11602 if (read(0, &c, 1) != 1) {
11614 if (!rflag && c == '\\') {
11620 if (startword && *ifs == ' ' && strchr(ifs, c)) {
11624 if (ap[1] != NULL && strchr(ifs, c) != NULL) {
11626 setvar(*ap, stackblock(), 0);
11635 #if ENABLE_ASH_READ_NCHARS
11636 if (nch_flag || silent)
11637 tcsetattr(0, TCSANOW, &old_tty);
11641 /* Remove trailing blanks */
11642 while ((char *)stackblock() <= --p && strchr(ifs, *p) != NULL)
11644 setvar(*ap, stackblock(), 0);
11645 while (*++ap != NULL)
11646 setvar(*ap, nullstr, 0);
11651 umaskcmd(int argc, char **argv)
11653 static const char permuser[3] = "ugo";
11654 static const char permmode[3] = "rwx";
11655 static const short int permmask[] = {
11656 S_IRUSR, S_IWUSR, S_IXUSR,
11657 S_IRGRP, S_IWGRP, S_IXGRP,
11658 S_IROTH, S_IWOTH, S_IXOTH
11664 int symbolic_mode = 0;
11666 while (nextopt("S") != '\0') {
11677 if (symbolic_mode) {
11681 for (i = 0; i < 3; i++) {
11684 *p++ = permuser[i];
11686 for (j = 0; j < 3; j++) {
11687 if ((mask & permmask[3 * i + j]) == 0) {
11688 *p++ = permmode[j];
11696 out1fmt("%.4o\n", mask);
11699 if (isdigit((unsigned char) *ap)) {
11702 if (*ap >= '8' || *ap < '0')
11703 ash_msg_and_raise_error(illnum, argv[1]);
11704 mask = (mask << 3) + (*ap - '0');
11705 } while (*++ap != '\0');
11708 mask = ~mask & 0777;
11709 if (!bb_parse_mode(ap, &mask)) {
11710 ash_msg_and_raise_error("illegal mode: %s", ap);
11712 umask(~mask & 0777);
11721 * This code, originally by Doug Gwyn, Doug Kingston, Eric Gisin, and
11722 * Michael Rendell was ripped from pdksh 5.0.8 and hacked for use with
11723 * ash by J.T. Conklin.
11731 int factor; /* multiply by to get rlim_{cur,max} values */
11735 static const struct limits limits[] = {
11737 { "time(seconds)", RLIMIT_CPU, 1, 't' },
11739 #ifdef RLIMIT_FSIZE
11740 { "file(blocks)", RLIMIT_FSIZE, 512, 'f' },
11743 { "data(kbytes)", RLIMIT_DATA, 1024, 'd' },
11745 #ifdef RLIMIT_STACK
11746 { "stack(kbytes)", RLIMIT_STACK, 1024, 's' },
11749 { "coredump(blocks)", RLIMIT_CORE, 512, 'c' },
11752 { "memory(kbytes)", RLIMIT_RSS, 1024, 'm' },
11754 #ifdef RLIMIT_MEMLOCK
11755 { "locked memory(kbytes)", RLIMIT_MEMLOCK, 1024, 'l' },
11757 #ifdef RLIMIT_NPROC
11758 { "process", RLIMIT_NPROC, 1, 'p' },
11760 #ifdef RLIMIT_NOFILE
11761 { "nofiles", RLIMIT_NOFILE, 1, 'n' },
11764 { "vmemory(kbytes)", RLIMIT_AS, 1024, 'v' },
11766 #ifdef RLIMIT_LOCKS
11767 { "locks", RLIMIT_LOCKS, 1, 'w' },
11769 { NULL, 0, 0, '\0' }
11772 enum limtype { SOFT = 0x1, HARD = 0x2 };
11775 printlim(enum limtype how, const struct rlimit *limit,
11776 const struct limits *l)
11780 val = limit->rlim_max;
11782 val = limit->rlim_cur;
11784 if (val == RLIM_INFINITY)
11785 out1fmt("unlimited\n");
11788 out1fmt("%lld\n", (long long) val);
11793 ulimitcmd(int argc, char **argv)
11797 enum limtype how = SOFT | HARD;
11798 const struct limits *l;
11801 struct rlimit limit;
11804 while ((optc = nextopt("HSa"
11808 #ifdef RLIMIT_FSIZE
11814 #ifdef RLIMIT_STACK
11823 #ifdef RLIMIT_MEMLOCK
11826 #ifdef RLIMIT_NPROC
11829 #ifdef RLIMIT_NOFILE
11835 #ifdef RLIMIT_LOCKS
11853 for (l = limits; l->option != what; l++)
11856 set = *argptr ? 1 : 0;
11860 if (all || argptr[1])
11861 ash_msg_and_raise_error("too many arguments");
11862 if (strncmp(p, "unlimited\n", 9) == 0)
11863 val = RLIM_INFINITY;
11867 while ((c = *p++) >= '0' && c <= '9') {
11868 val = (val * 10) + (long)(c - '0');
11869 if (val < (rlim_t) 0)
11873 ash_msg_and_raise_error("bad number");
11878 for (l = limits; l->name; l++) {
11879 getrlimit(l->cmd, &limit);
11880 out1fmt("%-20s ", l->name);
11881 printlim(how, &limit, l);
11886 getrlimit(l->cmd, &limit);
11889 limit.rlim_max = val;
11891 limit.rlim_cur = val;
11892 if (setrlimit(l->cmd, &limit) < 0)
11893 ash_msg_and_raise_error("error setting limit (%m)");
11895 printlim(how, &limit, l);
11901 /* ============ Math support */
11903 #if ENABLE_ASH_MATH_SUPPORT
11905 /* Copyright (c) 2001 Aaron Lehmann <aaronl@vitelus.com>
11907 Permission is hereby granted, free of charge, to any person obtaining
11908 a copy of this software and associated documentation files (the
11909 "Software"), to deal in the Software without restriction, including
11910 without limitation the rights to use, copy, modify, merge, publish,
11911 distribute, sublicense, and/or sell copies of the Software, and to
11912 permit persons to whom the Software is furnished to do so, subject to
11913 the following conditions:
11915 The above copyright notice and this permission notice shall be
11916 included in all copies or substantial portions of the Software.
11918 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
11919 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
11920 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
11921 IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
11922 CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
11923 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
11924 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
11927 /* This is my infix parser/evaluator. It is optimized for size, intended
11928 * as a replacement for yacc-based parsers. However, it may well be faster
11929 * than a comparable parser written in yacc. The supported operators are
11930 * listed in #defines below. Parens, order of operations, and error handling
11931 * are supported. This code is thread safe. The exact expression format should
11932 * be that which POSIX specifies for shells. */
11934 /* The code uses a simple two-stack algorithm. See
11935 * http://www.onthenet.com.au/~grahamis/int2008/week02/lect02.html
11936 * for a detailed explanation of the infix-to-postfix algorithm on which
11937 * this is based (this code differs in that it applies operators immediately
11938 * to the stack instead of adding them to a queue to end up with an
11941 /* To use the routine, call it with an expression string and error return
11945 * Aug 24, 2001 Manuel Novoa III
11947 * Reduced the generated code size by about 30% (i386) and fixed several bugs.
11949 * 1) In arith_apply():
11950 * a) Cached values of *numptr and &(numptr[-1]).
11951 * b) Removed redundant test for zero denominator.
11954 * a) Eliminated redundant code for processing operator tokens by moving
11955 * to a table-based implementation. Also folded handling of parens
11957 * b) Combined all 3 loops which called arith_apply to reduce generated
11958 * code size at the cost of speed.
11960 * 3) The following expressions were treated as valid by the original code:
11961 * 1() , 0! , 1 ( *3 ) .
11962 * These bugs have been fixed by internally enclosing the expression in
11963 * parens and then checking that all binary ops and right parens are
11964 * preceded by a valid expression (NUM_TOKEN).
11966 * Note: It may be desirable to replace Aaron's test for whitespace with
11967 * ctype's isspace() if it is used by another busybox applet or if additional
11968 * whitespace chars should be considered. Look below the "#include"s for a
11969 * precompiler test.
11973 * Aug 26, 2001 Manuel Novoa III
11975 * Return 0 for null expressions. Pointed out by Vladimir Oleynik.
11977 * Merge in Aaron's comments previously posted to the busybox list,
11978 * modified slightly to take account of my changes to the code.
11983 * (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
11985 * - allow access to variable,
11986 * used recursive find value indirection (c=2*2; a="c"; $((a+=2)) produce 6)
11987 * - realize assign syntax (VAR=expr, +=, *= etc)
11988 * - realize exponentiation (** operator)
11989 * - realize comma separated - expr, expr
11990 * - realise ++expr --expr expr++ expr--
11991 * - realise expr ? expr : expr (but, second expr calculate always)
11992 * - allow hexadecimal and octal numbers
11993 * - was restored loses XOR operator
11994 * - remove one goto label, added three ;-)
11995 * - protect $((num num)) as true zero expr (Manuel`s error)
11996 * - always use special isspace(), see comment from bash ;-)
11999 #define arith_isspace(arithval) \
12000 (arithval == ' ' || arithval == '\n' || arithval == '\t')
12002 typedef unsigned char operator;
12004 /* An operator's token id is a bit of a bitfield. The lower 5 bits are the
12005 * precedence, and 3 high bits are an ID unique across operators of that
12006 * precedence. The ID portion is so that multiple operators can have the
12007 * same precedence, ensuring that the leftmost one is evaluated first.
12008 * Consider * and /. */
12010 #define tok_decl(prec,id) (((id)<<5)|(prec))
12011 #define PREC(op) ((op) & 0x1F)
12013 #define TOK_LPAREN tok_decl(0,0)
12015 #define TOK_COMMA tok_decl(1,0)
12017 #define TOK_ASSIGN tok_decl(2,0)
12018 #define TOK_AND_ASSIGN tok_decl(2,1)
12019 #define TOK_OR_ASSIGN tok_decl(2,2)
12020 #define TOK_XOR_ASSIGN tok_decl(2,3)
12021 #define TOK_PLUS_ASSIGN tok_decl(2,4)
12022 #define TOK_MINUS_ASSIGN tok_decl(2,5)
12023 #define TOK_LSHIFT_ASSIGN tok_decl(2,6)
12024 #define TOK_RSHIFT_ASSIGN tok_decl(2,7)
12026 #define TOK_MUL_ASSIGN tok_decl(3,0)
12027 #define TOK_DIV_ASSIGN tok_decl(3,1)
12028 #define TOK_REM_ASSIGN tok_decl(3,2)
12030 /* all assign is right associativity and precedence eq, but (7+3)<<5 > 256 */
12031 #define convert_prec_is_assing(prec) do { if (prec == 3) prec = 2; } while (0)
12033 /* conditional is right associativity too */
12034 #define TOK_CONDITIONAL tok_decl(4,0)
12035 #define TOK_CONDITIONAL_SEP tok_decl(4,1)
12037 #define TOK_OR tok_decl(5,0)
12039 #define TOK_AND tok_decl(6,0)
12041 #define TOK_BOR tok_decl(7,0)
12043 #define TOK_BXOR tok_decl(8,0)
12045 #define TOK_BAND tok_decl(9,0)
12047 #define TOK_EQ tok_decl(10,0)
12048 #define TOK_NE tok_decl(10,1)
12050 #define TOK_LT tok_decl(11,0)
12051 #define TOK_GT tok_decl(11,1)
12052 #define TOK_GE tok_decl(11,2)
12053 #define TOK_LE tok_decl(11,3)
12055 #define TOK_LSHIFT tok_decl(12,0)
12056 #define TOK_RSHIFT tok_decl(12,1)
12058 #define TOK_ADD tok_decl(13,0)
12059 #define TOK_SUB tok_decl(13,1)
12061 #define TOK_MUL tok_decl(14,0)
12062 #define TOK_DIV tok_decl(14,1)
12063 #define TOK_REM tok_decl(14,2)
12065 /* exponent is right associativity */
12066 #define TOK_EXPONENT tok_decl(15,1)
12068 /* For now unary operators. */
12069 #define UNARYPREC 16
12070 #define TOK_BNOT tok_decl(UNARYPREC,0)
12071 #define TOK_NOT tok_decl(UNARYPREC,1)
12073 #define TOK_UMINUS tok_decl(UNARYPREC+1,0)
12074 #define TOK_UPLUS tok_decl(UNARYPREC+1,1)
12076 #define PREC_PRE (UNARYPREC+2)
12078 #define TOK_PRE_INC tok_decl(PREC_PRE, 0)
12079 #define TOK_PRE_DEC tok_decl(PREC_PRE, 1)
12081 #define PREC_POST (UNARYPREC+3)
12083 #define TOK_POST_INC tok_decl(PREC_POST, 0)
12084 #define TOK_POST_DEC tok_decl(PREC_POST, 1)
12086 #define SPEC_PREC (UNARYPREC+4)
12088 #define TOK_NUM tok_decl(SPEC_PREC, 0)
12089 #define TOK_RPAREN tok_decl(SPEC_PREC, 1)
12091 #define NUMPTR (*numstackptr)
12094 tok_have_assign(operator op)
12096 operator prec = PREC(op);
12098 convert_prec_is_assing(prec);
12099 return (prec == PREC(TOK_ASSIGN) ||
12100 prec == PREC_PRE || prec == PREC_POST);
12104 is_right_associativity(operator prec)
12106 return (prec == PREC(TOK_ASSIGN) || prec == PREC(TOK_EXPONENT)
12107 || prec == PREC(TOK_CONDITIONAL));
12110 typedef struct ARITCH_VAR_NUM {
12112 arith_t contidional_second_val;
12113 char contidional_second_val_initialized;
12114 char *var; /* if NULL then is regular number,
12115 else is variable name */
12118 typedef struct CHK_VAR_RECURSIVE_LOOPED {
12120 struct CHK_VAR_RECURSIVE_LOOPED *next;
12121 } chk_var_recursive_looped_t;
12123 static chk_var_recursive_looped_t *prev_chk_var_recursive;
12126 arith_lookup_val(v_n_t *t)
12129 const char * p = lookupvar(t->var);
12134 /* recursive try as expression */
12135 chk_var_recursive_looped_t *cur;
12136 chk_var_recursive_looped_t cur_save;
12138 for (cur = prev_chk_var_recursive; cur; cur = cur->next) {
12139 if (strcmp(cur->var, t->var) == 0) {
12140 /* expression recursion loop detected */
12144 /* save current lookuped var name */
12145 cur = prev_chk_var_recursive;
12146 cur_save.var = t->var;
12147 cur_save.next = cur;
12148 prev_chk_var_recursive = &cur_save;
12150 t->val = arith (p, &errcode);
12151 /* restore previous ptr after recursiving */
12152 prev_chk_var_recursive = cur;
12155 /* allow undefined var as 0 */
12161 /* "applying" a token means performing it on the top elements on the integer
12162 * stack. For a unary operator it will only change the top element, but a
12163 * binary operator will pop two arguments and push a result */
12165 arith_apply(operator op, v_n_t *numstack, v_n_t **numstackptr)
12168 arith_t numptr_val, rez;
12169 int ret_arith_lookup_val;
12171 /* There is no operator that can work without arguments */
12172 if (NUMPTR == numstack) goto err;
12173 numptr_m1 = NUMPTR - 1;
12175 /* check operand is var with noninteger value */
12176 ret_arith_lookup_val = arith_lookup_val(numptr_m1);
12177 if (ret_arith_lookup_val)
12178 return ret_arith_lookup_val;
12180 rez = numptr_m1->val;
12181 if (op == TOK_UMINUS)
12183 else if (op == TOK_NOT)
12185 else if (op == TOK_BNOT)
12187 else if (op == TOK_POST_INC || op == TOK_PRE_INC)
12189 else if (op == TOK_POST_DEC || op == TOK_PRE_DEC)
12191 else if (op != TOK_UPLUS) {
12192 /* Binary operators */
12194 /* check and binary operators need two arguments */
12195 if (numptr_m1 == numstack) goto err;
12197 /* ... and they pop one */
12200 if (op == TOK_CONDITIONAL) {
12201 if (! numptr_m1->contidional_second_val_initialized) {
12202 /* protect $((expr1 ? expr2)) without ": expr" */
12205 rez = numptr_m1->contidional_second_val;
12206 } else if (numptr_m1->contidional_second_val_initialized) {
12207 /* protect $((expr1 : expr2)) without "expr ? " */
12210 numptr_m1 = NUMPTR - 1;
12211 if (op != TOK_ASSIGN) {
12212 /* check operand is var with noninteger value for not '=' */
12213 ret_arith_lookup_val = arith_lookup_val(numptr_m1);
12214 if (ret_arith_lookup_val)
12215 return ret_arith_lookup_val;
12217 if (op == TOK_CONDITIONAL) {
12218 numptr_m1->contidional_second_val = rez;
12220 rez = numptr_m1->val;
12221 if (op == TOK_BOR || op == TOK_OR_ASSIGN)
12223 else if (op == TOK_OR)
12224 rez = numptr_val || rez;
12225 else if (op == TOK_BAND || op == TOK_AND_ASSIGN)
12227 else if (op == TOK_BXOR || op == TOK_XOR_ASSIGN)
12229 else if (op == TOK_AND)
12230 rez = rez && numptr_val;
12231 else if (op == TOK_EQ)
12232 rez = (rez == numptr_val);
12233 else if (op == TOK_NE)
12234 rez = (rez != numptr_val);
12235 else if (op == TOK_GE)
12236 rez = (rez >= numptr_val);
12237 else if (op == TOK_RSHIFT || op == TOK_RSHIFT_ASSIGN)
12238 rez >>= numptr_val;
12239 else if (op == TOK_LSHIFT || op == TOK_LSHIFT_ASSIGN)
12240 rez <<= numptr_val;
12241 else if (op == TOK_GT)
12242 rez = (rez > numptr_val);
12243 else if (op == TOK_LT)
12244 rez = (rez < numptr_val);
12245 else if (op == TOK_LE)
12246 rez = (rez <= numptr_val);
12247 else if (op == TOK_MUL || op == TOK_MUL_ASSIGN)
12249 else if (op == TOK_ADD || op == TOK_PLUS_ASSIGN)
12251 else if (op == TOK_SUB || op == TOK_MINUS_ASSIGN)
12253 else if (op == TOK_ASSIGN || op == TOK_COMMA)
12255 else if (op == TOK_CONDITIONAL_SEP) {
12256 if (numptr_m1 == numstack) {
12257 /* protect $((expr : expr)) without "expr ? " */
12260 numptr_m1->contidional_second_val_initialized = op;
12261 numptr_m1->contidional_second_val = numptr_val;
12262 } else if (op == TOK_CONDITIONAL) {
12264 numptr_val : numptr_m1->contidional_second_val;
12265 } else if (op == TOK_EXPONENT) {
12266 if (numptr_val < 0)
12267 return -3; /* exponent less than 0 */
12272 while (numptr_val--)
12276 } else if (numptr_val==0) /* zero divisor check */
12278 else if (op == TOK_DIV || op == TOK_DIV_ASSIGN)
12280 else if (op == TOK_REM || op == TOK_REM_ASSIGN)
12283 if (tok_have_assign(op)) {
12284 char buf[sizeof(arith_t_type)*3 + 2];
12286 if (numptr_m1->var == NULL) {
12290 /* save to shell variable */
12291 #if ENABLE_ASH_MATH_SUPPORT_64
12292 snprintf(buf, sizeof(buf), "%lld", (arith_t_type) rez);
12294 snprintf(buf, sizeof(buf), "%ld", (arith_t_type) rez);
12296 setvar(numptr_m1->var, buf, 0);
12297 /* after saving, make previous value for v++ or v-- */
12298 if (op == TOK_POST_INC)
12300 else if (op == TOK_POST_DEC)
12303 numptr_m1->val = rez;
12304 /* protect geting var value, is number now */
12305 numptr_m1->var = NULL;
12311 /* longest must be first */
12312 static const char op_tokens[] = {
12313 '<','<','=',0, TOK_LSHIFT_ASSIGN,
12314 '>','>','=',0, TOK_RSHIFT_ASSIGN,
12315 '<','<', 0, TOK_LSHIFT,
12316 '>','>', 0, TOK_RSHIFT,
12317 '|','|', 0, TOK_OR,
12318 '&','&', 0, TOK_AND,
12319 '!','=', 0, TOK_NE,
12320 '<','=', 0, TOK_LE,
12321 '>','=', 0, TOK_GE,
12322 '=','=', 0, TOK_EQ,
12323 '|','=', 0, TOK_OR_ASSIGN,
12324 '&','=', 0, TOK_AND_ASSIGN,
12325 '*','=', 0, TOK_MUL_ASSIGN,
12326 '/','=', 0, TOK_DIV_ASSIGN,
12327 '%','=', 0, TOK_REM_ASSIGN,
12328 '+','=', 0, TOK_PLUS_ASSIGN,
12329 '-','=', 0, TOK_MINUS_ASSIGN,
12330 '-','-', 0, TOK_POST_DEC,
12331 '^','=', 0, TOK_XOR_ASSIGN,
12332 '+','+', 0, TOK_POST_INC,
12333 '*','*', 0, TOK_EXPONENT,
12337 '=', 0, TOK_ASSIGN,
12349 '?', 0, TOK_CONDITIONAL,
12350 ':', 0, TOK_CONDITIONAL_SEP,
12351 ')', 0, TOK_RPAREN,
12352 '(', 0, TOK_LPAREN,
12356 #define endexpression &op_tokens[sizeof(op_tokens)-7]
12359 arith(const char *expr, int *perrcode)
12361 char arithval; /* Current character under analysis */
12362 operator lasttok, op;
12365 const char *p = endexpression;
12368 size_t datasizes = strlen(expr) + 2;
12370 /* Stack of integers */
12371 /* The proof that there can be no more than strlen(startbuf)/2+1 integers
12372 * in any given correct or incorrect expression is left as an exercise to
12374 v_n_t *numstack = alloca(((datasizes)/2)*sizeof(v_n_t)),
12375 *numstackptr = numstack;
12376 /* Stack of operator tokens */
12377 operator *stack = alloca((datasizes) * sizeof(operator)),
12380 *stackptr++ = lasttok = TOK_LPAREN; /* start off with a left paren */
12381 *perrcode = errcode = 0;
12385 if (arithval == 0) {
12386 if (p == endexpression) {
12387 /* Null expression. */
12391 /* This is only reached after all tokens have been extracted from the
12392 * input stream. If there are still tokens on the operator stack, they
12393 * are to be applied in order. At the end, there should be a final
12394 * result on the integer stack */
12396 if (expr != endexpression + 1) {
12397 /* If we haven't done so already, */
12398 /* append a closing right paren */
12399 expr = endexpression;
12400 /* and let the loop process it. */
12403 /* At this point, we're done with the expression. */
12404 if (numstackptr != numstack+1) {
12405 /* ... but if there isn't, it's bad */
12407 return (*perrcode = -1);
12409 if (numstack->var) {
12410 /* expression is $((var)) only, lookup now */
12411 errcode = arith_lookup_val(numstack);
12414 *perrcode = errcode;
12415 return numstack->val;
12418 /* Continue processing the expression. */
12419 if (arith_isspace(arithval)) {
12420 /* Skip whitespace */
12423 p = endofname(expr);
12425 size_t var_name_size = (p-expr) + 1; /* trailing zero */
12427 numstackptr->var = alloca(var_name_size);
12428 safe_strncpy(numstackptr->var, expr, var_name_size);
12431 numstackptr->contidional_second_val_initialized = 0;
12436 if (isdigit(arithval)) {
12437 numstackptr->var = NULL;
12438 #if ENABLE_ASH_MATH_SUPPORT_64
12439 numstackptr->val = strtoll(expr, (char **) &expr, 0);
12441 numstackptr->val = strtol(expr, (char **) &expr, 0);
12445 for (p = op_tokens; ; p++) {
12449 /* strange operator not found */
12452 for (o = expr; *p && *o == *p; p++)
12459 /* skip tail uncompared token */
12462 /* skip zero delim */
12467 /* post grammar: a++ reduce to num */
12468 if (lasttok == TOK_POST_INC || lasttok == TOK_POST_DEC)
12471 /* Plus and minus are binary (not unary) _only_ if the last
12472 * token was as number, or a right paren (which pretends to be
12473 * a number, since it evaluates to one). Think about it.
12474 * It makes sense. */
12475 if (lasttok != TOK_NUM) {
12491 /* We don't want a unary operator to cause recursive descent on the
12492 * stack, because there can be many in a row and it could cause an
12493 * operator to be evaluated before its argument is pushed onto the
12494 * integer stack. */
12495 /* But for binary operators, "apply" everything on the operator
12496 * stack until we find an operator with a lesser priority than the
12497 * one we have just extracted. */
12498 /* Left paren is given the lowest priority so it will never be
12499 * "applied" in this way.
12500 * if associativity is right and priority eq, applied also skip
12503 if ((prec > 0 && prec < UNARYPREC) || prec == SPEC_PREC) {
12504 /* not left paren or unary */
12505 if (lasttok != TOK_NUM) {
12506 /* binary op must be preceded by a num */
12509 while (stackptr != stack) {
12510 if (op == TOK_RPAREN) {
12511 /* The algorithm employed here is simple: while we don't
12512 * hit an open paren nor the bottom of the stack, pop
12513 * tokens and apply them */
12514 if (stackptr[-1] == TOK_LPAREN) {
12516 /* Any operator directly after a */
12518 /* close paren should consider itself binary */
12522 operator prev_prec = PREC(stackptr[-1]);
12524 convert_prec_is_assing(prec);
12525 convert_prec_is_assing(prev_prec);
12526 if (prev_prec < prec)
12528 /* check right assoc */
12529 if (prev_prec == prec && is_right_associativity(prec))
12532 errcode = arith_apply(*--stackptr, numstack, &numstackptr);
12533 if (errcode) goto ret;
12535 if (op == TOK_RPAREN) {
12540 /* Push this operator to the stack and remember it. */
12541 *stackptr++ = lasttok = op;
12546 #endif /* ASH_MATH_SUPPORT */
12549 /* ============ main() and helpers */
12552 * Called to exit the shell.
12554 static void exitshell(void) ATTRIBUTE_NORETURN;
12562 status = exitstatus;
12563 TRACE(("pid %d, exitshell(%d)\n", getpid(), status));
12564 if (setjmp(loc.loc)) {
12565 if (exception == EXEXIT)
12566 /* dash bug: it just does _exit(exitstatus) here
12567 * but we have to do setjobctl(0) first!
12568 * (bug is still not fixed in dash-0.5.3 - if you run dash
12569 * under Midnight Commander, on exit from dash MC is backgrounded) */
12570 status = exitstatus;
12573 exception_handler = &loc;
12579 flush_stdout_stderr();
12589 /* from input.c: */
12590 basepf.nextc = basepf.buf = basebuf;
12593 signal(SIGCHLD, SIG_DFL);
12598 char ppid[sizeof(int)*3 + 1];
12600 struct stat st1, st2;
12603 for (envp = environ; envp && *envp; envp++) {
12604 if (strchr(*envp, '=')) {
12605 setvareq(*envp, VEXPORT|VTEXTFIXED);
12609 snprintf(ppid, sizeof(ppid), "%u", (unsigned) getppid());
12610 setvar("PPID", ppid, 0);
12612 p = lookupvar("PWD");
12614 if (*p != '/' || stat(p, &st1) || stat(".", &st2)
12615 || st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino)
12622 * Process the shell command line arguments.
12625 procargs(int argc, char **argv)
12628 const char *xminusc;
12635 for (i = 0; i < NOPTS; i++)
12641 if (*xargv == NULL) {
12643 ash_msg_and_raise_error(bb_msg_requires_arg, "-c");
12646 if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
12650 for (i = 0; i < NOPTS; i++)
12651 if (optlist[i] == 2)
12656 /* POSIX 1003.2: first arg after -c cmd is $0, remainder $1... */
12661 } else if (!sflag) {
12662 setinputfile(*xargv, 0);
12665 commandname = arg0;
12668 shellparam.p = xargv;
12669 #if ENABLE_ASH_GETOPTS
12670 shellparam.optind = 1;
12671 shellparam.optoff = -1;
12673 /* assert(shellparam.malloc == 0 && shellparam.nparam == 0); */
12675 shellparam.nparam++;
12682 * Read /etc/profile or .profile.
12685 read_profile(const char *name)
12689 if (setinputfile(name, INPUT_PUSH_FILE | INPUT_NOFILE_OK) < 0)
12698 * This routine is called when an error or an interrupt occurs in an
12699 * interactive shell and control is returned to the main command loop.
12707 /* from input.c: */
12708 parselleft = parsenleft = 0; /* clear input buffer */
12710 /* from parser.c: */
12713 /* from redir.c: */
12718 static short profile_buf[16384];
12719 extern int etext();
12723 * Main routine. We initialize things, parse the arguments, execute
12724 * profiles if we're a login shell, and then call cmdloop to execute
12725 * commands. The setjmp call sets up the location to jump to when an
12726 * exception occurs. When an exception occurs the variable "state"
12727 * is used to figure out how far we had gotten.
12729 int ash_main(int argc, char **argv);
12730 int ash_main(int argc, char **argv)
12733 volatile int state;
12734 struct jmploc jmploc;
12735 struct stackmark smark;
12738 dash_errno = __errno_location();
12742 monitor(4, etext, profile_buf, sizeof(profile_buf), 50);
12745 #if ENABLE_FEATURE_EDITING
12746 line_input_state = new_line_input_t(FOR_SHELL | WITH_PATH_LOOKUP);
12749 if (setjmp(jmploc.loc)) {
12759 if (e == EXEXIT || s == 0 || iflag == 0 || shlvl)
12763 outcslow('\n', stderr);
12765 popstackmark(&smark);
12766 FORCE_INT_ON; /* enable interrupts */
12775 exception_handler = &jmploc;
12778 trace_puts("Shell args: ");
12779 trace_puts_args(argv);
12781 rootpid = getpid();
12783 #if ENABLE_ASH_RANDOM_SUPPORT
12784 rseed = rootpid + time(NULL);
12787 setstackmark(&smark);
12788 procargs(argc, argv);
12789 #if ENABLE_FEATURE_EDITING_SAVEHISTORY
12791 const char *hp = lookupvar("HISTFILE");
12794 hp = lookupvar("HOME");
12796 char *defhp = concat_path_file(hp, ".ash_history");
12797 setvar("HISTFILE", defhp, 0);
12803 if (argv[0] && argv[0][0] == '-')
12807 read_profile("/etc/profile");
12810 read_profile(".profile");
12816 getuid() == geteuid() && getgid() == getegid() &&
12820 shinit = lookupvar("ENV");
12821 if (shinit != NULL && *shinit != '\0') {
12822 read_profile(shinit);
12828 evalstring(minusc, 0);
12830 if (sflag || minusc == NULL) {
12831 #if ENABLE_FEATURE_EDITING_SAVEHISTORY
12833 const char *hp = lookupvar("HISTFILE");
12836 line_input_state->hist_file = hp;
12839 state4: /* XXX ??? - why isn't this before the "if" statement */
12847 extern void _mcleanup(void);
12856 const char *applet_name = "debug stuff usage";
12857 int main(int argc, char **argv)
12859 return ash_main(argc, argv);
12865 * Copyright (c) 1989, 1991, 1993, 1994
12866 * The Regents of the University of California. All rights reserved.
12868 * This code is derived from software contributed to Berkeley by
12869 * Kenneth Almquist.
12871 * Redistribution and use in source and binary forms, with or without
12872 * modification, are permitted provided that the following conditions
12874 * 1. Redistributions of source code must retain the above copyright
12875 * notice, this list of conditions and the following disclaimer.
12876 * 2. Redistributions in binary form must reproduce the above copyright
12877 * notice, this list of conditions and the following disclaimer in the
12878 * documentation and/or other materials provided with the distribution.
12879 * 3. Neither the name of the University nor the names of its contributors
12880 * may be used to endorse or promote products derived from this software
12881 * without specific prior written permission.
12883 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
12884 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
12885 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
12886 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
12887 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
12888 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
12889 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
12890 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
12891 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
12892 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF