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 if (strcmp(arg0, commandname))
989 fprintf(stderr, "%s: ", commandname);
990 if (!iflag || parsefile->fd)
991 fprintf(stderr, "line %d: ", startlinno);
993 vfprintf(stderr, msg, ap);
994 outcslow('\n', stderr);
998 * Exverror is called to raise the error exception. If the second argument
999 * is not NULL then error prints an error message using printf style
1000 * formatting. It then raises the error exception.
1002 static void ash_vmsg_and_raise(int, const char *, va_list) ATTRIBUTE_NORETURN;
1004 ash_vmsg_and_raise(int cond, const char *msg, va_list ap)
1008 TRACE(("ash_vmsg_and_raise(%d, \"", cond));
1010 TRACE(("\") pid=%d\n", getpid()));
1012 TRACE(("ash_vmsg_and_raise(%d, NULL) pid=%d\n", cond, getpid()));
1017 flush_stdout_stderr();
1018 raise_exception(cond);
1022 static void ash_msg_and_raise_error(const char *, ...) ATTRIBUTE_NORETURN;
1024 ash_msg_and_raise_error(const char *msg, ...)
1029 ash_vmsg_and_raise(EXERROR, msg, ap);
1034 static void ash_msg_and_raise(int, const char *, ...) ATTRIBUTE_NORETURN;
1036 ash_msg_and_raise(int cond, const char *msg, ...)
1041 ash_vmsg_and_raise(cond, msg, ap);
1047 * error/warning routines for external builtins
1050 ash_msg(const char *fmt, ...)
1060 * Return a string describing an error. The returned string may be a
1061 * pointer to a static buffer that will be overwritten on the next call.
1062 * Action describes the operation that got the error.
1065 errmsg(int e, const char *em)
1067 if (e == ENOENT || e == ENOTDIR) {
1074 /* ============ Memory allocation */
1077 * It appears that grabstackstr() will barf with such alignments
1078 * because stalloc() will return a string allocated in a new stackblock.
1080 #define SHELL_ALIGN(nbytes) (((nbytes) + SHELL_SIZE) & ~SHELL_SIZE)
1082 /* Most machines require the value returned from malloc to be aligned
1083 * in some way. The following macro will get this right
1084 * on many machines. */
1085 SHELL_SIZE = sizeof(union {int i; char *cp; double d; }) - 1,
1086 /* Minimum size of a block */
1087 MINSIZE = SHELL_ALIGN(504),
1090 struct stack_block {
1091 struct stack_block *prev;
1092 char space[MINSIZE];
1096 struct stack_block *stackp;
1099 struct stackmark *marknext;
1102 static struct stack_block stackbase;
1103 static struct stack_block *stackp = &stackbase;
1104 static struct stackmark *markp;
1105 static char *stacknxt = stackbase.space;
1106 static size_t stacknleft = MINSIZE;
1107 static char *sstrend = stackbase.space + MINSIZE;
1108 static int herefd = -1;
1110 #define stackblock() ((void *)stacknxt)
1111 #define stackblocksize() stacknleft
1114 ckrealloc(void * p, size_t nbytes)
1116 p = realloc(p, nbytes);
1118 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1123 ckmalloc(size_t nbytes)
1125 return ckrealloc(NULL, nbytes);
1129 * Make a copy of a string in safe storage.
1132 ckstrdup(const char *s)
1134 char *p = strdup(s);
1136 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1141 * Parse trees for commands are allocated in lifo order, so we use a stack
1142 * to make this more efficient, and also to avoid all sorts of exception
1143 * handling code to handle interrupts in the middle of a parse.
1145 * The size 504 was chosen because the Ultrix malloc handles that size
1149 stalloc(size_t nbytes)
1154 aligned = SHELL_ALIGN(nbytes);
1155 if (aligned > stacknleft) {
1158 struct stack_block *sp;
1160 blocksize = aligned;
1161 if (blocksize < MINSIZE)
1162 blocksize = MINSIZE;
1163 len = sizeof(struct stack_block) - MINSIZE + blocksize;
1164 if (len < blocksize)
1165 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1169 stacknxt = sp->space;
1170 stacknleft = blocksize;
1171 sstrend = stacknxt + blocksize;
1176 stacknxt += aligned;
1177 stacknleft -= aligned;
1185 if (!p || (stacknxt < (char *)p) || ((char *)p < stackp->space)) {
1186 write(2, "stunalloc\n", 10);
1190 stacknleft += stacknxt - (char *)p;
1195 * Like strdup but works with the ash stack.
1198 ststrdup(const char *p)
1200 size_t len = strlen(p) + 1;
1201 return memcpy(stalloc(len), p, len);
1205 setstackmark(struct stackmark *mark)
1207 mark->stackp = stackp;
1208 mark->stacknxt = stacknxt;
1209 mark->stacknleft = stacknleft;
1210 mark->marknext = markp;
1215 popstackmark(struct stackmark *mark)
1217 struct stack_block *sp;
1223 markp = mark->marknext;
1224 while (stackp != mark->stackp) {
1229 stacknxt = mark->stacknxt;
1230 stacknleft = mark->stacknleft;
1231 sstrend = mark->stacknxt + mark->stacknleft;
1236 * When the parser reads in a string, it wants to stick the string on the
1237 * stack and only adjust the stack pointer when it knows how big the
1238 * string is. Stackblock (defined in stack.h) returns a pointer to a block
1239 * of space on top of the stack and stackblocklen returns the length of
1240 * this block. Growstackblock will grow this space by at least one byte,
1241 * possibly moving it (like realloc). Grabstackblock actually allocates the
1242 * part of the block that has been used.
1245 growstackblock(void)
1249 newlen = stacknleft * 2;
1250 if (newlen < stacknleft)
1251 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1255 if (stacknxt == stackp->space && stackp != &stackbase) {
1256 struct stack_block *oldstackp;
1257 struct stackmark *xmark;
1258 struct stack_block *sp;
1259 struct stack_block *prevstackp;
1265 prevstackp = sp->prev;
1266 grosslen = newlen + sizeof(struct stack_block) - MINSIZE;
1267 sp = ckrealloc(sp, grosslen);
1268 sp->prev = prevstackp;
1270 stacknxt = sp->space;
1271 stacknleft = newlen;
1272 sstrend = sp->space + newlen;
1275 * Stack marks pointing to the start of the old block
1276 * must be relocated to point to the new block
1279 while (xmark != NULL && xmark->stackp == oldstackp) {
1280 xmark->stackp = stackp;
1281 xmark->stacknxt = stacknxt;
1282 xmark->stacknleft = stacknleft;
1283 xmark = xmark->marknext;
1287 char *oldspace = stacknxt;
1288 int oldlen = stacknleft;
1289 char *p = stalloc(newlen);
1291 /* free the space we just allocated */
1292 stacknxt = memcpy(p, oldspace, oldlen);
1293 stacknleft += newlen;
1298 grabstackblock(size_t len)
1300 len = SHELL_ALIGN(len);
1306 * The following routines are somewhat easier to use than the above.
1307 * The user declares a variable of type STACKSTR, which may be declared
1308 * to be a register. The macro STARTSTACKSTR initializes things. Then
1309 * the user uses the macro STPUTC to add characters to the string. In
1310 * effect, STPUTC(c, p) is the same as *p++ = c except that the stack is
1311 * grown as necessary. When the user is done, she can just leave the
1312 * string there and refer to it using stackblock(). Or she can allocate
1313 * the space for it using grabstackstr(). If it is necessary to allow
1314 * someone else to use the stack temporarily and then continue to grow
1315 * the string, the user should use grabstack to allocate the space, and
1316 * then call ungrabstr(p) to return to the previous mode of operation.
1318 * USTPUTC is like STPUTC except that it doesn't check for overflow.
1319 * CHECKSTACKSPACE can be called before USTPUTC to ensure that there
1320 * is space for at least one character.
1325 size_t len = stackblocksize();
1326 if (herefd >= 0 && len >= 1024) {
1327 full_write(herefd, stackblock(), len);
1328 return stackblock();
1331 return stackblock() + len;
1335 * Called from CHECKSTRSPACE.
1338 makestrspace(size_t newlen, char *p)
1340 size_t len = p - stacknxt;
1341 size_t size = stackblocksize();
1346 size = stackblocksize();
1348 if (nleft >= newlen)
1352 return stackblock() + len;
1356 stack_nputstr(const char *s, size_t n, char *p)
1358 p = makestrspace(n, p);
1359 p = memcpy(p, s, n) + n;
1364 stack_putstr(const char *s, char *p)
1366 return stack_nputstr(s, strlen(s), p);
1370 _STPUTC(int c, char *p)
1378 #define STARTSTACKSTR(p) ((p) = stackblock())
1379 #define STPUTC(c, p) ((p) = _STPUTC((c), (p)))
1380 #define CHECKSTRSPACE(n, p) \
1384 size_t m = sstrend - q; \
1386 (p) = makestrspace(l, q); \
1388 #define USTPUTC(c, p) (*p++ = (c))
1389 #define STACKSTRNUL(p) \
1391 if ((p) == sstrend) \
1392 p = growstackstr(); \
1395 #define STUNPUTC(p) (--p)
1396 #define STTOPC(p) (p[-1])
1397 #define STADJUST(amount, p) (p += (amount))
1399 #define grabstackstr(p) stalloc((char *)(p) - (char *)stackblock())
1400 #define ungrabstackstr(s, p) stunalloc((s))
1401 #define stackstrend() ((void *)sstrend)
1404 /* ============ String helpers */
1407 * prefix -- see if pfx is a prefix of string.
1410 prefix(const char *string, const char *pfx)
1413 if (*pfx++ != *string++)
1416 return (char *) string;
1420 * Check for a valid number. This should be elsewhere.
1423 is_number(const char *p)
1428 } while (*++p != '\0');
1433 * Convert a string of digits to an integer, printing an error message on
1437 number(const char *s)
1440 ash_msg_and_raise_error(illnum, s);
1445 * Produce a possibly single quoted string suitable as input to the shell.
1446 * The return string is allocated on the stack.
1449 single_quote(const char *s)
1459 len = strchrnul(s, '\'') - s;
1461 q = p = makestrspace(len + 3, p);
1464 q = memcpy(q, s, len) + len;
1470 len = strspn(s, "'");
1474 q = p = makestrspace(len + 3, p);
1477 q = memcpy(q, s, len) + len;
1486 return stackblock();
1490 /* ============ nextopt */
1492 static char **argptr; /* argument list for builtin commands */
1493 static char *optionarg; /* set by nextopt (like getopt) */
1494 static char *optptr; /* used by nextopt */
1497 * XXX - should get rid of. have all builtins use getopt(3). the
1498 * library getopt must have the BSD extension static variable "optreset"
1499 * otherwise it can't be used within the shell safely.
1501 * Standard option processing (a la getopt) for builtin routines. The
1502 * only argument that is passed to nextopt is the option string; the
1503 * other arguments are unnecessary. It return the character, or '\0' on
1507 nextopt(const char *optstring)
1514 if (p == NULL || *p == '\0') {
1516 if (p == NULL || *p != '-' || *++p == '\0')
1519 if (LONE_DASH(p)) /* check for "--" */
1523 for (q = optstring; *q != c; ) {
1525 ash_msg_and_raise_error("illegal option -%c", c);
1530 if (*p == '\0' && (p = *argptr++) == NULL)
1531 ash_msg_and_raise_error("no arg for -%c option", c);
1540 /* ============ Math support definitions */
1542 #if ENABLE_ASH_MATH_SUPPORT_64
1543 typedef int64_t arith_t;
1544 #define arith_t_type long long
1546 typedef long arith_t;
1547 #define arith_t_type long
1550 #if ENABLE_ASH_MATH_SUPPORT
1551 static arith_t dash_arith(const char *);
1552 static arith_t arith(const char *expr, int *perrcode);
1555 #if ENABLE_ASH_RANDOM_SUPPORT
1556 static unsigned long rseed;
1563 /* ============ Shell variables */
1566 #define VEXPORT 0x01 /* variable is exported */
1567 #define VREADONLY 0x02 /* variable cannot be modified */
1568 #define VSTRFIXED 0x04 /* variable struct is statically allocated */
1569 #define VTEXTFIXED 0x08 /* text is statically allocated */
1570 #define VSTACK 0x10 /* text is allocated on the stack */
1571 #define VUNSET 0x20 /* the variable is not set */
1572 #define VNOFUNC 0x40 /* don't call the callback function */
1573 #define VNOSET 0x80 /* do not set variable - just readonly test */
1574 #define VNOSAVE 0x100 /* when text is on the heap before setvareq */
1576 # define VDYNAMIC 0x200 /* dynamic variable */
1581 static const char defpathvar[] = "PATH=/usr/local/bin:/usr/bin:/sbin:/bin";
1583 static const char defifsvar[] = "IFS= \t\n";
1584 #define defifs (defifsvar + 4)
1586 static const char defifs[] = " \t\n";
1590 int nparam; /* # of positional parameters (without $0) */
1591 unsigned char malloc; /* if parameter list dynamically allocated */
1592 char **p; /* parameter list */
1593 #if ENABLE_ASH_GETOPTS
1594 int optind; /* next parameter to be processed by getopts */
1595 int optoff; /* used by getopts */
1599 static struct shparam shellparam; /* $@ current positional parameters */
1602 * Free the list of positional parameters.
1605 freeparam(volatile struct shparam *param)
1609 if (param->malloc) {
1610 for (ap = param->p; *ap; ap++)
1616 #if ENABLE_ASH_GETOPTS
1618 getoptsreset(const char *value)
1620 shellparam.optind = number(value);
1621 shellparam.optoff = -1;
1626 struct var *next; /* next entry in hash list */
1627 int flags; /* flags are defined above */
1628 const char *text; /* name=value */
1629 void (*func)(const char *); /* function to be called when */
1630 /* the variable gets set/unset */
1634 struct localvar *next; /* next local variable in list */
1635 struct var *vp; /* the variable that was made local */
1636 int flags; /* saved flags */
1637 const char *text; /* saved text */
1640 /* Forward decls for varinit[] */
1641 #if ENABLE_LOCALE_SUPPORT
1643 change_lc_all(const char *value)
1645 if (value && *value != '\0')
1646 setlocale(LC_ALL, value);
1649 change_lc_ctype(const char *value)
1651 if (value && *value != '\0')
1652 setlocale(LC_CTYPE, value);
1656 static void chkmail(void);
1657 static void changemail(const char *);
1659 static void changepath(const char *);
1660 #if ENABLE_ASH_RANDOM_SUPPORT
1661 static void change_random(const char *);
1664 static struct var varinit[] = {
1666 { NULL, VSTRFIXED|VTEXTFIXED, defifsvar, NULL },
1668 { NULL, VSTRFIXED|VTEXTFIXED|VUNSET, "IFS\0", NULL },
1671 { NULL, VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL\0", changemail },
1672 { NULL, VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH\0", changemail },
1674 { NULL, VSTRFIXED|VTEXTFIXED, defpathvar, changepath },
1675 { NULL, VSTRFIXED|VTEXTFIXED, "PS1=$ ", NULL },
1676 { NULL, VSTRFIXED|VTEXTFIXED, "PS2=> ", NULL },
1677 { NULL, VSTRFIXED|VTEXTFIXED, "PS4=+ ", NULL },
1678 #if ENABLE_ASH_GETOPTS
1679 { NULL, VSTRFIXED|VTEXTFIXED, "OPTIND=1", getoptsreset },
1681 #if ENABLE_ASH_RANDOM_SUPPORT
1682 { NULL, VSTRFIXED|VTEXTFIXED|VUNSET|VDYNAMIC, "RANDOM\0", change_random },
1684 #if ENABLE_LOCALE_SUPPORT
1685 { NULL, VSTRFIXED | VTEXTFIXED | VUNSET, "LC_ALL\0", change_lc_all },
1686 { NULL, VSTRFIXED | VTEXTFIXED | VUNSET, "LC_CTYPE\0", change_lc_ctype },
1688 #if ENABLE_FEATURE_EDITING_SAVEHISTORY
1689 { NULL, VSTRFIXED | VTEXTFIXED | VUNSET, "HISTFILE\0", NULL },
1693 #define vifs varinit[0]
1695 #define vmail (&vifs)[1]
1696 #define vmpath (&vmail)[1]
1700 #define vpath (&vmpath)[1]
1701 #define vps1 (&vpath)[1]
1702 #define vps2 (&vps1)[1]
1703 #define vps4 (&vps2)[1]
1704 #define voptind (&vps4)[1]
1705 #if ENABLE_ASH_GETOPTS
1706 #define vrandom (&voptind)[1]
1708 #define vrandom (&vps4)[1]
1710 #define defpath (defpathvar + 5)
1713 * The following macros access the values of the above variables.
1714 * They have to skip over the name. They return the null string
1715 * for unset variables.
1717 #define ifsval() (vifs.text + 4)
1718 #define ifsset() ((vifs.flags & VUNSET) == 0)
1719 #define mailval() (vmail.text + 5)
1720 #define mpathval() (vmpath.text + 9)
1721 #define pathval() (vpath.text + 5)
1722 #define ps1val() (vps1.text + 4)
1723 #define ps2val() (vps2.text + 4)
1724 #define ps4val() (vps4.text + 4)
1725 #define optindval() (voptind.text + 7)
1727 #define mpathset() ((vmpath.flags & VUNSET) == 0)
1730 * The parsefile structure pointed to by the global variable parsefile
1731 * contains information about the current file being read.
1734 struct redirtab *next;
1739 static struct redirtab *redirlist;
1740 static int nullredirs;
1741 extern char **environ;
1742 static int preverrout_fd; /* save fd2 before print debug if xflag is set. */
1746 static struct var *vartab[VTABSIZE];
1748 #define is_name(c) ((c) == '_' || isalpha((unsigned char)(c)))
1749 #define is_in_name(c) ((c) == '_' || isalnum((unsigned char)(c)))
1752 * Return of a legal variable name (a letter or underscore followed by zero or
1753 * more letters, underscores, and digits).
1756 endofname(const char *name)
1764 if (!is_in_name(*p))
1771 * Compares two strings up to the first = or '\0'. The first
1772 * string must be terminated by '='; the second may be terminated by
1773 * either '=' or '\0'.
1776 varcmp(const char *p, const char *q)
1780 while ((c = *p) == (d = *q)) {
1795 varequal(const char *a, const char *b)
1797 return !varcmp(a, b);
1801 * Find the appropriate entry in the hash table from the name.
1803 static struct var **
1804 hashvar(const char *p)
1808 hashval = ((unsigned char) *p) << 4;
1809 while (*p && *p != '=')
1810 hashval += (unsigned char) *p++;
1811 return &vartab[hashval % VTABSIZE];
1815 vpcmp(const void *a, const void *b)
1817 return varcmp(*(const char **)a, *(const char **)b);
1821 * This routine initializes the builtin variables.
1831 * PS1 depends on uid
1833 #if ENABLE_FEATURE_EDITING && ENABLE_FEATURE_EDITING_FANCY_PROMPT
1834 vps1.text = "PS1=\\w \\$ ";
1837 vps1.text = "PS1=# ";
1840 end = vp + sizeof(varinit) / sizeof(varinit[0]);
1842 vpp = hashvar(vp->text);
1845 } while (++vp < end);
1848 static struct var **
1849 findvar(struct var **vpp, const char *name)
1851 for (; *vpp; vpp = &(*vpp)->next) {
1852 if (varequal((*vpp)->text, name)) {
1860 * Find the value of a variable. Returns NULL if not set.
1863 lookupvar(const char *name)
1867 v = *findvar(hashvar(name), name);
1871 * Dynamic variables are implemented roughly the same way they are
1872 * in bash. Namely, they're "special" so long as they aren't unset.
1873 * As soon as they're unset, they're no longer dynamic, and dynamic
1874 * lookup will no longer happen at that point. -- PFM.
1876 if ((v->flags & VDYNAMIC))
1879 if (!(v->flags & VUNSET))
1880 return strchrnul(v->text, '=') + 1;
1886 * Search the environment of a builtin command.
1889 bltinlookup(const char *name)
1893 for (sp = cmdenviron; sp; sp = sp->next) {
1894 if (varequal(sp->text, name))
1895 return strchrnul(sp->text, '=') + 1;
1897 return lookupvar(name);
1901 * Same as setvar except that the variable and value are passed in
1902 * the first argument as name=value. Since the first argument will
1903 * be actually stored in the table, it should not be a string that
1905 * Called with interrupts off.
1908 setvareq(char *s, int flags)
1910 struct var *vp, **vpp;
1913 flags |= (VEXPORT & (((unsigned) (1 - aflag)) - 1));
1914 vp = *findvar(vpp, s);
1916 if ((vp->flags & (VREADONLY|VDYNAMIC)) == VREADONLY) {
1919 if (flags & VNOSAVE)
1922 ash_msg_and_raise_error("%.*s: is read only", strchrnul(n, '=') - n, n);
1928 if (vp->func && (flags & VNOFUNC) == 0)
1929 (*vp->func)(strchrnul(s, '=') + 1);
1931 if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
1932 free((char*)vp->text);
1934 flags |= vp->flags & ~(VTEXTFIXED|VSTACK|VNOSAVE|VUNSET);
1939 vp = ckmalloc(sizeof(*vp));
1944 if (!(flags & (VTEXTFIXED|VSTACK|VNOSAVE)))
1951 * Set the value of a variable. The flags argument is ored with the
1952 * flags of the variable. If val is NULL, the variable is unset.
1955 setvar(const char *name, const char *val, int flags)
1962 q = endofname(name);
1963 p = strchrnul(q, '=');
1965 if (!namelen || p != q)
1966 ash_msg_and_raise_error("%.*s: bad variable name", namelen, name);
1971 vallen = strlen(val);
1974 nameeq = ckmalloc(namelen + vallen + 2);
1975 p = memcpy(nameeq, name, namelen) + namelen;
1978 p = memcpy(p, val, vallen) + vallen;
1981 setvareq(nameeq, flags | VNOSAVE);
1985 #if ENABLE_ASH_GETOPTS
1987 * Safe version of setvar, returns 1 on success 0 on failure.
1990 setvarsafe(const char *name, const char *val, int flags)
1993 volatile int saveint;
1994 struct jmploc *volatile savehandler = exception_handler;
1995 struct jmploc jmploc;
1998 if (setjmp(jmploc.loc))
2001 exception_handler = &jmploc;
2002 setvar(name, val, flags);
2005 exception_handler = savehandler;
2006 RESTORE_INT(saveint);
2012 * Unset the specified variable.
2015 unsetvar(const char *s)
2021 vpp = findvar(hashvar(s), s);
2025 int flags = vp->flags;
2028 if (flags & VREADONLY)
2031 vp->flags &= ~VDYNAMIC;
2035 if ((flags & VSTRFIXED) == 0) {
2037 if ((flags & (VTEXTFIXED|VSTACK)) == 0)
2038 free((char*)vp->text);
2044 vp->flags &= ~VEXPORT;
2054 * Process a linked list of variable assignments.
2057 listsetvar(struct strlist *list_set_var, int flags)
2059 struct strlist *lp = list_set_var;
2065 setvareq(lp->text, flags);
2072 * Generate a list of variables satisfying the given conditions.
2075 listvars(int on, int off, char ***end)
2086 for (vp = *vpp; vp; vp = vp->next) {
2087 if ((vp->flags & mask) == on) {
2088 if (ep == stackstrend())
2089 ep = growstackstr();
2090 *ep++ = (char *) vp->text;
2093 } while (++vpp < vartab + VTABSIZE);
2094 if (ep == stackstrend())
2095 ep = growstackstr();
2099 return grabstackstr(ep);
2103 /* ============ Path search helper
2105 * The variable path (passed by reference) should be set to the start
2106 * of the path before the first call; padvance will update
2107 * this value as it proceeds. Successive calls to padvance will return
2108 * the possible path expansions in sequence. If an option (indicated by
2109 * a percent sign) appears in the path entry then the global variable
2110 * pathopt will be set to point to it; otherwise pathopt will be set to
2113 static const char *pathopt; /* set by padvance */
2116 padvance(const char **path, const char *name)
2126 for (p = start; *p && *p != ':' && *p != '%'; p++);
2127 len = p - start + strlen(name) + 2; /* "2" is for '/' and '\0' */
2128 while (stackblocksize() < len)
2132 memcpy(q, start, p - start);
2140 while (*p && *p != ':') p++;
2146 return stalloc(len);
2150 /* ============ Prompt */
2152 static int doprompt; /* if set, prompt the user */
2153 static int needprompt; /* true if interactive and at start of line */
2155 #if ENABLE_FEATURE_EDITING
2156 static line_input_t *line_input_state;
2157 static const char *cmdedit_prompt;
2159 putprompt(const char *s)
2161 if (ENABLE_ASH_EXPAND_PRMT) {
2162 free((char*)cmdedit_prompt);
2163 cmdedit_prompt = ckstrdup(s);
2170 putprompt(const char *s)
2176 #if ENABLE_ASH_EXPAND_PRMT
2177 /* expandstr() needs parsing machinery, so it is far away ahead... */
2178 static const char *expandstr(const char *ps);
2180 #define expandstr(s) s
2184 setprompt(int whichprompt)
2187 #if ENABLE_ASH_EXPAND_PRMT
2188 struct stackmark smark;
2193 switch (whichprompt) {
2203 #if ENABLE_ASH_EXPAND_PRMT
2204 setstackmark(&smark);
2205 stalloc(stackblocksize());
2207 putprompt(expandstr(prompt));
2208 #if ENABLE_ASH_EXPAND_PRMT
2209 popstackmark(&smark);
2214 /* ============ The cd and pwd commands */
2216 #define CD_PHYSICAL 1
2219 static int docd(const char *, int);
2221 static char *curdir = nullstr; /* current working directory */
2222 static char *physdir = nullstr; /* physical working directory */
2231 while ((i = nextopt("LP"))) {
2233 flags ^= CD_PHYSICAL;
2242 * Update curdir (the name of the current directory) in response to a
2246 updatepwd(const char *dir)
2253 cdcomppath = ststrdup(dir);
2256 if (curdir == nullstr)
2258 new = stack_putstr(curdir, new);
2260 new = makestrspace(strlen(dir) + 2, new);
2261 lim = stackblock() + 1;
2265 if (new > lim && *lim == '/')
2270 if (dir[1] == '/' && dir[2] != '/') {
2276 p = strtok(cdcomppath, "/");
2280 if (p[1] == '.' && p[2] == '\0') {
2287 } else if (p[1] == '\0')
2291 new = stack_putstr(p, new);
2299 return stackblock();
2303 * Find out what the current directory is. If we already know the current
2304 * directory, this routine returns immediately.
2309 char *dir = getcwd(0, 0);
2310 return dir ? dir : nullstr;
2314 setpwd(const char *val, int setold)
2318 oldcur = dir = curdir;
2321 setvar("OLDPWD", oldcur, VEXPORT);
2324 if (physdir != nullstr) {
2325 if (physdir != oldcur)
2329 if (oldcur == val || !val) {
2335 dir = ckstrdup(val);
2336 if (oldcur != dir && oldcur != nullstr) {
2341 setvar("PWD", dir, VEXPORT);
2344 static void hashcd(void);
2347 * Actually do the chdir. We also call hashcd to let the routines in exec.c
2348 * know that the current directory has changed.
2351 docd(const char *dest, int flags)
2353 const char *dir = 0;
2356 TRACE(("docd(\"%s\", %d) called\n", dest, flags));
2359 if (!(flags & CD_PHYSICAL)) {
2360 dir = updatepwd(dest);
2375 cdcmd(int argc, char **argv)
2387 dest = bltinlookup(homestr);
2388 else if (LONE_DASH(dest)) {
2389 dest = bltinlookup("OLDPWD");
2411 path = bltinlookup("CDPATH");
2420 p = padvance(&path, dest);
2421 if (stat(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) {
2425 if (!docd(p, flags))
2430 ash_msg_and_raise_error("can't cd to %s", dest);
2433 if (flags & CD_PRINT)
2434 out1fmt(snlfmt, curdir);
2439 pwdcmd(int argc, char **argv)
2442 const char *dir = curdir;
2446 if (physdir == nullstr)
2450 out1fmt(snlfmt, dir);
2455 /* ============ ... */
2457 #define IBUFSIZ (BUFSIZ + 1)
2458 #define basebuf bb_common_bufsiz1 /* buffer for top level input file */
2460 /* Syntax classes */
2461 #define CWORD 0 /* character is nothing special */
2462 #define CNL 1 /* newline character */
2463 #define CBACK 2 /* a backslash character */
2464 #define CSQUOTE 3 /* single quote */
2465 #define CDQUOTE 4 /* double quote */
2466 #define CENDQUOTE 5 /* a terminating quote */
2467 #define CBQUOTE 6 /* backwards single quote */
2468 #define CVAR 7 /* a dollar sign */
2469 #define CENDVAR 8 /* a '}' character */
2470 #define CLP 9 /* a left paren in arithmetic */
2471 #define CRP 10 /* a right paren in arithmetic */
2472 #define CENDFILE 11 /* end of file */
2473 #define CCTL 12 /* like CWORD, except it must be escaped */
2474 #define CSPCL 13 /* these terminate a word */
2475 #define CIGN 14 /* character should be ignored */
2477 #if ENABLE_ASH_ALIAS
2481 #define PEOA_OR_PEOF PEOA
2485 #define PEOA_OR_PEOF PEOF
2488 /* number syntax index */
2489 #define BASESYNTAX 0 /* not in quotes */
2490 #define DQSYNTAX 1 /* in double quotes */
2491 #define SQSYNTAX 2 /* in single quotes */
2492 #define ARISYNTAX 3 /* in arithmetic */
2494 #if ENABLE_ASH_OPTIMIZE_FOR_SIZE
2495 #define USE_SIT_FUNCTION
2498 #if ENABLE_ASH_MATH_SUPPORT
2499 static const char S_I_T[][4] = {
2500 #if ENABLE_ASH_ALIAS
2501 { CSPCL, CIGN, CIGN, CIGN }, /* 0, PEOA */
2503 { CSPCL, CWORD, CWORD, CWORD }, /* 1, ' ' */
2504 { CNL, CNL, CNL, CNL }, /* 2, \n */
2505 { CWORD, CCTL, CCTL, CWORD }, /* 3, !*-/:=?[]~ */
2506 { CDQUOTE, CENDQUOTE, CWORD, CWORD }, /* 4, '"' */
2507 { CVAR, CVAR, CWORD, CVAR }, /* 5, $ */
2508 { CSQUOTE, CWORD, CENDQUOTE, CWORD }, /* 6, "'" */
2509 { CSPCL, CWORD, CWORD, CLP }, /* 7, ( */
2510 { CSPCL, CWORD, CWORD, CRP }, /* 8, ) */
2511 { CBACK, CBACK, CCTL, CBACK }, /* 9, \ */
2512 { CBQUOTE, CBQUOTE, CWORD, CBQUOTE }, /* 10, ` */
2513 { CENDVAR, CENDVAR, CWORD, CENDVAR }, /* 11, } */
2514 #ifndef USE_SIT_FUNCTION
2515 { CENDFILE, CENDFILE, CENDFILE, CENDFILE }, /* 12, PEOF */
2516 { CWORD, CWORD, CWORD, CWORD }, /* 13, 0-9A-Za-z */
2517 { CCTL, CCTL, CCTL, CCTL } /* 14, CTLESC ... */
2521 static const char S_I_T[][3] = {
2522 #if ENABLE_ASH_ALIAS
2523 { CSPCL, CIGN, CIGN }, /* 0, PEOA */
2525 { CSPCL, CWORD, CWORD }, /* 1, ' ' */
2526 { CNL, CNL, CNL }, /* 2, \n */
2527 { CWORD, CCTL, CCTL }, /* 3, !*-/:=?[]~ */
2528 { CDQUOTE, CENDQUOTE, CWORD }, /* 4, '"' */
2529 { CVAR, CVAR, CWORD }, /* 5, $ */
2530 { CSQUOTE, CWORD, CENDQUOTE }, /* 6, "'" */
2531 { CSPCL, CWORD, CWORD }, /* 7, ( */
2532 { CSPCL, CWORD, CWORD }, /* 8, ) */
2533 { CBACK, CBACK, CCTL }, /* 9, \ */
2534 { CBQUOTE, CBQUOTE, CWORD }, /* 10, ` */
2535 { CENDVAR, CENDVAR, CWORD }, /* 11, } */
2536 #ifndef USE_SIT_FUNCTION
2537 { CENDFILE, CENDFILE, CENDFILE }, /* 12, PEOF */
2538 { CWORD, CWORD, CWORD }, /* 13, 0-9A-Za-z */
2539 { CCTL, CCTL, CCTL } /* 14, CTLESC ... */
2542 #endif /* ASH_MATH_SUPPORT */
2544 #ifdef USE_SIT_FUNCTION
2547 SIT(int c, int syntax)
2549 static const char spec_symbls[] = "\t\n !\"$&'()*-/:;<=>?[\\]`|}~";
2550 #if ENABLE_ASH_ALIAS
2551 static const char syntax_index_table[] = {
2552 1, 2, 1, 3, 4, 5, 1, 6, /* "\t\n !\"$&'" */
2553 7, 8, 3, 3, 3, 3, 1, 1, /* "()*-/:;<" */
2554 3, 1, 3, 3, 9, 3, 10, 1, /* "=>?[\\]`|" */
2558 static const char syntax_index_table[] = {
2559 0, 1, 0, 2, 3, 4, 0, 5, /* "\t\n !\"$&'" */
2560 6, 7, 2, 2, 2, 2, 0, 0, /* "()*-/:;<" */
2561 2, 0, 2, 2, 8, 2, 9, 0, /* "=>?[\\]`|" */
2568 if (c == PEOF) /* 2^8+2 */
2570 #if ENABLE_ASH_ALIAS
2571 if (c == PEOA) /* 2^8+1 */
2575 #define U_C(c) ((unsigned char)(c))
2577 if ((unsigned char)c >= (unsigned char)(CTLESC)
2578 && (unsigned char)c <= (unsigned char)(CTLQUOTEMARK)
2582 s = strchr(spec_symbls, c);
2583 if (s == NULL || *s == '\0')
2585 indx = syntax_index_table[(s - spec_symbls)];
2587 return S_I_T[indx][syntax];
2590 #else /* !USE_SIT_FUNCTION */
2592 #if ENABLE_ASH_ALIAS
2593 #define CSPCL_CIGN_CIGN_CIGN 0
2594 #define CSPCL_CWORD_CWORD_CWORD 1
2595 #define CNL_CNL_CNL_CNL 2
2596 #define CWORD_CCTL_CCTL_CWORD 3
2597 #define CDQUOTE_CENDQUOTE_CWORD_CWORD 4
2598 #define CVAR_CVAR_CWORD_CVAR 5
2599 #define CSQUOTE_CWORD_CENDQUOTE_CWORD 6
2600 #define CSPCL_CWORD_CWORD_CLP 7
2601 #define CSPCL_CWORD_CWORD_CRP 8
2602 #define CBACK_CBACK_CCTL_CBACK 9
2603 #define CBQUOTE_CBQUOTE_CWORD_CBQUOTE 10
2604 #define CENDVAR_CENDVAR_CWORD_CENDVAR 11
2605 #define CENDFILE_CENDFILE_CENDFILE_CENDFILE 12
2606 #define CWORD_CWORD_CWORD_CWORD 13
2607 #define CCTL_CCTL_CCTL_CCTL 14
2609 #define CSPCL_CWORD_CWORD_CWORD 0
2610 #define CNL_CNL_CNL_CNL 1
2611 #define CWORD_CCTL_CCTL_CWORD 2
2612 #define CDQUOTE_CENDQUOTE_CWORD_CWORD 3
2613 #define CVAR_CVAR_CWORD_CVAR 4
2614 #define CSQUOTE_CWORD_CENDQUOTE_CWORD 5
2615 #define CSPCL_CWORD_CWORD_CLP 6
2616 #define CSPCL_CWORD_CWORD_CRP 7
2617 #define CBACK_CBACK_CCTL_CBACK 8
2618 #define CBQUOTE_CBQUOTE_CWORD_CBQUOTE 9
2619 #define CENDVAR_CENDVAR_CWORD_CENDVAR 10
2620 #define CENDFILE_CENDFILE_CENDFILE_CENDFILE 11
2621 #define CWORD_CWORD_CWORD_CWORD 12
2622 #define CCTL_CCTL_CCTL_CCTL 13
2625 static const char syntax_index_table[258] = {
2626 /* BASESYNTAX_DQSYNTAX_SQSYNTAX_ARISYNTAX */
2627 /* 0 PEOF */ CENDFILE_CENDFILE_CENDFILE_CENDFILE,
2628 #if ENABLE_ASH_ALIAS
2629 /* 1 PEOA */ CSPCL_CIGN_CIGN_CIGN,
2631 /* 2 -128 0x80 */ CWORD_CWORD_CWORD_CWORD,
2632 /* 3 -127 CTLESC */ CCTL_CCTL_CCTL_CCTL,
2633 /* 4 -126 CTLVAR */ CCTL_CCTL_CCTL_CCTL,
2634 /* 5 -125 CTLENDVAR */ CCTL_CCTL_CCTL_CCTL,
2635 /* 6 -124 CTLBACKQ */ CCTL_CCTL_CCTL_CCTL,
2636 /* 7 -123 CTLQUOTE */ CCTL_CCTL_CCTL_CCTL,
2637 /* 8 -122 CTLARI */ CCTL_CCTL_CCTL_CCTL,
2638 /* 9 -121 CTLENDARI */ CCTL_CCTL_CCTL_CCTL,
2639 /* 10 -120 CTLQUOTEMARK */ CCTL_CCTL_CCTL_CCTL,
2640 /* 11 -119 */ CWORD_CWORD_CWORD_CWORD,
2641 /* 12 -118 */ CWORD_CWORD_CWORD_CWORD,
2642 /* 13 -117 */ CWORD_CWORD_CWORD_CWORD,
2643 /* 14 -116 */ CWORD_CWORD_CWORD_CWORD,
2644 /* 15 -115 */ CWORD_CWORD_CWORD_CWORD,
2645 /* 16 -114 */ CWORD_CWORD_CWORD_CWORD,
2646 /* 17 -113 */ CWORD_CWORD_CWORD_CWORD,
2647 /* 18 -112 */ CWORD_CWORD_CWORD_CWORD,
2648 /* 19 -111 */ CWORD_CWORD_CWORD_CWORD,
2649 /* 20 -110 */ CWORD_CWORD_CWORD_CWORD,
2650 /* 21 -109 */ CWORD_CWORD_CWORD_CWORD,
2651 /* 22 -108 */ CWORD_CWORD_CWORD_CWORD,
2652 /* 23 -107 */ CWORD_CWORD_CWORD_CWORD,
2653 /* 24 -106 */ CWORD_CWORD_CWORD_CWORD,
2654 /* 25 -105 */ CWORD_CWORD_CWORD_CWORD,
2655 /* 26 -104 */ CWORD_CWORD_CWORD_CWORD,
2656 /* 27 -103 */ CWORD_CWORD_CWORD_CWORD,
2657 /* 28 -102 */ CWORD_CWORD_CWORD_CWORD,
2658 /* 29 -101 */ CWORD_CWORD_CWORD_CWORD,
2659 /* 30 -100 */ CWORD_CWORD_CWORD_CWORD,
2660 /* 31 -99 */ CWORD_CWORD_CWORD_CWORD,
2661 /* 32 -98 */ CWORD_CWORD_CWORD_CWORD,
2662 /* 33 -97 */ CWORD_CWORD_CWORD_CWORD,
2663 /* 34 -96 */ CWORD_CWORD_CWORD_CWORD,
2664 /* 35 -95 */ CWORD_CWORD_CWORD_CWORD,
2665 /* 36 -94 */ CWORD_CWORD_CWORD_CWORD,
2666 /* 37 -93 */ CWORD_CWORD_CWORD_CWORD,
2667 /* 38 -92 */ CWORD_CWORD_CWORD_CWORD,
2668 /* 39 -91 */ CWORD_CWORD_CWORD_CWORD,
2669 /* 40 -90 */ CWORD_CWORD_CWORD_CWORD,
2670 /* 41 -89 */ CWORD_CWORD_CWORD_CWORD,
2671 /* 42 -88 */ CWORD_CWORD_CWORD_CWORD,
2672 /* 43 -87 */ CWORD_CWORD_CWORD_CWORD,
2673 /* 44 -86 */ CWORD_CWORD_CWORD_CWORD,
2674 /* 45 -85 */ CWORD_CWORD_CWORD_CWORD,
2675 /* 46 -84 */ CWORD_CWORD_CWORD_CWORD,
2676 /* 47 -83 */ CWORD_CWORD_CWORD_CWORD,
2677 /* 48 -82 */ CWORD_CWORD_CWORD_CWORD,
2678 /* 49 -81 */ CWORD_CWORD_CWORD_CWORD,
2679 /* 50 -80 */ CWORD_CWORD_CWORD_CWORD,
2680 /* 51 -79 */ CWORD_CWORD_CWORD_CWORD,
2681 /* 52 -78 */ CWORD_CWORD_CWORD_CWORD,
2682 /* 53 -77 */ CWORD_CWORD_CWORD_CWORD,
2683 /* 54 -76 */ CWORD_CWORD_CWORD_CWORD,
2684 /* 55 -75 */ CWORD_CWORD_CWORD_CWORD,
2685 /* 56 -74 */ CWORD_CWORD_CWORD_CWORD,
2686 /* 57 -73 */ CWORD_CWORD_CWORD_CWORD,
2687 /* 58 -72 */ CWORD_CWORD_CWORD_CWORD,
2688 /* 59 -71 */ CWORD_CWORD_CWORD_CWORD,
2689 /* 60 -70 */ CWORD_CWORD_CWORD_CWORD,
2690 /* 61 -69 */ CWORD_CWORD_CWORD_CWORD,
2691 /* 62 -68 */ CWORD_CWORD_CWORD_CWORD,
2692 /* 63 -67 */ CWORD_CWORD_CWORD_CWORD,
2693 /* 64 -66 */ CWORD_CWORD_CWORD_CWORD,
2694 /* 65 -65 */ CWORD_CWORD_CWORD_CWORD,
2695 /* 66 -64 */ CWORD_CWORD_CWORD_CWORD,
2696 /* 67 -63 */ CWORD_CWORD_CWORD_CWORD,
2697 /* 68 -62 */ CWORD_CWORD_CWORD_CWORD,
2698 /* 69 -61 */ CWORD_CWORD_CWORD_CWORD,
2699 /* 70 -60 */ CWORD_CWORD_CWORD_CWORD,
2700 /* 71 -59 */ CWORD_CWORD_CWORD_CWORD,
2701 /* 72 -58 */ CWORD_CWORD_CWORD_CWORD,
2702 /* 73 -57 */ CWORD_CWORD_CWORD_CWORD,
2703 /* 74 -56 */ CWORD_CWORD_CWORD_CWORD,
2704 /* 75 -55 */ CWORD_CWORD_CWORD_CWORD,
2705 /* 76 -54 */ CWORD_CWORD_CWORD_CWORD,
2706 /* 77 -53 */ CWORD_CWORD_CWORD_CWORD,
2707 /* 78 -52 */ CWORD_CWORD_CWORD_CWORD,
2708 /* 79 -51 */ CWORD_CWORD_CWORD_CWORD,
2709 /* 80 -50 */ CWORD_CWORD_CWORD_CWORD,
2710 /* 81 -49 */ CWORD_CWORD_CWORD_CWORD,
2711 /* 82 -48 */ CWORD_CWORD_CWORD_CWORD,
2712 /* 83 -47 */ CWORD_CWORD_CWORD_CWORD,
2713 /* 84 -46 */ CWORD_CWORD_CWORD_CWORD,
2714 /* 85 -45 */ CWORD_CWORD_CWORD_CWORD,
2715 /* 86 -44 */ CWORD_CWORD_CWORD_CWORD,
2716 /* 87 -43 */ CWORD_CWORD_CWORD_CWORD,
2717 /* 88 -42 */ CWORD_CWORD_CWORD_CWORD,
2718 /* 89 -41 */ CWORD_CWORD_CWORD_CWORD,
2719 /* 90 -40 */ CWORD_CWORD_CWORD_CWORD,
2720 /* 91 -39 */ CWORD_CWORD_CWORD_CWORD,
2721 /* 92 -38 */ CWORD_CWORD_CWORD_CWORD,
2722 /* 93 -37 */ CWORD_CWORD_CWORD_CWORD,
2723 /* 94 -36 */ CWORD_CWORD_CWORD_CWORD,
2724 /* 95 -35 */ CWORD_CWORD_CWORD_CWORD,
2725 /* 96 -34 */ CWORD_CWORD_CWORD_CWORD,
2726 /* 97 -33 */ CWORD_CWORD_CWORD_CWORD,
2727 /* 98 -32 */ CWORD_CWORD_CWORD_CWORD,
2728 /* 99 -31 */ CWORD_CWORD_CWORD_CWORD,
2729 /* 100 -30 */ CWORD_CWORD_CWORD_CWORD,
2730 /* 101 -29 */ CWORD_CWORD_CWORD_CWORD,
2731 /* 102 -28 */ CWORD_CWORD_CWORD_CWORD,
2732 /* 103 -27 */ CWORD_CWORD_CWORD_CWORD,
2733 /* 104 -26 */ CWORD_CWORD_CWORD_CWORD,
2734 /* 105 -25 */ CWORD_CWORD_CWORD_CWORD,
2735 /* 106 -24 */ CWORD_CWORD_CWORD_CWORD,
2736 /* 107 -23 */ CWORD_CWORD_CWORD_CWORD,
2737 /* 108 -22 */ CWORD_CWORD_CWORD_CWORD,
2738 /* 109 -21 */ CWORD_CWORD_CWORD_CWORD,
2739 /* 110 -20 */ CWORD_CWORD_CWORD_CWORD,
2740 /* 111 -19 */ CWORD_CWORD_CWORD_CWORD,
2741 /* 112 -18 */ CWORD_CWORD_CWORD_CWORD,
2742 /* 113 -17 */ CWORD_CWORD_CWORD_CWORD,
2743 /* 114 -16 */ CWORD_CWORD_CWORD_CWORD,
2744 /* 115 -15 */ CWORD_CWORD_CWORD_CWORD,
2745 /* 116 -14 */ CWORD_CWORD_CWORD_CWORD,
2746 /* 117 -13 */ CWORD_CWORD_CWORD_CWORD,
2747 /* 118 -12 */ CWORD_CWORD_CWORD_CWORD,
2748 /* 119 -11 */ CWORD_CWORD_CWORD_CWORD,
2749 /* 120 -10 */ CWORD_CWORD_CWORD_CWORD,
2750 /* 121 -9 */ CWORD_CWORD_CWORD_CWORD,
2751 /* 122 -8 */ CWORD_CWORD_CWORD_CWORD,
2752 /* 123 -7 */ CWORD_CWORD_CWORD_CWORD,
2753 /* 124 -6 */ CWORD_CWORD_CWORD_CWORD,
2754 /* 125 -5 */ CWORD_CWORD_CWORD_CWORD,
2755 /* 126 -4 */ CWORD_CWORD_CWORD_CWORD,
2756 /* 127 -3 */ CWORD_CWORD_CWORD_CWORD,
2757 /* 128 -2 */ CWORD_CWORD_CWORD_CWORD,
2758 /* 129 -1 */ CWORD_CWORD_CWORD_CWORD,
2759 /* 130 0 */ CWORD_CWORD_CWORD_CWORD,
2760 /* 131 1 */ CWORD_CWORD_CWORD_CWORD,
2761 /* 132 2 */ CWORD_CWORD_CWORD_CWORD,
2762 /* 133 3 */ CWORD_CWORD_CWORD_CWORD,
2763 /* 134 4 */ CWORD_CWORD_CWORD_CWORD,
2764 /* 135 5 */ CWORD_CWORD_CWORD_CWORD,
2765 /* 136 6 */ CWORD_CWORD_CWORD_CWORD,
2766 /* 137 7 */ CWORD_CWORD_CWORD_CWORD,
2767 /* 138 8 */ CWORD_CWORD_CWORD_CWORD,
2768 /* 139 9 "\t" */ CSPCL_CWORD_CWORD_CWORD,
2769 /* 140 10 "\n" */ CNL_CNL_CNL_CNL,
2770 /* 141 11 */ CWORD_CWORD_CWORD_CWORD,
2771 /* 142 12 */ CWORD_CWORD_CWORD_CWORD,
2772 /* 143 13 */ CWORD_CWORD_CWORD_CWORD,
2773 /* 144 14 */ CWORD_CWORD_CWORD_CWORD,
2774 /* 145 15 */ CWORD_CWORD_CWORD_CWORD,
2775 /* 146 16 */ CWORD_CWORD_CWORD_CWORD,
2776 /* 147 17 */ CWORD_CWORD_CWORD_CWORD,
2777 /* 148 18 */ CWORD_CWORD_CWORD_CWORD,
2778 /* 149 19 */ CWORD_CWORD_CWORD_CWORD,
2779 /* 150 20 */ CWORD_CWORD_CWORD_CWORD,
2780 /* 151 21 */ CWORD_CWORD_CWORD_CWORD,
2781 /* 152 22 */ CWORD_CWORD_CWORD_CWORD,
2782 /* 153 23 */ CWORD_CWORD_CWORD_CWORD,
2783 /* 154 24 */ CWORD_CWORD_CWORD_CWORD,
2784 /* 155 25 */ CWORD_CWORD_CWORD_CWORD,
2785 /* 156 26 */ CWORD_CWORD_CWORD_CWORD,
2786 /* 157 27 */ CWORD_CWORD_CWORD_CWORD,
2787 /* 158 28 */ CWORD_CWORD_CWORD_CWORD,
2788 /* 159 29 */ CWORD_CWORD_CWORD_CWORD,
2789 /* 160 30 */ CWORD_CWORD_CWORD_CWORD,
2790 /* 161 31 */ CWORD_CWORD_CWORD_CWORD,
2791 /* 162 32 " " */ CSPCL_CWORD_CWORD_CWORD,
2792 /* 163 33 "!" */ CWORD_CCTL_CCTL_CWORD,
2793 /* 164 34 """ */ CDQUOTE_CENDQUOTE_CWORD_CWORD,
2794 /* 165 35 "#" */ CWORD_CWORD_CWORD_CWORD,
2795 /* 166 36 "$" */ CVAR_CVAR_CWORD_CVAR,
2796 /* 167 37 "%" */ CWORD_CWORD_CWORD_CWORD,
2797 /* 168 38 "&" */ CSPCL_CWORD_CWORD_CWORD,
2798 /* 169 39 "'" */ CSQUOTE_CWORD_CENDQUOTE_CWORD,
2799 /* 170 40 "(" */ CSPCL_CWORD_CWORD_CLP,
2800 /* 171 41 ")" */ CSPCL_CWORD_CWORD_CRP,
2801 /* 172 42 "*" */ CWORD_CCTL_CCTL_CWORD,
2802 /* 173 43 "+" */ CWORD_CWORD_CWORD_CWORD,
2803 /* 174 44 "," */ CWORD_CWORD_CWORD_CWORD,
2804 /* 175 45 "-" */ CWORD_CCTL_CCTL_CWORD,
2805 /* 176 46 "." */ CWORD_CWORD_CWORD_CWORD,
2806 /* 177 47 "/" */ CWORD_CCTL_CCTL_CWORD,
2807 /* 178 48 "0" */ CWORD_CWORD_CWORD_CWORD,
2808 /* 179 49 "1" */ CWORD_CWORD_CWORD_CWORD,
2809 /* 180 50 "2" */ CWORD_CWORD_CWORD_CWORD,
2810 /* 181 51 "3" */ CWORD_CWORD_CWORD_CWORD,
2811 /* 182 52 "4" */ CWORD_CWORD_CWORD_CWORD,
2812 /* 183 53 "5" */ CWORD_CWORD_CWORD_CWORD,
2813 /* 184 54 "6" */ CWORD_CWORD_CWORD_CWORD,
2814 /* 185 55 "7" */ CWORD_CWORD_CWORD_CWORD,
2815 /* 186 56 "8" */ CWORD_CWORD_CWORD_CWORD,
2816 /* 187 57 "9" */ CWORD_CWORD_CWORD_CWORD,
2817 /* 188 58 ":" */ CWORD_CCTL_CCTL_CWORD,
2818 /* 189 59 ";" */ CSPCL_CWORD_CWORD_CWORD,
2819 /* 190 60 "<" */ CSPCL_CWORD_CWORD_CWORD,
2820 /* 191 61 "=" */ CWORD_CCTL_CCTL_CWORD,
2821 /* 192 62 ">" */ CSPCL_CWORD_CWORD_CWORD,
2822 /* 193 63 "?" */ CWORD_CCTL_CCTL_CWORD,
2823 /* 194 64 "@" */ CWORD_CWORD_CWORD_CWORD,
2824 /* 195 65 "A" */ CWORD_CWORD_CWORD_CWORD,
2825 /* 196 66 "B" */ CWORD_CWORD_CWORD_CWORD,
2826 /* 197 67 "C" */ CWORD_CWORD_CWORD_CWORD,
2827 /* 198 68 "D" */ CWORD_CWORD_CWORD_CWORD,
2828 /* 199 69 "E" */ CWORD_CWORD_CWORD_CWORD,
2829 /* 200 70 "F" */ CWORD_CWORD_CWORD_CWORD,
2830 /* 201 71 "G" */ CWORD_CWORD_CWORD_CWORD,
2831 /* 202 72 "H" */ CWORD_CWORD_CWORD_CWORD,
2832 /* 203 73 "I" */ CWORD_CWORD_CWORD_CWORD,
2833 /* 204 74 "J" */ CWORD_CWORD_CWORD_CWORD,
2834 /* 205 75 "K" */ CWORD_CWORD_CWORD_CWORD,
2835 /* 206 76 "L" */ CWORD_CWORD_CWORD_CWORD,
2836 /* 207 77 "M" */ CWORD_CWORD_CWORD_CWORD,
2837 /* 208 78 "N" */ CWORD_CWORD_CWORD_CWORD,
2838 /* 209 79 "O" */ CWORD_CWORD_CWORD_CWORD,
2839 /* 210 80 "P" */ CWORD_CWORD_CWORD_CWORD,
2840 /* 211 81 "Q" */ CWORD_CWORD_CWORD_CWORD,
2841 /* 212 82 "R" */ CWORD_CWORD_CWORD_CWORD,
2842 /* 213 83 "S" */ CWORD_CWORD_CWORD_CWORD,
2843 /* 214 84 "T" */ CWORD_CWORD_CWORD_CWORD,
2844 /* 215 85 "U" */ CWORD_CWORD_CWORD_CWORD,
2845 /* 216 86 "V" */ CWORD_CWORD_CWORD_CWORD,
2846 /* 217 87 "W" */ CWORD_CWORD_CWORD_CWORD,
2847 /* 218 88 "X" */ CWORD_CWORD_CWORD_CWORD,
2848 /* 219 89 "Y" */ CWORD_CWORD_CWORD_CWORD,
2849 /* 220 90 "Z" */ CWORD_CWORD_CWORD_CWORD,
2850 /* 221 91 "[" */ CWORD_CCTL_CCTL_CWORD,
2851 /* 222 92 "\" */ CBACK_CBACK_CCTL_CBACK,
2852 /* 223 93 "]" */ CWORD_CCTL_CCTL_CWORD,
2853 /* 224 94 "^" */ CWORD_CWORD_CWORD_CWORD,
2854 /* 225 95 "_" */ CWORD_CWORD_CWORD_CWORD,
2855 /* 226 96 "`" */ CBQUOTE_CBQUOTE_CWORD_CBQUOTE,
2856 /* 227 97 "a" */ CWORD_CWORD_CWORD_CWORD,
2857 /* 228 98 "b" */ CWORD_CWORD_CWORD_CWORD,
2858 /* 229 99 "c" */ CWORD_CWORD_CWORD_CWORD,
2859 /* 230 100 "d" */ CWORD_CWORD_CWORD_CWORD,
2860 /* 231 101 "e" */ CWORD_CWORD_CWORD_CWORD,
2861 /* 232 102 "f" */ CWORD_CWORD_CWORD_CWORD,
2862 /* 233 103 "g" */ CWORD_CWORD_CWORD_CWORD,
2863 /* 234 104 "h" */ CWORD_CWORD_CWORD_CWORD,
2864 /* 235 105 "i" */ CWORD_CWORD_CWORD_CWORD,
2865 /* 236 106 "j" */ CWORD_CWORD_CWORD_CWORD,
2866 /* 237 107 "k" */ CWORD_CWORD_CWORD_CWORD,
2867 /* 238 108 "l" */ CWORD_CWORD_CWORD_CWORD,
2868 /* 239 109 "m" */ CWORD_CWORD_CWORD_CWORD,
2869 /* 240 110 "n" */ CWORD_CWORD_CWORD_CWORD,
2870 /* 241 111 "o" */ CWORD_CWORD_CWORD_CWORD,
2871 /* 242 112 "p" */ CWORD_CWORD_CWORD_CWORD,
2872 /* 243 113 "q" */ CWORD_CWORD_CWORD_CWORD,
2873 /* 244 114 "r" */ CWORD_CWORD_CWORD_CWORD,
2874 /* 245 115 "s" */ CWORD_CWORD_CWORD_CWORD,
2875 /* 246 116 "t" */ CWORD_CWORD_CWORD_CWORD,
2876 /* 247 117 "u" */ CWORD_CWORD_CWORD_CWORD,
2877 /* 248 118 "v" */ CWORD_CWORD_CWORD_CWORD,
2878 /* 249 119 "w" */ CWORD_CWORD_CWORD_CWORD,
2879 /* 250 120 "x" */ CWORD_CWORD_CWORD_CWORD,
2880 /* 251 121 "y" */ CWORD_CWORD_CWORD_CWORD,
2881 /* 252 122 "z" */ CWORD_CWORD_CWORD_CWORD,
2882 /* 253 123 "{" */ CWORD_CWORD_CWORD_CWORD,
2883 /* 254 124 "|" */ CSPCL_CWORD_CWORD_CWORD,
2884 /* 255 125 "}" */ CENDVAR_CENDVAR_CWORD_CENDVAR,
2885 /* 256 126 "~" */ CWORD_CCTL_CCTL_CWORD,
2886 /* 257 127 */ CWORD_CWORD_CWORD_CWORD,
2889 #define SIT(c, syntax) (S_I_T[(int)syntax_index_table[((int)c)+SYNBASE]][syntax])
2891 #endif /* USE_SIT_FUNCTION */
2894 /* ============ Alias handling */
2896 #if ENABLE_ASH_ALIAS
2898 #define ALIASINUSE 1
2910 static struct alias *atab[ATABSIZE];
2912 static struct alias **
2913 __lookupalias(const char *name) {
2914 unsigned int hashval;
2921 ch = (unsigned char)*p;
2925 ch = (unsigned char)*++p;
2927 app = &atab[hashval % ATABSIZE];
2929 for (; *app; app = &(*app)->next) {
2930 if (strcmp(name, (*app)->name) == 0) {
2938 static struct alias *
2939 lookupalias(const char *name, int check)
2941 struct alias *ap = *__lookupalias(name);
2943 if (check && ap && (ap->flag & ALIASINUSE))
2948 static struct alias *
2949 freealias(struct alias *ap)
2953 if (ap->flag & ALIASINUSE) {
2954 ap->flag |= ALIASDEAD;
2966 setalias(const char *name, const char *val)
2968 struct alias *ap, **app;
2970 app = __lookupalias(name);
2974 if (!(ap->flag & ALIASINUSE)) {
2977 ap->val = ckstrdup(val);
2978 ap->flag &= ~ALIASDEAD;
2981 ap = ckmalloc(sizeof(struct alias));
2982 ap->name = ckstrdup(name);
2983 ap->val = ckstrdup(val);
2992 unalias(const char *name)
2996 app = __lookupalias(name);
3000 *app = freealias(*app);
3011 struct alias *ap, **app;
3015 for (i = 0; i < ATABSIZE; i++) {
3017 for (ap = *app; ap; ap = *app) {
3018 *app = freealias(*app);
3028 printalias(const struct alias *ap)
3030 out1fmt("%s=%s\n", ap->name, single_quote(ap->val));
3034 * TODO - sort output
3037 aliascmd(int argc, char **argv)
3046 for (i = 0; i < ATABSIZE; i++)
3047 for (ap = atab[i]; ap; ap = ap->next) {
3052 while ((n = *++argv) != NULL) {
3053 v = strchr(n+1, '=');
3054 if (v == NULL) { /* n+1: funny ksh stuff */
3055 ap = *__lookupalias(n);
3057 fprintf(stderr, "%s: %s not found\n", "alias", n);
3071 unaliascmd(int argc, char **argv)
3075 while ((i = nextopt("a")) != '\0') {
3081 for (i = 0; *argptr; argptr++) {
3082 if (unalias(*argptr)) {
3083 fprintf(stderr, "%s: %s not found\n", "unalias", *argptr);
3091 #endif /* ASH_ALIAS */
3094 /* ============ jobs.c */
3096 /* Mode argument to forkshell. Don't change FORK_FG or FORK_BG. */
3099 #define FORK_NOJOB 2
3101 /* mode flags for showjob(s) */
3102 #define SHOW_PGID 0x01 /* only show pgid - for jobs -p */
3103 #define SHOW_PID 0x04 /* include process pid */
3104 #define SHOW_CHANGED 0x08 /* only jobs whose state has changed */
3107 * A job structure contains information about a job. A job is either a
3108 * single process or a set of processes contained in a pipeline. In the
3109 * latter case, pidlist will be non-NULL, and will point to a -1 terminated
3114 pid_t pid; /* process id */
3115 int status; /* last process status from wait() */
3116 char *cmd; /* text of command being run */
3120 struct procstat ps0; /* status of process */
3121 struct procstat *ps; /* status or processes when more than one */
3123 int stopstatus; /* status of a stopped job */
3126 nprocs: 16, /* number of processes */
3128 #define JOBRUNNING 0 /* at least one proc running */
3129 #define JOBSTOPPED 1 /* all procs are stopped */
3130 #define JOBDONE 2 /* all procs are completed */
3132 sigint: 1, /* job was killed by SIGINT */
3133 jobctl: 1, /* job running under job control */
3135 waited: 1, /* true if this entry has been waited for */
3136 used: 1, /* true if this entry is in used */
3137 changed: 1; /* true if status has changed */
3138 struct job *prev_job; /* previous job */
3141 static pid_t backgndpid; /* pid of last background process */
3142 static int job_warning; /* user was warned about stopped jobs */
3144 static int jobctl; /* true if doing job control */
3147 static struct job *makejob(union node *, int);
3148 static int forkshell(struct job *, union node *, int);
3149 static int waitforjob(struct job *);
3152 #define setjobctl(on) /* do nothing */
3154 static void setjobctl(int);
3155 static void showjobs(FILE *, int);
3159 * Set the signal handler for the specified signal. The routine figures
3160 * out what it should be set to.
3163 setsignal(int signo)
3167 struct sigaction act;
3172 else if (*t != '\0')
3176 if (rootshell && action == S_DFL) {
3179 if (iflag || minusc || sflag == 0)
3202 t = &sigmode[signo - 1];
3206 * current setting unknown
3208 if (sigaction(signo, 0, &act) == -1) {
3210 * Pretend it worked; maybe we should give a warning
3211 * here, but other shells don't. We don't alter
3212 * sigmode, so that we retry every time.
3216 if (act.sa_handler == SIG_IGN) {
3218 && (signo == SIGTSTP || signo == SIGTTIN || signo == SIGTTOU)
3220 tsig = S_IGN; /* don't hard ignore these */
3224 tsig = S_RESET; /* force to be set */
3227 if (tsig == S_HARD_IGN || tsig == action)
3231 act.sa_handler = onsig;
3234 act.sa_handler = SIG_IGN;
3237 act.sa_handler = SIG_DFL;
3241 sigfillset(&act.sa_mask);
3242 sigaction(signo, &act, 0);
3245 /* mode flags for set_curjob */
3246 #define CUR_DELETE 2
3247 #define CUR_RUNNING 1
3248 #define CUR_STOPPED 0
3250 /* mode flags for dowait */
3251 #define DOWAIT_NORMAL 0
3252 #define DOWAIT_BLOCK 1
3255 /* pgrp of shell on invocation */
3256 static int initialpgrp;
3257 static int ttyfd = -1;
3260 static struct job *jobtab;
3262 static unsigned njobs;
3264 static struct job *curjob;
3265 /* number of presumed living untracked jobs */
3269 set_curjob(struct job *jp, unsigned mode)
3272 struct job **jpp, **curp;
3274 /* first remove from list */
3275 jpp = curp = &curjob;
3280 jpp = &jp1->prev_job;
3282 *jpp = jp1->prev_job;
3284 /* Then re-insert in correct position */
3292 /* job being deleted */
3295 /* newly created job or backgrounded job,
3296 put after all stopped jobs. */
3300 if (!jp1 || jp1->state != JOBSTOPPED)
3303 jpp = &jp1->prev_job;
3309 /* newly stopped job - becomes curjob */
3310 jp->prev_job = *jpp;
3318 jobno(const struct job *jp)
3320 return jp - jobtab + 1;
3325 * Convert a job name to a job structure.
3328 getjob(const char *name, int getctl)
3332 const char *err_msg = "No such job: %s";
3336 char *(*match)(const char *, const char *);
3351 if (c == '+' || c == '%') {
3353 err_msg = "No current job";
3359 err_msg = "No previous job";
3370 jp = jobtab + num - 1;
3387 if (match(jp->ps[0].cmd, p)) {
3391 err_msg = "%s: ambiguous";
3398 err_msg = "job %s not created under job control";
3399 if (getctl && jp->jobctl == 0)
3404 ash_msg_and_raise_error(err_msg, name);
3408 * Mark a job structure as unused.
3411 freejob(struct job *jp)
3413 struct procstat *ps;
3417 for (i = jp->nprocs, ps = jp->ps; --i >= 0; ps++) {
3418 if (ps->cmd != nullstr)
3421 if (jp->ps != &jp->ps0)
3424 set_curjob(jp, CUR_DELETE);
3430 xtcsetpgrp(int fd, pid_t pgrp)
3432 if (tcsetpgrp(fd, pgrp))
3433 ash_msg_and_raise_error("cannot set tty process group (%m)");
3437 * Turn job control on and off.
3439 * Note: This code assumes that the third arg to ioctl is a character
3440 * pointer, which is true on Berkeley systems but not System V. Since
3441 * System V doesn't have job control yet, this isn't a problem now.
3443 * Called with interrupts off.
3451 if (on == jobctl || rootshell == 0)
3455 ofd = fd = open(_PATH_TTY, O_RDWR);
3457 /* BTW, bash will try to open(ttyname(0)) if open("/dev/tty") fails.
3458 * That sometimes helps to acquire controlling tty.
3459 * Obviously, a workaround for bugs when someone
3460 * failed to provide a controlling tty to bash! :) */
3462 while (!isatty(fd) && --fd >= 0)
3465 fd = fcntl(fd, F_DUPFD, 10);
3469 fcntl(fd, F_SETFD, FD_CLOEXEC);
3470 do { /* while we are in the background */
3471 pgrp = tcgetpgrp(fd);
3474 ash_msg("can't access tty; job control turned off");
3478 if (pgrp == getpgrp())
3489 xtcsetpgrp(fd, pgrp);
3491 /* turning job control off */
3494 xtcsetpgrp(fd, pgrp);
3508 killcmd(int argc, char **argv)
3518 ash_msg_and_raise_error(
3519 "usage: kill [-s sigspec | -signum | -sigspec] [pid | job]... or\n"
3520 "kill -l [exitstatus]"
3524 if (**++argv == '-') {
3525 signo = get_signum(*argv + 1);
3529 while ((c = nextopt("ls:")) != '\0') {
3539 signo = get_signum(optionarg);
3541 ash_msg_and_raise_error(
3542 "invalid signal number or name: %s",
3554 if (!list && signo < 0)
3557 if ((signo < 0 || !*argv) ^ list) {
3565 for (i = 1; i < NSIG; i++) {
3566 name = get_signame(i);
3568 out1fmt(snlfmt, name);
3572 name = get_signame(signo);
3573 if (!isdigit(*name))
3574 ash_msg_and_raise_error("invalid signal number or exit status: %s", *argptr);
3575 out1fmt(snlfmt, name);
3581 if (**argv == '%') {
3582 jp = getjob(*argv, 0);
3583 pid = -jp->ps[0].pid;
3585 pid = **argv == '-' ?
3586 -number(*argv + 1) : number(*argv);
3588 if (kill(pid, signo) != 0) {
3589 ash_msg("(%d) - %m", pid);
3598 showpipe(struct job *jp, FILE *out)
3600 struct procstat *sp;
3601 struct procstat *spend;
3603 spend = jp->ps + jp->nprocs;
3604 for (sp = jp->ps + 1; sp < spend; sp++)
3605 fprintf(out, " | %s", sp->cmd);
3606 outcslow('\n', out);
3607 flush_stdout_stderr();
3612 restartjob(struct job *jp, int mode)
3614 struct procstat *ps;
3620 if (jp->state == JOBDONE)
3622 jp->state = JOBRUNNING;
3624 if (mode == FORK_FG)
3625 xtcsetpgrp(ttyfd, pgid);
3626 killpg(pgid, SIGCONT);
3630 if (WIFSTOPPED(ps->status)) {
3633 } while (ps++, --i);
3635 status = (mode == FORK_FG) ? waitforjob(jp) : 0;
3641 fg_bgcmd(int argc, char **argv)
3648 mode = (**argv == 'f') ? FORK_FG : FORK_BG;
3653 jp = getjob(*argv, 1);
3654 if (mode == FORK_BG) {
3655 set_curjob(jp, CUR_RUNNING);
3656 fprintf(out, "[%d] ", jobno(jp));
3658 outstr(jp->ps->cmd, out);
3660 retval = restartjob(jp, mode);
3661 } while (*argv && *++argv);
3667 sprint_status(char *s, int status, int sigonly)
3673 if (!WIFEXITED(status)) {
3675 if (WIFSTOPPED(status))
3676 st = WSTOPSIG(status);
3679 st = WTERMSIG(status);
3681 if (st == SIGINT || st == SIGPIPE)
3684 if (WIFSTOPPED(status))
3689 col = fmtstr(s, 32, strsignal(st));
3690 if (WCOREDUMP(status)) {
3691 col += fmtstr(s + col, 16, " (core dumped)");
3693 } else if (!sigonly) {
3694 st = WEXITSTATUS(status);
3696 col = fmtstr(s, 16, "Done(%d)", st);
3698 col = fmtstr(s, 16, "Done");
3705 * Do a wait system call. If job control is compiled in, we accept
3706 * stopped processes. If block is zero, we return a value of zero
3707 * rather than blocking.
3709 * System V doesn't have a non-blocking wait system call. It does
3710 * have a SIGCLD signal that is sent to a process when one of it's
3711 * children dies. The obvious way to use SIGCLD would be to install
3712 * a handler for SIGCLD which simply bumped a counter when a SIGCLD
3713 * was received, and have waitproc bump another counter when it got
3714 * the status of a process. Waitproc would then know that a wait
3715 * system call would not block if the two counters were different.
3716 * This approach doesn't work because if a process has children that
3717 * have not been waited for, System V will send it a SIGCLD when it
3718 * installs a signal handler for SIGCLD. What this means is that when
3719 * a child exits, the shell will be sent SIGCLD signals continuously
3720 * until is runs out of stack space, unless it does a wait call before
3721 * restoring the signal handler. The code below takes advantage of
3722 * this (mis)feature by installing a signal handler for SIGCLD and
3723 * then checking to see whether it was called. If there are any
3724 * children to be waited for, it will be.
3726 * If neither SYSV nor BSD is defined, we don't implement nonblocking
3727 * waits at all. In this case, the user will not be informed when
3728 * a background process until the next time she runs a real program
3729 * (as opposed to running a builtin command or just typing return),
3730 * and the jobs command may give out of date information.
3733 waitproc(int block, int *status)
3743 return wait3(status, flags, (struct rusage *)NULL);
3747 * Wait for a process to terminate.
3750 dowait(int block, struct job *job)
3755 struct job *thisjob;
3758 TRACE(("dowait(%d) called\n", block));
3759 pid = waitproc(block, &status);
3760 TRACE(("wait returns pid %d, status=%d\n", pid, status));
3765 for (jp = curjob; jp; jp = jp->prev_job) {
3766 struct procstat *sp;
3767 struct procstat *spend;
3768 if (jp->state == JOBDONE)
3771 spend = jp->ps + jp->nprocs;
3774 if (sp->pid == pid) {
3775 TRACE(("Job %d: changing status of proc %d "
3776 "from 0x%x to 0x%x\n",
3777 jobno(jp), pid, sp->status, status));
3778 sp->status = status;
3781 if (sp->status == -1)
3784 if (state == JOBRUNNING)
3786 if (WIFSTOPPED(sp->status)) {
3787 jp->stopstatus = sp->status;
3791 } while (++sp < spend);
3796 if (!WIFSTOPPED(status))
3803 if (state != JOBRUNNING) {
3804 thisjob->changed = 1;
3806 if (thisjob->state != state) {
3807 TRACE(("Job %d: changing state from %d to %d\n",
3808 jobno(thisjob), thisjob->state, state));
3809 thisjob->state = state;
3811 if (state == JOBSTOPPED) {
3812 set_curjob(thisjob, CUR_STOPPED);
3821 if (thisjob && thisjob == job) {
3825 len = sprint_status(s, status, 1);
3837 showjob(FILE *out, struct job *jp, int mode)
3839 struct procstat *ps;
3840 struct procstat *psend;
3847 if (mode & SHOW_PGID) {
3848 /* just output process (group) id of pipeline */
3849 fprintf(out, "%d\n", ps->pid);
3853 col = fmtstr(s, 16, "[%d] ", jobno(jp));
3858 else if (curjob && jp == curjob->prev_job)
3861 if (mode & SHOW_PID)
3862 col += fmtstr(s + col, 16, "%d ", ps->pid);
3864 psend = ps + jp->nprocs;
3866 if (jp->state == JOBRUNNING) {
3867 strcpy(s + col, "Running");
3868 col += sizeof("Running") - 1;
3870 int status = psend[-1].status;
3871 if (jp->state == JOBSTOPPED)
3872 status = jp->stopstatus;
3873 col += sprint_status(s + col, status, 0);
3879 /* for each process */
3880 col = fmtstr(s, 48, " |\n%*c%d ", indent, ' ', ps->pid) - 3;
3882 fprintf(out, "%s%*c%s",
3883 s, 33 - col >= 0 ? 33 - col : 0, ' ', ps->cmd
3885 if (!(mode & SHOW_PID)) {
3889 if (++ps == psend) {
3890 outcslow('\n', out);
3897 if (jp->state == JOBDONE) {
3898 TRACE(("showjob: freeing job %d\n", jobno(jp)));
3904 jobscmd(int argc, char **argv)
3910 while ((m = nextopt("lp"))) {
3921 showjob(out, getjob(*argv,0), mode);
3924 showjobs(out, mode);
3930 * Print a list of jobs. If "change" is nonzero, only print jobs whose
3931 * statuses have changed since the last call to showjobs.
3934 showjobs(FILE *out, int mode)
3938 TRACE(("showjobs(%x) called\n", mode));
3940 /* If not even one one job changed, there is nothing to do */
3941 while (dowait(DOWAIT_NORMAL, NULL) > 0)
3944 for (jp = curjob; jp; jp = jp->prev_job) {
3945 if (!(mode & SHOW_CHANGED) || jp->changed)
3946 showjob(out, jp, mode);
3952 getstatus(struct job *job)
3957 status = job->ps[job->nprocs - 1].status;
3958 retval = WEXITSTATUS(status);
3959 if (!WIFEXITED(status)) {
3961 retval = WSTOPSIG(status);
3962 if (!WIFSTOPPED(status))
3965 /* XXX: limits number of signals */
3966 retval = WTERMSIG(status);
3968 if (retval == SIGINT)
3974 TRACE(("getstatus: job %d, nproc %d, status %x, retval %x\n",
3975 jobno(job), job->nprocs, status, retval));
3980 waitcmd(int argc, char **argv)
3993 /* wait for all jobs */
3998 /* no running procs */
4001 if (jp->state == JOBRUNNING)
4006 dowait(DOWAIT_BLOCK, 0);
4012 if (**argv != '%') {
4013 pid_t pid = number(*argv);
4017 if (job->ps[job->nprocs - 1].pid == pid)
4019 job = job->prev_job;
4025 job = getjob(*argv, 0);
4026 /* loop until process terminated or stopped */
4027 while (job->state == JOBRUNNING)
4028 dowait(DOWAIT_BLOCK, 0);
4030 retval = getstatus(job);
4044 struct job *jp, *jq;
4046 len = njobs * sizeof(*jp);
4048 jp = ckrealloc(jq, len + 4 * sizeof(*jp));
4050 offset = (char *)jp - (char *)jq;
4052 /* Relocate pointers */
4055 jq = (struct job *)((char *)jq + l);
4059 #define joff(p) ((struct job *)((char *)(p) + l))
4060 #define jmove(p) (p) = (void *)((char *)(p) + offset)
4061 if (joff(jp)->ps == &jq->ps0)
4062 jmove(joff(jp)->ps);
4063 if (joff(jp)->prev_job)
4064 jmove(joff(jp)->prev_job);
4074 jp = (struct job *)((char *)jp + len);
4078 } while (--jq >= jp);
4083 * Return a new job structure.
4084 * Called with interrupts off.
4087 makejob(union node *node, int nprocs)
4092 for (i = njobs, jp = jobtab; ; jp++) {
4099 if (jp->state != JOBDONE || !jp->waited)
4108 memset(jp, 0, sizeof(*jp));
4113 jp->prev_job = curjob;
4118 jp->ps = ckmalloc(nprocs * sizeof(struct procstat));
4120 TRACE(("makejob(0x%lx, %d) returns %%%d\n", (long)node, nprocs,
4127 * Return a string identifying a command (to be printed by the
4130 static char *cmdnextc;
4133 cmdputs(const char *s)
4135 const char *p, *str;
4136 char c, cc[2] = " ";
4140 static const char vstype[VSTYPE + 1][4] = {
4141 "", "}", "-", "+", "?", "=",
4142 "%", "%%", "#", "##"
4145 nextc = makestrspace((strlen(s) + 1) * 8, cmdnextc);
4147 while ((c = *p++) != 0) {
4155 if ((subtype & VSTYPE) == VSLENGTH)
4159 if (!(subtype & VSQUOTE) == !(quoted & 1))
4165 str = "\"}" + !(quoted & 1);
4172 case CTLBACKQ+CTLQUOTE:
4175 #if ENABLE_ASH_MATH_SUPPORT
4190 if ((subtype & VSTYPE) != VSNORMAL)
4192 str = vstype[subtype & VSTYPE];
4193 if (subtype & VSNUL)
4202 /* These can only happen inside quotes */
4215 while ((c = *str++)) {
4220 USTPUTC('"', nextc);
4226 /* cmdtxt() and cmdlist() call each other */
4227 static void cmdtxt(union node *n);
4230 cmdlist(union node *np, int sep)
4232 for (; np; np = np->narg.next) {
4236 if (sep && np->narg.next)
4242 cmdtxt(union node *n)
4245 struct nodelist *lp;
4257 lp = n->npipe.cmdlist;
4275 cmdtxt(n->nbinary.ch1);
4291 cmdtxt(n->nif.test);
4294 if (n->nif.elsepart) {
4297 n = n->nif.elsepart;
4313 cmdtxt(n->nbinary.ch1);
4323 cmdputs(n->nfor.var);
4325 cmdlist(n->nfor.args, 1);
4330 cmdputs(n->narg.text);
4334 cmdlist(n->ncmd.args, 1);
4335 cmdlist(n->ncmd.redirect, 0);
4348 cmdputs(n->ncase.expr->narg.text);
4350 for (np = n->ncase.cases; np; np = np->nclist.next) {
4351 cmdtxt(np->nclist.pattern);
4353 cmdtxt(np->nclist.body);
4379 s[0] = n->nfile.fd + '0';
4383 if (n->type == NTOFD || n->type == NFROMFD) {
4384 s[0] = n->ndup.dupfd + '0';
4394 commandtext(union node *n)
4398 STARTSTACKSTR(cmdnextc);
4400 name = stackblock();
4401 TRACE(("commandtext: name %p, end %p\n\t\"%s\"\n",
4402 name, cmdnextc, cmdnextc));
4403 return ckstrdup(name);
4408 * Fork off a subshell. If we are doing job control, give the subshell its
4409 * own process group. Jp is a job structure that the job is to be added to.
4410 * N is the command that will be evaluated by the child. Both jp and n may
4411 * be NULL. The mode parameter can be one of the following:
4412 * FORK_FG - Fork off a foreground process.
4413 * FORK_BG - Fork off a background process.
4414 * FORK_NOJOB - Like FORK_FG, but don't give the process its own
4415 * process group even if job control is on.
4417 * When job control is turned off, background processes have their standard
4418 * input redirected to /dev/null (except for the second and later processes
4421 * Called with interrupts off.
4424 * Clear traps on a fork.
4431 for (tp = trap; tp < &trap[NSIG]; tp++) {
4432 if (*tp && **tp) { /* trap not NULL or SIG_IGN */
4437 setsignal(tp - trap);
4442 /* lives far away from here, needed for forkchild */
4443 static void closescript(void);
4445 forkchild(struct job *jp, union node *n, int mode)
4449 TRACE(("Child shell %d\n", getpid()));
4456 /* do job control only in root shell */
4458 if (mode != FORK_NOJOB && jp->jobctl && !oldlvl) {
4461 if (jp->nprocs == 0)
4464 pgrp = jp->ps[0].pid;
4465 /* This can fail because we are doing it in the parent also */
4466 (void)setpgid(0, pgrp);
4467 if (mode == FORK_FG)
4468 xtcsetpgrp(ttyfd, pgrp);
4473 if (mode == FORK_BG) {
4476 if (jp->nprocs == 0) {
4478 if (open(bb_dev_null, O_RDONLY) != 0)
4479 ash_msg_and_raise_error("can't open %s", bb_dev_null);
4482 if (!oldlvl && iflag) {
4487 for (jp = curjob; jp; jp = jp->prev_job)
4493 forkparent(struct job *jp, union node *n, int mode, pid_t pid)
4495 TRACE(("In parent shell: child = %d\n", pid));
4497 while (jobless && dowait(DOWAIT_NORMAL, 0) > 0);
4502 if (mode != FORK_NOJOB && jp->jobctl) {
4505 if (jp->nprocs == 0)
4508 pgrp = jp->ps[0].pid;
4509 /* This can fail because we are doing it in the child also */
4513 if (mode == FORK_BG) {
4514 backgndpid = pid; /* set $! */
4515 set_curjob(jp, CUR_RUNNING);
4518 struct procstat *ps = &jp->ps[jp->nprocs++];
4524 ps->cmd = commandtext(n);
4530 forkshell(struct job *jp, union node *n, int mode)
4534 TRACE(("forkshell(%%%d, %p, %d) called\n", jobno(jp), n, mode));
4537 TRACE(("Fork failed, errno=%d", errno));
4540 ash_msg_and_raise_error("cannot fork");
4543 forkchild(jp, n, mode);
4545 forkparent(jp, n, mode, pid);
4550 * Wait for job to finish.
4552 * Under job control we have the problem that while a child process is
4553 * running interrupts generated by the user are sent to the child but not
4554 * to the shell. This means that an infinite loop started by an inter-
4555 * active user may be hard to kill. With job control turned off, an
4556 * interactive user may place an interactive program inside a loop. If
4557 * the interactive program catches interrupts, the user doesn't want
4558 * these interrupts to also abort the loop. The approach we take here
4559 * is to have the shell ignore interrupt signals while waiting for a
4560 * foreground process to terminate, and then send itself an interrupt
4561 * signal if the child process was terminated by an interrupt signal.
4562 * Unfortunately, some programs want to do a bit of cleanup and then
4563 * exit on interrupt; unless these processes terminate themselves by
4564 * sending a signal to themselves (instead of calling exit) they will
4565 * confuse this approach.
4567 * Called with interrupts off.
4570 waitforjob(struct job *jp)
4574 TRACE(("waitforjob(%%%d) called\n", jobno(jp)));
4575 while (jp->state == JOBRUNNING) {
4576 dowait(DOWAIT_BLOCK, jp);
4581 xtcsetpgrp(ttyfd, rootpid);
4583 * This is truly gross.
4584 * If we're doing job control, then we did a TIOCSPGRP which
4585 * caused us (the shell) to no longer be in the controlling
4586 * session -- so we wouldn't have seen any ^C/SIGINT. So, we
4587 * intuit from the subprocess exit status whether a SIGINT
4588 * occurred, and if so interrupt ourselves. Yuck. - mycroft
4593 if (jp->state == JOBDONE)
4600 * return 1 if there are stopped jobs, otherwise 0
4612 if (jp && jp->state == JOBSTOPPED) {
4613 out2str("You have stopped jobs.\n");
4622 /* ============ redir.c
4624 * Code for dealing with input/output redirection.
4627 #define EMPTY -2 /* marks an unused slot in redirtab */
4629 # define PIPESIZE 4096 /* amount of buffering in a pipe */
4631 # define PIPESIZE PIPE_BUF
4635 * Open a file in noclobber mode.
4636 * The code was copied from bash.
4639 noclobberopen(const char *fname)
4642 struct stat finfo, finfo2;
4645 * If the file exists and is a regular file, return an error
4648 r = stat(fname, &finfo);
4649 if (r == 0 && S_ISREG(finfo.st_mode)) {
4655 * If the file was not present (r != 0), make sure we open it
4656 * exclusively so that if it is created before we open it, our open
4657 * will fail. Make sure that we do not truncate an existing file.
4658 * Note that we don't turn on O_EXCL unless the stat failed -- if the
4659 * file was not a regular file, we leave O_EXCL off.
4662 return open(fname, O_WRONLY|O_CREAT|O_EXCL, 0666);
4663 fd = open(fname, O_WRONLY|O_CREAT, 0666);
4665 /* If the open failed, return the file descriptor right away. */
4670 * OK, the open succeeded, but the file may have been changed from a
4671 * non-regular file to a regular file between the stat and the open.
4672 * We are assuming that the O_EXCL open handles the case where FILENAME
4673 * did not exist and is symlinked to an existing file between the stat
4678 * If we can open it and fstat the file descriptor, and neither check
4679 * revealed that it was a regular file, and the file has not been
4680 * replaced, return the file descriptor.
4682 if (fstat(fd, &finfo2) == 0 && !S_ISREG(finfo2.st_mode)
4683 && finfo.st_dev == finfo2.st_dev && finfo.st_ino == finfo2.st_ino)
4686 /* The file has been replaced. badness. */
4693 * Handle here documents. Normally we fork off a process to write the
4694 * data to a pipe. If the document is short, we can stuff the data in
4695 * the pipe without forking.
4697 /* openhere needs this forward reference */
4698 static void expandhere(union node *arg, int fd);
4700 openhere(union node *redir)
4706 ash_msg_and_raise_error("pipe call failed");
4707 if (redir->type == NHERE) {
4708 len = strlen(redir->nhere.doc->narg.text);
4709 if (len <= PIPESIZE) {
4710 full_write(pip[1], redir->nhere.doc->narg.text, len);
4714 if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) {
4716 signal(SIGINT, SIG_IGN);
4717 signal(SIGQUIT, SIG_IGN);
4718 signal(SIGHUP, SIG_IGN);
4720 signal(SIGTSTP, SIG_IGN);
4722 signal(SIGPIPE, SIG_DFL);
4723 if (redir->type == NHERE)
4724 full_write(pip[1], redir->nhere.doc->narg.text, len);
4726 expandhere(redir->nhere.doc, pip[1]);
4735 openredirect(union node *redir)
4740 switch (redir->nfile.type) {
4742 fname = redir->nfile.expfname;
4743 f = open(fname, O_RDONLY);
4748 fname = redir->nfile.expfname;
4749 f = open(fname, O_RDWR|O_CREAT|O_TRUNC, 0666);
4754 /* Take care of noclobber mode. */
4756 fname = redir->nfile.expfname;
4757 f = noclobberopen(fname);
4764 fname = redir->nfile.expfname;
4765 f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666);
4770 fname = redir->nfile.expfname;
4771 f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666);
4779 /* Fall through to eliminate warning. */
4786 f = openhere(redir);
4792 ash_msg_and_raise_error("cannot create %s: %s", fname, errmsg(errno, "nonexistent directory"));
4794 ash_msg_and_raise_error("cannot open %s: %s", fname, errmsg(errno, "no such file"));
4798 * Copy a file descriptor to be >= to. Returns -1
4799 * if the source file descriptor is closed, EMPTY if there are no unused
4800 * file descriptors left.
4803 copyfd(int from, int to)
4807 newfd = fcntl(from, F_DUPFD, to);
4809 if (errno == EMFILE)
4811 ash_msg_and_raise_error("%d: %m", from);
4817 dupredirect(union node *redir, int f)
4819 int fd = redir->nfile.fd;
4821 if (redir->nfile.type == NTOFD || redir->nfile.type == NFROMFD) {
4822 if (redir->ndup.dupfd >= 0) { /* if not ">&-" */
4823 copyfd(redir->ndup.dupfd, fd);
4835 * Process a list of redirection commands. If the REDIR_PUSH flag is set,
4836 * old file descriptors are stashed away so that the redirection can be
4837 * undone by calling popredir. If the REDIR_BACKQ flag is set, then the
4838 * standard output, and the standard error if it becomes a duplicate of
4839 * stdout, is saved in memory.
4841 /* flags passed to redirect */
4842 #define REDIR_PUSH 01 /* save previous values of file descriptors */
4843 #define REDIR_SAVEFD2 03 /* set preverrout */
4845 redirect(union node *redir, int flags)
4848 struct redirtab *sv;
4859 if (flags & REDIR_PUSH) {
4861 q = ckmalloc(sizeof(struct redirtab));
4862 q->next = redirlist;
4864 q->nullredirs = nullredirs - 1;
4865 for (i = 0; i < 10; i++)
4866 q->renamed[i] = EMPTY;
4873 if ((n->nfile.type == NTOFD || n->nfile.type == NFROMFD)
4874 && n->ndup.dupfd == fd)
4875 continue; /* redirect from/to same file descriptor */
4877 newfd = openredirect(n);
4880 if (sv && *(p = &sv->renamed[fd]) == EMPTY) {
4881 i = fcntl(fd, F_DUPFD, 10);
4888 ash_msg_and_raise_error("%d: %m", fd);
4898 dupredirect(n, newfd);
4899 } while ((n = n->nfile.next));
4901 if (flags & REDIR_SAVEFD2 && sv && sv->renamed[2] >= 0)
4902 preverrout_fd = sv->renamed[2];
4906 * Undo the effects of the last redirection.
4911 struct redirtab *rp;
4914 if (--nullredirs >= 0)
4918 for (i = 0; i < 10; i++) {
4919 if (rp->renamed[i] != EMPTY) {
4922 copyfd(rp->renamed[i], i);
4924 close(rp->renamed[i]);
4927 redirlist = rp->next;
4928 nullredirs = rp->nullredirs;
4934 * Undo all redirections. Called on error or interrupt.
4938 * Discard all saved file descriptors.
4941 clearredir(int drop)
4952 redirectsafe(union node *redir, int flags)
4955 volatile int saveint;
4956 struct jmploc *volatile savehandler = exception_handler;
4957 struct jmploc jmploc;
4960 err = setjmp(jmploc.loc) * 2;
4962 exception_handler = &jmploc;
4963 redirect(redir, flags);
4965 exception_handler = savehandler;
4966 if (err && exception != EXERROR)
4967 longjmp(exception_handler->loc, 1);
4968 RESTORE_INT(saveint);
4973 /* ============ Routines to expand arguments to commands
4975 * We have to deal with backquotes, shell variables, and file metacharacters.
4981 #define EXP_FULL 0x1 /* perform word splitting & file globbing */
4982 #define EXP_TILDE 0x2 /* do normal tilde expansion */
4983 #define EXP_VARTILDE 0x4 /* expand tildes in an assignment */
4984 #define EXP_REDIR 0x8 /* file glob for a redirection (1 match only) */
4985 #define EXP_CASE 0x10 /* keeps quotes around for CASE pattern */
4986 #define EXP_RECORD 0x20 /* need to record arguments for ifs breakup */
4987 #define EXP_VARTILDE2 0x40 /* expand tildes after colons only */
4988 #define EXP_WORD 0x80 /* expand word in parameter expansion */
4989 #define EXP_QWORD 0x100 /* expand word in quoted parameter expansion */
4993 #define RMESCAPE_ALLOC 0x1 /* Allocate a new string */
4994 #define RMESCAPE_GLOB 0x2 /* Add backslashes for glob */
4995 #define RMESCAPE_QUOTED 0x4 /* Remove CTLESC unless in quotes */
4996 #define RMESCAPE_GROW 0x8 /* Grow strings instead of stalloc */
4997 #define RMESCAPE_HEAP 0x10 /* Malloc strings instead of stalloc */
5000 * Structure specifying which parts of the string should be searched
5001 * for IFS characters.
5004 struct ifsregion *next; /* next region in list */
5005 int begoff; /* offset of start of region */
5006 int endoff; /* offset of end of region */
5007 int nulonly; /* search for nul bytes only */
5011 struct strlist *list;
5012 struct strlist **lastp;
5015 /* output of current string */
5016 static char *expdest;
5017 /* list of back quote expressions */
5018 static struct nodelist *argbackq;
5019 /* first struct in list of ifs regions */
5020 static struct ifsregion ifsfirst;
5021 /* last struct in list */
5022 static struct ifsregion *ifslastp;
5023 /* holds expanded arg list */
5024 static struct arglist exparg;
5034 expdest = makestrspace(32, expdest);
5035 #if ENABLE_ASH_MATH_SUPPORT_64
5036 len = fmtstr(expdest, 32, "%lld", (long long) num);
5038 len = fmtstr(expdest, 32, "%ld", num);
5040 STADJUST(len, expdest);
5045 esclen(const char *start, const char *p)
5049 while (p > start && *--p == CTLESC) {
5056 * Remove any CTLESC characters from a string.
5059 _rmescapes(char *str, int flag)
5062 static const char qchars[] = { CTLESC, CTLQUOTEMARK, 0 };
5067 p = strpbrk(str, qchars);
5073 if (flag & RMESCAPE_ALLOC) {
5074 size_t len = p - str;
5075 size_t fulllen = len + strlen(p) + 1;
5077 if (flag & RMESCAPE_GROW) {
5078 r = makestrspace(fulllen, expdest);
5079 } else if (flag & RMESCAPE_HEAP) {
5080 r = ckmalloc(fulllen);
5082 r = stalloc(fulllen);
5086 q = memcpy(q, str, len) + len;
5089 inquotes = (flag & RMESCAPE_QUOTED) ^ RMESCAPE_QUOTED;
5090 globbing = flag & RMESCAPE_GLOB;
5091 notescaped = globbing;
5093 if (*p == CTLQUOTEMARK) {
5094 inquotes = ~inquotes;
5096 notescaped = globbing;
5100 /* naked back slash */
5106 if (notescaped && inquotes && *p != '/') {
5110 notescaped = globbing;
5115 if (flag & RMESCAPE_GROW) {
5117 STADJUST(q - r + 1, expdest);
5121 #define rmescapes(p) _rmescapes((p), 0)
5123 #define pmatch(a, b) !fnmatch((a), (b), 0)
5126 * Prepare a pattern for a expmeta (internal glob(3)) call.
5128 * Returns an stalloced string.
5131 preglob(const char *pattern, int quoted, int flag)
5133 flag |= RMESCAPE_GLOB;
5135 flag |= RMESCAPE_QUOTED;
5137 return _rmescapes((char *)pattern, flag);
5141 * Put a string on the stack.
5144 memtodest(const char *p, size_t len, int syntax, int quotes)
5148 q = makestrspace(len * 2, q);
5151 int c = signed_char2int(*p++);
5154 if (quotes && (SIT(c, syntax) == CCTL || SIT(c, syntax) == CBACK))
5163 strtodest(const char *p, int syntax, int quotes)
5165 memtodest(p, strlen(p), syntax, quotes);
5169 * Record the fact that we have to scan this region of the
5170 * string for IFS characters.
5173 recordregion(int start, int end, int nulonly)
5175 struct ifsregion *ifsp;
5177 if (ifslastp == NULL) {
5181 ifsp = ckmalloc(sizeof(*ifsp));
5183 ifslastp->next = ifsp;
5187 ifslastp->begoff = start;
5188 ifslastp->endoff = end;
5189 ifslastp->nulonly = nulonly;
5193 removerecordregions(int endoff)
5195 if (ifslastp == NULL)
5198 if (ifsfirst.endoff > endoff) {
5199 while (ifsfirst.next != NULL) {
5200 struct ifsregion *ifsp;
5202 ifsp = ifsfirst.next->next;
5203 free(ifsfirst.next);
5204 ifsfirst.next = ifsp;
5207 if (ifsfirst.begoff > endoff)
5210 ifslastp = &ifsfirst;
5211 ifsfirst.endoff = endoff;
5216 ifslastp = &ifsfirst;
5217 while (ifslastp->next && ifslastp->next->begoff < endoff)
5218 ifslastp=ifslastp->next;
5219 while (ifslastp->next != NULL) {
5220 struct ifsregion *ifsp;
5222 ifsp = ifslastp->next->next;
5223 free(ifslastp->next);
5224 ifslastp->next = ifsp;
5227 if (ifslastp->endoff > endoff)
5228 ifslastp->endoff = endoff;
5232 exptilde(char *startp, char *p, int flag)
5238 int quotes = flag & (EXP_FULL | EXP_CASE);
5243 while ((c = *++p) != '\0') {
5250 if (flag & EXP_VARTILDE)
5260 if (*name == '\0') {
5261 home = lookupvar(homestr);
5263 pw = getpwnam(name);
5268 if (!home || !*home)
5271 startloc = expdest - (char *)stackblock();
5272 strtodest(home, SQSYNTAX, quotes);
5273 recordregion(startloc, expdest - (char *)stackblock(), 0);
5281 * Execute a command inside back quotes. If it's a builtin command, we
5282 * want to save its output in a block obtained from malloc. Otherwise
5283 * we fork off a subprocess and get the output of the command via a pipe.
5284 * Should be called with interrupts off.
5286 struct backcmd { /* result of evalbackcmd */
5287 int fd; /* file descriptor to read from */
5288 char *buf; /* buffer */
5289 int nleft; /* number of chars in buffer */
5290 struct job *jp; /* job structure for command */
5293 /* These forward decls are needed to use "eval" code for backticks handling: */
5294 static int back_exitstatus; /* exit status of backquoted command */
5295 #define EV_EXIT 01 /* exit after evaluating tree */
5296 static void evaltree(union node *, int);
5299 evalbackcmd(union node *n, struct backcmd *result)
5311 saveherefd = herefd;
5319 ash_msg_and_raise_error("pipe call failed");
5321 if (forkshell(jp, n, FORK_NOJOB) == 0) {
5330 evaltree(n, EV_EXIT); /* actually evaltreenr... */
5334 result->fd = pip[0];
5337 herefd = saveherefd;
5339 TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n",
5340 result->fd, result->buf, result->nleft, result->jp));
5344 * Expand stuff in backwards quotes.
5347 expbackq(union node *cmd, int quoted, int quotes)
5355 int syntax = quoted? DQSYNTAX : BASESYNTAX;
5356 struct stackmark smark;
5359 setstackmark(&smark);
5361 startloc = dest - (char *)stackblock();
5363 evalbackcmd(cmd, &in);
5364 popstackmark(&smark);
5371 memtodest(p, i, syntax, quotes);
5375 i = safe_read(in.fd, buf, sizeof(buf));
5376 TRACE(("expbackq: read returns %d\n", i));
5386 back_exitstatus = waitforjob(in.jp);
5390 /* Eat all trailing newlines */
5392 for (; dest > (char *)stackblock() && dest[-1] == '\n';)
5397 recordregion(startloc, dest - (char *)stackblock(), 0);
5398 TRACE(("evalbackq: size=%d: \"%.*s\"\n",
5399 (dest - (char *)stackblock()) - startloc,
5400 (dest - (char *)stackblock()) - startloc,
5401 stackblock() + startloc));
5404 #if ENABLE_ASH_MATH_SUPPORT
5406 * Expand arithmetic expression. Backup to start of expression,
5407 * evaluate, place result in (backed up) result, adjust string position.
5420 * This routine is slightly over-complicated for
5421 * efficiency. Next we scan backwards looking for the
5422 * start of arithmetic.
5424 start = stackblock();
5431 while (*p != CTLARI) {
5435 ash_msg_and_raise_error("missing CTLARI (shouldn't happen)");
5440 esc = esclen(start, p);
5450 removerecordregions(begoff);
5459 len = cvtnum(dash_arith(p + 2));
5462 recordregion(begoff, begoff + len, 0);
5466 /* argstr needs it */
5467 static char *evalvar(char *p, int flag);
5470 * Perform variable and command substitution. If EXP_FULL is set, output CTLESC
5471 * characters to allow for further processing. Otherwise treat
5472 * $@ like $* since no splitting will be performed.
5475 argstr(char *p, int flag)
5477 static const char spclchars[] = {
5485 CTLBACKQ | CTLQUOTE,
5486 #if ENABLE_ASH_MATH_SUPPORT
5491 const char *reject = spclchars;
5493 int quotes = flag & (EXP_FULL | EXP_CASE); /* do CTLESC */
5494 int breakall = flag & EXP_WORD;
5499 if (!(flag & EXP_VARTILDE)) {
5501 } else if (flag & EXP_VARTILDE2) {
5506 if (flag & EXP_TILDE) {
5512 if (*q == CTLESC && (flag & EXP_QWORD))
5515 p = exptilde(p, q, flag);
5518 startloc = expdest - (char *)stackblock();
5520 length += strcspn(p + length, reject);
5522 if (c && (!(c & 0x80)
5523 #if ENABLE_ASH_MATH_SUPPORT
5527 /* c == '=' || c == ':' || c == CTLENDARI */
5532 expdest = stack_nputstr(p, length, expdest);
5533 newloc = expdest - (char *)stackblock();
5534 if (breakall && !inquotes && newloc > startloc) {
5535 recordregion(startloc, newloc, 0);
5546 if (flag & EXP_VARTILDE2) {
5550 flag |= EXP_VARTILDE2;
5555 * sort of a hack - expand tildes in variable
5556 * assignments (after the first '=' and after ':'s).
5565 case CTLENDVAR: /* ??? */
5568 /* "$@" syntax adherence hack */
5571 !memcmp(p, dolatstr, 4) &&
5572 (p[4] == CTLQUOTEMARK || (
5573 p[4] == CTLENDVAR &&
5574 p[5] == CTLQUOTEMARK
5577 p = evalvar(p + 1, flag) + 1;
5580 inquotes = !inquotes;
5593 p = evalvar(p, flag);
5597 case CTLBACKQ|CTLQUOTE:
5598 expbackq(argbackq->n, c, quotes);
5599 argbackq = argbackq->next;
5601 #if ENABLE_ASH_MATH_SUPPORT
5614 scanleft(char *startp, char *rmesc, char *rmescend, char *str, int quotes,
5625 const char *s = loc2;
5631 match = pmatch(str, s);
5635 if (quotes && *loc == CTLESC)
5644 scanright(char *startp, char *rmesc, char *rmescend, char *str, int quotes,
5651 for (loc = str - 1, loc2 = rmescend; loc >= startp; loc2--) {
5654 const char *s = loc2;
5659 match = pmatch(str, s);
5666 esc = esclen(startp, loc);
5677 static void varunset(const char *, const char *, const char *, int) ATTRIBUTE_NORETURN;
5679 varunset(const char *end, const char *var, const char *umsg, int varflags)
5685 msg = "parameter not set";
5687 if (*end == CTLENDVAR) {
5688 if (varflags & VSNUL)
5693 ash_msg_and_raise_error("%.*s: %s%s", end - var - 1, var, msg, tail);
5697 subevalvar(char *p, char *str, int strloc, int subtype, int startloc, int varflags, int quotes)
5701 int saveherefd = herefd;
5702 struct nodelist *saveargbackq = argbackq;
5704 char *rmesc, *rmescend;
5706 char *(*scan)(char *, char *, char *, char *, int , int);
5709 argstr(p, subtype != VSASSIGN && subtype != VSQUESTION ? EXP_CASE : 0);
5710 STPUTC('\0', expdest);
5711 herefd = saveherefd;
5712 argbackq = saveargbackq;
5713 startp = stackblock() + startloc;
5717 setvar(str, startp, 0);
5718 amount = startp - expdest;
5719 STADJUST(amount, expdest);
5723 varunset(p, str, startp, varflags);
5727 subtype -= VSTRIMRIGHT;
5729 if (subtype < 0 || subtype > 3)
5734 rmescend = stackblock() + strloc;
5736 rmesc = _rmescapes(startp, RMESCAPE_ALLOC | RMESCAPE_GROW);
5737 if (rmesc != startp) {
5739 startp = stackblock() + startloc;
5743 str = stackblock() + strloc;
5744 preglob(str, varflags & VSQUOTE, 0);
5746 /* zero = subtype == VSTRIMLEFT || subtype == VSTRIMLEFTMAX */
5747 zero = subtype >> 1;
5748 /* VSTRIMLEFT/VSTRIMRIGHTMAX -> scanleft */
5749 scan = (subtype & 1) ^ zero ? scanleft : scanright;
5751 loc = scan(startp, rmesc, rmescend, str, quotes, zero);
5754 memmove(startp, loc, str - loc);
5755 loc = startp + (str - loc) - 1;
5758 amount = loc - expdest;
5759 STADJUST(amount, expdest);
5765 * Add the value of a specialized variable to the stack string.
5768 varvalue(char *name, int varflags, int flags)
5778 int quoted = varflags & VSQUOTE;
5779 int subtype = varflags & VSTYPE;
5780 int quotes = flags & (EXP_FULL | EXP_CASE);
5782 if (quoted && (flags & EXP_FULL))
5783 sep = 1 << CHAR_BIT;
5785 syntax = quoted ? DQSYNTAX : BASESYNTAX;
5794 num = shellparam.nparam;
5804 p = makestrspace(NOPTS, expdest);
5805 for (i = NOPTS - 1; i >= 0; i--) {
5807 USTPUTC(optletters(i), p);
5818 sep = ifsset() ? signed_char2int(ifsval()[0]) : ' ';
5819 if (quotes && (SIT(sep, syntax) == CCTL || SIT(sep, syntax) == CBACK))
5825 while ((p = *ap++)) {
5828 partlen = strlen(p);
5831 if (!(subtype == VSPLUS || subtype == VSLENGTH))
5832 memtodest(p, partlen, syntax, quotes);
5838 if (subtype == VSPLUS || subtype == VSLENGTH) {
5860 if (num < 0 || num > shellparam.nparam)
5862 p = num ? shellparam.p[num - 1] : arg0;
5865 p = lookupvar(name);
5871 if (!(subtype == VSPLUS || subtype == VSLENGTH))
5872 memtodest(p, len, syntax, quotes);
5876 if (subtype == VSPLUS || subtype == VSLENGTH)
5877 STADJUST(-len, expdest);
5882 * Expand a variable, and return a pointer to the next character in the
5886 evalvar(char *p, int flag)
5899 quotes = flag & (EXP_FULL | EXP_CASE);
5901 subtype = varflags & VSTYPE;
5902 quoted = varflags & VSQUOTE;
5904 easy = (!quoted || (*var == '@' && shellparam.nparam));
5905 startloc = expdest - (char *)stackblock();
5906 p = strchr(p, '=') + 1;
5909 varlen = varvalue(var, varflags, flag);
5910 if (varflags & VSNUL)
5913 if (subtype == VSPLUS) {
5914 varlen = -1 - varlen;
5918 if (subtype == VSMINUS) {
5922 p, flag | EXP_TILDE |
5923 (quoted ? EXP_QWORD : EXP_WORD)
5932 if (subtype == VSASSIGN || subtype == VSQUESTION) {
5934 if (subevalvar(p, var, 0, subtype, startloc, varflags, 0)) {
5937 * Remove any recorded regions beyond
5940 removerecordregions(startloc);
5950 if (varlen < 0 && uflag)
5951 varunset(p, var, 0, 0);
5953 if (subtype == VSLENGTH) {
5954 cvtnum(varlen > 0 ? varlen : 0);
5958 if (subtype == VSNORMAL) {
5962 recordregion(startloc, expdest - (char *)stackblock(), quoted);
5971 case VSTRIMRIGHTMAX:
5980 * Terminate the string and start recording the pattern
5983 STPUTC('\0', expdest);
5984 patloc = expdest - (char *)stackblock();
5985 if (subevalvar(p, NULL, patloc, subtype,
5986 startloc, varflags, quotes) == 0) {
5987 int amount = expdest - (
5988 (char *)stackblock() + patloc - 1
5990 STADJUST(-amount, expdest);
5992 /* Remove any recorded regions beyond start of variable */
5993 removerecordregions(startloc);
5998 if (subtype != VSNORMAL) { /* skip to end of alternative */
6004 else if (c == CTLBACKQ || c == (CTLBACKQ|CTLQUOTE)) {
6006 argbackq = argbackq->next;
6007 } else if (c == CTLVAR) {
6008 if ((*p++ & VSTYPE) != VSNORMAL)
6010 } else if (c == CTLENDVAR) {
6020 * Break the argument string into pieces based upon IFS and add the
6021 * strings to the argument list. The regions of the string to be
6022 * searched for IFS characters have been stored by recordregion.
6025 ifsbreakup(char *string, struct arglist *arglist)
6027 struct ifsregion *ifsp;
6032 const char *ifs, *realifs;
6037 if (ifslastp != NULL) {
6040 realifs = ifsset() ? ifsval() : defifs;
6043 p = string + ifsp->begoff;
6044 nulonly = ifsp->nulonly;
6045 ifs = nulonly ? nullstr : realifs;
6047 while (p < string + ifsp->endoff) {
6051 if (!strchr(ifs, *p)) {
6056 ifsspc = (strchr(defifs, *p) != NULL);
6057 /* Ignore IFS whitespace at start */
6058 if (q == start && ifsspc) {
6064 sp = stalloc(sizeof(*sp));
6066 *arglist->lastp = sp;
6067 arglist->lastp = &sp->next;
6071 if (p >= string + ifsp->endoff) {
6077 if (strchr(ifs, *p) == NULL ) {
6080 } else if (strchr(defifs, *p) == NULL) {
6095 } while (ifsp != NULL);
6104 sp = stalloc(sizeof(*sp));
6106 *arglist->lastp = sp;
6107 arglist->lastp = &sp->next;
6113 struct ifsregion *p;
6118 struct ifsregion *ifsp;
6124 ifsfirst.next = NULL;
6129 * Add a file name to the list.
6132 addfname(const char *name)
6136 sp = stalloc(sizeof(*sp));
6137 sp->text = ststrdup(name);
6139 exparg.lastp = &sp->next;
6142 static char *expdir;
6145 * Do metacharacter (i.e. *, ?, [...]) expansion.
6148 expmeta(char *enddir, char *name)
6163 for (p = name; *p; p++) {
6164 if (*p == '*' || *p == '?')
6166 else if (*p == '[') {
6173 if (*q == '/' || *q == '\0')
6180 } else if (*p == '\\')
6182 else if (*p == '/') {
6189 if (metaflag == 0) { /* we've reached the end of the file name */
6190 if (enddir != expdir)
6198 if (metaflag == 0 || lstat(expdir, &statb) >= 0)
6209 } while (p < start);
6211 if (enddir == expdir) {
6213 } else if (enddir == expdir + 1 && *expdir == '/') {
6222 if (enddir != expdir)
6224 if (*endname == 0) {
6236 while (! intpending && (dp = readdir(dirp)) != NULL) {
6237 if (dp->d_name[0] == '.' && ! matchdot)
6239 if (pmatch(start, dp->d_name)) {
6241 strcpy(enddir, dp->d_name);
6244 for (p = enddir, cp = dp->d_name; (*p++ = *cp++) != '\0';)
6247 expmeta(p, endname);
6256 static struct strlist *
6257 msort(struct strlist *list, int len)
6259 struct strlist *p, *q = NULL;
6260 struct strlist **lpp;
6268 for (n = half; --n >= 0; ) {
6272 q->next = NULL; /* terminate first half of list */
6273 q = msort(list, half); /* sort first half of list */
6274 p = msort(p, len - half); /* sort second half */
6277 #if ENABLE_LOCALE_SUPPORT
6278 if (strcoll(p->text, q->text) < 0)
6280 if (strcmp(p->text, q->text) < 0)
6304 * Sort the results of file name expansion. It calculates the number of
6305 * strings to sort and then calls msort (short for merge sort) to do the
6308 static struct strlist *
6309 expsort(struct strlist *str)
6315 for (sp = str; sp; sp = sp->next)
6317 return msort(str, len);
6321 expandmeta(struct strlist *str, int flag)
6323 static const char metachars[] = {
6326 /* TODO - EXP_REDIR */
6329 struct strlist **savelastp;
6335 if (!strpbrk(str->text, metachars))
6337 savelastp = exparg.lastp;
6340 p = preglob(str->text, 0, RMESCAPE_ALLOC | RMESCAPE_HEAP);
6342 int i = strlen(str->text);
6343 expdir = ckmalloc(i < 2048 ? 2048 : i); /* XXX */
6351 if (exparg.lastp == savelastp) {
6356 *exparg.lastp = str;
6357 rmescapes(str->text);
6358 exparg.lastp = &str->next;
6360 *exparg.lastp = NULL;
6361 *savelastp = sp = expsort(*savelastp);
6362 while (sp->next != NULL)
6364 exparg.lastp = &sp->next;
6371 * Perform variable substitution and command substitution on an argument,
6372 * placing the resulting list of arguments in arglist. If EXP_FULL is true,
6373 * perform splitting and file name expansion. When arglist is NULL, perform
6374 * here document expansion.
6377 expandarg(union node *arg, struct arglist *arglist, int flag)
6382 argbackq = arg->narg.backquote;
6383 STARTSTACKSTR(expdest);
6384 ifsfirst.next = NULL;
6386 argstr(arg->narg.text, flag);
6387 p = _STPUTC('\0', expdest);
6389 if (arglist == NULL) {
6390 return; /* here document expanded */
6392 p = grabstackstr(p);
6393 exparg.lastp = &exparg.list;
6397 if (flag & EXP_FULL) {
6398 ifsbreakup(p, &exparg);
6399 *exparg.lastp = NULL;
6400 exparg.lastp = &exparg.list;
6401 expandmeta(exparg.list, flag);
6403 if (flag & EXP_REDIR) /*XXX - for now, just remove escapes */
6405 sp = stalloc(sizeof(*sp));
6408 exparg.lastp = &sp->next;
6412 *exparg.lastp = NULL;
6414 *arglist->lastp = exparg.list;
6415 arglist->lastp = exparg.lastp;
6420 * Expand shell variables and backquotes inside a here document.
6423 expandhere(union node *arg, int fd)
6426 expandarg(arg, (struct arglist *)NULL, 0);
6427 full_write(fd, stackblock(), expdest - (char *)stackblock());
6431 * Returns true if the pattern matches the string.
6434 patmatch(char *pattern, const char *string)
6436 return pmatch(preglob(pattern, 0, 0), string);
6440 * See if a pattern matches in a case statement.
6443 casematch(union node *pattern, char *val)
6445 struct stackmark smark;
6448 setstackmark(&smark);
6449 argbackq = pattern->narg.backquote;
6450 STARTSTACKSTR(expdest);
6452 argstr(pattern->narg.text, EXP_TILDE | EXP_CASE);
6453 STACKSTRNUL(expdest);
6454 result = patmatch(stackblock(), val);
6455 popstackmark(&smark);
6460 /* ============ find_command */
6462 #if ENABLE_FEATURE_SH_STANDALONE_SHELL
6464 is_safe_applet(char *name)
6466 /* It isn't a bug to have non-existent applet here... */
6467 /* ...just a waste of space... */
6468 static const char safe_applets[][8] = {
6472 USE_CHMOD (, "chmod" )
6473 USE_CHOWN (, "chown" )
6477 USE_ECHO (, "echo" )
6478 USE_FIND (, "find" )
6479 USE_HEXDUMP(, "hexdump")
6482 USE_MKDIR (, "mkdir" )
6484 USE_SORT (, "sort" )
6485 USE_TEST (, "test" )
6486 USE_TOUCH (, "touch" )
6487 USE_XARGS (, "xargs" )
6489 int n = sizeof(safe_applets) / sizeof(safe_applets[0]);
6491 for (i = 0; i < n; i++)
6492 if (strcmp(safe_applets[i], name) == 0)
6501 int (*builtin)(int, char **);
6502 /* unsigned flags; */
6504 #define IS_BUILTIN_SPECIAL(b) ((b)->name[0] & 1)
6505 #define IS_BUILTIN_REGULAR(b) ((b)->name[0] & 2)
6506 #define IS_BUILTIN_ASSIGN(b) ((b)->name[0] & 4)
6512 const struct builtincmd *cmd;
6513 struct funcnode *func;
6516 /* values of cmdtype */
6517 #define CMDUNKNOWN -1 /* no entry in table for command */
6518 #define CMDNORMAL 0 /* command is an executable program */
6519 #define CMDFUNCTION 1 /* command is a shell function */
6520 #define CMDBUILTIN 2 /* command is a shell builtin */
6522 /* action to find_command() */
6523 #define DO_ERR 0x01 /* prints errors */
6524 #define DO_ABS 0x02 /* checks absolute paths */
6525 #define DO_NOFUNC 0x04 /* don't return shell functions, for command */
6526 #define DO_ALTPATH 0x08 /* using alternate path */
6527 #define DO_ALTBLTIN 0x20 /* %builtin in alt. path */
6529 static void find_command(char *, struct cmdentry *, int, const char *);
6532 /* ============ Hashing commands */
6535 * When commands are first encountered, they are entered in a hash table.
6536 * This ensures that a full path search will not have to be done for them
6537 * on each invocation.
6539 * We should investigate converting to a linear search, even though that
6540 * would make the command name "hash" a misnomer.
6543 #define CMDTABLESIZE 31 /* should be prime */
6544 #define ARB 1 /* actual size determined at run time */
6547 struct tblentry *next; /* next entry in hash chain */
6548 union param param; /* definition of builtin function */
6549 short cmdtype; /* index identifying command */
6550 char rehash; /* if set, cd done since entry created */
6551 char cmdname[ARB]; /* name of command */
6554 static struct tblentry *cmdtable[CMDTABLESIZE];
6555 static int builtinloc = -1; /* index in path of %builtin, or -1 */
6558 tryexec(char *cmd, char **argv, char **envp)
6562 #if ENABLE_FEATURE_SH_STANDALONE_SHELL
6563 if (strchr(cmd, '/') == NULL) {
6564 struct BB_applet *a;
6567 a = find_applet_by_name(cmd);
6569 if (is_safe_applet(cmd)) {
6574 exit(a->main(c - argv, argv));
6576 /* re-exec ourselves with the new arguments */
6577 execve(CONFIG_BUSYBOX_EXEC_PATH, argv, envp);
6578 /* If they called chroot or otherwise made the binary no longer
6579 * executable, fall through */
6587 execve(cmd, argv, envp);
6588 } while (errno == EINTR);
6590 execve(cmd, argv, envp);
6594 } else if (errno == ENOEXEC) {
6598 for (ap = argv; *ap; ap++)
6600 ap = new = ckmalloc((ap - argv + 2) * sizeof(char *));
6602 *ap = cmd = (char *)DEFAULT_SHELL;
6605 while ((*ap++ = *argv++))
6613 * Exec a program. Never returns. If you change this routine, you may
6614 * have to change the find_command routine as well.
6616 #define environment() listvars(VEXPORT, VUNSET, 0)
6617 static void shellexec(char **, const char *, int) ATTRIBUTE_NORETURN;
6619 shellexec(char **argv, const char *path, int idx)
6627 envp = environment();
6628 if (strchr(argv[0], '/')
6629 #if ENABLE_FEATURE_SH_STANDALONE_SHELL
6630 || find_applet_by_name(argv[0])
6633 tryexec(argv[0], argv, envp);
6637 while ((cmdname = padvance(&path, argv[0])) != NULL) {
6638 if (--idx < 0 && pathopt == NULL) {
6639 tryexec(cmdname, argv, envp);
6640 if (errno != ENOENT && errno != ENOTDIR)
6647 /* Map to POSIX errors */
6659 exitstatus = exerrno;
6660 TRACE(("shellexec failed for %s, errno %d, suppressint %d\n",
6661 argv[0], e, suppressint ));
6662 ash_msg_and_raise(EXEXEC, "%s: %s", argv[0], errmsg(e, "not found"));
6667 printentry(struct tblentry *cmdp)
6673 idx = cmdp->param.index;
6676 name = padvance(&path, cmdp->cmdname);
6678 } while (--idx >= 0);
6679 out1fmt("%s%s\n", name, (cmdp->rehash ? "*" : nullstr));
6683 * Clear out command entries. The argument specifies the first entry in
6684 * PATH which has changed.
6687 clearcmdentry(int firstchange)
6689 struct tblentry **tblp;
6690 struct tblentry **pp;
6691 struct tblentry *cmdp;
6694 for (tblp = cmdtable; tblp < &cmdtable[CMDTABLESIZE]; tblp++) {
6696 while ((cmdp = *pp) != NULL) {
6697 if ((cmdp->cmdtype == CMDNORMAL &&
6698 cmdp->param.index >= firstchange)
6699 || (cmdp->cmdtype == CMDBUILTIN &&
6700 builtinloc >= firstchange)
6713 * Locate a command in the command hash table. If "add" is nonzero,
6714 * add the command to the table if it is not already present. The
6715 * variable "lastcmdentry" is set to point to the address of the link
6716 * pointing to the entry, so that delete_cmd_entry can delete the
6719 * Interrupts must be off if called with add != 0.
6721 static struct tblentry **lastcmdentry;
6723 static struct tblentry *
6724 cmdlookup(const char *name, int add)
6726 unsigned int hashval;
6728 struct tblentry *cmdp;
6729 struct tblentry **pp;
6732 hashval = (unsigned char)*p << 4;
6734 hashval += (unsigned char)*p++;
6736 pp = &cmdtable[hashval % CMDTABLESIZE];
6737 for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
6738 if (strcmp(cmdp->cmdname, name) == 0)
6742 if (add && cmdp == NULL) {
6743 cmdp = *pp = ckmalloc(sizeof(struct tblentry) - ARB
6744 + strlen(name) + 1);
6746 cmdp->cmdtype = CMDUNKNOWN;
6747 strcpy(cmdp->cmdname, name);
6754 * Delete the command entry returned on the last lookup.
6757 delete_cmd_entry(void)
6759 struct tblentry *cmdp;
6762 cmdp = *lastcmdentry;
6763 *lastcmdentry = cmdp->next;
6764 if (cmdp->cmdtype == CMDFUNCTION)
6765 freefunc(cmdp->param.func);
6771 * Add a new command entry, replacing any existing command entry for
6772 * the same name - except special builtins.
6775 addcmdentry(char *name, struct cmdentry *entry)
6777 struct tblentry *cmdp;
6779 cmdp = cmdlookup(name, 1);
6780 if (cmdp->cmdtype == CMDFUNCTION) {
6781 freefunc(cmdp->param.func);
6783 cmdp->cmdtype = entry->cmdtype;
6784 cmdp->param = entry->u;
6789 hashcmd(int argc, char **argv)
6791 struct tblentry **pp;
6792 struct tblentry *cmdp;
6794 struct cmdentry entry;
6797 while ((c = nextopt("r")) != '\0') {
6801 if (*argptr == NULL) {
6802 for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
6803 for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
6804 if (cmdp->cmdtype == CMDNORMAL)
6811 while ((name = *argptr) != NULL) {
6812 cmdp = cmdlookup(name, 0);
6814 && (cmdp->cmdtype == CMDNORMAL
6815 || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0)))
6817 find_command(name, &entry, DO_ERR, pathval());
6818 if (entry.cmdtype == CMDUNKNOWN)
6826 * Called when a cd is done. Marks all commands so the next time they
6827 * are executed they will be rehashed.
6832 struct tblentry **pp;
6833 struct tblentry *cmdp;
6835 for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
6836 for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
6837 if (cmdp->cmdtype == CMDNORMAL || (
6838 cmdp->cmdtype == CMDBUILTIN &&
6839 !(IS_BUILTIN_REGULAR(cmdp->param.cmd)) &&
6848 * Fix command hash table when PATH changed.
6849 * Called before PATH is changed. The argument is the new value of PATH;
6850 * pathval() still returns the old value at this point.
6851 * Called with interrupts off.
6854 changepath(const char *newval)
6856 const char *old, *new;
6863 firstchange = 9999; /* assume no change */
6869 if ((*old == '\0' && *new == ':')
6870 || (*old == ':' && *new == '\0'))
6872 old = new; /* ignore subsequent differences */
6876 if (*new == '%' && idx_bltin < 0 && prefix(new + 1, "builtin"))
6883 if (builtinloc < 0 && idx_bltin >= 0)
6884 builtinloc = idx_bltin; /* zap builtins */
6885 if (builtinloc >= 0 && idx_bltin < 0)
6887 clearcmdentry(firstchange);
6888 builtinloc = idx_bltin;
6903 #define TENDBQUOTE 12
6921 /* first char is indicating which tokens mark the end of a list */
6922 static const char *const tokname_array[] = {
6936 #define KWDOFFSET 13
6937 /* the following are keywords */
6959 static char buf[16];
6963 sprintf(buf + (tok >= TSEMI), "%s%c",
6964 tokname_array[tok] + 1, (tok >= TSEMI ? '"' : 0));
6968 /* Wrapper around strcmp for qsort/bsearch/... */
6970 pstrcmp(const void *a, const void *b)
6972 return strcmp((const char *) a, (*(const char *const *) b) + 1);
6975 static const char *const *
6976 findkwd(const char *s)
6978 return bsearch(s, tokname_array + KWDOFFSET,
6979 (sizeof(tokname_array) / sizeof(const char *)) - KWDOFFSET,
6980 sizeof(const char *), pstrcmp);
6984 * Locate and print what a word is...
6986 #if ENABLE_ASH_CMDCMD
6988 describe_command(char *command, int describe_command_verbose)
6990 #define describe_command_verbose 1
6992 describe_command(char *command)
6995 struct cmdentry entry;
6996 struct tblentry *cmdp;
6997 #if ENABLE_ASH_ALIAS
6998 const struct alias *ap;
7000 const char *path = pathval();
7002 if (describe_command_verbose) {
7006 /* First look at the keywords */
7007 if (findkwd(command)) {
7008 out1str(describe_command_verbose ? " is a shell keyword" : command);
7012 #if ENABLE_ASH_ALIAS
7013 /* Then look at the aliases */
7014 ap = lookupalias(command, 0);
7016 if (describe_command_verbose) {
7017 out1fmt(" is an alias for %s", ap->val);
7026 /* Then check if it is a tracked alias */
7027 cmdp = cmdlookup(command, 0);
7029 entry.cmdtype = cmdp->cmdtype;
7030 entry.u = cmdp->param;
7032 /* Finally use brute force */
7033 find_command(command, &entry, DO_ABS, path);
7036 switch (entry.cmdtype) {
7038 int j = entry.u.index;
7044 p = padvance(&path, command);
7048 if (describe_command_verbose) {
7050 (cmdp ? " a tracked alias for" : nullstr), p
7059 if (describe_command_verbose) {
7060 out1str(" is a shell function");
7067 if (describe_command_verbose) {
7068 out1fmt(" is a %sshell builtin",
7069 IS_BUILTIN_SPECIAL(entry.u.cmd) ?
7070 "special " : nullstr
7078 if (describe_command_verbose) {
7079 out1str(": not found\n");
7084 outstr("\n", stdout);
7089 typecmd(int argc, char **argv)
7094 for (i = 1; i < argc; i++) {
7095 #if ENABLE_ASH_CMDCMD
7096 err |= describe_command(argv[i], 1);
7098 err |= describe_command(argv[i]);
7104 #if ENABLE_ASH_CMDCMD
7106 commandcmd(int argc, char **argv)
7114 while ((c = nextopt("pvV")) != '\0')
7116 verify |= VERIFY_VERBOSE;
7118 verify |= VERIFY_BRIEF;
7124 return describe_command(*argptr, verify - VERIFY_BRIEF);
7131 /* ============ eval.c */
7133 static int funcblocksize; /* size of structures in function */
7134 static int funcstringsize; /* size of strings in node */
7135 static void *funcblock; /* block to allocate function from */
7136 static char *funcstring; /* block to allocate strings from */
7138 /* flags in argument to evaltree */
7139 #define EV_EXIT 01 /* exit after evaluating tree */
7140 #define EV_TESTED 02 /* exit status is checked; ignore -e flag */
7141 #define EV_BACKCMD 04 /* command executing within back quotes */
7143 static const short nodesize[26] = {
7144 SHELL_ALIGN(sizeof(struct ncmd)),
7145 SHELL_ALIGN(sizeof(struct npipe)),
7146 SHELL_ALIGN(sizeof(struct nredir)),
7147 SHELL_ALIGN(sizeof(struct nredir)),
7148 SHELL_ALIGN(sizeof(struct nredir)),
7149 SHELL_ALIGN(sizeof(struct nbinary)),
7150 SHELL_ALIGN(sizeof(struct nbinary)),
7151 SHELL_ALIGN(sizeof(struct nbinary)),
7152 SHELL_ALIGN(sizeof(struct nif)),
7153 SHELL_ALIGN(sizeof(struct nbinary)),
7154 SHELL_ALIGN(sizeof(struct nbinary)),
7155 SHELL_ALIGN(sizeof(struct nfor)),
7156 SHELL_ALIGN(sizeof(struct ncase)),
7157 SHELL_ALIGN(sizeof(struct nclist)),
7158 SHELL_ALIGN(sizeof(struct narg)),
7159 SHELL_ALIGN(sizeof(struct narg)),
7160 SHELL_ALIGN(sizeof(struct nfile)),
7161 SHELL_ALIGN(sizeof(struct nfile)),
7162 SHELL_ALIGN(sizeof(struct nfile)),
7163 SHELL_ALIGN(sizeof(struct nfile)),
7164 SHELL_ALIGN(sizeof(struct nfile)),
7165 SHELL_ALIGN(sizeof(struct ndup)),
7166 SHELL_ALIGN(sizeof(struct ndup)),
7167 SHELL_ALIGN(sizeof(struct nhere)),
7168 SHELL_ALIGN(sizeof(struct nhere)),
7169 SHELL_ALIGN(sizeof(struct nnot)),
7172 static void calcsize(union node *n);
7175 sizenodelist(struct nodelist *lp)
7178 funcblocksize += SHELL_ALIGN(sizeof(struct nodelist));
7185 calcsize(union node *n)
7189 funcblocksize += nodesize[n->type];
7192 calcsize(n->ncmd.redirect);
7193 calcsize(n->ncmd.args);
7194 calcsize(n->ncmd.assign);
7197 sizenodelist(n->npipe.cmdlist);
7202 calcsize(n->nredir.redirect);
7203 calcsize(n->nredir.n);
7210 calcsize(n->nbinary.ch2);
7211 calcsize(n->nbinary.ch1);
7214 calcsize(n->nif.elsepart);
7215 calcsize(n->nif.ifpart);
7216 calcsize(n->nif.test);
7219 funcstringsize += strlen(n->nfor.var) + 1;
7220 calcsize(n->nfor.body);
7221 calcsize(n->nfor.args);
7224 calcsize(n->ncase.cases);
7225 calcsize(n->ncase.expr);
7228 calcsize(n->nclist.body);
7229 calcsize(n->nclist.pattern);
7230 calcsize(n->nclist.next);
7234 sizenodelist(n->narg.backquote);
7235 funcstringsize += strlen(n->narg.text) + 1;
7236 calcsize(n->narg.next);
7243 calcsize(n->nfile.fname);
7244 calcsize(n->nfile.next);
7248 calcsize(n->ndup.vname);
7249 calcsize(n->ndup.next);
7253 calcsize(n->nhere.doc);
7254 calcsize(n->nhere.next);
7257 calcsize(n->nnot.com);
7263 nodeckstrdup(char *s)
7265 char *rtn = funcstring;
7267 strcpy(funcstring, s);
7268 funcstring += strlen(s) + 1;
7272 static union node *copynode(union node *);
7274 static struct nodelist *
7275 copynodelist(struct nodelist *lp)
7277 struct nodelist *start;
7278 struct nodelist **lpp;
7283 funcblock = (char *) funcblock + SHELL_ALIGN(sizeof(struct nodelist));
7284 (*lpp)->n = copynode(lp->n);
7286 lpp = &(*lpp)->next;
7293 copynode(union node *n)
7300 funcblock = (char *) funcblock + nodesize[n->type];
7304 new->ncmd.redirect = copynode(n->ncmd.redirect);
7305 new->ncmd.args = copynode(n->ncmd.args);
7306 new->ncmd.assign = copynode(n->ncmd.assign);
7309 new->npipe.cmdlist = copynodelist(n->npipe.cmdlist);
7310 new->npipe.backgnd = n->npipe.backgnd;
7315 new->nredir.redirect = copynode(n->nredir.redirect);
7316 new->nredir.n = copynode(n->nredir.n);
7323 new->nbinary.ch2 = copynode(n->nbinary.ch2);
7324 new->nbinary.ch1 = copynode(n->nbinary.ch1);
7327 new->nif.elsepart = copynode(n->nif.elsepart);
7328 new->nif.ifpart = copynode(n->nif.ifpart);
7329 new->nif.test = copynode(n->nif.test);
7332 new->nfor.var = nodeckstrdup(n->nfor.var);
7333 new->nfor.body = copynode(n->nfor.body);
7334 new->nfor.args = copynode(n->nfor.args);
7337 new->ncase.cases = copynode(n->ncase.cases);
7338 new->ncase.expr = copynode(n->ncase.expr);
7341 new->nclist.body = copynode(n->nclist.body);
7342 new->nclist.pattern = copynode(n->nclist.pattern);
7343 new->nclist.next = copynode(n->nclist.next);
7347 new->narg.backquote = copynodelist(n->narg.backquote);
7348 new->narg.text = nodeckstrdup(n->narg.text);
7349 new->narg.next = copynode(n->narg.next);
7356 new->nfile.fname = copynode(n->nfile.fname);
7357 new->nfile.fd = n->nfile.fd;
7358 new->nfile.next = copynode(n->nfile.next);
7362 new->ndup.vname = copynode(n->ndup.vname);
7363 new->ndup.dupfd = n->ndup.dupfd;
7364 new->ndup.fd = n->ndup.fd;
7365 new->ndup.next = copynode(n->ndup.next);
7369 new->nhere.doc = copynode(n->nhere.doc);
7370 new->nhere.fd = n->nhere.fd;
7371 new->nhere.next = copynode(n->nhere.next);
7374 new->nnot.com = copynode(n->nnot.com);
7377 new->type = n->type;
7382 * Make a copy of a parse tree.
7384 static struct funcnode *
7385 copyfunc(union node *n)
7390 funcblocksize = offsetof(struct funcnode, n);
7393 blocksize = funcblocksize;
7394 f = ckmalloc(blocksize + funcstringsize);
7395 funcblock = (char *) f + offsetof(struct funcnode, n);
7396 funcstring = (char *) f + blocksize;
7403 * Define a shell function.
7406 defun(char *name, union node *func)
7408 struct cmdentry entry;
7411 entry.cmdtype = CMDFUNCTION;
7412 entry.u.func = copyfunc(func);
7413 addcmdentry(name, &entry);
7417 static int evalskip; /* set if we are skipping commands */
7418 /* reasons for skipping commands (see comment on breakcmd routine) */
7419 #define SKIPBREAK (1 << 0)
7420 #define SKIPCONT (1 << 1)
7421 #define SKIPFUNC (1 << 2)
7422 #define SKIPFILE (1 << 3)
7423 #define SKIPEVAL (1 << 4)
7424 static int skipcount; /* number of levels to skip */
7425 static int funcnest; /* depth of function calls */
7427 /* forward decl way out to parsing code - dotrap needs it */
7428 static int evalstring(char *s, int mask);
7431 * Called to execute a trap. Perhaps we should avoid entering new trap
7432 * handlers while we are executing a trap handler.
7443 savestatus = exitstatus;
7447 for (i = 0, q = gotsig; i < NSIG - 1; i++, q++) {
7455 skip = evalstring(p, SKIPEVAL);
7456 exitstatus = savestatus;
7464 /* forward declarations - evaluation is fairly recursive business... */
7465 static void evalloop(union node *, int);
7466 static void evalfor(union node *, int);
7467 static void evalcase(union node *, int);
7468 static void evalsubshell(union node *, int);
7469 static void expredir(union node *);
7470 static void evalpipe(union node *, int);
7471 static void evalcommand(union node *, int);
7472 static int evalbltin(const struct builtincmd *, int, char **);
7473 static void prehash(union node *);
7476 * Evaluate a parse tree. The value is left in the global variable
7480 evaltree(union node *n, int flags)
7483 void (*evalfn)(union node *, int);
7487 TRACE(("evaltree(NULL) called\n"));
7490 TRACE(("pid %d, evaltree(%p: %d, %d) called\n",
7491 getpid(), n, n->type, flags));
7495 out1fmt("Node type = %d\n", n->type);
7500 evaltree(n->nnot.com, EV_TESTED);
7501 status = !exitstatus;
7504 expredir(n->nredir.redirect);
7505 status = redirectsafe(n->nredir.redirect, REDIR_PUSH);
7507 evaltree(n->nredir.n, flags & EV_TESTED);
7508 status = exitstatus;
7513 evalfn = evalcommand;
7515 if (eflag && !(flags & EV_TESTED))
7527 evalfn = evalsubshell;
7539 #error NAND + 1 != NOR
7541 #if NOR + 1 != NSEMI
7542 #error NOR + 1 != NSEMI
7544 isor = n->type - NAND;
7547 (flags | ((isor >> 1) - 1)) & EV_TESTED
7549 if (!exitstatus == isor)
7561 evaltree(n->nif.test, EV_TESTED);
7564 if (exitstatus == 0) {
7567 } else if (n->nif.elsepart) {
7568 n = n->nif.elsepart;
7573 defun(n->narg.text, n->narg.next);
7577 exitstatus = status;
7581 if ((checkexit & exitstatus))
7582 evalskip |= SKIPEVAL;
7583 else if (pendingsigs && dotrap())
7586 if (flags & EV_EXIT) {
7588 raise_exception(EXEXIT);
7592 #if !defined(__alpha__) || (defined(__GNUC__) && __GNUC__ >= 3)
7595 void evaltreenr(union node *, int) __attribute__ ((alias("evaltree"),__noreturn__));
7597 static int loopnest; /* current loop nesting level */
7600 evalloop(union node *n, int flags)
7610 evaltree(n->nbinary.ch1, EV_TESTED);
7613 if (evalskip == SKIPCONT && --skipcount <= 0) {
7617 if (evalskip == SKIPBREAK && --skipcount <= 0)
7622 if (n->type != NWHILE)
7626 evaltree(n->nbinary.ch2, flags);
7627 status = exitstatus;
7632 exitstatus = status;
7636 evalfor(union node *n, int flags)
7638 struct arglist arglist;
7641 struct stackmark smark;
7643 setstackmark(&smark);
7644 arglist.lastp = &arglist.list;
7645 for (argp = n->nfor.args; argp; argp = argp->narg.next) {
7646 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE | EXP_RECORD);
7651 *arglist.lastp = NULL;
7656 for (sp = arglist.list; sp; sp = sp->next) {
7657 setvar(n->nfor.var, sp->text, 0);
7658 evaltree(n->nfor.body, flags);
7660 if (evalskip == SKIPCONT && --skipcount <= 0) {
7664 if (evalskip == SKIPBREAK && --skipcount <= 0)
7671 popstackmark(&smark);
7675 evalcase(union node *n, int flags)
7679 struct arglist arglist;
7680 struct stackmark smark;
7682 setstackmark(&smark);
7683 arglist.lastp = &arglist.list;
7684 expandarg(n->ncase.expr, &arglist, EXP_TILDE);
7686 for (cp = n->ncase.cases; cp && evalskip == 0; cp = cp->nclist.next) {
7687 for (patp = cp->nclist.pattern; patp; patp = patp->narg.next) {
7688 if (casematch(patp, arglist.list->text)) {
7689 if (evalskip == 0) {
7690 evaltree(cp->nclist.body, flags);
7697 popstackmark(&smark);
7701 * Kick off a subshell to evaluate a tree.
7704 evalsubshell(union node *n, int flags)
7707 int backgnd = (n->type == NBACKGND);
7710 expredir(n->nredir.redirect);
7711 if (!backgnd && flags & EV_EXIT && !trap[0])
7715 if (forkshell(jp, n, backgnd) == 0) {
7719 flags &=~ EV_TESTED;
7721 redirect(n->nredir.redirect, 0);
7722 evaltreenr(n->nredir.n, flags);
7727 status = waitforjob(jp);
7728 exitstatus = status;
7733 * Compute the names of the files in a redirection list.
7735 static void fixredir(union node *, const char *, int);
7737 expredir(union node *n)
7741 for (redir = n; redir; redir = redir->nfile.next) {
7744 memset(&fn, 0, sizeof(fn));
7745 fn.lastp = &fn.list;
7746 switch (redir->type) {
7752 expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
7753 redir->nfile.expfname = fn.list->text;
7757 if (redir->ndup.vname) {
7758 expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE);
7759 if (fn.list == NULL)
7760 ash_msg_and_raise_error("redir error");
7761 fixredir(redir, fn.list->text, 1);
7769 * Evaluate a pipeline. All the processes in the pipeline are children
7770 * of the process creating the pipeline. (This differs from some versions
7771 * of the shell, which make the last process in a pipeline the parent
7775 evalpipe(union node *n, int flags)
7778 struct nodelist *lp;
7783 TRACE(("evalpipe(0x%lx) called\n", (long)n));
7785 for (lp = n->npipe.cmdlist; lp; lp = lp->next)
7789 jp = makejob(n, pipelen);
7791 for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
7795 if (pipe(pip) < 0) {
7797 ash_msg_and_raise_error("pipe call failed");
7800 if (forkshell(jp, lp->n, n->npipe.backgnd) == 0) {
7813 evaltreenr(lp->n, flags);
7821 if (n->npipe.backgnd == 0) {
7822 exitstatus = waitforjob(jp);
7823 TRACE(("evalpipe: job done exit status %d\n", exitstatus));
7829 * Controls whether the shell is interactive or not.
7832 setinteractive(int on)
7834 static int is_interactive;
7836 if (++on == is_interactive)
7838 is_interactive = on;
7842 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
7843 if (is_interactive > 1) {
7844 /* Looks like they want an interactive shell */
7845 static smallint do_banner;
7850 "%s Built-in shell (ash)\n"
7851 "Enter 'help' for a list of built-in commands."
7860 #if ENABLE_FEATURE_EDITING_VI
7861 #define setvimode(on) do { \
7862 if (on) line_input_state->flags |= VI_MODE; \
7863 else line_input_state->flags &= ~VI_MODE; \
7866 #define setvimode(on) viflag = 0 /* forcibly keep the option off */
7875 setinteractive(iflag);
7880 static struct localvar *localvars;
7883 * Called after a function returns.
7884 * Interrupts must be off.
7889 struct localvar *lvp;
7892 while ((lvp = localvars) != NULL) {
7893 localvars = lvp->next;
7895 TRACE(("poplocalvar %s", vp ? vp->text : "-"));
7896 if (vp == NULL) { /* $- saved */
7897 memcpy(optlist, lvp->text, sizeof(optlist));
7898 free((char*)lvp->text);
7900 } else if ((lvp->flags & (VUNSET|VSTRFIXED)) == VUNSET) {
7904 (*vp->func)(strchrnul(lvp->text, '=') + 1);
7905 if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
7906 free((char*)vp->text);
7907 vp->flags = lvp->flags;
7908 vp->text = lvp->text;
7915 evalfun(struct funcnode *func, int argc, char **argv, int flags)
7917 volatile struct shparam saveparam;
7918 struct localvar *volatile savelocalvars;
7919 struct jmploc *volatile savehandler;
7920 struct jmploc jmploc;
7923 saveparam = shellparam;
7924 savelocalvars = localvars;
7925 e = setjmp(jmploc.loc);
7930 savehandler = exception_handler;
7931 exception_handler = &jmploc;
7933 shellparam.malloc = 0;
7937 shellparam.nparam = argc - 1;
7938 shellparam.p = argv + 1;
7939 #if ENABLE_ASH_GETOPTS
7940 shellparam.optind = 1;
7941 shellparam.optoff = -1;
7943 evaltree(&func->n, flags & EV_TESTED);
7949 localvars = savelocalvars;
7950 freeparam(&shellparam);
7951 shellparam = saveparam;
7952 exception_handler = savehandler;
7954 evalskip &= ~SKIPFUNC;
7958 #if ENABLE_ASH_CMDCMD
7960 parse_command_args(char **argv, const char **path)
7973 if (c == '-' && !*cp) {
7983 /* run 'typecmd' for other options */
7994 * Make a variable a local variable. When a variable is made local, it's
7995 * value and flags are saved in a localvar structure. The saved values
7996 * will be restored when the shell function returns. We handle the name
7997 * "-" as a special case.
8002 struct localvar *lvp;
8007 lvp = ckmalloc(sizeof(struct localvar));
8008 if (LONE_DASH(name)) {
8010 p = ckmalloc(sizeof(optlist));
8011 lvp->text = memcpy(p, optlist, sizeof(optlist));
8016 vpp = hashvar(name);
8017 vp = *findvar(vpp, name);
8018 eq = strchr(name, '=');
8021 setvareq(name, VSTRFIXED);
8023 setvar(name, NULL, VSTRFIXED);
8024 vp = *vpp; /* the new variable */
8025 lvp->flags = VUNSET;
8027 lvp->text = vp->text;
8028 lvp->flags = vp->flags;
8029 vp->flags |= VSTRFIXED|VTEXTFIXED;
8035 lvp->next = localvars;
8041 * The "local" command.
8044 localcmd(int argc, char **argv)
8049 while ((name = *argv++) != NULL) {
8056 falsecmd(int argc, char **argv)
8062 truecmd(int argc, char **argv)
8068 execcmd(int argc, char **argv)
8071 iflag = 0; /* exit on error */
8074 shellexec(argv + 1, pathval(), 0);
8080 * The return command.
8083 returncmd(int argc, char **argv)
8086 * If called outside a function, do what ksh does;
8087 * skip the rest of the file.
8089 evalskip = funcnest ? SKIPFUNC : SKIPFILE;
8090 return argv[1] ? number(argv[1]) : exitstatus;
8093 /* Forward declarations for builtintab[] */
8094 static int breakcmd(int, char **);
8095 static int dotcmd(int, char **);
8096 static int evalcmd(int, char **);
8097 #if ENABLE_ASH_BUILTIN_ECHO
8098 static int echocmd(int, char **);
8100 #if ENABLE_ASH_BUILTIN_TEST
8101 static int testcmd(int, char **);
8103 static int exitcmd(int, char **);
8104 static int exportcmd(int, char **);
8105 #if ENABLE_ASH_GETOPTS
8106 static int getoptscmd(int, char **);
8108 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
8109 static int helpcmd(int argc, char **argv);
8111 #if ENABLE_ASH_MATH_SUPPORT
8112 static int letcmd(int, char **);
8114 static int readcmd(int, char **);
8115 static int setcmd(int, char **);
8116 static int shiftcmd(int, char **);
8117 static int timescmd(int, char **);
8118 static int trapcmd(int, char **);
8119 static int umaskcmd(int, char **);
8120 static int unsetcmd(int, char **);
8121 static int ulimitcmd(int, char **);
8123 #define BUILTIN_NOSPEC "0"
8124 #define BUILTIN_SPECIAL "1"
8125 #define BUILTIN_REGULAR "2"
8126 #define BUILTIN_SPEC_REG "3"
8127 #define BUILTIN_ASSIGN "4"
8128 #define BUILTIN_SPEC_ASSG "5"
8129 #define BUILTIN_REG_ASSG "6"
8130 #define BUILTIN_SPEC_REG_ASSG "7"
8132 /* make sure to keep these in proper order since it is searched via bsearch() */
8133 static const struct builtincmd builtintab[] = {
8134 { BUILTIN_SPEC_REG ".", dotcmd },
8135 { BUILTIN_SPEC_REG ":", truecmd },
8136 #if ENABLE_ASH_BUILTIN_TEST
8137 { BUILTIN_REGULAR "[", testcmd },
8138 { BUILTIN_REGULAR "[[", testcmd },
8140 #if ENABLE_ASH_ALIAS
8141 { BUILTIN_REG_ASSG "alias", aliascmd },
8144 { BUILTIN_REGULAR "bg", fg_bgcmd },
8146 { BUILTIN_SPEC_REG "break", breakcmd },
8147 { BUILTIN_REGULAR "cd", cdcmd },
8148 { BUILTIN_NOSPEC "chdir", cdcmd },
8149 #if ENABLE_ASH_CMDCMD
8150 { BUILTIN_REGULAR "command", commandcmd },
8152 { BUILTIN_SPEC_REG "continue", breakcmd },
8153 #if ENABLE_ASH_BUILTIN_ECHO
8154 { BUILTIN_REGULAR "echo", echocmd },
8156 { BUILTIN_SPEC_REG "eval", evalcmd },
8157 { BUILTIN_SPEC_REG "exec", execcmd },
8158 { BUILTIN_SPEC_REG "exit", exitcmd },
8159 { BUILTIN_SPEC_REG_ASSG "export", exportcmd },
8160 { BUILTIN_REGULAR "false", falsecmd },
8162 { BUILTIN_REGULAR "fg", fg_bgcmd },
8164 #if ENABLE_ASH_GETOPTS
8165 { BUILTIN_REGULAR "getopts", getoptscmd },
8167 { BUILTIN_NOSPEC "hash", hashcmd },
8168 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
8169 { BUILTIN_NOSPEC "help", helpcmd },
8172 { BUILTIN_REGULAR "jobs", jobscmd },
8173 { BUILTIN_REGULAR "kill", killcmd },
8175 #if ENABLE_ASH_MATH_SUPPORT
8176 { BUILTIN_NOSPEC "let", letcmd },
8178 { BUILTIN_ASSIGN "local", localcmd },
8179 { BUILTIN_NOSPEC "pwd", pwdcmd },
8180 { BUILTIN_REGULAR "read", readcmd },
8181 { BUILTIN_SPEC_REG_ASSG "readonly", exportcmd },
8182 { BUILTIN_SPEC_REG "return", returncmd },
8183 { BUILTIN_SPEC_REG "set", setcmd },
8184 { BUILTIN_SPEC_REG "shift", shiftcmd },
8185 { BUILTIN_SPEC_REG "source", dotcmd },
8186 #if ENABLE_ASH_BUILTIN_TEST
8187 { BUILTIN_REGULAR "test", testcmd },
8189 { BUILTIN_SPEC_REG "times", timescmd },
8190 { BUILTIN_SPEC_REG "trap", trapcmd },
8191 { BUILTIN_REGULAR "true", truecmd },
8192 { BUILTIN_NOSPEC "type", typecmd },
8193 { BUILTIN_NOSPEC "ulimit", ulimitcmd },
8194 { BUILTIN_REGULAR "umask", umaskcmd },
8195 #if ENABLE_ASH_ALIAS
8196 { BUILTIN_REGULAR "unalias", unaliascmd },
8198 { BUILTIN_SPEC_REG "unset", unsetcmd },
8199 { BUILTIN_REGULAR "wait", waitcmd },
8202 #define NUMBUILTINS (sizeof(builtintab) / sizeof(builtintab[0]))
8204 #define COMMANDCMD (builtintab + 5 + \
8205 2 * ENABLE_ASH_BUILTIN_TEST + \
8206 ENABLE_ASH_ALIAS + \
8207 ENABLE_ASH_JOB_CONTROL)
8208 #define EXECCMD (builtintab + 7 + \
8209 2 * ENABLE_ASH_BUILTIN_TEST + \
8210 ENABLE_ASH_ALIAS + \
8211 ENABLE_ASH_JOB_CONTROL + \
8212 ENABLE_ASH_CMDCMD + \
8213 ENABLE_ASH_BUILTIN_ECHO)
8216 * Search the table of builtin commands.
8218 static struct builtincmd *
8219 find_builtin(const char *name)
8221 struct builtincmd *bp;
8224 name, builtintab, NUMBUILTINS, sizeof(builtintab[0]),
8231 * Execute a simple command.
8233 static int back_exitstatus; /* exit status of backquoted command */
8235 isassignment(const char *p)
8237 const char *q = endofname(p);
8243 bltincmd(int argc, char **argv)
8245 /* Preserve exitstatus of a previous possible redirection
8246 * as POSIX mandates */
8247 return back_exitstatus;
8250 evalcommand(union node *cmd, int flags)
8252 static const struct builtincmd bltin = {
8255 struct stackmark smark;
8257 struct arglist arglist;
8258 struct arglist varlist;
8261 const struct strlist *sp;
8262 struct cmdentry cmdentry;
8270 struct builtincmd *bcmd;
8271 int pseudovarflag = 0;
8273 /* First expand the arguments. */
8274 TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
8275 setstackmark(&smark);
8276 back_exitstatus = 0;
8278 cmdentry.cmdtype = CMDBUILTIN;
8279 cmdentry.u.cmd = &bltin;
8280 varlist.lastp = &varlist.list;
8281 *varlist.lastp = NULL;
8282 arglist.lastp = &arglist.list;
8283 *arglist.lastp = NULL;
8286 if (cmd->ncmd.args) {
8287 bcmd = find_builtin(cmd->ncmd.args->narg.text);
8288 pseudovarflag = bcmd && IS_BUILTIN_ASSIGN(bcmd);
8291 for (argp = cmd->ncmd.args; argp; argp = argp->narg.next) {
8292 struct strlist **spp;
8294 spp = arglist.lastp;
8295 if (pseudovarflag && isassignment(argp->narg.text))
8296 expandarg(argp, &arglist, EXP_VARTILDE);
8298 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
8300 for (sp = *spp; sp; sp = sp->next)
8304 argv = nargv = stalloc(sizeof(char *) * (argc + 1));
8305 for (sp = arglist.list; sp; sp = sp->next) {
8306 TRACE(("evalcommand arg: %s\n", sp->text));
8307 *nargv++ = sp->text;
8312 if (iflag && funcnest == 0 && argc > 0)
8313 lastarg = nargv[-1];
8316 expredir(cmd->ncmd.redirect);
8317 status = redirectsafe(cmd->ncmd.redirect, REDIR_PUSH | REDIR_SAVEFD2);
8320 for (argp = cmd->ncmd.assign; argp; argp = argp->narg.next) {
8321 struct strlist **spp;
8324 spp = varlist.lastp;
8325 expandarg(argp, &varlist, EXP_VARTILDE);
8328 * Modify the command lookup path, if a PATH= assignment
8332 if (varequal(p, path))
8336 /* Print the command if xflag is set. */
8339 const char *p = " %s";
8342 dprintf(preverrout_fd, p, expandstr(ps4val()));
8345 for (n = 0; n < 2; n++) {
8347 dprintf(preverrout_fd, p, sp->text);
8355 full_write(preverrout_fd, "\n", 1);
8361 /* Now locate the command. */
8363 const char *oldpath;
8364 int cmd_flag = DO_ERR;
8369 find_command(argv[0], &cmdentry, cmd_flag, path);
8370 if (cmdentry.cmdtype == CMDUNKNOWN) {
8376 /* implement bltin and command here */
8377 if (cmdentry.cmdtype != CMDBUILTIN)
8380 spclbltin = IS_BUILTIN_SPECIAL(cmdentry.u.cmd);
8381 if (cmdentry.u.cmd == EXECCMD)
8383 #if ENABLE_ASH_CMDCMD
8384 if (cmdentry.u.cmd == COMMANDCMD) {
8386 nargv = parse_command_args(argv, &path);
8389 argc -= nargv - argv;
8391 cmd_flag |= DO_NOFUNC;
8399 /* We have a redirection error. */
8401 raise_exception(EXERROR);
8403 exitstatus = status;
8407 /* Execute the command. */
8408 switch (cmdentry.cmdtype) {
8410 /* Fork off a child process if necessary. */
8411 if (!(flags & EV_EXIT) || trap[0]) {
8413 jp = makejob(cmd, 1);
8414 if (forkshell(jp, cmd, FORK_FG) != 0) {
8415 exitstatus = waitforjob(jp);
8421 listsetvar(varlist.list, VEXPORT|VSTACK);
8422 shellexec(argv, path, cmdentry.u.index);
8426 cmdenviron = varlist.list;
8428 struct strlist *list = cmdenviron;
8430 if (spclbltin > 0 || argc == 0) {
8432 if (cmd_is_exec && argc > 1)
8435 listsetvar(list, i);
8437 if (evalbltin(cmdentry.u.cmd, argc, argv)) {
8452 exit_status = j + 128;
8453 exitstatus = exit_status;
8455 if (i == EXINT || spclbltin > 0) {
8457 longjmp(exception_handler->loc, 1);
8464 listsetvar(varlist.list, 0);
8465 if (evalfun(cmdentry.u.func, argc, argv, flags))
8471 popredir(cmd_is_exec);
8473 /* dsl: I think this is intended to be used to support
8474 * '_' in 'vi' command mode during line editing...
8475 * However I implemented that within libedit itself.
8477 setvar("_", lastarg, 0);
8478 popstackmark(&smark);
8482 evalbltin(const struct builtincmd *cmd, int argc, char **argv)
8484 char *volatile savecmdname;
8485 struct jmploc *volatile savehandler;
8486 struct jmploc jmploc;
8489 savecmdname = commandname;
8490 i = setjmp(jmploc.loc);
8493 savehandler = exception_handler;
8494 exception_handler = &jmploc;
8495 commandname = argv[0];
8497 optptr = NULL; /* initialize nextopt */
8498 exitstatus = (*cmd->builtin)(argc, argv);
8499 flush_stdout_stderr();
8501 exitstatus |= ferror(stdout);
8503 commandname = savecmdname;
8505 exception_handler = savehandler;
8511 goodname(const char *p)
8513 return !*endofname(p);
8518 * Search for a command. This is called before we fork so that the
8519 * location of the command will be available in the parent as well as
8520 * the child. The check for "goodname" is an overly conservative
8521 * check that the name will not be subject to expansion.
8524 prehash(union node *n)
8526 struct cmdentry entry;
8528 if (n->type == NCMD && n->ncmd.args && goodname(n->ncmd.args->narg.text))
8529 find_command(n->ncmd.args->narg.text, &entry, 0, pathval());
8533 /* ============ Builtin commands
8535 * Builtin commands whose functions are closely tied to evaluation
8536 * are implemented here.
8540 * Handle break and continue commands. Break, continue, and return are
8541 * all handled by setting the evalskip flag. The evaluation routines
8542 * above all check this flag, and if it is set they start skipping
8543 * commands rather than executing them. The variable skipcount is
8544 * the number of loops to break/continue, or the number of function
8545 * levels to return. (The latter is always 1.) It should probably
8546 * be an error to break out of more loops than exist, but it isn't
8547 * in the standard shell so we don't make it one here.
8550 breakcmd(int argc, char **argv)
8552 int n = argc > 1 ? number(argv[1]) : 1;
8555 ash_msg_and_raise_error(illnum, argv[1]);
8559 evalskip = (**argv == 'c') ? SKIPCONT : SKIPBREAK;
8566 /* ============ input.c
8568 * This implements the input routines used by the parser.
8571 #define EOF_NLEFT -99 /* value of parsenleft when EOF pushed back */
8574 INPUT_PUSH_FILE = 1,
8575 INPUT_NOFILE_OK = 2,
8579 * NEOF is returned by parsecmd when it encounters an end of file. It
8580 * must be distinct from NULL, so we use the address of a variable that
8581 * happens to be handy.
8583 static int plinno = 1; /* input line number */
8584 /* number of characters left in input buffer */
8585 static int parsenleft; /* copy of parsefile->nleft */
8586 static int parselleft; /* copy of parsefile->lleft */
8587 /* next character in input buffer */
8588 static char *parsenextc; /* copy of parsefile->nextc */
8590 static int checkkwd;
8591 /* values of checkkwd variable */
8592 #define CHKALIAS 0x1
8599 struct strpush *sp = parsefile->strpush;
8602 #if ENABLE_ASH_ALIAS
8604 if (parsenextc[-1] == ' ' || parsenextc[-1] == '\t') {
8605 checkkwd |= CHKALIAS;
8607 if (sp->string != sp->ap->val) {
8610 sp->ap->flag &= ~ALIASINUSE;
8611 if (sp->ap->flag & ALIASDEAD) {
8612 unalias(sp->ap->name);
8616 parsenextc = sp->prevstring;
8617 parsenleft = sp->prevnleft;
8618 /*dprintf("*** calling popstring: restoring to '%s'\n", parsenextc);*/
8619 parsefile->strpush = sp->prev;
8620 if (sp != &(parsefile->basestrpush))
8629 char *buf = parsefile->buf;
8633 #if ENABLE_FEATURE_EDITING
8634 if (!iflag || parsefile->fd)
8635 nr = safe_read(parsefile->fd, buf, BUFSIZ - 1);
8637 #if ENABLE_FEATURE_TAB_COMPLETION
8638 line_input_state->path_lookup = pathval();
8640 nr = read_line_input(cmdedit_prompt, buf, BUFSIZ, line_input_state);
8642 /* Ctrl+C pressed */
8651 if (nr < 0 && errno == 0) {
8652 /* Ctrl+D presend */
8657 nr = safe_read(parsefile->fd, buf, BUFSIZ - 1);
8661 if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
8662 int flags = fcntl(0, F_GETFL, 0);
8663 if (flags >= 0 && flags & O_NONBLOCK) {
8664 flags &=~ O_NONBLOCK;
8665 if (fcntl(0, F_SETFL, flags) >= 0) {
8666 out2str("sh: turning off NDELAY mode\n");
8676 * Refill the input buffer and return the next input character:
8678 * 1) If a string was pushed back on the input, pop it;
8679 * 2) If an EOF was pushed back (parsenleft == EOF_NLEFT) or we are reading
8680 * from a string so we can't refill the buffer, return EOF.
8681 * 3) If the is more stuff in this buffer, use it else call read to fill it.
8682 * 4) Process input up to the next newline, deleting nul characters.
8691 while (parsefile->strpush) {
8692 #if ENABLE_ASH_ALIAS
8693 if (parsenleft == -1 && parsefile->strpush->ap &&
8694 parsenextc[-1] != ' ' && parsenextc[-1] != '\t') {
8699 if (--parsenleft >= 0)
8700 return signed_char2int(*parsenextc++);
8702 if (parsenleft == EOF_NLEFT || parsefile->buf == NULL)
8704 flush_stdout_stderr();
8711 parselleft = parsenleft = EOF_NLEFT;
8718 /* delete nul characters */
8726 memmove(q, q + 1, more);
8730 parsenleft = q - parsenextc - 1;
8736 parsenleft = q - parsenextc - 1;
8748 out2str(parsenextc);
8753 return signed_char2int(*parsenextc++);
8756 #define pgetc_as_macro() (--parsenleft >= 0? signed_char2int(*parsenextc++) : preadbuffer())
8760 return pgetc_as_macro();
8763 #if ENABLE_ASH_OPTIMIZE_FOR_SIZE
8764 #define pgetc_macro() pgetc()
8766 #define pgetc_macro() pgetc_as_macro()
8770 * Same as pgetc(), but ignores PEOA.
8772 #if ENABLE_ASH_ALIAS
8780 } while (c == PEOA);
8787 return pgetc_macro();
8792 * Read a line from the script.
8795 pfgets(char *line, int len)
8801 while (--nleft > 0) {
8817 * Undo the last call to pgetc. Only one character may be pushed back.
8818 * PEOF may be pushed back.
8828 * Push a string back onto the input at this current parsefile level.
8829 * We handle aliases this way.
8832 pushstring(char *s, void *ap)
8839 /*dprintf("*** calling pushstring: %s, %d\n", s, len);*/
8840 if (parsefile->strpush) {
8841 sp = ckmalloc(sizeof(struct strpush));
8842 sp->prev = parsefile->strpush;
8843 parsefile->strpush = sp;
8845 sp = parsefile->strpush = &(parsefile->basestrpush);
8846 sp->prevstring = parsenextc;
8847 sp->prevnleft = parsenleft;
8848 #if ENABLE_ASH_ALIAS
8849 sp->ap = (struct alias *)ap;
8851 ((struct alias *)ap)->flag |= ALIASINUSE;
8861 * To handle the "." command, a stack of input files is used. Pushfile
8862 * adds a new entry to the stack and popfile restores the previous level.
8867 struct parsefile *pf;
8869 parsefile->nleft = parsenleft;
8870 parsefile->lleft = parselleft;
8871 parsefile->nextc = parsenextc;
8872 parsefile->linno = plinno;
8873 pf = ckmalloc(sizeof(*pf));
8874 pf->prev = parsefile;
8877 pf->basestrpush.prev = NULL;
8884 struct parsefile *pf = parsefile;
8893 parsefile = pf->prev;
8895 parsenleft = parsefile->nleft;
8896 parselleft = parsefile->lleft;
8897 parsenextc = parsefile->nextc;
8898 plinno = parsefile->linno;
8903 * Return to top level.
8908 while (parsefile != &basepf)
8913 * Close the file(s) that the shell is reading commands from. Called
8914 * after a fork is done.
8920 if (parsefile->fd > 0) {
8921 close(parsefile->fd);
8927 * Like setinputfile, but takes an open file descriptor. Call this with
8931 setinputfd(int fd, int push)
8933 fcntl(fd, F_SETFD, FD_CLOEXEC);
8939 if (parsefile->buf == NULL)
8940 parsefile->buf = ckmalloc(IBUFSIZ);
8941 parselleft = parsenleft = 0;
8946 * Set the input to take input from a file. If push is set, push the
8947 * old input onto the stack first.
8950 setinputfile(const char *fname, int flags)
8956 fd = open(fname, O_RDONLY);
8958 if (flags & INPUT_NOFILE_OK)
8960 ash_msg_and_raise_error("can't open %s", fname);
8963 fd2 = copyfd(fd, 10);
8966 ash_msg_and_raise_error("out of file descriptors");
8969 setinputfd(fd, flags & INPUT_PUSH_FILE);
8976 * Like setinputfile, but takes input from a string.
8979 setinputstring(char *string)
8983 parsenextc = string;
8984 parsenleft = strlen(string);
8985 parsefile->buf = NULL;
8991 /* ============ mail.c
8993 * Routines to check for mail.
8998 #define MAXMBOXES 10
9000 /* times of mailboxes */
9001 static time_t mailtime[MAXMBOXES];
9002 /* Set if MAIL or MAILPATH is changed. */
9003 static int mail_var_path_changed;
9006 * Print appropriate message(s) if mail has arrived.
9007 * If mail_var_path_changed is set,
9008 * then the value of MAIL has mail_var_path_changed,
9009 * so we just update the values.
9018 struct stackmark smark;
9021 setstackmark(&smark);
9022 mpath = mpathset() ? mpathval() : mailval();
9023 for (mtp = mailtime; mtp < mailtime + MAXMBOXES; mtp++) {
9024 p = padvance(&mpath, nullstr);
9029 for (q = p; *q; q++);
9034 q[-1] = '\0'; /* delete trailing '/' */
9035 if (stat(p, &statb) < 0) {
9039 if (!mail_var_path_changed && statb.st_mtime != *mtp) {
9042 pathopt ? pathopt : "you have mail"
9045 *mtp = statb.st_mtime;
9047 mail_var_path_changed = 0;
9048 popstackmark(&smark);
9052 changemail(const char *val)
9054 mail_var_path_changed++;
9057 #endif /* ASH_MAIL */
9060 /* ============ ??? */
9063 * Set the shell parameters.
9066 setparam(char **argv)
9072 for (nparam = 0; argv[nparam]; nparam++);
9073 ap = newparam = ckmalloc((nparam + 1) * sizeof(*ap));
9075 *ap++ = ckstrdup(*argv++);
9078 freeparam(&shellparam);
9079 shellparam.malloc = 1;
9080 shellparam.nparam = nparam;
9081 shellparam.p = newparam;
9082 #if ENABLE_ASH_GETOPTS
9083 shellparam.optind = 1;
9084 shellparam.optoff = -1;
9089 * Process shell options. The global variable argptr contains a pointer
9090 * to the argument list; we advance it past the options.
9093 minus_o(char *name, int val)
9098 for (i = 0; i < NOPTS; i++) {
9099 if (strcmp(name, optnames(i)) == 0) {
9104 ash_msg_and_raise_error("illegal option -o %s", name);
9106 out1str("Current option settings\n");
9107 for (i = 0; i < NOPTS; i++)
9108 out1fmt("%-16s%s\n", optnames(i),
9109 optlist[i] ? "on" : "off");
9112 setoption(int flag, int val)
9116 for (i = 0; i < NOPTS; i++) {
9117 if (optletters(i) == flag) {
9122 ash_msg_and_raise_error("illegal option -%c", flag);
9126 options(int cmdline)
9134 while ((p = *argptr) != NULL) {
9139 if (p[0] == '\0' || LONE_DASH(p)) {
9141 /* "-" means turn off -x and -v */
9144 /* "--" means reset params */
9145 else if (*argptr == NULL)
9148 break; /* "-" or "--" terminates options */
9150 } else if (c == '+') {
9156 while ((c = *p++) != '\0') {
9157 if (c == 'c' && cmdline) {
9158 minusc = p; /* command is after shell args*/
9159 } else if (c == 'o') {
9160 minus_o(*argptr, val);
9163 } else if (cmdline && (c == '-')) { // long options
9164 if (strcmp(p, "login") == 0)
9175 * The shift builtin command.
9178 shiftcmd(int argc, char **argv)
9185 n = number(argv[1]);
9186 if (n > shellparam.nparam)
9187 ash_msg_and_raise_error("can't shift that many");
9189 shellparam.nparam -= n;
9190 for (ap1 = shellparam.p; --n >= 0; ap1++) {
9191 if (shellparam.malloc)
9195 while ((*ap2++ = *ap1++) != NULL);
9196 #if ENABLE_ASH_GETOPTS
9197 shellparam.optind = 1;
9198 shellparam.optoff = -1;
9205 * POSIX requires that 'set' (but not export or readonly) output the
9206 * variables in lexicographic order - by the locale's collating order (sigh).
9207 * Maybe we could keep them in an ordered balanced binary tree
9208 * instead of hashed lists.
9209 * For now just roll 'em through qsort for printing...
9212 showvars(const char *sep_prefix, int on, int off)
9217 ep = listvars(on, off, &epend);
9218 qsort(ep, epend - ep, sizeof(char *), vpcmp);
9220 sep = *sep_prefix ? " " : sep_prefix;
9222 for (; ep < epend; ep++) {
9226 p = strchrnul(*ep, '=');
9229 q = single_quote(++p);
9230 out1fmt("%s%s%.*s%s\n", sep_prefix, sep, (int)(p - *ep), *ep, q);
9236 * The set command builtin.
9239 setcmd(int argc, char **argv)
9242 return showvars(nullstr, 0, VUNSET);
9246 if (*argptr != NULL) {
9253 #if ENABLE_ASH_RANDOM_SUPPORT
9254 /* Roughly copied from bash.. */
9256 change_random(const char *value)
9258 if (value == NULL) {
9259 /* "get", generate */
9262 rseed = rseed * 1103515245 + 12345;
9263 sprintf(buf, "%d", (unsigned int)((rseed & 32767)));
9264 /* set without recursion */
9265 setvar(vrandom.text, buf, VNOFUNC);
9266 vrandom.flags &= ~VNOFUNC;
9269 rseed = strtoul(value, (char **)NULL, 10);
9274 #if ENABLE_ASH_GETOPTS
9276 getopts(char *optstr, char *optvar, char **optfirst, int *param_optind, int *optoff)
9285 if (*param_optind < 1)
9287 optnext = optfirst + *param_optind - 1;
9289 if (*param_optind <= 1 || *optoff < 0 || strlen(optnext[-1]) < *optoff)
9292 p = optnext[-1] + *optoff;
9293 if (p == NULL || *p == '\0') {
9294 /* Current word is done, advance */
9296 if (p == NULL || *p != '-' || *++p == '\0') {
9303 if (LONE_DASH(p)) /* check for "--" */
9308 for (q = optstr; *q != c; ) {
9310 if (optstr[0] == ':') {
9313 err |= setvarsafe("OPTARG", s, 0);
9315 fprintf(stderr, "Illegal option -%c\n", c);
9326 if (*p == '\0' && (p = *optnext) == NULL) {
9327 if (optstr[0] == ':') {
9330 err |= setvarsafe("OPTARG", s, 0);
9333 fprintf(stderr, "No arg for -%c option\n", c);
9342 err |= setvarsafe("OPTARG", p, 0);
9345 err |= setvarsafe("OPTARG", nullstr, 0);
9347 *optoff = p ? p - *(optnext - 1) : -1;
9348 *param_optind = optnext - optfirst + 1;
9349 fmtstr(s, sizeof(s), "%d", *param_optind);
9350 err |= setvarsafe("OPTIND", s, VNOFUNC);
9353 err |= setvarsafe(optvar, s, 0);
9357 flush_stdout_stderr();
9358 raise_exception(EXERROR);
9364 * The getopts builtin. Shellparam.optnext points to the next argument
9365 * to be processed. Shellparam.optptr points to the next character to
9366 * be processed in the current argument. If shellparam.optnext is NULL,
9367 * then it's the first time getopts has been called.
9370 getoptscmd(int argc, char **argv)
9375 ash_msg_and_raise_error("usage: getopts optstring var [arg]");
9377 optbase = shellparam.p;
9378 if (shellparam.optind > shellparam.nparam + 1) {
9379 shellparam.optind = 1;
9380 shellparam.optoff = -1;
9384 if (shellparam.optind > argc - 2) {
9385 shellparam.optind = 1;
9386 shellparam.optoff = -1;
9390 return getopts(argv[1], argv[2], optbase, &shellparam.optind,
9391 &shellparam.optoff);
9393 #endif /* ASH_GETOPTS */
9396 /* ============ Shell parser */
9398 static int tokpushback; /* last token pushed back */
9399 #define NEOF ((union node *)&tokpushback)
9400 static int parsebackquote; /* nonzero if we are inside backquotes */
9401 static int lasttoken; /* last token read */
9402 static char *wordtext; /* text of last word returned by readtoken */
9403 static struct nodelist *backquotelist;
9404 static union node *redirnode;
9405 static struct heredoc *heredoc;
9406 static int quoteflag; /* set if (part of) last token was quoted */
9408 static void raise_error_syntax(const char *) ATTRIBUTE_NORETURN;
9410 raise_error_syntax(const char *msg)
9412 ash_msg_and_raise_error("syntax error: %s", msg);
9417 * Called when an unexpected token is read during the parse. The argument
9418 * is the token that is expected, or -1 if more than one type of token can
9419 * occur at this point.
9421 static void raise_error_unexpected_syntax(int) ATTRIBUTE_NORETURN;
9423 raise_error_unexpected_syntax(int token)
9428 l = sprintf(msg, "%s unexpected", tokname(lasttoken));
9430 sprintf(msg + l, " (expecting %s)", tokname(token));
9431 raise_error_syntax(msg);
9435 #define EOFMARKLEN 79
9438 struct heredoc *next; /* next here document in list */
9439 union node *here; /* redirection node */
9440 char *eofmark; /* string indicating end of input */
9441 int striptabs; /* if set, strip leading tabs */
9444 static struct heredoc *heredoclist; /* list of here documents to read */
9446 /* parsing is heavily cross-recursive, need these forward decls */
9447 static union node *andor(void);
9448 static union node *pipeline(void);
9449 static union node *parse_command(void);
9450 static void parseheredoc(void);
9451 static char peektoken(void);
9452 static int readtoken(void);
9457 union node *n1, *n2, *n3;
9460 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9461 if (nlflag == 2 && peektoken())
9467 if (tok == TBACKGND) {
9468 if (n2->type == NPIPE) {
9469 n2->npipe.backgnd = 1;
9471 if (n2->type != NREDIR) {
9472 n3 = stalloc(sizeof(struct nredir));
9474 n3->nredir.redirect = NULL;
9477 n2->type = NBACKGND;
9483 n3 = stalloc(sizeof(struct nbinary));
9485 n3->nbinary.ch1 = n1;
9486 n3->nbinary.ch2 = n2;
9502 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9510 pungetc(); /* push back EOF on input */
9514 raise_error_unexpected_syntax(-1);
9524 union node *n1, *n2, *n3;
9532 } else if (t == TOR) {
9538 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9540 n3 = stalloc(sizeof(struct nbinary));
9542 n3->nbinary.ch1 = n1;
9543 n3->nbinary.ch2 = n2;
9551 union node *n1, *n2, *pipenode;
9552 struct nodelist *lp, *prev;
9556 TRACE(("pipeline: entered\n"));
9557 if (readtoken() == TNOT) {
9559 checkkwd = CHKKWD | CHKALIAS;
9562 n1 = parse_command();
9563 if (readtoken() == TPIPE) {
9564 pipenode = stalloc(sizeof(struct npipe));
9565 pipenode->type = NPIPE;
9566 pipenode->npipe.backgnd = 0;
9567 lp = stalloc(sizeof(struct nodelist));
9568 pipenode->npipe.cmdlist = lp;
9572 lp = stalloc(sizeof(struct nodelist));
9573 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9574 lp->n = parse_command();
9576 } while (readtoken() == TPIPE);
9582 n2 = stalloc(sizeof(struct nnot));
9595 n = stalloc(sizeof(struct narg));
9597 n->narg.next = NULL;
9598 n->narg.text = wordtext;
9599 n->narg.backquote = backquotelist;
9604 fixredir(union node *n, const char *text, int err)
9606 TRACE(("Fix redir %s %d\n", text, err));
9608 n->ndup.vname = NULL;
9610 if (isdigit(text[0]) && text[1] == '\0')
9611 n->ndup.dupfd = text[0] - '0';
9612 else if (LONE_DASH(text))
9616 raise_error_syntax("Bad fd number");
9617 n->ndup.vname = makename();
9622 * Returns true if the text contains nothing to expand (no dollar signs
9626 noexpand(char *text)
9632 while ((c = *p++) != '\0') {
9633 if (c == CTLQUOTEMARK)
9637 else if (SIT(c, BASESYNTAX) == CCTL)
9646 union node *n = redirnode;
9648 if (readtoken() != TWORD)
9649 raise_error_unexpected_syntax(-1);
9650 if (n->type == NHERE) {
9651 struct heredoc *here = heredoc;
9657 TRACE(("Here document %d\n", n->type));
9658 if (!noexpand(wordtext) || (i = strlen(wordtext)) == 0 || i > EOFMARKLEN)
9659 raise_error_syntax("Illegal eof marker for << redirection");
9660 rmescapes(wordtext);
9661 here->eofmark = wordtext;
9663 if (heredoclist == NULL)
9666 for (p = heredoclist; p->next; p = p->next);
9669 } else if (n->type == NTOFD || n->type == NFROMFD) {
9670 fixredir(n, wordtext, 0);
9672 n->nfile.fname = makename();
9679 union node *args, **app;
9680 union node *n = NULL;
9681 union node *vars, **vpp;
9682 union node **rpp, *redir;
9692 savecheckkwd = CHKALIAS;
9694 checkkwd = savecheckkwd;
9695 switch (readtoken()) {
9697 n = stalloc(sizeof(struct narg));
9699 n->narg.text = wordtext;
9700 n->narg.backquote = backquotelist;
9701 if (savecheckkwd && isassignment(wordtext)) {
9703 vpp = &n->narg.next;
9706 app = &n->narg.next;
9711 *rpp = n = redirnode;
9712 rpp = &n->nfile.next;
9713 parsefname(); /* read name of redirection file */
9716 if (args && app == &args->narg.next
9719 struct builtincmd *bcmd;
9722 /* We have a function */
9723 if (readtoken() != TRP)
9724 raise_error_unexpected_syntax(TRP);
9725 name = n->narg.text;
9727 || ((bcmd = find_builtin(name)) && IS_BUILTIN_SPECIAL(bcmd))
9729 raise_error_syntax("Bad function name");
9732 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9733 n->narg.next = parse_command();
9746 n = stalloc(sizeof(struct ncmd));
9748 n->ncmd.args = args;
9749 n->ncmd.assign = vars;
9750 n->ncmd.redirect = redir;
9757 union node *n1, *n2;
9758 union node *ap, **app;
9759 union node *cp, **cpp;
9760 union node *redir, **rpp;
9767 switch (readtoken()) {
9769 raise_error_unexpected_syntax(-1);
9772 n1 = stalloc(sizeof(struct nif));
9774 n1->nif.test = list(0);
9775 if (readtoken() != TTHEN)
9776 raise_error_unexpected_syntax(TTHEN);
9777 n1->nif.ifpart = list(0);
9779 while (readtoken() == TELIF) {
9780 n2->nif.elsepart = stalloc(sizeof(struct nif));
9781 n2 = n2->nif.elsepart;
9783 n2->nif.test = list(0);
9784 if (readtoken() != TTHEN)
9785 raise_error_unexpected_syntax(TTHEN);
9786 n2->nif.ifpart = list(0);
9788 if (lasttoken == TELSE)
9789 n2->nif.elsepart = list(0);
9791 n2->nif.elsepart = NULL;
9799 n1 = stalloc(sizeof(struct nbinary));
9800 n1->type = (lasttoken == TWHILE) ? NWHILE : NUNTIL;
9801 n1->nbinary.ch1 = list(0);
9804 TRACE(("expecting DO got %s %s\n", tokname(got),
9805 got == TWORD ? wordtext : ""));
9806 raise_error_unexpected_syntax(TDO);
9808 n1->nbinary.ch2 = list(0);
9813 if (readtoken() != TWORD || quoteflag || ! goodname(wordtext))
9814 raise_error_syntax("Bad for loop variable");
9815 n1 = stalloc(sizeof(struct nfor));
9817 n1->nfor.var = wordtext;
9818 checkkwd = CHKKWD | CHKALIAS;
9819 if (readtoken() == TIN) {
9821 while (readtoken() == TWORD) {
9822 n2 = stalloc(sizeof(struct narg));
9824 n2->narg.text = wordtext;
9825 n2->narg.backquote = backquotelist;
9827 app = &n2->narg.next;
9831 if (lasttoken != TNL && lasttoken != TSEMI)
9832 raise_error_unexpected_syntax(-1);
9834 n2 = stalloc(sizeof(struct narg));
9836 n2->narg.text = (char *)dolatstr;
9837 n2->narg.backquote = NULL;
9838 n2->narg.next = NULL;
9841 * Newline or semicolon here is optional (but note
9842 * that the original Bourne shell only allowed NL).
9844 if (lasttoken != TNL && lasttoken != TSEMI)
9847 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9848 if (readtoken() != TDO)
9849 raise_error_unexpected_syntax(TDO);
9850 n1->nfor.body = list(0);
9854 n1 = stalloc(sizeof(struct ncase));
9856 if (readtoken() != TWORD)
9857 raise_error_unexpected_syntax(TWORD);
9858 n1->ncase.expr = n2 = stalloc(sizeof(struct narg));
9860 n2->narg.text = wordtext;
9861 n2->narg.backquote = backquotelist;
9862 n2->narg.next = NULL;
9864 checkkwd = CHKKWD | CHKALIAS;
9865 } while (readtoken() == TNL);
9866 if (lasttoken != TIN)
9867 raise_error_unexpected_syntax(TIN);
9868 cpp = &n1->ncase.cases;
9870 checkkwd = CHKNL | CHKKWD;
9872 while (t != TESAC) {
9873 if (lasttoken == TLP)
9875 *cpp = cp = stalloc(sizeof(struct nclist));
9877 app = &cp->nclist.pattern;
9879 *app = ap = stalloc(sizeof(struct narg));
9881 ap->narg.text = wordtext;
9882 ap->narg.backquote = backquotelist;
9883 if (readtoken() != TPIPE)
9885 app = &ap->narg.next;
9888 ap->narg.next = NULL;
9889 if (lasttoken != TRP)
9890 raise_error_unexpected_syntax(TRP);
9891 cp->nclist.body = list(2);
9893 cpp = &cp->nclist.next;
9895 checkkwd = CHKNL | CHKKWD;
9899 raise_error_unexpected_syntax(TENDCASE);
9906 n1 = stalloc(sizeof(struct nredir));
9907 n1->type = NSUBSHELL;
9908 n1->nredir.n = list(0);
9909 n1->nredir.redirect = NULL;
9922 if (readtoken() != t)
9923 raise_error_unexpected_syntax(t);
9926 /* Now check for redirection which may follow command */
9927 checkkwd = CHKKWD | CHKALIAS;
9929 while (readtoken() == TREDIR) {
9930 *rpp = n2 = redirnode;
9931 rpp = &n2->nfile.next;
9937 if (n1->type != NSUBSHELL) {
9938 n2 = stalloc(sizeof(struct nredir));
9943 n1->nredir.redirect = redir;
9949 * If eofmark is NULL, read a word or a redirection symbol. If eofmark
9950 * is not NULL, read a here document. In the latter case, eofmark is the
9951 * word which marks the end of the document and striptabs is true if
9952 * leading tabs should be stripped from the document. The argument firstc
9953 * is the first character of the input token or document.
9955 * Because C does not have internal subroutines, I have simulated them
9956 * using goto's to implement the subroutine linkage. The following macros
9957 * will run code that appears at the end of readtoken1.
9960 static int parsebackquote; /* nonzero if we are inside backquotes */
9962 #define CHECKEND() {goto checkend; checkend_return:;}
9963 #define PARSEREDIR() {goto parseredir; parseredir_return:;}
9964 #define PARSESUB() {goto parsesub; parsesub_return:;}
9965 #define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
9966 #define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
9967 #define PARSEARITH() {goto parsearith; parsearith_return:;}
9970 readtoken1(int firstc, int syntax, char *eofmark, int striptabs)
9975 char line[EOFMARKLEN + 1];
9976 struct nodelist *bqlist = 0;
9979 int varnest = 0; /* levels of variables expansion */
9980 int arinest = 0; /* levels of arithmetic expansion */
9981 int parenlevel = 0; /* levels of parens in arithmetic */
9982 int dqvarnest = 0; /* levels of variables expansion within double quotes */
9984 int prevsyntax = 0; /* syntax before arithmetic */
9986 /* Avoid longjmp clobbering */
9999 startlinno = plinno;
10001 if (syntax == DQSYNTAX)
10010 STARTSTACKSTR(out);
10011 loop: { /* for each line, until end of word */
10012 CHECKEND(); /* set c to PEOF if at end of here document */
10013 for (;;) { /* until end of line or end of word */
10014 CHECKSTRSPACE(4, out); /* permit 4 calls to USTPUTC */
10015 switch (SIT(c, syntax)) {
10016 case CNL: /* '\n' */
10017 if (syntax == BASESYNTAX)
10018 goto endword; /* exit outer loop */
10024 goto loop; /* continue outer loop */
10029 if (eofmark == NULL || dblquote)
10030 USTPUTC(CTLESC, out);
10033 case CBACK: /* backslash */
10036 USTPUTC(CTLESC, out);
10037 USTPUTC('\\', out);
10039 } else if (c == '\n') {
10044 c != '\\' && c != '`' &&
10049 USTPUTC(CTLESC, out);
10050 USTPUTC('\\', out);
10052 if (SIT(c, SQSYNTAX) == CCTL)
10053 USTPUTC(CTLESC, out);
10061 if (eofmark == NULL) {
10062 USTPUTC(CTLQUOTEMARK, out);
10070 if (eofmark != NULL && arinest == 0
10075 if (dqvarnest == 0) {
10076 syntax = BASESYNTAX;
10083 case CVAR: /* '$' */
10084 PARSESUB(); /* parse substitution */
10086 case CENDVAR: /* '}' */
10089 if (dqvarnest > 0) {
10092 USTPUTC(CTLENDVAR, out);
10097 #if ENABLE_ASH_MATH_SUPPORT
10098 case CLP: /* '(' in arithmetic */
10102 case CRP: /* ')' in arithmetic */
10103 if (parenlevel > 0) {
10107 if (pgetc() == ')') {
10108 if (--arinest == 0) {
10109 USTPUTC(CTLENDARI, out);
10110 syntax = prevsyntax;
10111 if (syntax == DQSYNTAX)
10119 * unbalanced parens
10120 * (don't 2nd guess - no error)
10128 case CBQUOTE: /* '`' */
10132 goto endword; /* exit outer loop */
10137 goto endword; /* exit outer loop */
10138 #if ENABLE_ASH_ALIAS
10148 #if ENABLE_ASH_MATH_SUPPORT
10149 if (syntax == ARISYNTAX)
10150 raise_error_syntax("Missing '))'");
10152 if (syntax != BASESYNTAX && !parsebackquote && eofmark == NULL)
10153 raise_error_syntax("Unterminated quoted string");
10154 if (varnest != 0) {
10155 startlinno = plinno;
10157 raise_error_syntax("Missing '}'");
10159 USTPUTC('\0', out);
10160 len = out - (char *)stackblock();
10161 out = stackblock();
10162 if (eofmark == NULL) {
10163 if ((c == '>' || c == '<')
10166 && (*out == '\0' || isdigit(*out))) {
10168 return lasttoken = TREDIR;
10173 quoteflag = quotef;
10174 backquotelist = bqlist;
10175 grabstackblock(len);
10179 /* end of readtoken routine */
10182 * Check to see whether we are at the end of the here document. When this
10183 * is called, c is set to the first character of the next input line. If
10184 * we are at the end of the here document, this routine sets the c to PEOF.
10188 #if ENABLE_ASH_ALIAS
10194 while (c == '\t') {
10198 if (c == *eofmark) {
10199 if (pfgets(line, sizeof(line)) != NULL) {
10203 for (q = eofmark + 1; *q && *p == *q; p++, q++);
10204 if (*p == '\n' && *q == '\0') {
10207 needprompt = doprompt;
10209 pushstring(line, NULL);
10214 goto checkend_return;
10218 * Parse a redirection operator. The variable "out" points to a string
10219 * specifying the fd to be redirected. The variable "c" contains the
10220 * first character of the redirection operator.
10226 np = stalloc(sizeof(struct nfile));
10231 np->type = NAPPEND;
10233 np->type = NCLOBBER;
10240 } else { /* c == '<' */
10245 if (sizeof(struct nfile) != sizeof(struct nhere)) {
10246 np = stalloc(sizeof(struct nhere));
10250 heredoc = stalloc(sizeof(struct heredoc));
10251 heredoc->here = np;
10254 heredoc->striptabs = 1;
10256 heredoc->striptabs = 0;
10262 np->type = NFROMFD;
10266 np->type = NFROMTO;
10276 np->nfile.fd = fd - '0';
10278 goto parseredir_return;
10282 * Parse a substitution. At this point, we have read the dollar sign
10283 * and nothing else.
10286 /* is_special(c) evaluates to 1 for c in "!#$*-0123456789?@"; 0 otherwise
10287 * (assuming ascii char codes, as the original implementation did) */
10288 #define is_special(c) \
10289 ((((unsigned int)c) - 33 < 32) \
10290 && ((0xc1ff920dUL >> (((unsigned int)c) - 33)) & 1))
10296 static const char types[] = "}-+?=";
10300 c <= PEOA_OR_PEOF ||
10301 (c != '(' && c != '{' && !is_name(c) && !is_special(c))
10305 } else if (c == '(') { /* $(command) or $((arith)) */
10306 if (pgetc() == '(') {
10307 #if ENABLE_ASH_MATH_SUPPORT
10310 raise_error_syntax("We unsupport $((arith))");
10317 USTPUTC(CTLVAR, out);
10318 typeloc = out - (char *)stackblock();
10319 USTPUTC(VSNORMAL, out);
10320 subtype = VSNORMAL;
10328 subtype = VSLENGTH;
10332 if (c > PEOA_OR_PEOF && is_name(c)) {
10336 } while (c > PEOA_OR_PEOF && is_in_name(c));
10337 } else if (isdigit(c)) {
10341 } while (isdigit(c));
10342 } else if (is_special(c)) {
10346 badsub: raise_error_syntax("Bad substitution");
10350 if (subtype == 0) {
10357 p = strchr(types, c);
10360 subtype = p - types + VSNORMAL;
10366 subtype = c == '#' ? VSTRIMLEFT :
10379 if (dblquote || arinest)
10381 *((char *)stackblock() + typeloc) = subtype | flags;
10382 if (subtype != VSNORMAL) {
10384 if (dblquote || arinest) {
10389 goto parsesub_return;
10393 * Called to parse command substitutions. Newstyle is set if the command
10394 * is enclosed inside $(...); nlpp is a pointer to the head of the linked
10395 * list of commands (passed by reference), and savelen is the number of
10396 * characters on the top of the stack which must be preserved.
10399 struct nodelist **nlpp;
10402 char *volatile str;
10403 struct jmploc jmploc;
10404 struct jmploc *volatile savehandler;
10406 int saveprompt = 0;
10408 (void) &saveprompt;
10411 savepbq = parsebackquote;
10412 if (setjmp(jmploc.loc)) {
10415 parsebackquote = 0;
10416 exception_handler = savehandler;
10417 longjmp(exception_handler->loc, 1);
10421 savelen = out - (char *)stackblock();
10423 str = ckmalloc(savelen);
10424 memcpy(str, stackblock(), savelen);
10426 savehandler = exception_handler;
10427 exception_handler = &jmploc;
10430 /* We must read until the closing backquote, giving special
10431 treatment to some slashes, and then push the string and
10432 reread it as input, interpreting it normally. */
10439 STARTSTACKSTR(pout);
10456 * If eating a newline, avoid putting
10457 * the newline into the new character
10458 * stream (via the STPUTC after the
10463 if (pc != '\\' && pc != '`' && pc != '$'
10464 && (!dblquote || pc != '"'))
10465 STPUTC('\\', pout);
10466 if (pc > PEOA_OR_PEOF) {
10472 #if ENABLE_ASH_ALIAS
10475 startlinno = plinno;
10476 raise_error_syntax("EOF in backquote substitution");
10480 needprompt = doprompt;
10489 STPUTC('\0', pout);
10490 psavelen = pout - (char *)stackblock();
10491 if (psavelen > 0) {
10492 pstr = grabstackstr(pout);
10493 setinputstring(pstr);
10498 nlpp = &(*nlpp)->next;
10499 *nlpp = stalloc(sizeof(**nlpp));
10500 (*nlpp)->next = NULL;
10501 parsebackquote = oldstyle;
10504 saveprompt = doprompt;
10511 doprompt = saveprompt;
10512 else if (readtoken() != TRP)
10513 raise_error_unexpected_syntax(TRP);
10518 * Start reading from old file again, ignoring any pushed back
10519 * tokens left from the backquote parsing
10524 while (stackblocksize() <= savelen)
10526 STARTSTACKSTR(out);
10528 memcpy(out, str, savelen);
10529 STADJUST(savelen, out);
10535 parsebackquote = savepbq;
10536 exception_handler = savehandler;
10537 if (arinest || dblquote)
10538 USTPUTC(CTLBACKQ | CTLQUOTE, out);
10540 USTPUTC(CTLBACKQ, out);
10542 goto parsebackq_oldreturn;
10543 goto parsebackq_newreturn;
10546 #if ENABLE_ASH_MATH_SUPPORT
10548 * Parse an arithmetic expansion (indicate start of one and set state)
10551 if (++arinest == 1) {
10552 prevsyntax = syntax;
10553 syntax = ARISYNTAX;
10554 USTPUTC(CTLARI, out);
10561 * we collapse embedded arithmetic expansion to
10562 * parenthesis, which should be equivalent
10566 goto parsearith_return;
10570 } /* end of readtoken */
10573 * Read the next input token.
10574 * If the token is a word, we set backquotelist to the list of cmds in
10575 * backquotes. We set quoteflag to true if any part of the word was
10577 * If the token is TREDIR, then we set redirnode to a structure containing
10579 * In all cases, the variable startlinno is set to the number of the line
10580 * on which the token starts.
10582 * [Change comment: here documents and internal procedures]
10583 * [Readtoken shouldn't have any arguments. Perhaps we should make the
10584 * word parsing code into a separate routine. In this case, readtoken
10585 * doesn't need to have any internal procedures, but parseword does.
10586 * We could also make parseoperator in essence the main routine, and
10587 * have parseword (readtoken1?) handle both words and redirection.]
10589 #define NEW_xxreadtoken
10590 #ifdef NEW_xxreadtoken
10591 /* singles must be first! */
10592 static const char xxreadtoken_chars[7] = { '\n', '(', ')', '&', '|', ';', 0 };
10594 static const char xxreadtoken_tokens[] = {
10595 TNL, TLP, TRP, /* only single occurrence allowed */
10596 TBACKGND, TPIPE, TSEMI, /* if single occurrence */
10597 TEOF, /* corresponds to trailing nul */
10598 TAND, TOR, TENDCASE, /* if double occurrence */
10601 #define xxreadtoken_doubles \
10602 (sizeof(xxreadtoken_tokens) - sizeof(xxreadtoken_chars))
10603 #define xxreadtoken_singles \
10604 (sizeof(xxreadtoken_chars) - xxreadtoken_doubles - 1)
10618 startlinno = plinno;
10619 for (;;) { /* until token or start of word found */
10622 if ((c != ' ') && (c != '\t')
10623 #if ENABLE_ASH_ALIAS
10628 while ((c = pgetc()) != '\n' && c != PEOF);
10630 } else if (c == '\\') {
10631 if (pgetc() != '\n') {
10635 startlinno = ++plinno;
10640 = xxreadtoken_chars + sizeof(xxreadtoken_chars) - 1;
10645 needprompt = doprompt;
10648 p = strchr(xxreadtoken_chars, c);
10651 return readtoken1(c, BASESYNTAX, (char *) NULL, 0);
10654 if (p - xxreadtoken_chars >= xxreadtoken_singles) {
10655 if (pgetc() == *p) { /* double occurrence? */
10656 p += xxreadtoken_doubles + 1;
10662 return lasttoken = xxreadtoken_tokens[p - xxreadtoken_chars];
10668 #define RETURN(token) return lasttoken = token
10681 startlinno = plinno;
10682 for (;;) { /* until token or start of word found */
10685 case ' ': case '\t':
10686 #if ENABLE_ASH_ALIAS
10691 while ((c = pgetc()) != '\n' && c != PEOF);
10695 if (pgetc() == '\n') {
10696 startlinno = ++plinno;
10705 needprompt = doprompt;
10710 if (pgetc() == '&')
10715 if (pgetc() == '|')
10720 if (pgetc() == ';')
10733 return readtoken1(c, BASESYNTAX, (char *)NULL, 0);
10736 #endif /* NEW_xxreadtoken */
10743 int alreadyseen = tokpushback;
10746 #if ENABLE_ASH_ALIAS
10755 if (checkkwd & CHKNL) {
10762 if (t != TWORD || quoteflag) {
10767 * check for keywords
10769 if (checkkwd & CHKKWD) {
10770 const char *const *pp;
10772 pp = findkwd(wordtext);
10774 lasttoken = t = pp - tokname_array;
10775 TRACE(("keyword %s recognized\n", tokname(t)));
10780 if (checkkwd & CHKALIAS) {
10781 #if ENABLE_ASH_ALIAS
10783 ap = lookupalias(wordtext, 1);
10786 pushstring(ap->val, ap);
10796 TRACE(("token %s %s\n", tokname(t), t == TWORD ? wordtext : ""));
10798 TRACE(("reread token %s %s\n", tokname(t), t == TWORD ? wordtext : ""));
10810 return tokname_array[t][0];
10814 * Read and parse a command. Returns NEOF on end of file. (NULL is a
10815 * valid parse tree indicating a blank line.)
10817 static union node *
10818 parsecmd(int interact)
10823 doprompt = interact;
10825 setprompt(doprompt);
10837 * Input any here documents.
10842 struct heredoc *here;
10845 here = heredoclist;
10852 readtoken1(pgetc(), here->here->type == NHERE? SQSYNTAX : DQSYNTAX,
10853 here->eofmark, here->striptabs);
10854 n = stalloc(sizeof(struct narg));
10855 n->narg.type = NARG;
10856 n->narg.next = NULL;
10857 n->narg.text = wordtext;
10858 n->narg.backquote = backquotelist;
10859 here->here->nhere.doc = n;
10866 * called by editline -- any expansions to the prompt should be added here.
10868 #if ENABLE_ASH_EXPAND_PRMT
10869 static const char *
10870 expandstr(const char *ps)
10874 /* XXX Fix (char *) cast. */
10875 setinputstring((char *)ps);
10876 readtoken1(pgetc(), DQSYNTAX, nullstr, 0);
10879 n.narg.type = NARG;
10880 n.narg.next = NULL;
10881 n.narg.text = wordtext;
10882 n.narg.backquote = backquotelist;
10884 expandarg(&n, NULL, 0);
10885 return stackblock();
10890 * Execute a command or commands contained in a string.
10893 evalstring(char *s, int mask)
10896 struct stackmark smark;
10900 setstackmark(&smark);
10903 while ((n = parsecmd(0)) != NEOF) {
10905 popstackmark(&smark);
10918 * The eval command.
10921 evalcmd(int argc, char **argv)
10930 STARTSTACKSTR(concat);
10933 concat = stack_putstr(p, concat);
10937 STPUTC(' ', concat);
10939 STPUTC('\0', concat);
10940 p = grabstackstr(concat);
10942 evalstring(p, ~SKIPEVAL);
10949 * Read and execute commands. "Top" is nonzero for the top level command
10950 * loop; it turns on prompting if the shell is interactive.
10956 struct stackmark smark;
10960 TRACE(("cmdloop(%d) called\n", top));
10964 setstackmark(&smark);
10967 showjobs(stderr, SHOW_CHANGED);
10970 if (iflag && top) {
10972 #if ENABLE_ASH_MAIL
10976 n = parsecmd(inter);
10977 /* showtree(n); DEBUG */
10979 if (!top || numeof >= 50)
10981 if (!stoppedjobs()) {
10984 out2str("\nUse \"exit\" to leave shell.\n");
10987 } else if (nflag == 0) {
10988 job_warning = (job_warning == 2) ? 1 : 0;
10992 popstackmark(&smark);
10997 return skip & SKIPEVAL;
11004 * Take commands from a file. To be compatible we should do a path
11005 * search for the file, which is necessary to find sub-commands.
11008 find_dot_file(char *name)
11011 const char *path = pathval();
11014 /* don't try this for absolute or relative paths */
11015 if (strchr(name, '/'))
11018 while ((fullname = padvance(&path, name)) != NULL) {
11019 if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) {
11021 * Don't bother freeing here, since it will
11022 * be freed by the caller.
11026 stunalloc(fullname);
11029 /* not found in the PATH */
11030 ash_msg_and_raise_error("%s: not found", name);
11035 dotcmd(int argc, char **argv)
11037 struct strlist *sp;
11038 volatile struct shparam saveparam;
11041 for (sp = cmdenviron; sp; sp = sp->next)
11042 setvareq(ckstrdup(sp->text), VSTRFIXED | VTEXTFIXED);
11044 if (argc >= 2) { /* That's what SVR2 does */
11047 fullname = find_dot_file(argv[1]);
11050 saveparam = shellparam;
11051 shellparam.malloc = 0;
11052 shellparam.nparam = argc - 2;
11053 shellparam.p = argv + 2;
11056 setinputfile(fullname, INPUT_PUSH_FILE);
11057 commandname = fullname;
11062 freeparam(&shellparam);
11063 shellparam = saveparam;
11065 status = exitstatus;
11071 exitcmd(int argc, char **argv)
11076 exitstatus = number(argv[1]);
11077 raise_exception(EXEXIT);
11081 #if ENABLE_ASH_BUILTIN_ECHO
11083 echocmd(int argc, char **argv)
11085 return bb_echo(argv);
11089 #if ENABLE_ASH_BUILTIN_TEST
11091 testcmd(int argc, char **argv)
11093 return bb_test(argc, argv);
11098 * Read a file containing shell functions.
11101 readcmdfile(char *name)
11103 setinputfile(name, INPUT_PUSH_FILE);
11109 /* ============ find_command inplementation */
11112 * Resolve a command name. If you change this routine, you may have to
11113 * change the shellexec routine as well.
11116 find_command(char *name, struct cmdentry *entry, int act, const char *path)
11118 struct tblentry *cmdp;
11125 struct builtincmd *bcmd;
11127 /* If name contains a slash, don't use PATH or hash table */
11128 if (strchr(name, '/') != NULL) {
11129 entry->u.index = -1;
11130 if (act & DO_ABS) {
11131 while (stat(name, &statb) < 0) {
11133 if (errno == EINTR)
11136 entry->cmdtype = CMDUNKNOWN;
11140 entry->cmdtype = CMDNORMAL;
11144 #if ENABLE_FEATURE_SH_STANDALONE_SHELL
11145 if (find_applet_by_name(name)) {
11146 entry->cmdtype = CMDNORMAL;
11147 entry->u.index = -1;
11150 /* Already caught above
11151 if (is_safe_applet(name)) {
11152 entry->cmdtype = CMDNORMAL;
11153 entry->u.index = -1;
11158 updatetbl = (path == pathval());
11161 if (strstr(path, "%builtin") != NULL)
11162 act |= DO_ALTBLTIN;
11165 /* If name is in the table, check answer will be ok */
11166 cmdp = cmdlookup(name, 0);
11167 if (cmdp != NULL) {
11170 switch (cmdp->cmdtype) {
11188 } else if (cmdp->rehash == 0)
11189 /* if not invalidated by cd, we're done */
11193 /* If %builtin not in path, check for builtin next */
11194 bcmd = find_builtin(name);
11196 if (IS_BUILTIN_REGULAR(bcmd))
11197 goto builtin_success;
11198 if (act & DO_ALTPATH) {
11199 if (!(act & DO_ALTBLTIN))
11200 goto builtin_success;
11201 } else if (builtinloc <= 0) {
11202 goto builtin_success;
11206 /* We have to search path. */
11207 prev = -1; /* where to start */
11208 if (cmdp && cmdp->rehash) { /* doing a rehash */
11209 if (cmdp->cmdtype == CMDBUILTIN)
11212 prev = cmdp->param.index;
11218 while ((fullname = padvance(&path, name)) != NULL) {
11219 stunalloc(fullname);
11222 if (prefix(pathopt, "builtin")) {
11224 goto builtin_success;
11226 } else if (!(act & DO_NOFUNC) &&
11227 prefix(pathopt, "func")) {
11228 /* handled below */
11230 /* ignore unimplemented options */
11234 /* if rehash, don't redo absolute path names */
11235 if (fullname[0] == '/' && idx <= prev) {
11238 TRACE(("searchexec \"%s\": no change\n", name));
11241 while (stat(fullname, &statb) < 0) {
11243 if (errno == EINTR)
11246 if (errno != ENOENT && errno != ENOTDIR)
11250 e = EACCES; /* if we fail, this will be the error */
11251 if (!S_ISREG(statb.st_mode))
11253 if (pathopt) { /* this is a %func directory */
11254 stalloc(strlen(fullname) + 1);
11255 readcmdfile(fullname);
11256 cmdp = cmdlookup(name, 0);
11257 if (cmdp == NULL || cmdp->cmdtype != CMDFUNCTION)
11258 ash_msg_and_raise_error("%s not defined in %s", name, fullname);
11259 stunalloc(fullname);
11262 TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
11264 entry->cmdtype = CMDNORMAL;
11265 entry->u.index = idx;
11269 cmdp = cmdlookup(name, 1);
11270 cmdp->cmdtype = CMDNORMAL;
11271 cmdp->param.index = idx;
11276 /* We failed. If there was an entry for this command, delete it */
11277 if (cmdp && updatetbl)
11278 delete_cmd_entry();
11280 ash_msg("%s: %s", name, errmsg(e, "not found"));
11281 entry->cmdtype = CMDUNKNOWN;
11286 entry->cmdtype = CMDBUILTIN;
11287 entry->u.cmd = bcmd;
11291 cmdp = cmdlookup(name, 1);
11292 cmdp->cmdtype = CMDBUILTIN;
11293 cmdp->param.cmd = bcmd;
11297 entry->cmdtype = cmdp->cmdtype;
11298 entry->u = cmdp->param;
11302 /* ============ trap.c */
11305 * The trap builtin.
11308 trapcmd(int argc, char **argv)
11317 for (signo = 0; signo < NSIG; signo++) {
11318 if (trap[signo] != NULL) {
11321 sn = get_signame(signo);
11322 out1fmt("trap -- %s %s\n",
11323 single_quote(trap[signo]), sn);
11333 signo = get_signum(*ap);
11335 ash_msg_and_raise_error("%s: bad trap", *ap);
11338 if (LONE_DASH(action))
11341 action = ckstrdup(action);
11345 trap[signo] = action;
11355 /* ============ Builtins */
11357 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
11359 * Lists available builtins
11362 helpcmd(int argc, char **argv)
11366 out1fmt("\nBuilt-in commands:\n-------------------\n");
11367 for (col = 0, i = 0; i < NUMBUILTINS; i++) {
11368 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '),
11369 builtintab[i].name + 1);
11375 #if ENABLE_FEATURE_SH_STANDALONE_SHELL
11376 for (i = 0; i < NUM_APPLETS; i++) {
11377 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '), applets[i].name);
11385 return EXIT_SUCCESS;
11387 #endif /* FEATURE_SH_EXTRA_QUIET */
11390 * The export and readonly commands.
11393 exportcmd(int argc, char **argv)
11399 int flag = argv[0][0] == 'r'? VREADONLY : VEXPORT;
11401 if (nextopt("p") != 'p') {
11406 p = strchr(name, '=');
11410 vp = *findvar(hashvar(name), name);
11416 setvar(name, p, flag);
11417 } while ((name = *++aptr) != NULL);
11421 showvars(argv[0], flag, 0);
11426 * Delete a function if it exists.
11429 unsetfunc(const char *name)
11431 struct tblentry *cmdp;
11433 cmdp = cmdlookup(name, 0);
11434 if (cmdp!= NULL && cmdp->cmdtype == CMDFUNCTION)
11435 delete_cmd_entry();
11439 * The unset builtin command. We unset the function before we unset the
11440 * variable to allow a function to be unset when there is a readonly variable
11441 * with the same name.
11444 unsetcmd(int argc, char **argv)
11451 while ((i = nextopt("vf")) != '\0') {
11455 for (ap = argptr; *ap; ap++) {
11471 #include <sys/times.h>
11473 static const unsigned char timescmd_str[] = {
11474 ' ', offsetof(struct tms, tms_utime),
11475 '\n', offsetof(struct tms, tms_stime),
11476 ' ', offsetof(struct tms, tms_cutime),
11477 '\n', offsetof(struct tms, tms_cstime),
11482 timescmd(int ac, char **av)
11484 long clk_tck, s, t;
11485 const unsigned char *p;
11488 clk_tck = sysconf(_SC_CLK_TCK);
11493 t = *(clock_t *)(((char *) &buf) + p[1]);
11495 out1fmt("%ldm%ld.%.3lds%c",
11497 ((t - s * clk_tck) * 1000) / clk_tck,
11499 } while (*(p += 2));
11504 #if ENABLE_ASH_MATH_SUPPORT
11506 dash_arith(const char *s)
11512 result = arith(s, &errcode);
11515 ash_msg_and_raise_error("exponent less than 0");
11517 ash_msg_and_raise_error("divide by zero");
11519 ash_msg_and_raise_error("expression recursion loop detected");
11520 raise_error_syntax(s);
11528 * The let builtin. partial stolen from GNU Bash, the Bourne Again SHell.
11529 * Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
11531 * Copyright (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
11534 letcmd(int argc, char **argv)
11541 ash_msg_and_raise_error("expression expected");
11542 for (ap = argv + 1; *ap; ap++) {
11543 i = dash_arith(*ap);
11548 #endif /* ASH_MATH_SUPPORT */
11551 /* ============ miscbltin.c
11553 * Miscellaneous builtins.
11558 #if defined(__GLIBC__) && __GLIBC__ == 2 && __GLIBC_MINOR__ < 1
11559 typedef enum __rlimit_resource rlim_t;
11563 * The read builtin. The -e option causes backslashes to escape the
11564 * following character.
11566 * This uses unbuffered input, which may be avoidable in some cases.
11569 readcmd(int argc, char **argv)
11581 #if ENABLE_ASH_READ_NCHARS
11585 struct termios tty, old_tty;
11587 #if ENABLE_ASH_READ_TIMEOUT
11591 ts.tv_sec = ts.tv_usec = 0;
11596 #if ENABLE_ASH_READ_NCHARS && ENABLE_ASH_READ_TIMEOUT
11597 while ((i = nextopt("p:rt:n:s")) != '\0')
11598 #elif ENABLE_ASH_READ_NCHARS
11599 while ((i = nextopt("p:rn:s")) != '\0')
11600 #elif ENABLE_ASH_READ_TIMEOUT
11601 while ((i = nextopt("p:rt:")) != '\0')
11603 while ((i = nextopt("p:r")) != '\0')
11608 prompt = optionarg;
11610 #if ENABLE_ASH_READ_NCHARS
11612 nchars = strtol(optionarg, &p, 10);
11614 ash_msg_and_raise_error("invalid count");
11615 nch_flag = (nchars > 0);
11621 #if ENABLE_ASH_READ_TIMEOUT
11623 ts.tv_sec = strtol(optionarg, &p, 10);
11629 ts.tv_usec = strtol(p, &p2, 10);
11631 ash_msg_and_raise_error("invalid timeout");
11633 /* normalize to usec */
11635 ash_msg_and_raise_error("invalid timeout");
11636 while (scale++ < 6)
11640 ash_msg_and_raise_error("invalid timeout");
11642 if ( ! ts.tv_sec && ! ts.tv_usec)
11643 ash_msg_and_raise_error("invalid timeout");
11653 if (prompt && isatty(0)) {
11658 ash_msg_and_raise_error("arg count");
11659 ifs = bltinlookup("IFS");
11662 #if ENABLE_ASH_READ_NCHARS
11663 if (nch_flag || silent) {
11664 tcgetattr(0, &tty);
11667 tty.c_lflag &= ~ICANON;
11668 tty.c_cc[VMIN] = nchars;
11671 tty.c_lflag &= ~(ECHO|ECHOK|ECHONL);
11674 tcsetattr(0, TCSANOW, &tty);
11677 #if ENABLE_ASH_READ_TIMEOUT
11678 if (ts.tv_sec || ts.tv_usec) {
11682 i = select(FD_SETSIZE, &set, NULL, NULL, &ts);
11684 #if ENABLE_ASH_READ_NCHARS
11686 tcsetattr(0, TCSANOW, &old_tty);
11696 #if ENABLE_ASH_READ_NCHARS
11697 while (!nch_flag || nchars--)
11702 if (read(0, &c, 1) != 1) {
11714 if (!rflag && c == '\\') {
11720 if (startword && *ifs == ' ' && strchr(ifs, c)) {
11724 if (ap[1] != NULL && strchr(ifs, c) != NULL) {
11726 setvar(*ap, stackblock(), 0);
11735 #if ENABLE_ASH_READ_NCHARS
11736 if (nch_flag || silent)
11737 tcsetattr(0, TCSANOW, &old_tty);
11741 /* Remove trailing blanks */
11742 while ((char *)stackblock() <= --p && strchr(ifs, *p) != NULL)
11744 setvar(*ap, stackblock(), 0);
11745 while (*++ap != NULL)
11746 setvar(*ap, nullstr, 0);
11751 umaskcmd(int argc, char **argv)
11753 static const char permuser[3] = "ugo";
11754 static const char permmode[3] = "rwx";
11755 static const short int permmask[] = {
11756 S_IRUSR, S_IWUSR, S_IXUSR,
11757 S_IRGRP, S_IWGRP, S_IXGRP,
11758 S_IROTH, S_IWOTH, S_IXOTH
11764 int symbolic_mode = 0;
11766 while (nextopt("S") != '\0') {
11777 if (symbolic_mode) {
11781 for (i = 0; i < 3; i++) {
11784 *p++ = permuser[i];
11786 for (j = 0; j < 3; j++) {
11787 if ((mask & permmask[3 * i + j]) == 0) {
11788 *p++ = permmode[j];
11796 out1fmt("%.4o\n", mask);
11799 if (isdigit((unsigned char) *ap)) {
11802 if (*ap >= '8' || *ap < '0')
11803 ash_msg_and_raise_error(illnum, argv[1]);
11804 mask = (mask << 3) + (*ap - '0');
11805 } while (*++ap != '\0');
11808 mask = ~mask & 0777;
11809 if (!bb_parse_mode(ap, &mask)) {
11810 ash_msg_and_raise_error("illegal mode: %s", ap);
11812 umask(~mask & 0777);
11821 * This code, originally by Doug Gwyn, Doug Kingston, Eric Gisin, and
11822 * Michael Rendell was ripped from pdksh 5.0.8 and hacked for use with
11823 * ash by J.T. Conklin.
11831 int factor; /* multiply by to get rlim_{cur,max} values */
11835 static const struct limits limits[] = {
11837 { "time(seconds)", RLIMIT_CPU, 1, 't' },
11839 #ifdef RLIMIT_FSIZE
11840 { "file(blocks)", RLIMIT_FSIZE, 512, 'f' },
11843 { "data(kbytes)", RLIMIT_DATA, 1024, 'd' },
11845 #ifdef RLIMIT_STACK
11846 { "stack(kbytes)", RLIMIT_STACK, 1024, 's' },
11849 { "coredump(blocks)", RLIMIT_CORE, 512, 'c' },
11852 { "memory(kbytes)", RLIMIT_RSS, 1024, 'm' },
11854 #ifdef RLIMIT_MEMLOCK
11855 { "locked memory(kbytes)", RLIMIT_MEMLOCK, 1024, 'l' },
11857 #ifdef RLIMIT_NPROC
11858 { "process", RLIMIT_NPROC, 1, 'p' },
11860 #ifdef RLIMIT_NOFILE
11861 { "nofiles", RLIMIT_NOFILE, 1, 'n' },
11864 { "vmemory(kbytes)", RLIMIT_AS, 1024, 'v' },
11866 #ifdef RLIMIT_LOCKS
11867 { "locks", RLIMIT_LOCKS, 1, 'w' },
11869 { NULL, 0, 0, '\0' }
11872 enum limtype { SOFT = 0x1, HARD = 0x2 };
11875 printlim(enum limtype how, const struct rlimit *limit,
11876 const struct limits *l)
11880 val = limit->rlim_max;
11882 val = limit->rlim_cur;
11884 if (val == RLIM_INFINITY)
11885 out1fmt("unlimited\n");
11888 out1fmt("%lld\n", (long long) val);
11893 ulimitcmd(int argc, char **argv)
11897 enum limtype how = SOFT | HARD;
11898 const struct limits *l;
11901 struct rlimit limit;
11904 while ((optc = nextopt("HSa"
11908 #ifdef RLIMIT_FSIZE
11914 #ifdef RLIMIT_STACK
11923 #ifdef RLIMIT_MEMLOCK
11926 #ifdef RLIMIT_NPROC
11929 #ifdef RLIMIT_NOFILE
11935 #ifdef RLIMIT_LOCKS
11953 for (l = limits; l->option != what; l++)
11956 set = *argptr ? 1 : 0;
11960 if (all || argptr[1])
11961 ash_msg_and_raise_error("too many arguments");
11962 if (strncmp(p, "unlimited\n", 9) == 0)
11963 val = RLIM_INFINITY;
11967 while ((c = *p++) >= '0' && c <= '9') {
11968 val = (val * 10) + (long)(c - '0');
11969 if (val < (rlim_t) 0)
11973 ash_msg_and_raise_error("bad number");
11978 for (l = limits; l->name; l++) {
11979 getrlimit(l->cmd, &limit);
11980 out1fmt("%-20s ", l->name);
11981 printlim(how, &limit, l);
11986 getrlimit(l->cmd, &limit);
11989 limit.rlim_max = val;
11991 limit.rlim_cur = val;
11992 if (setrlimit(l->cmd, &limit) < 0)
11993 ash_msg_and_raise_error("error setting limit (%m)");
11995 printlim(how, &limit, l);
12001 /* ============ Math support */
12003 #if ENABLE_ASH_MATH_SUPPORT
12005 /* Copyright (c) 2001 Aaron Lehmann <aaronl@vitelus.com>
12007 Permission is hereby granted, free of charge, to any person obtaining
12008 a copy of this software and associated documentation files (the
12009 "Software"), to deal in the Software without restriction, including
12010 without limitation the rights to use, copy, modify, merge, publish,
12011 distribute, sublicense, and/or sell copies of the Software, and to
12012 permit persons to whom the Software is furnished to do so, subject to
12013 the following conditions:
12015 The above copyright notice and this permission notice shall be
12016 included in all copies or substantial portions of the Software.
12018 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
12019 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
12020 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
12021 IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
12022 CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
12023 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
12024 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
12027 /* This is my infix parser/evaluator. It is optimized for size, intended
12028 * as a replacement for yacc-based parsers. However, it may well be faster
12029 * than a comparable parser written in yacc. The supported operators are
12030 * listed in #defines below. Parens, order of operations, and error handling
12031 * are supported. This code is thread safe. The exact expression format should
12032 * be that which POSIX specifies for shells. */
12034 /* The code uses a simple two-stack algorithm. See
12035 * http://www.onthenet.com.au/~grahamis/int2008/week02/lect02.html
12036 * for a detailed explanation of the infix-to-postfix algorithm on which
12037 * this is based (this code differs in that it applies operators immediately
12038 * to the stack instead of adding them to a queue to end up with an
12041 /* To use the routine, call it with an expression string and error return
12045 * Aug 24, 2001 Manuel Novoa III
12047 * Reduced the generated code size by about 30% (i386) and fixed several bugs.
12049 * 1) In arith_apply():
12050 * a) Cached values of *numptr and &(numptr[-1]).
12051 * b) Removed redundant test for zero denominator.
12054 * a) Eliminated redundant code for processing operator tokens by moving
12055 * to a table-based implementation. Also folded handling of parens
12057 * b) Combined all 3 loops which called arith_apply to reduce generated
12058 * code size at the cost of speed.
12060 * 3) The following expressions were treated as valid by the original code:
12061 * 1() , 0! , 1 ( *3 ) .
12062 * These bugs have been fixed by internally enclosing the expression in
12063 * parens and then checking that all binary ops and right parens are
12064 * preceded by a valid expression (NUM_TOKEN).
12066 * Note: It may be desirable to replace Aaron's test for whitespace with
12067 * ctype's isspace() if it is used by another busybox applet or if additional
12068 * whitespace chars should be considered. Look below the "#include"s for a
12069 * precompiler test.
12073 * Aug 26, 2001 Manuel Novoa III
12075 * Return 0 for null expressions. Pointed out by Vladimir Oleynik.
12077 * Merge in Aaron's comments previously posted to the busybox list,
12078 * modified slightly to take account of my changes to the code.
12083 * (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
12085 * - allow access to variable,
12086 * used recursive find value indirection (c=2*2; a="c"; $((a+=2)) produce 6)
12087 * - realize assign syntax (VAR=expr, +=, *= etc)
12088 * - realize exponentiation (** operator)
12089 * - realize comma separated - expr, expr
12090 * - realise ++expr --expr expr++ expr--
12091 * - realise expr ? expr : expr (but, second expr calculate always)
12092 * - allow hexadecimal and octal numbers
12093 * - was restored loses XOR operator
12094 * - remove one goto label, added three ;-)
12095 * - protect $((num num)) as true zero expr (Manuel`s error)
12096 * - always use special isspace(), see comment from bash ;-)
12099 #define arith_isspace(arithval) \
12100 (arithval == ' ' || arithval == '\n' || arithval == '\t')
12102 typedef unsigned char operator;
12104 /* An operator's token id is a bit of a bitfield. The lower 5 bits are the
12105 * precedence, and 3 high bits are an ID unique across operators of that
12106 * precedence. The ID portion is so that multiple operators can have the
12107 * same precedence, ensuring that the leftmost one is evaluated first.
12108 * Consider * and /. */
12110 #define tok_decl(prec,id) (((id)<<5)|(prec))
12111 #define PREC(op) ((op) & 0x1F)
12113 #define TOK_LPAREN tok_decl(0,0)
12115 #define TOK_COMMA tok_decl(1,0)
12117 #define TOK_ASSIGN tok_decl(2,0)
12118 #define TOK_AND_ASSIGN tok_decl(2,1)
12119 #define TOK_OR_ASSIGN tok_decl(2,2)
12120 #define TOK_XOR_ASSIGN tok_decl(2,3)
12121 #define TOK_PLUS_ASSIGN tok_decl(2,4)
12122 #define TOK_MINUS_ASSIGN tok_decl(2,5)
12123 #define TOK_LSHIFT_ASSIGN tok_decl(2,6)
12124 #define TOK_RSHIFT_ASSIGN tok_decl(2,7)
12126 #define TOK_MUL_ASSIGN tok_decl(3,0)
12127 #define TOK_DIV_ASSIGN tok_decl(3,1)
12128 #define TOK_REM_ASSIGN tok_decl(3,2)
12130 /* all assign is right associativity and precedence eq, but (7+3)<<5 > 256 */
12131 #define convert_prec_is_assing(prec) do { if (prec == 3) prec = 2; } while (0)
12133 /* conditional is right associativity too */
12134 #define TOK_CONDITIONAL tok_decl(4,0)
12135 #define TOK_CONDITIONAL_SEP tok_decl(4,1)
12137 #define TOK_OR tok_decl(5,0)
12139 #define TOK_AND tok_decl(6,0)
12141 #define TOK_BOR tok_decl(7,0)
12143 #define TOK_BXOR tok_decl(8,0)
12145 #define TOK_BAND tok_decl(9,0)
12147 #define TOK_EQ tok_decl(10,0)
12148 #define TOK_NE tok_decl(10,1)
12150 #define TOK_LT tok_decl(11,0)
12151 #define TOK_GT tok_decl(11,1)
12152 #define TOK_GE tok_decl(11,2)
12153 #define TOK_LE tok_decl(11,3)
12155 #define TOK_LSHIFT tok_decl(12,0)
12156 #define TOK_RSHIFT tok_decl(12,1)
12158 #define TOK_ADD tok_decl(13,0)
12159 #define TOK_SUB tok_decl(13,1)
12161 #define TOK_MUL tok_decl(14,0)
12162 #define TOK_DIV tok_decl(14,1)
12163 #define TOK_REM tok_decl(14,2)
12165 /* exponent is right associativity */
12166 #define TOK_EXPONENT tok_decl(15,1)
12168 /* For now unary operators. */
12169 #define UNARYPREC 16
12170 #define TOK_BNOT tok_decl(UNARYPREC,0)
12171 #define TOK_NOT tok_decl(UNARYPREC,1)
12173 #define TOK_UMINUS tok_decl(UNARYPREC+1,0)
12174 #define TOK_UPLUS tok_decl(UNARYPREC+1,1)
12176 #define PREC_PRE (UNARYPREC+2)
12178 #define TOK_PRE_INC tok_decl(PREC_PRE, 0)
12179 #define TOK_PRE_DEC tok_decl(PREC_PRE, 1)
12181 #define PREC_POST (UNARYPREC+3)
12183 #define TOK_POST_INC tok_decl(PREC_POST, 0)
12184 #define TOK_POST_DEC tok_decl(PREC_POST, 1)
12186 #define SPEC_PREC (UNARYPREC+4)
12188 #define TOK_NUM tok_decl(SPEC_PREC, 0)
12189 #define TOK_RPAREN tok_decl(SPEC_PREC, 1)
12191 #define NUMPTR (*numstackptr)
12194 tok_have_assign(operator op)
12196 operator prec = PREC(op);
12198 convert_prec_is_assing(prec);
12199 return (prec == PREC(TOK_ASSIGN) ||
12200 prec == PREC_PRE || prec == PREC_POST);
12204 is_right_associativity(operator prec)
12206 return (prec == PREC(TOK_ASSIGN) || prec == PREC(TOK_EXPONENT)
12207 || prec == PREC(TOK_CONDITIONAL));
12210 typedef struct ARITCH_VAR_NUM {
12212 arith_t contidional_second_val;
12213 char contidional_second_val_initialized;
12214 char *var; /* if NULL then is regular number,
12215 else is variable name */
12218 typedef struct CHK_VAR_RECURSIVE_LOOPED {
12220 struct CHK_VAR_RECURSIVE_LOOPED *next;
12221 } chk_var_recursive_looped_t;
12223 static chk_var_recursive_looped_t *prev_chk_var_recursive;
12226 arith_lookup_val(v_n_t *t)
12229 const char * p = lookupvar(t->var);
12234 /* recursive try as expression */
12235 chk_var_recursive_looped_t *cur;
12236 chk_var_recursive_looped_t cur_save;
12238 for (cur = prev_chk_var_recursive; cur; cur = cur->next) {
12239 if (strcmp(cur->var, t->var) == 0) {
12240 /* expression recursion loop detected */
12244 /* save current lookuped var name */
12245 cur = prev_chk_var_recursive;
12246 cur_save.var = t->var;
12247 cur_save.next = cur;
12248 prev_chk_var_recursive = &cur_save;
12250 t->val = arith (p, &errcode);
12251 /* restore previous ptr after recursiving */
12252 prev_chk_var_recursive = cur;
12255 /* allow undefined var as 0 */
12261 /* "applying" a token means performing it on the top elements on the integer
12262 * stack. For a unary operator it will only change the top element, but a
12263 * binary operator will pop two arguments and push a result */
12265 arith_apply(operator op, v_n_t *numstack, v_n_t **numstackptr)
12268 arith_t numptr_val, rez;
12269 int ret_arith_lookup_val;
12271 /* There is no operator that can work without arguments */
12272 if (NUMPTR == numstack) goto err;
12273 numptr_m1 = NUMPTR - 1;
12275 /* check operand is var with noninteger value */
12276 ret_arith_lookup_val = arith_lookup_val(numptr_m1);
12277 if (ret_arith_lookup_val)
12278 return ret_arith_lookup_val;
12280 rez = numptr_m1->val;
12281 if (op == TOK_UMINUS)
12283 else if (op == TOK_NOT)
12285 else if (op == TOK_BNOT)
12287 else if (op == TOK_POST_INC || op == TOK_PRE_INC)
12289 else if (op == TOK_POST_DEC || op == TOK_PRE_DEC)
12291 else if (op != TOK_UPLUS) {
12292 /* Binary operators */
12294 /* check and binary operators need two arguments */
12295 if (numptr_m1 == numstack) goto err;
12297 /* ... and they pop one */
12300 if (op == TOK_CONDITIONAL) {
12301 if (! numptr_m1->contidional_second_val_initialized) {
12302 /* protect $((expr1 ? expr2)) without ": expr" */
12305 rez = numptr_m1->contidional_second_val;
12306 } else if (numptr_m1->contidional_second_val_initialized) {
12307 /* protect $((expr1 : expr2)) without "expr ? " */
12310 numptr_m1 = NUMPTR - 1;
12311 if (op != TOK_ASSIGN) {
12312 /* check operand is var with noninteger value for not '=' */
12313 ret_arith_lookup_val = arith_lookup_val(numptr_m1);
12314 if (ret_arith_lookup_val)
12315 return ret_arith_lookup_val;
12317 if (op == TOK_CONDITIONAL) {
12318 numptr_m1->contidional_second_val = rez;
12320 rez = numptr_m1->val;
12321 if (op == TOK_BOR || op == TOK_OR_ASSIGN)
12323 else if (op == TOK_OR)
12324 rez = numptr_val || rez;
12325 else if (op == TOK_BAND || op == TOK_AND_ASSIGN)
12327 else if (op == TOK_BXOR || op == TOK_XOR_ASSIGN)
12329 else if (op == TOK_AND)
12330 rez = rez && numptr_val;
12331 else if (op == TOK_EQ)
12332 rez = (rez == numptr_val);
12333 else if (op == TOK_NE)
12334 rez = (rez != numptr_val);
12335 else if (op == TOK_GE)
12336 rez = (rez >= numptr_val);
12337 else if (op == TOK_RSHIFT || op == TOK_RSHIFT_ASSIGN)
12338 rez >>= numptr_val;
12339 else if (op == TOK_LSHIFT || op == TOK_LSHIFT_ASSIGN)
12340 rez <<= numptr_val;
12341 else if (op == TOK_GT)
12342 rez = (rez > numptr_val);
12343 else if (op == TOK_LT)
12344 rez = (rez < numptr_val);
12345 else if (op == TOK_LE)
12346 rez = (rez <= numptr_val);
12347 else if (op == TOK_MUL || op == TOK_MUL_ASSIGN)
12349 else if (op == TOK_ADD || op == TOK_PLUS_ASSIGN)
12351 else if (op == TOK_SUB || op == TOK_MINUS_ASSIGN)
12353 else if (op == TOK_ASSIGN || op == TOK_COMMA)
12355 else if (op == TOK_CONDITIONAL_SEP) {
12356 if (numptr_m1 == numstack) {
12357 /* protect $((expr : expr)) without "expr ? " */
12360 numptr_m1->contidional_second_val_initialized = op;
12361 numptr_m1->contidional_second_val = numptr_val;
12362 } else if (op == TOK_CONDITIONAL) {
12364 numptr_val : numptr_m1->contidional_second_val;
12365 } else if (op == TOK_EXPONENT) {
12366 if (numptr_val < 0)
12367 return -3; /* exponent less than 0 */
12372 while (numptr_val--)
12376 } else if (numptr_val==0) /* zero divisor check */
12378 else if (op == TOK_DIV || op == TOK_DIV_ASSIGN)
12380 else if (op == TOK_REM || op == TOK_REM_ASSIGN)
12383 if (tok_have_assign(op)) {
12384 char buf[sizeof(arith_t_type)*3 + 2];
12386 if (numptr_m1->var == NULL) {
12390 /* save to shell variable */
12391 #if ENABLE_ASH_MATH_SUPPORT_64
12392 snprintf(buf, sizeof(buf), "%lld", (arith_t_type) rez);
12394 snprintf(buf, sizeof(buf), "%ld", (arith_t_type) rez);
12396 setvar(numptr_m1->var, buf, 0);
12397 /* after saving, make previous value for v++ or v-- */
12398 if (op == TOK_POST_INC)
12400 else if (op == TOK_POST_DEC)
12403 numptr_m1->val = rez;
12404 /* protect geting var value, is number now */
12405 numptr_m1->var = NULL;
12411 /* longest must be first */
12412 static const char op_tokens[] = {
12413 '<','<','=',0, TOK_LSHIFT_ASSIGN,
12414 '>','>','=',0, TOK_RSHIFT_ASSIGN,
12415 '<','<', 0, TOK_LSHIFT,
12416 '>','>', 0, TOK_RSHIFT,
12417 '|','|', 0, TOK_OR,
12418 '&','&', 0, TOK_AND,
12419 '!','=', 0, TOK_NE,
12420 '<','=', 0, TOK_LE,
12421 '>','=', 0, TOK_GE,
12422 '=','=', 0, TOK_EQ,
12423 '|','=', 0, TOK_OR_ASSIGN,
12424 '&','=', 0, TOK_AND_ASSIGN,
12425 '*','=', 0, TOK_MUL_ASSIGN,
12426 '/','=', 0, TOK_DIV_ASSIGN,
12427 '%','=', 0, TOK_REM_ASSIGN,
12428 '+','=', 0, TOK_PLUS_ASSIGN,
12429 '-','=', 0, TOK_MINUS_ASSIGN,
12430 '-','-', 0, TOK_POST_DEC,
12431 '^','=', 0, TOK_XOR_ASSIGN,
12432 '+','+', 0, TOK_POST_INC,
12433 '*','*', 0, TOK_EXPONENT,
12437 '=', 0, TOK_ASSIGN,
12449 '?', 0, TOK_CONDITIONAL,
12450 ':', 0, TOK_CONDITIONAL_SEP,
12451 ')', 0, TOK_RPAREN,
12452 '(', 0, TOK_LPAREN,
12456 #define endexpression &op_tokens[sizeof(op_tokens)-7]
12459 arith(const char *expr, int *perrcode)
12461 char arithval; /* Current character under analysis */
12462 operator lasttok, op;
12465 const char *p = endexpression;
12468 size_t datasizes = strlen(expr) + 2;
12470 /* Stack of integers */
12471 /* The proof that there can be no more than strlen(startbuf)/2+1 integers
12472 * in any given correct or incorrect expression is left as an exercise to
12474 v_n_t *numstack = alloca(((datasizes)/2)*sizeof(v_n_t)),
12475 *numstackptr = numstack;
12476 /* Stack of operator tokens */
12477 operator *stack = alloca((datasizes) * sizeof(operator)),
12480 *stackptr++ = lasttok = TOK_LPAREN; /* start off with a left paren */
12481 *perrcode = errcode = 0;
12485 if (arithval == 0) {
12486 if (p == endexpression) {
12487 /* Null expression. */
12491 /* This is only reached after all tokens have been extracted from the
12492 * input stream. If there are still tokens on the operator stack, they
12493 * are to be applied in order. At the end, there should be a final
12494 * result on the integer stack */
12496 if (expr != endexpression + 1) {
12497 /* If we haven't done so already, */
12498 /* append a closing right paren */
12499 expr = endexpression;
12500 /* and let the loop process it. */
12503 /* At this point, we're done with the expression. */
12504 if (numstackptr != numstack+1) {
12505 /* ... but if there isn't, it's bad */
12507 return (*perrcode = -1);
12509 if (numstack->var) {
12510 /* expression is $((var)) only, lookup now */
12511 errcode = arith_lookup_val(numstack);
12514 *perrcode = errcode;
12515 return numstack->val;
12518 /* Continue processing the expression. */
12519 if (arith_isspace(arithval)) {
12520 /* Skip whitespace */
12523 p = endofname(expr);
12525 size_t var_name_size = (p-expr) + 1; /* trailing zero */
12527 numstackptr->var = alloca(var_name_size);
12528 safe_strncpy(numstackptr->var, expr, var_name_size);
12531 numstackptr->contidional_second_val_initialized = 0;
12536 if (isdigit(arithval)) {
12537 numstackptr->var = NULL;
12538 #if ENABLE_ASH_MATH_SUPPORT_64
12539 numstackptr->val = strtoll(expr, (char **) &expr, 0);
12541 numstackptr->val = strtol(expr, (char **) &expr, 0);
12545 for (p = op_tokens; ; p++) {
12549 /* strange operator not found */
12552 for (o = expr; *p && *o == *p; p++)
12559 /* skip tail uncompared token */
12562 /* skip zero delim */
12567 /* post grammar: a++ reduce to num */
12568 if (lasttok == TOK_POST_INC || lasttok == TOK_POST_DEC)
12571 /* Plus and minus are binary (not unary) _only_ if the last
12572 * token was as number, or a right paren (which pretends to be
12573 * a number, since it evaluates to one). Think about it.
12574 * It makes sense. */
12575 if (lasttok != TOK_NUM) {
12591 /* We don't want a unary operator to cause recursive descent on the
12592 * stack, because there can be many in a row and it could cause an
12593 * operator to be evaluated before its argument is pushed onto the
12594 * integer stack. */
12595 /* But for binary operators, "apply" everything on the operator
12596 * stack until we find an operator with a lesser priority than the
12597 * one we have just extracted. */
12598 /* Left paren is given the lowest priority so it will never be
12599 * "applied" in this way.
12600 * if associativity is right and priority eq, applied also skip
12603 if ((prec > 0 && prec < UNARYPREC) || prec == SPEC_PREC) {
12604 /* not left paren or unary */
12605 if (lasttok != TOK_NUM) {
12606 /* binary op must be preceded by a num */
12609 while (stackptr != stack) {
12610 if (op == TOK_RPAREN) {
12611 /* The algorithm employed here is simple: while we don't
12612 * hit an open paren nor the bottom of the stack, pop
12613 * tokens and apply them */
12614 if (stackptr[-1] == TOK_LPAREN) {
12616 /* Any operator directly after a */
12618 /* close paren should consider itself binary */
12622 operator prev_prec = PREC(stackptr[-1]);
12624 convert_prec_is_assing(prec);
12625 convert_prec_is_assing(prev_prec);
12626 if (prev_prec < prec)
12628 /* check right assoc */
12629 if (prev_prec == prec && is_right_associativity(prec))
12632 errcode = arith_apply(*--stackptr, numstack, &numstackptr);
12633 if (errcode) goto ret;
12635 if (op == TOK_RPAREN) {
12640 /* Push this operator to the stack and remember it. */
12641 *stackptr++ = lasttok = op;
12646 #endif /* ASH_MATH_SUPPORT */
12649 /* ============ main() and helpers */
12652 * Called to exit the shell.
12654 static void exitshell(void) ATTRIBUTE_NORETURN;
12662 status = exitstatus;
12663 TRACE(("pid %d, exitshell(%d)\n", getpid(), status));
12664 if (setjmp(loc.loc)) {
12665 if (exception == EXEXIT)
12666 /* dash bug: it just does _exit(exitstatus) here
12667 * but we have to do setjobctl(0) first!
12668 * (bug is still not fixed in dash-0.5.3 - if you run dash
12669 * under Midnight Commander, on exit from dash MC is backgrounded) */
12670 status = exitstatus;
12673 exception_handler = &loc;
12679 flush_stdout_stderr();
12689 /* from input.c: */
12690 basepf.nextc = basepf.buf = basebuf;
12693 signal(SIGCHLD, SIG_DFL);
12698 char ppid[sizeof(int)*3 + 1];
12700 struct stat st1, st2;
12703 for (envp = environ; envp && *envp; envp++) {
12704 if (strchr(*envp, '=')) {
12705 setvareq(*envp, VEXPORT|VTEXTFIXED);
12709 snprintf(ppid, sizeof(ppid), "%u", (unsigned) getppid());
12710 setvar("PPID", ppid, 0);
12712 p = lookupvar("PWD");
12714 if (*p != '/' || stat(p, &st1) || stat(".", &st2)
12715 || st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino)
12722 * Process the shell command line arguments.
12725 procargs(int argc, char **argv)
12728 const char *xminusc;
12735 for (i = 0; i < NOPTS; i++)
12741 if (*xargv == NULL) {
12743 ash_msg_and_raise_error(bb_msg_requires_arg, "-c");
12746 if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
12750 for (i = 0; i < NOPTS; i++)
12751 if (optlist[i] == 2)
12756 /* POSIX 1003.2: first arg after -c cmd is $0, remainder $1... */
12761 } else if (!sflag) {
12762 setinputfile(*xargv, 0);
12765 commandname = arg0;
12768 shellparam.p = xargv;
12769 #if ENABLE_ASH_GETOPTS
12770 shellparam.optind = 1;
12771 shellparam.optoff = -1;
12773 /* assert(shellparam.malloc == 0 && shellparam.nparam == 0); */
12775 shellparam.nparam++;
12782 * Read /etc/profile or .profile.
12785 read_profile(const char *name)
12789 if (setinputfile(name, INPUT_PUSH_FILE | INPUT_NOFILE_OK) < 0)
12798 * This routine is called when an error or an interrupt occurs in an
12799 * interactive shell and control is returned to the main command loop.
12807 /* from input.c: */
12808 parselleft = parsenleft = 0; /* clear input buffer */
12810 /* from parser.c: */
12813 /* from redir.c: */
12818 static short profile_buf[16384];
12819 extern int etext();
12823 * Main routine. We initialize things, parse the arguments, execute
12824 * profiles if we're a login shell, and then call cmdloop to execute
12825 * commands. The setjmp call sets up the location to jump to when an
12826 * exception occurs. When an exception occurs the variable "state"
12827 * is used to figure out how far we had gotten.
12829 int ash_main(int argc, char **argv);
12830 int ash_main(int argc, char **argv)
12833 volatile int state;
12834 struct jmploc jmploc;
12835 struct stackmark smark;
12838 dash_errno = __errno_location();
12842 monitor(4, etext, profile_buf, sizeof(profile_buf), 50);
12845 #if ENABLE_FEATURE_EDITING
12846 line_input_state = new_line_input_t(FOR_SHELL | WITH_PATH_LOOKUP);
12849 if (setjmp(jmploc.loc)) {
12859 if (e == EXEXIT || s == 0 || iflag == 0 || shlvl)
12863 outcslow('\n', stderr);
12865 popstackmark(&smark);
12866 FORCE_INT_ON; /* enable interrupts */
12875 exception_handler = &jmploc;
12878 trace_puts("Shell args: ");
12879 trace_puts_args(argv);
12881 rootpid = getpid();
12883 #if ENABLE_ASH_RANDOM_SUPPORT
12884 rseed = rootpid + time(NULL);
12887 setstackmark(&smark);
12888 procargs(argc, argv);
12889 #if ENABLE_FEATURE_EDITING_SAVEHISTORY
12891 const char *hp = lookupvar("HISTFILE");
12894 hp = lookupvar("HOME");
12896 char *defhp = concat_path_file(hp, ".ash_history");
12897 setvar("HISTFILE", defhp, 0);
12903 if (argv[0] && argv[0][0] == '-')
12907 read_profile("/etc/profile");
12910 read_profile(".profile");
12916 getuid() == geteuid() && getgid() == getegid() &&
12920 shinit = lookupvar("ENV");
12921 if (shinit != NULL && *shinit != '\0') {
12922 read_profile(shinit);
12928 evalstring(minusc, 0);
12930 if (sflag || minusc == NULL) {
12931 #if ENABLE_FEATURE_EDITING_SAVEHISTORY
12933 const char *hp = lookupvar("HISTFILE");
12936 line_input_state->hist_file = hp;
12939 state4: /* XXX ??? - why isn't this before the "if" statement */
12947 extern void _mcleanup(void);
12956 const char *applet_name = "debug stuff usage";
12957 int main(int argc, char **argv)
12959 return ash_main(argc, argv);
12965 * Copyright (c) 1989, 1991, 1993, 1994
12966 * The Regents of the University of California. All rights reserved.
12968 * This code is derived from software contributed to Berkeley by
12969 * Kenneth Almquist.
12971 * Redistribution and use in source and binary forms, with or without
12972 * modification, are permitted provided that the following conditions
12974 * 1. Redistributions of source code must retain the above copyright
12975 * notice, this list of conditions and the following disclaimer.
12976 * 2. Redistributions in binary form must reproduce the above copyright
12977 * notice, this list of conditions and the following disclaimer in the
12978 * documentation and/or other materials provided with the distribution.
12979 * 3. Neither the name of the University nor the names of its contributors
12980 * may be used to endorse or promote products derived from this software
12981 * without specific prior written permission.
12983 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
12984 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
12985 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
12986 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
12987 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
12988 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
12989 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
12990 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
12991 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
12992 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF