1 /* vi: set sw=4 ts=4: */
3 * ash shell port for busybox
5 * Copyright (c) 1989, 1991, 1993, 1994
6 * The Regents of the University of California. All rights reserved.
8 * Copyright (c) 1997-2005 Herbert Xu <herbert@gondor.apana.org.au>
9 * was re-ported from NetBSD and debianized.
12 * This code is derived from software contributed to Berkeley by
15 * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
17 * Original BSD copyright notice is retained at the end of this file.
21 * rewrite arith.y to micro stack based cryptic algorithm by
22 * Copyright (c) 2001 Aaron Lehmann <aaronl@vitelus.com>
24 * Modified by Paul Mundt <lethal@linux-sh.org> (c) 2004 to support
27 * Modified by Vladimir Oleynik <dzo@simtreas.ru> (c) 2001-2005 to be
28 * used in busybox and size optimizations,
29 * rewrote arith (see notes to this), added locale support,
30 * rewrote dynamic variables.
35 * The follow should be set to reflect the type of system you have:
36 * JOBS -> 1 if you have Berkeley job control, 0 otherwise.
37 * define SYSV if you are running under System V.
38 * define DEBUG=1 to compile in debugging ('set -o debug' to turn on)
39 * define DEBUG=2 to compile in and turn on debugging.
41 * When debugging is on, debugging info will be written to ./trace and
42 * a quit signal will generate a core dump.
47 #if ENABLE_ASH_JOB_CONTROL
60 #if JOBS || ENABLE_ASH_READ_NCHARS
64 #if defined(__uClinux__)
65 #error "Do not even bother, ash will not run on uClinux"
69 /* ============ Misc helpers */
71 #define xbarrier() do { __asm__ __volatile__ ("": : :"memory"); } while (0)
73 /* C99 say: "char" declaration may be signed or unsigned default */
74 #define signed_char2int(sc) ((int)((signed char)sc))
77 /* ============ Shell options */
79 static const char *const optletters_optnames[] = {
100 #define optletters(n) optletters_optnames[(n)][0]
101 #define optnames(n) (&optletters_optnames[(n)][1])
103 #define NOPTS (sizeof(optletters_optnames)/sizeof(optletters_optnames[0]))
105 static char optlist[NOPTS];
107 #define eflag optlist[0]
108 #define fflag optlist[1]
109 #define Iflag optlist[2]
110 #define iflag optlist[3]
111 #define mflag optlist[4]
112 #define nflag optlist[5]
113 #define sflag optlist[6]
114 #define xflag optlist[7]
115 #define vflag optlist[8]
116 #define Cflag optlist[9]
117 #define aflag optlist[10]
118 #define bflag optlist[11]
119 #define uflag optlist[12]
120 #define viflag optlist[13]
122 #define nolog optlist[14]
123 #define debug optlist[15]
127 /* ============ Misc data */
131 static int *dash_errno;
133 #define errno (*dash_errno)
136 static char nullstr[1]; /* zero length string */
137 static const char homestr[] = "HOME";
138 static const char snlfmt[] = "%s\n";
139 static const char illnum[] = "Illegal number: %s";
141 static char *minusc; /* argument to -c option */
143 static int isloginsh;
144 /* pid of main shell */
146 /* shell level: 0 for the main shell, 1 for its children, and so on */
148 #define rootshell (!shlvl)
149 /* trap handler commands */
150 static char *trap[NSIG];
151 /* current value of signal */
152 static char sigmode[NSIG - 1];
153 /* indicates specified signal received */
154 static char gotsig[NSIG - 1];
155 static char *arg0; /* value of $0 */
158 /* ============ Interrupts / exceptions */
161 * We enclose jmp_buf in a structure so that we can declare pointers to
162 * jump locations. The global variable handler contains the location to
163 * jump to when an exception occurs, and the global variable exception
164 * contains a code identifying the exception. To implement nested
165 * exception handlers, the user should save the value of handler on entry
166 * to an inner scope, set handler to point to a jmploc structure for the
167 * inner scope, and restore handler on exit from the scope.
172 static struct jmploc *exception_handler;
173 static int exception;
175 #define EXINT 0 /* SIGINT received */
176 #define EXERROR 1 /* a generic error */
177 #define EXSHELLPROC 2 /* execute a shell procedure */
178 #define EXEXEC 3 /* command execution failed */
179 #define EXEXIT 4 /* exit the shell */
180 #define EXSIG 5 /* trapped signal in wait(1) */
181 static volatile int suppressint;
182 static volatile sig_atomic_t intpending;
183 /* do we generate EXSIG events */
185 /* last pending signal */
186 static volatile sig_atomic_t pendingsigs;
189 * Sigmode records the current value of the signal handlers for the various
190 * modes. A value of zero means that the current handler is not known.
191 * S_HARD_IGN indicates that the signal was ignored on entry to the shell,
194 #define S_DFL 1 /* default signal handling (SIG_DFL) */
195 #define S_CATCH 2 /* signal is caught */
196 #define S_IGN 3 /* signal is ignored (SIG_IGN) */
197 #define S_HARD_IGN 4 /* signal is ignored permenantly */
198 #define S_RESET 5 /* temporary - to reset a hard ignored sig */
201 * These macros allow the user to suspend the handling of interrupt signals
202 * over a period of time. This is similar to SIGHOLD to or sigblock, but
203 * much more efficient and portable. (But hacking the kernel is so much
204 * more fun than worrying about efficiency and portability. :-))
213 * Called to raise an exception. Since C doesn't include exceptions, we
214 * just do a longjmp to the exception handler. The type of exception is
215 * stored in the global variable "exception".
217 static void raise_exception(int) ATTRIBUTE_NORETURN;
219 raise_exception(int e)
222 if (exception_handler == NULL)
227 longjmp(exception_handler->loc, 1);
231 * Called from trap.c when a SIGINT is received. (If the user specifies
232 * that SIGINT is to be trapped or ignored using the trap builtin, then
233 * this routine is not called.) Suppressint is nonzero when interrupts
234 * are held using the INT_OFF macro. (The test for iflag is just
235 * defensive programming.)
237 static void raise_interrupt(void) ATTRIBUTE_NORETURN;
239 raise_interrupt(void)
245 if (gotsig[SIGINT - 1] && !trap[SIGINT]) {
246 if (!(rootshell && iflag)) {
247 signal(SIGINT, SIG_DFL);
256 #if ENABLE_ASH_OPTIMIZE_FOR_SIZE
260 if (--suppressint == 0 && intpending) {
264 #define INT_ON int_on()
272 #define FORCE_INT_ON force_int_on()
277 if (--suppressint == 0 && intpending) \
280 #define FORCE_INT_ON \
287 #endif /* ASH_OPTIMIZE_FOR_SIZE */
289 #define SAVE_INT(v) ((v) = suppressint)
291 #define RESTORE_INT(v) \
295 if (suppressint == 0 && intpending) \
304 raise_exception(EXSIG); \
306 /* EXSIG is turned off by evalbltin(). */
309 * Ignore a signal. Only one usage site - in forkchild()
314 if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) {
315 signal(signo, SIG_IGN);
317 sigmode[signo - 1] = S_HARD_IGN;
321 * Signal handler. Only one usage site - in setsignal()
326 gotsig[signo - 1] = 1;
329 if (exsig || (signo == SIGINT && !trap[SIGINT])) {
337 /* ============ Stdout/stderr output */
340 outstr(const char *p, FILE *file)
348 flush_stdout_stderr(void)
365 outcslow(int c, FILE *dest)
373 static int out1fmt(const char *, ...) __attribute__((__format__(__printf__,1,2)));
375 out1fmt(const char *fmt, ...)
382 r = vprintf(fmt, ap);
388 static int fmtstr(char *, size_t, const char *, ...) __attribute__((__format__(__printf__,3,4)));
390 fmtstr(char *outbuf, size_t length, const char *fmt, ...)
397 ret = vsnprintf(outbuf, length, fmt, ap);
404 out1str(const char *p)
410 out2str(const char *p)
417 /* ============ Parser structures */
419 /* control characters in argument strings */
420 #define CTLESC '\201' /* escape next character */
421 #define CTLVAR '\202' /* variable defn */
422 #define CTLENDVAR '\203'
423 #define CTLBACKQ '\204'
424 #define CTLQUOTE 01 /* ored with CTLBACKQ code if in quotes */
425 /* CTLBACKQ | CTLQUOTE == '\205' */
426 #define CTLARI '\206' /* arithmetic expression */
427 #define CTLENDARI '\207'
428 #define CTLQUOTEMARK '\210'
430 /* variable substitution byte (follows CTLVAR) */
431 #define VSTYPE 0x0f /* type of variable substitution */
432 #define VSNUL 0x10 /* colon--treat the empty string as unset */
433 #define VSQUOTE 0x80 /* inside double quotes--suppress splitting */
435 /* values of VSTYPE field */
436 #define VSNORMAL 0x1 /* normal variable: $var or ${var} */
437 #define VSMINUS 0x2 /* ${var-text} */
438 #define VSPLUS 0x3 /* ${var+text} */
439 #define VSQUESTION 0x4 /* ${var?message} */
440 #define VSASSIGN 0x5 /* ${var=text} */
441 #define VSTRIMRIGHT 0x6 /* ${var%pattern} */
442 #define VSTRIMRIGHTMAX 0x7 /* ${var%%pattern} */
443 #define VSTRIMLEFT 0x8 /* ${var#pattern} */
444 #define VSTRIMLEFTMAX 0x9 /* ${var##pattern} */
445 #define VSLENGTH 0xa /* ${#var} */
447 static const char dolatstr[] = { CTLVAR, VSNORMAL|VSQUOTE, '@', '=', '\0' };
482 union node *redirect;
488 struct nodelist *cmdlist;
494 union node *redirect;
507 union node *elsepart;
534 struct nodelist *backquote;
569 struct nredir nredir;
570 struct nbinary nbinary;
574 struct nclist nclist;
583 struct nodelist *next;
596 freefunc(struct funcnode *f)
598 if (f && --f->count < 0)
603 /* ============ Debugging output */
607 static FILE *tracefile;
610 trace_printf(const char *fmt, ...)
617 vfprintf(tracefile, fmt, va);
622 trace_vprintf(const char *fmt, va_list va)
626 vfprintf(tracefile, fmt, va);
630 trace_puts(const char *s)
638 trace_puts_quoted(char *s)
645 putc('"', tracefile);
646 for (p = s; *p; p++) {
648 case '\n': c = 'n'; goto backslash;
649 case '\t': c = 't'; goto backslash;
650 case '\r': c = 'r'; goto backslash;
651 case '"': c = '"'; goto backslash;
652 case '\\': c = '\\'; goto backslash;
653 case CTLESC: c = 'e'; goto backslash;
654 case CTLVAR: c = 'v'; goto backslash;
655 case CTLVAR+CTLQUOTE: c = 'V'; goto backslash;
656 case CTLBACKQ: c = 'q'; goto backslash;
657 case CTLBACKQ+CTLQUOTE: c = 'Q'; goto backslash;
659 putc('\\', tracefile);
663 if (*p >= ' ' && *p <= '~')
666 putc('\\', tracefile);
667 putc(*p >> 6 & 03, tracefile);
668 putc(*p >> 3 & 07, tracefile);
669 putc(*p & 07, tracefile);
674 putc('"', tracefile);
678 trace_puts_args(char **ap)
685 trace_puts_quoted(*ap);
687 putc('\n', tracefile);
690 putc(' ', tracefile);
705 /* leave open because libedit might be using it */
708 strcpy(s, "./trace");
710 if (!freopen(s, "a", tracefile)) {
711 fprintf(stderr, "Can't re-open %s\n", s);
716 tracefile = fopen(s, "a");
717 if (tracefile == NULL) {
718 fprintf(stderr, "Can't open %s\n", s);
724 flags = fcntl(fileno(tracefile), F_GETFL, 0);
726 fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND);
728 setlinebuf(tracefile);
729 fputs("\nTracing started.\n", tracefile);
733 indent(int amount, char *pfx, FILE *fp)
737 for (i = 0; i < amount; i++) {
738 if (pfx && i == amount - 1)
744 /* little circular references here... */
745 static void shtree(union node *n, int ind, char *pfx, FILE *fp);
748 sharg(union node *arg, FILE *fp)
751 struct nodelist *bqlist;
754 if (arg->type != NARG) {
755 out1fmt("<node type %d>\n", arg->type);
758 bqlist = arg->narg.backquote;
759 for (p = arg->narg.text; *p; p++) {
768 if (subtype == VSLENGTH)
777 switch (subtype & VSTYPE) {
810 out1fmt("<subtype %d>", subtype);
817 case CTLBACKQ|CTLQUOTE:
820 shtree(bqlist->n, -1, NULL, fp);
831 shcmd(union node *cmd, FILE *fp)
839 for (np = cmd->ncmd.args; np; np = np->narg.next) {
845 for (np = cmd->ncmd.redirect; np; np = np->nfile.next) {
848 switch (np->nfile.type) {
849 case NTO: s = ">"; dftfd = 1; break;
850 case NCLOBBER: s = ">|"; dftfd = 1; break;
851 case NAPPEND: s = ">>"; dftfd = 1; break;
852 case NTOFD: s = ">&"; dftfd = 1; break;
853 case NFROM: s = "<"; dftfd = 0; break;
854 case NFROMFD: s = "<&"; dftfd = 0; break;
855 case NFROMTO: s = "<>"; dftfd = 0; break;
856 default: s = "*error*"; dftfd = 0; break;
858 if (np->nfile.fd != dftfd)
859 fprintf(fp, "%d", np->nfile.fd);
861 if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) {
862 fprintf(fp, "%d", np->ndup.dupfd);
864 sharg(np->nfile.fname, fp);
871 shtree(union node *n, int ind, char *pfx, FILE *fp)
879 indent(ind, pfx, fp);
890 shtree(n->nbinary.ch1, ind, NULL, fp);
893 shtree(n->nbinary.ch2, ind, NULL, fp);
901 for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
906 if (n->npipe.backgnd)
912 fprintf(fp, "<node type %d>", n->type);
920 showtree(union node *n)
922 trace_puts("showtree called\n");
923 shtree(n, 1, NULL, stdout);
926 #define TRACE(param) trace_printf param
927 #define TRACEV(param) trace_vprintf param
932 #define TRACEV(param)
937 /* ============ Parser data */
940 * ash_vmsg() needs parsefile->fd, hence parsefile definition is moved up.
943 struct strlist *next;
952 struct strpush *prev; /* preceding string on stack */
956 struct alias *ap; /* if push was associated with an alias */
958 char *string; /* remember the string since it may change */
962 struct parsefile *prev; /* preceding file on stack */
963 int linno; /* current line */
964 int fd; /* file descriptor (or -1 if string) */
965 int nleft; /* number of chars left in this line */
966 int lleft; /* number of chars left in this buffer */
967 char *nextc; /* next char in buffer */
968 char *buf; /* input buffer */
969 struct strpush *strpush; /* for pushing strings at this level */
970 struct strpush basestrpush; /* so pushing one is fast */
973 static struct parsefile basepf; /* top level input file */
974 static struct parsefile *parsefile = &basepf; /* current input file */
975 static int startlinno; /* line # where last token started */
976 static char *commandname; /* currently executing command */
977 static struct strlist *cmdenviron; /* environment for builtin command */
978 static int exitstatus; /* exit status of last command */
981 /* ============ Message printing */
984 ash_vmsg(const char *msg, va_list ap)
986 fprintf(stderr, "%s: ", arg0);
988 const char *fmt = (!iflag || parsefile->fd) ?
990 fprintf(stderr, fmt, commandname, startlinno);
992 vfprintf(stderr, msg, ap);
993 outcslow('\n', stderr);
997 * Exverror is called to raise the error exception. If the second argument
998 * is not NULL then error prints an error message using printf style
999 * formatting. It then raises the error exception.
1001 static void ash_vmsg_and_raise(int, const char *, va_list) ATTRIBUTE_NORETURN;
1003 ash_vmsg_and_raise(int cond, const char *msg, va_list ap)
1007 TRACE(("ash_vmsg_and_raise(%d, \"", cond));
1009 TRACE(("\") pid=%d\n", getpid()));
1011 TRACE(("ash_vmsg_and_raise(%d, NULL) pid=%d\n", cond, getpid()));
1016 flush_stdout_stderr();
1017 raise_exception(cond);
1021 static void ash_msg_and_raise_error(const char *, ...) ATTRIBUTE_NORETURN;
1023 ash_msg_and_raise_error(const char *msg, ...)
1028 ash_vmsg_and_raise(EXERROR, msg, ap);
1033 static void ash_msg_and_raise(int, const char *, ...) ATTRIBUTE_NORETURN;
1035 ash_msg_and_raise(int cond, const char *msg, ...)
1040 ash_vmsg_and_raise(cond, msg, ap);
1046 * error/warning routines for external builtins
1049 ash_msg(const char *fmt, ...)
1059 * Return a string describing an error. The returned string may be a
1060 * pointer to a static buffer that will be overwritten on the next call.
1061 * Action describes the operation that got the error.
1064 errmsg(int e, const char *em)
1066 if (e == ENOENT || e == ENOTDIR) {
1073 /* ============ Memory allocation */
1076 * It appears that grabstackstr() will barf with such alignments
1077 * because stalloc() will return a string allocated in a new stackblock.
1079 #define SHELL_ALIGN(nbytes) (((nbytes) + SHELL_SIZE) & ~SHELL_SIZE)
1081 /* Most machines require the value returned from malloc to be aligned
1082 * in some way. The following macro will get this right
1083 * on many machines. */
1084 SHELL_SIZE = sizeof(union {int i; char *cp; double d; }) - 1,
1085 /* Minimum size of a block */
1086 MINSIZE = SHELL_ALIGN(504),
1089 struct stack_block {
1090 struct stack_block *prev;
1091 char space[MINSIZE];
1095 struct stack_block *stackp;
1098 struct stackmark *marknext;
1101 static struct stack_block stackbase;
1102 static struct stack_block *stackp = &stackbase;
1103 static struct stackmark *markp;
1104 static char *stacknxt = stackbase.space;
1105 static size_t stacknleft = MINSIZE;
1106 static char *sstrend = stackbase.space + MINSIZE;
1107 static int herefd = -1;
1109 #define stackblock() ((void *)stacknxt)
1110 #define stackblocksize() stacknleft
1113 ckrealloc(void * p, size_t nbytes)
1115 p = realloc(p, nbytes);
1117 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1122 ckmalloc(size_t nbytes)
1124 return ckrealloc(NULL, nbytes);
1128 * Make a copy of a string in safe storage.
1131 ckstrdup(const char *s)
1133 char *p = strdup(s);
1135 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1140 * Parse trees for commands are allocated in lifo order, so we use a stack
1141 * to make this more efficient, and also to avoid all sorts of exception
1142 * handling code to handle interrupts in the middle of a parse.
1144 * The size 504 was chosen because the Ultrix malloc handles that size
1148 stalloc(size_t nbytes)
1153 aligned = SHELL_ALIGN(nbytes);
1154 if (aligned > stacknleft) {
1157 struct stack_block *sp;
1159 blocksize = aligned;
1160 if (blocksize < MINSIZE)
1161 blocksize = MINSIZE;
1162 len = sizeof(struct stack_block) - MINSIZE + blocksize;
1163 if (len < blocksize)
1164 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1168 stacknxt = sp->space;
1169 stacknleft = blocksize;
1170 sstrend = stacknxt + blocksize;
1175 stacknxt += aligned;
1176 stacknleft -= aligned;
1184 if (!p || (stacknxt < (char *)p) || ((char *)p < stackp->space)) {
1185 write(2, "stunalloc\n", 10);
1189 stacknleft += stacknxt - (char *)p;
1194 * Like strdup but works with the ash stack.
1197 ststrdup(const char *p)
1199 size_t len = strlen(p) + 1;
1200 return memcpy(stalloc(len), p, len);
1204 setstackmark(struct stackmark *mark)
1206 mark->stackp = stackp;
1207 mark->stacknxt = stacknxt;
1208 mark->stacknleft = stacknleft;
1209 mark->marknext = markp;
1214 popstackmark(struct stackmark *mark)
1216 struct stack_block *sp;
1219 markp = mark->marknext;
1220 while (stackp != mark->stackp) {
1225 stacknxt = mark->stacknxt;
1226 stacknleft = mark->stacknleft;
1227 sstrend = mark->stacknxt + mark->stacknleft;
1232 * When the parser reads in a string, it wants to stick the string on the
1233 * stack and only adjust the stack pointer when it knows how big the
1234 * string is. Stackblock (defined in stack.h) returns a pointer to a block
1235 * of space on top of the stack and stackblocklen returns the length of
1236 * this block. Growstackblock will grow this space by at least one byte,
1237 * possibly moving it (like realloc). Grabstackblock actually allocates the
1238 * part of the block that has been used.
1241 growstackblock(void)
1245 newlen = stacknleft * 2;
1246 if (newlen < stacknleft)
1247 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1251 if (stacknxt == stackp->space && stackp != &stackbase) {
1252 struct stack_block *oldstackp;
1253 struct stackmark *xmark;
1254 struct stack_block *sp;
1255 struct stack_block *prevstackp;
1261 prevstackp = sp->prev;
1262 grosslen = newlen + sizeof(struct stack_block) - MINSIZE;
1263 sp = ckrealloc(sp, grosslen);
1264 sp->prev = prevstackp;
1266 stacknxt = sp->space;
1267 stacknleft = newlen;
1268 sstrend = sp->space + newlen;
1271 * Stack marks pointing to the start of the old block
1272 * must be relocated to point to the new block
1275 while (xmark != NULL && xmark->stackp == oldstackp) {
1276 xmark->stackp = stackp;
1277 xmark->stacknxt = stacknxt;
1278 xmark->stacknleft = stacknleft;
1279 xmark = xmark->marknext;
1283 char *oldspace = stacknxt;
1284 int oldlen = stacknleft;
1285 char *p = stalloc(newlen);
1287 /* free the space we just allocated */
1288 stacknxt = memcpy(p, oldspace, oldlen);
1289 stacknleft += newlen;
1294 grabstackblock(size_t len)
1296 len = SHELL_ALIGN(len);
1302 * The following routines are somewhat easier to use than the above.
1303 * The user declares a variable of type STACKSTR, which may be declared
1304 * to be a register. The macro STARTSTACKSTR initializes things. Then
1305 * the user uses the macro STPUTC to add characters to the string. In
1306 * effect, STPUTC(c, p) is the same as *p++ = c except that the stack is
1307 * grown as necessary. When the user is done, she can just leave the
1308 * string there and refer to it using stackblock(). Or she can allocate
1309 * the space for it using grabstackstr(). If it is necessary to allow
1310 * someone else to use the stack temporarily and then continue to grow
1311 * the string, the user should use grabstack to allocate the space, and
1312 * then call ungrabstr(p) to return to the previous mode of operation.
1314 * USTPUTC is like STPUTC except that it doesn't check for overflow.
1315 * CHECKSTACKSPACE can be called before USTPUTC to ensure that there
1316 * is space for at least one character.
1321 size_t len = stackblocksize();
1322 if (herefd >= 0 && len >= 1024) {
1323 full_write(herefd, stackblock(), len);
1324 return stackblock();
1327 return stackblock() + len;
1331 * Called from CHECKSTRSPACE.
1334 makestrspace(size_t newlen, char *p)
1336 size_t len = p - stacknxt;
1337 size_t size = stackblocksize();
1342 size = stackblocksize();
1344 if (nleft >= newlen)
1348 return stackblock() + len;
1352 stack_nputstr(const char *s, size_t n, char *p)
1354 p = makestrspace(n, p);
1355 p = memcpy(p, s, n) + n;
1360 stack_putstr(const char *s, char *p)
1362 return stack_nputstr(s, strlen(s), p);
1366 _STPUTC(int c, char *p)
1374 #define STARTSTACKSTR(p) ((p) = stackblock())
1375 #define STPUTC(c, p) ((p) = _STPUTC((c), (p)))
1376 #define CHECKSTRSPACE(n, p) \
1380 size_t m = sstrend - q; \
1382 (p) = makestrspace(l, q); \
1384 #define USTPUTC(c, p) (*p++ = (c))
1385 #define STACKSTRNUL(p) \
1387 if ((p) == sstrend) \
1388 p = growstackstr(); \
1391 #define STUNPUTC(p) (--p)
1392 #define STTOPC(p) (p[-1])
1393 #define STADJUST(amount, p) (p += (amount))
1395 #define grabstackstr(p) stalloc((char *)(p) - (char *)stackblock())
1396 #define ungrabstackstr(s, p) stunalloc((s))
1397 #define stackstrend() ((void *)sstrend)
1400 /* ============ String helpers */
1403 * prefix -- see if pfx is a prefix of string.
1406 prefix(const char *string, const char *pfx)
1409 if (*pfx++ != *string++)
1412 return (char *) string;
1416 * Check for a valid number. This should be elsewhere.
1419 is_number(const char *p)
1424 } while (*++p != '\0');
1429 * Convert a string of digits to an integer, printing an error message on
1433 number(const char *s)
1436 ash_msg_and_raise_error(illnum, s);
1441 * Produce a possibly single quoted string suitable as input to the shell.
1442 * The return string is allocated on the stack.
1445 single_quote(const char *s)
1455 len = strchrnul(s, '\'') - s;
1457 q = p = makestrspace(len + 3, p);
1460 q = memcpy(q, s, len) + len;
1466 len = strspn(s, "'");
1470 q = p = makestrspace(len + 3, p);
1473 q = memcpy(q, s, len) + len;
1482 return stackblock();
1486 /* ============ nextopt */
1488 static char **argptr; /* argument list for builtin commands */
1489 static char *optionarg; /* set by nextopt (like getopt) */
1490 static char *optptr; /* used by nextopt */
1493 * XXX - should get rid of. have all builtins use getopt(3). the
1494 * library getopt must have the BSD extension static variable "optreset"
1495 * otherwise it can't be used within the shell safely.
1497 * Standard option processing (a la getopt) for builtin routines. The
1498 * only argument that is passed to nextopt is the option string; the
1499 * other arguments are unnecessary. It return the character, or '\0' on
1503 nextopt(const char *optstring)
1510 if (p == NULL || *p == '\0') {
1512 if (p == NULL || *p != '-' || *++p == '\0')
1515 if (LONE_DASH(p)) /* check for "--" */
1519 for (q = optstring; *q != c; ) {
1521 ash_msg_and_raise_error("Illegal option -%c", c);
1526 if (*p == '\0' && (p = *argptr++) == NULL)
1527 ash_msg_and_raise_error("No arg for -%c option", c);
1536 /* ============ Math support definitions */
1538 #if ENABLE_ASH_MATH_SUPPORT_64
1539 typedef int64_t arith_t;
1540 #define arith_t_type long long
1542 typedef long arith_t;
1543 #define arith_t_type long
1546 #if ENABLE_ASH_MATH_SUPPORT
1547 static arith_t dash_arith(const char *);
1548 static arith_t arith(const char *expr, int *perrcode);
1551 #if ENABLE_ASH_RANDOM_SUPPORT
1552 static unsigned long rseed;
1559 /* ============ Shell variables */
1562 #define VEXPORT 0x01 /* variable is exported */
1563 #define VREADONLY 0x02 /* variable cannot be modified */
1564 #define VSTRFIXED 0x04 /* variable struct is statically allocated */
1565 #define VTEXTFIXED 0x08 /* text is statically allocated */
1566 #define VSTACK 0x10 /* text is allocated on the stack */
1567 #define VUNSET 0x20 /* the variable is not set */
1568 #define VNOFUNC 0x40 /* don't call the callback function */
1569 #define VNOSET 0x80 /* do not set variable - just readonly test */
1570 #define VNOSAVE 0x100 /* when text is on the heap before setvareq */
1572 # define VDYNAMIC 0x200 /* dynamic variable */
1577 static const char defpathvar[] = "PATH=/usr/local/bin:/usr/bin:/sbin:/bin";
1579 static const char defifsvar[] = "IFS= \t\n";
1580 #define defifs (defifsvar + 4)
1582 static const char defifs[] = " \t\n";
1586 int nparam; /* # of positional parameters (without $0) */
1587 unsigned char malloc; /* if parameter list dynamically allocated */
1588 char **p; /* parameter list */
1589 #if ENABLE_ASH_GETOPTS
1590 int optind; /* next parameter to be processed by getopts */
1591 int optoff; /* used by getopts */
1595 static struct shparam shellparam; /* $@ current positional parameters */
1598 * Free the list of positional parameters.
1601 freeparam(volatile struct shparam *param)
1605 if (param->malloc) {
1606 for (ap = param->p; *ap; ap++)
1612 #if ENABLE_ASH_GETOPTS
1614 getoptsreset(const char *value)
1616 shellparam.optind = number(value);
1617 shellparam.optoff = -1;
1622 struct var *next; /* next entry in hash list */
1623 int flags; /* flags are defined above */
1624 const char *text; /* name=value */
1625 void (*func)(const char *); /* function to be called when */
1626 /* the variable gets set/unset */
1630 struct localvar *next; /* next local variable in list */
1631 struct var *vp; /* the variable that was made local */
1632 int flags; /* saved flags */
1633 const char *text; /* saved text */
1636 /* Forward decls for varinit[] */
1637 #if ENABLE_LOCALE_SUPPORT
1639 change_lc_all(const char *value)
1641 if (value && *value != '\0')
1642 setlocale(LC_ALL, value);
1645 change_lc_ctype(const char *value)
1647 if (value && *value != '\0')
1648 setlocale(LC_CTYPE, value);
1652 static void chkmail(void);
1653 static void changemail(const char *);
1655 static void changepath(const char *);
1656 #if ENABLE_ASH_RANDOM_SUPPORT
1657 static void change_random(const char *);
1660 static struct var varinit[] = {
1662 { NULL, VSTRFIXED|VTEXTFIXED, defifsvar, NULL },
1664 { NULL, VSTRFIXED|VTEXTFIXED|VUNSET, "IFS\0", NULL },
1667 { NULL, VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL\0", changemail },
1668 { NULL, VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH\0", changemail },
1670 { NULL, VSTRFIXED|VTEXTFIXED, defpathvar, changepath },
1671 { NULL, VSTRFIXED|VTEXTFIXED, "PS1=$ ", NULL },
1672 { NULL, VSTRFIXED|VTEXTFIXED, "PS2=> ", NULL },
1673 { NULL, VSTRFIXED|VTEXTFIXED, "PS4=+ ", NULL },
1674 #if ENABLE_ASH_GETOPTS
1675 { NULL, VSTRFIXED|VTEXTFIXED, "OPTIND=1", getoptsreset },
1677 #if ENABLE_ASH_RANDOM_SUPPORT
1678 { NULL, VSTRFIXED|VTEXTFIXED|VUNSET|VDYNAMIC, "RANDOM\0", change_random },
1680 #if ENABLE_LOCALE_SUPPORT
1681 { NULL, VSTRFIXED | VTEXTFIXED | VUNSET, "LC_ALL\0", change_lc_all },
1682 { NULL, VSTRFIXED | VTEXTFIXED | VUNSET, "LC_CTYPE\0", change_lc_ctype },
1684 #if ENABLE_FEATURE_EDITING_SAVEHISTORY
1685 { NULL, VSTRFIXED | VTEXTFIXED | VUNSET, "HISTFILE\0", NULL },
1689 #define vifs varinit[0]
1691 #define vmail (&vifs)[1]
1692 #define vmpath (&vmail)[1]
1696 #define vpath (&vmpath)[1]
1697 #define vps1 (&vpath)[1]
1698 #define vps2 (&vps1)[1]
1699 #define vps4 (&vps2)[1]
1700 #define voptind (&vps4)[1]
1701 #if ENABLE_ASH_GETOPTS
1702 #define vrandom (&voptind)[1]
1704 #define vrandom (&vps4)[1]
1706 #define defpath (defpathvar + 5)
1709 * The following macros access the values of the above variables.
1710 * They have to skip over the name. They return the null string
1711 * for unset variables.
1713 #define ifsval() (vifs.text + 4)
1714 #define ifsset() ((vifs.flags & VUNSET) == 0)
1715 #define mailval() (vmail.text + 5)
1716 #define mpathval() (vmpath.text + 9)
1717 #define pathval() (vpath.text + 5)
1718 #define ps1val() (vps1.text + 4)
1719 #define ps2val() (vps2.text + 4)
1720 #define ps4val() (vps4.text + 4)
1721 #define optindval() (voptind.text + 7)
1723 #define mpathset() ((vmpath.flags & VUNSET) == 0)
1726 * The parsefile structure pointed to by the global variable parsefile
1727 * contains information about the current file being read.
1730 struct redirtab *next;
1735 static struct redirtab *redirlist;
1736 static int nullredirs;
1737 extern char **environ;
1738 static int preverrout_fd; /* save fd2 before print debug if xflag is set. */
1742 static struct var *vartab[VTABSIZE];
1744 #define is_name(c) ((c) == '_' || isalpha((unsigned char)(c)))
1745 #define is_in_name(c) ((c) == '_' || isalnum((unsigned char)(c)))
1748 * Return of a legal variable name (a letter or underscore followed by zero or
1749 * more letters, underscores, and digits).
1752 endofname(const char *name)
1760 if (!is_in_name(*p))
1767 * Compares two strings up to the first = or '\0'. The first
1768 * string must be terminated by '='; the second may be terminated by
1769 * either '=' or '\0'.
1772 varcmp(const char *p, const char *q)
1776 while ((c = *p) == (d = *q)) {
1791 varequal(const char *a, const char *b)
1793 return !varcmp(a, b);
1797 * Find the appropriate entry in the hash table from the name.
1799 static struct var **
1800 hashvar(const char *p)
1804 hashval = ((unsigned char) *p) << 4;
1805 while (*p && *p != '=')
1806 hashval += (unsigned char) *p++;
1807 return &vartab[hashval % VTABSIZE];
1811 vpcmp(const void *a, const void *b)
1813 return varcmp(*(const char **)a, *(const char **)b);
1817 * This routine initializes the builtin variables.
1827 * PS1 depends on uid
1829 #if ENABLE_FEATURE_EDITING && ENABLE_FEATURE_EDITING_FANCY_PROMPT
1830 vps1.text = "PS1=\\w \\$ ";
1833 vps1.text = "PS1=# ";
1836 end = vp + sizeof(varinit) / sizeof(varinit[0]);
1838 vpp = hashvar(vp->text);
1841 } while (++vp < end);
1844 static struct var **
1845 findvar(struct var **vpp, const char *name)
1847 for (; *vpp; vpp = &(*vpp)->next) {
1848 if (varequal((*vpp)->text, name)) {
1856 * Find the value of a variable. Returns NULL if not set.
1859 lookupvar(const char *name)
1863 v = *findvar(hashvar(name), name);
1867 * Dynamic variables are implemented roughly the same way they are
1868 * in bash. Namely, they're "special" so long as they aren't unset.
1869 * As soon as they're unset, they're no longer dynamic, and dynamic
1870 * lookup will no longer happen at that point. -- PFM.
1872 if ((v->flags & VDYNAMIC))
1875 if (!(v->flags & VUNSET))
1876 return strchrnul(v->text, '=') + 1;
1882 * Search the environment of a builtin command.
1885 bltinlookup(const char *name)
1889 for (sp = cmdenviron; sp; sp = sp->next) {
1890 if (varequal(sp->text, name))
1891 return strchrnul(sp->text, '=') + 1;
1893 return lookupvar(name);
1897 * Same as setvar except that the variable and value are passed in
1898 * the first argument as name=value. Since the first argument will
1899 * be actually stored in the table, it should not be a string that
1901 * Called with interrupts off.
1904 setvareq(char *s, int flags)
1906 struct var *vp, **vpp;
1909 flags |= (VEXPORT & (((unsigned) (1 - aflag)) - 1));
1910 vp = *findvar(vpp, s);
1912 if ((vp->flags & (VREADONLY|VDYNAMIC)) == VREADONLY) {
1915 if (flags & VNOSAVE)
1918 ash_msg_and_raise_error("%.*s: is read only", strchrnul(n, '=') - n, n);
1924 if (vp->func && (flags & VNOFUNC) == 0)
1925 (*vp->func)(strchrnul(s, '=') + 1);
1927 if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
1928 free((char*)vp->text);
1930 flags |= vp->flags & ~(VTEXTFIXED|VSTACK|VNOSAVE|VUNSET);
1935 vp = ckmalloc(sizeof(*vp));
1940 if (!(flags & (VTEXTFIXED|VSTACK|VNOSAVE)))
1947 * Set the value of a variable. The flags argument is ored with the
1948 * flags of the variable. If val is NULL, the variable is unset.
1951 setvar(const char *name, const char *val, int flags)
1958 q = endofname(name);
1959 p = strchrnul(q, '=');
1961 if (!namelen || p != q)
1962 ash_msg_and_raise_error("%.*s: bad variable name", namelen, name);
1967 vallen = strlen(val);
1970 nameeq = ckmalloc(namelen + vallen + 2);
1971 p = memcpy(nameeq, name, namelen) + namelen;
1974 p = memcpy(p, val, vallen) + vallen;
1977 setvareq(nameeq, flags | VNOSAVE);
1981 #if ENABLE_ASH_GETOPTS
1983 * Safe version of setvar, returns 1 on success 0 on failure.
1986 setvarsafe(const char *name, const char *val, int flags)
1989 volatile int saveint;
1990 struct jmploc *volatile savehandler = exception_handler;
1991 struct jmploc jmploc;
1994 if (setjmp(jmploc.loc))
1997 exception_handler = &jmploc;
1998 setvar(name, val, flags);
2001 exception_handler = savehandler;
2002 RESTORE_INT(saveint);
2008 * Unset the specified variable.
2011 unsetvar(const char *s)
2017 vpp = findvar(hashvar(s), s);
2021 int flags = vp->flags;
2024 if (flags & VREADONLY)
2027 vp->flags &= ~VDYNAMIC;
2031 if ((flags & VSTRFIXED) == 0) {
2033 if ((flags & (VTEXTFIXED|VSTACK)) == 0)
2034 free((char*)vp->text);
2040 vp->flags &= ~VEXPORT;
2050 * Process a linked list of variable assignments.
2053 listsetvar(struct strlist *list_set_var, int flags)
2055 struct strlist *lp = list_set_var;
2061 setvareq(lp->text, flags);
2068 * Generate a list of variables satisfying the given conditions.
2071 listvars(int on, int off, char ***end)
2082 for (vp = *vpp; vp; vp = vp->next) {
2083 if ((vp->flags & mask) == on) {
2084 if (ep == stackstrend())
2085 ep = growstackstr();
2086 *ep++ = (char *) vp->text;
2089 } while (++vpp < vartab + VTABSIZE);
2090 if (ep == stackstrend())
2091 ep = growstackstr();
2095 return grabstackstr(ep);
2099 /* ============ Path search helper
2101 * The variable path (passed by reference) should be set to the start
2102 * of the path before the first call; padvance will update
2103 * this value as it proceeds. Successive calls to padvance will return
2104 * the possible path expansions in sequence. If an option (indicated by
2105 * a percent sign) appears in the path entry then the global variable
2106 * pathopt will be set to point to it; otherwise pathopt will be set to
2109 static const char *pathopt; /* set by padvance */
2112 padvance(const char **path, const char *name)
2122 for (p = start; *p && *p != ':' && *p != '%'; p++);
2123 len = p - start + strlen(name) + 2; /* "2" is for '/' and '\0' */
2124 while (stackblocksize() < len)
2128 memcpy(q, start, p - start);
2136 while (*p && *p != ':') p++;
2142 return stalloc(len);
2146 /* ============ Prompt */
2148 static int doprompt; /* if set, prompt the user */
2149 static int needprompt; /* true if interactive and at start of line */
2151 #if ENABLE_FEATURE_EDITING
2152 static line_input_t *line_input_state;
2153 static const char *cmdedit_prompt;
2155 putprompt(const char *s)
2157 if (ENABLE_ASH_EXPAND_PRMT) {
2158 free((char*)cmdedit_prompt);
2159 cmdedit_prompt = xstrdup(s);
2166 putprompt(const char *s)
2172 #if ENABLE_ASH_EXPAND_PRMT
2173 /* expandstr() needs parsing machinery, so it is far away ahead... */
2174 static const char *expandstr(const char *ps);
2176 #define expandstr(s) s
2180 setprompt(int whichprompt)
2183 #if ENABLE_ASH_EXPAND_PRMT
2184 struct stackmark smark;
2189 switch (whichprompt) {
2199 #if ENABLE_ASH_EXPAND_PRMT
2200 setstackmark(&smark);
2201 stalloc(stackblocksize());
2203 putprompt(expandstr(prompt));
2204 #if ENABLE_ASH_EXPAND_PRMT
2205 popstackmark(&smark);
2210 /* ============ The cd and pwd commands */
2212 #define CD_PHYSICAL 1
2215 static int docd(const char *, int);
2217 static char *curdir = nullstr; /* current working directory */
2218 static char *physdir = nullstr; /* physical working directory */
2227 while ((i = nextopt("LP"))) {
2229 flags ^= CD_PHYSICAL;
2238 * Update curdir (the name of the current directory) in response to a
2242 updatepwd(const char *dir)
2249 cdcomppath = ststrdup(dir);
2252 if (curdir == nullstr)
2254 new = stack_putstr(curdir, new);
2256 new = makestrspace(strlen(dir) + 2, new);
2257 lim = stackblock() + 1;
2261 if (new > lim && *lim == '/')
2266 if (dir[1] == '/' && dir[2] != '/') {
2272 p = strtok(cdcomppath, "/");
2276 if (p[1] == '.' && p[2] == '\0') {
2283 } else if (p[1] == '\0')
2287 new = stack_putstr(p, new);
2295 return stackblock();
2299 * Find out what the current directory is. If we already know the current
2300 * directory, this routine returns immediately.
2305 char *dir = getcwd(0, 0);
2306 return dir ? dir : nullstr;
2310 setpwd(const char *val, int setold)
2314 oldcur = dir = curdir;
2317 setvar("OLDPWD", oldcur, VEXPORT);
2320 if (physdir != nullstr) {
2321 if (physdir != oldcur)
2325 if (oldcur == val || !val) {
2331 dir = ckstrdup(val);
2332 if (oldcur != dir && oldcur != nullstr) {
2337 setvar("PWD", dir, VEXPORT);
2340 static void hashcd(void);
2343 * Actually do the chdir. We also call hashcd to let the routines in exec.c
2344 * know that the current directory has changed.
2347 docd(const char *dest, int flags)
2349 const char *dir = 0;
2352 TRACE(("docd(\"%s\", %d) called\n", dest, flags));
2355 if (!(flags & CD_PHYSICAL)) {
2356 dir = updatepwd(dest);
2371 cdcmd(int argc, char **argv)
2383 dest = bltinlookup(homestr);
2384 else if (LONE_DASH(dest)) {
2385 dest = bltinlookup("OLDPWD");
2407 path = bltinlookup("CDPATH");
2416 p = padvance(&path, dest);
2417 if (stat(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) {
2421 if (!docd(p, flags))
2426 ash_msg_and_raise_error("can't cd to %s", dest);
2429 if (flags & CD_PRINT)
2430 out1fmt(snlfmt, curdir);
2435 pwdcmd(int argc, char **argv)
2438 const char *dir = curdir;
2442 if (physdir == nullstr)
2446 out1fmt(snlfmt, dir);
2451 /* ============ ... */
2453 #define IBUFSIZ (BUFSIZ + 1)
2454 #define basebuf bb_common_bufsiz1 /* buffer for top level input file */
2456 /* Syntax classes */
2457 #define CWORD 0 /* character is nothing special */
2458 #define CNL 1 /* newline character */
2459 #define CBACK 2 /* a backslash character */
2460 #define CSQUOTE 3 /* single quote */
2461 #define CDQUOTE 4 /* double quote */
2462 #define CENDQUOTE 5 /* a terminating quote */
2463 #define CBQUOTE 6 /* backwards single quote */
2464 #define CVAR 7 /* a dollar sign */
2465 #define CENDVAR 8 /* a '}' character */
2466 #define CLP 9 /* a left paren in arithmetic */
2467 #define CRP 10 /* a right paren in arithmetic */
2468 #define CENDFILE 11 /* end of file */
2469 #define CCTL 12 /* like CWORD, except it must be escaped */
2470 #define CSPCL 13 /* these terminate a word */
2471 #define CIGN 14 /* character should be ignored */
2473 #if ENABLE_ASH_ALIAS
2477 #define PEOA_OR_PEOF PEOA
2481 #define PEOA_OR_PEOF PEOF
2484 /* number syntax index */
2485 #define BASESYNTAX 0 /* not in quotes */
2486 #define DQSYNTAX 1 /* in double quotes */
2487 #define SQSYNTAX 2 /* in single quotes */
2488 #define ARISYNTAX 3 /* in arithmetic */
2490 #if ENABLE_ASH_OPTIMIZE_FOR_SIZE
2491 #define USE_SIT_FUNCTION
2494 #if ENABLE_ASH_MATH_SUPPORT
2495 static const char S_I_T[][4] = {
2496 #if ENABLE_ASH_ALIAS
2497 { CSPCL, CIGN, CIGN, CIGN }, /* 0, PEOA */
2499 { CSPCL, CWORD, CWORD, CWORD }, /* 1, ' ' */
2500 { CNL, CNL, CNL, CNL }, /* 2, \n */
2501 { CWORD, CCTL, CCTL, CWORD }, /* 3, !*-/:=?[]~ */
2502 { CDQUOTE, CENDQUOTE, CWORD, CWORD }, /* 4, '"' */
2503 { CVAR, CVAR, CWORD, CVAR }, /* 5, $ */
2504 { CSQUOTE, CWORD, CENDQUOTE, CWORD }, /* 6, "'" */
2505 { CSPCL, CWORD, CWORD, CLP }, /* 7, ( */
2506 { CSPCL, CWORD, CWORD, CRP }, /* 8, ) */
2507 { CBACK, CBACK, CCTL, CBACK }, /* 9, \ */
2508 { CBQUOTE, CBQUOTE, CWORD, CBQUOTE }, /* 10, ` */
2509 { CENDVAR, CENDVAR, CWORD, CENDVAR }, /* 11, } */
2510 #ifndef USE_SIT_FUNCTION
2511 { CENDFILE, CENDFILE, CENDFILE, CENDFILE }, /* 12, PEOF */
2512 { CWORD, CWORD, CWORD, CWORD }, /* 13, 0-9A-Za-z */
2513 { CCTL, CCTL, CCTL, CCTL } /* 14, CTLESC ... */
2517 static const char S_I_T[][3] = {
2518 #if ENABLE_ASH_ALIAS
2519 { CSPCL, CIGN, CIGN }, /* 0, PEOA */
2521 { CSPCL, CWORD, CWORD }, /* 1, ' ' */
2522 { CNL, CNL, CNL }, /* 2, \n */
2523 { CWORD, CCTL, CCTL }, /* 3, !*-/:=?[]~ */
2524 { CDQUOTE, CENDQUOTE, CWORD }, /* 4, '"' */
2525 { CVAR, CVAR, CWORD }, /* 5, $ */
2526 { CSQUOTE, CWORD, CENDQUOTE }, /* 6, "'" */
2527 { CSPCL, CWORD, CWORD }, /* 7, ( */
2528 { CSPCL, CWORD, CWORD }, /* 8, ) */
2529 { CBACK, CBACK, CCTL }, /* 9, \ */
2530 { CBQUOTE, CBQUOTE, CWORD }, /* 10, ` */
2531 { CENDVAR, CENDVAR, CWORD }, /* 11, } */
2532 #ifndef USE_SIT_FUNCTION
2533 { CENDFILE, CENDFILE, CENDFILE }, /* 12, PEOF */
2534 { CWORD, CWORD, CWORD }, /* 13, 0-9A-Za-z */
2535 { CCTL, CCTL, CCTL } /* 14, CTLESC ... */
2538 #endif /* ASH_MATH_SUPPORT */
2540 #ifdef USE_SIT_FUNCTION
2543 SIT(int c, int syntax)
2545 static const char spec_symbls[] = "\t\n !\"$&'()*-/:;<=>?[\\]`|}~";
2546 #if ENABLE_ASH_ALIAS
2547 static const char syntax_index_table[] = {
2548 1, 2, 1, 3, 4, 5, 1, 6, /* "\t\n !\"$&'" */
2549 7, 8, 3, 3, 3, 3, 1, 1, /* "()*-/:;<" */
2550 3, 1, 3, 3, 9, 3, 10, 1, /* "=>?[\\]`|" */
2554 static const char syntax_index_table[] = {
2555 0, 1, 0, 2, 3, 4, 0, 5, /* "\t\n !\"$&'" */
2556 6, 7, 2, 2, 2, 2, 0, 0, /* "()*-/:;<" */
2557 2, 0, 2, 2, 8, 2, 9, 0, /* "=>?[\\]`|" */
2564 if (c == PEOF) /* 2^8+2 */
2566 #if ENABLE_ASH_ALIAS
2567 if (c == PEOA) /* 2^8+1 */
2571 #define U_C(c) ((unsigned char)(c))
2573 if ((unsigned char)c >= (unsigned char)(CTLESC)
2574 && (unsigned char)c <= (unsigned char)(CTLQUOTEMARK)
2578 s = strchr(spec_symbls, c);
2579 if (s == NULL || *s == '\0')
2581 indx = syntax_index_table[(s - spec_symbls)];
2583 return S_I_T[indx][syntax];
2586 #else /* !USE_SIT_FUNCTION */
2588 #if ENABLE_ASH_ALIAS
2589 #define CSPCL_CIGN_CIGN_CIGN 0
2590 #define CSPCL_CWORD_CWORD_CWORD 1
2591 #define CNL_CNL_CNL_CNL 2
2592 #define CWORD_CCTL_CCTL_CWORD 3
2593 #define CDQUOTE_CENDQUOTE_CWORD_CWORD 4
2594 #define CVAR_CVAR_CWORD_CVAR 5
2595 #define CSQUOTE_CWORD_CENDQUOTE_CWORD 6
2596 #define CSPCL_CWORD_CWORD_CLP 7
2597 #define CSPCL_CWORD_CWORD_CRP 8
2598 #define CBACK_CBACK_CCTL_CBACK 9
2599 #define CBQUOTE_CBQUOTE_CWORD_CBQUOTE 10
2600 #define CENDVAR_CENDVAR_CWORD_CENDVAR 11
2601 #define CENDFILE_CENDFILE_CENDFILE_CENDFILE 12
2602 #define CWORD_CWORD_CWORD_CWORD 13
2603 #define CCTL_CCTL_CCTL_CCTL 14
2605 #define CSPCL_CWORD_CWORD_CWORD 0
2606 #define CNL_CNL_CNL_CNL 1
2607 #define CWORD_CCTL_CCTL_CWORD 2
2608 #define CDQUOTE_CENDQUOTE_CWORD_CWORD 3
2609 #define CVAR_CVAR_CWORD_CVAR 4
2610 #define CSQUOTE_CWORD_CENDQUOTE_CWORD 5
2611 #define CSPCL_CWORD_CWORD_CLP 6
2612 #define CSPCL_CWORD_CWORD_CRP 7
2613 #define CBACK_CBACK_CCTL_CBACK 8
2614 #define CBQUOTE_CBQUOTE_CWORD_CBQUOTE 9
2615 #define CENDVAR_CENDVAR_CWORD_CENDVAR 10
2616 #define CENDFILE_CENDFILE_CENDFILE_CENDFILE 11
2617 #define CWORD_CWORD_CWORD_CWORD 12
2618 #define CCTL_CCTL_CCTL_CCTL 13
2621 static const char syntax_index_table[258] = {
2622 /* BASESYNTAX_DQSYNTAX_SQSYNTAX_ARISYNTAX */
2623 /* 0 PEOF */ CENDFILE_CENDFILE_CENDFILE_CENDFILE,
2624 #if ENABLE_ASH_ALIAS
2625 /* 1 PEOA */ CSPCL_CIGN_CIGN_CIGN,
2627 /* 2 -128 0x80 */ CWORD_CWORD_CWORD_CWORD,
2628 /* 3 -127 CTLESC */ CCTL_CCTL_CCTL_CCTL,
2629 /* 4 -126 CTLVAR */ CCTL_CCTL_CCTL_CCTL,
2630 /* 5 -125 CTLENDVAR */ CCTL_CCTL_CCTL_CCTL,
2631 /* 6 -124 CTLBACKQ */ CCTL_CCTL_CCTL_CCTL,
2632 /* 7 -123 CTLQUOTE */ CCTL_CCTL_CCTL_CCTL,
2633 /* 8 -122 CTLARI */ CCTL_CCTL_CCTL_CCTL,
2634 /* 9 -121 CTLENDARI */ CCTL_CCTL_CCTL_CCTL,
2635 /* 10 -120 CTLQUOTEMARK */ CCTL_CCTL_CCTL_CCTL,
2636 /* 11 -119 */ CWORD_CWORD_CWORD_CWORD,
2637 /* 12 -118 */ CWORD_CWORD_CWORD_CWORD,
2638 /* 13 -117 */ CWORD_CWORD_CWORD_CWORD,
2639 /* 14 -116 */ CWORD_CWORD_CWORD_CWORD,
2640 /* 15 -115 */ CWORD_CWORD_CWORD_CWORD,
2641 /* 16 -114 */ CWORD_CWORD_CWORD_CWORD,
2642 /* 17 -113 */ CWORD_CWORD_CWORD_CWORD,
2643 /* 18 -112 */ CWORD_CWORD_CWORD_CWORD,
2644 /* 19 -111 */ CWORD_CWORD_CWORD_CWORD,
2645 /* 20 -110 */ CWORD_CWORD_CWORD_CWORD,
2646 /* 21 -109 */ CWORD_CWORD_CWORD_CWORD,
2647 /* 22 -108 */ CWORD_CWORD_CWORD_CWORD,
2648 /* 23 -107 */ CWORD_CWORD_CWORD_CWORD,
2649 /* 24 -106 */ CWORD_CWORD_CWORD_CWORD,
2650 /* 25 -105 */ CWORD_CWORD_CWORD_CWORD,
2651 /* 26 -104 */ CWORD_CWORD_CWORD_CWORD,
2652 /* 27 -103 */ CWORD_CWORD_CWORD_CWORD,
2653 /* 28 -102 */ CWORD_CWORD_CWORD_CWORD,
2654 /* 29 -101 */ CWORD_CWORD_CWORD_CWORD,
2655 /* 30 -100 */ CWORD_CWORD_CWORD_CWORD,
2656 /* 31 -99 */ CWORD_CWORD_CWORD_CWORD,
2657 /* 32 -98 */ CWORD_CWORD_CWORD_CWORD,
2658 /* 33 -97 */ CWORD_CWORD_CWORD_CWORD,
2659 /* 34 -96 */ CWORD_CWORD_CWORD_CWORD,
2660 /* 35 -95 */ CWORD_CWORD_CWORD_CWORD,
2661 /* 36 -94 */ CWORD_CWORD_CWORD_CWORD,
2662 /* 37 -93 */ CWORD_CWORD_CWORD_CWORD,
2663 /* 38 -92 */ CWORD_CWORD_CWORD_CWORD,
2664 /* 39 -91 */ CWORD_CWORD_CWORD_CWORD,
2665 /* 40 -90 */ CWORD_CWORD_CWORD_CWORD,
2666 /* 41 -89 */ CWORD_CWORD_CWORD_CWORD,
2667 /* 42 -88 */ CWORD_CWORD_CWORD_CWORD,
2668 /* 43 -87 */ CWORD_CWORD_CWORD_CWORD,
2669 /* 44 -86 */ CWORD_CWORD_CWORD_CWORD,
2670 /* 45 -85 */ CWORD_CWORD_CWORD_CWORD,
2671 /* 46 -84 */ CWORD_CWORD_CWORD_CWORD,
2672 /* 47 -83 */ CWORD_CWORD_CWORD_CWORD,
2673 /* 48 -82 */ CWORD_CWORD_CWORD_CWORD,
2674 /* 49 -81 */ CWORD_CWORD_CWORD_CWORD,
2675 /* 50 -80 */ CWORD_CWORD_CWORD_CWORD,
2676 /* 51 -79 */ CWORD_CWORD_CWORD_CWORD,
2677 /* 52 -78 */ CWORD_CWORD_CWORD_CWORD,
2678 /* 53 -77 */ CWORD_CWORD_CWORD_CWORD,
2679 /* 54 -76 */ CWORD_CWORD_CWORD_CWORD,
2680 /* 55 -75 */ CWORD_CWORD_CWORD_CWORD,
2681 /* 56 -74 */ CWORD_CWORD_CWORD_CWORD,
2682 /* 57 -73 */ CWORD_CWORD_CWORD_CWORD,
2683 /* 58 -72 */ CWORD_CWORD_CWORD_CWORD,
2684 /* 59 -71 */ CWORD_CWORD_CWORD_CWORD,
2685 /* 60 -70 */ CWORD_CWORD_CWORD_CWORD,
2686 /* 61 -69 */ CWORD_CWORD_CWORD_CWORD,
2687 /* 62 -68 */ CWORD_CWORD_CWORD_CWORD,
2688 /* 63 -67 */ CWORD_CWORD_CWORD_CWORD,
2689 /* 64 -66 */ CWORD_CWORD_CWORD_CWORD,
2690 /* 65 -65 */ CWORD_CWORD_CWORD_CWORD,
2691 /* 66 -64 */ CWORD_CWORD_CWORD_CWORD,
2692 /* 67 -63 */ CWORD_CWORD_CWORD_CWORD,
2693 /* 68 -62 */ CWORD_CWORD_CWORD_CWORD,
2694 /* 69 -61 */ CWORD_CWORD_CWORD_CWORD,
2695 /* 70 -60 */ CWORD_CWORD_CWORD_CWORD,
2696 /* 71 -59 */ CWORD_CWORD_CWORD_CWORD,
2697 /* 72 -58 */ CWORD_CWORD_CWORD_CWORD,
2698 /* 73 -57 */ CWORD_CWORD_CWORD_CWORD,
2699 /* 74 -56 */ CWORD_CWORD_CWORD_CWORD,
2700 /* 75 -55 */ CWORD_CWORD_CWORD_CWORD,
2701 /* 76 -54 */ CWORD_CWORD_CWORD_CWORD,
2702 /* 77 -53 */ CWORD_CWORD_CWORD_CWORD,
2703 /* 78 -52 */ CWORD_CWORD_CWORD_CWORD,
2704 /* 79 -51 */ CWORD_CWORD_CWORD_CWORD,
2705 /* 80 -50 */ CWORD_CWORD_CWORD_CWORD,
2706 /* 81 -49 */ CWORD_CWORD_CWORD_CWORD,
2707 /* 82 -48 */ CWORD_CWORD_CWORD_CWORD,
2708 /* 83 -47 */ CWORD_CWORD_CWORD_CWORD,
2709 /* 84 -46 */ CWORD_CWORD_CWORD_CWORD,
2710 /* 85 -45 */ CWORD_CWORD_CWORD_CWORD,
2711 /* 86 -44 */ CWORD_CWORD_CWORD_CWORD,
2712 /* 87 -43 */ CWORD_CWORD_CWORD_CWORD,
2713 /* 88 -42 */ CWORD_CWORD_CWORD_CWORD,
2714 /* 89 -41 */ CWORD_CWORD_CWORD_CWORD,
2715 /* 90 -40 */ CWORD_CWORD_CWORD_CWORD,
2716 /* 91 -39 */ CWORD_CWORD_CWORD_CWORD,
2717 /* 92 -38 */ CWORD_CWORD_CWORD_CWORD,
2718 /* 93 -37 */ CWORD_CWORD_CWORD_CWORD,
2719 /* 94 -36 */ CWORD_CWORD_CWORD_CWORD,
2720 /* 95 -35 */ CWORD_CWORD_CWORD_CWORD,
2721 /* 96 -34 */ CWORD_CWORD_CWORD_CWORD,
2722 /* 97 -33 */ CWORD_CWORD_CWORD_CWORD,
2723 /* 98 -32 */ CWORD_CWORD_CWORD_CWORD,
2724 /* 99 -31 */ CWORD_CWORD_CWORD_CWORD,
2725 /* 100 -30 */ CWORD_CWORD_CWORD_CWORD,
2726 /* 101 -29 */ CWORD_CWORD_CWORD_CWORD,
2727 /* 102 -28 */ CWORD_CWORD_CWORD_CWORD,
2728 /* 103 -27 */ CWORD_CWORD_CWORD_CWORD,
2729 /* 104 -26 */ CWORD_CWORD_CWORD_CWORD,
2730 /* 105 -25 */ CWORD_CWORD_CWORD_CWORD,
2731 /* 106 -24 */ CWORD_CWORD_CWORD_CWORD,
2732 /* 107 -23 */ CWORD_CWORD_CWORD_CWORD,
2733 /* 108 -22 */ CWORD_CWORD_CWORD_CWORD,
2734 /* 109 -21 */ CWORD_CWORD_CWORD_CWORD,
2735 /* 110 -20 */ CWORD_CWORD_CWORD_CWORD,
2736 /* 111 -19 */ CWORD_CWORD_CWORD_CWORD,
2737 /* 112 -18 */ CWORD_CWORD_CWORD_CWORD,
2738 /* 113 -17 */ CWORD_CWORD_CWORD_CWORD,
2739 /* 114 -16 */ CWORD_CWORD_CWORD_CWORD,
2740 /* 115 -15 */ CWORD_CWORD_CWORD_CWORD,
2741 /* 116 -14 */ CWORD_CWORD_CWORD_CWORD,
2742 /* 117 -13 */ CWORD_CWORD_CWORD_CWORD,
2743 /* 118 -12 */ CWORD_CWORD_CWORD_CWORD,
2744 /* 119 -11 */ CWORD_CWORD_CWORD_CWORD,
2745 /* 120 -10 */ CWORD_CWORD_CWORD_CWORD,
2746 /* 121 -9 */ CWORD_CWORD_CWORD_CWORD,
2747 /* 122 -8 */ CWORD_CWORD_CWORD_CWORD,
2748 /* 123 -7 */ CWORD_CWORD_CWORD_CWORD,
2749 /* 124 -6 */ CWORD_CWORD_CWORD_CWORD,
2750 /* 125 -5 */ CWORD_CWORD_CWORD_CWORD,
2751 /* 126 -4 */ CWORD_CWORD_CWORD_CWORD,
2752 /* 127 -3 */ CWORD_CWORD_CWORD_CWORD,
2753 /* 128 -2 */ CWORD_CWORD_CWORD_CWORD,
2754 /* 129 -1 */ CWORD_CWORD_CWORD_CWORD,
2755 /* 130 0 */ CWORD_CWORD_CWORD_CWORD,
2756 /* 131 1 */ CWORD_CWORD_CWORD_CWORD,
2757 /* 132 2 */ CWORD_CWORD_CWORD_CWORD,
2758 /* 133 3 */ CWORD_CWORD_CWORD_CWORD,
2759 /* 134 4 */ CWORD_CWORD_CWORD_CWORD,
2760 /* 135 5 */ CWORD_CWORD_CWORD_CWORD,
2761 /* 136 6 */ CWORD_CWORD_CWORD_CWORD,
2762 /* 137 7 */ CWORD_CWORD_CWORD_CWORD,
2763 /* 138 8 */ CWORD_CWORD_CWORD_CWORD,
2764 /* 139 9 "\t" */ CSPCL_CWORD_CWORD_CWORD,
2765 /* 140 10 "\n" */ CNL_CNL_CNL_CNL,
2766 /* 141 11 */ CWORD_CWORD_CWORD_CWORD,
2767 /* 142 12 */ CWORD_CWORD_CWORD_CWORD,
2768 /* 143 13 */ CWORD_CWORD_CWORD_CWORD,
2769 /* 144 14 */ CWORD_CWORD_CWORD_CWORD,
2770 /* 145 15 */ CWORD_CWORD_CWORD_CWORD,
2771 /* 146 16 */ CWORD_CWORD_CWORD_CWORD,
2772 /* 147 17 */ CWORD_CWORD_CWORD_CWORD,
2773 /* 148 18 */ CWORD_CWORD_CWORD_CWORD,
2774 /* 149 19 */ CWORD_CWORD_CWORD_CWORD,
2775 /* 150 20 */ CWORD_CWORD_CWORD_CWORD,
2776 /* 151 21 */ CWORD_CWORD_CWORD_CWORD,
2777 /* 152 22 */ CWORD_CWORD_CWORD_CWORD,
2778 /* 153 23 */ CWORD_CWORD_CWORD_CWORD,
2779 /* 154 24 */ CWORD_CWORD_CWORD_CWORD,
2780 /* 155 25 */ CWORD_CWORD_CWORD_CWORD,
2781 /* 156 26 */ CWORD_CWORD_CWORD_CWORD,
2782 /* 157 27 */ CWORD_CWORD_CWORD_CWORD,
2783 /* 158 28 */ CWORD_CWORD_CWORD_CWORD,
2784 /* 159 29 */ CWORD_CWORD_CWORD_CWORD,
2785 /* 160 30 */ CWORD_CWORD_CWORD_CWORD,
2786 /* 161 31 */ CWORD_CWORD_CWORD_CWORD,
2787 /* 162 32 " " */ CSPCL_CWORD_CWORD_CWORD,
2788 /* 163 33 "!" */ CWORD_CCTL_CCTL_CWORD,
2789 /* 164 34 """ */ CDQUOTE_CENDQUOTE_CWORD_CWORD,
2790 /* 165 35 "#" */ CWORD_CWORD_CWORD_CWORD,
2791 /* 166 36 "$" */ CVAR_CVAR_CWORD_CVAR,
2792 /* 167 37 "%" */ CWORD_CWORD_CWORD_CWORD,
2793 /* 168 38 "&" */ CSPCL_CWORD_CWORD_CWORD,
2794 /* 169 39 "'" */ CSQUOTE_CWORD_CENDQUOTE_CWORD,
2795 /* 170 40 "(" */ CSPCL_CWORD_CWORD_CLP,
2796 /* 171 41 ")" */ CSPCL_CWORD_CWORD_CRP,
2797 /* 172 42 "*" */ CWORD_CCTL_CCTL_CWORD,
2798 /* 173 43 "+" */ CWORD_CWORD_CWORD_CWORD,
2799 /* 174 44 "," */ CWORD_CWORD_CWORD_CWORD,
2800 /* 175 45 "-" */ CWORD_CCTL_CCTL_CWORD,
2801 /* 176 46 "." */ CWORD_CWORD_CWORD_CWORD,
2802 /* 177 47 "/" */ CWORD_CCTL_CCTL_CWORD,
2803 /* 178 48 "0" */ CWORD_CWORD_CWORD_CWORD,
2804 /* 179 49 "1" */ CWORD_CWORD_CWORD_CWORD,
2805 /* 180 50 "2" */ CWORD_CWORD_CWORD_CWORD,
2806 /* 181 51 "3" */ CWORD_CWORD_CWORD_CWORD,
2807 /* 182 52 "4" */ CWORD_CWORD_CWORD_CWORD,
2808 /* 183 53 "5" */ CWORD_CWORD_CWORD_CWORD,
2809 /* 184 54 "6" */ CWORD_CWORD_CWORD_CWORD,
2810 /* 185 55 "7" */ CWORD_CWORD_CWORD_CWORD,
2811 /* 186 56 "8" */ CWORD_CWORD_CWORD_CWORD,
2812 /* 187 57 "9" */ CWORD_CWORD_CWORD_CWORD,
2813 /* 188 58 ":" */ CWORD_CCTL_CCTL_CWORD,
2814 /* 189 59 ";" */ CSPCL_CWORD_CWORD_CWORD,
2815 /* 190 60 "<" */ CSPCL_CWORD_CWORD_CWORD,
2816 /* 191 61 "=" */ CWORD_CCTL_CCTL_CWORD,
2817 /* 192 62 ">" */ CSPCL_CWORD_CWORD_CWORD,
2818 /* 193 63 "?" */ CWORD_CCTL_CCTL_CWORD,
2819 /* 194 64 "@" */ CWORD_CWORD_CWORD_CWORD,
2820 /* 195 65 "A" */ CWORD_CWORD_CWORD_CWORD,
2821 /* 196 66 "B" */ CWORD_CWORD_CWORD_CWORD,
2822 /* 197 67 "C" */ CWORD_CWORD_CWORD_CWORD,
2823 /* 198 68 "D" */ CWORD_CWORD_CWORD_CWORD,
2824 /* 199 69 "E" */ CWORD_CWORD_CWORD_CWORD,
2825 /* 200 70 "F" */ CWORD_CWORD_CWORD_CWORD,
2826 /* 201 71 "G" */ CWORD_CWORD_CWORD_CWORD,
2827 /* 202 72 "H" */ CWORD_CWORD_CWORD_CWORD,
2828 /* 203 73 "I" */ CWORD_CWORD_CWORD_CWORD,
2829 /* 204 74 "J" */ CWORD_CWORD_CWORD_CWORD,
2830 /* 205 75 "K" */ CWORD_CWORD_CWORD_CWORD,
2831 /* 206 76 "L" */ CWORD_CWORD_CWORD_CWORD,
2832 /* 207 77 "M" */ CWORD_CWORD_CWORD_CWORD,
2833 /* 208 78 "N" */ CWORD_CWORD_CWORD_CWORD,
2834 /* 209 79 "O" */ CWORD_CWORD_CWORD_CWORD,
2835 /* 210 80 "P" */ CWORD_CWORD_CWORD_CWORD,
2836 /* 211 81 "Q" */ CWORD_CWORD_CWORD_CWORD,
2837 /* 212 82 "R" */ CWORD_CWORD_CWORD_CWORD,
2838 /* 213 83 "S" */ CWORD_CWORD_CWORD_CWORD,
2839 /* 214 84 "T" */ CWORD_CWORD_CWORD_CWORD,
2840 /* 215 85 "U" */ CWORD_CWORD_CWORD_CWORD,
2841 /* 216 86 "V" */ CWORD_CWORD_CWORD_CWORD,
2842 /* 217 87 "W" */ CWORD_CWORD_CWORD_CWORD,
2843 /* 218 88 "X" */ CWORD_CWORD_CWORD_CWORD,
2844 /* 219 89 "Y" */ CWORD_CWORD_CWORD_CWORD,
2845 /* 220 90 "Z" */ CWORD_CWORD_CWORD_CWORD,
2846 /* 221 91 "[" */ CWORD_CCTL_CCTL_CWORD,
2847 /* 222 92 "\" */ CBACK_CBACK_CCTL_CBACK,
2848 /* 223 93 "]" */ CWORD_CCTL_CCTL_CWORD,
2849 /* 224 94 "^" */ CWORD_CWORD_CWORD_CWORD,
2850 /* 225 95 "_" */ CWORD_CWORD_CWORD_CWORD,
2851 /* 226 96 "`" */ CBQUOTE_CBQUOTE_CWORD_CBQUOTE,
2852 /* 227 97 "a" */ CWORD_CWORD_CWORD_CWORD,
2853 /* 228 98 "b" */ CWORD_CWORD_CWORD_CWORD,
2854 /* 229 99 "c" */ CWORD_CWORD_CWORD_CWORD,
2855 /* 230 100 "d" */ CWORD_CWORD_CWORD_CWORD,
2856 /* 231 101 "e" */ CWORD_CWORD_CWORD_CWORD,
2857 /* 232 102 "f" */ CWORD_CWORD_CWORD_CWORD,
2858 /* 233 103 "g" */ CWORD_CWORD_CWORD_CWORD,
2859 /* 234 104 "h" */ CWORD_CWORD_CWORD_CWORD,
2860 /* 235 105 "i" */ CWORD_CWORD_CWORD_CWORD,
2861 /* 236 106 "j" */ CWORD_CWORD_CWORD_CWORD,
2862 /* 237 107 "k" */ CWORD_CWORD_CWORD_CWORD,
2863 /* 238 108 "l" */ CWORD_CWORD_CWORD_CWORD,
2864 /* 239 109 "m" */ CWORD_CWORD_CWORD_CWORD,
2865 /* 240 110 "n" */ CWORD_CWORD_CWORD_CWORD,
2866 /* 241 111 "o" */ CWORD_CWORD_CWORD_CWORD,
2867 /* 242 112 "p" */ CWORD_CWORD_CWORD_CWORD,
2868 /* 243 113 "q" */ CWORD_CWORD_CWORD_CWORD,
2869 /* 244 114 "r" */ CWORD_CWORD_CWORD_CWORD,
2870 /* 245 115 "s" */ CWORD_CWORD_CWORD_CWORD,
2871 /* 246 116 "t" */ CWORD_CWORD_CWORD_CWORD,
2872 /* 247 117 "u" */ CWORD_CWORD_CWORD_CWORD,
2873 /* 248 118 "v" */ CWORD_CWORD_CWORD_CWORD,
2874 /* 249 119 "w" */ CWORD_CWORD_CWORD_CWORD,
2875 /* 250 120 "x" */ CWORD_CWORD_CWORD_CWORD,
2876 /* 251 121 "y" */ CWORD_CWORD_CWORD_CWORD,
2877 /* 252 122 "z" */ CWORD_CWORD_CWORD_CWORD,
2878 /* 253 123 "{" */ CWORD_CWORD_CWORD_CWORD,
2879 /* 254 124 "|" */ CSPCL_CWORD_CWORD_CWORD,
2880 /* 255 125 "}" */ CENDVAR_CENDVAR_CWORD_CENDVAR,
2881 /* 256 126 "~" */ CWORD_CCTL_CCTL_CWORD,
2882 /* 257 127 */ CWORD_CWORD_CWORD_CWORD,
2885 #define SIT(c, syntax) (S_I_T[(int)syntax_index_table[((int)c)+SYNBASE]][syntax])
2887 #endif /* USE_SIT_FUNCTION */
2890 /* ============ Alias handling */
2892 #if ENABLE_ASH_ALIAS
2894 #define ALIASINUSE 1
2906 static struct alias *atab[ATABSIZE];
2908 static struct alias **
2909 __lookupalias(const char *name) {
2910 unsigned int hashval;
2917 ch = (unsigned char)*p;
2921 ch = (unsigned char)*++p;
2923 app = &atab[hashval % ATABSIZE];
2925 for (; *app; app = &(*app)->next) {
2926 if (strcmp(name, (*app)->name) == 0) {
2934 static struct alias *
2935 lookupalias(const char *name, int check)
2937 struct alias *ap = *__lookupalias(name);
2939 if (check && ap && (ap->flag & ALIASINUSE))
2944 static struct alias *
2945 freealias(struct alias *ap)
2949 if (ap->flag & ALIASINUSE) {
2950 ap->flag |= ALIASDEAD;
2962 setalias(const char *name, const char *val)
2964 struct alias *ap, **app;
2966 app = __lookupalias(name);
2970 if (!(ap->flag & ALIASINUSE)) {
2973 ap->val = ckstrdup(val);
2974 ap->flag &= ~ALIASDEAD;
2977 ap = ckmalloc(sizeof(struct alias));
2978 ap->name = ckstrdup(name);
2979 ap->val = ckstrdup(val);
2988 unalias(const char *name)
2992 app = __lookupalias(name);
2996 *app = freealias(*app);
3007 struct alias *ap, **app;
3011 for (i = 0; i < ATABSIZE; i++) {
3013 for (ap = *app; ap; ap = *app) {
3014 *app = freealias(*app);
3024 printalias(const struct alias *ap)
3026 out1fmt("%s=%s\n", ap->name, single_quote(ap->val));
3030 * TODO - sort output
3033 aliascmd(int argc, char **argv)
3042 for (i = 0; i < ATABSIZE; i++)
3043 for (ap = atab[i]; ap; ap = ap->next) {
3048 while ((n = *++argv) != NULL) {
3049 v = strchr(n+1, '=');
3050 if (v == NULL) { /* n+1: funny ksh stuff */
3051 ap = *__lookupalias(n);
3053 fprintf(stderr, "%s: %s not found\n", "alias", n);
3067 unaliascmd(int argc, char **argv)
3071 while ((i = nextopt("a")) != '\0') {
3077 for (i = 0; *argptr; argptr++) {
3078 if (unalias(*argptr)) {
3079 fprintf(stderr, "%s: %s not found\n", "unalias", *argptr);
3087 #endif /* ASH_ALIAS */
3090 /* ============ jobs.c */
3092 /* Mode argument to forkshell. Don't change FORK_FG or FORK_BG. */
3095 #define FORK_NOJOB 2
3097 /* mode flags for showjob(s) */
3098 #define SHOW_PGID 0x01 /* only show pgid - for jobs -p */
3099 #define SHOW_PID 0x04 /* include process pid */
3100 #define SHOW_CHANGED 0x08 /* only jobs whose state has changed */
3103 * A job structure contains information about a job. A job is either a
3104 * single process or a set of processes contained in a pipeline. In the
3105 * latter case, pidlist will be non-NULL, and will point to a -1 terminated
3110 pid_t pid; /* process id */
3111 int status; /* last process status from wait() */
3112 char *cmd; /* text of command being run */
3116 struct procstat ps0; /* status of process */
3117 struct procstat *ps; /* status or processes when more than one */
3119 int stopstatus; /* status of a stopped job */
3122 nprocs: 16, /* number of processes */
3124 #define JOBRUNNING 0 /* at least one proc running */
3125 #define JOBSTOPPED 1 /* all procs are stopped */
3126 #define JOBDONE 2 /* all procs are completed */
3128 sigint: 1, /* job was killed by SIGINT */
3129 jobctl: 1, /* job running under job control */
3131 waited: 1, /* true if this entry has been waited for */
3132 used: 1, /* true if this entry is in used */
3133 changed: 1; /* true if status has changed */
3134 struct job *prev_job; /* previous job */
3137 static pid_t backgndpid; /* pid of last background process */
3138 static int job_warning; /* user was warned about stopped jobs */
3140 static int jobctl; /* true if doing job control */
3143 static struct job *makejob(union node *, int);
3144 static int forkshell(struct job *, union node *, int);
3145 static int waitforjob(struct job *);
3148 #define setjobctl(on) /* do nothing */
3150 static void setjobctl(int);
3151 static void showjobs(FILE *, int);
3155 * Set the signal handler for the specified signal. The routine figures
3156 * out what it should be set to.
3159 setsignal(int signo)
3163 struct sigaction act;
3168 else if (*t != '\0')
3172 if (rootshell && action == S_DFL) {
3175 if (iflag || minusc || sflag == 0)
3198 t = &sigmode[signo - 1];
3202 * current setting unknown
3204 if (sigaction(signo, 0, &act) == -1) {
3206 * Pretend it worked; maybe we should give a warning
3207 * here, but other shells don't. We don't alter
3208 * sigmode, so that we retry every time.
3212 if (act.sa_handler == SIG_IGN) {
3214 && (signo == SIGTSTP || signo == SIGTTIN || signo == SIGTTOU)
3216 tsig = S_IGN; /* don't hard ignore these */
3220 tsig = S_RESET; /* force to be set */
3223 if (tsig == S_HARD_IGN || tsig == action)
3227 act.sa_handler = onsig;
3230 act.sa_handler = SIG_IGN;
3233 act.sa_handler = SIG_DFL;
3237 sigfillset(&act.sa_mask);
3238 sigaction(signo, &act, 0);
3241 /* mode flags for set_curjob */
3242 #define CUR_DELETE 2
3243 #define CUR_RUNNING 1
3244 #define CUR_STOPPED 0
3246 /* mode flags for dowait */
3247 #define DOWAIT_NORMAL 0
3248 #define DOWAIT_BLOCK 1
3251 /* pgrp of shell on invocation */
3252 static int initialpgrp;
3253 static int ttyfd = -1;
3256 static struct job *jobtab;
3258 static unsigned njobs;
3260 static struct job *curjob;
3261 /* number of presumed living untracked jobs */
3265 set_curjob(struct job *jp, unsigned mode)
3268 struct job **jpp, **curp;
3270 /* first remove from list */
3271 jpp = curp = &curjob;
3276 jpp = &jp1->prev_job;
3278 *jpp = jp1->prev_job;
3280 /* Then re-insert in correct position */
3288 /* job being deleted */
3291 /* newly created job or backgrounded job,
3292 put after all stopped jobs. */
3296 if (!jp1 || jp1->state != JOBSTOPPED)
3299 jpp = &jp1->prev_job;
3305 /* newly stopped job - becomes curjob */
3306 jp->prev_job = *jpp;
3314 jobno(const struct job *jp)
3316 return jp - jobtab + 1;
3321 * Convert a job name to a job structure.
3324 getjob(const char *name, int getctl)
3328 const char *err_msg = "No such job: %s";
3332 char *(*match)(const char *, const char *);
3347 if (c == '+' || c == '%') {
3349 err_msg = "No current job";
3355 err_msg = "No previous job";
3366 jp = jobtab + num - 1;
3383 if (match(jp->ps[0].cmd, p)) {
3387 err_msg = "%s: ambiguous";
3394 err_msg = "job %s not created under job control";
3395 if (getctl && jp->jobctl == 0)
3400 ash_msg_and_raise_error(err_msg, name);
3404 * Mark a job structure as unused.
3407 freejob(struct job *jp)
3409 struct procstat *ps;
3413 for (i = jp->nprocs, ps = jp->ps; --i >= 0; ps++) {
3414 if (ps->cmd != nullstr)
3417 if (jp->ps != &jp->ps0)
3420 set_curjob(jp, CUR_DELETE);
3426 xtcsetpgrp(int fd, pid_t pgrp)
3428 if (tcsetpgrp(fd, pgrp))
3429 ash_msg_and_raise_error("Cannot set tty process group (%m)");
3433 * Turn job control on and off.
3435 * Note: This code assumes that the third arg to ioctl is a character
3436 * pointer, which is true on Berkeley systems but not System V. Since
3437 * System V doesn't have job control yet, this isn't a problem now.
3439 * Called with interrupts off.
3447 if (on == jobctl || rootshell == 0)
3451 ofd = fd = open(_PATH_TTY, O_RDWR);
3453 /* BTW, bash will try to open(ttyname(0)) if open("/dev/tty") fails.
3454 * That sometimes helps to acquire controlling tty.
3455 * Obviously, a workaround for bugs when someone
3456 * failed to provide a controlling tty to bash! :) */
3458 while (!isatty(fd) && --fd >= 0)
3461 fd = fcntl(fd, F_DUPFD, 10);
3465 fcntl(fd, F_SETFD, FD_CLOEXEC);
3466 do { /* while we are in the background */
3467 pgrp = tcgetpgrp(fd);
3470 ash_msg("can't access tty; job control turned off");
3474 if (pgrp == getpgrp())
3485 xtcsetpgrp(fd, pgrp);
3487 /* turning job control off */
3490 xtcsetpgrp(fd, pgrp);
3504 killcmd(int argc, char **argv)
3514 ash_msg_and_raise_error(
3515 "Usage: kill [-s sigspec | -signum | -sigspec] [pid | job]... or\n"
3516 "kill -l [exitstatus]"
3520 if (**++argv == '-') {
3521 signo = get_signum(*argv + 1);
3525 while ((c = nextopt("ls:")) != '\0') {
3535 signo = get_signum(optionarg);
3537 ash_msg_and_raise_error(
3538 "invalid signal number or name: %s",
3550 if (!list && signo < 0)
3553 if ((signo < 0 || !*argv) ^ list) {
3561 for (i = 1; i < NSIG; i++) {
3562 name = get_signame(i);
3564 out1fmt(snlfmt, name);
3568 name = get_signame(signo);
3569 if (!isdigit(*name))
3570 ash_msg_and_raise_error("invalid signal number or exit status: %s", *argptr);
3571 out1fmt(snlfmt, name);
3577 if (**argv == '%') {
3578 jp = getjob(*argv, 0);
3579 pid = -jp->ps[0].pid;
3581 pid = **argv == '-' ?
3582 -number(*argv + 1) : number(*argv);
3584 if (kill(pid, signo) != 0) {
3585 ash_msg("(%d) - %m", pid);
3594 showpipe(struct job *jp, FILE *out)
3596 struct procstat *sp;
3597 struct procstat *spend;
3599 spend = jp->ps + jp->nprocs;
3600 for (sp = jp->ps + 1; sp < spend; sp++)
3601 fprintf(out, " | %s", sp->cmd);
3602 outcslow('\n', out);
3603 flush_stdout_stderr();
3608 restartjob(struct job *jp, int mode)
3610 struct procstat *ps;
3616 if (jp->state == JOBDONE)
3618 jp->state = JOBRUNNING;
3620 if (mode == FORK_FG)
3621 xtcsetpgrp(ttyfd, pgid);
3622 killpg(pgid, SIGCONT);
3626 if (WIFSTOPPED(ps->status)) {
3629 } while (ps++, --i);
3631 status = (mode == FORK_FG) ? waitforjob(jp) : 0;
3637 fg_bgcmd(int argc, char **argv)
3644 mode = (**argv == 'f') ? FORK_FG : FORK_BG;
3649 jp = getjob(*argv, 1);
3650 if (mode == FORK_BG) {
3651 set_curjob(jp, CUR_RUNNING);
3652 fprintf(out, "[%d] ", jobno(jp));
3654 outstr(jp->ps->cmd, out);
3656 retval = restartjob(jp, mode);
3657 } while (*argv && *++argv);
3663 sprint_status(char *s, int status, int sigonly)
3669 if (!WIFEXITED(status)) {
3671 if (WIFSTOPPED(status))
3672 st = WSTOPSIG(status);
3675 st = WTERMSIG(status);
3677 if (st == SIGINT || st == SIGPIPE)
3680 if (WIFSTOPPED(status))
3685 col = fmtstr(s, 32, strsignal(st));
3686 if (WCOREDUMP(status)) {
3687 col += fmtstr(s + col, 16, " (core dumped)");
3689 } else if (!sigonly) {
3690 st = WEXITSTATUS(status);
3692 col = fmtstr(s, 16, "Done(%d)", st);
3694 col = fmtstr(s, 16, "Done");
3701 * Do a wait system call. If job control is compiled in, we accept
3702 * stopped processes. If block is zero, we return a value of zero
3703 * rather than blocking.
3705 * System V doesn't have a non-blocking wait system call. It does
3706 * have a SIGCLD signal that is sent to a process when one of it's
3707 * children dies. The obvious way to use SIGCLD would be to install
3708 * a handler for SIGCLD which simply bumped a counter when a SIGCLD
3709 * was received, and have waitproc bump another counter when it got
3710 * the status of a process. Waitproc would then know that a wait
3711 * system call would not block if the two counters were different.
3712 * This approach doesn't work because if a process has children that
3713 * have not been waited for, System V will send it a SIGCLD when it
3714 * installs a signal handler for SIGCLD. What this means is that when
3715 * a child exits, the shell will be sent SIGCLD signals continuously
3716 * until is runs out of stack space, unless it does a wait call before
3717 * restoring the signal handler. The code below takes advantage of
3718 * this (mis)feature by installing a signal handler for SIGCLD and
3719 * then checking to see whether it was called. If there are any
3720 * children to be waited for, it will be.
3722 * If neither SYSV nor BSD is defined, we don't implement nonblocking
3723 * waits at all. In this case, the user will not be informed when
3724 * a background process until the next time she runs a real program
3725 * (as opposed to running a builtin command or just typing return),
3726 * and the jobs command may give out of date information.
3729 waitproc(int block, int *status)
3739 return wait3(status, flags, (struct rusage *)NULL);
3743 * Wait for a process to terminate.
3746 dowait(int block, struct job *job)
3751 struct job *thisjob;
3754 TRACE(("dowait(%d) called\n", block));
3755 pid = waitproc(block, &status);
3756 TRACE(("wait returns pid %d, status=%d\n", pid, status));
3761 for (jp = curjob; jp; jp = jp->prev_job) {
3762 struct procstat *sp;
3763 struct procstat *spend;
3764 if (jp->state == JOBDONE)
3767 spend = jp->ps + jp->nprocs;
3770 if (sp->pid == pid) {
3771 TRACE(("Job %d: changing status of proc %d "
3772 "from 0x%x to 0x%x\n",
3773 jobno(jp), pid, sp->status, status));
3774 sp->status = status;
3777 if (sp->status == -1)
3780 if (state == JOBRUNNING)
3782 if (WIFSTOPPED(sp->status)) {
3783 jp->stopstatus = sp->status;
3787 } while (++sp < spend);
3792 if (!WIFSTOPPED(status))
3799 if (state != JOBRUNNING) {
3800 thisjob->changed = 1;
3802 if (thisjob->state != state) {
3803 TRACE(("Job %d: changing state from %d to %d\n",
3804 jobno(thisjob), thisjob->state, state));
3805 thisjob->state = state;
3807 if (state == JOBSTOPPED) {
3808 set_curjob(thisjob, CUR_STOPPED);
3817 if (thisjob && thisjob == job) {
3821 len = sprint_status(s, status, 1);
3833 showjob(FILE *out, struct job *jp, int mode)
3835 struct procstat *ps;
3836 struct procstat *psend;
3843 if (mode & SHOW_PGID) {
3844 /* just output process (group) id of pipeline */
3845 fprintf(out, "%d\n", ps->pid);
3849 col = fmtstr(s, 16, "[%d] ", jobno(jp));
3854 else if (curjob && jp == curjob->prev_job)
3857 if (mode & SHOW_PID)
3858 col += fmtstr(s + col, 16, "%d ", ps->pid);
3860 psend = ps + jp->nprocs;
3862 if (jp->state == JOBRUNNING) {
3863 strcpy(s + col, "Running");
3864 col += sizeof("Running") - 1;
3866 int status = psend[-1].status;
3867 if (jp->state == JOBSTOPPED)
3868 status = jp->stopstatus;
3869 col += sprint_status(s + col, status, 0);
3875 /* for each process */
3876 col = fmtstr(s, 48, " |\n%*c%d ", indent, ' ', ps->pid) - 3;
3878 fprintf(out, "%s%*c%s",
3879 s, 33 - col >= 0 ? 33 - col : 0, ' ', ps->cmd
3881 if (!(mode & SHOW_PID)) {
3885 if (++ps == psend) {
3886 outcslow('\n', out);
3893 if (jp->state == JOBDONE) {
3894 TRACE(("showjob: freeing job %d\n", jobno(jp)));
3900 jobscmd(int argc, char **argv)
3906 while ((m = nextopt("lp"))) {
3917 showjob(out, getjob(*argv,0), mode);
3920 showjobs(out, mode);
3926 * Print a list of jobs. If "change" is nonzero, only print jobs whose
3927 * statuses have changed since the last call to showjobs.
3930 showjobs(FILE *out, int mode)
3934 TRACE(("showjobs(%x) called\n", mode));
3936 /* If not even one one job changed, there is nothing to do */
3937 while (dowait(DOWAIT_NORMAL, NULL) > 0)
3940 for (jp = curjob; jp; jp = jp->prev_job) {
3941 if (!(mode & SHOW_CHANGED) || jp->changed)
3942 showjob(out, jp, mode);
3948 getstatus(struct job *job)
3953 status = job->ps[job->nprocs - 1].status;
3954 retval = WEXITSTATUS(status);
3955 if (!WIFEXITED(status)) {
3957 retval = WSTOPSIG(status);
3958 if (!WIFSTOPPED(status))
3961 /* XXX: limits number of signals */
3962 retval = WTERMSIG(status);
3964 if (retval == SIGINT)
3970 TRACE(("getstatus: job %d, nproc %d, status %x, retval %x\n",
3971 jobno(job), job->nprocs, status, retval));
3976 waitcmd(int argc, char **argv)
3989 /* wait for all jobs */
3994 /* no running procs */
3997 if (jp->state == JOBRUNNING)
4002 dowait(DOWAIT_BLOCK, 0);
4008 if (**argv != '%') {
4009 pid_t pid = number(*argv);
4013 if (job->ps[job->nprocs - 1].pid == pid)
4015 job = job->prev_job;
4021 job = getjob(*argv, 0);
4022 /* loop until process terminated or stopped */
4023 while (job->state == JOBRUNNING)
4024 dowait(DOWAIT_BLOCK, 0);
4026 retval = getstatus(job);
4040 struct job *jp, *jq;
4042 len = njobs * sizeof(*jp);
4044 jp = ckrealloc(jq, len + 4 * sizeof(*jp));
4046 offset = (char *)jp - (char *)jq;
4048 /* Relocate pointers */
4051 jq = (struct job *)((char *)jq + l);
4055 #define joff(p) ((struct job *)((char *)(p) + l))
4056 #define jmove(p) (p) = (void *)((char *)(p) + offset)
4057 if (joff(jp)->ps == &jq->ps0)
4058 jmove(joff(jp)->ps);
4059 if (joff(jp)->prev_job)
4060 jmove(joff(jp)->prev_job);
4070 jp = (struct job *)((char *)jp + len);
4074 } while (--jq >= jp);
4079 * Return a new job structure.
4080 * Called with interrupts off.
4083 makejob(union node *node, int nprocs)
4088 for (i = njobs, jp = jobtab; ; jp++) {
4095 if (jp->state != JOBDONE || !jp->waited)
4104 memset(jp, 0, sizeof(*jp));
4109 jp->prev_job = curjob;
4114 jp->ps = ckmalloc(nprocs * sizeof(struct procstat));
4116 TRACE(("makejob(0x%lx, %d) returns %%%d\n", (long)node, nprocs,
4123 * Return a string identifying a command (to be printed by the
4126 static char *cmdnextc;
4129 cmdputs(const char *s)
4131 const char *p, *str;
4132 char c, cc[2] = " ";
4136 static const char vstype[VSTYPE + 1][4] = {
4137 "", "}", "-", "+", "?", "=",
4138 "%", "%%", "#", "##"
4141 nextc = makestrspace((strlen(s) + 1) * 8, cmdnextc);
4143 while ((c = *p++) != 0) {
4151 if ((subtype & VSTYPE) == VSLENGTH)
4155 if (!(subtype & VSQUOTE) == !(quoted & 1))
4161 str = "\"}" + !(quoted & 1);
4168 case CTLBACKQ+CTLQUOTE:
4171 #if ENABLE_ASH_MATH_SUPPORT
4186 if ((subtype & VSTYPE) != VSNORMAL)
4188 str = vstype[subtype & VSTYPE];
4189 if (subtype & VSNUL)
4198 /* These can only happen inside quotes */
4211 while ((c = *str++)) {
4216 USTPUTC('"', nextc);
4222 /* cmdtxt() and cmdlist() call each other */
4223 static void cmdtxt(union node *n);
4226 cmdlist(union node *np, int sep)
4228 for (; np; np = np->narg.next) {
4232 if (sep && np->narg.next)
4238 cmdtxt(union node *n)
4241 struct nodelist *lp;
4253 lp = n->npipe.cmdlist;
4271 cmdtxt(n->nbinary.ch1);
4287 cmdtxt(n->nif.test);
4290 if (n->nif.elsepart) {
4293 n = n->nif.elsepart;
4309 cmdtxt(n->nbinary.ch1);
4319 cmdputs(n->nfor.var);
4321 cmdlist(n->nfor.args, 1);
4326 cmdputs(n->narg.text);
4330 cmdlist(n->ncmd.args, 1);
4331 cmdlist(n->ncmd.redirect, 0);
4344 cmdputs(n->ncase.expr->narg.text);
4346 for (np = n->ncase.cases; np; np = np->nclist.next) {
4347 cmdtxt(np->nclist.pattern);
4349 cmdtxt(np->nclist.body);
4375 s[0] = n->nfile.fd + '0';
4379 if (n->type == NTOFD || n->type == NFROMFD) {
4380 s[0] = n->ndup.dupfd + '0';
4390 commandtext(union node *n)
4394 STARTSTACKSTR(cmdnextc);
4396 name = stackblock();
4397 TRACE(("commandtext: name %p, end %p\n\t\"%s\"\n",
4398 name, cmdnextc, cmdnextc));
4399 return ckstrdup(name);
4404 * Fork off a subshell. If we are doing job control, give the subshell its
4405 * own process group. Jp is a job structure that the job is to be added to.
4406 * N is the command that will be evaluated by the child. Both jp and n may
4407 * be NULL. The mode parameter can be one of the following:
4408 * FORK_FG - Fork off a foreground process.
4409 * FORK_BG - Fork off a background process.
4410 * FORK_NOJOB - Like FORK_FG, but don't give the process its own
4411 * process group even if job control is on.
4413 * When job control is turned off, background processes have their standard
4414 * input redirected to /dev/null (except for the second and later processes
4417 * Called with interrupts off.
4420 * Clear traps on a fork.
4427 for (tp = trap; tp < &trap[NSIG]; tp++) {
4428 if (*tp && **tp) { /* trap not NULL or SIG_IGN */
4433 setsignal(tp - trap);
4438 /* lives far away from here, needed for forkchild */
4439 static void closescript(void);
4441 forkchild(struct job *jp, union node *n, int mode)
4445 TRACE(("Child shell %d\n", getpid()));
4452 /* do job control only in root shell */
4454 if (mode != FORK_NOJOB && jp->jobctl && !oldlvl) {
4457 if (jp->nprocs == 0)
4460 pgrp = jp->ps[0].pid;
4461 /* This can fail because we are doing it in the parent also */
4462 (void)setpgid(0, pgrp);
4463 if (mode == FORK_FG)
4464 xtcsetpgrp(ttyfd, pgrp);
4469 if (mode == FORK_BG) {
4472 if (jp->nprocs == 0) {
4474 if (open(bb_dev_null, O_RDONLY) != 0)
4475 ash_msg_and_raise_error("Can't open %s", bb_dev_null);
4478 if (!oldlvl && iflag) {
4483 for (jp = curjob; jp; jp = jp->prev_job)
4489 forkparent(struct job *jp, union node *n, int mode, pid_t pid)
4491 TRACE(("In parent shell: child = %d\n", pid));
4493 while (jobless && dowait(DOWAIT_NORMAL, 0) > 0);
4498 if (mode != FORK_NOJOB && jp->jobctl) {
4501 if (jp->nprocs == 0)
4504 pgrp = jp->ps[0].pid;
4505 /* This can fail because we are doing it in the child also */
4509 if (mode == FORK_BG) {
4510 backgndpid = pid; /* set $! */
4511 set_curjob(jp, CUR_RUNNING);
4514 struct procstat *ps = &jp->ps[jp->nprocs++];
4520 ps->cmd = commandtext(n);
4526 forkshell(struct job *jp, union node *n, int mode)
4530 TRACE(("forkshell(%%%d, %p, %d) called\n", jobno(jp), n, mode));
4533 TRACE(("Fork failed, errno=%d", errno));
4536 ash_msg_and_raise_error("Cannot fork");
4539 forkchild(jp, n, mode);
4541 forkparent(jp, n, mode, pid);
4546 * Wait for job to finish.
4548 * Under job control we have the problem that while a child process is
4549 * running interrupts generated by the user are sent to the child but not
4550 * to the shell. This means that an infinite loop started by an inter-
4551 * active user may be hard to kill. With job control turned off, an
4552 * interactive user may place an interactive program inside a loop. If
4553 * the interactive program catches interrupts, the user doesn't want
4554 * these interrupts to also abort the loop. The approach we take here
4555 * is to have the shell ignore interrupt signals while waiting for a
4556 * foreground process to terminate, and then send itself an interrupt
4557 * signal if the child process was terminated by an interrupt signal.
4558 * Unfortunately, some programs want to do a bit of cleanup and then
4559 * exit on interrupt; unless these processes terminate themselves by
4560 * sending a signal to themselves (instead of calling exit) they will
4561 * confuse this approach.
4563 * Called with interrupts off.
4566 waitforjob(struct job *jp)
4570 TRACE(("waitforjob(%%%d) called\n", jobno(jp)));
4571 while (jp->state == JOBRUNNING) {
4572 dowait(DOWAIT_BLOCK, jp);
4577 xtcsetpgrp(ttyfd, rootpid);
4579 * This is truly gross.
4580 * If we're doing job control, then we did a TIOCSPGRP which
4581 * caused us (the shell) to no longer be in the controlling
4582 * session -- so we wouldn't have seen any ^C/SIGINT. So, we
4583 * intuit from the subprocess exit status whether a SIGINT
4584 * occurred, and if so interrupt ourselves. Yuck. - mycroft
4589 if (jp->state == JOBDONE)
4596 * return 1 if there are stopped jobs, otherwise 0
4608 if (jp && jp->state == JOBSTOPPED) {
4609 out2str("You have stopped jobs.\n");
4618 /* ============ redir.c
4620 * Code for dealing with input/output redirection.
4623 #define EMPTY -2 /* marks an unused slot in redirtab */
4625 # define PIPESIZE 4096 /* amount of buffering in a pipe */
4627 # define PIPESIZE PIPE_BUF
4631 * Open a file in noclobber mode.
4632 * The code was copied from bash.
4635 noclobberopen(const char *fname)
4638 struct stat finfo, finfo2;
4641 * If the file exists and is a regular file, return an error
4644 r = stat(fname, &finfo);
4645 if (r == 0 && S_ISREG(finfo.st_mode)) {
4651 * If the file was not present (r != 0), make sure we open it
4652 * exclusively so that if it is created before we open it, our open
4653 * will fail. Make sure that we do not truncate an existing file.
4654 * Note that we don't turn on O_EXCL unless the stat failed -- if the
4655 * file was not a regular file, we leave O_EXCL off.
4658 return open(fname, O_WRONLY|O_CREAT|O_EXCL, 0666);
4659 fd = open(fname, O_WRONLY|O_CREAT, 0666);
4661 /* If the open failed, return the file descriptor right away. */
4666 * OK, the open succeeded, but the file may have been changed from a
4667 * non-regular file to a regular file between the stat and the open.
4668 * We are assuming that the O_EXCL open handles the case where FILENAME
4669 * did not exist and is symlinked to an existing file between the stat
4674 * If we can open it and fstat the file descriptor, and neither check
4675 * revealed that it was a regular file, and the file has not been
4676 * replaced, return the file descriptor.
4678 if (fstat(fd, &finfo2) == 0 && !S_ISREG(finfo2.st_mode)
4679 && finfo.st_dev == finfo2.st_dev && finfo.st_ino == finfo2.st_ino)
4682 /* The file has been replaced. badness. */
4689 * Handle here documents. Normally we fork off a process to write the
4690 * data to a pipe. If the document is short, we can stuff the data in
4691 * the pipe without forking.
4693 /* openhere needs this forward reference */
4694 static void expandhere(union node *arg, int fd);
4696 openhere(union node *redir)
4702 ash_msg_and_raise_error("Pipe call failed");
4703 if (redir->type == NHERE) {
4704 len = strlen(redir->nhere.doc->narg.text);
4705 if (len <= PIPESIZE) {
4706 full_write(pip[1], redir->nhere.doc->narg.text, len);
4710 if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) {
4712 signal(SIGINT, SIG_IGN);
4713 signal(SIGQUIT, SIG_IGN);
4714 signal(SIGHUP, SIG_IGN);
4716 signal(SIGTSTP, SIG_IGN);
4718 signal(SIGPIPE, SIG_DFL);
4719 if (redir->type == NHERE)
4720 full_write(pip[1], redir->nhere.doc->narg.text, len);
4722 expandhere(redir->nhere.doc, pip[1]);
4731 openredirect(union node *redir)
4736 switch (redir->nfile.type) {
4738 fname = redir->nfile.expfname;
4739 f = open(fname, O_RDONLY);
4744 fname = redir->nfile.expfname;
4745 f = open(fname, O_RDWR|O_CREAT|O_TRUNC, 0666);
4750 /* Take care of noclobber mode. */
4752 fname = redir->nfile.expfname;
4753 f = noclobberopen(fname);
4760 fname = redir->nfile.expfname;
4761 f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666);
4766 fname = redir->nfile.expfname;
4767 f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666);
4775 /* Fall through to eliminate warning. */
4782 f = openhere(redir);
4788 ash_msg_and_raise_error("cannot create %s: %s", fname, errmsg(errno, "Directory nonexistent"));
4790 ash_msg_and_raise_error("cannot open %s: %s", fname, errmsg(errno, "No such file"));
4794 * Copy a file descriptor to be >= to. Returns -1
4795 * if the source file descriptor is closed, EMPTY if there are no unused
4796 * file descriptors left.
4799 copyfd(int from, int to)
4803 newfd = fcntl(from, F_DUPFD, to);
4805 if (errno == EMFILE)
4807 ash_msg_and_raise_error("%d: %m", from);
4813 dupredirect(union node *redir, int f)
4815 int fd = redir->nfile.fd;
4817 if (redir->nfile.type == NTOFD || redir->nfile.type == NFROMFD) {
4818 if (redir->ndup.dupfd >= 0) { /* if not ">&-" */
4819 copyfd(redir->ndup.dupfd, fd);
4831 * Process a list of redirection commands. If the REDIR_PUSH flag is set,
4832 * old file descriptors are stashed away so that the redirection can be
4833 * undone by calling popredir. If the REDIR_BACKQ flag is set, then the
4834 * standard output, and the standard error if it becomes a duplicate of
4835 * stdout, is saved in memory.
4837 /* flags passed to redirect */
4838 #define REDIR_PUSH 01 /* save previous values of file descriptors */
4839 #define REDIR_SAVEFD2 03 /* set preverrout */
4841 redirect(union node *redir, int flags)
4844 struct redirtab *sv;
4855 if (flags & REDIR_PUSH) {
4857 q = ckmalloc(sizeof(struct redirtab));
4858 q->next = redirlist;
4860 q->nullredirs = nullredirs - 1;
4861 for (i = 0; i < 10; i++)
4862 q->renamed[i] = EMPTY;
4869 if ((n->nfile.type == NTOFD || n->nfile.type == NFROMFD)
4870 && n->ndup.dupfd == fd)
4871 continue; /* redirect from/to same file descriptor */
4873 newfd = openredirect(n);
4876 if (sv && *(p = &sv->renamed[fd]) == EMPTY) {
4877 i = fcntl(fd, F_DUPFD, 10);
4884 ash_msg_and_raise_error("%d: %m", fd);
4894 dupredirect(n, newfd);
4895 } while ((n = n->nfile.next));
4897 if (flags & REDIR_SAVEFD2 && sv && sv->renamed[2] >= 0)
4898 preverrout_fd = sv->renamed[2];
4902 * Undo the effects of the last redirection.
4907 struct redirtab *rp;
4910 if (--nullredirs >= 0)
4914 for (i = 0; i < 10; i++) {
4915 if (rp->renamed[i] != EMPTY) {
4918 copyfd(rp->renamed[i], i);
4920 close(rp->renamed[i]);
4923 redirlist = rp->next;
4924 nullredirs = rp->nullredirs;
4930 * Undo all redirections. Called on error or interrupt.
4934 * Discard all saved file descriptors.
4937 clearredir(int drop)
4948 redirectsafe(union node *redir, int flags)
4951 volatile int saveint;
4952 struct jmploc *volatile savehandler = exception_handler;
4953 struct jmploc jmploc;
4956 err = setjmp(jmploc.loc) * 2;
4958 exception_handler = &jmploc;
4959 redirect(redir, flags);
4961 exception_handler = savehandler;
4962 if (err && exception != EXERROR)
4963 longjmp(exception_handler->loc, 1);
4964 RESTORE_INT(saveint);
4969 /* ============ Routines to expand arguments to commands
4971 * We have to deal with backquotes, shell variables, and file metacharacters.
4977 #define EXP_FULL 0x1 /* perform word splitting & file globbing */
4978 #define EXP_TILDE 0x2 /* do normal tilde expansion */
4979 #define EXP_VARTILDE 0x4 /* expand tildes in an assignment */
4980 #define EXP_REDIR 0x8 /* file glob for a redirection (1 match only) */
4981 #define EXP_CASE 0x10 /* keeps quotes around for CASE pattern */
4982 #define EXP_RECORD 0x20 /* need to record arguments for ifs breakup */
4983 #define EXP_VARTILDE2 0x40 /* expand tildes after colons only */
4984 #define EXP_WORD 0x80 /* expand word in parameter expansion */
4985 #define EXP_QWORD 0x100 /* expand word in quoted parameter expansion */
4989 #define RMESCAPE_ALLOC 0x1 /* Allocate a new string */
4990 #define RMESCAPE_GLOB 0x2 /* Add backslashes for glob */
4991 #define RMESCAPE_QUOTED 0x4 /* Remove CTLESC unless in quotes */
4992 #define RMESCAPE_GROW 0x8 /* Grow strings instead of stalloc */
4993 #define RMESCAPE_HEAP 0x10 /* Malloc strings instead of stalloc */
4996 * Structure specifying which parts of the string should be searched
4997 * for IFS characters.
5000 struct ifsregion *next; /* next region in list */
5001 int begoff; /* offset of start of region */
5002 int endoff; /* offset of end of region */
5003 int nulonly; /* search for nul bytes only */
5007 struct strlist *list;
5008 struct strlist **lastp;
5011 /* output of current string */
5012 static char *expdest;
5013 /* list of back quote expressions */
5014 static struct nodelist *argbackq;
5015 /* first struct in list of ifs regions */
5016 static struct ifsregion ifsfirst;
5017 /* last struct in list */
5018 static struct ifsregion *ifslastp;
5019 /* holds expanded arg list */
5020 static struct arglist exparg;
5030 expdest = makestrspace(32, expdest);
5031 #if ENABLE_ASH_MATH_SUPPORT_64
5032 len = fmtstr(expdest, 32, "%lld", (long long) num);
5034 len = fmtstr(expdest, 32, "%ld", num);
5036 STADJUST(len, expdest);
5041 esclen(const char *start, const char *p)
5045 while (p > start && *--p == CTLESC) {
5052 * Remove any CTLESC characters from a string.
5055 _rmescapes(char *str, int flag)
5058 static const char qchars[] = { CTLESC, CTLQUOTEMARK, 0 };
5063 p = strpbrk(str, qchars);
5069 if (flag & RMESCAPE_ALLOC) {
5070 size_t len = p - str;
5071 size_t fulllen = len + strlen(p) + 1;
5073 if (flag & RMESCAPE_GROW) {
5074 r = makestrspace(fulllen, expdest);
5075 } else if (flag & RMESCAPE_HEAP) {
5076 r = ckmalloc(fulllen);
5078 r = stalloc(fulllen);
5082 q = memcpy(q, str, len) + len;
5085 inquotes = (flag & RMESCAPE_QUOTED) ^ RMESCAPE_QUOTED;
5086 globbing = flag & RMESCAPE_GLOB;
5087 notescaped = globbing;
5089 if (*p == CTLQUOTEMARK) {
5090 inquotes = ~inquotes;
5092 notescaped = globbing;
5096 /* naked back slash */
5102 if (notescaped && inquotes && *p != '/') {
5106 notescaped = globbing;
5111 if (flag & RMESCAPE_GROW) {
5113 STADJUST(q - r + 1, expdest);
5117 #define rmescapes(p) _rmescapes((p), 0)
5119 #define pmatch(a, b) !fnmatch((a), (b), 0)
5122 * Prepare a pattern for a expmeta (internal glob(3)) call.
5124 * Returns an stalloced string.
5127 preglob(const char *pattern, int quoted, int flag)
5129 flag |= RMESCAPE_GLOB;
5131 flag |= RMESCAPE_QUOTED;
5133 return _rmescapes((char *)pattern, flag);
5137 * Put a string on the stack.
5140 memtodest(const char *p, size_t len, int syntax, int quotes)
5144 q = makestrspace(len * 2, q);
5147 int c = signed_char2int(*p++);
5150 if (quotes && (SIT(c, syntax) == CCTL || SIT(c, syntax) == CBACK))
5159 strtodest(const char *p, int syntax, int quotes)
5161 memtodest(p, strlen(p), syntax, quotes);
5165 * Record the fact that we have to scan this region of the
5166 * string for IFS characters.
5169 recordregion(int start, int end, int nulonly)
5171 struct ifsregion *ifsp;
5173 if (ifslastp == NULL) {
5177 ifsp = ckmalloc(sizeof(*ifsp));
5179 ifslastp->next = ifsp;
5183 ifslastp->begoff = start;
5184 ifslastp->endoff = end;
5185 ifslastp->nulonly = nulonly;
5189 removerecordregions(int endoff)
5191 if (ifslastp == NULL)
5194 if (ifsfirst.endoff > endoff) {
5195 while (ifsfirst.next != NULL) {
5196 struct ifsregion *ifsp;
5198 ifsp = ifsfirst.next->next;
5199 free(ifsfirst.next);
5200 ifsfirst.next = ifsp;
5203 if (ifsfirst.begoff > endoff)
5206 ifslastp = &ifsfirst;
5207 ifsfirst.endoff = endoff;
5212 ifslastp = &ifsfirst;
5213 while (ifslastp->next && ifslastp->next->begoff < endoff)
5214 ifslastp=ifslastp->next;
5215 while (ifslastp->next != NULL) {
5216 struct ifsregion *ifsp;
5218 ifsp = ifslastp->next->next;
5219 free(ifslastp->next);
5220 ifslastp->next = ifsp;
5223 if (ifslastp->endoff > endoff)
5224 ifslastp->endoff = endoff;
5228 exptilde(char *startp, char *p, int flag)
5234 int quotes = flag & (EXP_FULL | EXP_CASE);
5239 while ((c = *++p) != '\0') {
5246 if (flag & EXP_VARTILDE)
5256 if (*name == '\0') {
5257 home = lookupvar(homestr);
5259 pw = getpwnam(name);
5264 if (!home || !*home)
5267 startloc = expdest - (char *)stackblock();
5268 strtodest(home, SQSYNTAX, quotes);
5269 recordregion(startloc, expdest - (char *)stackblock(), 0);
5277 * Execute a command inside back quotes. If it's a builtin command, we
5278 * want to save its output in a block obtained from malloc. Otherwise
5279 * we fork off a subprocess and get the output of the command via a pipe.
5280 * Should be called with interrupts off.
5282 struct backcmd { /* result of evalbackcmd */
5283 int fd; /* file descriptor to read from */
5284 char *buf; /* buffer */
5285 int nleft; /* number of chars in buffer */
5286 struct job *jp; /* job structure for command */
5289 /* These forward decls are needed to use "eval" code for backticks handling: */
5290 static int back_exitstatus; /* exit status of backquoted command */
5291 #define EV_EXIT 01 /* exit after evaluating tree */
5292 static void evaltree(union node *, int);
5295 evalbackcmd(union node *n, struct backcmd *result)
5307 saveherefd = herefd;
5315 ash_msg_and_raise_error("Pipe call failed");
5317 if (forkshell(jp, n, FORK_NOJOB) == 0) {
5326 evaltree(n, EV_EXIT); /* actually evaltreenr... */
5330 result->fd = pip[0];
5333 herefd = saveherefd;
5335 TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n",
5336 result->fd, result->buf, result->nleft, result->jp));
5340 * Expand stuff in backwards quotes.
5343 expbackq(union node *cmd, int quoted, int quotes)
5351 int syntax = quoted? DQSYNTAX : BASESYNTAX;
5352 struct stackmark smark;
5355 setstackmark(&smark);
5357 startloc = dest - (char *)stackblock();
5359 evalbackcmd(cmd, &in);
5360 popstackmark(&smark);
5367 memtodest(p, i, syntax, quotes);
5371 i = safe_read(in.fd, buf, sizeof(buf));
5372 TRACE(("expbackq: read returns %d\n", i));
5382 back_exitstatus = waitforjob(in.jp);
5386 /* Eat all trailing newlines */
5388 for (; dest > (char *)stackblock() && dest[-1] == '\n';)
5393 recordregion(startloc, dest - (char *)stackblock(), 0);
5394 TRACE(("evalbackq: size=%d: \"%.*s\"\n",
5395 (dest - (char *)stackblock()) - startloc,
5396 (dest - (char *)stackblock()) - startloc,
5397 stackblock() + startloc));
5400 #if ENABLE_ASH_MATH_SUPPORT
5402 * Expand arithmetic expression. Backup to start of expression,
5403 * evaluate, place result in (backed up) result, adjust string position.
5416 * This routine is slightly over-complicated for
5417 * efficiency. Next we scan backwards looking for the
5418 * start of arithmetic.
5420 start = stackblock();
5427 while (*p != CTLARI) {
5431 ash_msg_and_raise_error("missing CTLARI (shouldn't happen)");
5436 esc = esclen(start, p);
5446 removerecordregions(begoff);
5455 len = cvtnum(dash_arith(p + 2));
5458 recordregion(begoff, begoff + len, 0);
5462 /* argstr needs it */
5463 static char *evalvar(char *p, int flag);
5466 * Perform variable and command substitution. If EXP_FULL is set, output CTLESC
5467 * characters to allow for further processing. Otherwise treat
5468 * $@ like $* since no splitting will be performed.
5471 argstr(char *p, int flag)
5473 static const char spclchars[] = {
5481 CTLBACKQ | CTLQUOTE,
5482 #if ENABLE_ASH_MATH_SUPPORT
5487 const char *reject = spclchars;
5489 int quotes = flag & (EXP_FULL | EXP_CASE); /* do CTLESC */
5490 int breakall = flag & EXP_WORD;
5495 if (!(flag & EXP_VARTILDE)) {
5497 } else if (flag & EXP_VARTILDE2) {
5502 if (flag & EXP_TILDE) {
5508 if (*q == CTLESC && (flag & EXP_QWORD))
5511 p = exptilde(p, q, flag);
5514 startloc = expdest - (char *)stackblock();
5516 length += strcspn(p + length, reject);
5518 if (c && (!(c & 0x80)
5519 #if ENABLE_ASH_MATH_SUPPORT
5523 /* c == '=' || c == ':' || c == CTLENDARI */
5528 expdest = stack_nputstr(p, length, expdest);
5529 newloc = expdest - (char *)stackblock();
5530 if (breakall && !inquotes && newloc > startloc) {
5531 recordregion(startloc, newloc, 0);
5542 if (flag & EXP_VARTILDE2) {
5546 flag |= EXP_VARTILDE2;
5551 * sort of a hack - expand tildes in variable
5552 * assignments (after the first '=' and after ':'s).
5561 case CTLENDVAR: /* ??? */
5564 /* "$@" syntax adherence hack */
5567 !memcmp(p, dolatstr, 4) &&
5568 (p[4] == CTLQUOTEMARK || (
5569 p[4] == CTLENDVAR &&
5570 p[5] == CTLQUOTEMARK
5573 p = evalvar(p + 1, flag) + 1;
5576 inquotes = !inquotes;
5589 p = evalvar(p, flag);
5593 case CTLBACKQ|CTLQUOTE:
5594 expbackq(argbackq->n, c, quotes);
5595 argbackq = argbackq->next;
5597 #if ENABLE_ASH_MATH_SUPPORT
5610 scanleft(char *startp, char *rmesc, char *rmescend, char *str, int quotes,
5621 const char *s = loc2;
5627 match = pmatch(str, s);
5631 if (quotes && *loc == CTLESC)
5640 scanright(char *startp, char *rmesc, char *rmescend, char *str, int quotes,
5647 for (loc = str - 1, loc2 = rmescend; loc >= startp; loc2--) {
5650 const char *s = loc2;
5655 match = pmatch(str, s);
5662 esc = esclen(startp, loc);
5673 static void varunset(const char *, const char *, const char *, int) ATTRIBUTE_NORETURN;
5675 varunset(const char *end, const char *var, const char *umsg, int varflags)
5681 msg = "parameter not set";
5683 if (*end == CTLENDVAR) {
5684 if (varflags & VSNUL)
5689 ash_msg_and_raise_error("%.*s: %s%s", end - var - 1, var, msg, tail);
5693 subevalvar(char *p, char *str, int strloc, int subtype, int startloc, int varflags, int quotes)
5697 int saveherefd = herefd;
5698 struct nodelist *saveargbackq = argbackq;
5700 char *rmesc, *rmescend;
5702 char *(*scan)(char *, char *, char *, char *, int , int);
5705 argstr(p, subtype != VSASSIGN && subtype != VSQUESTION ? EXP_CASE : 0);
5706 STPUTC('\0', expdest);
5707 herefd = saveherefd;
5708 argbackq = saveargbackq;
5709 startp = stackblock() + startloc;
5713 setvar(str, startp, 0);
5714 amount = startp - expdest;
5715 STADJUST(amount, expdest);
5719 varunset(p, str, startp, varflags);
5723 subtype -= VSTRIMRIGHT;
5725 if (subtype < 0 || subtype > 3)
5730 rmescend = stackblock() + strloc;
5732 rmesc = _rmescapes(startp, RMESCAPE_ALLOC | RMESCAPE_GROW);
5733 if (rmesc != startp) {
5735 startp = stackblock() + startloc;
5739 str = stackblock() + strloc;
5740 preglob(str, varflags & VSQUOTE, 0);
5742 /* zero = subtype == VSTRIMLEFT || subtype == VSTRIMLEFTMAX */
5743 zero = subtype >> 1;
5744 /* VSTRIMLEFT/VSTRIMRIGHTMAX -> scanleft */
5745 scan = (subtype & 1) ^ zero ? scanleft : scanright;
5747 loc = scan(startp, rmesc, rmescend, str, quotes, zero);
5750 memmove(startp, loc, str - loc);
5751 loc = startp + (str - loc) - 1;
5754 amount = loc - expdest;
5755 STADJUST(amount, expdest);
5761 * Add the value of a specialized variable to the stack string.
5764 varvalue(char *name, int varflags, int flags)
5774 int quoted = varflags & VSQUOTE;
5775 int subtype = varflags & VSTYPE;
5776 int quotes = flags & (EXP_FULL | EXP_CASE);
5778 if (quoted && (flags & EXP_FULL))
5779 sep = 1 << CHAR_BIT;
5781 syntax = quoted ? DQSYNTAX : BASESYNTAX;
5790 num = shellparam.nparam;
5800 p = makestrspace(NOPTS, expdest);
5801 for (i = NOPTS - 1; i >= 0; i--) {
5803 USTPUTC(optletters(i), p);
5814 sep = ifsset() ? signed_char2int(ifsval()[0]) : ' ';
5815 if (quotes && (SIT(sep, syntax) == CCTL || SIT(sep, syntax) == CBACK))
5821 while ((p = *ap++)) {
5824 partlen = strlen(p);
5827 if (!(subtype == VSPLUS || subtype == VSLENGTH))
5828 memtodest(p, partlen, syntax, quotes);
5834 if (subtype == VSPLUS || subtype == VSLENGTH) {
5856 if (num < 0 || num > shellparam.nparam)
5858 p = num ? shellparam.p[num - 1] : arg0;
5861 p = lookupvar(name);
5867 if (!(subtype == VSPLUS || subtype == VSLENGTH))
5868 memtodest(p, len, syntax, quotes);
5872 if (subtype == VSPLUS || subtype == VSLENGTH)
5873 STADJUST(-len, expdest);
5878 * Expand a variable, and return a pointer to the next character in the
5882 evalvar(char *p, int flag)
5895 quotes = flag & (EXP_FULL | EXP_CASE);
5897 subtype = varflags & VSTYPE;
5898 quoted = varflags & VSQUOTE;
5900 easy = (!quoted || (*var == '@' && shellparam.nparam));
5901 startloc = expdest - (char *)stackblock();
5902 p = strchr(p, '=') + 1;
5905 varlen = varvalue(var, varflags, flag);
5906 if (varflags & VSNUL)
5909 if (subtype == VSPLUS) {
5910 varlen = -1 - varlen;
5914 if (subtype == VSMINUS) {
5918 p, flag | EXP_TILDE |
5919 (quoted ? EXP_QWORD : EXP_WORD)
5928 if (subtype == VSASSIGN || subtype == VSQUESTION) {
5930 if (subevalvar(p, var, 0, subtype, startloc, varflags, 0)) {
5933 * Remove any recorded regions beyond
5936 removerecordregions(startloc);
5946 if (varlen < 0 && uflag)
5947 varunset(p, var, 0, 0);
5949 if (subtype == VSLENGTH) {
5950 cvtnum(varlen > 0 ? varlen : 0);
5954 if (subtype == VSNORMAL) {
5958 recordregion(startloc, expdest - (char *)stackblock(), quoted);
5967 case VSTRIMRIGHTMAX:
5976 * Terminate the string and start recording the pattern
5979 STPUTC('\0', expdest);
5980 patloc = expdest - (char *)stackblock();
5981 if (subevalvar(p, NULL, patloc, subtype,
5982 startloc, varflags, quotes) == 0) {
5983 int amount = expdest - (
5984 (char *)stackblock() + patloc - 1
5986 STADJUST(-amount, expdest);
5988 /* Remove any recorded regions beyond start of variable */
5989 removerecordregions(startloc);
5994 if (subtype != VSNORMAL) { /* skip to end of alternative */
6000 else if (c == CTLBACKQ || c == (CTLBACKQ|CTLQUOTE)) {
6002 argbackq = argbackq->next;
6003 } else if (c == CTLVAR) {
6004 if ((*p++ & VSTYPE) != VSNORMAL)
6006 } else if (c == CTLENDVAR) {
6016 * Break the argument string into pieces based upon IFS and add the
6017 * strings to the argument list. The regions of the string to be
6018 * searched for IFS characters have been stored by recordregion.
6021 ifsbreakup(char *string, struct arglist *arglist)
6023 struct ifsregion *ifsp;
6028 const char *ifs, *realifs;
6033 if (ifslastp != NULL) {
6036 realifs = ifsset() ? ifsval() : defifs;
6039 p = string + ifsp->begoff;
6040 nulonly = ifsp->nulonly;
6041 ifs = nulonly ? nullstr : realifs;
6043 while (p < string + ifsp->endoff) {
6047 if (!strchr(ifs, *p)) {
6052 ifsspc = (strchr(defifs, *p) != NULL);
6053 /* Ignore IFS whitespace at start */
6054 if (q == start && ifsspc) {
6060 sp = stalloc(sizeof(*sp));
6062 *arglist->lastp = sp;
6063 arglist->lastp = &sp->next;
6067 if (p >= string + ifsp->endoff) {
6073 if (strchr(ifs, *p) == NULL ) {
6076 } else if (strchr(defifs, *p) == NULL) {
6091 } while (ifsp != NULL);
6100 sp = stalloc(sizeof(*sp));
6102 *arglist->lastp = sp;
6103 arglist->lastp = &sp->next;
6109 struct ifsregion *p;
6114 struct ifsregion *ifsp;
6120 ifsfirst.next = NULL;
6125 * Add a file name to the list.
6128 addfname(const char *name)
6132 sp = stalloc(sizeof(*sp));
6133 sp->text = ststrdup(name);
6135 exparg.lastp = &sp->next;
6138 static char *expdir;
6141 * Do metacharacter (i.e. *, ?, [...]) expansion.
6144 expmeta(char *enddir, char *name)
6159 for (p = name; *p; p++) {
6160 if (*p == '*' || *p == '?')
6162 else if (*p == '[') {
6169 if (*q == '/' || *q == '\0')
6176 } else if (*p == '\\')
6178 else if (*p == '/') {
6185 if (metaflag == 0) { /* we've reached the end of the file name */
6186 if (enddir != expdir)
6194 if (metaflag == 0 || lstat(expdir, &statb) >= 0)
6205 } while (p < start);
6207 if (enddir == expdir) {
6209 } else if (enddir == expdir + 1 && *expdir == '/') {
6218 if (enddir != expdir)
6220 if (*endname == 0) {
6232 while (! intpending && (dp = readdir(dirp)) != NULL) {
6233 if (dp->d_name[0] == '.' && ! matchdot)
6235 if (pmatch(start, dp->d_name)) {
6237 strcpy(enddir, dp->d_name);
6240 for (p = enddir, cp = dp->d_name; (*p++ = *cp++) != '\0';)
6243 expmeta(p, endname);
6252 static struct strlist *
6253 msort(struct strlist *list, int len)
6255 struct strlist *p, *q = NULL;
6256 struct strlist **lpp;
6264 for (n = half; --n >= 0; ) {
6268 q->next = NULL; /* terminate first half of list */
6269 q = msort(list, half); /* sort first half of list */
6270 p = msort(p, len - half); /* sort second half */
6273 #if ENABLE_LOCALE_SUPPORT
6274 if (strcoll(p->text, q->text) < 0)
6276 if (strcmp(p->text, q->text) < 0)
6300 * Sort the results of file name expansion. It calculates the number of
6301 * strings to sort and then calls msort (short for merge sort) to do the
6304 static struct strlist *
6305 expsort(struct strlist *str)
6311 for (sp = str; sp; sp = sp->next)
6313 return msort(str, len);
6317 expandmeta(struct strlist *str, int flag)
6319 static const char metachars[] = {
6322 /* TODO - EXP_REDIR */
6325 struct strlist **savelastp;
6331 if (!strpbrk(str->text, metachars))
6333 savelastp = exparg.lastp;
6336 p = preglob(str->text, 0, RMESCAPE_ALLOC | RMESCAPE_HEAP);
6338 int i = strlen(str->text);
6339 expdir = ckmalloc(i < 2048 ? 2048 : i); /* XXX */
6347 if (exparg.lastp == savelastp) {
6352 *exparg.lastp = str;
6353 rmescapes(str->text);
6354 exparg.lastp = &str->next;
6356 *exparg.lastp = NULL;
6357 *savelastp = sp = expsort(*savelastp);
6358 while (sp->next != NULL)
6360 exparg.lastp = &sp->next;
6367 * Perform variable substitution and command substitution on an argument,
6368 * placing the resulting list of arguments in arglist. If EXP_FULL is true,
6369 * perform splitting and file name expansion. When arglist is NULL, perform
6370 * here document expansion.
6373 expandarg(union node *arg, struct arglist *arglist, int flag)
6378 argbackq = arg->narg.backquote;
6379 STARTSTACKSTR(expdest);
6380 ifsfirst.next = NULL;
6382 argstr(arg->narg.text, flag);
6383 p = _STPUTC('\0', expdest);
6385 if (arglist == NULL) {
6386 return; /* here document expanded */
6388 p = grabstackstr(p);
6389 exparg.lastp = &exparg.list;
6393 if (flag & EXP_FULL) {
6394 ifsbreakup(p, &exparg);
6395 *exparg.lastp = NULL;
6396 exparg.lastp = &exparg.list;
6397 expandmeta(exparg.list, flag);
6399 if (flag & EXP_REDIR) /*XXX - for now, just remove escapes */
6401 sp = stalloc(sizeof(*sp));
6404 exparg.lastp = &sp->next;
6408 *exparg.lastp = NULL;
6410 *arglist->lastp = exparg.list;
6411 arglist->lastp = exparg.lastp;
6416 * Expand shell variables and backquotes inside a here document.
6419 expandhere(union node *arg, int fd)
6422 expandarg(arg, (struct arglist *)NULL, 0);
6423 full_write(fd, stackblock(), expdest - (char *)stackblock());
6427 * Returns true if the pattern matches the string.
6430 patmatch(char *pattern, const char *string)
6432 return pmatch(preglob(pattern, 0, 0), string);
6436 * See if a pattern matches in a case statement.
6439 casematch(union node *pattern, char *val)
6441 struct stackmark smark;
6444 setstackmark(&smark);
6445 argbackq = pattern->narg.backquote;
6446 STARTSTACKSTR(expdest);
6448 argstr(pattern->narg.text, EXP_TILDE | EXP_CASE);
6449 STACKSTRNUL(expdest);
6450 result = patmatch(stackblock(), val);
6451 popstackmark(&smark);
6456 /* ============ find_command */
6458 static int is_safe_applet(char *name)
6460 /* It isn't a bug to have non-existent applet here... */
6461 /* ...just a waste of space... */
6462 static const char safe_applets[][8] = {
6466 USE_CHMOD (, "chmod" )
6467 USE_CHOWN (, "chown" )
6471 USE_ECHO (, "echo" )
6472 USE_FIND (, "find" )
6473 USE_HEXDUMP(, "hexdump")
6476 USE_MKDIR (, "mkdir" )
6478 USE_SORT (, "sort" )
6479 USE_TEST (, "test" )
6480 USE_TOUCH (, "touch" )
6481 USE_XARGS (, "xargs" )
6483 int n = sizeof(safe_applets) / sizeof(safe_applets[0]);
6485 for (i = 0; i < n; i++)
6486 if (strcmp(safe_applets[i], name) == 0)
6494 int (*builtin)(int, char **);
6495 /* unsigned flags; */
6497 #define IS_BUILTIN_SPECIAL(b) ((b)->name[0] & 1)
6498 #define IS_BUILTIN_REGULAR(b) ((b)->name[0] & 2)
6499 #define IS_BUILTIN_ASSIGN(b) ((b)->name[0] & 4)
6505 const struct builtincmd *cmd;
6506 struct funcnode *func;
6509 /* values of cmdtype */
6510 #define CMDUNKNOWN -1 /* no entry in table for command */
6511 #define CMDNORMAL 0 /* command is an executable program */
6512 #define CMDFUNCTION 1 /* command is a shell function */
6513 #define CMDBUILTIN 2 /* command is a shell builtin */
6515 /* action to find_command() */
6516 #define DO_ERR 0x01 /* prints errors */
6517 #define DO_ABS 0x02 /* checks absolute paths */
6518 #define DO_NOFUNC 0x04 /* don't return shell functions, for command */
6519 #define DO_ALTPATH 0x08 /* using alternate path */
6520 #define DO_ALTBLTIN 0x20 /* %builtin in alt. path */
6522 static void find_command(char *, struct cmdentry *, int, const char *);
6525 /* ============ Hashing commands */
6528 * When commands are first encountered, they are entered in a hash table.
6529 * This ensures that a full path search will not have to be done for them
6530 * on each invocation.
6532 * We should investigate converting to a linear search, even though that
6533 * would make the command name "hash" a misnomer.
6536 #define CMDTABLESIZE 31 /* should be prime */
6537 #define ARB 1 /* actual size determined at run time */
6540 struct tblentry *next; /* next entry in hash chain */
6541 union param param; /* definition of builtin function */
6542 short cmdtype; /* index identifying command */
6543 char rehash; /* if set, cd done since entry created */
6544 char cmdname[ARB]; /* name of command */
6547 static struct tblentry *cmdtable[CMDTABLESIZE];
6548 static int builtinloc = -1; /* index in path of %builtin, or -1 */
6551 tryexec(char *cmd, char **argv, char **envp)
6554 struct BB_applet *a;
6558 if (strchr(cmd, '/') == NULL
6559 && (a = find_applet_by_name(cmd)) != NULL
6560 && is_safe_applet(cmd)
6563 while (*c != NULL) {
6567 exit(a->main(argc, argv));
6569 #if ENABLE_FEATURE_SH_STANDALONE_SHELL
6570 if (find_applet_by_name(cmd) != NULL) {
6571 /* re-exec ourselves with the new arguments */
6572 execve(CONFIG_BUSYBOX_EXEC_PATH, argv, envp);
6573 /* If they called chroot or otherwise made the binary no longer
6574 * executable, fall through */
6581 execve(cmd, argv, envp);
6582 } while (errno == EINTR);
6584 execve(cmd, argv, envp);
6588 } else if (errno == ENOEXEC) {
6592 for (ap = argv; *ap; ap++)
6594 ap = new = ckmalloc((ap - argv + 2) * sizeof(char *));
6596 *ap = cmd = (char *)DEFAULT_SHELL;
6599 while ((*ap++ = *argv++))
6607 * Exec a program. Never returns. If you change this routine, you may
6608 * have to change the find_command routine as well.
6610 #define environment() listvars(VEXPORT, VUNSET, 0)
6611 static void shellexec(char **, const char *, int) ATTRIBUTE_NORETURN;
6613 shellexec(char **argv, const char *path, int idx)
6621 envp = environment();
6622 if (strchr(argv[0], '/') || is_safe_applet(argv[0])
6623 #if ENABLE_FEATURE_SH_STANDALONE_SHELL
6624 || find_applet_by_name(argv[0])
6627 tryexec(argv[0], argv, envp);
6631 while ((cmdname = padvance(&path, argv[0])) != NULL) {
6632 if (--idx < 0 && pathopt == NULL) {
6633 tryexec(cmdname, argv, envp);
6634 if (errno != ENOENT && errno != ENOTDIR)
6641 /* Map to POSIX errors */
6653 exitstatus = exerrno;
6654 TRACE(("shellexec failed for %s, errno %d, suppressint %d\n",
6655 argv[0], e, suppressint ));
6656 ash_msg_and_raise(EXEXEC, "%s: %s", argv[0], errmsg(e, "not found"));
6661 printentry(struct tblentry *cmdp)
6667 idx = cmdp->param.index;
6670 name = padvance(&path, cmdp->cmdname);
6672 } while (--idx >= 0);
6673 out1fmt("%s%s\n", name, (cmdp->rehash ? "*" : nullstr));
6677 * Clear out command entries. The argument specifies the first entry in
6678 * PATH which has changed.
6681 clearcmdentry(int firstchange)
6683 struct tblentry **tblp;
6684 struct tblentry **pp;
6685 struct tblentry *cmdp;
6688 for (tblp = cmdtable; tblp < &cmdtable[CMDTABLESIZE]; tblp++) {
6690 while ((cmdp = *pp) != NULL) {
6691 if ((cmdp->cmdtype == CMDNORMAL &&
6692 cmdp->param.index >= firstchange)
6693 || (cmdp->cmdtype == CMDBUILTIN &&
6694 builtinloc >= firstchange)
6707 * Locate a command in the command hash table. If "add" is nonzero,
6708 * add the command to the table if it is not already present. The
6709 * variable "lastcmdentry" is set to point to the address of the link
6710 * pointing to the entry, so that delete_cmd_entry can delete the
6713 * Interrupts must be off if called with add != 0.
6715 static struct tblentry **lastcmdentry;
6717 static struct tblentry *
6718 cmdlookup(const char *name, int add)
6720 unsigned int hashval;
6722 struct tblentry *cmdp;
6723 struct tblentry **pp;
6726 hashval = (unsigned char)*p << 4;
6728 hashval += (unsigned char)*p++;
6730 pp = &cmdtable[hashval % CMDTABLESIZE];
6731 for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
6732 if (strcmp(cmdp->cmdname, name) == 0)
6736 if (add && cmdp == NULL) {
6737 cmdp = *pp = ckmalloc(sizeof(struct tblentry) - ARB
6738 + strlen(name) + 1);
6740 cmdp->cmdtype = CMDUNKNOWN;
6741 strcpy(cmdp->cmdname, name);
6748 * Delete the command entry returned on the last lookup.
6751 delete_cmd_entry(void)
6753 struct tblentry *cmdp;
6756 cmdp = *lastcmdentry;
6757 *lastcmdentry = cmdp->next;
6758 if (cmdp->cmdtype == CMDFUNCTION)
6759 freefunc(cmdp->param.func);
6765 * Add a new command entry, replacing any existing command entry for
6766 * the same name - except special builtins.
6769 addcmdentry(char *name, struct cmdentry *entry)
6771 struct tblentry *cmdp;
6773 cmdp = cmdlookup(name, 1);
6774 if (cmdp->cmdtype == CMDFUNCTION) {
6775 freefunc(cmdp->param.func);
6777 cmdp->cmdtype = entry->cmdtype;
6778 cmdp->param = entry->u;
6783 hashcmd(int argc, char **argv)
6785 struct tblentry **pp;
6786 struct tblentry *cmdp;
6788 struct cmdentry entry;
6791 while ((c = nextopt("r")) != '\0') {
6795 if (*argptr == NULL) {
6796 for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
6797 for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
6798 if (cmdp->cmdtype == CMDNORMAL)
6805 while ((name = *argptr) != NULL) {
6806 cmdp = cmdlookup(name, 0);
6808 && (cmdp->cmdtype == CMDNORMAL
6809 || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0)))
6811 find_command(name, &entry, DO_ERR, pathval());
6812 if (entry.cmdtype == CMDUNKNOWN)
6820 * Called when a cd is done. Marks all commands so the next time they
6821 * are executed they will be rehashed.
6826 struct tblentry **pp;
6827 struct tblentry *cmdp;
6829 for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
6830 for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
6831 if (cmdp->cmdtype == CMDNORMAL || (
6832 cmdp->cmdtype == CMDBUILTIN &&
6833 !(IS_BUILTIN_REGULAR(cmdp->param.cmd)) &&
6842 * Fix command hash table when PATH changed.
6843 * Called before PATH is changed. The argument is the new value of PATH;
6844 * pathval() still returns the old value at this point.
6845 * Called with interrupts off.
6848 changepath(const char *newval)
6850 const char *old, *new;
6857 firstchange = 9999; /* assume no change */
6863 if ((*old == '\0' && *new == ':')
6864 || (*old == ':' && *new == '\0'))
6866 old = new; /* ignore subsequent differences */
6870 if (*new == '%' && idx_bltin < 0 && prefix(new + 1, "builtin"))
6877 if (builtinloc < 0 && idx_bltin >= 0)
6878 builtinloc = idx_bltin; /* zap builtins */
6879 if (builtinloc >= 0 && idx_bltin < 0)
6881 clearcmdentry(firstchange);
6882 builtinloc = idx_bltin;
6897 #define TENDBQUOTE 12
6915 /* first char is indicating which tokens mark the end of a list */
6916 static const char *const tokname_array[] = {
6930 #define KWDOFFSET 13
6931 /* the following are keywords */
6953 static char buf[16];
6957 sprintf(buf + (tok >= TSEMI), "%s%c",
6958 tokname_array[tok] + 1, (tok >= TSEMI ? '"' : 0));
6962 /* Wrapper around strcmp for qsort/bsearch/... */
6964 pstrcmp(const void *a, const void *b)
6966 return strcmp((const char *) a, (*(const char *const *) b) + 1);
6969 static const char *const *
6970 findkwd(const char *s)
6972 return bsearch(s, tokname_array + KWDOFFSET,
6973 (sizeof(tokname_array) / sizeof(const char *)) - KWDOFFSET,
6974 sizeof(const char *), pstrcmp);
6978 * Locate and print what a word is...
6980 #if ENABLE_ASH_CMDCMD
6982 describe_command(char *command, int describe_command_verbose)
6984 #define describe_command_verbose 1
6986 describe_command(char *command)
6989 struct cmdentry entry;
6990 struct tblentry *cmdp;
6991 #if ENABLE_ASH_ALIAS
6992 const struct alias *ap;
6994 const char *path = pathval();
6996 if (describe_command_verbose) {
7000 /* First look at the keywords */
7001 if (findkwd(command)) {
7002 out1str(describe_command_verbose ? " is a shell keyword" : command);
7006 #if ENABLE_ASH_ALIAS
7007 /* Then look at the aliases */
7008 ap = lookupalias(command, 0);
7010 if (describe_command_verbose) {
7011 out1fmt(" is an alias for %s", ap->val);
7020 /* Then check if it is a tracked alias */
7021 cmdp = cmdlookup(command, 0);
7023 entry.cmdtype = cmdp->cmdtype;
7024 entry.u = cmdp->param;
7026 /* Finally use brute force */
7027 find_command(command, &entry, DO_ABS, path);
7030 switch (entry.cmdtype) {
7032 int j = entry.u.index;
7038 p = padvance(&path, command);
7042 if (describe_command_verbose) {
7044 (cmdp ? " a tracked alias for" : nullstr), p
7053 if (describe_command_verbose) {
7054 out1str(" is a shell function");
7061 if (describe_command_verbose) {
7062 out1fmt(" is a %sshell builtin",
7063 IS_BUILTIN_SPECIAL(entry.u.cmd) ?
7064 "special " : nullstr
7072 if (describe_command_verbose) {
7073 out1str(": not found\n");
7078 outstr("\n", stdout);
7083 typecmd(int argc, char **argv)
7088 for (i = 1; i < argc; i++) {
7089 #if ENABLE_ASH_CMDCMD
7090 err |= describe_command(argv[i], 1);
7092 err |= describe_command(argv[i]);
7098 #if ENABLE_ASH_CMDCMD
7100 commandcmd(int argc, char **argv)
7108 while ((c = nextopt("pvV")) != '\0')
7110 verify |= VERIFY_VERBOSE;
7112 verify |= VERIFY_BRIEF;
7118 return describe_command(*argptr, verify - VERIFY_BRIEF);
7125 /* ============ eval.c */
7127 static int funcblocksize; /* size of structures in function */
7128 static int funcstringsize; /* size of strings in node */
7129 static void *funcblock; /* block to allocate function from */
7130 static char *funcstring; /* block to allocate strings from */
7132 /* flags in argument to evaltree */
7133 #define EV_EXIT 01 /* exit after evaluating tree */
7134 #define EV_TESTED 02 /* exit status is checked; ignore -e flag */
7135 #define EV_BACKCMD 04 /* command executing within back quotes */
7137 static const short nodesize[26] = {
7138 SHELL_ALIGN(sizeof(struct ncmd)),
7139 SHELL_ALIGN(sizeof(struct npipe)),
7140 SHELL_ALIGN(sizeof(struct nredir)),
7141 SHELL_ALIGN(sizeof(struct nredir)),
7142 SHELL_ALIGN(sizeof(struct nredir)),
7143 SHELL_ALIGN(sizeof(struct nbinary)),
7144 SHELL_ALIGN(sizeof(struct nbinary)),
7145 SHELL_ALIGN(sizeof(struct nbinary)),
7146 SHELL_ALIGN(sizeof(struct nif)),
7147 SHELL_ALIGN(sizeof(struct nbinary)),
7148 SHELL_ALIGN(sizeof(struct nbinary)),
7149 SHELL_ALIGN(sizeof(struct nfor)),
7150 SHELL_ALIGN(sizeof(struct ncase)),
7151 SHELL_ALIGN(sizeof(struct nclist)),
7152 SHELL_ALIGN(sizeof(struct narg)),
7153 SHELL_ALIGN(sizeof(struct narg)),
7154 SHELL_ALIGN(sizeof(struct nfile)),
7155 SHELL_ALIGN(sizeof(struct nfile)),
7156 SHELL_ALIGN(sizeof(struct nfile)),
7157 SHELL_ALIGN(sizeof(struct nfile)),
7158 SHELL_ALIGN(sizeof(struct nfile)),
7159 SHELL_ALIGN(sizeof(struct ndup)),
7160 SHELL_ALIGN(sizeof(struct ndup)),
7161 SHELL_ALIGN(sizeof(struct nhere)),
7162 SHELL_ALIGN(sizeof(struct nhere)),
7163 SHELL_ALIGN(sizeof(struct nnot)),
7166 static void calcsize(union node *n);
7169 sizenodelist(struct nodelist *lp)
7172 funcblocksize += SHELL_ALIGN(sizeof(struct nodelist));
7179 calcsize(union node *n)
7183 funcblocksize += nodesize[n->type];
7186 calcsize(n->ncmd.redirect);
7187 calcsize(n->ncmd.args);
7188 calcsize(n->ncmd.assign);
7191 sizenodelist(n->npipe.cmdlist);
7196 calcsize(n->nredir.redirect);
7197 calcsize(n->nredir.n);
7204 calcsize(n->nbinary.ch2);
7205 calcsize(n->nbinary.ch1);
7208 calcsize(n->nif.elsepart);
7209 calcsize(n->nif.ifpart);
7210 calcsize(n->nif.test);
7213 funcstringsize += strlen(n->nfor.var) + 1;
7214 calcsize(n->nfor.body);
7215 calcsize(n->nfor.args);
7218 calcsize(n->ncase.cases);
7219 calcsize(n->ncase.expr);
7222 calcsize(n->nclist.body);
7223 calcsize(n->nclist.pattern);
7224 calcsize(n->nclist.next);
7228 sizenodelist(n->narg.backquote);
7229 funcstringsize += strlen(n->narg.text) + 1;
7230 calcsize(n->narg.next);
7237 calcsize(n->nfile.fname);
7238 calcsize(n->nfile.next);
7242 calcsize(n->ndup.vname);
7243 calcsize(n->ndup.next);
7247 calcsize(n->nhere.doc);
7248 calcsize(n->nhere.next);
7251 calcsize(n->nnot.com);
7257 nodeckstrdup(char *s)
7259 char *rtn = funcstring;
7261 strcpy(funcstring, s);
7262 funcstring += strlen(s) + 1;
7266 static union node *copynode(union node *);
7268 static struct nodelist *
7269 copynodelist(struct nodelist *lp)
7271 struct nodelist *start;
7272 struct nodelist **lpp;
7277 funcblock = (char *) funcblock + SHELL_ALIGN(sizeof(struct nodelist));
7278 (*lpp)->n = copynode(lp->n);
7280 lpp = &(*lpp)->next;
7287 copynode(union node *n)
7294 funcblock = (char *) funcblock + nodesize[n->type];
7298 new->ncmd.redirect = copynode(n->ncmd.redirect);
7299 new->ncmd.args = copynode(n->ncmd.args);
7300 new->ncmd.assign = copynode(n->ncmd.assign);
7303 new->npipe.cmdlist = copynodelist(n->npipe.cmdlist);
7304 new->npipe.backgnd = n->npipe.backgnd;
7309 new->nredir.redirect = copynode(n->nredir.redirect);
7310 new->nredir.n = copynode(n->nredir.n);
7317 new->nbinary.ch2 = copynode(n->nbinary.ch2);
7318 new->nbinary.ch1 = copynode(n->nbinary.ch1);
7321 new->nif.elsepart = copynode(n->nif.elsepart);
7322 new->nif.ifpart = copynode(n->nif.ifpart);
7323 new->nif.test = copynode(n->nif.test);
7326 new->nfor.var = nodeckstrdup(n->nfor.var);
7327 new->nfor.body = copynode(n->nfor.body);
7328 new->nfor.args = copynode(n->nfor.args);
7331 new->ncase.cases = copynode(n->ncase.cases);
7332 new->ncase.expr = copynode(n->ncase.expr);
7335 new->nclist.body = copynode(n->nclist.body);
7336 new->nclist.pattern = copynode(n->nclist.pattern);
7337 new->nclist.next = copynode(n->nclist.next);
7341 new->narg.backquote = copynodelist(n->narg.backquote);
7342 new->narg.text = nodeckstrdup(n->narg.text);
7343 new->narg.next = copynode(n->narg.next);
7350 new->nfile.fname = copynode(n->nfile.fname);
7351 new->nfile.fd = n->nfile.fd;
7352 new->nfile.next = copynode(n->nfile.next);
7356 new->ndup.vname = copynode(n->ndup.vname);
7357 new->ndup.dupfd = n->ndup.dupfd;
7358 new->ndup.fd = n->ndup.fd;
7359 new->ndup.next = copynode(n->ndup.next);
7363 new->nhere.doc = copynode(n->nhere.doc);
7364 new->nhere.fd = n->nhere.fd;
7365 new->nhere.next = copynode(n->nhere.next);
7368 new->nnot.com = copynode(n->nnot.com);
7371 new->type = n->type;
7376 * Make a copy of a parse tree.
7378 static struct funcnode *
7379 copyfunc(union node *n)
7384 funcblocksize = offsetof(struct funcnode, n);
7387 blocksize = funcblocksize;
7388 f = ckmalloc(blocksize + funcstringsize);
7389 funcblock = (char *) f + offsetof(struct funcnode, n);
7390 funcstring = (char *) f + blocksize;
7397 * Define a shell function.
7400 defun(char *name, union node *func)
7402 struct cmdentry entry;
7405 entry.cmdtype = CMDFUNCTION;
7406 entry.u.func = copyfunc(func);
7407 addcmdentry(name, &entry);
7411 static int evalskip; /* set if we are skipping commands */
7412 /* reasons for skipping commands (see comment on breakcmd routine) */
7413 #define SKIPBREAK (1 << 0)
7414 #define SKIPCONT (1 << 1)
7415 #define SKIPFUNC (1 << 2)
7416 #define SKIPFILE (1 << 3)
7417 #define SKIPEVAL (1 << 4)
7418 static int skipcount; /* number of levels to skip */
7419 static int funcnest; /* depth of function calls */
7421 /* forward decl way out to parsing code - dotrap needs it */
7422 static int evalstring(char *s, int mask);
7425 * Called to execute a trap. Perhaps we should avoid entering new trap
7426 * handlers while we are executing a trap handler.
7437 savestatus = exitstatus;
7441 for (i = 0, q = gotsig; i < NSIG - 1; i++, q++) {
7449 skip = evalstring(p, SKIPEVAL);
7450 exitstatus = savestatus;
7458 /* forward declarations - evaluation is fairly recursive business... */
7459 static void evalloop(union node *, int);
7460 static void evalfor(union node *, int);
7461 static void evalcase(union node *, int);
7462 static void evalsubshell(union node *, int);
7463 static void expredir(union node *);
7464 static void evalpipe(union node *, int);
7465 static void evalcommand(union node *, int);
7466 static int evalbltin(const struct builtincmd *, int, char **);
7467 static void prehash(union node *);
7470 * Evaluate a parse tree. The value is left in the global variable
7474 evaltree(union node *n, int flags)
7477 void (*evalfn)(union node *, int);
7481 TRACE(("evaltree(NULL) called\n"));
7484 TRACE(("pid %d, evaltree(%p: %d, %d) called\n",
7485 getpid(), n, n->type, flags));
7489 out1fmt("Node type = %d\n", n->type);
7494 evaltree(n->nnot.com, EV_TESTED);
7495 status = !exitstatus;
7498 expredir(n->nredir.redirect);
7499 status = redirectsafe(n->nredir.redirect, REDIR_PUSH);
7501 evaltree(n->nredir.n, flags & EV_TESTED);
7502 status = exitstatus;
7507 evalfn = evalcommand;
7509 if (eflag && !(flags & EV_TESTED))
7521 evalfn = evalsubshell;
7533 #error NAND + 1 != NOR
7535 #if NOR + 1 != NSEMI
7536 #error NOR + 1 != NSEMI
7538 isor = n->type - NAND;
7541 (flags | ((isor >> 1) - 1)) & EV_TESTED
7543 if (!exitstatus == isor)
7555 evaltree(n->nif.test, EV_TESTED);
7558 if (exitstatus == 0) {
7561 } else if (n->nif.elsepart) {
7562 n = n->nif.elsepart;
7567 defun(n->narg.text, n->narg.next);
7571 exitstatus = status;
7575 if ((checkexit & exitstatus))
7576 evalskip |= SKIPEVAL;
7577 else if (pendingsigs && dotrap())
7580 if (flags & EV_EXIT) {
7582 raise_exception(EXEXIT);
7586 #if !defined(__alpha__) || (defined(__GNUC__) && __GNUC__ >= 3)
7589 void evaltreenr(union node *, int) __attribute__ ((alias("evaltree"),__noreturn__));
7591 static int loopnest; /* current loop nesting level */
7594 evalloop(union node *n, int flags)
7604 evaltree(n->nbinary.ch1, EV_TESTED);
7607 if (evalskip == SKIPCONT && --skipcount <= 0) {
7611 if (evalskip == SKIPBREAK && --skipcount <= 0)
7616 if (n->type != NWHILE)
7620 evaltree(n->nbinary.ch2, flags);
7621 status = exitstatus;
7626 exitstatus = status;
7630 evalfor(union node *n, int flags)
7632 struct arglist arglist;
7635 struct stackmark smark;
7637 setstackmark(&smark);
7638 arglist.lastp = &arglist.list;
7639 for (argp = n->nfor.args; argp; argp = argp->narg.next) {
7640 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE | EXP_RECORD);
7645 *arglist.lastp = NULL;
7650 for (sp = arglist.list; sp; sp = sp->next) {
7651 setvar(n->nfor.var, sp->text, 0);
7652 evaltree(n->nfor.body, flags);
7654 if (evalskip == SKIPCONT && --skipcount <= 0) {
7658 if (evalskip == SKIPBREAK && --skipcount <= 0)
7665 popstackmark(&smark);
7669 evalcase(union node *n, int flags)
7673 struct arglist arglist;
7674 struct stackmark smark;
7676 setstackmark(&smark);
7677 arglist.lastp = &arglist.list;
7678 expandarg(n->ncase.expr, &arglist, EXP_TILDE);
7680 for (cp = n->ncase.cases; cp && evalskip == 0; cp = cp->nclist.next) {
7681 for (patp = cp->nclist.pattern; patp; patp = patp->narg.next) {
7682 if (casematch(patp, arglist.list->text)) {
7683 if (evalskip == 0) {
7684 evaltree(cp->nclist.body, flags);
7691 popstackmark(&smark);
7695 * Kick off a subshell to evaluate a tree.
7698 evalsubshell(union node *n, int flags)
7701 int backgnd = (n->type == NBACKGND);
7704 expredir(n->nredir.redirect);
7705 if (!backgnd && flags & EV_EXIT && !trap[0])
7709 if (forkshell(jp, n, backgnd) == 0) {
7713 flags &=~ EV_TESTED;
7715 redirect(n->nredir.redirect, 0);
7716 evaltreenr(n->nredir.n, flags);
7721 status = waitforjob(jp);
7722 exitstatus = status;
7727 * Compute the names of the files in a redirection list.
7729 static void fixredir(union node *, const char *, int);
7731 expredir(union node *n)
7735 for (redir = n; redir; redir = redir->nfile.next) {
7738 memset(&fn, 0, sizeof(fn));
7739 fn.lastp = &fn.list;
7740 switch (redir->type) {
7746 expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
7747 redir->nfile.expfname = fn.list->text;
7751 if (redir->ndup.vname) {
7752 expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE);
7753 if (fn.list == NULL)
7754 ash_msg_and_raise_error("redir error");
7755 fixredir(redir, fn.list->text, 1);
7763 * Evaluate a pipeline. All the processes in the pipeline are children
7764 * of the process creating the pipeline. (This differs from some versions
7765 * of the shell, which make the last process in a pipeline the parent
7769 evalpipe(union node *n, int flags)
7772 struct nodelist *lp;
7777 TRACE(("evalpipe(0x%lx) called\n", (long)n));
7779 for (lp = n->npipe.cmdlist; lp; lp = lp->next)
7783 jp = makejob(n, pipelen);
7785 for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
7789 if (pipe(pip) < 0) {
7791 ash_msg_and_raise_error("Pipe call failed");
7794 if (forkshell(jp, lp->n, n->npipe.backgnd) == 0) {
7807 evaltreenr(lp->n, flags);
7815 if (n->npipe.backgnd == 0) {
7816 exitstatus = waitforjob(jp);
7817 TRACE(("evalpipe: job done exit status %d\n", exitstatus));
7823 * Controls whether the shell is interactive or not.
7826 setinteractive(int on)
7828 static int is_interactive;
7830 if (++on == is_interactive)
7832 is_interactive = on;
7836 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
7837 if (is_interactive > 1) {
7838 /* Looks like they want an interactive shell */
7839 static smallint do_banner;
7844 "%s Built-in shell (ash)\n"
7845 "Enter 'help' for a list of built-in commands."
7854 #if ENABLE_FEATURE_EDITING_VI
7855 #define setvimode(on) do { \
7856 if (on) line_input_state->flags |= VI_MODE; \
7857 else line_input_state->flags &= ~VI_MODE; \
7860 #define setvimode(on) viflag = 0 /* forcibly keep the option off */
7869 setinteractive(iflag);
7874 static struct localvar *localvars;
7877 * Called after a function returns.
7878 * Interrupts must be off.
7883 struct localvar *lvp;
7886 while ((lvp = localvars) != NULL) {
7887 localvars = lvp->next;
7889 TRACE(("poplocalvar %s", vp ? vp->text : "-"));
7890 if (vp == NULL) { /* $- saved */
7891 memcpy(optlist, lvp->text, sizeof(optlist));
7892 free((char*)lvp->text);
7894 } else if ((lvp->flags & (VUNSET|VSTRFIXED)) == VUNSET) {
7898 (*vp->func)(strchrnul(lvp->text, '=') + 1);
7899 if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
7900 free((char*)vp->text);
7901 vp->flags = lvp->flags;
7902 vp->text = lvp->text;
7909 evalfun(struct funcnode *func, int argc, char **argv, int flags)
7911 volatile struct shparam saveparam;
7912 struct localvar *volatile savelocalvars;
7913 struct jmploc *volatile savehandler;
7914 struct jmploc jmploc;
7917 saveparam = shellparam;
7918 savelocalvars = localvars;
7919 e = setjmp(jmploc.loc);
7924 savehandler = exception_handler;
7925 exception_handler = &jmploc;
7927 shellparam.malloc = 0;
7931 shellparam.nparam = argc - 1;
7932 shellparam.p = argv + 1;
7933 #if ENABLE_ASH_GETOPTS
7934 shellparam.optind = 1;
7935 shellparam.optoff = -1;
7937 evaltree(&func->n, flags & EV_TESTED);
7943 localvars = savelocalvars;
7944 freeparam(&shellparam);
7945 shellparam = saveparam;
7946 exception_handler = savehandler;
7948 evalskip &= ~SKIPFUNC;
7952 #if ENABLE_ASH_CMDCMD
7954 parse_command_args(char **argv, const char **path)
7967 if (c == '-' && !*cp) {
7977 /* run 'typecmd' for other options */
7988 * Make a variable a local variable. When a variable is made local, it's
7989 * value and flags are saved in a localvar structure. The saved values
7990 * will be restored when the shell function returns. We handle the name
7991 * "-" as a special case.
7996 struct localvar *lvp;
8001 lvp = ckmalloc(sizeof(struct localvar));
8002 if (LONE_DASH(name)) {
8004 p = ckmalloc(sizeof(optlist));
8005 lvp->text = memcpy(p, optlist, sizeof(optlist));
8010 vpp = hashvar(name);
8011 vp = *findvar(vpp, name);
8012 eq = strchr(name, '=');
8015 setvareq(name, VSTRFIXED);
8017 setvar(name, NULL, VSTRFIXED);
8018 vp = *vpp; /* the new variable */
8019 lvp->flags = VUNSET;
8021 lvp->text = vp->text;
8022 lvp->flags = vp->flags;
8023 vp->flags |= VSTRFIXED|VTEXTFIXED;
8029 lvp->next = localvars;
8035 * The "local" command.
8038 localcmd(int argc, char **argv)
8043 while ((name = *argv++) != NULL) {
8050 falsecmd(int argc, char **argv)
8056 truecmd(int argc, char **argv)
8062 execcmd(int argc, char **argv)
8065 iflag = 0; /* exit on error */
8068 shellexec(argv + 1, pathval(), 0);
8074 * The return command.
8077 returncmd(int argc, char **argv)
8080 * If called outside a function, do what ksh does;
8081 * skip the rest of the file.
8083 evalskip = funcnest ? SKIPFUNC : SKIPFILE;
8084 return argv[1] ? number(argv[1]) : exitstatus;
8087 /* Forward declarations for builtintab[] */
8088 static int breakcmd(int, char **);
8089 static int dotcmd(int, char **);
8090 static int evalcmd(int, char **);
8091 #if ENABLE_ASH_BUILTIN_ECHO
8092 static int echocmd(int, char **);
8094 #if ENABLE_ASH_BUILTIN_TEST
8095 static int testcmd(int, char **);
8097 static int exitcmd(int, char **);
8098 static int exportcmd(int, char **);
8099 #if ENABLE_ASH_GETOPTS
8100 static int getoptscmd(int, char **);
8102 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
8103 static int helpcmd(int argc, char **argv);
8105 #if ENABLE_ASH_MATH_SUPPORT
8106 static int letcmd(int, char **);
8108 static int readcmd(int, char **);
8109 static int setcmd(int, char **);
8110 static int shiftcmd(int, char **);
8111 static int timescmd(int, char **);
8112 static int trapcmd(int, char **);
8113 static int umaskcmd(int, char **);
8114 static int unsetcmd(int, char **);
8115 static int ulimitcmd(int, char **);
8117 #define BUILTIN_NOSPEC "0"
8118 #define BUILTIN_SPECIAL "1"
8119 #define BUILTIN_REGULAR "2"
8120 #define BUILTIN_SPEC_REG "3"
8121 #define BUILTIN_ASSIGN "4"
8122 #define BUILTIN_SPEC_ASSG "5"
8123 #define BUILTIN_REG_ASSG "6"
8124 #define BUILTIN_SPEC_REG_ASSG "7"
8126 /* make sure to keep these in proper order since it is searched via bsearch() */
8127 static const struct builtincmd builtintab[] = {
8128 { BUILTIN_SPEC_REG ".", dotcmd },
8129 { BUILTIN_SPEC_REG ":", truecmd },
8130 #if ENABLE_ASH_BUILTIN_TEST
8131 { BUILTIN_REGULAR "[", testcmd },
8132 { BUILTIN_REGULAR "[[", testcmd },
8134 #if ENABLE_ASH_ALIAS
8135 { BUILTIN_REG_ASSG "alias", aliascmd },
8138 { BUILTIN_REGULAR "bg", fg_bgcmd },
8140 { BUILTIN_SPEC_REG "break", breakcmd },
8141 { BUILTIN_REGULAR "cd", cdcmd },
8142 { BUILTIN_NOSPEC "chdir", cdcmd },
8143 #if ENABLE_ASH_CMDCMD
8144 { BUILTIN_REGULAR "command", commandcmd },
8146 { BUILTIN_SPEC_REG "continue", breakcmd },
8147 #if ENABLE_ASH_BUILTIN_ECHO
8148 { BUILTIN_REGULAR "echo", echocmd },
8150 { BUILTIN_SPEC_REG "eval", evalcmd },
8151 { BUILTIN_SPEC_REG "exec", execcmd },
8152 { BUILTIN_SPEC_REG "exit", exitcmd },
8153 { BUILTIN_SPEC_REG_ASSG "export", exportcmd },
8154 { BUILTIN_REGULAR "false", falsecmd },
8156 { BUILTIN_REGULAR "fg", fg_bgcmd },
8158 #if ENABLE_ASH_GETOPTS
8159 { BUILTIN_REGULAR "getopts", getoptscmd },
8161 { BUILTIN_NOSPEC "hash", hashcmd },
8162 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
8163 { BUILTIN_NOSPEC "help", helpcmd },
8166 { BUILTIN_REGULAR "jobs", jobscmd },
8167 { BUILTIN_REGULAR "kill", killcmd },
8169 #if ENABLE_ASH_MATH_SUPPORT
8170 { BUILTIN_NOSPEC "let", letcmd },
8172 { BUILTIN_ASSIGN "local", localcmd },
8173 { BUILTIN_NOSPEC "pwd", pwdcmd },
8174 { BUILTIN_REGULAR "read", readcmd },
8175 { BUILTIN_SPEC_REG_ASSG "readonly", exportcmd },
8176 { BUILTIN_SPEC_REG "return", returncmd },
8177 { BUILTIN_SPEC_REG "set", setcmd },
8178 { BUILTIN_SPEC_REG "shift", shiftcmd },
8179 { BUILTIN_SPEC_REG "source", dotcmd },
8180 #if ENABLE_ASH_BUILTIN_TEST
8181 { BUILTIN_REGULAR "test", testcmd },
8183 { BUILTIN_SPEC_REG "times", timescmd },
8184 { BUILTIN_SPEC_REG "trap", trapcmd },
8185 { BUILTIN_REGULAR "true", truecmd },
8186 { BUILTIN_NOSPEC "type", typecmd },
8187 { BUILTIN_NOSPEC "ulimit", ulimitcmd },
8188 { BUILTIN_REGULAR "umask", umaskcmd },
8189 #if ENABLE_ASH_ALIAS
8190 { BUILTIN_REGULAR "unalias", unaliascmd },
8192 { BUILTIN_SPEC_REG "unset", unsetcmd },
8193 { BUILTIN_REGULAR "wait", waitcmd },
8196 #define NUMBUILTINS (sizeof(builtintab) / sizeof(builtintab[0]))
8198 #define COMMANDCMD (builtintab + 5 + \
8199 2 * ENABLE_ASH_BUILTIN_TEST + \
8200 ENABLE_ASH_ALIAS + \
8201 ENABLE_ASH_JOB_CONTROL)
8202 #define EXECCMD (builtintab + 7 + \
8203 2 * ENABLE_ASH_BUILTIN_TEST + \
8204 ENABLE_ASH_ALIAS + \
8205 ENABLE_ASH_JOB_CONTROL + \
8206 ENABLE_ASH_CMDCMD + \
8207 ENABLE_ASH_BUILTIN_ECHO)
8210 * Search the table of builtin commands.
8212 static struct builtincmd *
8213 find_builtin(const char *name)
8215 struct builtincmd *bp;
8218 name, builtintab, NUMBUILTINS, sizeof(builtintab[0]),
8225 * Execute a simple command.
8227 static int back_exitstatus; /* exit status of backquoted command */
8229 isassignment(const char *p)
8231 const char *q = endofname(p);
8237 bltincmd(int argc, char **argv)
8239 /* Preserve exitstatus of a previous possible redirection
8240 * as POSIX mandates */
8241 return back_exitstatus;
8244 evalcommand(union node *cmd, int flags)
8246 static const struct builtincmd bltin = {
8249 struct stackmark smark;
8251 struct arglist arglist;
8252 struct arglist varlist;
8255 const struct strlist *sp;
8256 struct cmdentry cmdentry;
8264 struct builtincmd *bcmd;
8265 int pseudovarflag = 0;
8267 /* First expand the arguments. */
8268 TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
8269 setstackmark(&smark);
8270 back_exitstatus = 0;
8272 cmdentry.cmdtype = CMDBUILTIN;
8273 cmdentry.u.cmd = &bltin;
8274 varlist.lastp = &varlist.list;
8275 *varlist.lastp = NULL;
8276 arglist.lastp = &arglist.list;
8277 *arglist.lastp = NULL;
8280 if (cmd->ncmd.args) {
8281 bcmd = find_builtin(cmd->ncmd.args->narg.text);
8282 pseudovarflag = bcmd && IS_BUILTIN_ASSIGN(bcmd);
8285 for (argp = cmd->ncmd.args; argp; argp = argp->narg.next) {
8286 struct strlist **spp;
8288 spp = arglist.lastp;
8289 if (pseudovarflag && isassignment(argp->narg.text))
8290 expandarg(argp, &arglist, EXP_VARTILDE);
8292 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
8294 for (sp = *spp; sp; sp = sp->next)
8298 argv = nargv = stalloc(sizeof(char *) * (argc + 1));
8299 for (sp = arglist.list; sp; sp = sp->next) {
8300 TRACE(("evalcommand arg: %s\n", sp->text));
8301 *nargv++ = sp->text;
8306 if (iflag && funcnest == 0 && argc > 0)
8307 lastarg = nargv[-1];
8310 expredir(cmd->ncmd.redirect);
8311 status = redirectsafe(cmd->ncmd.redirect, REDIR_PUSH | REDIR_SAVEFD2);
8314 for (argp = cmd->ncmd.assign; argp; argp = argp->narg.next) {
8315 struct strlist **spp;
8318 spp = varlist.lastp;
8319 expandarg(argp, &varlist, EXP_VARTILDE);
8322 * Modify the command lookup path, if a PATH= assignment
8326 if (varequal(p, path))
8330 /* Print the command if xflag is set. */
8333 const char *p = " %s";
8336 dprintf(preverrout_fd, p, expandstr(ps4val()));
8339 for (n = 0; n < 2; n++) {
8341 dprintf(preverrout_fd, p, sp->text);
8349 full_write(preverrout_fd, "\n", 1);
8355 /* Now locate the command. */
8357 const char *oldpath;
8358 int cmd_flag = DO_ERR;
8363 find_command(argv[0], &cmdentry, cmd_flag, path);
8364 if (cmdentry.cmdtype == CMDUNKNOWN) {
8370 /* implement bltin and command here */
8371 if (cmdentry.cmdtype != CMDBUILTIN)
8374 spclbltin = IS_BUILTIN_SPECIAL(cmdentry.u.cmd);
8375 if (cmdentry.u.cmd == EXECCMD)
8377 #if ENABLE_ASH_CMDCMD
8378 if (cmdentry.u.cmd == COMMANDCMD) {
8380 nargv = parse_command_args(argv, &path);
8383 argc -= nargv - argv;
8385 cmd_flag |= DO_NOFUNC;
8393 /* We have a redirection error. */
8395 raise_exception(EXERROR);
8397 exitstatus = status;
8401 /* Execute the command. */
8402 switch (cmdentry.cmdtype) {
8404 /* Fork off a child process if necessary. */
8405 if (!(flags & EV_EXIT) || trap[0]) {
8407 jp = makejob(cmd, 1);
8408 if (forkshell(jp, cmd, FORK_FG) != 0) {
8409 exitstatus = waitforjob(jp);
8415 listsetvar(varlist.list, VEXPORT|VSTACK);
8416 shellexec(argv, path, cmdentry.u.index);
8420 cmdenviron = varlist.list;
8422 struct strlist *list = cmdenviron;
8424 if (spclbltin > 0 || argc == 0) {
8426 if (cmd_is_exec && argc > 1)
8429 listsetvar(list, i);
8431 if (evalbltin(cmdentry.u.cmd, argc, argv)) {
8446 exit_status = j + 128;
8447 exitstatus = exit_status;
8449 if (i == EXINT || spclbltin > 0) {
8451 longjmp(exception_handler->loc, 1);
8458 listsetvar(varlist.list, 0);
8459 if (evalfun(cmdentry.u.func, argc, argv, flags))
8465 popredir(cmd_is_exec);
8467 /* dsl: I think this is intended to be used to support
8468 * '_' in 'vi' command mode during line editing...
8469 * However I implemented that within libedit itself.
8471 setvar("_", lastarg, 0);
8472 popstackmark(&smark);
8476 evalbltin(const struct builtincmd *cmd, int argc, char **argv)
8478 char *volatile savecmdname;
8479 struct jmploc *volatile savehandler;
8480 struct jmploc jmploc;
8483 savecmdname = commandname;
8484 i = setjmp(jmploc.loc);
8487 savehandler = exception_handler;
8488 exception_handler = &jmploc;
8489 commandname = argv[0];
8491 optptr = NULL; /* initialize nextopt */
8492 exitstatus = (*cmd->builtin)(argc, argv);
8493 flush_stdout_stderr();
8495 exitstatus |= ferror(stdout);
8497 commandname = savecmdname;
8499 exception_handler = savehandler;
8505 goodname(const char *p)
8507 return !*endofname(p);
8512 * Search for a command. This is called before we fork so that the
8513 * location of the command will be available in the parent as well as
8514 * the child. The check for "goodname" is an overly conservative
8515 * check that the name will not be subject to expansion.
8518 prehash(union node *n)
8520 struct cmdentry entry;
8522 if (n->type == NCMD && n->ncmd.args && goodname(n->ncmd.args->narg.text))
8523 find_command(n->ncmd.args->narg.text, &entry, 0, pathval());
8527 /* ============ Builtin commands
8529 * Builtin commands whose functions are closely tied to evaluation
8530 * are implemented here.
8534 * Handle break and continue commands. Break, continue, and return are
8535 * all handled by setting the evalskip flag. The evaluation routines
8536 * above all check this flag, and if it is set they start skipping
8537 * commands rather than executing them. The variable skipcount is
8538 * the number of loops to break/continue, or the number of function
8539 * levels to return. (The latter is always 1.) It should probably
8540 * be an error to break out of more loops than exist, but it isn't
8541 * in the standard shell so we don't make it one here.
8544 breakcmd(int argc, char **argv)
8546 int n = argc > 1 ? number(argv[1]) : 1;
8549 ash_msg_and_raise_error(illnum, argv[1]);
8553 evalskip = (**argv == 'c') ? SKIPCONT : SKIPBREAK;
8560 /* ============ input.c
8562 * This implements the input routines used by the parser.
8565 #define EOF_NLEFT -99 /* value of parsenleft when EOF pushed back */
8568 INPUT_PUSH_FILE = 1,
8569 INPUT_NOFILE_OK = 2,
8573 * NEOF is returned by parsecmd when it encounters an end of file. It
8574 * must be distinct from NULL, so we use the address of a variable that
8575 * happens to be handy.
8577 static int plinno = 1; /* input line number */
8578 /* number of characters left in input buffer */
8579 static int parsenleft; /* copy of parsefile->nleft */
8580 static int parselleft; /* copy of parsefile->lleft */
8581 /* next character in input buffer */
8582 static char *parsenextc; /* copy of parsefile->nextc */
8584 static int checkkwd;
8585 /* values of checkkwd variable */
8586 #define CHKALIAS 0x1
8593 struct strpush *sp = parsefile->strpush;
8596 #if ENABLE_ASH_ALIAS
8598 if (parsenextc[-1] == ' ' || parsenextc[-1] == '\t') {
8599 checkkwd |= CHKALIAS;
8601 if (sp->string != sp->ap->val) {
8604 sp->ap->flag &= ~ALIASINUSE;
8605 if (sp->ap->flag & ALIASDEAD) {
8606 unalias(sp->ap->name);
8610 parsenextc = sp->prevstring;
8611 parsenleft = sp->prevnleft;
8612 /*dprintf("*** calling popstring: restoring to '%s'\n", parsenextc);*/
8613 parsefile->strpush = sp->prev;
8614 if (sp != &(parsefile->basestrpush))
8623 char *buf = parsefile->buf;
8627 #if ENABLE_FEATURE_EDITING
8628 if (!iflag || parsefile->fd)
8629 nr = safe_read(parsefile->fd, buf, BUFSIZ - 1);
8631 #if ENABLE_FEATURE_TAB_COMPLETION
8632 line_input_state->path_lookup = pathval();
8634 nr = read_line_input(cmdedit_prompt, buf, BUFSIZ, line_input_state);
8636 /* Ctrl+C pressed */
8645 if (nr < 0 && errno == 0) {
8646 /* Ctrl+D presend */
8651 nr = safe_read(parsefile->fd, buf, BUFSIZ - 1);
8655 if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
8656 int flags = fcntl(0, F_GETFL, 0);
8657 if (flags >= 0 && flags & O_NONBLOCK) {
8658 flags &=~ O_NONBLOCK;
8659 if (fcntl(0, F_SETFL, flags) >= 0) {
8660 out2str("sh: turning off NDELAY mode\n");
8670 * Refill the input buffer and return the next input character:
8672 * 1) If a string was pushed back on the input, pop it;
8673 * 2) If an EOF was pushed back (parsenleft == EOF_NLEFT) or we are reading
8674 * from a string so we can't refill the buffer, return EOF.
8675 * 3) If the is more stuff in this buffer, use it else call read to fill it.
8676 * 4) Process input up to the next newline, deleting nul characters.
8685 while (parsefile->strpush) {
8686 #if ENABLE_ASH_ALIAS
8687 if (parsenleft == -1 && parsefile->strpush->ap &&
8688 parsenextc[-1] != ' ' && parsenextc[-1] != '\t') {
8693 if (--parsenleft >= 0)
8694 return signed_char2int(*parsenextc++);
8696 if (parsenleft == EOF_NLEFT || parsefile->buf == NULL)
8698 flush_stdout_stderr();
8705 parselleft = parsenleft = EOF_NLEFT;
8712 /* delete nul characters */
8720 memmove(q, q + 1, more);
8724 parsenleft = q - parsenextc - 1;
8730 parsenleft = q - parsenextc - 1;
8742 out2str(parsenextc);
8747 return signed_char2int(*parsenextc++);
8750 #define pgetc_as_macro() (--parsenleft >= 0? signed_char2int(*parsenextc++) : preadbuffer())
8754 return pgetc_as_macro();
8757 #if ENABLE_ASH_OPTIMIZE_FOR_SIZE
8758 #define pgetc_macro() pgetc()
8760 #define pgetc_macro() pgetc_as_macro()
8764 * Same as pgetc(), but ignores PEOA.
8766 #if ENABLE_ASH_ALIAS
8774 } while (c == PEOA);
8781 return pgetc_macro();
8786 * Read a line from the script.
8789 pfgets(char *line, int len)
8795 while (--nleft > 0) {
8811 * Undo the last call to pgetc. Only one character may be pushed back.
8812 * PEOF may be pushed back.
8822 * Push a string back onto the input at this current parsefile level.
8823 * We handle aliases this way.
8826 pushstring(char *s, void *ap)
8833 /*dprintf("*** calling pushstring: %s, %d\n", s, len);*/
8834 if (parsefile->strpush) {
8835 sp = ckmalloc(sizeof(struct strpush));
8836 sp->prev = parsefile->strpush;
8837 parsefile->strpush = sp;
8839 sp = parsefile->strpush = &(parsefile->basestrpush);
8840 sp->prevstring = parsenextc;
8841 sp->prevnleft = parsenleft;
8842 #if ENABLE_ASH_ALIAS
8843 sp->ap = (struct alias *)ap;
8845 ((struct alias *)ap)->flag |= ALIASINUSE;
8855 * To handle the "." command, a stack of input files is used. Pushfile
8856 * adds a new entry to the stack and popfile restores the previous level.
8861 struct parsefile *pf;
8863 parsefile->nleft = parsenleft;
8864 parsefile->lleft = parselleft;
8865 parsefile->nextc = parsenextc;
8866 parsefile->linno = plinno;
8867 pf = ckmalloc(sizeof(*pf));
8868 pf->prev = parsefile;
8871 pf->basestrpush.prev = NULL;
8878 struct parsefile *pf = parsefile;
8887 parsefile = pf->prev;
8889 parsenleft = parsefile->nleft;
8890 parselleft = parsefile->lleft;
8891 parsenextc = parsefile->nextc;
8892 plinno = parsefile->linno;
8897 * Return to top level.
8902 while (parsefile != &basepf)
8907 * Close the file(s) that the shell is reading commands from. Called
8908 * after a fork is done.
8914 if (parsefile->fd > 0) {
8915 close(parsefile->fd);
8921 * Like setinputfile, but takes an open file descriptor. Call this with
8925 setinputfd(int fd, int push)
8927 fcntl(fd, F_SETFD, FD_CLOEXEC);
8933 if (parsefile->buf == NULL)
8934 parsefile->buf = ckmalloc(IBUFSIZ);
8935 parselleft = parsenleft = 0;
8940 * Set the input to take input from a file. If push is set, push the
8941 * old input onto the stack first.
8944 setinputfile(const char *fname, int flags)
8950 fd = open(fname, O_RDONLY);
8952 if (flags & INPUT_NOFILE_OK)
8954 ash_msg_and_raise_error("Can't open %s", fname);
8957 fd2 = copyfd(fd, 10);
8960 ash_msg_and_raise_error("Out of file descriptors");
8963 setinputfd(fd, flags & INPUT_PUSH_FILE);
8970 * Like setinputfile, but takes input from a string.
8973 setinputstring(char *string)
8977 parsenextc = string;
8978 parsenleft = strlen(string);
8979 parsefile->buf = NULL;
8985 /* ============ mail.c
8987 * Routines to check for mail.
8992 #define MAXMBOXES 10
8994 /* times of mailboxes */
8995 static time_t mailtime[MAXMBOXES];
8996 /* Set if MAIL or MAILPATH is changed. */
8997 static int mail_var_path_changed;
9000 * Print appropriate message(s) if mail has arrived.
9001 * If mail_var_path_changed is set,
9002 * then the value of MAIL has mail_var_path_changed,
9003 * so we just update the values.
9012 struct stackmark smark;
9015 setstackmark(&smark);
9016 mpath = mpathset() ? mpathval() : mailval();
9017 for (mtp = mailtime; mtp < mailtime + MAXMBOXES; mtp++) {
9018 p = padvance(&mpath, nullstr);
9023 for (q = p; *q; q++);
9028 q[-1] = '\0'; /* delete trailing '/' */
9029 if (stat(p, &statb) < 0) {
9033 if (!mail_var_path_changed && statb.st_mtime != *mtp) {
9036 pathopt ? pathopt : "you have mail"
9039 *mtp = statb.st_mtime;
9041 mail_var_path_changed = 0;
9042 popstackmark(&smark);
9046 changemail(const char *val)
9048 mail_var_path_changed++;
9051 #endif /* ASH_MAIL */
9054 /* ============ ??? */
9057 * Set the shell parameters.
9060 setparam(char **argv)
9066 for (nparam = 0; argv[nparam]; nparam++);
9067 ap = newparam = ckmalloc((nparam + 1) * sizeof(*ap));
9069 *ap++ = ckstrdup(*argv++);
9072 freeparam(&shellparam);
9073 shellparam.malloc = 1;
9074 shellparam.nparam = nparam;
9075 shellparam.p = newparam;
9076 #if ENABLE_ASH_GETOPTS
9077 shellparam.optind = 1;
9078 shellparam.optoff = -1;
9083 * Process shell options. The global variable argptr contains a pointer
9084 * to the argument list; we advance it past the options.
9087 minus_o(char *name, int val)
9092 for (i = 0; i < NOPTS; i++) {
9093 if (strcmp(name, optnames(i)) == 0) {
9098 ash_msg_and_raise_error("Illegal option -o %s", name);
9100 out1str("Current option settings\n");
9101 for (i = 0; i < NOPTS; i++)
9102 out1fmt("%-16s%s\n", optnames(i),
9103 optlist[i] ? "on" : "off");
9106 setoption(int flag, int val)
9110 for (i = 0; i < NOPTS; i++) {
9111 if (optletters(i) == flag) {
9116 ash_msg_and_raise_error("Illegal option -%c", flag);
9120 options(int cmdline)
9128 while ((p = *argptr) != NULL) {
9133 if (p[0] == '\0' || LONE_DASH(p)) {
9135 /* "-" means turn off -x and -v */
9138 /* "--" means reset params */
9139 else if (*argptr == NULL)
9142 break; /* "-" or "--" terminates options */
9144 } else if (c == '+') {
9150 while ((c = *p++) != '\0') {
9151 if (c == 'c' && cmdline) {
9152 minusc = p; /* command is after shell args*/
9153 } else if (c == 'o') {
9154 minus_o(*argptr, val);
9157 } else if (cmdline && (c == '-')) { // long options
9158 if (strcmp(p, "login") == 0)
9169 * The shift builtin command.
9172 shiftcmd(int argc, char **argv)
9179 n = number(argv[1]);
9180 if (n > shellparam.nparam)
9181 ash_msg_and_raise_error("can't shift that many");
9183 shellparam.nparam -= n;
9184 for (ap1 = shellparam.p; --n >= 0; ap1++) {
9185 if (shellparam.malloc)
9189 while ((*ap2++ = *ap1++) != NULL);
9190 #if ENABLE_ASH_GETOPTS
9191 shellparam.optind = 1;
9192 shellparam.optoff = -1;
9199 * POSIX requires that 'set' (but not export or readonly) output the
9200 * variables in lexicographic order - by the locale's collating order (sigh).
9201 * Maybe we could keep them in an ordered balanced binary tree
9202 * instead of hashed lists.
9203 * For now just roll 'em through qsort for printing...
9206 showvars(const char *sep_prefix, int on, int off)
9211 ep = listvars(on, off, &epend);
9212 qsort(ep, epend - ep, sizeof(char *), vpcmp);
9214 sep = *sep_prefix ? " " : sep_prefix;
9216 for (; ep < epend; ep++) {
9220 p = strchrnul(*ep, '=');
9223 q = single_quote(++p);
9224 out1fmt("%s%s%.*s%s\n", sep_prefix, sep, (int)(p - *ep), *ep, q);
9230 * The set command builtin.
9233 setcmd(int argc, char **argv)
9236 return showvars(nullstr, 0, VUNSET);
9240 if (*argptr != NULL) {
9247 #if ENABLE_ASH_RANDOM_SUPPORT
9248 /* Roughly copied from bash.. */
9250 change_random(const char *value)
9252 if (value == NULL) {
9253 /* "get", generate */
9256 rseed = rseed * 1103515245 + 12345;
9257 sprintf(buf, "%d", (unsigned int)((rseed & 32767)));
9258 /* set without recursion */
9259 setvar(vrandom.text, buf, VNOFUNC);
9260 vrandom.flags &= ~VNOFUNC;
9263 rseed = strtoul(value, (char **)NULL, 10);
9268 #if ENABLE_ASH_GETOPTS
9270 getopts(char *optstr, char *optvar, char **optfirst, int *param_optind, int *optoff)
9279 if (*param_optind < 1)
9281 optnext = optfirst + *param_optind - 1;
9283 if (*param_optind <= 1 || *optoff < 0 || strlen(optnext[-1]) < *optoff)
9286 p = optnext[-1] + *optoff;
9287 if (p == NULL || *p == '\0') {
9288 /* Current word is done, advance */
9290 if (p == NULL || *p != '-' || *++p == '\0') {
9297 if (LONE_DASH(p)) /* check for "--" */
9302 for (q = optstr; *q != c; ) {
9304 if (optstr[0] == ':') {
9307 err |= setvarsafe("OPTARG", s, 0);
9309 fprintf(stderr, "Illegal option -%c\n", c);
9320 if (*p == '\0' && (p = *optnext) == NULL) {
9321 if (optstr[0] == ':') {
9324 err |= setvarsafe("OPTARG", s, 0);
9327 fprintf(stderr, "No arg for -%c option\n", c);
9336 err |= setvarsafe("OPTARG", p, 0);
9339 err |= setvarsafe("OPTARG", nullstr, 0);
9341 *optoff = p ? p - *(optnext - 1) : -1;
9342 *param_optind = optnext - optfirst + 1;
9343 fmtstr(s, sizeof(s), "%d", *param_optind);
9344 err |= setvarsafe("OPTIND", s, VNOFUNC);
9347 err |= setvarsafe(optvar, s, 0);
9351 flush_stdout_stderr();
9352 raise_exception(EXERROR);
9358 * The getopts builtin. Shellparam.optnext points to the next argument
9359 * to be processed. Shellparam.optptr points to the next character to
9360 * be processed in the current argument. If shellparam.optnext is NULL,
9361 * then it's the first time getopts has been called.
9364 getoptscmd(int argc, char **argv)
9369 ash_msg_and_raise_error("Usage: getopts optstring var [arg]");
9371 optbase = shellparam.p;
9372 if (shellparam.optind > shellparam.nparam + 1) {
9373 shellparam.optind = 1;
9374 shellparam.optoff = -1;
9378 if (shellparam.optind > argc - 2) {
9379 shellparam.optind = 1;
9380 shellparam.optoff = -1;
9384 return getopts(argv[1], argv[2], optbase, &shellparam.optind,
9385 &shellparam.optoff);
9387 #endif /* ASH_GETOPTS */
9390 /* ============ Shell parser */
9392 static int tokpushback; /* last token pushed back */
9393 #define NEOF ((union node *)&tokpushback)
9394 static int parsebackquote; /* nonzero if we are inside backquotes */
9395 static int lasttoken; /* last token read */
9396 static char *wordtext; /* text of last word returned by readtoken */
9397 static struct nodelist *backquotelist;
9398 static union node *redirnode;
9399 static struct heredoc *heredoc;
9400 static int quoteflag; /* set if (part of) last token was quoted */
9402 static void raise_error_syntax(const char *) ATTRIBUTE_NORETURN;
9404 raise_error_syntax(const char *msg)
9406 ash_msg_and_raise_error("Syntax error: %s", msg);
9411 * Called when an unexpected token is read during the parse. The argument
9412 * is the token that is expected, or -1 if more than one type of token can
9413 * occur at this point.
9415 static void raise_error_unexpected_syntax(int) ATTRIBUTE_NORETURN;
9417 raise_error_unexpected_syntax(int token)
9422 l = sprintf(msg, "%s unexpected", tokname(lasttoken));
9424 sprintf(msg + l, " (expecting %s)", tokname(token));
9425 raise_error_syntax(msg);
9429 #define EOFMARKLEN 79
9432 struct heredoc *next; /* next here document in list */
9433 union node *here; /* redirection node */
9434 char *eofmark; /* string indicating end of input */
9435 int striptabs; /* if set, strip leading tabs */
9438 static struct heredoc *heredoclist; /* list of here documents to read */
9440 /* parsing is heavily cross-recursive, need these forward decls */
9441 static union node *andor(void);
9442 static union node *pipeline(void);
9443 static union node *parse_command(void);
9444 static void parseheredoc(void);
9445 static char peektoken(void);
9446 static int readtoken(void);
9451 union node *n1, *n2, *n3;
9454 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9455 if (nlflag == 2 && peektoken())
9461 if (tok == TBACKGND) {
9462 if (n2->type == NPIPE) {
9463 n2->npipe.backgnd = 1;
9465 if (n2->type != NREDIR) {
9466 n3 = stalloc(sizeof(struct nredir));
9468 n3->nredir.redirect = NULL;
9471 n2->type = NBACKGND;
9477 n3 = stalloc(sizeof(struct nbinary));
9479 n3->nbinary.ch1 = n1;
9480 n3->nbinary.ch2 = n2;
9496 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9504 pungetc(); /* push back EOF on input */
9508 raise_error_unexpected_syntax(-1);
9518 union node *n1, *n2, *n3;
9526 } else if (t == TOR) {
9532 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9534 n3 = stalloc(sizeof(struct nbinary));
9536 n3->nbinary.ch1 = n1;
9537 n3->nbinary.ch2 = n2;
9545 union node *n1, *n2, *pipenode;
9546 struct nodelist *lp, *prev;
9550 TRACE(("pipeline: entered\n"));
9551 if (readtoken() == TNOT) {
9553 checkkwd = CHKKWD | CHKALIAS;
9556 n1 = parse_command();
9557 if (readtoken() == TPIPE) {
9558 pipenode = stalloc(sizeof(struct npipe));
9559 pipenode->type = NPIPE;
9560 pipenode->npipe.backgnd = 0;
9561 lp = stalloc(sizeof(struct nodelist));
9562 pipenode->npipe.cmdlist = lp;
9566 lp = stalloc(sizeof(struct nodelist));
9567 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9568 lp->n = parse_command();
9570 } while (readtoken() == TPIPE);
9576 n2 = stalloc(sizeof(struct nnot));
9589 n = stalloc(sizeof(struct narg));
9591 n->narg.next = NULL;
9592 n->narg.text = wordtext;
9593 n->narg.backquote = backquotelist;
9598 fixredir(union node *n, const char *text, int err)
9600 TRACE(("Fix redir %s %d\n", text, err));
9602 n->ndup.vname = NULL;
9604 if (isdigit(text[0]) && text[1] == '\0')
9605 n->ndup.dupfd = text[0] - '0';
9606 else if (LONE_DASH(text))
9610 raise_error_syntax("Bad fd number");
9611 n->ndup.vname = makename();
9616 * Returns true if the text contains nothing to expand (no dollar signs
9620 noexpand(char *text)
9626 while ((c = *p++) != '\0') {
9627 if (c == CTLQUOTEMARK)
9631 else if (SIT(c, BASESYNTAX) == CCTL)
9640 union node *n = redirnode;
9642 if (readtoken() != TWORD)
9643 raise_error_unexpected_syntax(-1);
9644 if (n->type == NHERE) {
9645 struct heredoc *here = heredoc;
9651 TRACE(("Here document %d\n", n->type));
9652 if (!noexpand(wordtext) || (i = strlen(wordtext)) == 0 || i > EOFMARKLEN)
9653 raise_error_syntax("Illegal eof marker for << redirection");
9654 rmescapes(wordtext);
9655 here->eofmark = wordtext;
9657 if (heredoclist == NULL)
9660 for (p = heredoclist; p->next; p = p->next);
9663 } else if (n->type == NTOFD || n->type == NFROMFD) {
9664 fixredir(n, wordtext, 0);
9666 n->nfile.fname = makename();
9673 union node *args, **app;
9674 union node *n = NULL;
9675 union node *vars, **vpp;
9676 union node **rpp, *redir;
9686 savecheckkwd = CHKALIAS;
9688 checkkwd = savecheckkwd;
9689 switch (readtoken()) {
9691 n = stalloc(sizeof(struct narg));
9693 n->narg.text = wordtext;
9694 n->narg.backquote = backquotelist;
9695 if (savecheckkwd && isassignment(wordtext)) {
9697 vpp = &n->narg.next;
9700 app = &n->narg.next;
9705 *rpp = n = redirnode;
9706 rpp = &n->nfile.next;
9707 parsefname(); /* read name of redirection file */
9710 if (args && app == &args->narg.next
9713 struct builtincmd *bcmd;
9716 /* We have a function */
9717 if (readtoken() != TRP)
9718 raise_error_unexpected_syntax(TRP);
9719 name = n->narg.text;
9721 || ((bcmd = find_builtin(name)) && IS_BUILTIN_SPECIAL(bcmd))
9723 raise_error_syntax("Bad function name");
9726 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9727 n->narg.next = parse_command();
9740 n = stalloc(sizeof(struct ncmd));
9742 n->ncmd.args = args;
9743 n->ncmd.assign = vars;
9744 n->ncmd.redirect = redir;
9751 union node *n1, *n2;
9752 union node *ap, **app;
9753 union node *cp, **cpp;
9754 union node *redir, **rpp;
9761 switch (readtoken()) {
9763 raise_error_unexpected_syntax(-1);
9766 n1 = stalloc(sizeof(struct nif));
9768 n1->nif.test = list(0);
9769 if (readtoken() != TTHEN)
9770 raise_error_unexpected_syntax(TTHEN);
9771 n1->nif.ifpart = list(0);
9773 while (readtoken() == TELIF) {
9774 n2->nif.elsepart = stalloc(sizeof(struct nif));
9775 n2 = n2->nif.elsepart;
9777 n2->nif.test = list(0);
9778 if (readtoken() != TTHEN)
9779 raise_error_unexpected_syntax(TTHEN);
9780 n2->nif.ifpart = list(0);
9782 if (lasttoken == TELSE)
9783 n2->nif.elsepart = list(0);
9785 n2->nif.elsepart = NULL;
9793 n1 = stalloc(sizeof(struct nbinary));
9794 n1->type = (lasttoken == TWHILE) ? NWHILE : NUNTIL;
9795 n1->nbinary.ch1 = list(0);
9798 TRACE(("expecting DO got %s %s\n", tokname(got),
9799 got == TWORD ? wordtext : ""));
9800 raise_error_unexpected_syntax(TDO);
9802 n1->nbinary.ch2 = list(0);
9807 if (readtoken() != TWORD || quoteflag || ! goodname(wordtext))
9808 raise_error_syntax("Bad for loop variable");
9809 n1 = stalloc(sizeof(struct nfor));
9811 n1->nfor.var = wordtext;
9812 checkkwd = CHKKWD | CHKALIAS;
9813 if (readtoken() == TIN) {
9815 while (readtoken() == TWORD) {
9816 n2 = stalloc(sizeof(struct narg));
9818 n2->narg.text = wordtext;
9819 n2->narg.backquote = backquotelist;
9821 app = &n2->narg.next;
9825 if (lasttoken != TNL && lasttoken != TSEMI)
9826 raise_error_unexpected_syntax(-1);
9828 n2 = stalloc(sizeof(struct narg));
9830 n2->narg.text = (char *)dolatstr;
9831 n2->narg.backquote = NULL;
9832 n2->narg.next = NULL;
9835 * Newline or semicolon here is optional (but note
9836 * that the original Bourne shell only allowed NL).
9838 if (lasttoken != TNL && lasttoken != TSEMI)
9841 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9842 if (readtoken() != TDO)
9843 raise_error_unexpected_syntax(TDO);
9844 n1->nfor.body = list(0);
9848 n1 = stalloc(sizeof(struct ncase));
9850 if (readtoken() != TWORD)
9851 raise_error_unexpected_syntax(TWORD);
9852 n1->ncase.expr = n2 = stalloc(sizeof(struct narg));
9854 n2->narg.text = wordtext;
9855 n2->narg.backquote = backquotelist;
9856 n2->narg.next = NULL;
9858 checkkwd = CHKKWD | CHKALIAS;
9859 } while (readtoken() == TNL);
9860 if (lasttoken != TIN)
9861 raise_error_unexpected_syntax(TIN);
9862 cpp = &n1->ncase.cases;
9864 checkkwd = CHKNL | CHKKWD;
9866 while (t != TESAC) {
9867 if (lasttoken == TLP)
9869 *cpp = cp = stalloc(sizeof(struct nclist));
9871 app = &cp->nclist.pattern;
9873 *app = ap = stalloc(sizeof(struct narg));
9875 ap->narg.text = wordtext;
9876 ap->narg.backquote = backquotelist;
9877 if (readtoken() != TPIPE)
9879 app = &ap->narg.next;
9882 ap->narg.next = NULL;
9883 if (lasttoken != TRP)
9884 raise_error_unexpected_syntax(TRP);
9885 cp->nclist.body = list(2);
9887 cpp = &cp->nclist.next;
9889 checkkwd = CHKNL | CHKKWD;
9893 raise_error_unexpected_syntax(TENDCASE);
9900 n1 = stalloc(sizeof(struct nredir));
9901 n1->type = NSUBSHELL;
9902 n1->nredir.n = list(0);
9903 n1->nredir.redirect = NULL;
9916 if (readtoken() != t)
9917 raise_error_unexpected_syntax(t);
9920 /* Now check for redirection which may follow command */
9921 checkkwd = CHKKWD | CHKALIAS;
9923 while (readtoken() == TREDIR) {
9924 *rpp = n2 = redirnode;
9925 rpp = &n2->nfile.next;
9931 if (n1->type != NSUBSHELL) {
9932 n2 = stalloc(sizeof(struct nredir));
9937 n1->nredir.redirect = redir;
9943 * If eofmark is NULL, read a word or a redirection symbol. If eofmark
9944 * is not NULL, read a here document. In the latter case, eofmark is the
9945 * word which marks the end of the document and striptabs is true if
9946 * leading tabs should be stripped from the document. The argument firstc
9947 * is the first character of the input token or document.
9949 * Because C does not have internal subroutines, I have simulated them
9950 * using goto's to implement the subroutine linkage. The following macros
9951 * will run code that appears at the end of readtoken1.
9954 static int parsebackquote; /* nonzero if we are inside backquotes */
9956 #define CHECKEND() {goto checkend; checkend_return:;}
9957 #define PARSEREDIR() {goto parseredir; parseredir_return:;}
9958 #define PARSESUB() {goto parsesub; parsesub_return:;}
9959 #define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
9960 #define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
9961 #define PARSEARITH() {goto parsearith; parsearith_return:;}
9964 readtoken1(int firstc, int syntax, char *eofmark, int striptabs)
9969 char line[EOFMARKLEN + 1];
9970 struct nodelist *bqlist = 0;
9973 int varnest = 0; /* levels of variables expansion */
9974 int arinest = 0; /* levels of arithmetic expansion */
9975 int parenlevel = 0; /* levels of parens in arithmetic */
9976 int dqvarnest = 0; /* levels of variables expansion within double quotes */
9978 int prevsyntax = 0; /* syntax before arithmetic */
9980 /* Avoid longjmp clobbering */
9993 startlinno = plinno;
9995 if (syntax == DQSYNTAX)
10004 STARTSTACKSTR(out);
10005 loop: { /* for each line, until end of word */
10006 CHECKEND(); /* set c to PEOF if at end of here document */
10007 for (;;) { /* until end of line or end of word */
10008 CHECKSTRSPACE(4, out); /* permit 4 calls to USTPUTC */
10009 switch (SIT(c, syntax)) {
10010 case CNL: /* '\n' */
10011 if (syntax == BASESYNTAX)
10012 goto endword; /* exit outer loop */
10018 goto loop; /* continue outer loop */
10023 if (eofmark == NULL || dblquote)
10024 USTPUTC(CTLESC, out);
10027 case CBACK: /* backslash */
10030 USTPUTC(CTLESC, out);
10031 USTPUTC('\\', out);
10033 } else if (c == '\n') {
10038 c != '\\' && c != '`' &&
10043 USTPUTC(CTLESC, out);
10044 USTPUTC('\\', out);
10046 if (SIT(c, SQSYNTAX) == CCTL)
10047 USTPUTC(CTLESC, out);
10055 if (eofmark == NULL) {
10056 USTPUTC(CTLQUOTEMARK, out);
10064 if (eofmark != NULL && arinest == 0
10069 if (dqvarnest == 0) {
10070 syntax = BASESYNTAX;
10077 case CVAR: /* '$' */
10078 PARSESUB(); /* parse substitution */
10080 case CENDVAR: /* '}' */
10083 if (dqvarnest > 0) {
10086 USTPUTC(CTLENDVAR, out);
10091 #if ENABLE_ASH_MATH_SUPPORT
10092 case CLP: /* '(' in arithmetic */
10096 case CRP: /* ')' in arithmetic */
10097 if (parenlevel > 0) {
10101 if (pgetc() == ')') {
10102 if (--arinest == 0) {
10103 USTPUTC(CTLENDARI, out);
10104 syntax = prevsyntax;
10105 if (syntax == DQSYNTAX)
10113 * unbalanced parens
10114 * (don't 2nd guess - no error)
10122 case CBQUOTE: /* '`' */
10126 goto endword; /* exit outer loop */
10131 goto endword; /* exit outer loop */
10132 #if ENABLE_ASH_ALIAS
10142 #if ENABLE_ASH_MATH_SUPPORT
10143 if (syntax == ARISYNTAX)
10144 raise_error_syntax("Missing '))'");
10146 if (syntax != BASESYNTAX && !parsebackquote && eofmark == NULL)
10147 raise_error_syntax("Unterminated quoted string");
10148 if (varnest != 0) {
10149 startlinno = plinno;
10151 raise_error_syntax("Missing '}'");
10153 USTPUTC('\0', out);
10154 len = out - (char *)stackblock();
10155 out = stackblock();
10156 if (eofmark == NULL) {
10157 if ((c == '>' || c == '<')
10160 && (*out == '\0' || isdigit(*out))) {
10162 return lasttoken = TREDIR;
10167 quoteflag = quotef;
10168 backquotelist = bqlist;
10169 grabstackblock(len);
10173 /* end of readtoken routine */
10176 * Check to see whether we are at the end of the here document. When this
10177 * is called, c is set to the first character of the next input line. If
10178 * we are at the end of the here document, this routine sets the c to PEOF.
10182 #if ENABLE_ASH_ALIAS
10188 while (c == '\t') {
10192 if (c == *eofmark) {
10193 if (pfgets(line, sizeof(line)) != NULL) {
10197 for (q = eofmark + 1; *q && *p == *q; p++, q++);
10198 if (*p == '\n' && *q == '\0') {
10201 needprompt = doprompt;
10203 pushstring(line, NULL);
10208 goto checkend_return;
10212 * Parse a redirection operator. The variable "out" points to a string
10213 * specifying the fd to be redirected. The variable "c" contains the
10214 * first character of the redirection operator.
10220 np = stalloc(sizeof(struct nfile));
10225 np->type = NAPPEND;
10227 np->type = NCLOBBER;
10234 } else { /* c == '<' */
10239 if (sizeof(struct nfile) != sizeof(struct nhere)) {
10240 np = stalloc(sizeof(struct nhere));
10244 heredoc = stalloc(sizeof(struct heredoc));
10245 heredoc->here = np;
10248 heredoc->striptabs = 1;
10250 heredoc->striptabs = 0;
10256 np->type = NFROMFD;
10260 np->type = NFROMTO;
10270 np->nfile.fd = fd - '0';
10272 goto parseredir_return;
10276 * Parse a substitution. At this point, we have read the dollar sign
10277 * and nothing else.
10280 /* is_special(c) evaluates to 1 for c in "!#$*-0123456789?@"; 0 otherwise
10281 * (assuming ascii char codes, as the original implementation did) */
10282 #define is_special(c) \
10283 ((((unsigned int)c) - 33 < 32) \
10284 && ((0xc1ff920dUL >> (((unsigned int)c) - 33)) & 1))
10290 static const char types[] = "}-+?=";
10294 c <= PEOA_OR_PEOF ||
10295 (c != '(' && c != '{' && !is_name(c) && !is_special(c))
10299 } else if (c == '(') { /* $(command) or $((arith)) */
10300 if (pgetc() == '(') {
10301 #if ENABLE_ASH_MATH_SUPPORT
10304 raise_error_syntax("We unsupport $((arith))");
10311 USTPUTC(CTLVAR, out);
10312 typeloc = out - (char *)stackblock();
10313 USTPUTC(VSNORMAL, out);
10314 subtype = VSNORMAL;
10322 subtype = VSLENGTH;
10326 if (c > PEOA_OR_PEOF && is_name(c)) {
10330 } while (c > PEOA_OR_PEOF && is_in_name(c));
10331 } else if (isdigit(c)) {
10335 } while (isdigit(c));
10336 } else if (is_special(c)) {
10340 badsub: raise_error_syntax("Bad substitution");
10344 if (subtype == 0) {
10351 p = strchr(types, c);
10354 subtype = p - types + VSNORMAL;
10360 subtype = c == '#' ? VSTRIMLEFT :
10373 if (dblquote || arinest)
10375 *((char *)stackblock() + typeloc) = subtype | flags;
10376 if (subtype != VSNORMAL) {
10378 if (dblquote || arinest) {
10383 goto parsesub_return;
10387 * Called to parse command substitutions. Newstyle is set if the command
10388 * is enclosed inside $(...); nlpp is a pointer to the head of the linked
10389 * list of commands (passed by reference), and savelen is the number of
10390 * characters on the top of the stack which must be preserved.
10393 struct nodelist **nlpp;
10396 char *volatile str;
10397 struct jmploc jmploc;
10398 struct jmploc *volatile savehandler;
10400 int saveprompt = 0;
10402 (void) &saveprompt;
10405 savepbq = parsebackquote;
10406 if (setjmp(jmploc.loc)) {
10409 parsebackquote = 0;
10410 exception_handler = savehandler;
10411 longjmp(exception_handler->loc, 1);
10415 savelen = out - (char *)stackblock();
10417 str = ckmalloc(savelen);
10418 memcpy(str, stackblock(), savelen);
10420 savehandler = exception_handler;
10421 exception_handler = &jmploc;
10424 /* We must read until the closing backquote, giving special
10425 treatment to some slashes, and then push the string and
10426 reread it as input, interpreting it normally. */
10433 STARTSTACKSTR(pout);
10450 * If eating a newline, avoid putting
10451 * the newline into the new character
10452 * stream (via the STPUTC after the
10457 if (pc != '\\' && pc != '`' && pc != '$'
10458 && (!dblquote || pc != '"'))
10459 STPUTC('\\', pout);
10460 if (pc > PEOA_OR_PEOF) {
10466 #if ENABLE_ASH_ALIAS
10469 startlinno = plinno;
10470 raise_error_syntax("EOF in backquote substitution");
10474 needprompt = doprompt;
10483 STPUTC('\0', pout);
10484 psavelen = pout - (char *)stackblock();
10485 if (psavelen > 0) {
10486 pstr = grabstackstr(pout);
10487 setinputstring(pstr);
10492 nlpp = &(*nlpp)->next;
10493 *nlpp = stalloc(sizeof(**nlpp));
10494 (*nlpp)->next = NULL;
10495 parsebackquote = oldstyle;
10498 saveprompt = doprompt;
10505 doprompt = saveprompt;
10506 else if (readtoken() != TRP)
10507 raise_error_unexpected_syntax(TRP);
10512 * Start reading from old file again, ignoring any pushed back
10513 * tokens left from the backquote parsing
10518 while (stackblocksize() <= savelen)
10520 STARTSTACKSTR(out);
10522 memcpy(out, str, savelen);
10523 STADJUST(savelen, out);
10529 parsebackquote = savepbq;
10530 exception_handler = savehandler;
10531 if (arinest || dblquote)
10532 USTPUTC(CTLBACKQ | CTLQUOTE, out);
10534 USTPUTC(CTLBACKQ, out);
10536 goto parsebackq_oldreturn;
10537 goto parsebackq_newreturn;
10540 #if ENABLE_ASH_MATH_SUPPORT
10542 * Parse an arithmetic expansion (indicate start of one and set state)
10545 if (++arinest == 1) {
10546 prevsyntax = syntax;
10547 syntax = ARISYNTAX;
10548 USTPUTC(CTLARI, out);
10555 * we collapse embedded arithmetic expansion to
10556 * parenthesis, which should be equivalent
10560 goto parsearith_return;
10564 } /* end of readtoken */
10567 * Read the next input token.
10568 * If the token is a word, we set backquotelist to the list of cmds in
10569 * backquotes. We set quoteflag to true if any part of the word was
10571 * If the token is TREDIR, then we set redirnode to a structure containing
10573 * In all cases, the variable startlinno is set to the number of the line
10574 * on which the token starts.
10576 * [Change comment: here documents and internal procedures]
10577 * [Readtoken shouldn't have any arguments. Perhaps we should make the
10578 * word parsing code into a separate routine. In this case, readtoken
10579 * doesn't need to have any internal procedures, but parseword does.
10580 * We could also make parseoperator in essence the main routine, and
10581 * have parseword (readtoken1?) handle both words and redirection.]
10583 #define NEW_xxreadtoken
10584 #ifdef NEW_xxreadtoken
10585 /* singles must be first! */
10586 static const char xxreadtoken_chars[7] = { '\n', '(', ')', '&', '|', ';', 0 };
10588 static const char xxreadtoken_tokens[] = {
10589 TNL, TLP, TRP, /* only single occurrence allowed */
10590 TBACKGND, TPIPE, TSEMI, /* if single occurrence */
10591 TEOF, /* corresponds to trailing nul */
10592 TAND, TOR, TENDCASE, /* if double occurrence */
10595 #define xxreadtoken_doubles \
10596 (sizeof(xxreadtoken_tokens) - sizeof(xxreadtoken_chars))
10597 #define xxreadtoken_singles \
10598 (sizeof(xxreadtoken_chars) - xxreadtoken_doubles - 1)
10612 startlinno = plinno;
10613 for (;;) { /* until token or start of word found */
10616 if ((c != ' ') && (c != '\t')
10617 #if ENABLE_ASH_ALIAS
10622 while ((c = pgetc()) != '\n' && c != PEOF);
10624 } else if (c == '\\') {
10625 if (pgetc() != '\n') {
10629 startlinno = ++plinno;
10634 = xxreadtoken_chars + sizeof(xxreadtoken_chars) - 1;
10639 needprompt = doprompt;
10642 p = strchr(xxreadtoken_chars, c);
10645 return readtoken1(c, BASESYNTAX, (char *) NULL, 0);
10648 if (p - xxreadtoken_chars >= xxreadtoken_singles) {
10649 if (pgetc() == *p) { /* double occurrence? */
10650 p += xxreadtoken_doubles + 1;
10656 return lasttoken = xxreadtoken_tokens[p - xxreadtoken_chars];
10662 #define RETURN(token) return lasttoken = token
10675 startlinno = plinno;
10676 for (;;) { /* until token or start of word found */
10679 case ' ': case '\t':
10680 #if ENABLE_ASH_ALIAS
10685 while ((c = pgetc()) != '\n' && c != PEOF);
10689 if (pgetc() == '\n') {
10690 startlinno = ++plinno;
10699 needprompt = doprompt;
10704 if (pgetc() == '&')
10709 if (pgetc() == '|')
10714 if (pgetc() == ';')
10727 return readtoken1(c, BASESYNTAX, (char *)NULL, 0);
10730 #endif /* NEW_xxreadtoken */
10737 int alreadyseen = tokpushback;
10740 #if ENABLE_ASH_ALIAS
10749 if (checkkwd & CHKNL) {
10756 if (t != TWORD || quoteflag) {
10761 * check for keywords
10763 if (checkkwd & CHKKWD) {
10764 const char *const *pp;
10766 pp = findkwd(wordtext);
10768 lasttoken = t = pp - tokname_array;
10769 TRACE(("keyword %s recognized\n", tokname(t)));
10774 if (checkkwd & CHKALIAS) {
10775 #if ENABLE_ASH_ALIAS
10777 ap = lookupalias(wordtext, 1);
10780 pushstring(ap->val, ap);
10790 TRACE(("token %s %s\n", tokname(t), t == TWORD ? wordtext : ""));
10792 TRACE(("reread token %s %s\n", tokname(t), t == TWORD ? wordtext : ""));
10804 return tokname_array[t][0];
10808 * Read and parse a command. Returns NEOF on end of file. (NULL is a
10809 * valid parse tree indicating a blank line.)
10811 static union node *
10812 parsecmd(int interact)
10817 doprompt = interact;
10819 setprompt(doprompt);
10831 * Input any here documents.
10836 struct heredoc *here;
10839 here = heredoclist;
10846 readtoken1(pgetc(), here->here->type == NHERE? SQSYNTAX : DQSYNTAX,
10847 here->eofmark, here->striptabs);
10848 n = stalloc(sizeof(struct narg));
10849 n->narg.type = NARG;
10850 n->narg.next = NULL;
10851 n->narg.text = wordtext;
10852 n->narg.backquote = backquotelist;
10853 here->here->nhere.doc = n;
10860 * called by editline -- any expansions to the prompt should be added here.
10862 #if ENABLE_ASH_EXPAND_PRMT
10863 static const char *
10864 expandstr(const char *ps)
10868 /* XXX Fix (char *) cast. */
10869 setinputstring((char *)ps);
10870 readtoken1(pgetc(), DQSYNTAX, nullstr, 0);
10873 n.narg.type = NARG;
10874 n.narg.next = NULL;
10875 n.narg.text = wordtext;
10876 n.narg.backquote = backquotelist;
10878 expandarg(&n, NULL, 0);
10879 return stackblock();
10884 * Execute a command or commands contained in a string.
10887 evalstring(char *s, int mask)
10890 struct stackmark smark;
10894 setstackmark(&smark);
10897 while ((n = parsecmd(0)) != NEOF) {
10899 popstackmark(&smark);
10912 * The eval command.
10915 evalcmd(int argc, char **argv)
10924 STARTSTACKSTR(concat);
10927 concat = stack_putstr(p, concat);
10931 STPUTC(' ', concat);
10933 STPUTC('\0', concat);
10934 p = grabstackstr(concat);
10936 evalstring(p, ~SKIPEVAL);
10943 * Read and execute commands. "Top" is nonzero for the top level command
10944 * loop; it turns on prompting if the shell is interactive.
10950 struct stackmark smark;
10954 TRACE(("cmdloop(%d) called\n", top));
10958 setstackmark(&smark);
10961 showjobs(stderr, SHOW_CHANGED);
10964 if (iflag && top) {
10966 #if ENABLE_ASH_MAIL
10970 n = parsecmd(inter);
10971 /* showtree(n); DEBUG */
10973 if (!top || numeof >= 50)
10975 if (!stoppedjobs()) {
10978 out2str("\nUse \"exit\" to leave shell.\n");
10981 } else if (nflag == 0) {
10982 job_warning = (job_warning == 2) ? 1 : 0;
10986 popstackmark(&smark);
10991 return skip & SKIPEVAL;
10998 * Take commands from a file. To be compatible we should do a path
10999 * search for the file, which is necessary to find sub-commands.
11002 find_dot_file(char *name)
11005 const char *path = pathval();
11008 /* don't try this for absolute or relative paths */
11009 if (strchr(name, '/'))
11012 while ((fullname = padvance(&path, name)) != NULL) {
11013 if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) {
11015 * Don't bother freeing here, since it will
11016 * be freed by the caller.
11020 stunalloc(fullname);
11023 /* not found in the PATH */
11024 ash_msg_and_raise_error("%s: not found", name);
11029 dotcmd(int argc, char **argv)
11031 struct strlist *sp;
11032 volatile struct shparam saveparam;
11035 for (sp = cmdenviron; sp; sp = sp->next)
11036 setvareq(xstrdup(sp->text), VSTRFIXED | VTEXTFIXED);
11038 if (argc >= 2) { /* That's what SVR2 does */
11041 fullname = find_dot_file(argv[1]);
11044 saveparam = shellparam;
11045 shellparam.malloc = 0;
11046 shellparam.nparam = argc - 2;
11047 shellparam.p = argv + 2;
11050 setinputfile(fullname, INPUT_PUSH_FILE);
11051 commandname = fullname;
11056 freeparam(&shellparam);
11057 shellparam = saveparam;
11059 status = exitstatus;
11065 exitcmd(int argc, char **argv)
11070 exitstatus = number(argv[1]);
11071 raise_exception(EXEXIT);
11075 #if ENABLE_ASH_BUILTIN_ECHO
11077 echocmd(int argc, char **argv)
11079 return bb_echo(argv);
11083 #if ENABLE_ASH_BUILTIN_TEST
11085 testcmd(int argc, char **argv)
11087 return bb_test(argc, argv);
11092 * Read a file containing shell functions.
11095 readcmdfile(char *name)
11097 setinputfile(name, INPUT_PUSH_FILE);
11103 /* ============ find_command inplementation */
11106 * Resolve a command name. If you change this routine, you may have to
11107 * change the shellexec routine as well.
11110 find_command(char *name, struct cmdentry *entry, int act, const char *path)
11112 struct tblentry *cmdp;
11119 struct builtincmd *bcmd;
11121 /* If name contains a slash, don't use PATH or hash table */
11122 if (strchr(name, '/') != NULL) {
11123 entry->u.index = -1;
11124 if (act & DO_ABS) {
11125 while (stat(name, &statb) < 0) {
11127 if (errno == EINTR)
11130 entry->cmdtype = CMDUNKNOWN;
11134 entry->cmdtype = CMDNORMAL;
11138 #if ENABLE_FEATURE_SH_STANDALONE_SHELL
11139 if (find_applet_by_name(name)) {
11140 entry->cmdtype = CMDNORMAL;
11141 entry->u.index = -1;
11146 if (is_safe_applet(name)) {
11147 entry->cmdtype = CMDNORMAL;
11148 entry->u.index = -1;
11152 updatetbl = (path == pathval());
11155 if (strstr(path, "%builtin") != NULL)
11156 act |= DO_ALTBLTIN;
11159 /* If name is in the table, check answer will be ok */
11160 cmdp = cmdlookup(name, 0);
11161 if (cmdp != NULL) {
11164 switch (cmdp->cmdtype) {
11182 } else if (cmdp->rehash == 0)
11183 /* if not invalidated by cd, we're done */
11187 /* If %builtin not in path, check for builtin next */
11188 bcmd = find_builtin(name);
11190 if (IS_BUILTIN_REGULAR(bcmd))
11191 goto builtin_success;
11192 if (act & DO_ALTPATH) {
11193 if (!(act & DO_ALTBLTIN))
11194 goto builtin_success;
11195 } else if (builtinloc <= 0) {
11196 goto builtin_success;
11200 /* We have to search path. */
11201 prev = -1; /* where to start */
11202 if (cmdp && cmdp->rehash) { /* doing a rehash */
11203 if (cmdp->cmdtype == CMDBUILTIN)
11206 prev = cmdp->param.index;
11212 while ((fullname = padvance(&path, name)) != NULL) {
11213 stunalloc(fullname);
11216 if (prefix(pathopt, "builtin")) {
11218 goto builtin_success;
11220 } else if (!(act & DO_NOFUNC) &&
11221 prefix(pathopt, "func")) {
11222 /* handled below */
11224 /* ignore unimplemented options */
11228 /* if rehash, don't redo absolute path names */
11229 if (fullname[0] == '/' && idx <= prev) {
11232 TRACE(("searchexec \"%s\": no change\n", name));
11235 while (stat(fullname, &statb) < 0) {
11237 if (errno == EINTR)
11240 if (errno != ENOENT && errno != ENOTDIR)
11244 e = EACCES; /* if we fail, this will be the error */
11245 if (!S_ISREG(statb.st_mode))
11247 if (pathopt) { /* this is a %func directory */
11248 stalloc(strlen(fullname) + 1);
11249 readcmdfile(fullname);
11250 cmdp = cmdlookup(name, 0);
11251 if (cmdp == NULL || cmdp->cmdtype != CMDFUNCTION)
11252 ash_msg_and_raise_error("%s not defined in %s", name, fullname);
11253 stunalloc(fullname);
11256 TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
11258 entry->cmdtype = CMDNORMAL;
11259 entry->u.index = idx;
11263 cmdp = cmdlookup(name, 1);
11264 cmdp->cmdtype = CMDNORMAL;
11265 cmdp->param.index = idx;
11270 /* We failed. If there was an entry for this command, delete it */
11271 if (cmdp && updatetbl)
11272 delete_cmd_entry();
11274 ash_msg("%s: %s", name, errmsg(e, "not found"));
11275 entry->cmdtype = CMDUNKNOWN;
11280 entry->cmdtype = CMDBUILTIN;
11281 entry->u.cmd = bcmd;
11285 cmdp = cmdlookup(name, 1);
11286 cmdp->cmdtype = CMDBUILTIN;
11287 cmdp->param.cmd = bcmd;
11291 entry->cmdtype = cmdp->cmdtype;
11292 entry->u = cmdp->param;
11296 /* ============ trap.c */
11299 * The trap builtin.
11302 trapcmd(int argc, char **argv)
11311 for (signo = 0; signo < NSIG; signo++) {
11312 if (trap[signo] != NULL) {
11315 sn = get_signame(signo);
11316 out1fmt("trap -- %s %s\n",
11317 single_quote(trap[signo]), sn);
11327 signo = get_signum(*ap);
11329 ash_msg_and_raise_error("%s: bad trap", *ap);
11332 if (LONE_DASH(action))
11335 action = ckstrdup(action);
11339 trap[signo] = action;
11349 /* ============ Builtins */
11351 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
11353 * Lists available builtins
11356 helpcmd(int argc, char **argv)
11360 out1fmt("\nBuilt-in commands:\n-------------------\n");
11361 for (col = 0, i = 0; i < NUMBUILTINS; i++) {
11362 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '),
11363 builtintab[i].name + 1);
11369 #if ENABLE_FEATURE_SH_STANDALONE_SHELL
11370 for (i = 0; i < NUM_APPLETS; i++) {
11371 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '), applets[i].name);
11379 return EXIT_SUCCESS;
11381 #endif /* FEATURE_SH_EXTRA_QUIET */
11384 * The export and readonly commands.
11387 exportcmd(int argc, char **argv)
11393 int flag = argv[0][0] == 'r'? VREADONLY : VEXPORT;
11395 if (nextopt("p") != 'p') {
11400 p = strchr(name, '=');
11404 vp = *findvar(hashvar(name), name);
11410 setvar(name, p, flag);
11411 } while ((name = *++aptr) != NULL);
11415 showvars(argv[0], flag, 0);
11420 * Delete a function if it exists.
11423 unsetfunc(const char *name)
11425 struct tblentry *cmdp;
11427 cmdp = cmdlookup(name, 0);
11428 if (cmdp!= NULL && cmdp->cmdtype == CMDFUNCTION)
11429 delete_cmd_entry();
11433 * The unset builtin command. We unset the function before we unset the
11434 * variable to allow a function to be unset when there is a readonly variable
11435 * with the same name.
11438 unsetcmd(int argc, char **argv)
11445 while ((i = nextopt("vf")) != '\0') {
11449 for (ap = argptr; *ap; ap++) {
11465 #include <sys/times.h>
11467 static const unsigned char timescmd_str[] = {
11468 ' ', offsetof(struct tms, tms_utime),
11469 '\n', offsetof(struct tms, tms_stime),
11470 ' ', offsetof(struct tms, tms_cutime),
11471 '\n', offsetof(struct tms, tms_cstime),
11476 timescmd(int ac, char **av)
11478 long clk_tck, s, t;
11479 const unsigned char *p;
11482 clk_tck = sysconf(_SC_CLK_TCK);
11487 t = *(clock_t *)(((char *) &buf) + p[1]);
11489 out1fmt("%ldm%ld.%.3lds%c",
11491 ((t - s * clk_tck) * 1000) / clk_tck,
11493 } while (*(p += 2));
11498 #if ENABLE_ASH_MATH_SUPPORT
11500 dash_arith(const char *s)
11506 result = arith(s, &errcode);
11509 ash_msg_and_raise_error("exponent less than 0");
11511 ash_msg_and_raise_error("divide by zero");
11513 ash_msg_and_raise_error("expression recursion loop detected");
11514 raise_error_syntax(s);
11522 * The let builtin. partial stolen from GNU Bash, the Bourne Again SHell.
11523 * Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
11525 * Copyright (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
11528 letcmd(int argc, char **argv)
11535 ash_msg_and_raise_error("expression expected");
11536 for (ap = argv + 1; *ap; ap++) {
11537 i = dash_arith(*ap);
11542 #endif /* ASH_MATH_SUPPORT */
11545 /* ============ miscbltin.c
11547 * Miscellaneous builtins.
11552 #if defined(__GLIBC__) && __GLIBC__ == 2 && __GLIBC_MINOR__ < 1
11553 typedef enum __rlimit_resource rlim_t;
11557 * The read builtin. The -e option causes backslashes to escape the
11558 * following character.
11560 * This uses unbuffered input, which may be avoidable in some cases.
11563 readcmd(int argc, char **argv)
11575 #if ENABLE_ASH_READ_NCHARS
11579 struct termios tty, old_tty;
11581 #if ENABLE_ASH_READ_TIMEOUT
11585 ts.tv_sec = ts.tv_usec = 0;
11590 #if ENABLE_ASH_READ_NCHARS && ENABLE_ASH_READ_TIMEOUT
11591 while ((i = nextopt("p:rt:n:s")) != '\0')
11592 #elif ENABLE_ASH_READ_NCHARS
11593 while ((i = nextopt("p:rn:s")) != '\0')
11594 #elif ENABLE_ASH_READ_TIMEOUT
11595 while ((i = nextopt("p:rt:")) != '\0')
11597 while ((i = nextopt("p:r")) != '\0')
11602 prompt = optionarg;
11604 #if ENABLE_ASH_READ_NCHARS
11606 nchars = strtol(optionarg, &p, 10);
11608 ash_msg_and_raise_error("invalid count");
11609 nch_flag = (nchars > 0);
11615 #if ENABLE_ASH_READ_TIMEOUT
11617 ts.tv_sec = strtol(optionarg, &p, 10);
11623 ts.tv_usec = strtol(p, &p2, 10);
11625 ash_msg_and_raise_error("invalid timeout");
11627 /* normalize to usec */
11629 ash_msg_and_raise_error("invalid timeout");
11630 while (scale++ < 6)
11634 ash_msg_and_raise_error("invalid timeout");
11636 if ( ! ts.tv_sec && ! ts.tv_usec)
11637 ash_msg_and_raise_error("invalid timeout");
11647 if (prompt && isatty(0)) {
11652 ash_msg_and_raise_error("arg count");
11653 ifs = bltinlookup("IFS");
11656 #if ENABLE_ASH_READ_NCHARS
11657 if (nch_flag || silent) {
11658 tcgetattr(0, &tty);
11661 tty.c_lflag &= ~ICANON;
11662 tty.c_cc[VMIN] = nchars;
11665 tty.c_lflag &= ~(ECHO|ECHOK|ECHONL);
11668 tcsetattr(0, TCSANOW, &tty);
11671 #if ENABLE_ASH_READ_TIMEOUT
11672 if (ts.tv_sec || ts.tv_usec) {
11676 i = select(FD_SETSIZE, &set, NULL, NULL, &ts);
11678 #if ENABLE_ASH_READ_NCHARS
11680 tcsetattr(0, TCSANOW, &old_tty);
11690 #if ENABLE_ASH_READ_NCHARS
11691 while (!nch_flag || nchars--)
11696 if (read(0, &c, 1) != 1) {
11708 if (!rflag && c == '\\') {
11714 if (startword && *ifs == ' ' && strchr(ifs, c)) {
11718 if (ap[1] != NULL && strchr(ifs, c) != NULL) {
11720 setvar(*ap, stackblock(), 0);
11729 #if ENABLE_ASH_READ_NCHARS
11730 if (nch_flag || silent)
11731 tcsetattr(0, TCSANOW, &old_tty);
11735 /* Remove trailing blanks */
11736 while ((char *)stackblock() <= --p && strchr(ifs, *p) != NULL)
11738 setvar(*ap, stackblock(), 0);
11739 while (*++ap != NULL)
11740 setvar(*ap, nullstr, 0);
11745 umaskcmd(int argc, char **argv)
11747 static const char permuser[3] = "ugo";
11748 static const char permmode[3] = "rwx";
11749 static const short int permmask[] = {
11750 S_IRUSR, S_IWUSR, S_IXUSR,
11751 S_IRGRP, S_IWGRP, S_IXGRP,
11752 S_IROTH, S_IWOTH, S_IXOTH
11758 int symbolic_mode = 0;
11760 while (nextopt("S") != '\0') {
11771 if (symbolic_mode) {
11775 for (i = 0; i < 3; i++) {
11778 *p++ = permuser[i];
11780 for (j = 0; j < 3; j++) {
11781 if ((mask & permmask[3 * i + j]) == 0) {
11782 *p++ = permmode[j];
11790 out1fmt("%.4o\n", mask);
11793 if (isdigit((unsigned char) *ap)) {
11796 if (*ap >= '8' || *ap < '0')
11797 ash_msg_and_raise_error(illnum, argv[1]);
11798 mask = (mask << 3) + (*ap - '0');
11799 } while (*++ap != '\0');
11802 mask = ~mask & 0777;
11803 if (!bb_parse_mode(ap, &mask)) {
11804 ash_msg_and_raise_error("Illegal mode: %s", ap);
11806 umask(~mask & 0777);
11815 * This code, originally by Doug Gwyn, Doug Kingston, Eric Gisin, and
11816 * Michael Rendell was ripped from pdksh 5.0.8 and hacked for use with
11817 * ash by J.T. Conklin.
11825 int factor; /* multiply by to get rlim_{cur,max} values */
11829 static const struct limits limits[] = {
11831 { "time(seconds)", RLIMIT_CPU, 1, 't' },
11833 #ifdef RLIMIT_FSIZE
11834 { "file(blocks)", RLIMIT_FSIZE, 512, 'f' },
11837 { "data(kbytes)", RLIMIT_DATA, 1024, 'd' },
11839 #ifdef RLIMIT_STACK
11840 { "stack(kbytes)", RLIMIT_STACK, 1024, 's' },
11843 { "coredump(blocks)", RLIMIT_CORE, 512, 'c' },
11846 { "memory(kbytes)", RLIMIT_RSS, 1024, 'm' },
11848 #ifdef RLIMIT_MEMLOCK
11849 { "locked memory(kbytes)", RLIMIT_MEMLOCK, 1024, 'l' },
11851 #ifdef RLIMIT_NPROC
11852 { "process", RLIMIT_NPROC, 1, 'p' },
11854 #ifdef RLIMIT_NOFILE
11855 { "nofiles", RLIMIT_NOFILE, 1, 'n' },
11858 { "vmemory(kbytes)", RLIMIT_AS, 1024, 'v' },
11860 #ifdef RLIMIT_LOCKS
11861 { "locks", RLIMIT_LOCKS, 1, 'w' },
11863 { NULL, 0, 0, '\0' }
11866 enum limtype { SOFT = 0x1, HARD = 0x2 };
11869 printlim(enum limtype how, const struct rlimit *limit,
11870 const struct limits *l)
11874 val = limit->rlim_max;
11876 val = limit->rlim_cur;
11878 if (val == RLIM_INFINITY)
11879 out1fmt("unlimited\n");
11882 out1fmt("%lld\n", (long long) val);
11887 ulimitcmd(int argc, char **argv)
11891 enum limtype how = SOFT | HARD;
11892 const struct limits *l;
11895 struct rlimit limit;
11898 while ((optc = nextopt("HSa"
11902 #ifdef RLIMIT_FSIZE
11908 #ifdef RLIMIT_STACK
11917 #ifdef RLIMIT_MEMLOCK
11920 #ifdef RLIMIT_NPROC
11923 #ifdef RLIMIT_NOFILE
11929 #ifdef RLIMIT_LOCKS
11947 for (l = limits; l->option != what; l++)
11950 set = *argptr ? 1 : 0;
11954 if (all || argptr[1])
11955 ash_msg_and_raise_error("too many arguments");
11956 if (strncmp(p, "unlimited\n", 9) == 0)
11957 val = RLIM_INFINITY;
11961 while ((c = *p++) >= '0' && c <= '9') {
11962 val = (val * 10) + (long)(c - '0');
11963 if (val < (rlim_t) 0)
11967 ash_msg_and_raise_error("bad number");
11972 for (l = limits; l->name; l++) {
11973 getrlimit(l->cmd, &limit);
11974 out1fmt("%-20s ", l->name);
11975 printlim(how, &limit, l);
11980 getrlimit(l->cmd, &limit);
11983 limit.rlim_max = val;
11985 limit.rlim_cur = val;
11986 if (setrlimit(l->cmd, &limit) < 0)
11987 ash_msg_and_raise_error("error setting limit (%m)");
11989 printlim(how, &limit, l);
11995 /* ============ Math support */
11997 #if ENABLE_ASH_MATH_SUPPORT
11999 /* Copyright (c) 2001 Aaron Lehmann <aaronl@vitelus.com>
12001 Permission is hereby granted, free of charge, to any person obtaining
12002 a copy of this software and associated documentation files (the
12003 "Software"), to deal in the Software without restriction, including
12004 without limitation the rights to use, copy, modify, merge, publish,
12005 distribute, sublicense, and/or sell copies of the Software, and to
12006 permit persons to whom the Software is furnished to do so, subject to
12007 the following conditions:
12009 The above copyright notice and this permission notice shall be
12010 included in all copies or substantial portions of the Software.
12012 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
12013 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
12014 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
12015 IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
12016 CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
12017 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
12018 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
12021 /* This is my infix parser/evaluator. It is optimized for size, intended
12022 * as a replacement for yacc-based parsers. However, it may well be faster
12023 * than a comparable parser written in yacc. The supported operators are
12024 * listed in #defines below. Parens, order of operations, and error handling
12025 * are supported. This code is thread safe. The exact expression format should
12026 * be that which POSIX specifies for shells. */
12028 /* The code uses a simple two-stack algorithm. See
12029 * http://www.onthenet.com.au/~grahamis/int2008/week02/lect02.html
12030 * for a detailed explanation of the infix-to-postfix algorithm on which
12031 * this is based (this code differs in that it applies operators immediately
12032 * to the stack instead of adding them to a queue to end up with an
12035 /* To use the routine, call it with an expression string and error return
12039 * Aug 24, 2001 Manuel Novoa III
12041 * Reduced the generated code size by about 30% (i386) and fixed several bugs.
12043 * 1) In arith_apply():
12044 * a) Cached values of *numptr and &(numptr[-1]).
12045 * b) Removed redundant test for zero denominator.
12048 * a) Eliminated redundant code for processing operator tokens by moving
12049 * to a table-based implementation. Also folded handling of parens
12051 * b) Combined all 3 loops which called arith_apply to reduce generated
12052 * code size at the cost of speed.
12054 * 3) The following expressions were treated as valid by the original code:
12055 * 1() , 0! , 1 ( *3 ) .
12056 * These bugs have been fixed by internally enclosing the expression in
12057 * parens and then checking that all binary ops and right parens are
12058 * preceded by a valid expression (NUM_TOKEN).
12060 * Note: It may be desirable to replace Aaron's test for whitespace with
12061 * ctype's isspace() if it is used by another busybox applet or if additional
12062 * whitespace chars should be considered. Look below the "#include"s for a
12063 * precompiler test.
12067 * Aug 26, 2001 Manuel Novoa III
12069 * Return 0 for null expressions. Pointed out by Vladimir Oleynik.
12071 * Merge in Aaron's comments previously posted to the busybox list,
12072 * modified slightly to take account of my changes to the code.
12077 * (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
12079 * - allow access to variable,
12080 * used recursive find value indirection (c=2*2; a="c"; $((a+=2)) produce 6)
12081 * - realize assign syntax (VAR=expr, +=, *= etc)
12082 * - realize exponentiation (** operator)
12083 * - realize comma separated - expr, expr
12084 * - realise ++expr --expr expr++ expr--
12085 * - realise expr ? expr : expr (but, second expr calculate always)
12086 * - allow hexadecimal and octal numbers
12087 * - was restored loses XOR operator
12088 * - remove one goto label, added three ;-)
12089 * - protect $((num num)) as true zero expr (Manuel`s error)
12090 * - always use special isspace(), see comment from bash ;-)
12093 #define arith_isspace(arithval) \
12094 (arithval == ' ' || arithval == '\n' || arithval == '\t')
12096 typedef unsigned char operator;
12098 /* An operator's token id is a bit of a bitfield. The lower 5 bits are the
12099 * precedence, and 3 high bits are an ID unique across operators of that
12100 * precedence. The ID portion is so that multiple operators can have the
12101 * same precedence, ensuring that the leftmost one is evaluated first.
12102 * Consider * and /. */
12104 #define tok_decl(prec,id) (((id)<<5)|(prec))
12105 #define PREC(op) ((op) & 0x1F)
12107 #define TOK_LPAREN tok_decl(0,0)
12109 #define TOK_COMMA tok_decl(1,0)
12111 #define TOK_ASSIGN tok_decl(2,0)
12112 #define TOK_AND_ASSIGN tok_decl(2,1)
12113 #define TOK_OR_ASSIGN tok_decl(2,2)
12114 #define TOK_XOR_ASSIGN tok_decl(2,3)
12115 #define TOK_PLUS_ASSIGN tok_decl(2,4)
12116 #define TOK_MINUS_ASSIGN tok_decl(2,5)
12117 #define TOK_LSHIFT_ASSIGN tok_decl(2,6)
12118 #define TOK_RSHIFT_ASSIGN tok_decl(2,7)
12120 #define TOK_MUL_ASSIGN tok_decl(3,0)
12121 #define TOK_DIV_ASSIGN tok_decl(3,1)
12122 #define TOK_REM_ASSIGN tok_decl(3,2)
12124 /* all assign is right associativity and precedence eq, but (7+3)<<5 > 256 */
12125 #define convert_prec_is_assing(prec) do { if (prec == 3) prec = 2; } while (0)
12127 /* conditional is right associativity too */
12128 #define TOK_CONDITIONAL tok_decl(4,0)
12129 #define TOK_CONDITIONAL_SEP tok_decl(4,1)
12131 #define TOK_OR tok_decl(5,0)
12133 #define TOK_AND tok_decl(6,0)
12135 #define TOK_BOR tok_decl(7,0)
12137 #define TOK_BXOR tok_decl(8,0)
12139 #define TOK_BAND tok_decl(9,0)
12141 #define TOK_EQ tok_decl(10,0)
12142 #define TOK_NE tok_decl(10,1)
12144 #define TOK_LT tok_decl(11,0)
12145 #define TOK_GT tok_decl(11,1)
12146 #define TOK_GE tok_decl(11,2)
12147 #define TOK_LE tok_decl(11,3)
12149 #define TOK_LSHIFT tok_decl(12,0)
12150 #define TOK_RSHIFT tok_decl(12,1)
12152 #define TOK_ADD tok_decl(13,0)
12153 #define TOK_SUB tok_decl(13,1)
12155 #define TOK_MUL tok_decl(14,0)
12156 #define TOK_DIV tok_decl(14,1)
12157 #define TOK_REM tok_decl(14,2)
12159 /* exponent is right associativity */
12160 #define TOK_EXPONENT tok_decl(15,1)
12162 /* For now unary operators. */
12163 #define UNARYPREC 16
12164 #define TOK_BNOT tok_decl(UNARYPREC,0)
12165 #define TOK_NOT tok_decl(UNARYPREC,1)
12167 #define TOK_UMINUS tok_decl(UNARYPREC+1,0)
12168 #define TOK_UPLUS tok_decl(UNARYPREC+1,1)
12170 #define PREC_PRE (UNARYPREC+2)
12172 #define TOK_PRE_INC tok_decl(PREC_PRE, 0)
12173 #define TOK_PRE_DEC tok_decl(PREC_PRE, 1)
12175 #define PREC_POST (UNARYPREC+3)
12177 #define TOK_POST_INC tok_decl(PREC_POST, 0)
12178 #define TOK_POST_DEC tok_decl(PREC_POST, 1)
12180 #define SPEC_PREC (UNARYPREC+4)
12182 #define TOK_NUM tok_decl(SPEC_PREC, 0)
12183 #define TOK_RPAREN tok_decl(SPEC_PREC, 1)
12185 #define NUMPTR (*numstackptr)
12188 tok_have_assign(operator op)
12190 operator prec = PREC(op);
12192 convert_prec_is_assing(prec);
12193 return (prec == PREC(TOK_ASSIGN) ||
12194 prec == PREC_PRE || prec == PREC_POST);
12198 is_right_associativity(operator prec)
12200 return (prec == PREC(TOK_ASSIGN) || prec == PREC(TOK_EXPONENT)
12201 || prec == PREC(TOK_CONDITIONAL));
12204 typedef struct ARITCH_VAR_NUM {
12206 arith_t contidional_second_val;
12207 char contidional_second_val_initialized;
12208 char *var; /* if NULL then is regular number,
12209 else is variable name */
12212 typedef struct CHK_VAR_RECURSIVE_LOOPED {
12214 struct CHK_VAR_RECURSIVE_LOOPED *next;
12215 } chk_var_recursive_looped_t;
12217 static chk_var_recursive_looped_t *prev_chk_var_recursive;
12220 arith_lookup_val(v_n_t *t)
12223 const char * p = lookupvar(t->var);
12228 /* recursive try as expression */
12229 chk_var_recursive_looped_t *cur;
12230 chk_var_recursive_looped_t cur_save;
12232 for (cur = prev_chk_var_recursive; cur; cur = cur->next) {
12233 if (strcmp(cur->var, t->var) == 0) {
12234 /* expression recursion loop detected */
12238 /* save current lookuped var name */
12239 cur = prev_chk_var_recursive;
12240 cur_save.var = t->var;
12241 cur_save.next = cur;
12242 prev_chk_var_recursive = &cur_save;
12244 t->val = arith (p, &errcode);
12245 /* restore previous ptr after recursiving */
12246 prev_chk_var_recursive = cur;
12249 /* allow undefined var as 0 */
12255 /* "applying" a token means performing it on the top elements on the integer
12256 * stack. For a unary operator it will only change the top element, but a
12257 * binary operator will pop two arguments and push a result */
12259 arith_apply(operator op, v_n_t *numstack, v_n_t **numstackptr)
12262 arith_t numptr_val, rez;
12263 int ret_arith_lookup_val;
12265 /* There is no operator that can work without arguments */
12266 if (NUMPTR == numstack) goto err;
12267 numptr_m1 = NUMPTR - 1;
12269 /* check operand is var with noninteger value */
12270 ret_arith_lookup_val = arith_lookup_val(numptr_m1);
12271 if (ret_arith_lookup_val)
12272 return ret_arith_lookup_val;
12274 rez = numptr_m1->val;
12275 if (op == TOK_UMINUS)
12277 else if (op == TOK_NOT)
12279 else if (op == TOK_BNOT)
12281 else if (op == TOK_POST_INC || op == TOK_PRE_INC)
12283 else if (op == TOK_POST_DEC || op == TOK_PRE_DEC)
12285 else if (op != TOK_UPLUS) {
12286 /* Binary operators */
12288 /* check and binary operators need two arguments */
12289 if (numptr_m1 == numstack) goto err;
12291 /* ... and they pop one */
12294 if (op == TOK_CONDITIONAL) {
12295 if (! numptr_m1->contidional_second_val_initialized) {
12296 /* protect $((expr1 ? expr2)) without ": expr" */
12299 rez = numptr_m1->contidional_second_val;
12300 } else if (numptr_m1->contidional_second_val_initialized) {
12301 /* protect $((expr1 : expr2)) without "expr ? " */
12304 numptr_m1 = NUMPTR - 1;
12305 if (op != TOK_ASSIGN) {
12306 /* check operand is var with noninteger value for not '=' */
12307 ret_arith_lookup_val = arith_lookup_val(numptr_m1);
12308 if (ret_arith_lookup_val)
12309 return ret_arith_lookup_val;
12311 if (op == TOK_CONDITIONAL) {
12312 numptr_m1->contidional_second_val = rez;
12314 rez = numptr_m1->val;
12315 if (op == TOK_BOR || op == TOK_OR_ASSIGN)
12317 else if (op == TOK_OR)
12318 rez = numptr_val || rez;
12319 else if (op == TOK_BAND || op == TOK_AND_ASSIGN)
12321 else if (op == TOK_BXOR || op == TOK_XOR_ASSIGN)
12323 else if (op == TOK_AND)
12324 rez = rez && numptr_val;
12325 else if (op == TOK_EQ)
12326 rez = (rez == numptr_val);
12327 else if (op == TOK_NE)
12328 rez = (rez != numptr_val);
12329 else if (op == TOK_GE)
12330 rez = (rez >= numptr_val);
12331 else if (op == TOK_RSHIFT || op == TOK_RSHIFT_ASSIGN)
12332 rez >>= numptr_val;
12333 else if (op == TOK_LSHIFT || op == TOK_LSHIFT_ASSIGN)
12334 rez <<= numptr_val;
12335 else if (op == TOK_GT)
12336 rez = (rez > numptr_val);
12337 else if (op == TOK_LT)
12338 rez = (rez < numptr_val);
12339 else if (op == TOK_LE)
12340 rez = (rez <= numptr_val);
12341 else if (op == TOK_MUL || op == TOK_MUL_ASSIGN)
12343 else if (op == TOK_ADD || op == TOK_PLUS_ASSIGN)
12345 else if (op == TOK_SUB || op == TOK_MINUS_ASSIGN)
12347 else if (op == TOK_ASSIGN || op == TOK_COMMA)
12349 else if (op == TOK_CONDITIONAL_SEP) {
12350 if (numptr_m1 == numstack) {
12351 /* protect $((expr : expr)) without "expr ? " */
12354 numptr_m1->contidional_second_val_initialized = op;
12355 numptr_m1->contidional_second_val = numptr_val;
12356 } else if (op == TOK_CONDITIONAL) {
12358 numptr_val : numptr_m1->contidional_second_val;
12359 } else if (op == TOK_EXPONENT) {
12360 if (numptr_val < 0)
12361 return -3; /* exponent less than 0 */
12366 while (numptr_val--)
12370 } else if (numptr_val==0) /* zero divisor check */
12372 else if (op == TOK_DIV || op == TOK_DIV_ASSIGN)
12374 else if (op == TOK_REM || op == TOK_REM_ASSIGN)
12377 if (tok_have_assign(op)) {
12378 char buf[sizeof(arith_t_type)*3 + 2];
12380 if (numptr_m1->var == NULL) {
12384 /* save to shell variable */
12385 #if ENABLE_ASH_MATH_SUPPORT_64
12386 snprintf(buf, sizeof(buf), "%lld", (arith_t_type) rez);
12388 snprintf(buf, sizeof(buf), "%ld", (arith_t_type) rez);
12390 setvar(numptr_m1->var, buf, 0);
12391 /* after saving, make previous value for v++ or v-- */
12392 if (op == TOK_POST_INC)
12394 else if (op == TOK_POST_DEC)
12397 numptr_m1->val = rez;
12398 /* protect geting var value, is number now */
12399 numptr_m1->var = NULL;
12405 /* longest must be first */
12406 static const char op_tokens[] = {
12407 '<','<','=',0, TOK_LSHIFT_ASSIGN,
12408 '>','>','=',0, TOK_RSHIFT_ASSIGN,
12409 '<','<', 0, TOK_LSHIFT,
12410 '>','>', 0, TOK_RSHIFT,
12411 '|','|', 0, TOK_OR,
12412 '&','&', 0, TOK_AND,
12413 '!','=', 0, TOK_NE,
12414 '<','=', 0, TOK_LE,
12415 '>','=', 0, TOK_GE,
12416 '=','=', 0, TOK_EQ,
12417 '|','=', 0, TOK_OR_ASSIGN,
12418 '&','=', 0, TOK_AND_ASSIGN,
12419 '*','=', 0, TOK_MUL_ASSIGN,
12420 '/','=', 0, TOK_DIV_ASSIGN,
12421 '%','=', 0, TOK_REM_ASSIGN,
12422 '+','=', 0, TOK_PLUS_ASSIGN,
12423 '-','=', 0, TOK_MINUS_ASSIGN,
12424 '-','-', 0, TOK_POST_DEC,
12425 '^','=', 0, TOK_XOR_ASSIGN,
12426 '+','+', 0, TOK_POST_INC,
12427 '*','*', 0, TOK_EXPONENT,
12431 '=', 0, TOK_ASSIGN,
12443 '?', 0, TOK_CONDITIONAL,
12444 ':', 0, TOK_CONDITIONAL_SEP,
12445 ')', 0, TOK_RPAREN,
12446 '(', 0, TOK_LPAREN,
12450 #define endexpression &op_tokens[sizeof(op_tokens)-7]
12453 arith(const char *expr, int *perrcode)
12455 char arithval; /* Current character under analysis */
12456 operator lasttok, op;
12459 const char *p = endexpression;
12462 size_t datasizes = strlen(expr) + 2;
12464 /* Stack of integers */
12465 /* The proof that there can be no more than strlen(startbuf)/2+1 integers
12466 * in any given correct or incorrect expression is left as an exercise to
12468 v_n_t *numstack = alloca(((datasizes)/2)*sizeof(v_n_t)),
12469 *numstackptr = numstack;
12470 /* Stack of operator tokens */
12471 operator *stack = alloca((datasizes) * sizeof(operator)),
12474 *stackptr++ = lasttok = TOK_LPAREN; /* start off with a left paren */
12475 *perrcode = errcode = 0;
12479 if (arithval == 0) {
12480 if (p == endexpression) {
12481 /* Null expression. */
12485 /* This is only reached after all tokens have been extracted from the
12486 * input stream. If there are still tokens on the operator stack, they
12487 * are to be applied in order. At the end, there should be a final
12488 * result on the integer stack */
12490 if (expr != endexpression + 1) {
12491 /* If we haven't done so already, */
12492 /* append a closing right paren */
12493 expr = endexpression;
12494 /* and let the loop process it. */
12497 /* At this point, we're done with the expression. */
12498 if (numstackptr != numstack+1) {
12499 /* ... but if there isn't, it's bad */
12501 return (*perrcode = -1);
12503 if (numstack->var) {
12504 /* expression is $((var)) only, lookup now */
12505 errcode = arith_lookup_val(numstack);
12508 *perrcode = errcode;
12509 return numstack->val;
12512 /* Continue processing the expression. */
12513 if (arith_isspace(arithval)) {
12514 /* Skip whitespace */
12517 p = endofname(expr);
12519 size_t var_name_size = (p-expr) + 1; /* trailing zero */
12521 numstackptr->var = alloca(var_name_size);
12522 safe_strncpy(numstackptr->var, expr, var_name_size);
12525 numstackptr->contidional_second_val_initialized = 0;
12530 if (isdigit(arithval)) {
12531 numstackptr->var = NULL;
12532 #if ENABLE_ASH_MATH_SUPPORT_64
12533 numstackptr->val = strtoll(expr, (char **) &expr, 0);
12535 numstackptr->val = strtol(expr, (char **) &expr, 0);
12539 for (p = op_tokens; ; p++) {
12543 /* strange operator not found */
12546 for (o = expr; *p && *o == *p; p++)
12553 /* skip tail uncompared token */
12556 /* skip zero delim */
12561 /* post grammar: a++ reduce to num */
12562 if (lasttok == TOK_POST_INC || lasttok == TOK_POST_DEC)
12565 /* Plus and minus are binary (not unary) _only_ if the last
12566 * token was as number, or a right paren (which pretends to be
12567 * a number, since it evaluates to one). Think about it.
12568 * It makes sense. */
12569 if (lasttok != TOK_NUM) {
12585 /* We don't want a unary operator to cause recursive descent on the
12586 * stack, because there can be many in a row and it could cause an
12587 * operator to be evaluated before its argument is pushed onto the
12588 * integer stack. */
12589 /* But for binary operators, "apply" everything on the operator
12590 * stack until we find an operator with a lesser priority than the
12591 * one we have just extracted. */
12592 /* Left paren is given the lowest priority so it will never be
12593 * "applied" in this way.
12594 * if associativity is right and priority eq, applied also skip
12597 if ((prec > 0 && prec < UNARYPREC) || prec == SPEC_PREC) {
12598 /* not left paren or unary */
12599 if (lasttok != TOK_NUM) {
12600 /* binary op must be preceded by a num */
12603 while (stackptr != stack) {
12604 if (op == TOK_RPAREN) {
12605 /* The algorithm employed here is simple: while we don't
12606 * hit an open paren nor the bottom of the stack, pop
12607 * tokens and apply them */
12608 if (stackptr[-1] == TOK_LPAREN) {
12610 /* Any operator directly after a */
12612 /* close paren should consider itself binary */
12616 operator prev_prec = PREC(stackptr[-1]);
12618 convert_prec_is_assing(prec);
12619 convert_prec_is_assing(prev_prec);
12620 if (prev_prec < prec)
12622 /* check right assoc */
12623 if (prev_prec == prec && is_right_associativity(prec))
12626 errcode = arith_apply(*--stackptr, numstack, &numstackptr);
12627 if (errcode) goto ret;
12629 if (op == TOK_RPAREN) {
12634 /* Push this operator to the stack and remember it. */
12635 *stackptr++ = lasttok = op;
12640 #endif /* ASH_MATH_SUPPORT */
12643 /* ============ main() and helpers */
12646 * Called to exit the shell.
12648 static void exitshell(void) ATTRIBUTE_NORETURN;
12656 status = exitstatus;
12657 TRACE(("pid %d, exitshell(%d)\n", getpid(), status));
12658 if (setjmp(loc.loc)) {
12659 if (exception == EXEXIT)
12660 /* dash bug: it just does _exit(exitstatus) here
12661 * but we have to do setjobctl(0) first!
12662 * (bug is still not fixed in dash-0.5.3 - if you run dash
12663 * under Midnight Commander, on exit from dash MC is backgrounded) */
12664 status = exitstatus;
12667 exception_handler = &loc;
12673 flush_stdout_stderr();
12683 /* from input.c: */
12684 basepf.nextc = basepf.buf = basebuf;
12687 signal(SIGCHLD, SIG_DFL);
12692 char ppid[sizeof(int)*3 + 1];
12694 struct stat st1, st2;
12697 for (envp = environ; envp && *envp; envp++) {
12698 if (strchr(*envp, '=')) {
12699 setvareq(*envp, VEXPORT|VTEXTFIXED);
12703 snprintf(ppid, sizeof(ppid), "%u", (unsigned) getppid());
12704 setvar("PPID", ppid, 0);
12706 p = lookupvar("PWD");
12708 if (*p != '/' || stat(p, &st1) || stat(".", &st2)
12709 || st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino)
12716 * Process the shell command line arguments.
12719 procargs(int argc, char **argv)
12722 const char *xminusc;
12729 for (i = 0; i < NOPTS; i++)
12735 if (*xargv == NULL) {
12737 ash_msg_and_raise_error(bb_msg_requires_arg, "-c");
12740 if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
12744 for (i = 0; i < NOPTS; i++)
12745 if (optlist[i] == 2)
12750 /* POSIX 1003.2: first arg after -c cmd is $0, remainder $1... */
12755 } else if (!sflag) {
12756 setinputfile(*xargv, 0);
12759 commandname = arg0;
12762 shellparam.p = xargv;
12763 #if ENABLE_ASH_GETOPTS
12764 shellparam.optind = 1;
12765 shellparam.optoff = -1;
12767 /* assert(shellparam.malloc == 0 && shellparam.nparam == 0); */
12769 shellparam.nparam++;
12776 * Read /etc/profile or .profile.
12779 read_profile(const char *name)
12783 if (setinputfile(name, INPUT_PUSH_FILE | INPUT_NOFILE_OK) < 0)
12792 * This routine is called when an error or an interrupt occurs in an
12793 * interactive shell and control is returned to the main command loop.
12801 /* from input.c: */
12802 parselleft = parsenleft = 0; /* clear input buffer */
12804 /* from parser.c: */
12807 /* from redir.c: */
12812 static short profile_buf[16384];
12813 extern int etext();
12817 * Main routine. We initialize things, parse the arguments, execute
12818 * profiles if we're a login shell, and then call cmdloop to execute
12819 * commands. The setjmp call sets up the location to jump to when an
12820 * exception occurs. When an exception occurs the variable "state"
12821 * is used to figure out how far we had gotten.
12823 int ash_main(int argc, char **argv);
12824 int ash_main(int argc, char **argv)
12827 volatile int state;
12828 struct jmploc jmploc;
12829 struct stackmark smark;
12832 dash_errno = __errno_location();
12836 monitor(4, etext, profile_buf, sizeof(profile_buf), 50);
12839 #if ENABLE_FEATURE_EDITING
12840 line_input_state = new_line_input_t(FOR_SHELL | WITH_PATH_LOOKUP);
12843 if (setjmp(jmploc.loc)) {
12853 if (e == EXEXIT || s == 0 || iflag == 0 || shlvl)
12857 outcslow('\n', stderr);
12859 popstackmark(&smark);
12860 FORCE_INT_ON; /* enable interrupts */
12869 exception_handler = &jmploc;
12872 trace_puts("Shell args: ");
12873 trace_puts_args(argv);
12875 rootpid = getpid();
12877 #if ENABLE_ASH_RANDOM_SUPPORT
12878 rseed = rootpid + time(NULL);
12881 setstackmark(&smark);
12882 procargs(argc, argv);
12883 #if ENABLE_FEATURE_EDITING_SAVEHISTORY
12885 const char *hp = lookupvar("HISTFILE");
12888 hp = lookupvar("HOME");
12890 char *defhp = concat_path_file(hp, ".ash_history");
12891 setvar("HISTFILE", defhp, 0);
12897 if (argv[0] && argv[0][0] == '-')
12901 read_profile("/etc/profile");
12904 read_profile(".profile");
12910 getuid() == geteuid() && getgid() == getegid() &&
12914 shinit = lookupvar("ENV");
12915 if (shinit != NULL && *shinit != '\0') {
12916 read_profile(shinit);
12922 evalstring(minusc, 0);
12924 if (sflag || minusc == NULL) {
12925 #if ENABLE_FEATURE_EDITING_SAVEHISTORY
12927 const char *hp = lookupvar("HISTFILE");
12930 line_input_state->hist_file = hp;
12933 state4: /* XXX ??? - why isn't this before the "if" statement */
12941 extern void _mcleanup(void);
12950 const char *applet_name = "debug stuff usage";
12951 int main(int argc, char **argv)
12953 return ash_main(argc, argv);
12959 * Copyright (c) 1989, 1991, 1993, 1994
12960 * The Regents of the University of California. All rights reserved.
12962 * This code is derived from software contributed to Berkeley by
12963 * Kenneth Almquist.
12965 * Redistribution and use in source and binary forms, with or without
12966 * modification, are permitted provided that the following conditions
12968 * 1. Redistributions of source code must retain the above copyright
12969 * notice, this list of conditions and the following disclaimer.
12970 * 2. Redistributions in binary form must reproduce the above copyright
12971 * notice, this list of conditions and the following disclaimer in the
12972 * documentation and/or other materials provided with the distribution.
12973 * 3. Neither the name of the University nor the names of its contributors
12974 * may be used to endorse or promote products derived from this software
12975 * without specific prior written permission.
12977 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
12978 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
12979 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
12980 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
12981 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
12982 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
12983 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
12984 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
12985 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
12986 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF