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 /* ============ Shell options */
71 static const char *const optletters_optnames[] = {
92 #define optletters(n) optletters_optnames[(n)][0]
93 #define optnames(n) (&optletters_optnames[(n)][1])
95 #define NOPTS (sizeof(optletters_optnames)/sizeof(optletters_optnames[0]))
97 static char optlist[NOPTS];
99 #define eflag optlist[0]
100 #define fflag optlist[1]
101 #define Iflag optlist[2]
102 #define iflag optlist[3]
103 #define mflag optlist[4]
104 #define nflag optlist[5]
105 #define sflag optlist[6]
106 #define xflag optlist[7]
107 #define vflag optlist[8]
108 #define Cflag optlist[9]
109 #define aflag optlist[10]
110 #define bflag optlist[11]
111 #define uflag optlist[12]
112 #define viflag optlist[13]
114 #define nolog optlist[14]
115 #define debug optlist[15]
119 /* ============ Misc data */
123 static int *dash_errno;
125 #define errno (*dash_errno)
128 static char nullstr[1]; /* zero length string */
129 static const char homestr[] = "HOME";
130 static const char snlfmt[] = "%s\n";
131 static const char illnum[] = "Illegal number: %s";
133 static int isloginsh;
134 /* pid of main shell */
136 /* shell level: 0 for the main shell, 1 for its children, and so on */
138 #define rootshell (!shlvl)
139 /* trap handler commands */
140 static char *trap[NSIG];
141 /* current value of signal */
142 static char sigmode[NSIG - 1];
143 /* indicates specified signal received */
144 static char gotsig[NSIG - 1];
145 static char *arg0; /* value of $0 */
148 /* ============ Interrupts / exceptions
150 * We enclose jmp_buf in a structure so that we can declare pointers to
151 * jump locations. The global variable handler contains the location to
152 * jump to when an exception occurs, and the global variable exception
153 * contains a code identifying the exception. To implement nested
154 * exception handlers, the user should save the value of handler on entry
155 * to an inner scope, set handler to point to a jmploc structure for the
156 * inner scope, and restore handler on exit from the scope.
161 static struct jmploc *exception_handler;
162 static int exception;
164 #define EXINT 0 /* SIGINT received */
165 #define EXERROR 1 /* a generic error */
166 #define EXSHELLPROC 2 /* execute a shell procedure */
167 #define EXEXEC 3 /* command execution failed */
168 #define EXEXIT 4 /* exit the shell */
169 #define EXSIG 5 /* trapped signal in wait(1) */
170 static volatile int suppressint;
171 static volatile sig_atomic_t intpending;
172 /* do we generate EXSIG events */
174 /* last pending signal */
175 static volatile sig_atomic_t pendingsigs;
178 * Sigmode records the current value of the signal handlers for the various
179 * modes. A value of zero means that the current handler is not known.
180 * S_HARD_IGN indicates that the signal was ignored on entry to the shell,
183 #define S_DFL 1 /* default signal handling (SIG_DFL) */
184 #define S_CATCH 2 /* signal is caught */
185 #define S_IGN 3 /* signal is ignored (SIG_IGN) */
186 #define S_HARD_IGN 4 /* signal is ignored permenantly */
187 #define S_RESET 5 /* temporary - to reset a hard ignored sig */
190 * These macros allow the user to suspend the handling of interrupt signals
191 * over a period of time. This is similar to SIGHOLD to or sigblock, but
192 * much more efficient and portable. (But hacking the kernel is so much
193 * more fun than worrying about efficiency and portability. :-))
195 #define xbarrier() ({ __asm__ __volatile__ ("": : :"memory"); })
204 * Called to raise an exception. Since C doesn't include exceptions, we
205 * just do a longjmp to the exception handler. The type of exception is
206 * stored in the global variable "exception".
208 static void raise_exception(int) ATTRIBUTE_NORETURN;
210 raise_exception(int e)
213 if (exception_handler == NULL)
218 longjmp(exception_handler->loc, 1);
222 * Called from trap.c when a SIGINT is received. (If the user specifies
223 * that SIGINT is to be trapped or ignored using the trap builtin, then
224 * this routine is not called.) Suppressint is nonzero when interrupts
225 * are held using the INT_OFF macro. (The test for iflag is just
226 * defensive programming.)
228 static void raise_interrupt(void) ATTRIBUTE_NORETURN;
230 raise_interrupt(void)
236 if (gotsig[SIGINT - 1] && !trap[SIGINT]) {
237 if (!(rootshell && iflag)) {
238 signal(SIGINT, SIG_DFL);
247 #if ENABLE_ASH_OPTIMIZE_FOR_SIZE
251 if (--suppressint == 0 && intpending) {
255 #define INT_ON int_on()
263 #define FORCE_INT_ON force_int_on()
268 if (--suppressint == 0 && intpending) raise_interrupt(); \
271 #define FORCE_INT_ON \
275 if (intpending) raise_interrupt(); \
278 #endif /* ASH_OPTIMIZE_FOR_SIZE */
280 #define SAVE_INT(v) ((v) = suppressint)
282 #define RESTORE_INT(v) \
286 if (suppressint == 0 && intpending) raise_interrupt(); \
295 raise_exception(EXSIG); \
298 /* EXSIG is turned off by evalbltin(). */
301 * Ignore a signal. Only one usage site - in forkchild()
306 if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) {
307 signal(signo, SIG_IGN);
309 sigmode[signo - 1] = S_HARD_IGN;
313 * Signal handler. Only one usage site - in setsignal()
318 gotsig[signo - 1] = 1;
321 if (exsig || (signo == SIGINT && !trap[SIGINT])) {
329 /* ============ Stdout/stderr output */
332 outstr(const char *p, FILE *file)
340 flush_stdout_stderr(void)
357 outcslow(int c, FILE *dest)
365 static int out1fmt(const char *, ...) __attribute__((__format__(__printf__,1,2)));
367 out1fmt(const char *fmt, ...)
374 r = vprintf(fmt, ap);
380 static int fmtstr(char *, size_t, const char *, ...) __attribute__((__format__(__printf__,3,4)));
382 fmtstr(char *outbuf, size_t length, const char *fmt, ...)
389 ret = vsnprintf(outbuf, length, fmt, ap);
396 out1str(const char *p)
402 out2str(const char *p)
409 /* ============ Parsing structures */
411 /* control characters in argument strings */
412 #define CTLESC '\201' /* escape next character */
413 #define CTLVAR '\202' /* variable defn */
414 #define CTLENDVAR '\203'
415 #define CTLBACKQ '\204'
416 #define CTLQUOTE 01 /* ored with CTLBACKQ code if in quotes */
417 /* CTLBACKQ | CTLQUOTE == '\205' */
418 #define CTLARI '\206' /* arithmetic expression */
419 #define CTLENDARI '\207'
420 #define CTLQUOTEMARK '\210'
422 /* variable substitution byte (follows CTLVAR) */
423 #define VSTYPE 0x0f /* type of variable substitution */
424 #define VSNUL 0x10 /* colon--treat the empty string as unset */
425 #define VSQUOTE 0x80 /* inside double quotes--suppress splitting */
427 /* values of VSTYPE field */
428 #define VSNORMAL 0x1 /* normal variable: $var or ${var} */
429 #define VSMINUS 0x2 /* ${var-text} */
430 #define VSPLUS 0x3 /* ${var+text} */
431 #define VSQUESTION 0x4 /* ${var?message} */
432 #define VSASSIGN 0x5 /* ${var=text} */
433 #define VSTRIMRIGHT 0x6 /* ${var%pattern} */
434 #define VSTRIMRIGHTMAX 0x7 /* ${var%%pattern} */
435 #define VSTRIMLEFT 0x8 /* ${var#pattern} */
436 #define VSTRIMLEFTMAX 0x9 /* ${var##pattern} */
437 #define VSLENGTH 0xa /* ${#var} */
472 union node *redirect;
478 struct nodelist *cmdlist;
484 union node *redirect;
497 union node *elsepart;
524 struct nodelist *backquote;
559 struct nredir nredir;
560 struct nbinary nbinary;
564 struct nclist nclist;
573 struct nodelist *next;
586 freefunc(struct funcnode *f)
588 if (f && --f->count < 0)
593 /* ============ Debugging output */
597 static FILE *tracefile;
600 trace_printf(const char *fmt, ...)
607 vfprintf(tracefile, fmt, va);
612 trace_vprintf(const char *fmt, va_list va)
616 vfprintf(tracefile, fmt, va);
620 trace_puts(const char *s)
628 trace_puts_quoted(char *s)
635 putc('"', tracefile);
636 for (p = s; *p; p++) {
638 case '\n': c = 'n'; goto backslash;
639 case '\t': c = 't'; goto backslash;
640 case '\r': c = 'r'; goto backslash;
641 case '"': c = '"'; goto backslash;
642 case '\\': c = '\\'; goto backslash;
643 case CTLESC: c = 'e'; goto backslash;
644 case CTLVAR: c = 'v'; goto backslash;
645 case CTLVAR+CTLQUOTE: c = 'V'; goto backslash;
646 case CTLBACKQ: c = 'q'; goto backslash;
647 case CTLBACKQ+CTLQUOTE: c = 'Q'; goto backslash;
649 putc('\\', tracefile);
653 if (*p >= ' ' && *p <= '~')
656 putc('\\', tracefile);
657 putc(*p >> 6 & 03, tracefile);
658 putc(*p >> 3 & 07, tracefile);
659 putc(*p & 07, tracefile);
664 putc('"', tracefile);
668 trace_puts_args(char **ap)
675 trace_puts_quoted(*ap);
677 putc('\n', tracefile);
680 putc(' ', tracefile);
695 /* leave open because libedit might be using it */
698 strcpy(s, "./trace");
700 if (!freopen(s, "a", tracefile)) {
701 fprintf(stderr, "Can't re-open %s\n", s);
706 tracefile = fopen(s, "a");
707 if (tracefile == NULL) {
708 fprintf(stderr, "Can't open %s\n", s);
714 flags = fcntl(fileno(tracefile), F_GETFL, 0);
716 fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND);
718 setlinebuf(tracefile);
719 fputs("\nTracing started.\n", tracefile);
723 indent(int amount, char *pfx, FILE *fp)
727 for (i = 0; i < amount; i++) {
728 if (pfx && i == amount - 1)
734 /* little circular references here... */
735 static void shtree(union node *n, int ind, char *pfx, FILE *fp);
738 sharg(union node *arg, FILE *fp)
741 struct nodelist *bqlist;
744 if (arg->type != NARG) {
745 out1fmt("<node type %d>\n", arg->type);
748 bqlist = arg->narg.backquote;
749 for (p = arg->narg.text; *p; p++) {
758 if (subtype == VSLENGTH)
767 switch (subtype & VSTYPE) {
800 out1fmt("<subtype %d>", subtype);
807 case CTLBACKQ|CTLQUOTE:
810 shtree(bqlist->n, -1, NULL, fp);
821 shcmd(union node *cmd, FILE *fp)
829 for (np = cmd->ncmd.args; np; np = np->narg.next) {
835 for (np = cmd->ncmd.redirect; np; np = np->nfile.next) {
838 switch (np->nfile.type) {
839 case NTO: s = ">"; dftfd = 1; break;
840 case NCLOBBER: s = ">|"; dftfd = 1; break;
841 case NAPPEND: s = ">>"; dftfd = 1; break;
842 case NTOFD: s = ">&"; dftfd = 1; break;
843 case NFROM: s = "<"; dftfd = 0; break;
844 case NFROMFD: s = "<&"; dftfd = 0; break;
845 case NFROMTO: s = "<>"; dftfd = 0; break;
846 default: s = "*error*"; dftfd = 0; break;
848 if (np->nfile.fd != dftfd)
849 fprintf(fp, "%d", np->nfile.fd);
851 if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) {
852 fprintf(fp, "%d", np->ndup.dupfd);
854 sharg(np->nfile.fname, fp);
861 shtree(union node *n, int ind, char *pfx, FILE *fp)
869 indent(ind, pfx, fp);
880 shtree(n->nbinary.ch1, ind, NULL, fp);
883 shtree(n->nbinary.ch2, ind, NULL, fp);
891 for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
896 if (n->npipe.backgnd)
902 fprintf(fp, "<node type %d>", n->type);
910 showtree(union node *n)
912 trace_puts("showtree called\n");
913 shtree(n, 1, NULL, stdout);
916 #define TRACE(param) trace_printf param
917 #define TRACEV(param) trace_vprintf param
922 #define TRACEV(param)
927 /* ============ Parser data */
930 * ash_vmsg() needs parsefile->fd, hence parsefile definition is moved up.
933 struct strlist *next;
942 struct strpush *prev; /* preceding string on stack */
946 struct alias *ap; /* if push was associated with an alias */
948 char *string; /* remember the string since it may change */
952 struct parsefile *prev; /* preceding file on stack */
953 int linno; /* current line */
954 int fd; /* file descriptor (or -1 if string) */
955 int nleft; /* number of chars left in this line */
956 int lleft; /* number of chars left in this buffer */
957 char *nextc; /* next char in buffer */
958 char *buf; /* input buffer */
959 struct strpush *strpush; /* for pushing strings at this level */
960 struct strpush basestrpush; /* so pushing one is fast */
963 static struct parsefile basepf; /* top level input file */
964 static struct parsefile *parsefile = &basepf; /* current input file */
965 static int startlinno; /* line # where last token started */
966 static char *commandname; /* currently executing command */
967 static struct strlist *cmdenviron; /* environment for builtin command */
968 static int exitstatus; /* exit status of last command */
971 /* ============ Message printing */
974 ash_vmsg(const char *msg, va_list ap)
976 fprintf(stderr, "%s: ", arg0);
978 const char *fmt = (!iflag || parsefile->fd) ?
980 fprintf(stderr, fmt, commandname, startlinno);
982 vfprintf(stderr, msg, ap);
983 outcslow('\n', stderr);
987 * Exverror is called to raise the error exception. If the second argument
988 * is not NULL then error prints an error message using printf style
989 * formatting. It then raises the error exception.
991 static void ash_vmsg_and_raise(int, const char *, va_list) ATTRIBUTE_NORETURN;
993 ash_vmsg_and_raise(int cond, const char *msg, va_list ap)
997 TRACE(("ash_vmsg_and_raise(%d, \"", cond));
999 TRACE(("\") pid=%d\n", getpid()));
1001 TRACE(("ash_vmsg_and_raise(%d, NULL) pid=%d\n", cond, getpid()));
1006 flush_stdout_stderr();
1007 raise_exception(cond);
1011 static void ash_msg_and_raise_error(const char *, ...) ATTRIBUTE_NORETURN;
1013 ash_msg_and_raise_error(const char *msg, ...)
1018 ash_vmsg_and_raise(EXERROR, msg, ap);
1023 static void ash_msg_and_raise(int, const char *, ...) ATTRIBUTE_NORETURN;
1025 ash_msg_and_raise(int cond, const char *msg, ...)
1030 ash_vmsg_and_raise(cond, msg, ap);
1036 * error/warning routines for external builtins
1039 ash_msg(const char *fmt, ...)
1049 * Return a string describing an error. The returned string may be a
1050 * pointer to a static buffer that will be overwritten on the next call.
1051 * Action describes the operation that got the error.
1054 errmsg(int e, const char *em)
1056 if (e == ENOENT || e == ENOTDIR) {
1063 /* ============ Memory allocation */
1066 * It appears that grabstackstr() will barf with such alignments
1067 * because stalloc() will return a string allocated in a new stackblock.
1069 #define SHELL_ALIGN(nbytes) (((nbytes) + SHELL_SIZE) & ~SHELL_SIZE)
1071 /* Most machines require the value returned from malloc to be aligned
1072 * in some way. The following macro will get this right
1073 * on many machines. */
1074 SHELL_SIZE = sizeof(union {int i; char *cp; double d; }) - 1,
1075 /* Minimum size of a block */
1076 MINSIZE = SHELL_ALIGN(504),
1079 struct stack_block {
1080 struct stack_block *prev;
1081 char space[MINSIZE];
1085 struct stack_block *stackp;
1088 struct stackmark *marknext;
1091 static struct stack_block stackbase;
1092 static struct stack_block *stackp = &stackbase;
1093 static struct stackmark *markp;
1094 static char *stacknxt = stackbase.space;
1095 static size_t stacknleft = MINSIZE;
1096 static char *sstrend = stackbase.space + MINSIZE;
1097 static int herefd = -1;
1099 #define stackblock() ((void *)stacknxt)
1100 #define stackblocksize() stacknleft
1103 ckrealloc(void * p, size_t nbytes)
1105 p = realloc(p, nbytes);
1107 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1112 ckmalloc(size_t nbytes)
1114 return ckrealloc(NULL, nbytes);
1118 * Make a copy of a string in safe storage.
1121 ckstrdup(const char *s)
1123 char *p = strdup(s);
1125 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1130 * Parse trees for commands are allocated in lifo order, so we use a stack
1131 * to make this more efficient, and also to avoid all sorts of exception
1132 * handling code to handle interrupts in the middle of a parse.
1134 * The size 504 was chosen because the Ultrix malloc handles that size
1138 stalloc(size_t nbytes)
1143 aligned = SHELL_ALIGN(nbytes);
1144 if (aligned > stacknleft) {
1147 struct stack_block *sp;
1149 blocksize = aligned;
1150 if (blocksize < MINSIZE)
1151 blocksize = MINSIZE;
1152 len = sizeof(struct stack_block) - MINSIZE + blocksize;
1153 if (len < blocksize)
1154 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1158 stacknxt = sp->space;
1159 stacknleft = blocksize;
1160 sstrend = stacknxt + blocksize;
1165 stacknxt += aligned;
1166 stacknleft -= aligned;
1174 if (!p || (stacknxt < (char *)p) || ((char *)p < stackp->space)) {
1175 write(2, "stunalloc\n", 10);
1179 stacknleft += stacknxt - (char *)p;
1184 * Like strdup but works with the ash stack.
1187 ststrdup(const char *p)
1189 size_t len = strlen(p) + 1;
1190 return memcpy(stalloc(len), p, len);
1194 setstackmark(struct stackmark *mark)
1196 mark->stackp = stackp;
1197 mark->stacknxt = stacknxt;
1198 mark->stacknleft = stacknleft;
1199 mark->marknext = markp;
1204 popstackmark(struct stackmark *mark)
1206 struct stack_block *sp;
1209 markp = mark->marknext;
1210 while (stackp != mark->stackp) {
1215 stacknxt = mark->stacknxt;
1216 stacknleft = mark->stacknleft;
1217 sstrend = mark->stacknxt + mark->stacknleft;
1222 * When the parser reads in a string, it wants to stick the string on the
1223 * stack and only adjust the stack pointer when it knows how big the
1224 * string is. Stackblock (defined in stack.h) returns a pointer to a block
1225 * of space on top of the stack and stackblocklen returns the length of
1226 * this block. Growstackblock will grow this space by at least one byte,
1227 * possibly moving it (like realloc). Grabstackblock actually allocates the
1228 * part of the block that has been used.
1231 growstackblock(void)
1235 newlen = stacknleft * 2;
1236 if (newlen < stacknleft)
1237 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1241 if (stacknxt == stackp->space && stackp != &stackbase) {
1242 struct stack_block *oldstackp;
1243 struct stackmark *xmark;
1244 struct stack_block *sp;
1245 struct stack_block *prevstackp;
1251 prevstackp = sp->prev;
1252 grosslen = newlen + sizeof(struct stack_block) - MINSIZE;
1253 sp = ckrealloc(sp, grosslen);
1254 sp->prev = prevstackp;
1256 stacknxt = sp->space;
1257 stacknleft = newlen;
1258 sstrend = sp->space + newlen;
1261 * Stack marks pointing to the start of the old block
1262 * must be relocated to point to the new block
1265 while (xmark != NULL && xmark->stackp == oldstackp) {
1266 xmark->stackp = stackp;
1267 xmark->stacknxt = stacknxt;
1268 xmark->stacknleft = stacknleft;
1269 xmark = xmark->marknext;
1273 char *oldspace = stacknxt;
1274 int oldlen = stacknleft;
1275 char *p = stalloc(newlen);
1277 /* free the space we just allocated */
1278 stacknxt = memcpy(p, oldspace, oldlen);
1279 stacknleft += newlen;
1284 grabstackblock(size_t len)
1286 len = SHELL_ALIGN(len);
1292 * The following routines are somewhat easier to use than the above.
1293 * The user declares a variable of type STACKSTR, which may be declared
1294 * to be a register. The macro STARTSTACKSTR initializes things. Then
1295 * the user uses the macro STPUTC to add characters to the string. In
1296 * effect, STPUTC(c, p) is the same as *p++ = c except that the stack is
1297 * grown as necessary. When the user is done, she can just leave the
1298 * string there and refer to it using stackblock(). Or she can allocate
1299 * the space for it using grabstackstr(). If it is necessary to allow
1300 * someone else to use the stack temporarily and then continue to grow
1301 * the string, the user should use grabstack to allocate the space, and
1302 * then call ungrabstr(p) to return to the previous mode of operation.
1304 * USTPUTC is like STPUTC except that it doesn't check for overflow.
1305 * CHECKSTACKSPACE can be called before USTPUTC to ensure that there
1306 * is space for at least one character.
1311 size_t len = stackblocksize();
1312 if (herefd >= 0 && len >= 1024) {
1313 full_write(herefd, stackblock(), len);
1314 return stackblock();
1317 return stackblock() + len;
1321 * Called from CHECKSTRSPACE.
1324 makestrspace(size_t newlen, char *p)
1326 size_t len = p - stacknxt;
1327 size_t size = stackblocksize();
1332 size = stackblocksize();
1334 if (nleft >= newlen)
1338 return stackblock() + len;
1342 stack_nputstr(const char *s, size_t n, char *p)
1344 p = makestrspace(n, p);
1345 p = memcpy(p, s, n) + n;
1350 stack_putstr(const char *s, char *p)
1352 return stack_nputstr(s, strlen(s), p);
1356 _STPUTC(int c, char *p)
1364 #define STARTSTACKSTR(p) ((p) = stackblock())
1365 #define STPUTC(c, p) ((p) = _STPUTC((c), (p)))
1366 #define CHECKSTRSPACE(n, p) \
1370 size_t m = sstrend - q; \
1372 (p) = makestrspace(l, q); \
1375 #define USTPUTC(c, p) (*p++ = (c))
1376 #define STACKSTRNUL(p) ((p) == sstrend ? (p = growstackstr(), *p = '\0') : (*p = '\0'))
1377 #define STUNPUTC(p) (--p)
1378 #define STTOPC(p) p[-1]
1379 #define STADJUST(amount, p) (p += (amount))
1381 #define grabstackstr(p) stalloc((char *)(p) - (char *)stackblock())
1382 #define ungrabstackstr(s, p) stunalloc((s))
1383 #define stackstrend() ((void *)sstrend)
1386 /* ============ String helpers */
1389 * prefix -- see if pfx is a prefix of string.
1392 prefix(const char *string, const char *pfx)
1395 if (*pfx++ != *string++)
1398 return (char *) string;
1402 * Check for a valid number. This should be elsewhere.
1405 is_number(const char *p)
1410 } while (*++p != '\0');
1415 * Convert a string of digits to an integer, printing an error message on
1419 number(const char *s)
1422 ash_msg_and_raise_error(illnum, s);
1427 * Produce a possibly single quoted string suitable as input to the shell.
1428 * The return string is allocated on the stack.
1431 single_quote(const char *s)
1441 len = strchrnul(s, '\'') - s;
1443 q = p = makestrspace(len + 3, p);
1446 q = memcpy(q, s, len) + len;
1452 len = strspn(s, "'");
1456 q = p = makestrspace(len + 3, p);
1459 q = memcpy(q, s, len) + len;
1468 return stackblock();
1472 /* ============ nextopt */
1474 static char **argptr; /* argument list for builtin commands */
1475 static char *optionarg; /* set by nextopt (like getopt) */
1476 static char *optptr; /* used by nextopt */
1479 * XXX - should get rid of. have all builtins use getopt(3). the
1480 * library getopt must have the BSD extension static variable "optreset"
1481 * otherwise it can't be used within the shell safely.
1483 * Standard option processing (a la getopt) for builtin routines. The
1484 * only argument that is passed to nextopt is the option string; the
1485 * other arguments are unnecessary. It return the character, or '\0' on
1489 nextopt(const char *optstring)
1496 if (p == NULL || *p == '\0') {
1498 if (p == NULL || *p != '-' || *++p == '\0')
1501 if (LONE_DASH(p)) /* check for "--" */
1505 for (q = optstring; *q != c; ) {
1507 ash_msg_and_raise_error("Illegal option -%c", c);
1512 if (*p == '\0' && (p = *argptr++) == NULL)
1513 ash_msg_and_raise_error("No arg for -%c option", c);
1522 /* ============ Shell variables */
1525 #define VEXPORT 0x01 /* variable is exported */
1526 #define VREADONLY 0x02 /* variable cannot be modified */
1527 #define VSTRFIXED 0x04 /* variable struct is statically allocated */
1528 #define VTEXTFIXED 0x08 /* text is statically allocated */
1529 #define VSTACK 0x10 /* text is allocated on the stack */
1530 #define VUNSET 0x20 /* the variable is not set */
1531 #define VNOFUNC 0x40 /* don't call the callback function */
1532 #define VNOSET 0x80 /* do not set variable - just readonly test */
1533 #define VNOSAVE 0x100 /* when text is on the heap before setvareq */
1535 # define VDYNAMIC 0x200 /* dynamic variable */
1540 static const char defpathvar[] = "PATH=/usr/local/bin:/usr/bin:/sbin:/bin";
1542 static const char defifsvar[] = "IFS= \t\n";
1543 #define defifs (defifsvar + 4)
1545 static const char defifs[] = " \t\n";
1549 int nparam; /* # of positional parameters (without $0) */
1550 unsigned char malloc; /* if parameter list dynamically allocated */
1551 char **p; /* parameter list */
1552 #if ENABLE_ASH_GETOPTS
1553 int optind; /* next parameter to be processed by getopts */
1554 int optoff; /* used by getopts */
1558 static struct shparam shellparam; /* $@ current positional parameters */
1560 #if ENABLE_ASH_GETOPTS
1562 getoptsreset(const char *value)
1564 shellparam.optind = number(value);
1565 shellparam.optoff = -1;
1570 struct var *next; /* next entry in hash list */
1571 int flags; /* flags are defined above */
1572 const char *text; /* name=value */
1573 void (*func)(const char *); /* function to be called when */
1574 /* the variable gets set/unset */
1578 struct localvar *next; /* next local variable in list */
1579 struct var *vp; /* the variable that was made local */
1580 int flags; /* saved flags */
1581 const char *text; /* saved text */
1584 /* Forward decls for varinit[] */
1585 #if ENABLE_LOCALE_SUPPORT
1587 change_lc_all(const char *value)
1589 if (value && *value != '\0')
1590 setlocale(LC_ALL, value);
1593 change_lc_ctype(const char *value)
1595 if (value && *value != '\0')
1596 setlocale(LC_CTYPE, value);
1600 static void chkmail(void);
1601 static void changemail(const char *);
1603 static void changepath(const char *);
1604 #if ENABLE_ASH_RANDOM_SUPPORT
1605 static void change_random(const char *);
1608 static struct var varinit[] = {
1610 { NULL, VSTRFIXED|VTEXTFIXED, defifsvar, NULL },
1612 { NULL, VSTRFIXED|VTEXTFIXED|VUNSET, "IFS\0", NULL },
1615 { NULL, VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL\0", changemail },
1616 { NULL, VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH\0", changemail },
1618 { NULL, VSTRFIXED|VTEXTFIXED, defpathvar, changepath },
1619 { NULL, VSTRFIXED|VTEXTFIXED, "PS1=$ ", NULL },
1620 { NULL, VSTRFIXED|VTEXTFIXED, "PS2=> ", NULL },
1621 { NULL, VSTRFIXED|VTEXTFIXED, "PS4=+ ", NULL },
1622 #if ENABLE_ASH_GETOPTS
1623 { NULL, VSTRFIXED|VTEXTFIXED, "OPTIND=1", getoptsreset },
1625 #if ENABLE_ASH_RANDOM_SUPPORT
1626 { NULL, VSTRFIXED|VTEXTFIXED|VUNSET|VDYNAMIC, "RANDOM\0", change_random },
1628 #if ENABLE_LOCALE_SUPPORT
1629 { NULL, VSTRFIXED | VTEXTFIXED | VUNSET, "LC_ALL\0", change_lc_all },
1630 { NULL, VSTRFIXED | VTEXTFIXED | VUNSET, "LC_CTYPE\0", change_lc_ctype },
1632 #if ENABLE_FEATURE_EDITING_SAVEHISTORY
1633 { NULL, VSTRFIXED | VTEXTFIXED | VUNSET, "HISTFILE\0", NULL },
1637 #define vifs varinit[0]
1639 #define vmail (&vifs)[1]
1640 #define vmpath (&vmail)[1]
1644 #define vpath (&vmpath)[1]
1645 #define vps1 (&vpath)[1]
1646 #define vps2 (&vps1)[1]
1647 #define vps4 (&vps2)[1]
1648 #define voptind (&vps4)[1]
1649 #if ENABLE_ASH_GETOPTS
1650 #define vrandom (&voptind)[1]
1652 #define vrandom (&vps4)[1]
1654 #define defpath (defpathvar + 5)
1657 * The following macros access the values of the above variables.
1658 * They have to skip over the name. They return the null string
1659 * for unset variables.
1661 #define ifsval() (vifs.text + 4)
1662 #define ifsset() ((vifs.flags & VUNSET) == 0)
1663 #define mailval() (vmail.text + 5)
1664 #define mpathval() (vmpath.text + 9)
1665 #define pathval() (vpath.text + 5)
1666 #define ps1val() (vps1.text + 4)
1667 #define ps2val() (vps2.text + 4)
1668 #define ps4val() (vps4.text + 4)
1669 #define optindval() (voptind.text + 7)
1671 #define mpathset() ((vmpath.flags & VUNSET) == 0)
1674 * The parsefile structure pointed to by the global variable parsefile
1675 * contains information about the current file being read.
1678 struct redirtab *next;
1683 static struct redirtab *redirlist;
1684 static int nullredirs;
1685 extern char **environ;
1686 static int preverrout_fd; /* save fd2 before print debug if xflag is set. */
1690 static struct var *vartab[VTABSIZE];
1692 #define is_name(c) ((c) == '_' || isalpha((unsigned char)(c)))
1693 #define is_in_name(c) ((c) == '_' || isalnum((unsigned char)(c)))
1696 * Return of a legal variable name (a letter or underscore followed by zero or
1697 * more letters, underscores, and digits).
1700 endofname(const char *name)
1708 if (!is_in_name(*p))
1715 * Compares two strings up to the first = or '\0'. The first
1716 * string must be terminated by '='; the second may be terminated by
1717 * either '=' or '\0'.
1720 varcmp(const char *p, const char *q)
1724 while ((c = *p) == (d = *q)) {
1739 varequal(const char *a, const char *b)
1741 return !varcmp(a, b);
1745 * Find the appropriate entry in the hash table from the name.
1747 static struct var **
1748 hashvar(const char *p)
1752 hashval = ((unsigned char) *p) << 4;
1753 while (*p && *p != '=')
1754 hashval += (unsigned char) *p++;
1755 return &vartab[hashval % VTABSIZE];
1759 vpcmp(const void *a, const void *b)
1761 return varcmp(*(const char **)a, *(const char **)b);
1765 * This routine initializes the builtin variables.
1775 * PS1 depends on uid
1777 #if ENABLE_FEATURE_EDITING && ENABLE_FEATURE_EDITING_FANCY_PROMPT
1778 vps1.text = "PS1=\\w \\$ ";
1781 vps1.text = "PS1=# ";
1784 end = vp + sizeof(varinit) / sizeof(varinit[0]);
1786 vpp = hashvar(vp->text);
1789 } while (++vp < end);
1792 static struct var **
1793 findvar(struct var **vpp, const char *name)
1795 for (; *vpp; vpp = &(*vpp)->next) {
1796 if (varequal((*vpp)->text, name)) {
1804 * Find the value of a variable. Returns NULL if not set.
1807 lookupvar(const char *name)
1811 v = *findvar(hashvar(name), name);
1815 * Dynamic variables are implemented roughly the same way they are
1816 * in bash. Namely, they're "special" so long as they aren't unset.
1817 * As soon as they're unset, they're no longer dynamic, and dynamic
1818 * lookup will no longer happen at that point. -- PFM.
1820 if ((v->flags & VDYNAMIC))
1823 if (!(v->flags & VUNSET))
1824 return strchrnul(v->text, '=') + 1;
1830 * Search the environment of a builtin command.
1833 bltinlookup(const char *name)
1837 for (sp = cmdenviron; sp; sp = sp->next) {
1838 if (varequal(sp->text, name))
1839 return strchrnul(sp->text, '=') + 1;
1841 return lookupvar(name);
1845 * Same as setvar except that the variable and value are passed in
1846 * the first argument as name=value. Since the first argument will
1847 * be actually stored in the table, it should not be a string that
1849 * Called with interrupts off.
1852 setvareq(char *s, int flags)
1854 struct var *vp, **vpp;
1857 flags |= (VEXPORT & (((unsigned) (1 - aflag)) - 1));
1858 vp = *findvar(vpp, s);
1860 if ((vp->flags & (VREADONLY|VDYNAMIC)) == VREADONLY) {
1863 if (flags & VNOSAVE)
1866 ash_msg_and_raise_error("%.*s: is read only", strchrnul(n, '=') - n, n);
1872 if (vp->func && (flags & VNOFUNC) == 0)
1873 (*vp->func)(strchrnul(s, '=') + 1);
1875 if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
1876 free((char*)vp->text);
1878 flags |= vp->flags & ~(VTEXTFIXED|VSTACK|VNOSAVE|VUNSET);
1883 vp = ckmalloc(sizeof(*vp));
1888 if (!(flags & (VTEXTFIXED|VSTACK|VNOSAVE)))
1895 * Set the value of a variable. The flags argument is ored with the
1896 * flags of the variable. If val is NULL, the variable is unset.
1899 setvar(const char *name, const char *val, int flags)
1906 q = endofname(name);
1907 p = strchrnul(q, '=');
1909 if (!namelen || p != q)
1910 ash_msg_and_raise_error("%.*s: bad variable name", namelen, name);
1915 vallen = strlen(val);
1918 nameeq = ckmalloc(namelen + vallen + 2);
1919 p = memcpy(nameeq, name, namelen) + namelen;
1922 p = memcpy(p, val, vallen) + vallen;
1925 setvareq(nameeq, flags | VNOSAVE);
1929 #if ENABLE_ASH_GETOPTS
1931 * Safe version of setvar, returns 1 on success 0 on failure.
1934 setvarsafe(const char *name, const char *val, int flags)
1937 volatile int saveint;
1938 struct jmploc *volatile savehandler = exception_handler;
1939 struct jmploc jmploc;
1942 if (setjmp(jmploc.loc))
1945 exception_handler = &jmploc;
1946 setvar(name, val, flags);
1949 exception_handler = savehandler;
1950 RESTORE_INT(saveint);
1956 * Unset the specified variable.
1959 unsetvar(const char *s)
1965 vpp = findvar(hashvar(s), s);
1969 int flags = vp->flags;
1972 if (flags & VREADONLY)
1975 vp->flags &= ~VDYNAMIC;
1979 if ((flags & VSTRFIXED) == 0) {
1981 if ((flags & (VTEXTFIXED|VSTACK)) == 0)
1982 free((char*)vp->text);
1988 vp->flags &= ~VEXPORT;
1998 * Process a linked list of variable assignments.
2001 listsetvar(struct strlist *list_set_var, int flags)
2003 struct strlist *lp = list_set_var;
2009 setvareq(lp->text, flags);
2016 * Generate a list of variables satisfying the given conditions.
2019 listvars(int on, int off, char ***end)
2030 for (vp = *vpp; vp; vp = vp->next) {
2031 if ((vp->flags & mask) == on) {
2032 if (ep == stackstrend())
2033 ep = growstackstr();
2034 *ep++ = (char *) vp->text;
2037 } while (++vpp < vartab + VTABSIZE);
2038 if (ep == stackstrend())
2039 ep = growstackstr();
2043 return grabstackstr(ep);
2047 /* ============ Path search helper
2049 * The variable path (passed by reference) should be set to the start
2050 * of the path before the first call; padvance will update
2051 * this value as it proceeds. Successive calls to padvance will return
2052 * the possible path expansions in sequence. If an option (indicated by
2053 * a percent sign) appears in the path entry then the global variable
2054 * pathopt will be set to point to it; otherwise pathopt will be set to
2057 static const char *pathopt; /* set by padvance */
2060 padvance(const char **path, const char *name)
2070 for (p = start; *p && *p != ':' && *p != '%'; p++);
2071 len = p - start + strlen(name) + 2; /* "2" is for '/' and '\0' */
2072 while (stackblocksize() < len)
2076 memcpy(q, start, p - start);
2084 while (*p && *p != ':') p++;
2090 return stalloc(len);
2094 /* ============ Prompt */
2096 static int doprompt; /* if set, prompt the user */
2097 static int needprompt; /* true if interactive and at start of line */
2099 #if ENABLE_FEATURE_EDITING
2100 static line_input_t *line_input_state;
2101 static const char *cmdedit_prompt;
2103 putprompt(const char *s)
2105 if (ENABLE_ASH_EXPAND_PRMT) {
2106 free((char*)cmdedit_prompt);
2107 cmdedit_prompt = xstrdup(s);
2114 putprompt(const char *s)
2120 #if ENABLE_ASH_EXPAND_PRMT
2121 /* expandstr() needs parsing machinery, so it is far away ahead... */
2122 static const char *expandstr(const char *ps);
2124 #define expandstr(s) s
2128 setprompt(int whichprompt)
2131 #if ENABLE_ASH_EXPAND_PRMT
2132 struct stackmark smark;
2137 switch (whichprompt) {
2147 #if ENABLE_ASH_EXPAND_PRMT
2148 setstackmark(&smark);
2149 stalloc(stackblocksize());
2151 putprompt(expandstr(prompt));
2152 #if ENABLE_ASH_EXPAND_PRMT
2153 popstackmark(&smark);
2158 /* ============ The cd and pwd commands */
2160 #define CD_PHYSICAL 1
2163 static int docd(const char *, int);
2165 static char *curdir = nullstr; /* current working directory */
2166 static char *physdir = nullstr; /* physical working directory */
2175 while ((i = nextopt("LP"))) {
2177 flags ^= CD_PHYSICAL;
2186 * Update curdir (the name of the current directory) in response to a
2190 updatepwd(const char *dir)
2197 cdcomppath = ststrdup(dir);
2200 if (curdir == nullstr)
2202 new = stack_putstr(curdir, new);
2204 new = makestrspace(strlen(dir) + 2, new);
2205 lim = stackblock() + 1;
2209 if (new > lim && *lim == '/')
2214 if (dir[1] == '/' && dir[2] != '/') {
2220 p = strtok(cdcomppath, "/");
2224 if (p[1] == '.' && p[2] == '\0') {
2231 } else if (p[1] == '\0')
2235 new = stack_putstr(p, new);
2243 return stackblock();
2247 * Find out what the current directory is. If we already know the current
2248 * directory, this routine returns immediately.
2253 char *dir = getcwd(0, 0);
2254 return dir ? dir : nullstr;
2258 setpwd(const char *val, int setold)
2262 oldcur = dir = curdir;
2265 setvar("OLDPWD", oldcur, VEXPORT);
2268 if (physdir != nullstr) {
2269 if (physdir != oldcur)
2273 if (oldcur == val || !val) {
2279 dir = ckstrdup(val);
2280 if (oldcur != dir && oldcur != nullstr) {
2285 setvar("PWD", dir, VEXPORT);
2288 static void hashcd(void);
2291 * Actually do the chdir. We also call hashcd to let the routines in exec.c
2292 * know that the current directory has changed.
2295 docd(const char *dest, int flags)
2297 const char *dir = 0;
2300 TRACE(("docd(\"%s\", %d) called\n", dest, flags));
2303 if (!(flags & CD_PHYSICAL)) {
2304 dir = updatepwd(dest);
2319 cdcmd(int argc, char **argv)
2331 dest = bltinlookup(homestr);
2332 else if (LONE_DASH(dest)) {
2333 dest = bltinlookup("OLDPWD");
2355 path = bltinlookup("CDPATH");
2364 p = padvance(&path, dest);
2365 if (stat(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) {
2369 if (!docd(p, flags))
2374 ash_msg_and_raise_error("can't cd to %s", dest);
2377 if (flags & CD_PRINT)
2378 out1fmt(snlfmt, curdir);
2383 pwdcmd(int argc, char **argv)
2386 const char *dir = curdir;
2390 if (physdir == nullstr)
2394 out1fmt(snlfmt, dir);
2399 /* ============ ... */
2401 #define IBUFSIZ (BUFSIZ + 1)
2402 #define basebuf bb_common_bufsiz1 /* buffer for top level input file */
2407 static const char spcstr[] = " ";
2408 static const char dolatstr[] = { CTLVAR, VSNORMAL|VSQUOTE, '@', '=', '\0' };
2410 /* Syntax classes */
2411 #define CWORD 0 /* character is nothing special */
2412 #define CNL 1 /* newline character */
2413 #define CBACK 2 /* a backslash character */
2414 #define CSQUOTE 3 /* single quote */
2415 #define CDQUOTE 4 /* double quote */
2416 #define CENDQUOTE 5 /* a terminating quote */
2417 #define CBQUOTE 6 /* backwards single quote */
2418 #define CVAR 7 /* a dollar sign */
2419 #define CENDVAR 8 /* a '}' character */
2420 #define CLP 9 /* a left paren in arithmetic */
2421 #define CRP 10 /* a right paren in arithmetic */
2422 #define CENDFILE 11 /* end of file */
2423 #define CCTL 12 /* like CWORD, except it must be escaped */
2424 #define CSPCL 13 /* these terminate a word */
2425 #define CIGN 14 /* character should be ignored */
2427 #if ENABLE_ASH_ALIAS
2431 #define PEOA_OR_PEOF PEOA
2435 #define PEOA_OR_PEOF PEOF
2438 /* C99 say: "char" declaration may be signed or unsigned default */
2439 #define SC2INT(chr2may_be_negative_int) (int)((signed char)chr2may_be_negative_int)
2442 * is_special(c) evaluates to 1 for c in "!#$*-0123456789?@"; 0 otherwise
2443 * (assuming ascii char codes, as the original implementation did)
2445 #define is_special(c) \
2446 ( (((unsigned int)c) - 33 < 32) \
2447 && ((0xc1ff920dUL >> (((unsigned int)c) - 33)) & 1))
2449 #if ENABLE_ASH_OPTIMIZE_FOR_SIZE
2450 #define USE_SIT_FUNCTION
2453 /* number syntax index */
2454 #define BASESYNTAX 0 /* not in quotes */
2455 #define DQSYNTAX 1 /* in double quotes */
2456 #define SQSYNTAX 2 /* in single quotes */
2457 #define ARISYNTAX 3 /* in arithmetic */
2459 #if ENABLE_ASH_MATH_SUPPORT
2460 static const char S_I_T[][4] = {
2461 #if ENABLE_ASH_ALIAS
2462 {CSPCL, CIGN, CIGN, CIGN}, /* 0, PEOA */
2464 {CSPCL, CWORD, CWORD, CWORD}, /* 1, ' ' */
2465 {CNL, CNL, CNL, CNL}, /* 2, \n */
2466 {CWORD, CCTL, CCTL, CWORD}, /* 3, !*-/:=?[]~ */
2467 {CDQUOTE, CENDQUOTE, CWORD, CWORD}, /* 4, '"' */
2468 {CVAR, CVAR, CWORD, CVAR}, /* 5, $ */
2469 {CSQUOTE, CWORD, CENDQUOTE, CWORD}, /* 6, "'" */
2470 {CSPCL, CWORD, CWORD, CLP}, /* 7, ( */
2471 {CSPCL, CWORD, CWORD, CRP}, /* 8, ) */
2472 {CBACK, CBACK, CCTL, CBACK}, /* 9, \ */
2473 {CBQUOTE, CBQUOTE, CWORD, CBQUOTE}, /* 10, ` */
2474 {CENDVAR, CENDVAR, CWORD, CENDVAR}, /* 11, } */
2475 #ifndef USE_SIT_FUNCTION
2476 {CENDFILE, CENDFILE, CENDFILE, CENDFILE}, /* 12, PEOF */
2477 {CWORD, CWORD, CWORD, CWORD}, /* 13, 0-9A-Za-z */
2478 {CCTL, CCTL, CCTL, CCTL} /* 14, CTLESC ... */
2482 static const char S_I_T[][3] = {
2483 #if ENABLE_ASH_ALIAS
2484 {CSPCL, CIGN, CIGN}, /* 0, PEOA */
2486 {CSPCL, CWORD, CWORD}, /* 1, ' ' */
2487 {CNL, CNL, CNL}, /* 2, \n */
2488 {CWORD, CCTL, CCTL}, /* 3, !*-/:=?[]~ */
2489 {CDQUOTE, CENDQUOTE, CWORD}, /* 4, '"' */
2490 {CVAR, CVAR, CWORD}, /* 5, $ */
2491 {CSQUOTE, CWORD, CENDQUOTE}, /* 6, "'" */
2492 {CSPCL, CWORD, CWORD}, /* 7, ( */
2493 {CSPCL, CWORD, CWORD}, /* 8, ) */
2494 {CBACK, CBACK, CCTL}, /* 9, \ */
2495 {CBQUOTE, CBQUOTE, CWORD}, /* 10, ` */
2496 {CENDVAR, CENDVAR, CWORD}, /* 11, } */
2497 #ifndef USE_SIT_FUNCTION
2498 {CENDFILE, CENDFILE, CENDFILE}, /* 12, PEOF */
2499 {CWORD, CWORD, CWORD}, /* 13, 0-9A-Za-z */
2500 {CCTL, CCTL, CCTL} /* 14, CTLESC ... */
2503 #endif /* ASH_MATH_SUPPORT */
2505 #ifdef USE_SIT_FUNCTION
2507 #define U_C(c) ((unsigned char)(c))
2510 SIT(int c, int syntax)
2512 static const char spec_symbls[] = "\t\n !\"$&'()*-/:;<=>?[\\]`|}~";
2513 #if ENABLE_ASH_ALIAS
2514 static const char syntax_index_table[] = {
2515 1, 2, 1, 3, 4, 5, 1, 6, /* "\t\n !\"$&'" */
2516 7, 8, 3, 3, 3, 3, 1, 1, /* "()*-/:;<" */
2517 3, 1, 3, 3, 9, 3, 10, 1, /* "=>?[\\]`|" */
2521 static const char syntax_index_table[] = {
2522 0, 1, 0, 2, 3, 4, 0, 5, /* "\t\n !\"$&'" */
2523 6, 7, 2, 2, 2, 2, 0, 0, /* "()*-/:;<" */
2524 2, 0, 2, 2, 8, 2, 9, 0, /* "=>?[\\]`|" */
2531 if (c == PEOF) /* 2^8+2 */
2533 #if ENABLE_ASH_ALIAS
2534 if (c == PEOA) /* 2^8+1 */
2538 if (U_C(c) >= U_C(CTLESC) && U_C(c) <= U_C(CTLQUOTEMARK))
2541 s = strchr(spec_symbls, c);
2542 if (s == NULL || *s == '\0')
2544 indx = syntax_index_table[(s - spec_symbls)];
2546 return S_I_T[indx][syntax];
2549 #else /* USE_SIT_FUNCTION */
2551 #define SIT(c, syntax) S_I_T[(int)syntax_index_table[((int)c)+SYNBASE]][syntax]
2553 #if ENABLE_ASH_ALIAS
2554 #define CSPCL_CIGN_CIGN_CIGN 0
2555 #define CSPCL_CWORD_CWORD_CWORD 1
2556 #define CNL_CNL_CNL_CNL 2
2557 #define CWORD_CCTL_CCTL_CWORD 3
2558 #define CDQUOTE_CENDQUOTE_CWORD_CWORD 4
2559 #define CVAR_CVAR_CWORD_CVAR 5
2560 #define CSQUOTE_CWORD_CENDQUOTE_CWORD 6
2561 #define CSPCL_CWORD_CWORD_CLP 7
2562 #define CSPCL_CWORD_CWORD_CRP 8
2563 #define CBACK_CBACK_CCTL_CBACK 9
2564 #define CBQUOTE_CBQUOTE_CWORD_CBQUOTE 10
2565 #define CENDVAR_CENDVAR_CWORD_CENDVAR 11
2566 #define CENDFILE_CENDFILE_CENDFILE_CENDFILE 12
2567 #define CWORD_CWORD_CWORD_CWORD 13
2568 #define CCTL_CCTL_CCTL_CCTL 14
2570 #define CSPCL_CWORD_CWORD_CWORD 0
2571 #define CNL_CNL_CNL_CNL 1
2572 #define CWORD_CCTL_CCTL_CWORD 2
2573 #define CDQUOTE_CENDQUOTE_CWORD_CWORD 3
2574 #define CVAR_CVAR_CWORD_CVAR 4
2575 #define CSQUOTE_CWORD_CENDQUOTE_CWORD 5
2576 #define CSPCL_CWORD_CWORD_CLP 6
2577 #define CSPCL_CWORD_CWORD_CRP 7
2578 #define CBACK_CBACK_CCTL_CBACK 8
2579 #define CBQUOTE_CBQUOTE_CWORD_CBQUOTE 9
2580 #define CENDVAR_CENDVAR_CWORD_CENDVAR 10
2581 #define CENDFILE_CENDFILE_CENDFILE_CENDFILE 11
2582 #define CWORD_CWORD_CWORD_CWORD 12
2583 #define CCTL_CCTL_CCTL_CCTL 13
2586 static const char syntax_index_table[258] = {
2587 /* BASESYNTAX_DQSYNTAX_SQSYNTAX_ARISYNTAX */
2588 /* 0 PEOF */ CENDFILE_CENDFILE_CENDFILE_CENDFILE,
2589 #if ENABLE_ASH_ALIAS
2590 /* 1 PEOA */ CSPCL_CIGN_CIGN_CIGN,
2592 /* 2 -128 0x80 */ CWORD_CWORD_CWORD_CWORD,
2593 /* 3 -127 CTLESC */ CCTL_CCTL_CCTL_CCTL,
2594 /* 4 -126 CTLVAR */ CCTL_CCTL_CCTL_CCTL,
2595 /* 5 -125 CTLENDVAR */ CCTL_CCTL_CCTL_CCTL,
2596 /* 6 -124 CTLBACKQ */ CCTL_CCTL_CCTL_CCTL,
2597 /* 7 -123 CTLQUOTE */ CCTL_CCTL_CCTL_CCTL,
2598 /* 8 -122 CTLARI */ CCTL_CCTL_CCTL_CCTL,
2599 /* 9 -121 CTLENDARI */ CCTL_CCTL_CCTL_CCTL,
2600 /* 10 -120 CTLQUOTEMARK */ CCTL_CCTL_CCTL_CCTL,
2601 /* 11 -119 */ CWORD_CWORD_CWORD_CWORD,
2602 /* 12 -118 */ CWORD_CWORD_CWORD_CWORD,
2603 /* 13 -117 */ CWORD_CWORD_CWORD_CWORD,
2604 /* 14 -116 */ CWORD_CWORD_CWORD_CWORD,
2605 /* 15 -115 */ CWORD_CWORD_CWORD_CWORD,
2606 /* 16 -114 */ CWORD_CWORD_CWORD_CWORD,
2607 /* 17 -113 */ CWORD_CWORD_CWORD_CWORD,
2608 /* 18 -112 */ CWORD_CWORD_CWORD_CWORD,
2609 /* 19 -111 */ CWORD_CWORD_CWORD_CWORD,
2610 /* 20 -110 */ CWORD_CWORD_CWORD_CWORD,
2611 /* 21 -109 */ CWORD_CWORD_CWORD_CWORD,
2612 /* 22 -108 */ CWORD_CWORD_CWORD_CWORD,
2613 /* 23 -107 */ CWORD_CWORD_CWORD_CWORD,
2614 /* 24 -106 */ CWORD_CWORD_CWORD_CWORD,
2615 /* 25 -105 */ CWORD_CWORD_CWORD_CWORD,
2616 /* 26 -104 */ CWORD_CWORD_CWORD_CWORD,
2617 /* 27 -103 */ CWORD_CWORD_CWORD_CWORD,
2618 /* 28 -102 */ CWORD_CWORD_CWORD_CWORD,
2619 /* 29 -101 */ CWORD_CWORD_CWORD_CWORD,
2620 /* 30 -100 */ CWORD_CWORD_CWORD_CWORD,
2621 /* 31 -99 */ CWORD_CWORD_CWORD_CWORD,
2622 /* 32 -98 */ CWORD_CWORD_CWORD_CWORD,
2623 /* 33 -97 */ CWORD_CWORD_CWORD_CWORD,
2624 /* 34 -96 */ CWORD_CWORD_CWORD_CWORD,
2625 /* 35 -95 */ CWORD_CWORD_CWORD_CWORD,
2626 /* 36 -94 */ CWORD_CWORD_CWORD_CWORD,
2627 /* 37 -93 */ CWORD_CWORD_CWORD_CWORD,
2628 /* 38 -92 */ CWORD_CWORD_CWORD_CWORD,
2629 /* 39 -91 */ CWORD_CWORD_CWORD_CWORD,
2630 /* 40 -90 */ CWORD_CWORD_CWORD_CWORD,
2631 /* 41 -89 */ CWORD_CWORD_CWORD_CWORD,
2632 /* 42 -88 */ CWORD_CWORD_CWORD_CWORD,
2633 /* 43 -87 */ CWORD_CWORD_CWORD_CWORD,
2634 /* 44 -86 */ CWORD_CWORD_CWORD_CWORD,
2635 /* 45 -85 */ CWORD_CWORD_CWORD_CWORD,
2636 /* 46 -84 */ CWORD_CWORD_CWORD_CWORD,
2637 /* 47 -83 */ CWORD_CWORD_CWORD_CWORD,
2638 /* 48 -82 */ CWORD_CWORD_CWORD_CWORD,
2639 /* 49 -81 */ CWORD_CWORD_CWORD_CWORD,
2640 /* 50 -80 */ CWORD_CWORD_CWORD_CWORD,
2641 /* 51 -79 */ CWORD_CWORD_CWORD_CWORD,
2642 /* 52 -78 */ CWORD_CWORD_CWORD_CWORD,
2643 /* 53 -77 */ CWORD_CWORD_CWORD_CWORD,
2644 /* 54 -76 */ CWORD_CWORD_CWORD_CWORD,
2645 /* 55 -75 */ CWORD_CWORD_CWORD_CWORD,
2646 /* 56 -74 */ CWORD_CWORD_CWORD_CWORD,
2647 /* 57 -73 */ CWORD_CWORD_CWORD_CWORD,
2648 /* 58 -72 */ CWORD_CWORD_CWORD_CWORD,
2649 /* 59 -71 */ CWORD_CWORD_CWORD_CWORD,
2650 /* 60 -70 */ CWORD_CWORD_CWORD_CWORD,
2651 /* 61 -69 */ CWORD_CWORD_CWORD_CWORD,
2652 /* 62 -68 */ CWORD_CWORD_CWORD_CWORD,
2653 /* 63 -67 */ CWORD_CWORD_CWORD_CWORD,
2654 /* 64 -66 */ CWORD_CWORD_CWORD_CWORD,
2655 /* 65 -65 */ CWORD_CWORD_CWORD_CWORD,
2656 /* 66 -64 */ CWORD_CWORD_CWORD_CWORD,
2657 /* 67 -63 */ CWORD_CWORD_CWORD_CWORD,
2658 /* 68 -62 */ CWORD_CWORD_CWORD_CWORD,
2659 /* 69 -61 */ CWORD_CWORD_CWORD_CWORD,
2660 /* 70 -60 */ CWORD_CWORD_CWORD_CWORD,
2661 /* 71 -59 */ CWORD_CWORD_CWORD_CWORD,
2662 /* 72 -58 */ CWORD_CWORD_CWORD_CWORD,
2663 /* 73 -57 */ CWORD_CWORD_CWORD_CWORD,
2664 /* 74 -56 */ CWORD_CWORD_CWORD_CWORD,
2665 /* 75 -55 */ CWORD_CWORD_CWORD_CWORD,
2666 /* 76 -54 */ CWORD_CWORD_CWORD_CWORD,
2667 /* 77 -53 */ CWORD_CWORD_CWORD_CWORD,
2668 /* 78 -52 */ CWORD_CWORD_CWORD_CWORD,
2669 /* 79 -51 */ CWORD_CWORD_CWORD_CWORD,
2670 /* 80 -50 */ CWORD_CWORD_CWORD_CWORD,
2671 /* 81 -49 */ CWORD_CWORD_CWORD_CWORD,
2672 /* 82 -48 */ CWORD_CWORD_CWORD_CWORD,
2673 /* 83 -47 */ CWORD_CWORD_CWORD_CWORD,
2674 /* 84 -46 */ CWORD_CWORD_CWORD_CWORD,
2675 /* 85 -45 */ CWORD_CWORD_CWORD_CWORD,
2676 /* 86 -44 */ CWORD_CWORD_CWORD_CWORD,
2677 /* 87 -43 */ CWORD_CWORD_CWORD_CWORD,
2678 /* 88 -42 */ CWORD_CWORD_CWORD_CWORD,
2679 /* 89 -41 */ CWORD_CWORD_CWORD_CWORD,
2680 /* 90 -40 */ CWORD_CWORD_CWORD_CWORD,
2681 /* 91 -39 */ CWORD_CWORD_CWORD_CWORD,
2682 /* 92 -38 */ CWORD_CWORD_CWORD_CWORD,
2683 /* 93 -37 */ CWORD_CWORD_CWORD_CWORD,
2684 /* 94 -36 */ CWORD_CWORD_CWORD_CWORD,
2685 /* 95 -35 */ CWORD_CWORD_CWORD_CWORD,
2686 /* 96 -34 */ CWORD_CWORD_CWORD_CWORD,
2687 /* 97 -33 */ CWORD_CWORD_CWORD_CWORD,
2688 /* 98 -32 */ CWORD_CWORD_CWORD_CWORD,
2689 /* 99 -31 */ CWORD_CWORD_CWORD_CWORD,
2690 /* 100 -30 */ CWORD_CWORD_CWORD_CWORD,
2691 /* 101 -29 */ CWORD_CWORD_CWORD_CWORD,
2692 /* 102 -28 */ CWORD_CWORD_CWORD_CWORD,
2693 /* 103 -27 */ CWORD_CWORD_CWORD_CWORD,
2694 /* 104 -26 */ CWORD_CWORD_CWORD_CWORD,
2695 /* 105 -25 */ CWORD_CWORD_CWORD_CWORD,
2696 /* 106 -24 */ CWORD_CWORD_CWORD_CWORD,
2697 /* 107 -23 */ CWORD_CWORD_CWORD_CWORD,
2698 /* 108 -22 */ CWORD_CWORD_CWORD_CWORD,
2699 /* 109 -21 */ CWORD_CWORD_CWORD_CWORD,
2700 /* 110 -20 */ CWORD_CWORD_CWORD_CWORD,
2701 /* 111 -19 */ CWORD_CWORD_CWORD_CWORD,
2702 /* 112 -18 */ CWORD_CWORD_CWORD_CWORD,
2703 /* 113 -17 */ CWORD_CWORD_CWORD_CWORD,
2704 /* 114 -16 */ CWORD_CWORD_CWORD_CWORD,
2705 /* 115 -15 */ CWORD_CWORD_CWORD_CWORD,
2706 /* 116 -14 */ CWORD_CWORD_CWORD_CWORD,
2707 /* 117 -13 */ CWORD_CWORD_CWORD_CWORD,
2708 /* 118 -12 */ CWORD_CWORD_CWORD_CWORD,
2709 /* 119 -11 */ CWORD_CWORD_CWORD_CWORD,
2710 /* 120 -10 */ CWORD_CWORD_CWORD_CWORD,
2711 /* 121 -9 */ CWORD_CWORD_CWORD_CWORD,
2712 /* 122 -8 */ CWORD_CWORD_CWORD_CWORD,
2713 /* 123 -7 */ CWORD_CWORD_CWORD_CWORD,
2714 /* 124 -6 */ CWORD_CWORD_CWORD_CWORD,
2715 /* 125 -5 */ CWORD_CWORD_CWORD_CWORD,
2716 /* 126 -4 */ CWORD_CWORD_CWORD_CWORD,
2717 /* 127 -3 */ CWORD_CWORD_CWORD_CWORD,
2718 /* 128 -2 */ CWORD_CWORD_CWORD_CWORD,
2719 /* 129 -1 */ CWORD_CWORD_CWORD_CWORD,
2720 /* 130 0 */ CWORD_CWORD_CWORD_CWORD,
2721 /* 131 1 */ CWORD_CWORD_CWORD_CWORD,
2722 /* 132 2 */ CWORD_CWORD_CWORD_CWORD,
2723 /* 133 3 */ CWORD_CWORD_CWORD_CWORD,
2724 /* 134 4 */ CWORD_CWORD_CWORD_CWORD,
2725 /* 135 5 */ CWORD_CWORD_CWORD_CWORD,
2726 /* 136 6 */ CWORD_CWORD_CWORD_CWORD,
2727 /* 137 7 */ CWORD_CWORD_CWORD_CWORD,
2728 /* 138 8 */ CWORD_CWORD_CWORD_CWORD,
2729 /* 139 9 "\t" */ CSPCL_CWORD_CWORD_CWORD,
2730 /* 140 10 "\n" */ CNL_CNL_CNL_CNL,
2731 /* 141 11 */ CWORD_CWORD_CWORD_CWORD,
2732 /* 142 12 */ CWORD_CWORD_CWORD_CWORD,
2733 /* 143 13 */ CWORD_CWORD_CWORD_CWORD,
2734 /* 144 14 */ CWORD_CWORD_CWORD_CWORD,
2735 /* 145 15 */ CWORD_CWORD_CWORD_CWORD,
2736 /* 146 16 */ CWORD_CWORD_CWORD_CWORD,
2737 /* 147 17 */ CWORD_CWORD_CWORD_CWORD,
2738 /* 148 18 */ CWORD_CWORD_CWORD_CWORD,
2739 /* 149 19 */ CWORD_CWORD_CWORD_CWORD,
2740 /* 150 20 */ CWORD_CWORD_CWORD_CWORD,
2741 /* 151 21 */ CWORD_CWORD_CWORD_CWORD,
2742 /* 152 22 */ CWORD_CWORD_CWORD_CWORD,
2743 /* 153 23 */ CWORD_CWORD_CWORD_CWORD,
2744 /* 154 24 */ CWORD_CWORD_CWORD_CWORD,
2745 /* 155 25 */ CWORD_CWORD_CWORD_CWORD,
2746 /* 156 26 */ CWORD_CWORD_CWORD_CWORD,
2747 /* 157 27 */ CWORD_CWORD_CWORD_CWORD,
2748 /* 158 28 */ CWORD_CWORD_CWORD_CWORD,
2749 /* 159 29 */ CWORD_CWORD_CWORD_CWORD,
2750 /* 160 30 */ CWORD_CWORD_CWORD_CWORD,
2751 /* 161 31 */ CWORD_CWORD_CWORD_CWORD,
2752 /* 162 32 " " */ CSPCL_CWORD_CWORD_CWORD,
2753 /* 163 33 "!" */ CWORD_CCTL_CCTL_CWORD,
2754 /* 164 34 """ */ CDQUOTE_CENDQUOTE_CWORD_CWORD,
2755 /* 165 35 "#" */ CWORD_CWORD_CWORD_CWORD,
2756 /* 166 36 "$" */ CVAR_CVAR_CWORD_CVAR,
2757 /* 167 37 "%" */ CWORD_CWORD_CWORD_CWORD,
2758 /* 168 38 "&" */ CSPCL_CWORD_CWORD_CWORD,
2759 /* 169 39 "'" */ CSQUOTE_CWORD_CENDQUOTE_CWORD,
2760 /* 170 40 "(" */ CSPCL_CWORD_CWORD_CLP,
2761 /* 171 41 ")" */ CSPCL_CWORD_CWORD_CRP,
2762 /* 172 42 "*" */ CWORD_CCTL_CCTL_CWORD,
2763 /* 173 43 "+" */ CWORD_CWORD_CWORD_CWORD,
2764 /* 174 44 "," */ CWORD_CWORD_CWORD_CWORD,
2765 /* 175 45 "-" */ CWORD_CCTL_CCTL_CWORD,
2766 /* 176 46 "." */ CWORD_CWORD_CWORD_CWORD,
2767 /* 177 47 "/" */ CWORD_CCTL_CCTL_CWORD,
2768 /* 178 48 "0" */ CWORD_CWORD_CWORD_CWORD,
2769 /* 179 49 "1" */ CWORD_CWORD_CWORD_CWORD,
2770 /* 180 50 "2" */ CWORD_CWORD_CWORD_CWORD,
2771 /* 181 51 "3" */ CWORD_CWORD_CWORD_CWORD,
2772 /* 182 52 "4" */ CWORD_CWORD_CWORD_CWORD,
2773 /* 183 53 "5" */ CWORD_CWORD_CWORD_CWORD,
2774 /* 184 54 "6" */ CWORD_CWORD_CWORD_CWORD,
2775 /* 185 55 "7" */ CWORD_CWORD_CWORD_CWORD,
2776 /* 186 56 "8" */ CWORD_CWORD_CWORD_CWORD,
2777 /* 187 57 "9" */ CWORD_CWORD_CWORD_CWORD,
2778 /* 188 58 ":" */ CWORD_CCTL_CCTL_CWORD,
2779 /* 189 59 ";" */ CSPCL_CWORD_CWORD_CWORD,
2780 /* 190 60 "<" */ CSPCL_CWORD_CWORD_CWORD,
2781 /* 191 61 "=" */ CWORD_CCTL_CCTL_CWORD,
2782 /* 192 62 ">" */ CSPCL_CWORD_CWORD_CWORD,
2783 /* 193 63 "?" */ CWORD_CCTL_CCTL_CWORD,
2784 /* 194 64 "@" */ CWORD_CWORD_CWORD_CWORD,
2785 /* 195 65 "A" */ CWORD_CWORD_CWORD_CWORD,
2786 /* 196 66 "B" */ CWORD_CWORD_CWORD_CWORD,
2787 /* 197 67 "C" */ CWORD_CWORD_CWORD_CWORD,
2788 /* 198 68 "D" */ CWORD_CWORD_CWORD_CWORD,
2789 /* 199 69 "E" */ CWORD_CWORD_CWORD_CWORD,
2790 /* 200 70 "F" */ CWORD_CWORD_CWORD_CWORD,
2791 /* 201 71 "G" */ CWORD_CWORD_CWORD_CWORD,
2792 /* 202 72 "H" */ CWORD_CWORD_CWORD_CWORD,
2793 /* 203 73 "I" */ CWORD_CWORD_CWORD_CWORD,
2794 /* 204 74 "J" */ CWORD_CWORD_CWORD_CWORD,
2795 /* 205 75 "K" */ CWORD_CWORD_CWORD_CWORD,
2796 /* 206 76 "L" */ CWORD_CWORD_CWORD_CWORD,
2797 /* 207 77 "M" */ CWORD_CWORD_CWORD_CWORD,
2798 /* 208 78 "N" */ CWORD_CWORD_CWORD_CWORD,
2799 /* 209 79 "O" */ CWORD_CWORD_CWORD_CWORD,
2800 /* 210 80 "P" */ CWORD_CWORD_CWORD_CWORD,
2801 /* 211 81 "Q" */ CWORD_CWORD_CWORD_CWORD,
2802 /* 212 82 "R" */ CWORD_CWORD_CWORD_CWORD,
2803 /* 213 83 "S" */ CWORD_CWORD_CWORD_CWORD,
2804 /* 214 84 "T" */ CWORD_CWORD_CWORD_CWORD,
2805 /* 215 85 "U" */ CWORD_CWORD_CWORD_CWORD,
2806 /* 216 86 "V" */ CWORD_CWORD_CWORD_CWORD,
2807 /* 217 87 "W" */ CWORD_CWORD_CWORD_CWORD,
2808 /* 218 88 "X" */ CWORD_CWORD_CWORD_CWORD,
2809 /* 219 89 "Y" */ CWORD_CWORD_CWORD_CWORD,
2810 /* 220 90 "Z" */ CWORD_CWORD_CWORD_CWORD,
2811 /* 221 91 "[" */ CWORD_CCTL_CCTL_CWORD,
2812 /* 222 92 "\" */ CBACK_CBACK_CCTL_CBACK,
2813 /* 223 93 "]" */ CWORD_CCTL_CCTL_CWORD,
2814 /* 224 94 "^" */ CWORD_CWORD_CWORD_CWORD,
2815 /* 225 95 "_" */ CWORD_CWORD_CWORD_CWORD,
2816 /* 226 96 "`" */ CBQUOTE_CBQUOTE_CWORD_CBQUOTE,
2817 /* 227 97 "a" */ CWORD_CWORD_CWORD_CWORD,
2818 /* 228 98 "b" */ CWORD_CWORD_CWORD_CWORD,
2819 /* 229 99 "c" */ CWORD_CWORD_CWORD_CWORD,
2820 /* 230 100 "d" */ CWORD_CWORD_CWORD_CWORD,
2821 /* 231 101 "e" */ CWORD_CWORD_CWORD_CWORD,
2822 /* 232 102 "f" */ CWORD_CWORD_CWORD_CWORD,
2823 /* 233 103 "g" */ CWORD_CWORD_CWORD_CWORD,
2824 /* 234 104 "h" */ CWORD_CWORD_CWORD_CWORD,
2825 /* 235 105 "i" */ CWORD_CWORD_CWORD_CWORD,
2826 /* 236 106 "j" */ CWORD_CWORD_CWORD_CWORD,
2827 /* 237 107 "k" */ CWORD_CWORD_CWORD_CWORD,
2828 /* 238 108 "l" */ CWORD_CWORD_CWORD_CWORD,
2829 /* 239 109 "m" */ CWORD_CWORD_CWORD_CWORD,
2830 /* 240 110 "n" */ CWORD_CWORD_CWORD_CWORD,
2831 /* 241 111 "o" */ CWORD_CWORD_CWORD_CWORD,
2832 /* 242 112 "p" */ CWORD_CWORD_CWORD_CWORD,
2833 /* 243 113 "q" */ CWORD_CWORD_CWORD_CWORD,
2834 /* 244 114 "r" */ CWORD_CWORD_CWORD_CWORD,
2835 /* 245 115 "s" */ CWORD_CWORD_CWORD_CWORD,
2836 /* 246 116 "t" */ CWORD_CWORD_CWORD_CWORD,
2837 /* 247 117 "u" */ CWORD_CWORD_CWORD_CWORD,
2838 /* 248 118 "v" */ CWORD_CWORD_CWORD_CWORD,
2839 /* 249 119 "w" */ CWORD_CWORD_CWORD_CWORD,
2840 /* 250 120 "x" */ CWORD_CWORD_CWORD_CWORD,
2841 /* 251 121 "y" */ CWORD_CWORD_CWORD_CWORD,
2842 /* 252 122 "z" */ CWORD_CWORD_CWORD_CWORD,
2843 /* 253 123 "{" */ CWORD_CWORD_CWORD_CWORD,
2844 /* 254 124 "|" */ CSPCL_CWORD_CWORD_CWORD,
2845 /* 255 125 "}" */ CENDVAR_CENDVAR_CWORD_CENDVAR,
2846 /* 256 126 "~" */ CWORD_CCTL_CCTL_CWORD,
2847 /* 257 127 */ CWORD_CWORD_CWORD_CWORD,
2850 #endif /* USE_SIT_FUNCTION */
2855 #if ENABLE_ASH_MATH_SUPPORT_64
2856 typedef int64_t arith_t;
2857 #define arith_t_type long long
2859 typedef long arith_t;
2860 #define arith_t_type long
2863 #if ENABLE_ASH_MATH_SUPPORT
2864 static arith_t dash_arith(const char *);
2865 static arith_t arith(const char *expr, int *perrcode);
2868 #if ENABLE_ASH_RANDOM_SUPPORT
2869 static unsigned long rseed;
2870 # ifndef DYNAMIC_VAR
2871 # define DYNAMIC_VAR
2878 static void readcmdfile(char *);
2883 static char *minusc; /* argument to -c option */
2885 static void optschanged(void);
2886 static void setparam(char **);
2887 static void freeparam(volatile struct shparam *);
2888 static int shiftcmd(int, char **);
2889 static int setcmd(int, char **);
2890 static int nextopt(const char *);
2895 /* flags passed to redirect */
2896 #define REDIR_PUSH 01 /* save previous values of file descriptors */
2897 #define REDIR_SAVEFD2 03 /* set preverrout */
2899 static void redirect(union node *, int);
2900 static void popredir(int);
2901 static void clearredir(int);
2902 static int copyfd(int, int);
2903 static int redirectsafe(union node *, int);
2906 /* ============ Alias handling */
2908 #if ENABLE_ASH_ALIAS
2910 #define ALIASINUSE 1
2922 static struct alias *atab[ATABSIZE];
2924 static struct alias **
2925 __lookupalias(const char *name) {
2926 unsigned int hashval;
2933 ch = (unsigned char)*p;
2937 ch = (unsigned char)*++p;
2939 app = &atab[hashval % ATABSIZE];
2941 for (; *app; app = &(*app)->next) {
2942 if (strcmp(name, (*app)->name) == 0) {
2950 static struct alias *
2951 lookupalias(const char *name, int check)
2953 struct alias *ap = *__lookupalias(name);
2955 if (check && ap && (ap->flag & ALIASINUSE))
2960 static struct alias *
2961 freealias(struct alias *ap)
2965 if (ap->flag & ALIASINUSE) {
2966 ap->flag |= ALIASDEAD;
2978 setalias(const char *name, const char *val)
2980 struct alias *ap, **app;
2982 app = __lookupalias(name);
2986 if (!(ap->flag & ALIASINUSE)) {
2989 ap->val = ckstrdup(val);
2990 ap->flag &= ~ALIASDEAD;
2993 ap = ckmalloc(sizeof(struct alias));
2994 ap->name = ckstrdup(name);
2995 ap->val = ckstrdup(val);
3004 unalias(const char *name)
3008 app = __lookupalias(name);
3012 *app = freealias(*app);
3023 struct alias *ap, **app;
3027 for (i = 0; i < ATABSIZE; i++) {
3029 for (ap = *app; ap; ap = *app) {
3030 *app = freealias(*app);
3040 printalias(const struct alias *ap)
3042 out1fmt("%s=%s\n", ap->name, single_quote(ap->val));
3046 * TODO - sort output
3049 aliascmd(int argc, char **argv)
3058 for (i = 0; i < ATABSIZE; i++)
3059 for (ap = atab[i]; ap; ap = ap->next) {
3064 while ((n = *++argv) != NULL) {
3065 v = strchr(n+1, '=');
3066 if (v == NULL) { /* n+1: funny ksh stuff */
3067 ap = *__lookupalias(n);
3069 fprintf(stderr, "%s: %s not found\n", "alias", n);
3083 unaliascmd(int argc, char **argv)
3087 while ((i = nextopt("a")) != '\0') {
3093 for (i = 0; *argptr; argptr++) {
3094 if (unalias(*argptr)) {
3095 fprintf(stderr, "%s: %s not found\n", "unalias", *argptr);
3103 #endif /* ASH_ALIAS */
3106 /* ============ jobs.c */
3108 /* Mode argument to forkshell. Don't change FORK_FG or FORK_BG. */
3111 #define FORK_NOJOB 2
3113 /* mode flags for showjob(s) */
3114 #define SHOW_PGID 0x01 /* only show pgid - for jobs -p */
3115 #define SHOW_PID 0x04 /* include process pid */
3116 #define SHOW_CHANGED 0x08 /* only jobs whose state has changed */
3120 * A job structure contains information about a job. A job is either a
3121 * single process or a set of processes contained in a pipeline. In the
3122 * latter case, pidlist will be non-NULL, and will point to a -1 terminated
3127 pid_t pid; /* process id */
3128 int status; /* last process status from wait() */
3129 char *cmd; /* text of command being run */
3133 struct procstat ps0; /* status of process */
3134 struct procstat *ps; /* status or processes when more than one */
3136 int stopstatus; /* status of a stopped job */
3139 nprocs: 16, /* number of processes */
3141 #define JOBRUNNING 0 /* at least one proc running */
3142 #define JOBSTOPPED 1 /* all procs are stopped */
3143 #define JOBDONE 2 /* all procs are completed */
3145 sigint: 1, /* job was killed by SIGINT */
3146 jobctl: 1, /* job running under job control */
3148 waited: 1, /* true if this entry has been waited for */
3149 used: 1, /* true if this entry is in used */
3150 changed: 1; /* true if status has changed */
3151 struct job *prev_job; /* previous job */
3154 static pid_t backgndpid; /* pid of last background process */
3155 static int job_warning; /* user was warned about stopped jobs */
3157 static int jobctl; /* true if doing job control */
3160 static struct job *makejob(union node *, int);
3161 static int forkshell(struct job *, union node *, int);
3162 static int waitforjob(struct job *);
3165 #define setjobctl(on) /* do nothing */
3167 static void setjobctl(int);
3168 static void showjobs(FILE *, int);
3172 * Set the signal handler for the specified signal. The routine figures
3173 * out what it should be set to.
3176 setsignal(int signo)
3180 struct sigaction act;
3185 else if (*t != '\0')
3189 if (rootshell && action == S_DFL) {
3192 if (iflag || minusc || sflag == 0)
3215 t = &sigmode[signo - 1];
3219 * current setting unknown
3221 if (sigaction(signo, 0, &act) == -1) {
3223 * Pretend it worked; maybe we should give a warning
3224 * here, but other shells don't. We don't alter
3225 * sigmode, so that we retry every time.
3229 if (act.sa_handler == SIG_IGN) {
3231 && (signo == SIGTSTP || signo == SIGTTIN || signo == SIGTTOU)
3233 tsig = S_IGN; /* don't hard ignore these */
3237 tsig = S_RESET; /* force to be set */
3240 if (tsig == S_HARD_IGN || tsig == action)
3244 act.sa_handler = onsig;
3247 act.sa_handler = SIG_IGN;
3250 act.sa_handler = SIG_DFL;
3254 sigfillset(&act.sa_mask);
3255 sigaction(signo, &act, 0);
3258 /* mode flags for set_curjob */
3259 #define CUR_DELETE 2
3260 #define CUR_RUNNING 1
3261 #define CUR_STOPPED 0
3263 /* mode flags for dowait */
3264 #define DOWAIT_NORMAL 0
3265 #define DOWAIT_BLOCK 1
3268 /* pgrp of shell on invocation */
3269 static int initialpgrp;
3270 static int ttyfd = -1;
3273 static struct job *jobtab;
3275 static unsigned njobs;
3277 static struct job *curjob;
3278 /* number of presumed living untracked jobs */
3282 set_curjob(struct job *jp, unsigned mode)
3285 struct job **jpp, **curp;
3287 /* first remove from list */
3288 jpp = curp = &curjob;
3293 jpp = &jp1->prev_job;
3295 *jpp = jp1->prev_job;
3297 /* Then re-insert in correct position */
3305 /* job being deleted */
3308 /* newly created job or backgrounded job,
3309 put after all stopped jobs. */
3313 if (!jp1 || jp1->state != JOBSTOPPED)
3316 jpp = &jp1->prev_job;
3322 /* newly stopped job - becomes curjob */
3323 jp->prev_job = *jpp;
3331 jobno(const struct job *jp)
3333 return jp - jobtab + 1;
3338 * Convert a job name to a job structure.
3341 getjob(const char *name, int getctl)
3345 const char *err_msg = "No such job: %s";
3349 char *(*match)(const char *, const char *);
3364 if (c == '+' || c == '%') {
3366 err_msg = "No current job";
3372 err_msg = "No previous job";
3383 jp = jobtab + num - 1;
3400 if (match(jp->ps[0].cmd, p)) {
3404 err_msg = "%s: ambiguous";
3411 err_msg = "job %s not created under job control";
3412 if (getctl && jp->jobctl == 0)
3417 ash_msg_and_raise_error(err_msg, name);
3421 * Mark a job structure as unused.
3424 freejob(struct job *jp)
3426 struct procstat *ps;
3430 for (i = jp->nprocs, ps = jp->ps; --i >= 0; ps++) {
3431 if (ps->cmd != nullstr)
3434 if (jp->ps != &jp->ps0)
3437 set_curjob(jp, CUR_DELETE);
3443 xtcsetpgrp(int fd, pid_t pgrp)
3445 if (tcsetpgrp(fd, pgrp))
3446 ash_msg_and_raise_error("Cannot set tty process group (%m)");
3450 * Turn job control on and off.
3452 * Note: This code assumes that the third arg to ioctl is a character
3453 * pointer, which is true on Berkeley systems but not System V. Since
3454 * System V doesn't have job control yet, this isn't a problem now.
3456 * Called with interrupts off.
3464 if (on == jobctl || rootshell == 0)
3468 ofd = fd = open(_PATH_TTY, O_RDWR);
3470 /* BTW, bash will try to open(ttyname(0)) if open("/dev/tty") fails.
3471 * That sometimes helps to acquire controlling tty.
3472 * Obviously, a workaround for bugs when someone
3473 * failed to provide a controlling tty to bash! :) */
3475 while (!isatty(fd) && --fd >= 0)
3478 fd = fcntl(fd, F_DUPFD, 10);
3482 fcntl(fd, F_SETFD, FD_CLOEXEC);
3483 do { /* while we are in the background */
3484 pgrp = tcgetpgrp(fd);
3487 ash_msg("can't access tty; job control turned off");
3491 if (pgrp == getpgrp())
3502 xtcsetpgrp(fd, pgrp);
3504 /* turning job control off */
3507 xtcsetpgrp(fd, pgrp);
3521 killcmd(int argc, char **argv)
3531 ash_msg_and_raise_error(
3532 "Usage: kill [-s sigspec | -signum | -sigspec] [pid | job]... or\n"
3533 "kill -l [exitstatus]"
3537 if (**++argv == '-') {
3538 signo = get_signum(*argv + 1);
3542 while ((c = nextopt("ls:")) != '\0') {
3552 signo = get_signum(optionarg);
3554 ash_msg_and_raise_error(
3555 "invalid signal number or name: %s",
3567 if (!list && signo < 0)
3570 if ((signo < 0 || !*argv) ^ list) {
3578 for (i = 1; i < NSIG; i++) {
3579 name = get_signame(i);
3581 out1fmt(snlfmt, name);
3585 name = get_signame(signo);
3586 if (!isdigit(*name))
3587 ash_msg_and_raise_error("invalid signal number or exit status: %s", *argptr);
3588 out1fmt(snlfmt, name);
3594 if (**argv == '%') {
3595 jp = getjob(*argv, 0);
3596 pid = -jp->ps[0].pid;
3598 pid = **argv == '-' ?
3599 -number(*argv + 1) : number(*argv);
3601 if (kill(pid, signo) != 0) {
3602 ash_msg("(%d) - %m", pid);
3611 showpipe(struct job *jp, FILE *out)
3613 struct procstat *sp;
3614 struct procstat *spend;
3616 spend = jp->ps + jp->nprocs;
3617 for (sp = jp->ps + 1; sp < spend; sp++)
3618 fprintf(out, " | %s", sp->cmd);
3619 outcslow('\n', out);
3620 flush_stdout_stderr();
3625 restartjob(struct job *jp, int mode)
3627 struct procstat *ps;
3633 if (jp->state == JOBDONE)
3635 jp->state = JOBRUNNING;
3637 if (mode == FORK_FG)
3638 xtcsetpgrp(ttyfd, pgid);
3639 killpg(pgid, SIGCONT);
3643 if (WIFSTOPPED(ps->status)) {
3646 } while (ps++, --i);
3648 status = (mode == FORK_FG) ? waitforjob(jp) : 0;
3654 fg_bgcmd(int argc, char **argv)
3661 mode = (**argv == 'f') ? FORK_FG : FORK_BG;
3666 jp = getjob(*argv, 1);
3667 if (mode == FORK_BG) {
3668 set_curjob(jp, CUR_RUNNING);
3669 fprintf(out, "[%d] ", jobno(jp));
3671 outstr(jp->ps->cmd, out);
3673 retval = restartjob(jp, mode);
3674 } while (*argv && *++argv);
3680 sprint_status(char *s, int status, int sigonly)
3686 if (!WIFEXITED(status)) {
3688 if (WIFSTOPPED(status))
3689 st = WSTOPSIG(status);
3692 st = WTERMSIG(status);
3694 if (st == SIGINT || st == SIGPIPE)
3697 if (WIFSTOPPED(status))
3702 col = fmtstr(s, 32, strsignal(st));
3703 if (WCOREDUMP(status)) {
3704 col += fmtstr(s + col, 16, " (core dumped)");
3706 } else if (!sigonly) {
3707 st = WEXITSTATUS(status);
3709 col = fmtstr(s, 16, "Done(%d)", st);
3711 col = fmtstr(s, 16, "Done");
3718 * Do a wait system call. If job control is compiled in, we accept
3719 * stopped processes. If block is zero, we return a value of zero
3720 * rather than blocking.
3722 * System V doesn't have a non-blocking wait system call. It does
3723 * have a SIGCLD signal that is sent to a process when one of it's
3724 * children dies. The obvious way to use SIGCLD would be to install
3725 * a handler for SIGCLD which simply bumped a counter when a SIGCLD
3726 * was received, and have waitproc bump another counter when it got
3727 * the status of a process. Waitproc would then know that a wait
3728 * system call would not block if the two counters were different.
3729 * This approach doesn't work because if a process has children that
3730 * have not been waited for, System V will send it a SIGCLD when it
3731 * installs a signal handler for SIGCLD. What this means is that when
3732 * a child exits, the shell will be sent SIGCLD signals continuously
3733 * until is runs out of stack space, unless it does a wait call before
3734 * restoring the signal handler. The code below takes advantage of
3735 * this (mis)feature by installing a signal handler for SIGCLD and
3736 * then checking to see whether it was called. If there are any
3737 * children to be waited for, it will be.
3739 * If neither SYSV nor BSD is defined, we don't implement nonblocking
3740 * waits at all. In this case, the user will not be informed when
3741 * a background process until the next time she runs a real program
3742 * (as opposed to running a builtin command or just typing return),
3743 * and the jobs command may give out of date information.
3746 waitproc(int block, int *status)
3756 return wait3(status, flags, (struct rusage *)NULL);
3760 * Wait for a process to terminate.
3763 dowait(int block, struct job *job)
3768 struct job *thisjob;
3771 TRACE(("dowait(%d) called\n", block));
3772 pid = waitproc(block, &status);
3773 TRACE(("wait returns pid %d, status=%d\n", pid, status));
3778 for (jp = curjob; jp; jp = jp->prev_job) {
3779 struct procstat *sp;
3780 struct procstat *spend;
3781 if (jp->state == JOBDONE)
3784 spend = jp->ps + jp->nprocs;
3787 if (sp->pid == pid) {
3788 TRACE(("Job %d: changing status of proc %d "
3789 "from 0x%x to 0x%x\n",
3790 jobno(jp), pid, sp->status, status));
3791 sp->status = status;
3794 if (sp->status == -1)
3797 if (state == JOBRUNNING)
3799 if (WIFSTOPPED(sp->status)) {
3800 jp->stopstatus = sp->status;
3804 } while (++sp < spend);
3809 if (!WIFSTOPPED(status))
3816 if (state != JOBRUNNING) {
3817 thisjob->changed = 1;
3819 if (thisjob->state != state) {
3820 TRACE(("Job %d: changing state from %d to %d\n",
3821 jobno(thisjob), thisjob->state, state));
3822 thisjob->state = state;
3824 if (state == JOBSTOPPED) {
3825 set_curjob(thisjob, CUR_STOPPED);
3834 if (thisjob && thisjob == job) {
3838 len = sprint_status(s, status, 1);
3850 showjob(FILE *out, struct job *jp, int mode)
3852 struct procstat *ps;
3853 struct procstat *psend;
3860 if (mode & SHOW_PGID) {
3861 /* just output process (group) id of pipeline */
3862 fprintf(out, "%d\n", ps->pid);
3866 col = fmtstr(s, 16, "[%d] ", jobno(jp));
3871 else if (curjob && jp == curjob->prev_job)
3874 if (mode & SHOW_PID)
3875 col += fmtstr(s + col, 16, "%d ", ps->pid);
3877 psend = ps + jp->nprocs;
3879 if (jp->state == JOBRUNNING) {
3880 strcpy(s + col, "Running");
3881 col += sizeof("Running") - 1;
3883 int status = psend[-1].status;
3884 if (jp->state == JOBSTOPPED)
3885 status = jp->stopstatus;
3886 col += sprint_status(s + col, status, 0);
3892 /* for each process */
3893 col = fmtstr(s, 48, " |\n%*c%d ", indent, ' ', ps->pid) - 3;
3895 fprintf(out, "%s%*c%s",
3896 s, 33 - col >= 0 ? 33 - col : 0, ' ', ps->cmd
3898 if (!(mode & SHOW_PID)) {
3902 if (++ps == psend) {
3903 outcslow('\n', out);
3910 if (jp->state == JOBDONE) {
3911 TRACE(("showjob: freeing job %d\n", jobno(jp)));
3917 jobscmd(int argc, char **argv)
3923 while ((m = nextopt("lp"))) {
3934 showjob(out, getjob(*argv,0), mode);
3937 showjobs(out, mode);
3943 * Print a list of jobs. If "change" is nonzero, only print jobs whose
3944 * statuses have changed since the last call to showjobs.
3947 showjobs(FILE *out, int mode)
3951 TRACE(("showjobs(%x) called\n", mode));
3953 /* If not even one one job changed, there is nothing to do */
3954 while (dowait(DOWAIT_NORMAL, NULL) > 0)
3957 for (jp = curjob; jp; jp = jp->prev_job) {
3958 if (!(mode & SHOW_CHANGED) || jp->changed)
3959 showjob(out, jp, mode);
3965 getstatus(struct job *job)
3970 status = job->ps[job->nprocs - 1].status;
3971 retval = WEXITSTATUS(status);
3972 if (!WIFEXITED(status)) {
3974 retval = WSTOPSIG(status);
3975 if (!WIFSTOPPED(status))
3978 /* XXX: limits number of signals */
3979 retval = WTERMSIG(status);
3981 if (retval == SIGINT)
3987 TRACE(("getstatus: job %d, nproc %d, status %x, retval %x\n",
3988 jobno(job), job->nprocs, status, retval));
3993 waitcmd(int argc, char **argv)
4006 /* wait for all jobs */
4011 /* no running procs */
4014 if (jp->state == JOBRUNNING)
4019 dowait(DOWAIT_BLOCK, 0);
4025 if (**argv != '%') {
4026 pid_t pid = number(*argv);
4030 if (job->ps[job->nprocs - 1].pid == pid)
4032 job = job->prev_job;
4038 job = getjob(*argv, 0);
4039 /* loop until process terminated or stopped */
4040 while (job->state == JOBRUNNING)
4041 dowait(DOWAIT_BLOCK, 0);
4043 retval = getstatus(job);
4057 struct job *jp, *jq;
4059 len = njobs * sizeof(*jp);
4061 jp = ckrealloc(jq, len + 4 * sizeof(*jp));
4063 offset = (char *)jp - (char *)jq;
4065 /* Relocate pointers */
4068 jq = (struct job *)((char *)jq + l);
4072 #define joff(p) ((struct job *)((char *)(p) + l))
4073 #define jmove(p) (p) = (void *)((char *)(p) + offset)
4074 if (joff(jp)->ps == &jq->ps0)
4075 jmove(joff(jp)->ps);
4076 if (joff(jp)->prev_job)
4077 jmove(joff(jp)->prev_job);
4087 jp = (struct job *)((char *)jp + len);
4091 } while (--jq >= jp);
4096 * Return a new job structure.
4097 * Called with interrupts off.
4100 makejob(union node *node, int nprocs)
4105 for (i = njobs, jp = jobtab; ; jp++) {
4112 if (jp->state != JOBDONE || !jp->waited)
4121 memset(jp, 0, sizeof(*jp));
4126 jp->prev_job = curjob;
4131 jp->ps = ckmalloc(nprocs * sizeof(struct procstat));
4133 TRACE(("makejob(0x%lx, %d) returns %%%d\n", (long)node, nprocs,
4140 * Return a string identifying a command (to be printed by the
4143 static char *cmdnextc;
4146 cmdputs(const char *s)
4148 const char *p, *str;
4149 char c, cc[2] = " ";
4153 static const char vstype[VSTYPE + 1][4] = {
4154 "", "}", "-", "+", "?", "=",
4155 "%", "%%", "#", "##"
4158 nextc = makestrspace((strlen(s) + 1) * 8, cmdnextc);
4160 while ((c = *p++) != 0) {
4168 if ((subtype & VSTYPE) == VSLENGTH)
4172 if (!(subtype & VSQUOTE) == !(quoted & 1))
4178 str = "\"}" + !(quoted & 1);
4185 case CTLBACKQ+CTLQUOTE:
4188 #if ENABLE_ASH_MATH_SUPPORT
4203 if ((subtype & VSTYPE) != VSNORMAL)
4205 str = vstype[subtype & VSTYPE];
4206 if (subtype & VSNUL)
4215 /* These can only happen inside quotes */
4228 while ((c = *str++)) {
4233 USTPUTC('"', nextc);
4239 /* cmdtxt() and cmdlist() call each other */
4240 static void cmdtxt(union node *n);
4243 cmdlist(union node *np, int sep)
4245 for (; np; np = np->narg.next) {
4249 if (sep && np->narg.next)
4255 cmdtxt(union node *n)
4258 struct nodelist *lp;
4270 lp = n->npipe.cmdlist;
4288 cmdtxt(n->nbinary.ch1);
4304 cmdtxt(n->nif.test);
4307 if (n->nif.elsepart) {
4310 n = n->nif.elsepart;
4326 cmdtxt(n->nbinary.ch1);
4336 cmdputs(n->nfor.var);
4338 cmdlist(n->nfor.args, 1);
4343 cmdputs(n->narg.text);
4347 cmdlist(n->ncmd.args, 1);
4348 cmdlist(n->ncmd.redirect, 0);
4361 cmdputs(n->ncase.expr->narg.text);
4363 for (np = n->ncase.cases; np; np = np->nclist.next) {
4364 cmdtxt(np->nclist.pattern);
4366 cmdtxt(np->nclist.body);
4392 s[0] = n->nfile.fd + '0';
4396 if (n->type == NTOFD || n->type == NFROMFD) {
4397 s[0] = n->ndup.dupfd + '0';
4407 commandtext(union node *n)
4411 STARTSTACKSTR(cmdnextc);
4413 name = stackblock();
4414 TRACE(("commandtext: name %p, end %p\n\t\"%s\"\n",
4415 name, cmdnextc, cmdnextc));
4416 return ckstrdup(name);
4421 * Fork off a subshell. If we are doing job control, give the subshell its
4422 * own process group. Jp is a job structure that the job is to be added to.
4423 * N is the command that will be evaluated by the child. Both jp and n may
4424 * be NULL. The mode parameter can be one of the following:
4425 * FORK_FG - Fork off a foreground process.
4426 * FORK_BG - Fork off a background process.
4427 * FORK_NOJOB - Like FORK_FG, but don't give the process its own
4428 * process group even if job control is on.
4430 * When job control is turned off, background processes have their standard
4431 * input redirected to /dev/null (except for the second and later processes
4434 * Called with interrupts off.
4437 * Clear traps on a fork.
4444 for (tp = trap; tp < &trap[NSIG]; tp++) {
4445 if (*tp && **tp) { /* trap not NULL or SIG_IGN */
4450 setsignal(tp - trap);
4455 /* lives far away from here, needed for forkchild */
4456 static void closescript(void);
4458 forkchild(struct job *jp, union node *n, int mode)
4462 TRACE(("Child shell %d\n", getpid()));
4469 /* do job control only in root shell */
4471 if (mode != FORK_NOJOB && jp->jobctl && !oldlvl) {
4474 if (jp->nprocs == 0)
4477 pgrp = jp->ps[0].pid;
4478 /* This can fail because we are doing it in the parent also */
4479 (void)setpgid(0, pgrp);
4480 if (mode == FORK_FG)
4481 xtcsetpgrp(ttyfd, pgrp);
4486 if (mode == FORK_BG) {
4489 if (jp->nprocs == 0) {
4491 if (open(bb_dev_null, O_RDONLY) != 0)
4492 ash_msg_and_raise_error("Can't open %s", bb_dev_null);
4495 if (!oldlvl && iflag) {
4500 for (jp = curjob; jp; jp = jp->prev_job)
4506 forkparent(struct job *jp, union node *n, int mode, pid_t pid)
4508 TRACE(("In parent shell: child = %d\n", pid));
4510 while (jobless && dowait(DOWAIT_NORMAL, 0) > 0);
4515 if (mode != FORK_NOJOB && jp->jobctl) {
4518 if (jp->nprocs == 0)
4521 pgrp = jp->ps[0].pid;
4522 /* This can fail because we are doing it in the child also */
4526 if (mode == FORK_BG) {
4527 backgndpid = pid; /* set $! */
4528 set_curjob(jp, CUR_RUNNING);
4531 struct procstat *ps = &jp->ps[jp->nprocs++];
4537 ps->cmd = commandtext(n);
4543 forkshell(struct job *jp, union node *n, int mode)
4547 TRACE(("forkshell(%%%d, %p, %d) called\n", jobno(jp), n, mode));
4550 TRACE(("Fork failed, errno=%d", errno));
4553 ash_msg_and_raise_error("Cannot fork");
4556 forkchild(jp, n, mode);
4558 forkparent(jp, n, mode, pid);
4563 * Wait for job to finish.
4565 * Under job control we have the problem that while a child process is
4566 * running interrupts generated by the user are sent to the child but not
4567 * to the shell. This means that an infinite loop started by an inter-
4568 * active user may be hard to kill. With job control turned off, an
4569 * interactive user may place an interactive program inside a loop. If
4570 * the interactive program catches interrupts, the user doesn't want
4571 * these interrupts to also abort the loop. The approach we take here
4572 * is to have the shell ignore interrupt signals while waiting for a
4573 * foreground process to terminate, and then send itself an interrupt
4574 * signal if the child process was terminated by an interrupt signal.
4575 * Unfortunately, some programs want to do a bit of cleanup and then
4576 * exit on interrupt; unless these processes terminate themselves by
4577 * sending a signal to themselves (instead of calling exit) they will
4578 * confuse this approach.
4580 * Called with interrupts off.
4583 waitforjob(struct job *jp)
4587 TRACE(("waitforjob(%%%d) called\n", jobno(jp)));
4588 while (jp->state == JOBRUNNING) {
4589 dowait(DOWAIT_BLOCK, jp);
4594 xtcsetpgrp(ttyfd, rootpid);
4596 * This is truly gross.
4597 * If we're doing job control, then we did a TIOCSPGRP which
4598 * caused us (the shell) to no longer be in the controlling
4599 * session -- so we wouldn't have seen any ^C/SIGINT. So, we
4600 * intuit from the subprocess exit status whether a SIGINT
4601 * occurred, and if so interrupt ourselves. Yuck. - mycroft
4606 if (jp->state == JOBDONE)
4613 * return 1 if there are stopped jobs, otherwise 0
4625 if (jp && jp->state == JOBSTOPPED) {
4626 out2str("You have stopped jobs.\n");
4635 /* ============ Routines to expand arguments to commands
4637 * We have to deal with backquotes, shell variables, and file metacharacters.
4643 #define EXP_FULL 0x1 /* perform word splitting & file globbing */
4644 #define EXP_TILDE 0x2 /* do normal tilde expansion */
4645 #define EXP_VARTILDE 0x4 /* expand tildes in an assignment */
4646 #define EXP_REDIR 0x8 /* file glob for a redirection (1 match only) */
4647 #define EXP_CASE 0x10 /* keeps quotes around for CASE pattern */
4648 #define EXP_RECORD 0x20 /* need to record arguments for ifs breakup */
4649 #define EXP_VARTILDE2 0x40 /* expand tildes after colons only */
4650 #define EXP_WORD 0x80 /* expand word in parameter expansion */
4651 #define EXP_QWORD 0x100 /* expand word in quoted parameter expansion */
4655 #define RMESCAPE_ALLOC 0x1 /* Allocate a new string */
4656 #define RMESCAPE_GLOB 0x2 /* Add backslashes for glob */
4657 #define RMESCAPE_QUOTED 0x4 /* Remove CTLESC unless in quotes */
4658 #define RMESCAPE_GROW 0x8 /* Grow strings instead of stalloc */
4659 #define RMESCAPE_HEAP 0x10 /* Malloc strings instead of stalloc */
4662 * Structure specifying which parts of the string should be searched
4663 * for IFS characters.
4666 struct ifsregion *next; /* next region in list */
4667 int begoff; /* offset of start of region */
4668 int endoff; /* offset of end of region */
4669 int nulonly; /* search for nul bytes only */
4673 struct strlist *list;
4674 struct strlist **lastp;
4677 /* output of current string */
4678 static char *expdest;
4679 /* list of back quote expressions */
4680 static struct nodelist *argbackq;
4681 /* first struct in list of ifs regions */
4682 static struct ifsregion ifsfirst;
4683 /* last struct in list */
4684 static struct ifsregion *ifslastp;
4685 /* holds expanded arg list */
4686 static struct arglist exparg;
4696 expdest = makestrspace(32, expdest);
4697 #if ENABLE_ASH_MATH_SUPPORT_64
4698 len = fmtstr(expdest, 32, "%lld", (long long) num);
4700 len = fmtstr(expdest, 32, "%ld", num);
4702 STADJUST(len, expdest);
4707 esclen(const char *start, const char *p)
4711 while (p > start && *--p == CTLESC) {
4718 * Remove any CTLESC characters from a string.
4721 _rmescapes(char *str, int flag)
4724 static const char qchars[] = { CTLESC, CTLQUOTEMARK, 0 };
4729 p = strpbrk(str, qchars);
4735 if (flag & RMESCAPE_ALLOC) {
4736 size_t len = p - str;
4737 size_t fulllen = len + strlen(p) + 1;
4739 if (flag & RMESCAPE_GROW) {
4740 r = makestrspace(fulllen, expdest);
4741 } else if (flag & RMESCAPE_HEAP) {
4742 r = ckmalloc(fulllen);
4744 r = stalloc(fulllen);
4748 q = memcpy(q, str, len) + len;
4751 inquotes = (flag & RMESCAPE_QUOTED) ^ RMESCAPE_QUOTED;
4752 globbing = flag & RMESCAPE_GLOB;
4753 notescaped = globbing;
4755 if (*p == CTLQUOTEMARK) {
4756 inquotes = ~inquotes;
4758 notescaped = globbing;
4762 /* naked back slash */
4768 if (notescaped && inquotes && *p != '/') {
4772 notescaped = globbing;
4777 if (flag & RMESCAPE_GROW) {
4779 STADJUST(q - r + 1, expdest);
4783 #define rmescapes(p) _rmescapes((p), 0)
4785 #define pmatch(a, b) !fnmatch((a), (b), 0)
4788 * Prepare a pattern for a expmeta (internal glob(3)) call.
4790 * Returns an stalloced string.
4793 preglob(const char *pattern, int quoted, int flag)
4795 flag |= RMESCAPE_GLOB;
4797 flag |= RMESCAPE_QUOTED;
4799 return _rmescapes((char *)pattern, flag);
4803 * Put a string on the stack.
4806 memtodest(const char *p, size_t len, int syntax, int quotes)
4810 q = makestrspace(len * 2, q);
4813 int c = SC2INT(*p++);
4816 if (quotes && (SIT(c, syntax) == CCTL || SIT(c, syntax) == CBACK))
4825 strtodest(const char *p, int syntax, int quotes)
4827 memtodest(p, strlen(p), syntax, quotes);
4831 * Record the fact that we have to scan this region of the
4832 * string for IFS characters.
4835 recordregion(int start, int end, int nulonly)
4837 struct ifsregion *ifsp;
4839 if (ifslastp == NULL) {
4843 ifsp = ckmalloc(sizeof(*ifsp));
4845 ifslastp->next = ifsp;
4849 ifslastp->begoff = start;
4850 ifslastp->endoff = end;
4851 ifslastp->nulonly = nulonly;
4855 removerecordregions(int endoff)
4857 if (ifslastp == NULL)
4860 if (ifsfirst.endoff > endoff) {
4861 while (ifsfirst.next != NULL) {
4862 struct ifsregion *ifsp;
4864 ifsp = ifsfirst.next->next;
4865 free(ifsfirst.next);
4866 ifsfirst.next = ifsp;
4869 if (ifsfirst.begoff > endoff)
4872 ifslastp = &ifsfirst;
4873 ifsfirst.endoff = endoff;
4878 ifslastp = &ifsfirst;
4879 while (ifslastp->next && ifslastp->next->begoff < endoff)
4880 ifslastp=ifslastp->next;
4881 while (ifslastp->next != NULL) {
4882 struct ifsregion *ifsp;
4884 ifsp = ifslastp->next->next;
4885 free(ifslastp->next);
4886 ifslastp->next = ifsp;
4889 if (ifslastp->endoff > endoff)
4890 ifslastp->endoff = endoff;
4894 exptilde(char *startp, char *p, int flag)
4900 int quotes = flag & (EXP_FULL | EXP_CASE);
4905 while ((c = *++p) != '\0') {
4912 if (flag & EXP_VARTILDE)
4922 if (*name == '\0') {
4923 home = lookupvar(homestr);
4925 pw = getpwnam(name);
4930 if (!home || !*home)
4933 startloc = expdest - (char *)stackblock();
4934 strtodest(home, SQSYNTAX, quotes);
4935 recordregion(startloc, expdest - (char *)stackblock(), 0);
4943 * Execute a command inside back quotes. If it's a builtin command, we
4944 * want to save its output in a block obtained from malloc. Otherwise
4945 * we fork off a subprocess and get the output of the command via a pipe.
4946 * Should be called with interrupts off.
4948 struct backcmd { /* result of evalbackcmd */
4949 int fd; /* file descriptor to read from */
4950 char *buf; /* buffer */
4951 int nleft; /* number of chars in buffer */
4952 struct job *jp; /* job structure for command */
4955 /* These forward decls are needed to use "eval" code for backticks handling: */
4956 static int back_exitstatus; /* exit status of backquoted command */
4957 #define EV_EXIT 01 /* exit after evaluating tree */
4958 static void evaltree(union node *, int);
4961 evalbackcmd(union node *n, struct backcmd *result)
4973 saveherefd = herefd;
4981 ash_msg_and_raise_error("Pipe call failed");
4983 if (forkshell(jp, n, FORK_NOJOB) == 0) {
4992 evaltree(n, EV_EXIT); /* actually evaltreenr... */
4996 result->fd = pip[0];
4999 herefd = saveherefd;
5001 TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n",
5002 result->fd, result->buf, result->nleft, result->jp));
5006 * Expand stuff in backwards quotes.
5009 expbackq(union node *cmd, int quoted, int quotes)
5017 int syntax = quoted? DQSYNTAX : BASESYNTAX;
5018 struct stackmark smark;
5021 setstackmark(&smark);
5023 startloc = dest - (char *)stackblock();
5025 evalbackcmd(cmd, &in);
5026 popstackmark(&smark);
5033 memtodest(p, i, syntax, quotes);
5037 i = safe_read(in.fd, buf, sizeof(buf));
5038 TRACE(("expbackq: read returns %d\n", i));
5048 back_exitstatus = waitforjob(in.jp);
5052 /* Eat all trailing newlines */
5054 for (; dest > (char *)stackblock() && dest[-1] == '\n';)
5059 recordregion(startloc, dest - (char *)stackblock(), 0);
5060 TRACE(("evalbackq: size=%d: \"%.*s\"\n",
5061 (dest - (char *)stackblock()) - startloc,
5062 (dest - (char *)stackblock()) - startloc,
5063 stackblock() + startloc));
5066 #if ENABLE_ASH_MATH_SUPPORT
5068 * Expand arithmetic expression. Backup to start of expression,
5069 * evaluate, place result in (backed up) result, adjust string position.
5082 * This routine is slightly over-complicated for
5083 * efficiency. Next we scan backwards looking for the
5084 * start of arithmetic.
5086 start = stackblock();
5093 while (*p != CTLARI) {
5097 ash_msg_and_raise_error("missing CTLARI (shouldn't happen)");
5102 esc = esclen(start, p);
5112 removerecordregions(begoff);
5121 len = cvtnum(dash_arith(p + 2));
5124 recordregion(begoff, begoff + len, 0);
5128 /* argstr needs it */
5129 static char *evalvar(char *p, int flag);
5132 * Perform variable and command substitution. If EXP_FULL is set, output CTLESC
5133 * characters to allow for further processing. Otherwise treat
5134 * $@ like $* since no splitting will be performed.
5137 argstr(char *p, int flag)
5139 static const char spclchars[] = {
5147 CTLBACKQ | CTLQUOTE,
5148 #if ENABLE_ASH_MATH_SUPPORT
5153 const char *reject = spclchars;
5155 int quotes = flag & (EXP_FULL | EXP_CASE); /* do CTLESC */
5156 int breakall = flag & EXP_WORD;
5161 if (!(flag & EXP_VARTILDE)) {
5163 } else if (flag & EXP_VARTILDE2) {
5168 if (flag & EXP_TILDE) {
5174 if (*q == CTLESC && (flag & EXP_QWORD))
5177 p = exptilde(p, q, flag);
5180 startloc = expdest - (char *)stackblock();
5182 length += strcspn(p + length, reject);
5184 if (c && (!(c & 0x80)
5185 #if ENABLE_ASH_MATH_SUPPORT
5189 /* c == '=' || c == ':' || c == CTLENDARI */
5194 expdest = stack_nputstr(p, length, expdest);
5195 newloc = expdest - (char *)stackblock();
5196 if (breakall && !inquotes && newloc > startloc) {
5197 recordregion(startloc, newloc, 0);
5208 if (flag & EXP_VARTILDE2) {
5212 flag |= EXP_VARTILDE2;
5217 * sort of a hack - expand tildes in variable
5218 * assignments (after the first '=' and after ':'s).
5227 case CTLENDVAR: /* ??? */
5230 /* "$@" syntax adherence hack */
5233 !memcmp(p, dolatstr, 4) &&
5234 (p[4] == CTLQUOTEMARK || (
5235 p[4] == CTLENDVAR &&
5236 p[5] == CTLQUOTEMARK
5239 p = evalvar(p + 1, flag) + 1;
5242 inquotes = !inquotes;
5255 p = evalvar(p, flag);
5259 case CTLBACKQ|CTLQUOTE:
5260 expbackq(argbackq->n, c, quotes);
5261 argbackq = argbackq->next;
5263 #if ENABLE_ASH_MATH_SUPPORT
5276 scanleft(char *startp, char *rmesc, char *rmescend, char *str, int quotes,
5287 const char *s = loc2;
5293 match = pmatch(str, s);
5297 if (quotes && *loc == CTLESC)
5306 scanright(char *startp, char *rmesc, char *rmescend, char *str, int quotes,
5313 for (loc = str - 1, loc2 = rmescend; loc >= startp; loc2--) {
5316 const char *s = loc2;
5321 match = pmatch(str, s);
5328 esc = esclen(startp, loc);
5339 static void varunset(const char *, const char *, const char *, int) ATTRIBUTE_NORETURN;
5341 varunset(const char *end, const char *var, const char *umsg, int varflags)
5347 msg = "parameter not set";
5349 if (*end == CTLENDVAR) {
5350 if (varflags & VSNUL)
5355 ash_msg_and_raise_error("%.*s: %s%s", end - var - 1, var, msg, tail);
5359 subevalvar(char *p, char *str, int strloc, int subtype, int startloc, int varflags, int quotes)
5363 int saveherefd = herefd;
5364 struct nodelist *saveargbackq = argbackq;
5366 char *rmesc, *rmescend;
5368 char *(*scan)(char *, char *, char *, char *, int , int);
5371 argstr(p, subtype != VSASSIGN && subtype != VSQUESTION ? EXP_CASE : 0);
5372 STPUTC('\0', expdest);
5373 herefd = saveherefd;
5374 argbackq = saveargbackq;
5375 startp = stackblock() + startloc;
5379 setvar(str, startp, 0);
5380 amount = startp - expdest;
5381 STADJUST(amount, expdest);
5385 varunset(p, str, startp, varflags);
5389 subtype -= VSTRIMRIGHT;
5391 if (subtype < 0 || subtype > 3)
5396 rmescend = stackblock() + strloc;
5398 rmesc = _rmescapes(startp, RMESCAPE_ALLOC | RMESCAPE_GROW);
5399 if (rmesc != startp) {
5401 startp = stackblock() + startloc;
5405 str = stackblock() + strloc;
5406 preglob(str, varflags & VSQUOTE, 0);
5408 /* zero = subtype == VSTRIMLEFT || subtype == VSTRIMLEFTMAX */
5409 zero = subtype >> 1;
5410 /* VSTRIMLEFT/VSTRIMRIGHTMAX -> scanleft */
5411 scan = (subtype & 1) ^ zero ? scanleft : scanright;
5413 loc = scan(startp, rmesc, rmescend, str, quotes, zero);
5416 memmove(startp, loc, str - loc);
5417 loc = startp + (str - loc) - 1;
5420 amount = loc - expdest;
5421 STADJUST(amount, expdest);
5427 * Add the value of a specialized variable to the stack string.
5430 varvalue(char *name, int varflags, int flags)
5440 int quoted = varflags & VSQUOTE;
5441 int subtype = varflags & VSTYPE;
5442 int quotes = flags & (EXP_FULL | EXP_CASE);
5444 if (quoted && (flags & EXP_FULL))
5445 sep = 1 << CHAR_BIT;
5447 syntax = quoted ? DQSYNTAX : BASESYNTAX;
5456 num = shellparam.nparam;
5466 p = makestrspace(NOPTS, expdest);
5467 for (i = NOPTS - 1; i >= 0; i--) {
5469 USTPUTC(optletters(i), p);
5480 sep = ifsset() ? SC2INT(ifsval()[0]) : ' ';
5481 if (quotes && (SIT(sep, syntax) == CCTL || SIT(sep, syntax) == CBACK))
5487 while ((p = *ap++)) {
5490 partlen = strlen(p);
5493 if (!(subtype == VSPLUS || subtype == VSLENGTH))
5494 memtodest(p, partlen, syntax, quotes);
5500 if (subtype == VSPLUS || subtype == VSLENGTH) {
5522 if (num < 0 || num > shellparam.nparam)
5524 p = num ? shellparam.p[num - 1] : arg0;
5527 p = lookupvar(name);
5533 if (!(subtype == VSPLUS || subtype == VSLENGTH))
5534 memtodest(p, len, syntax, quotes);
5538 if (subtype == VSPLUS || subtype == VSLENGTH)
5539 STADJUST(-len, expdest);
5544 * Expand a variable, and return a pointer to the next character in the
5548 evalvar(char *p, int flag)
5561 quotes = flag & (EXP_FULL | EXP_CASE);
5563 subtype = varflags & VSTYPE;
5564 quoted = varflags & VSQUOTE;
5566 easy = (!quoted || (*var == '@' && shellparam.nparam));
5567 startloc = expdest - (char *)stackblock();
5568 p = strchr(p, '=') + 1;
5571 varlen = varvalue(var, varflags, flag);
5572 if (varflags & VSNUL)
5575 if (subtype == VSPLUS) {
5576 varlen = -1 - varlen;
5580 if (subtype == VSMINUS) {
5584 p, flag | EXP_TILDE |
5585 (quoted ? EXP_QWORD : EXP_WORD)
5594 if (subtype == VSASSIGN || subtype == VSQUESTION) {
5596 if (subevalvar(p, var, 0, subtype, startloc, varflags, 0)) {
5599 * Remove any recorded regions beyond
5602 removerecordregions(startloc);
5612 if (varlen < 0 && uflag)
5613 varunset(p, var, 0, 0);
5615 if (subtype == VSLENGTH) {
5616 cvtnum(varlen > 0 ? varlen : 0);
5620 if (subtype == VSNORMAL) {
5624 recordregion(startloc, expdest - (char *)stackblock(), quoted);
5633 case VSTRIMRIGHTMAX:
5642 * Terminate the string and start recording the pattern
5645 STPUTC('\0', expdest);
5646 patloc = expdest - (char *)stackblock();
5647 if (subevalvar(p, NULL, patloc, subtype,
5648 startloc, varflags, quotes) == 0) {
5649 int amount = expdest - (
5650 (char *)stackblock() + patloc - 1
5652 STADJUST(-amount, expdest);
5654 /* Remove any recorded regions beyond start of variable */
5655 removerecordregions(startloc);
5660 if (subtype != VSNORMAL) { /* skip to end of alternative */
5666 else if (c == CTLBACKQ || c == (CTLBACKQ|CTLQUOTE)) {
5668 argbackq = argbackq->next;
5669 } else if (c == CTLVAR) {
5670 if ((*p++ & VSTYPE) != VSNORMAL)
5672 } else if (c == CTLENDVAR) {
5682 * Break the argument string into pieces based upon IFS and add the
5683 * strings to the argument list. The regions of the string to be
5684 * searched for IFS characters have been stored by recordregion.
5687 ifsbreakup(char *string, struct arglist *arglist)
5689 struct ifsregion *ifsp;
5694 const char *ifs, *realifs;
5699 if (ifslastp != NULL) {
5702 realifs = ifsset() ? ifsval() : defifs;
5705 p = string + ifsp->begoff;
5706 nulonly = ifsp->nulonly;
5707 ifs = nulonly ? nullstr : realifs;
5709 while (p < string + ifsp->endoff) {
5713 if (!strchr(ifs, *p)) {
5718 ifsspc = (strchr(defifs, *p) != NULL);
5719 /* Ignore IFS whitespace at start */
5720 if (q == start && ifsspc) {
5726 sp = stalloc(sizeof(*sp));
5728 *arglist->lastp = sp;
5729 arglist->lastp = &sp->next;
5733 if (p >= string + ifsp->endoff) {
5739 if (strchr(ifs, *p) == NULL ) {
5742 } else if (strchr(defifs, *p) == NULL) {
5757 } while (ifsp != NULL);
5766 sp = stalloc(sizeof(*sp));
5768 *arglist->lastp = sp;
5769 arglist->lastp = &sp->next;
5775 struct ifsregion *p;
5780 struct ifsregion *ifsp;
5786 ifsfirst.next = NULL;
5791 * Add a file name to the list.
5794 addfname(const char *name)
5798 sp = stalloc(sizeof(*sp));
5799 sp->text = ststrdup(name);
5801 exparg.lastp = &sp->next;
5804 static char *expdir;
5807 * Do metacharacter (i.e. *, ?, [...]) expansion.
5810 expmeta(char *enddir, char *name)
5825 for (p = name; *p; p++) {
5826 if (*p == '*' || *p == '?')
5828 else if (*p == '[') {
5835 if (*q == '/' || *q == '\0')
5842 } else if (*p == '\\')
5844 else if (*p == '/') {
5851 if (metaflag == 0) { /* we've reached the end of the file name */
5852 if (enddir != expdir)
5860 if (metaflag == 0 || lstat(expdir, &statb) >= 0)
5871 } while (p < start);
5873 if (enddir == expdir) {
5875 } else if (enddir == expdir + 1 && *expdir == '/') {
5884 if (enddir != expdir)
5886 if (*endname == 0) {
5898 while (! intpending && (dp = readdir(dirp)) != NULL) {
5899 if (dp->d_name[0] == '.' && ! matchdot)
5901 if (pmatch(start, dp->d_name)) {
5903 strcpy(enddir, dp->d_name);
5906 for (p = enddir, cp = dp->d_name; (*p++ = *cp++) != '\0';)
5909 expmeta(p, endname);
5918 static struct strlist *
5919 msort(struct strlist *list, int len)
5921 struct strlist *p, *q = NULL;
5922 struct strlist **lpp;
5930 for (n = half; --n >= 0; ) {
5934 q->next = NULL; /* terminate first half of list */
5935 q = msort(list, half); /* sort first half of list */
5936 p = msort(p, len - half); /* sort second half */
5939 #if ENABLE_LOCALE_SUPPORT
5940 if (strcoll(p->text, q->text) < 0)
5942 if (strcmp(p->text, q->text) < 0)
5966 * Sort the results of file name expansion. It calculates the number of
5967 * strings to sort and then calls msort (short for merge sort) to do the
5970 static struct strlist *
5971 expsort(struct strlist *str)
5977 for (sp = str; sp; sp = sp->next)
5979 return msort(str, len);
5983 expandmeta(struct strlist *str, int flag)
5985 static const char metachars[] = {
5988 /* TODO - EXP_REDIR */
5991 struct strlist **savelastp;
5997 if (!strpbrk(str->text, metachars))
5999 savelastp = exparg.lastp;
6002 p = preglob(str->text, 0, RMESCAPE_ALLOC | RMESCAPE_HEAP);
6004 int i = strlen(str->text);
6005 expdir = ckmalloc(i < 2048 ? 2048 : i); /* XXX */
6013 if (exparg.lastp == savelastp) {
6018 *exparg.lastp = str;
6019 rmescapes(str->text);
6020 exparg.lastp = &str->next;
6022 *exparg.lastp = NULL;
6023 *savelastp = sp = expsort(*savelastp);
6024 while (sp->next != NULL)
6026 exparg.lastp = &sp->next;
6033 * Perform variable substitution and command substitution on an argument,
6034 * placing the resulting list of arguments in arglist. If EXP_FULL is true,
6035 * perform splitting and file name expansion. When arglist is NULL, perform
6036 * here document expansion.
6039 expandarg(union node *arg, struct arglist *arglist, int flag)
6044 argbackq = arg->narg.backquote;
6045 STARTSTACKSTR(expdest);
6046 ifsfirst.next = NULL;
6048 argstr(arg->narg.text, flag);
6049 p = _STPUTC('\0', expdest);
6051 if (arglist == NULL) {
6052 return; /* here document expanded */
6054 p = grabstackstr(p);
6055 exparg.lastp = &exparg.list;
6059 if (flag & EXP_FULL) {
6060 ifsbreakup(p, &exparg);
6061 *exparg.lastp = NULL;
6062 exparg.lastp = &exparg.list;
6063 expandmeta(exparg.list, flag);
6065 if (flag & EXP_REDIR) /*XXX - for now, just remove escapes */
6067 sp = stalloc(sizeof(*sp));
6070 exparg.lastp = &sp->next;
6074 *exparg.lastp = NULL;
6076 *arglist->lastp = exparg.list;
6077 arglist->lastp = exparg.lastp;
6082 * Expand shell variables and backquotes inside a here document.
6085 expandhere(union node *arg, int fd)
6088 expandarg(arg, (struct arglist *)NULL, 0);
6089 full_write(fd, stackblock(), expdest - (char *)stackblock());
6093 * Returns true if the pattern matches the string.
6096 patmatch(char *pattern, const char *string)
6098 return pmatch(preglob(pattern, 0, 0), string);
6102 * See if a pattern matches in a case statement.
6105 casematch(union node *pattern, char *val)
6107 struct stackmark smark;
6110 setstackmark(&smark);
6111 argbackq = pattern->narg.backquote;
6112 STARTSTACKSTR(expdest);
6114 argstr(pattern->narg.text, EXP_TILDE | EXP_CASE);
6115 STACKSTRNUL(expdest);
6116 result = patmatch(stackblock(), val);
6117 popstackmark(&smark);
6122 /* ============ find_command */
6124 static int is_safe_applet(char *name)
6126 /* It isn't a bug to have non-existent applet here... */
6127 /* ...just a waste of space... */
6128 static const char safe_applets[][8] = {
6132 USE_CHMOD (, "chmod" )
6133 USE_CHOWN (, "chown" )
6137 USE_ECHO (, "echo" )
6138 USE_FIND (, "find" )
6139 USE_HEXDUMP(, "hexdump")
6142 USE_MKDIR (, "mkdir" )
6144 USE_SORT (, "sort" )
6145 USE_TEST (, "test" )
6146 USE_TOUCH (, "touch" )
6147 USE_XARGS (, "xargs" )
6149 int n = sizeof(safe_applets) / sizeof(safe_applets[0]);
6151 for (i = 0; i < n; i++)
6152 if (strcmp(safe_applets[i], name) == 0)
6160 int (*builtin)(int, char **);
6161 /* unsigned flags; */
6163 #define IS_BUILTIN_SPECIAL(b) ((b)->name[0] & 1)
6164 #define IS_BUILTIN_REGULAR(b) ((b)->name[0] & 2)
6165 #define IS_BUILTIN_ASSIGN(b) ((b)->name[0] & 4)
6171 const struct builtincmd *cmd;
6172 struct funcnode *func;
6175 /* values of cmdtype */
6176 #define CMDUNKNOWN -1 /* no entry in table for command */
6177 #define CMDNORMAL 0 /* command is an executable program */
6178 #define CMDFUNCTION 1 /* command is a shell function */
6179 #define CMDBUILTIN 2 /* command is a shell builtin */
6181 /* action to find_command() */
6182 #define DO_ERR 0x01 /* prints errors */
6183 #define DO_ABS 0x02 /* checks absolute paths */
6184 #define DO_NOFUNC 0x04 /* don't return shell functions, for command */
6185 #define DO_ALTPATH 0x08 /* using alternate path */
6186 #define DO_ALTBLTIN 0x20 /* %builtin in alt. path */
6188 static void find_command(char *, struct cmdentry *, int, const char *);
6191 /* ============ Hashing commands */
6194 * When commands are first encountered, they are entered in a hash table.
6195 * This ensures that a full path search will not have to be done for them
6196 * on each invocation.
6198 * We should investigate converting to a linear search, even though that
6199 * would make the command name "hash" a misnomer.
6202 #define CMDTABLESIZE 31 /* should be prime */
6203 #define ARB 1 /* actual size determined at run time */
6206 struct tblentry *next; /* next entry in hash chain */
6207 union param param; /* definition of builtin function */
6208 short cmdtype; /* index identifying command */
6209 char rehash; /* if set, cd done since entry created */
6210 char cmdname[ARB]; /* name of command */
6213 static struct tblentry *cmdtable[CMDTABLESIZE];
6214 static int builtinloc = -1; /* index in path of %builtin, or -1 */
6217 tryexec(char *cmd, char **argv, char **envp)
6220 struct BB_applet *a;
6224 if (strchr(cmd, '/') == NULL
6225 && (a = find_applet_by_name(cmd)) != NULL
6226 && is_safe_applet(cmd)
6229 while (*c != NULL) {
6233 exit(a->main(argc, argv));
6235 #if ENABLE_FEATURE_SH_STANDALONE_SHELL
6236 if (find_applet_by_name(cmd) != NULL) {
6237 /* re-exec ourselves with the new arguments */
6238 execve(CONFIG_BUSYBOX_EXEC_PATH, argv, envp);
6239 /* If they called chroot or otherwise made the binary no longer
6240 * executable, fall through */
6247 execve(cmd, argv, envp);
6248 } while (errno == EINTR);
6250 execve(cmd, argv, envp);
6254 } else if (errno == ENOEXEC) {
6258 for (ap = argv; *ap; ap++)
6260 ap = new = ckmalloc((ap - argv + 2) * sizeof(char *));
6262 *ap = cmd = (char *)DEFAULT_SHELL;
6265 while ((*ap++ = *argv++))
6273 * Exec a program. Never returns. If you change this routine, you may
6274 * have to change the find_command routine as well.
6276 #define environment() listvars(VEXPORT, VUNSET, 0)
6277 static void shellexec(char **, const char *, int) ATTRIBUTE_NORETURN;
6279 shellexec(char **argv, const char *path, int idx)
6287 envp = environment();
6288 if (strchr(argv[0], '/') || is_safe_applet(argv[0])
6289 #if ENABLE_FEATURE_SH_STANDALONE_SHELL
6290 || find_applet_by_name(argv[0])
6293 tryexec(argv[0], argv, envp);
6297 while ((cmdname = padvance(&path, argv[0])) != NULL) {
6298 if (--idx < 0 && pathopt == NULL) {
6299 tryexec(cmdname, argv, envp);
6300 if (errno != ENOENT && errno != ENOTDIR)
6307 /* Map to POSIX errors */
6319 exitstatus = exerrno;
6320 TRACE(("shellexec failed for %s, errno %d, suppressint %d\n",
6321 argv[0], e, suppressint ));
6322 ash_msg_and_raise(EXEXEC, "%s: %s", argv[0], errmsg(e, "not found"));
6327 printentry(struct tblentry *cmdp)
6333 idx = cmdp->param.index;
6336 name = padvance(&path, cmdp->cmdname);
6338 } while (--idx >= 0);
6339 out1fmt("%s%s\n", name, (cmdp->rehash ? "*" : nullstr));
6343 * Clear out command entries. The argument specifies the first entry in
6344 * PATH which has changed.
6347 clearcmdentry(int firstchange)
6349 struct tblentry **tblp;
6350 struct tblentry **pp;
6351 struct tblentry *cmdp;
6354 for (tblp = cmdtable; tblp < &cmdtable[CMDTABLESIZE]; tblp++) {
6356 while ((cmdp = *pp) != NULL) {
6357 if ((cmdp->cmdtype == CMDNORMAL &&
6358 cmdp->param.index >= firstchange)
6359 || (cmdp->cmdtype == CMDBUILTIN &&
6360 builtinloc >= firstchange)
6373 * Locate a command in the command hash table. If "add" is nonzero,
6374 * add the command to the table if it is not already present. The
6375 * variable "lastcmdentry" is set to point to the address of the link
6376 * pointing to the entry, so that delete_cmd_entry can delete the
6379 * Interrupts must be off if called with add != 0.
6381 static struct tblentry **lastcmdentry;
6383 static struct tblentry *
6384 cmdlookup(const char *name, int add)
6386 unsigned int hashval;
6388 struct tblentry *cmdp;
6389 struct tblentry **pp;
6392 hashval = (unsigned char)*p << 4;
6394 hashval += (unsigned char)*p++;
6396 pp = &cmdtable[hashval % CMDTABLESIZE];
6397 for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
6398 if (strcmp(cmdp->cmdname, name) == 0)
6402 if (add && cmdp == NULL) {
6403 cmdp = *pp = ckmalloc(sizeof(struct tblentry) - ARB
6404 + strlen(name) + 1);
6406 cmdp->cmdtype = CMDUNKNOWN;
6407 strcpy(cmdp->cmdname, name);
6414 * Delete the command entry returned on the last lookup.
6417 delete_cmd_entry(void)
6419 struct tblentry *cmdp;
6422 cmdp = *lastcmdentry;
6423 *lastcmdentry = cmdp->next;
6424 if (cmdp->cmdtype == CMDFUNCTION)
6425 freefunc(cmdp->param.func);
6431 * Add a new command entry, replacing any existing command entry for
6432 * the same name - except special builtins.
6435 addcmdentry(char *name, struct cmdentry *entry)
6437 struct tblentry *cmdp;
6439 cmdp = cmdlookup(name, 1);
6440 if (cmdp->cmdtype == CMDFUNCTION) {
6441 freefunc(cmdp->param.func);
6443 cmdp->cmdtype = entry->cmdtype;
6444 cmdp->param = entry->u;
6449 hashcmd(int argc, char **argv)
6451 struct tblentry **pp;
6452 struct tblentry *cmdp;
6454 struct cmdentry entry;
6457 while ((c = nextopt("r")) != '\0') {
6461 if (*argptr == NULL) {
6462 for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
6463 for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
6464 if (cmdp->cmdtype == CMDNORMAL)
6471 while ((name = *argptr) != NULL) {
6472 cmdp = cmdlookup(name, 0);
6474 && (cmdp->cmdtype == CMDNORMAL
6475 || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0)))
6477 find_command(name, &entry, DO_ERR, pathval());
6478 if (entry.cmdtype == CMDUNKNOWN)
6486 * Called when a cd is done. Marks all commands so the next time they
6487 * are executed they will be rehashed.
6492 struct tblentry **pp;
6493 struct tblentry *cmdp;
6495 for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
6496 for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
6497 if (cmdp->cmdtype == CMDNORMAL || (
6498 cmdp->cmdtype == CMDBUILTIN &&
6499 !(IS_BUILTIN_REGULAR(cmdp->param.cmd)) &&
6508 * Fix command hash table when PATH changed.
6509 * Called before PATH is changed. The argument is the new value of PATH;
6510 * pathval() still returns the old value at this point.
6511 * Called with interrupts off.
6514 changepath(const char *newval)
6516 const char *old, *new;
6523 firstchange = 9999; /* assume no change */
6529 if ((*old == '\0' && *new == ':')
6530 || (*old == ':' && *new == '\0'))
6532 old = new; /* ignore subsequent differences */
6536 if (*new == '%' && idx_bltin < 0 && prefix(new + 1, "builtin"))
6543 if (builtinloc < 0 && idx_bltin >= 0)
6544 builtinloc = idx_bltin; /* zap builtins */
6545 if (builtinloc >= 0 && idx_bltin < 0)
6547 clearcmdentry(firstchange);
6548 builtinloc = idx_bltin;
6563 #define TENDBQUOTE 12
6581 /* first char is indicating which tokens mark the end of a list */
6582 static const char *const tokname_array[] = {
6596 #define KWDOFFSET 13
6597 /* the following are keywords */
6619 static char buf[16];
6623 sprintf(buf + (tok >= TSEMI), "%s%c",
6624 tokname_array[tok] + 1, (tok >= TSEMI ? '"' : 0));
6628 /* Wrapper around strcmp for qsort/bsearch/... */
6630 pstrcmp(const void *a, const void *b)
6632 return strcmp((const char *) a, (*(const char *const *) b) + 1);
6635 static const char *const *
6636 findkwd(const char *s)
6638 return bsearch(s, tokname_array + KWDOFFSET,
6639 (sizeof(tokname_array) / sizeof(const char *)) - KWDOFFSET,
6640 sizeof(const char *), pstrcmp);
6644 * Locate and print what a word is...
6646 #if ENABLE_ASH_CMDCMD
6648 describe_command(char *command, int describe_command_verbose)
6650 #define describe_command_verbose 1
6652 describe_command(char *command)
6655 struct cmdentry entry;
6656 struct tblentry *cmdp;
6657 #if ENABLE_ASH_ALIAS
6658 const struct alias *ap;
6660 const char *path = pathval();
6662 if (describe_command_verbose) {
6666 /* First look at the keywords */
6667 if (findkwd(command)) {
6668 out1str(describe_command_verbose ? " is a shell keyword" : command);
6672 #if ENABLE_ASH_ALIAS
6673 /* Then look at the aliases */
6674 ap = lookupalias(command, 0);
6676 if (describe_command_verbose) {
6677 out1fmt(" is an alias for %s", ap->val);
6686 /* Then check if it is a tracked alias */
6687 cmdp = cmdlookup(command, 0);
6689 entry.cmdtype = cmdp->cmdtype;
6690 entry.u = cmdp->param;
6692 /* Finally use brute force */
6693 find_command(command, &entry, DO_ABS, path);
6696 switch (entry.cmdtype) {
6698 int j = entry.u.index;
6704 p = padvance(&path, command);
6708 if (describe_command_verbose) {
6710 (cmdp ? " a tracked alias for" : nullstr), p
6719 if (describe_command_verbose) {
6720 out1str(" is a shell function");
6727 if (describe_command_verbose) {
6728 out1fmt(" is a %sshell builtin",
6729 IS_BUILTIN_SPECIAL(entry.u.cmd) ?
6730 "special " : nullstr
6738 if (describe_command_verbose) {
6739 out1str(": not found\n");
6744 outstr("\n", stdout);
6749 typecmd(int argc, char **argv)
6754 for (i = 1; i < argc; i++) {
6755 #if ENABLE_ASH_CMDCMD
6756 err |= describe_command(argv[i], 1);
6758 err |= describe_command(argv[i]);
6764 #if ENABLE_ASH_CMDCMD
6766 commandcmd(int argc, char **argv)
6774 while ((c = nextopt("pvV")) != '\0')
6776 verify |= VERIFY_VERBOSE;
6778 verify |= VERIFY_BRIEF;
6784 return describe_command(*argptr, verify - VERIFY_BRIEF);
6791 /* ============ eval.c */
6793 static int funcblocksize; /* size of structures in function */
6794 static int funcstringsize; /* size of strings in node */
6795 static void *funcblock; /* block to allocate function from */
6796 static char *funcstring; /* block to allocate strings from */
6798 /* flags in argument to evaltree */
6799 #define EV_EXIT 01 /* exit after evaluating tree */
6800 #define EV_TESTED 02 /* exit status is checked; ignore -e flag */
6801 #define EV_BACKCMD 04 /* command executing within back quotes */
6803 static const short nodesize[26] = {
6804 SHELL_ALIGN(sizeof(struct ncmd)),
6805 SHELL_ALIGN(sizeof(struct npipe)),
6806 SHELL_ALIGN(sizeof(struct nredir)),
6807 SHELL_ALIGN(sizeof(struct nredir)),
6808 SHELL_ALIGN(sizeof(struct nredir)),
6809 SHELL_ALIGN(sizeof(struct nbinary)),
6810 SHELL_ALIGN(sizeof(struct nbinary)),
6811 SHELL_ALIGN(sizeof(struct nbinary)),
6812 SHELL_ALIGN(sizeof(struct nif)),
6813 SHELL_ALIGN(sizeof(struct nbinary)),
6814 SHELL_ALIGN(sizeof(struct nbinary)),
6815 SHELL_ALIGN(sizeof(struct nfor)),
6816 SHELL_ALIGN(sizeof(struct ncase)),
6817 SHELL_ALIGN(sizeof(struct nclist)),
6818 SHELL_ALIGN(sizeof(struct narg)),
6819 SHELL_ALIGN(sizeof(struct narg)),
6820 SHELL_ALIGN(sizeof(struct nfile)),
6821 SHELL_ALIGN(sizeof(struct nfile)),
6822 SHELL_ALIGN(sizeof(struct nfile)),
6823 SHELL_ALIGN(sizeof(struct nfile)),
6824 SHELL_ALIGN(sizeof(struct nfile)),
6825 SHELL_ALIGN(sizeof(struct ndup)),
6826 SHELL_ALIGN(sizeof(struct ndup)),
6827 SHELL_ALIGN(sizeof(struct nhere)),
6828 SHELL_ALIGN(sizeof(struct nhere)),
6829 SHELL_ALIGN(sizeof(struct nnot)),
6832 static void calcsize(union node *n);
6835 sizenodelist(struct nodelist *lp)
6838 funcblocksize += SHELL_ALIGN(sizeof(struct nodelist));
6845 calcsize(union node *n)
6849 funcblocksize += nodesize[n->type];
6852 calcsize(n->ncmd.redirect);
6853 calcsize(n->ncmd.args);
6854 calcsize(n->ncmd.assign);
6857 sizenodelist(n->npipe.cmdlist);
6862 calcsize(n->nredir.redirect);
6863 calcsize(n->nredir.n);
6870 calcsize(n->nbinary.ch2);
6871 calcsize(n->nbinary.ch1);
6874 calcsize(n->nif.elsepart);
6875 calcsize(n->nif.ifpart);
6876 calcsize(n->nif.test);
6879 funcstringsize += strlen(n->nfor.var) + 1;
6880 calcsize(n->nfor.body);
6881 calcsize(n->nfor.args);
6884 calcsize(n->ncase.cases);
6885 calcsize(n->ncase.expr);
6888 calcsize(n->nclist.body);
6889 calcsize(n->nclist.pattern);
6890 calcsize(n->nclist.next);
6894 sizenodelist(n->narg.backquote);
6895 funcstringsize += strlen(n->narg.text) + 1;
6896 calcsize(n->narg.next);
6903 calcsize(n->nfile.fname);
6904 calcsize(n->nfile.next);
6908 calcsize(n->ndup.vname);
6909 calcsize(n->ndup.next);
6913 calcsize(n->nhere.doc);
6914 calcsize(n->nhere.next);
6917 calcsize(n->nnot.com);
6923 nodeckstrdup(char *s)
6925 char *rtn = funcstring;
6927 strcpy(funcstring, s);
6928 funcstring += strlen(s) + 1;
6932 static union node *copynode(union node *);
6934 static struct nodelist *
6935 copynodelist(struct nodelist *lp)
6937 struct nodelist *start;
6938 struct nodelist **lpp;
6943 funcblock = (char *) funcblock + SHELL_ALIGN(sizeof(struct nodelist));
6944 (*lpp)->n = copynode(lp->n);
6946 lpp = &(*lpp)->next;
6953 copynode(union node *n)
6960 funcblock = (char *) funcblock + nodesize[n->type];
6964 new->ncmd.redirect = copynode(n->ncmd.redirect);
6965 new->ncmd.args = copynode(n->ncmd.args);
6966 new->ncmd.assign = copynode(n->ncmd.assign);
6969 new->npipe.cmdlist = copynodelist(n->npipe.cmdlist);
6970 new->npipe.backgnd = n->npipe.backgnd;
6975 new->nredir.redirect = copynode(n->nredir.redirect);
6976 new->nredir.n = copynode(n->nredir.n);
6983 new->nbinary.ch2 = copynode(n->nbinary.ch2);
6984 new->nbinary.ch1 = copynode(n->nbinary.ch1);
6987 new->nif.elsepart = copynode(n->nif.elsepart);
6988 new->nif.ifpart = copynode(n->nif.ifpart);
6989 new->nif.test = copynode(n->nif.test);
6992 new->nfor.var = nodeckstrdup(n->nfor.var);
6993 new->nfor.body = copynode(n->nfor.body);
6994 new->nfor.args = copynode(n->nfor.args);
6997 new->ncase.cases = copynode(n->ncase.cases);
6998 new->ncase.expr = copynode(n->ncase.expr);
7001 new->nclist.body = copynode(n->nclist.body);
7002 new->nclist.pattern = copynode(n->nclist.pattern);
7003 new->nclist.next = copynode(n->nclist.next);
7007 new->narg.backquote = copynodelist(n->narg.backquote);
7008 new->narg.text = nodeckstrdup(n->narg.text);
7009 new->narg.next = copynode(n->narg.next);
7016 new->nfile.fname = copynode(n->nfile.fname);
7017 new->nfile.fd = n->nfile.fd;
7018 new->nfile.next = copynode(n->nfile.next);
7022 new->ndup.vname = copynode(n->ndup.vname);
7023 new->ndup.dupfd = n->ndup.dupfd;
7024 new->ndup.fd = n->ndup.fd;
7025 new->ndup.next = copynode(n->ndup.next);
7029 new->nhere.doc = copynode(n->nhere.doc);
7030 new->nhere.fd = n->nhere.fd;
7031 new->nhere.next = copynode(n->nhere.next);
7034 new->nnot.com = copynode(n->nnot.com);
7037 new->type = n->type;
7042 * Make a copy of a parse tree.
7044 static struct funcnode *
7045 copyfunc(union node *n)
7050 funcblocksize = offsetof(struct funcnode, n);
7053 blocksize = funcblocksize;
7054 f = ckmalloc(blocksize + funcstringsize);
7055 funcblock = (char *) f + offsetof(struct funcnode, n);
7056 funcstring = (char *) f + blocksize;
7063 * Define a shell function.
7066 defun(char *name, union node *func)
7068 struct cmdentry entry;
7071 entry.cmdtype = CMDFUNCTION;
7072 entry.u.func = copyfunc(func);
7073 addcmdentry(name, &entry);
7077 static int evalskip; /* set if we are skipping commands */
7078 /* reasons for skipping commands (see comment on breakcmd routine) */
7079 #define SKIPBREAK (1 << 0)
7080 #define SKIPCONT (1 << 1)
7081 #define SKIPFUNC (1 << 2)
7082 #define SKIPFILE (1 << 3)
7083 #define SKIPEVAL (1 << 4)
7084 static int skipcount; /* number of levels to skip */
7085 static int funcnest; /* depth of function calls */
7087 /* forward decl way out to parsing code - dotrap needs it */
7088 static int evalstring(char *s, int mask);
7091 * Called to execute a trap. Perhaps we should avoid entering new trap
7092 * handlers while we are executing a trap handler.
7103 savestatus = exitstatus;
7107 for (i = 0, q = gotsig; i < NSIG - 1; i++, q++) {
7115 skip = evalstring(p, SKIPEVAL);
7116 exitstatus = savestatus;
7124 /* forward declarations - evaluation is fairly recursive business... */
7125 static void evalloop(union node *, int);
7126 static void evalfor(union node *, int);
7127 static void evalcase(union node *, int);
7128 static void evalsubshell(union node *, int);
7129 static void expredir(union node *);
7130 static void evalpipe(union node *, int);
7131 static void evalcommand(union node *, int);
7132 static int evalbltin(const struct builtincmd *, int, char **);
7133 static void prehash(union node *);
7136 * Evaluate a parse tree. The value is left in the global variable
7140 evaltree(union node *n, int flags)
7143 void (*evalfn)(union node *, int);
7147 TRACE(("evaltree(NULL) called\n"));
7150 TRACE(("pid %d, evaltree(%p: %d, %d) called\n",
7151 getpid(), n, n->type, flags));
7155 out1fmt("Node type = %d\n", n->type);
7160 evaltree(n->nnot.com, EV_TESTED);
7161 status = !exitstatus;
7164 expredir(n->nredir.redirect);
7165 status = redirectsafe(n->nredir.redirect, REDIR_PUSH);
7167 evaltree(n->nredir.n, flags & EV_TESTED);
7168 status = exitstatus;
7173 evalfn = evalcommand;
7175 if (eflag && !(flags & EV_TESTED))
7187 evalfn = evalsubshell;
7199 #error NAND + 1 != NOR
7201 #if NOR + 1 != NSEMI
7202 #error NOR + 1 != NSEMI
7204 isor = n->type - NAND;
7207 (flags | ((isor >> 1) - 1)) & EV_TESTED
7209 if (!exitstatus == isor)
7221 evaltree(n->nif.test, EV_TESTED);
7224 if (exitstatus == 0) {
7227 } else if (n->nif.elsepart) {
7228 n = n->nif.elsepart;
7233 defun(n->narg.text, n->narg.next);
7237 exitstatus = status;
7241 if ((checkexit & exitstatus))
7242 evalskip |= SKIPEVAL;
7243 else if (pendingsigs && dotrap())
7246 if (flags & EV_EXIT) {
7248 raise_exception(EXEXIT);
7252 #if !defined(__alpha__) || (defined(__GNUC__) && __GNUC__ >= 3)
7255 void evaltreenr(union node *, int) __attribute__ ((alias("evaltree"),__noreturn__));
7257 static int loopnest; /* current loop nesting level */
7260 evalloop(union node *n, int flags)
7270 evaltree(n->nbinary.ch1, EV_TESTED);
7273 if (evalskip == SKIPCONT && --skipcount <= 0) {
7277 if (evalskip == SKIPBREAK && --skipcount <= 0)
7282 if (n->type != NWHILE)
7286 evaltree(n->nbinary.ch2, flags);
7287 status = exitstatus;
7292 exitstatus = status;
7296 evalfor(union node *n, int flags)
7298 struct arglist arglist;
7301 struct stackmark smark;
7303 setstackmark(&smark);
7304 arglist.lastp = &arglist.list;
7305 for (argp = n->nfor.args; argp; argp = argp->narg.next) {
7306 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE | EXP_RECORD);
7311 *arglist.lastp = NULL;
7316 for (sp = arglist.list; sp; sp = sp->next) {
7317 setvar(n->nfor.var, sp->text, 0);
7318 evaltree(n->nfor.body, flags);
7320 if (evalskip == SKIPCONT && --skipcount <= 0) {
7324 if (evalskip == SKIPBREAK && --skipcount <= 0)
7331 popstackmark(&smark);
7335 evalcase(union node *n, int flags)
7339 struct arglist arglist;
7340 struct stackmark smark;
7342 setstackmark(&smark);
7343 arglist.lastp = &arglist.list;
7344 expandarg(n->ncase.expr, &arglist, EXP_TILDE);
7346 for (cp = n->ncase.cases; cp && evalskip == 0; cp = cp->nclist.next) {
7347 for (patp = cp->nclist.pattern; patp; patp = patp->narg.next) {
7348 if (casematch(patp, arglist.list->text)) {
7349 if (evalskip == 0) {
7350 evaltree(cp->nclist.body, flags);
7357 popstackmark(&smark);
7361 * Kick off a subshell to evaluate a tree.
7364 evalsubshell(union node *n, int flags)
7367 int backgnd = (n->type == NBACKGND);
7370 expredir(n->nredir.redirect);
7371 if (!backgnd && flags & EV_EXIT && !trap[0])
7375 if (forkshell(jp, n, backgnd) == 0) {
7379 flags &=~ EV_TESTED;
7381 redirect(n->nredir.redirect, 0);
7382 evaltreenr(n->nredir.n, flags);
7387 status = waitforjob(jp);
7388 exitstatus = status;
7393 * Compute the names of the files in a redirection list.
7395 static void fixredir(union node *, const char *, int);
7397 expredir(union node *n)
7401 for (redir = n; redir; redir = redir->nfile.next) {
7404 memset(&fn, 0, sizeof(fn));
7405 fn.lastp = &fn.list;
7406 switch (redir->type) {
7412 expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
7413 redir->nfile.expfname = fn.list->text;
7417 if (redir->ndup.vname) {
7418 expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE);
7419 if (fn.list == NULL)
7420 ash_msg_and_raise_error("redir error");
7421 fixredir(redir, fn.list->text, 1);
7429 * Evaluate a pipeline. All the processes in the pipeline are children
7430 * of the process creating the pipeline. (This differs from some versions
7431 * of the shell, which make the last process in a pipeline the parent
7435 evalpipe(union node *n, int flags)
7438 struct nodelist *lp;
7443 TRACE(("evalpipe(0x%lx) called\n", (long)n));
7445 for (lp = n->npipe.cmdlist; lp; lp = lp->next)
7449 jp = makejob(n, pipelen);
7451 for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
7455 if (pipe(pip) < 0) {
7457 ash_msg_and_raise_error("Pipe call failed");
7460 if (forkshell(jp, lp->n, n->npipe.backgnd) == 0) {
7473 evaltreenr(lp->n, flags);
7481 if (n->npipe.backgnd == 0) {
7482 exitstatus = waitforjob(jp);
7483 TRACE(("evalpipe: job done exit status %d\n", exitstatus));
7488 static struct localvar *localvars;
7491 * Called after a function returns.
7492 * Interrupts must be off.
7497 struct localvar *lvp;
7500 while ((lvp = localvars) != NULL) {
7501 localvars = lvp->next;
7503 TRACE(("poplocalvar %s", vp ? vp->text : "-"));
7504 if (vp == NULL) { /* $- saved */
7505 memcpy(optlist, lvp->text, sizeof(optlist));
7506 free((char*)lvp->text);
7508 } else if ((lvp->flags & (VUNSET|VSTRFIXED)) == VUNSET) {
7512 (*vp->func)(strchrnul(lvp->text, '=') + 1);
7513 if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
7514 free((char*)vp->text);
7515 vp->flags = lvp->flags;
7516 vp->text = lvp->text;
7523 evalfun(struct funcnode *func, int argc, char **argv, int flags)
7525 volatile struct shparam saveparam;
7526 struct localvar *volatile savelocalvars;
7527 struct jmploc *volatile savehandler;
7528 struct jmploc jmploc;
7531 saveparam = shellparam;
7532 savelocalvars = localvars;
7533 e = setjmp(jmploc.loc);
7538 savehandler = exception_handler;
7539 exception_handler = &jmploc;
7541 shellparam.malloc = 0;
7545 shellparam.nparam = argc - 1;
7546 shellparam.p = argv + 1;
7547 #if ENABLE_ASH_GETOPTS
7548 shellparam.optind = 1;
7549 shellparam.optoff = -1;
7551 evaltree(&func->n, flags & EV_TESTED);
7557 localvars = savelocalvars;
7558 freeparam(&shellparam);
7559 shellparam = saveparam;
7560 exception_handler = savehandler;
7562 evalskip &= ~SKIPFUNC;
7566 #if ENABLE_ASH_CMDCMD
7568 parse_command_args(char **argv, const char **path)
7581 if (c == '-' && !*cp) {
7591 /* run 'typecmd' for other options */
7602 * Make a variable a local variable. When a variable is made local, it's
7603 * value and flags are saved in a localvar structure. The saved values
7604 * will be restored when the shell function returns. We handle the name
7605 * "-" as a special case.
7610 struct localvar *lvp;
7615 lvp = ckmalloc(sizeof(struct localvar));
7616 if (LONE_DASH(name)) {
7618 p = ckmalloc(sizeof(optlist));
7619 lvp->text = memcpy(p, optlist, sizeof(optlist));
7624 vpp = hashvar(name);
7625 vp = *findvar(vpp, name);
7626 eq = strchr(name, '=');
7629 setvareq(name, VSTRFIXED);
7631 setvar(name, NULL, VSTRFIXED);
7632 vp = *vpp; /* the new variable */
7633 lvp->flags = VUNSET;
7635 lvp->text = vp->text;
7636 lvp->flags = vp->flags;
7637 vp->flags |= VSTRFIXED|VTEXTFIXED;
7643 lvp->next = localvars;
7649 * The "local" command.
7652 localcmd(int argc, char **argv)
7657 while ((name = *argv++) != NULL) {
7663 /* Forward declarations for builtintab[] */
7665 static int fg_bgcmd(int, char **);
7667 static int breakcmd(int, char **);
7668 #if ENABLE_ASH_CMDCMD
7669 static int commandcmd(int, char **);
7671 static int dotcmd(int, char **);
7672 static int evalcmd(int, char **);
7673 #if ENABLE_ASH_BUILTIN_ECHO
7674 static int echocmd(int, char **);
7676 #if ENABLE_ASH_BUILTIN_TEST
7677 static int testcmd(int, char **);
7679 static int execcmd(int, char **);
7680 static int exitcmd(int, char **);
7681 static int exportcmd(int, char **);
7682 static int falsecmd(int, char **);
7683 #if ENABLE_ASH_GETOPTS
7684 static int getoptscmd(int, char **);
7686 static int hashcmd(int, char **);
7687 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
7688 static int helpcmd(int argc, char **argv);
7691 static int jobscmd(int, char **);
7693 #if ENABLE_ASH_MATH_SUPPORT
7694 static int letcmd(int, char **);
7696 static int pwdcmd(int, char **);
7697 static int readcmd(int, char **);
7698 static int returncmd(int, char **);
7699 static int setcmd(int, char **);
7700 static int shiftcmd(int, char **);
7701 static int timescmd(int, char **);
7702 static int trapcmd(int, char **);
7703 static int truecmd(int, char **);
7704 static int typecmd(int, char **);
7705 static int umaskcmd(int, char **);
7706 static int unsetcmd(int, char **);
7707 static int waitcmd(int, char **);
7708 static int ulimitcmd(int, char **);
7710 static int killcmd(int, char **);
7713 #define BUILTIN_NOSPEC "0"
7714 #define BUILTIN_SPECIAL "1"
7715 #define BUILTIN_REGULAR "2"
7716 #define BUILTIN_SPEC_REG "3"
7717 #define BUILTIN_ASSIGN "4"
7718 #define BUILTIN_SPEC_ASSG "5"
7719 #define BUILTIN_REG_ASSG "6"
7720 #define BUILTIN_SPEC_REG_ASSG "7"
7722 /* make sure to keep these in proper order since it is searched via bsearch() */
7723 static const struct builtincmd builtintab[] = {
7724 { BUILTIN_SPEC_REG ".", dotcmd },
7725 { BUILTIN_SPEC_REG ":", truecmd },
7726 #if ENABLE_ASH_BUILTIN_TEST
7727 { BUILTIN_REGULAR "[", testcmd },
7728 { BUILTIN_REGULAR "[[", testcmd },
7730 #if ENABLE_ASH_ALIAS
7731 { BUILTIN_REG_ASSG "alias", aliascmd },
7734 { BUILTIN_REGULAR "bg", fg_bgcmd },
7736 { BUILTIN_SPEC_REG "break", breakcmd },
7737 { BUILTIN_REGULAR "cd", cdcmd },
7738 { BUILTIN_NOSPEC "chdir", cdcmd },
7739 #if ENABLE_ASH_CMDCMD
7740 { BUILTIN_REGULAR "command", commandcmd },
7742 { BUILTIN_SPEC_REG "continue", breakcmd },
7743 #if ENABLE_ASH_BUILTIN_ECHO
7744 { BUILTIN_REGULAR "echo", echocmd },
7746 { BUILTIN_SPEC_REG "eval", evalcmd },
7747 { BUILTIN_SPEC_REG "exec", execcmd },
7748 { BUILTIN_SPEC_REG "exit", exitcmd },
7749 { BUILTIN_SPEC_REG_ASSG "export", exportcmd },
7750 { BUILTIN_REGULAR "false", falsecmd },
7752 { BUILTIN_REGULAR "fg", fg_bgcmd },
7754 #if ENABLE_ASH_GETOPTS
7755 { BUILTIN_REGULAR "getopts", getoptscmd },
7757 { BUILTIN_NOSPEC "hash", hashcmd },
7758 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
7759 { BUILTIN_NOSPEC "help", helpcmd },
7762 { BUILTIN_REGULAR "jobs", jobscmd },
7763 { BUILTIN_REGULAR "kill", killcmd },
7765 #if ENABLE_ASH_MATH_SUPPORT
7766 { BUILTIN_NOSPEC "let", letcmd },
7768 { BUILTIN_ASSIGN "local", localcmd },
7769 { BUILTIN_NOSPEC "pwd", pwdcmd },
7770 { BUILTIN_REGULAR "read", readcmd },
7771 { BUILTIN_SPEC_REG_ASSG "readonly", exportcmd },
7772 { BUILTIN_SPEC_REG "return", returncmd },
7773 { BUILTIN_SPEC_REG "set", setcmd },
7774 { BUILTIN_SPEC_REG "shift", shiftcmd },
7775 { BUILTIN_SPEC_REG "source", dotcmd },
7776 #if ENABLE_ASH_BUILTIN_TEST
7777 { BUILTIN_REGULAR "test", testcmd },
7779 { BUILTIN_SPEC_REG "times", timescmd },
7780 { BUILTIN_SPEC_REG "trap", trapcmd },
7781 { BUILTIN_REGULAR "true", truecmd },
7782 { BUILTIN_NOSPEC "type", typecmd },
7783 { BUILTIN_NOSPEC "ulimit", ulimitcmd },
7784 { BUILTIN_REGULAR "umask", umaskcmd },
7785 #if ENABLE_ASH_ALIAS
7786 { BUILTIN_REGULAR "unalias", unaliascmd },
7788 { BUILTIN_SPEC_REG "unset", unsetcmd },
7789 { BUILTIN_REGULAR "wait", waitcmd },
7792 #define NUMBUILTINS (sizeof(builtintab) / sizeof(builtintab[0]))
7794 #define COMMANDCMD (builtintab + 5 + \
7795 2 * ENABLE_ASH_BUILTIN_TEST + \
7796 ENABLE_ASH_ALIAS + \
7797 ENABLE_ASH_JOB_CONTROL)
7798 #define EXECCMD (builtintab + 7 + \
7799 2 * ENABLE_ASH_BUILTIN_TEST + \
7800 ENABLE_ASH_ALIAS + \
7801 ENABLE_ASH_JOB_CONTROL + \
7802 ENABLE_ASH_CMDCMD + \
7803 ENABLE_ASH_BUILTIN_ECHO)
7806 * Search the table of builtin commands.
7808 static struct builtincmd *
7809 find_builtin(const char *name)
7811 struct builtincmd *bp;
7814 name, builtintab, NUMBUILTINS, sizeof(builtintab[0]),
7821 * Resolve a command name. If you change this routine, you may have to
7822 * change the shellexec routine as well.
7825 find_command(char *name, struct cmdentry *entry, int act, const char *path)
7827 struct tblentry *cmdp;
7834 struct builtincmd *bcmd;
7836 /* If name contains a slash, don't use PATH or hash table */
7837 if (strchr(name, '/') != NULL) {
7838 entry->u.index = -1;
7840 while (stat(name, &statb) < 0) {
7845 entry->cmdtype = CMDUNKNOWN;
7849 entry->cmdtype = CMDNORMAL;
7853 #if ENABLE_FEATURE_SH_STANDALONE_SHELL
7854 if (find_applet_by_name(name)) {
7855 entry->cmdtype = CMDNORMAL;
7856 entry->u.index = -1;
7861 if (is_safe_applet(name)) {
7862 entry->cmdtype = CMDNORMAL;
7863 entry->u.index = -1;
7867 updatetbl = (path == pathval());
7870 if (strstr(path, "%builtin") != NULL)
7874 /* If name is in the table, check answer will be ok */
7875 cmdp = cmdlookup(name, 0);
7879 switch (cmdp->cmdtype) {
7897 } else if (cmdp->rehash == 0)
7898 /* if not invalidated by cd, we're done */
7902 /* If %builtin not in path, check for builtin next */
7903 bcmd = find_builtin(name);
7904 if (bcmd && (IS_BUILTIN_REGULAR(bcmd) || (
7905 act & DO_ALTPATH ? !(act & DO_ALTBLTIN) : builtinloc <= 0
7907 goto builtin_success;
7909 /* We have to search path. */
7910 prev = -1; /* where to start */
7911 if (cmdp && cmdp->rehash) { /* doing a rehash */
7912 if (cmdp->cmdtype == CMDBUILTIN)
7915 prev = cmdp->param.index;
7921 while ((fullname = padvance(&path, name)) != NULL) {
7922 stunalloc(fullname);
7925 if (prefix(pathopt, "builtin")) {
7927 goto builtin_success;
7929 } else if (!(act & DO_NOFUNC) &&
7930 prefix(pathopt, "func")) {
7933 /* ignore unimplemented options */
7937 /* if rehash, don't redo absolute path names */
7938 if (fullname[0] == '/' && idx <= prev) {
7941 TRACE(("searchexec \"%s\": no change\n", name));
7944 while (stat(fullname, &statb) < 0) {
7949 if (errno != ENOENT && errno != ENOTDIR)
7953 e = EACCES; /* if we fail, this will be the error */
7954 if (!S_ISREG(statb.st_mode))
7956 if (pathopt) { /* this is a %func directory */
7957 stalloc(strlen(fullname) + 1);
7958 readcmdfile(fullname);
7959 cmdp = cmdlookup(name, 0);
7960 if (cmdp == NULL || cmdp->cmdtype != CMDFUNCTION)
7961 ash_msg_and_raise_error("%s not defined in %s", name, fullname);
7962 stunalloc(fullname);
7965 TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
7967 entry->cmdtype = CMDNORMAL;
7968 entry->u.index = idx;
7972 cmdp = cmdlookup(name, 1);
7973 cmdp->cmdtype = CMDNORMAL;
7974 cmdp->param.index = idx;
7979 /* We failed. If there was an entry for this command, delete it */
7980 if (cmdp && updatetbl)
7983 ash_msg("%s: %s", name, errmsg(e, "not found"));
7984 entry->cmdtype = CMDUNKNOWN;
7989 entry->cmdtype = CMDBUILTIN;
7990 entry->u.cmd = bcmd;
7994 cmdp = cmdlookup(name, 1);
7995 cmdp->cmdtype = CMDBUILTIN;
7996 cmdp->param.cmd = bcmd;
8000 entry->cmdtype = cmdp->cmdtype;
8001 entry->u = cmdp->param;
8005 * Execute a simple command.
8007 static int back_exitstatus; /* exit status of backquoted command */
8009 isassignment(const char *p)
8011 const char *q = endofname(p);
8017 bltincmd(int argc, char **argv)
8019 /* Preserve exitstatus of a previous possible redirection
8020 * as POSIX mandates */
8021 return back_exitstatus;
8024 evalcommand(union node *cmd, int flags)
8026 static const struct builtincmd bltin = {
8029 struct stackmark smark;
8031 struct arglist arglist;
8032 struct arglist varlist;
8035 const struct strlist *sp;
8036 struct cmdentry cmdentry;
8044 struct builtincmd *bcmd;
8045 int pseudovarflag = 0;
8047 /* First expand the arguments. */
8048 TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
8049 setstackmark(&smark);
8050 back_exitstatus = 0;
8052 cmdentry.cmdtype = CMDBUILTIN;
8053 cmdentry.u.cmd = &bltin;
8054 varlist.lastp = &varlist.list;
8055 *varlist.lastp = NULL;
8056 arglist.lastp = &arglist.list;
8057 *arglist.lastp = NULL;
8060 if (cmd->ncmd.args) {
8061 bcmd = find_builtin(cmd->ncmd.args->narg.text);
8062 pseudovarflag = bcmd && IS_BUILTIN_ASSIGN(bcmd);
8065 for (argp = cmd->ncmd.args; argp; argp = argp->narg.next) {
8066 struct strlist **spp;
8068 spp = arglist.lastp;
8069 if (pseudovarflag && isassignment(argp->narg.text))
8070 expandarg(argp, &arglist, EXP_VARTILDE);
8072 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
8074 for (sp = *spp; sp; sp = sp->next)
8078 argv = nargv = stalloc(sizeof(char *) * (argc + 1));
8079 for (sp = arglist.list; sp; sp = sp->next) {
8080 TRACE(("evalcommand arg: %s\n", sp->text));
8081 *nargv++ = sp->text;
8086 if (iflag && funcnest == 0 && argc > 0)
8087 lastarg = nargv[-1];
8090 expredir(cmd->ncmd.redirect);
8091 status = redirectsafe(cmd->ncmd.redirect, REDIR_PUSH|REDIR_SAVEFD2);
8094 for (argp = cmd->ncmd.assign; argp; argp = argp->narg.next) {
8095 struct strlist **spp;
8098 spp = varlist.lastp;
8099 expandarg(argp, &varlist, EXP_VARTILDE);
8102 * Modify the command lookup path, if a PATH= assignment
8106 if (varequal(p, path))
8110 /* Print the command if xflag is set. */
8113 const char *p = " %s";
8116 dprintf(preverrout_fd, p, expandstr(ps4val()));
8119 for (n = 0; n < 2; n++) {
8121 dprintf(preverrout_fd, p, sp->text);
8129 full_write(preverrout_fd, "\n", 1);
8135 /* Now locate the command. */
8137 const char *oldpath;
8138 int cmd_flag = DO_ERR;
8143 find_command(argv[0], &cmdentry, cmd_flag, path);
8144 if (cmdentry.cmdtype == CMDUNKNOWN) {
8150 /* implement bltin and command here */
8151 if (cmdentry.cmdtype != CMDBUILTIN)
8154 spclbltin = IS_BUILTIN_SPECIAL(cmdentry.u.cmd);
8155 if (cmdentry.u.cmd == EXECCMD)
8157 #if ENABLE_ASH_CMDCMD
8158 if (cmdentry.u.cmd == COMMANDCMD) {
8160 nargv = parse_command_args(argv, &path);
8163 argc -= nargv - argv;
8165 cmd_flag |= DO_NOFUNC;
8173 /* We have a redirection error. */
8175 raise_exception(EXERROR);
8177 exitstatus = status;
8181 /* Execute the command. */
8182 switch (cmdentry.cmdtype) {
8184 /* Fork off a child process if necessary. */
8185 if (!(flags & EV_EXIT) || trap[0]) {
8187 jp = makejob(cmd, 1);
8188 if (forkshell(jp, cmd, FORK_FG) != 0) {
8189 exitstatus = waitforjob(jp);
8195 listsetvar(varlist.list, VEXPORT|VSTACK);
8196 shellexec(argv, path, cmdentry.u.index);
8200 cmdenviron = varlist.list;
8202 struct strlist *list = cmdenviron;
8204 if (spclbltin > 0 || argc == 0) {
8206 if (cmd_is_exec && argc > 1)
8209 listsetvar(list, i);
8211 if (evalbltin(cmdentry.u.cmd, argc, argv)) {
8226 exit_status = j + 128;
8227 exitstatus = exit_status;
8229 if (i == EXINT || spclbltin > 0) {
8231 longjmp(exception_handler->loc, 1);
8238 listsetvar(varlist.list, 0);
8239 if (evalfun(cmdentry.u.func, argc, argv, flags))
8245 popredir(cmd_is_exec);
8247 /* dsl: I think this is intended to be used to support
8248 * '_' in 'vi' command mode during line editing...
8249 * However I implemented that within libedit itself.
8251 setvar("_", lastarg, 0);
8252 popstackmark(&smark);
8256 evalbltin(const struct builtincmd *cmd, int argc, char **argv)
8258 char *volatile savecmdname;
8259 struct jmploc *volatile savehandler;
8260 struct jmploc jmploc;
8263 savecmdname = commandname;
8264 i = setjmp(jmploc.loc);
8267 savehandler = exception_handler;
8268 exception_handler = &jmploc;
8269 commandname = argv[0];
8271 optptr = NULL; /* initialize nextopt */
8272 exitstatus = (*cmd->builtin)(argc, argv);
8273 flush_stdout_stderr();
8275 exitstatus |= ferror(stdout);
8277 commandname = savecmdname;
8279 exception_handler = savehandler;
8285 goodname(const char *p)
8287 return !*endofname(p);
8292 * Search for a command. This is called before we fork so that the
8293 * location of the command will be available in the parent as well as
8294 * the child. The check for "goodname" is an overly conservative
8295 * check that the name will not be subject to expansion.
8298 prehash(union node *n)
8300 struct cmdentry entry;
8302 if (n->type == NCMD && n->ncmd.args && goodname(n->ncmd.args->narg.text))
8303 find_command(n->ncmd.args->narg.text, &entry, 0, pathval());
8308 * Builtin commands. Builtin commands whose functions are closely
8309 * tied to evaluation are implemented here.
8313 * Handle break and continue commands. Break, continue, and return are
8314 * all handled by setting the evalskip flag. The evaluation routines
8315 * above all check this flag, and if it is set they start skipping
8316 * commands rather than executing them. The variable skipcount is
8317 * the number of loops to break/continue, or the number of function
8318 * levels to return. (The latter is always 1.) It should probably
8319 * be an error to break out of more loops than exist, but it isn't
8320 * in the standard shell so we don't make it one here.
8324 breakcmd(int argc, char **argv)
8326 int n = argc > 1 ? number(argv[1]) : 1;
8329 ash_msg_and_raise_error(illnum, argv[1]);
8333 evalskip = (**argv == 'c')? SKIPCONT : SKIPBREAK;
8340 * The return command.
8343 returncmd(int argc, char **argv)
8346 * If called outside a function, do what ksh does;
8347 * skip the rest of the file.
8349 evalskip = funcnest ? SKIPFUNC : SKIPFILE;
8350 return argv[1] ? number(argv[1]) : exitstatus;
8354 falsecmd(int argc, char **argv)
8360 truecmd(int argc, char **argv)
8366 execcmd(int argc, char **argv)
8369 iflag = 0; /* exit on error */
8372 shellexec(argv + 1, pathval(), 0);
8378 /* ============ input.c
8380 * This implements the input routines used by the parser.
8383 #define EOF_NLEFT -99 /* value of parsenleft when EOF pushed back */
8386 INPUT_PUSH_FILE = 1,
8387 INPUT_NOFILE_OK = 2,
8391 * NEOF is returned by parsecmd when it encounters an end of file. It
8392 * must be distinct from NULL, so we use the address of a variable that
8393 * happens to be handy.
8395 static int plinno = 1; /* input line number */
8396 /* number of characters left in input buffer */
8397 static int parsenleft; /* copy of parsefile->nleft */
8398 static int parselleft; /* copy of parsefile->lleft */
8399 /* next character in input buffer */
8400 static char *parsenextc; /* copy of parsefile->nextc */
8402 static int checkkwd;
8403 /* values of checkkwd variable */
8404 #define CHKALIAS 0x1
8412 struct strpush *sp = parsefile->strpush;
8415 #if ENABLE_ASH_ALIAS
8417 if (parsenextc[-1] == ' ' || parsenextc[-1] == '\t') {
8418 checkkwd |= CHKALIAS;
8420 if (sp->string != sp->ap->val) {
8423 sp->ap->flag &= ~ALIASINUSE;
8424 if (sp->ap->flag & ALIASDEAD) {
8425 unalias(sp->ap->name);
8429 parsenextc = sp->prevstring;
8430 parsenleft = sp->prevnleft;
8431 /*dprintf("*** calling popstring: restoring to '%s'\n", parsenextc);*/
8432 parsefile->strpush = sp->prev;
8433 if (sp != &(parsefile->basestrpush))
8442 char *buf = parsefile->buf;
8446 #if ENABLE_FEATURE_EDITING
8447 if (!iflag || parsefile->fd)
8448 nr = safe_read(parsefile->fd, buf, BUFSIZ - 1);
8450 #if ENABLE_FEATURE_TAB_COMPLETION
8451 line_input_state->path_lookup = pathval();
8453 nr = read_line_input(cmdedit_prompt, buf, BUFSIZ, line_input_state);
8455 /* Ctrl+C pressed */
8464 if (nr < 0 && errno == 0) {
8465 /* Ctrl+D presend */
8470 nr = safe_read(parsefile->fd, buf, BUFSIZ - 1);
8474 if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
8475 int flags = fcntl(0, F_GETFL, 0);
8476 if (flags >= 0 && flags & O_NONBLOCK) {
8477 flags &=~ O_NONBLOCK;
8478 if (fcntl(0, F_SETFL, flags) >= 0) {
8479 out2str("sh: turning off NDELAY mode\n");
8489 * Refill the input buffer and return the next input character:
8491 * 1) If a string was pushed back on the input, pop it;
8492 * 2) If an EOF was pushed back (parsenleft == EOF_NLEFT) or we are reading
8493 * from a string so we can't refill the buffer, return EOF.
8494 * 3) If the is more stuff in this buffer, use it else call read to fill it.
8495 * 4) Process input up to the next newline, deleting nul characters.
8504 while (parsefile->strpush) {
8505 #if ENABLE_ASH_ALIAS
8506 if (parsenleft == -1 && parsefile->strpush->ap &&
8507 parsenextc[-1] != ' ' && parsenextc[-1] != '\t') {
8512 if (--parsenleft >= 0)
8513 return SC2INT(*parsenextc++);
8515 if (parsenleft == EOF_NLEFT || parsefile->buf == NULL)
8517 flush_stdout_stderr();
8524 parselleft = parsenleft = EOF_NLEFT;
8531 /* delete nul characters */
8539 memmove(q, q + 1, more);
8543 parsenleft = q - parsenextc - 1;
8549 parsenleft = q - parsenextc - 1;
8561 out2str(parsenextc);
8566 return SC2INT(*parsenextc++);
8569 #define pgetc_as_macro() (--parsenleft >= 0? SC2INT(*parsenextc++) : preadbuffer())
8571 #if ENABLE_ASH_OPTIMIZE_FOR_SIZE
8572 #define pgetc_macro() pgetc()
8576 return pgetc_as_macro();
8579 #define pgetc_macro() pgetc_as_macro()
8583 return pgetc_macro();
8588 * Same as pgetc(), but ignores PEOA.
8590 #if ENABLE_ASH_ALIAS
8598 } while (c == PEOA);
8605 return pgetc_macro();
8610 * Read a line from the script.
8613 pfgets(char *line, int len)
8619 while (--nleft > 0) {
8635 * Undo the last call to pgetc. Only one character may be pushed back.
8636 * PEOF may be pushed back.
8646 * Push a string back onto the input at this current parsefile level.
8647 * We handle aliases this way.
8650 pushstring(char *s, void *ap)
8657 /*dprintf("*** calling pushstring: %s, %d\n", s, len);*/
8658 if (parsefile->strpush) {
8659 sp = ckmalloc(sizeof(struct strpush));
8660 sp->prev = parsefile->strpush;
8661 parsefile->strpush = sp;
8663 sp = parsefile->strpush = &(parsefile->basestrpush);
8664 sp->prevstring = parsenextc;
8665 sp->prevnleft = parsenleft;
8666 #if ENABLE_ASH_ALIAS
8667 sp->ap = (struct alias *)ap;
8669 ((struct alias *)ap)->flag |= ALIASINUSE;
8679 * To handle the "." command, a stack of input files is used. Pushfile
8680 * adds a new entry to the stack and popfile restores the previous level.
8685 struct parsefile *pf;
8687 parsefile->nleft = parsenleft;
8688 parsefile->lleft = parselleft;
8689 parsefile->nextc = parsenextc;
8690 parsefile->linno = plinno;
8691 pf = ckmalloc(sizeof(*pf));
8692 pf->prev = parsefile;
8695 pf->basestrpush.prev = NULL;
8702 struct parsefile *pf = parsefile;
8711 parsefile = pf->prev;
8713 parsenleft = parsefile->nleft;
8714 parselleft = parsefile->lleft;
8715 parsenextc = parsefile->nextc;
8716 plinno = parsefile->linno;
8721 * Return to top level.
8726 while (parsefile != &basepf)
8731 * Close the file(s) that the shell is reading commands from. Called
8732 * after a fork is done.
8738 if (parsefile->fd > 0) {
8739 close(parsefile->fd);
8745 * Like setinputfile, but takes an open file descriptor. Call this with
8749 setinputfd(int fd, int push)
8751 fcntl(fd, F_SETFD, FD_CLOEXEC);
8757 if (parsefile->buf == NULL)
8758 parsefile->buf = ckmalloc(IBUFSIZ);
8759 parselleft = parsenleft = 0;
8764 * Set the input to take input from a file. If push is set, push the
8765 * old input onto the stack first.
8768 setinputfile(const char *fname, int flags)
8774 fd = open(fname, O_RDONLY);
8776 if (flags & INPUT_NOFILE_OK)
8778 ash_msg_and_raise_error("Can't open %s", fname);
8781 fd2 = copyfd(fd, 10);
8784 ash_msg_and_raise_error("Out of file descriptors");
8787 setinputfd(fd, flags & INPUT_PUSH_FILE);
8794 * Like setinputfile, but takes input from a string.
8797 setinputstring(char *string)
8801 parsenextc = string;
8802 parsenleft = strlen(string);
8803 parsefile->buf = NULL;
8809 /* ============ mail.c
8811 * Routines to check for mail.
8815 #define MAXMBOXES 10
8817 /* times of mailboxes */
8818 static time_t mailtime[MAXMBOXES];
8819 /* Set if MAIL or MAILPATH is changed. */
8820 static int mail_var_path_changed;
8823 * Print appropriate message(s) if mail has arrived.
8824 * If mail_var_path_changed is set,
8825 * then the value of MAIL has mail_var_path_changed,
8826 * so we just update the values.
8835 struct stackmark smark;
8838 setstackmark(&smark);
8839 mpath = mpathset() ? mpathval() : mailval();
8840 for (mtp = mailtime; mtp < mailtime + MAXMBOXES; mtp++) {
8841 p = padvance(&mpath, nullstr);
8846 for (q = p; *q; q++);
8851 q[-1] = '\0'; /* delete trailing '/' */
8852 if (stat(p, &statb) < 0) {
8856 if (!mail_var_path_changed && statb.st_mtime != *mtp) {
8859 pathopt ? pathopt : "you have mail"
8862 *mtp = statb.st_mtime;
8864 mail_var_path_changed = 0;
8865 popstackmark(&smark);
8869 changemail(const char *val)
8871 mail_var_path_changed++;
8873 #endif /* ASH_MAIL */
8876 /* ============ ??? */
8879 * Take commands from a file. To be compatible we should do a path
8880 * search for the file, which is necessary to find sub-commands.
8883 find_dot_file(char *name)
8886 const char *path = pathval();
8889 /* don't try this for absolute or relative paths */
8890 if (strchr(name, '/'))
8893 while ((fullname = padvance(&path, name)) != NULL) {
8894 if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) {
8896 * Don't bother freeing here, since it will
8897 * be freed by the caller.
8901 stunalloc(fullname);
8904 /* not found in the PATH */
8905 ash_msg_and_raise_error("%s: not found", name);
8910 * Controls whether the shell is interactive or not.
8913 setinteractive(int on)
8915 static int is_interactive;
8917 if (++on == is_interactive)
8919 is_interactive = on;
8923 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
8924 if (is_interactive > 1) {
8925 /* Looks like they want an interactive shell */
8926 static smallint do_banner;
8931 "%s Built-in shell (ash)\n"
8932 "Enter 'help' for a list of built-in commands."
8941 #if ENABLE_FEATURE_EDITING_VI
8942 #define setvimode(on) do { \
8943 if (on) line_input_state->flags |= VI_MODE; \
8944 else line_input_state->flags &= ~VI_MODE; \
8947 #define setvimode(on) viflag = 0 /* forcibly keep the option off */
8956 setinteractive(iflag);
8962 minus_o(char *name, int val)
8967 for (i = 0; i < NOPTS; i++) {
8968 if (strcmp(name, optnames(i)) == 0) {
8973 ash_msg_and_raise_error("Illegal option -o %s", name);
8975 out1str("Current option settings\n");
8976 for (i = 0; i < NOPTS; i++)
8977 out1fmt("%-16s%s\n", optnames(i),
8978 optlist[i] ? "on" : "off");
8982 setoption(int flag, int val)
8986 for (i = 0; i < NOPTS; i++) {
8987 if (optletters(i) == flag) {
8992 ash_msg_and_raise_error("Illegal option -%c", flag);
8997 * Process shell options. The global variable argptr contains a pointer
8998 * to the argument list; we advance it past the options.
9001 options(int cmdline)
9009 while ((p = *argptr) != NULL) {
9014 if (p[0] == '\0' || LONE_DASH(p)) {
9016 /* "-" means turn off -x and -v */
9019 /* "--" means reset params */
9020 else if (*argptr == NULL)
9023 break; /* "-" or "--" terminates options */
9025 } else if (c == '+') {
9031 while ((c = *p++) != '\0') {
9032 if (c == 'c' && cmdline) {
9033 minusc = p; /* command is after shell args*/
9034 } else if (c == 'o') {
9035 minus_o(*argptr, val);
9038 } else if (cmdline && (c == '-')) { // long options
9039 if (strcmp(p, "login") == 0)
9050 * Set the shell parameters.
9053 setparam(char **argv)
9059 for (nparam = 0; argv[nparam]; nparam++);
9060 ap = newparam = ckmalloc((nparam + 1) * sizeof(*ap));
9062 *ap++ = ckstrdup(*argv++);
9065 freeparam(&shellparam);
9066 shellparam.malloc = 1;
9067 shellparam.nparam = nparam;
9068 shellparam.p = newparam;
9069 #if ENABLE_ASH_GETOPTS
9070 shellparam.optind = 1;
9071 shellparam.optoff = -1;
9076 * Free the list of positional parameters.
9079 freeparam(volatile struct shparam *param)
9083 if (param->malloc) {
9084 for (ap = param->p; *ap; ap++)
9091 * The shift builtin command.
9094 shiftcmd(int argc, char **argv)
9101 n = number(argv[1]);
9102 if (n > shellparam.nparam)
9103 ash_msg_and_raise_error("can't shift that many");
9105 shellparam.nparam -= n;
9106 for (ap1 = shellparam.p; --n >= 0; ap1++) {
9107 if (shellparam.malloc)
9111 while ((*ap2++ = *ap1++) != NULL);
9112 #if ENABLE_ASH_GETOPTS
9113 shellparam.optind = 1;
9114 shellparam.optoff = -1;
9121 * POSIX requires that 'set' (but not export or readonly) output the
9122 * variables in lexicographic order - by the locale's collating order (sigh).
9123 * Maybe we could keep them in an ordered balanced binary tree
9124 * instead of hashed lists.
9125 * For now just roll 'em through qsort for printing...
9128 showvars(const char *sep_prefix, int on, int off)
9133 ep = listvars(on, off, &epend);
9134 qsort(ep, epend - ep, sizeof(char *), vpcmp);
9136 sep = *sep_prefix ? spcstr : sep_prefix;
9138 for (; ep < epend; ep++) {
9142 p = strchrnul(*ep, '=');
9145 q = single_quote(++p);
9146 out1fmt("%s%s%.*s%s\n", sep_prefix, sep, (int)(p - *ep), *ep, q);
9152 * The set command builtin.
9155 setcmd(int argc, char **argv)
9158 return showvars(nullstr, 0, VUNSET);
9162 if (*argptr != NULL) {
9169 #if ENABLE_ASH_RANDOM_SUPPORT
9170 /* Roughly copied from bash.. */
9172 change_random(const char *value)
9174 if (value == NULL) {
9175 /* "get", generate */
9178 rseed = rseed * 1103515245 + 12345;
9179 sprintf(buf, "%d", (unsigned int)((rseed & 32767)));
9180 /* set without recursion */
9181 setvar(vrandom.text, buf, VNOFUNC);
9182 vrandom.flags &= ~VNOFUNC;
9185 rseed = strtoul(value, (char **)NULL, 10);
9190 #if ENABLE_ASH_GETOPTS
9192 getopts(char *optstr, char *optvar, char **optfirst, int *param_optind, int *optoff)
9201 if (*param_optind < 1)
9203 optnext = optfirst + *param_optind - 1;
9205 if (*param_optind <= 1 || *optoff < 0 || strlen(optnext[-1]) < *optoff)
9208 p = optnext[-1] + *optoff;
9209 if (p == NULL || *p == '\0') {
9210 /* Current word is done, advance */
9212 if (p == NULL || *p != '-' || *++p == '\0') {
9219 if (LONE_DASH(p)) /* check for "--" */
9224 for (q = optstr; *q != c; ) {
9226 if (optstr[0] == ':') {
9229 err |= setvarsafe("OPTARG", s, 0);
9231 fprintf(stderr, "Illegal option -%c\n", c);
9242 if (*p == '\0' && (p = *optnext) == NULL) {
9243 if (optstr[0] == ':') {
9246 err |= setvarsafe("OPTARG", s, 0);
9249 fprintf(stderr, "No arg for -%c option\n", c);
9258 err |= setvarsafe("OPTARG", p, 0);
9261 err |= setvarsafe("OPTARG", nullstr, 0);
9263 *optoff = p ? p - *(optnext - 1) : -1;
9264 *param_optind = optnext - optfirst + 1;
9265 fmtstr(s, sizeof(s), "%d", *param_optind);
9266 err |= setvarsafe("OPTIND", s, VNOFUNC);
9269 err |= setvarsafe(optvar, s, 0);
9273 flush_stdout_stderr();
9274 raise_exception(EXERROR);
9280 * The getopts builtin. Shellparam.optnext points to the next argument
9281 * to be processed. Shellparam.optptr points to the next character to
9282 * be processed in the current argument. If shellparam.optnext is NULL,
9283 * then it's the first time getopts has been called.
9286 getoptscmd(int argc, char **argv)
9291 ash_msg_and_raise_error("Usage: getopts optstring var [arg]");
9293 optbase = shellparam.p;
9294 if (shellparam.optind > shellparam.nparam + 1) {
9295 shellparam.optind = 1;
9296 shellparam.optoff = -1;
9300 if (shellparam.optind > argc - 2) {
9301 shellparam.optind = 1;
9302 shellparam.optoff = -1;
9306 return getopts(argv[1], argv[2], optbase, &shellparam.optind,
9307 &shellparam.optoff);
9309 #endif /* ASH_GETOPTS */
9312 /* ============ Shell parser */
9314 static int tokpushback; /* last token pushed back */
9315 #define NEOF ((union node *)&tokpushback)
9316 static int parsebackquote; /* nonzero if we are inside backquotes */
9317 static int lasttoken; /* last token read */
9318 static char *wordtext; /* text of last word returned by readtoken */
9319 static struct nodelist *backquotelist;
9320 static union node *redirnode;
9321 static struct heredoc *heredoc;
9322 static int quoteflag; /* set if (part of) last token was quoted */
9324 static void raise_error_syntax(const char *) ATTRIBUTE_NORETURN;
9326 raise_error_syntax(const char *msg)
9328 ash_msg_and_raise_error("Syntax error: %s", msg);
9333 * Called when an unexpected token is read during the parse. The argument
9334 * is the token that is expected, or -1 if more than one type of token can
9335 * occur at this point.
9337 static void raise_error_unexpected_syntax(int) ATTRIBUTE_NORETURN;
9339 raise_error_unexpected_syntax(int token)
9344 l = sprintf(msg, "%s unexpected", tokname(lasttoken));
9346 sprintf(msg + l, " (expecting %s)", tokname(token));
9347 raise_error_syntax(msg);
9351 #define EOFMARKLEN 79
9354 struct heredoc *next; /* next here document in list */
9355 union node *here; /* redirection node */
9356 char *eofmark; /* string indicating end of input */
9357 int striptabs; /* if set, strip leading tabs */
9360 static struct heredoc *heredoclist; /* list of here documents to read */
9362 /* parsing is heavily cross-recursive, need these forward decls */
9363 static union node *andor(void);
9364 static union node *pipeline(void);
9365 static union node *parse_command(void);
9366 static void parseheredoc(void);
9367 static char peektoken(void);
9368 static int readtoken(void);
9373 union node *n1, *n2, *n3;
9376 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9377 if (nlflag == 2 && peektoken())
9383 if (tok == TBACKGND) {
9384 if (n2->type == NPIPE) {
9385 n2->npipe.backgnd = 1;
9387 if (n2->type != NREDIR) {
9388 n3 = stalloc(sizeof(struct nredir));
9390 n3->nredir.redirect = NULL;
9393 n2->type = NBACKGND;
9399 n3 = stalloc(sizeof(struct nbinary));
9401 n3->nbinary.ch1 = n1;
9402 n3->nbinary.ch2 = n2;
9418 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9426 pungetc(); /* push back EOF on input */
9430 raise_error_unexpected_syntax(-1);
9440 union node *n1, *n2, *n3;
9448 } else if (t == TOR) {
9454 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9456 n3 = stalloc(sizeof(struct nbinary));
9458 n3->nbinary.ch1 = n1;
9459 n3->nbinary.ch2 = n2;
9467 union node *n1, *n2, *pipenode;
9468 struct nodelist *lp, *prev;
9472 TRACE(("pipeline: entered\n"));
9473 if (readtoken() == TNOT) {
9475 checkkwd = CHKKWD | CHKALIAS;
9478 n1 = parse_command();
9479 if (readtoken() == TPIPE) {
9480 pipenode = stalloc(sizeof(struct npipe));
9481 pipenode->type = NPIPE;
9482 pipenode->npipe.backgnd = 0;
9483 lp = stalloc(sizeof(struct nodelist));
9484 pipenode->npipe.cmdlist = lp;
9488 lp = stalloc(sizeof(struct nodelist));
9489 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9490 lp->n = parse_command();
9492 } while (readtoken() == TPIPE);
9498 n2 = stalloc(sizeof(struct nnot));
9511 n = stalloc(sizeof(struct narg));
9513 n->narg.next = NULL;
9514 n->narg.text = wordtext;
9515 n->narg.backquote = backquotelist;
9520 fixredir(union node *n, const char *text, int err)
9522 TRACE(("Fix redir %s %d\n", text, err));
9524 n->ndup.vname = NULL;
9526 if (isdigit(text[0]) && text[1] == '\0')
9527 n->ndup.dupfd = text[0] - '0';
9528 else if (LONE_DASH(text))
9532 raise_error_syntax("Bad fd number");
9533 n->ndup.vname = makename();
9538 * Returns true if the text contains nothing to expand (no dollar signs
9542 noexpand(char *text)
9548 while ((c = *p++) != '\0') {
9549 if (c == CTLQUOTEMARK)
9553 else if (SIT(c, BASESYNTAX) == CCTL)
9562 union node *n = redirnode;
9564 if (readtoken() != TWORD)
9565 raise_error_unexpected_syntax(-1);
9566 if (n->type == NHERE) {
9567 struct heredoc *here = heredoc;
9573 TRACE(("Here document %d\n", n->type));
9574 if (!noexpand(wordtext) || (i = strlen(wordtext)) == 0 || i > EOFMARKLEN)
9575 raise_error_syntax("Illegal eof marker for << redirection");
9576 rmescapes(wordtext);
9577 here->eofmark = wordtext;
9579 if (heredoclist == NULL)
9582 for (p = heredoclist; p->next; p = p->next);
9585 } else if (n->type == NTOFD || n->type == NFROMFD) {
9586 fixredir(n, wordtext, 0);
9588 n->nfile.fname = makename();
9595 union node *args, **app;
9596 union node *n = NULL;
9597 union node *vars, **vpp;
9598 union node **rpp, *redir;
9608 savecheckkwd = CHKALIAS;
9610 checkkwd = savecheckkwd;
9611 switch (readtoken()) {
9613 n = stalloc(sizeof(struct narg));
9615 n->narg.text = wordtext;
9616 n->narg.backquote = backquotelist;
9617 if (savecheckkwd && isassignment(wordtext)) {
9619 vpp = &n->narg.next;
9622 app = &n->narg.next;
9627 *rpp = n = redirnode;
9628 rpp = &n->nfile.next;
9629 parsefname(); /* read name of redirection file */
9632 if (args && app == &args->narg.next
9635 struct builtincmd *bcmd;
9638 /* We have a function */
9639 if (readtoken() != TRP)
9640 raise_error_unexpected_syntax(TRP);
9641 name = n->narg.text;
9643 || ((bcmd = find_builtin(name)) && IS_BUILTIN_SPECIAL(bcmd))
9645 raise_error_syntax("Bad function name");
9648 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9649 n->narg.next = parse_command();
9662 n = stalloc(sizeof(struct ncmd));
9664 n->ncmd.args = args;
9665 n->ncmd.assign = vars;
9666 n->ncmd.redirect = redir;
9673 union node *n1, *n2;
9674 union node *ap, **app;
9675 union node *cp, **cpp;
9676 union node *redir, **rpp;
9683 switch (readtoken()) {
9685 raise_error_unexpected_syntax(-1);
9688 n1 = stalloc(sizeof(struct nif));
9690 n1->nif.test = list(0);
9691 if (readtoken() != TTHEN)
9692 raise_error_unexpected_syntax(TTHEN);
9693 n1->nif.ifpart = list(0);
9695 while (readtoken() == TELIF) {
9696 n2->nif.elsepart = stalloc(sizeof(struct nif));
9697 n2 = n2->nif.elsepart;
9699 n2->nif.test = list(0);
9700 if (readtoken() != TTHEN)
9701 raise_error_unexpected_syntax(TTHEN);
9702 n2->nif.ifpart = list(0);
9704 if (lasttoken == TELSE)
9705 n2->nif.elsepart = list(0);
9707 n2->nif.elsepart = NULL;
9715 n1 = stalloc(sizeof(struct nbinary));
9716 n1->type = (lasttoken == TWHILE) ? NWHILE : NUNTIL;
9717 n1->nbinary.ch1 = list(0);
9720 TRACE(("expecting DO got %s %s\n", tokname(got),
9721 got == TWORD ? wordtext : ""));
9722 raise_error_unexpected_syntax(TDO);
9724 n1->nbinary.ch2 = list(0);
9729 if (readtoken() != TWORD || quoteflag || ! goodname(wordtext))
9730 raise_error_syntax("Bad for loop variable");
9731 n1 = stalloc(sizeof(struct nfor));
9733 n1->nfor.var = wordtext;
9734 checkkwd = CHKKWD | CHKALIAS;
9735 if (readtoken() == TIN) {
9737 while (readtoken() == TWORD) {
9738 n2 = stalloc(sizeof(struct narg));
9740 n2->narg.text = wordtext;
9741 n2->narg.backquote = backquotelist;
9743 app = &n2->narg.next;
9747 if (lasttoken != TNL && lasttoken != TSEMI)
9748 raise_error_unexpected_syntax(-1);
9750 n2 = stalloc(sizeof(struct narg));
9752 n2->narg.text = (char *)dolatstr;
9753 n2->narg.backquote = NULL;
9754 n2->narg.next = NULL;
9757 * Newline or semicolon here is optional (but note
9758 * that the original Bourne shell only allowed NL).
9760 if (lasttoken != TNL && lasttoken != TSEMI)
9763 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9764 if (readtoken() != TDO)
9765 raise_error_unexpected_syntax(TDO);
9766 n1->nfor.body = list(0);
9770 n1 = stalloc(sizeof(struct ncase));
9772 if (readtoken() != TWORD)
9773 raise_error_unexpected_syntax(TWORD);
9774 n1->ncase.expr = n2 = stalloc(sizeof(struct narg));
9776 n2->narg.text = wordtext;
9777 n2->narg.backquote = backquotelist;
9778 n2->narg.next = NULL;
9780 checkkwd = CHKKWD | CHKALIAS;
9781 } while (readtoken() == TNL);
9782 if (lasttoken != TIN)
9783 raise_error_unexpected_syntax(TIN);
9784 cpp = &n1->ncase.cases;
9786 checkkwd = CHKNL | CHKKWD;
9788 while (t != TESAC) {
9789 if (lasttoken == TLP)
9791 *cpp = cp = stalloc(sizeof(struct nclist));
9793 app = &cp->nclist.pattern;
9795 *app = ap = stalloc(sizeof(struct narg));
9797 ap->narg.text = wordtext;
9798 ap->narg.backquote = backquotelist;
9799 if (readtoken() != TPIPE)
9801 app = &ap->narg.next;
9804 ap->narg.next = NULL;
9805 if (lasttoken != TRP)
9806 raise_error_unexpected_syntax(TRP);
9807 cp->nclist.body = list(2);
9809 cpp = &cp->nclist.next;
9811 checkkwd = CHKNL | CHKKWD;
9815 raise_error_unexpected_syntax(TENDCASE);
9822 n1 = stalloc(sizeof(struct nredir));
9823 n1->type = NSUBSHELL;
9824 n1->nredir.n = list(0);
9825 n1->nredir.redirect = NULL;
9838 if (readtoken() != t)
9839 raise_error_unexpected_syntax(t);
9842 /* Now check for redirection which may follow command */
9843 checkkwd = CHKKWD | CHKALIAS;
9845 while (readtoken() == TREDIR) {
9846 *rpp = n2 = redirnode;
9847 rpp = &n2->nfile.next;
9853 if (n1->type != NSUBSHELL) {
9854 n2 = stalloc(sizeof(struct nredir));
9859 n1->nredir.redirect = redir;
9865 * If eofmark is NULL, read a word or a redirection symbol. If eofmark
9866 * is not NULL, read a here document. In the latter case, eofmark is the
9867 * word which marks the end of the document and striptabs is true if
9868 * leading tabs should be stripped from the document. The argument firstc
9869 * is the first character of the input token or document.
9871 * Because C does not have internal subroutines, I have simulated them
9872 * using goto's to implement the subroutine linkage. The following macros
9873 * will run code that appears at the end of readtoken1.
9876 static int parsebackquote; /* nonzero if we are inside backquotes */
9878 #define CHECKEND() {goto checkend; checkend_return:;}
9879 #define PARSEREDIR() {goto parseredir; parseredir_return:;}
9880 #define PARSESUB() {goto parsesub; parsesub_return:;}
9881 #define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
9882 #define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
9883 #define PARSEARITH() {goto parsearith; parsearith_return:;}
9886 readtoken1(int firstc, int syntax, char *eofmark, int striptabs)
9891 char line[EOFMARKLEN + 1];
9892 struct nodelist *bqlist = 0;
9895 int varnest = 0; /* levels of variables expansion */
9896 int arinest = 0; /* levels of arithmetic expansion */
9897 int parenlevel = 0; /* levels of parens in arithmetic */
9898 int dqvarnest = 0; /* levels of variables expansion within double quotes */
9900 int prevsyntax = 0; /* syntax before arithmetic */
9902 /* Avoid longjmp clobbering */
9915 startlinno = plinno;
9917 if (syntax == DQSYNTAX)
9927 loop: { /* for each line, until end of word */
9928 CHECKEND(); /* set c to PEOF if at end of here document */
9929 for (;;) { /* until end of line or end of word */
9930 CHECKSTRSPACE(4, out); /* permit 4 calls to USTPUTC */
9931 switch (SIT(c, syntax)) {
9932 case CNL: /* '\n' */
9933 if (syntax == BASESYNTAX)
9934 goto endword; /* exit outer loop */
9940 goto loop; /* continue outer loop */
9945 if (eofmark == NULL || dblquote)
9946 USTPUTC(CTLESC, out);
9949 case CBACK: /* backslash */
9952 USTPUTC(CTLESC, out);
9955 } else if (c == '\n') {
9960 c != '\\' && c != '`' &&
9965 USTPUTC(CTLESC, out);
9968 if (SIT(c, SQSYNTAX) == CCTL)
9969 USTPUTC(CTLESC, out);
9977 if (eofmark == NULL) {
9978 USTPUTC(CTLQUOTEMARK, out);
9986 if (eofmark != NULL && arinest == 0
9991 if (dqvarnest == 0) {
9992 syntax = BASESYNTAX;
9999 case CVAR: /* '$' */
10000 PARSESUB(); /* parse substitution */
10002 case CENDVAR: /* '}' */
10005 if (dqvarnest > 0) {
10008 USTPUTC(CTLENDVAR, out);
10013 #if ENABLE_ASH_MATH_SUPPORT
10014 case CLP: /* '(' in arithmetic */
10018 case CRP: /* ')' in arithmetic */
10019 if (parenlevel > 0) {
10023 if (pgetc() == ')') {
10024 if (--arinest == 0) {
10025 USTPUTC(CTLENDARI, out);
10026 syntax = prevsyntax;
10027 if (syntax == DQSYNTAX)
10035 * unbalanced parens
10036 * (don't 2nd guess - no error)
10044 case CBQUOTE: /* '`' */
10048 goto endword; /* exit outer loop */
10053 goto endword; /* exit outer loop */
10054 #if ENABLE_ASH_ALIAS
10064 #if ENABLE_ASH_MATH_SUPPORT
10065 if (syntax == ARISYNTAX)
10066 raise_error_syntax("Missing '))'");
10068 if (syntax != BASESYNTAX && !parsebackquote && eofmark == NULL)
10069 raise_error_syntax("Unterminated quoted string");
10070 if (varnest != 0) {
10071 startlinno = plinno;
10073 raise_error_syntax("Missing '}'");
10075 USTPUTC('\0', out);
10076 len = out - (char *)stackblock();
10077 out = stackblock();
10078 if (eofmark == NULL) {
10079 if ((c == '>' || c == '<')
10082 && (*out == '\0' || isdigit(*out))) {
10084 return lasttoken = TREDIR;
10089 quoteflag = quotef;
10090 backquotelist = bqlist;
10091 grabstackblock(len);
10095 /* end of readtoken routine */
10099 * Check to see whether we are at the end of the here document. When this
10100 * is called, c is set to the first character of the next input line. If
10101 * we are at the end of the here document, this routine sets the c to PEOF.
10105 #if ENABLE_ASH_ALIAS
10111 while (c == '\t') {
10115 if (c == *eofmark) {
10116 if (pfgets(line, sizeof(line)) != NULL) {
10120 for (q = eofmark + 1; *q && *p == *q; p++, q++);
10121 if (*p == '\n' && *q == '\0') {
10124 needprompt = doprompt;
10126 pushstring(line, NULL);
10131 goto checkend_return;
10136 * Parse a redirection operator. The variable "out" points to a string
10137 * specifying the fd to be redirected. The variable "c" contains the
10138 * first character of the redirection operator.
10144 np = stalloc(sizeof(struct nfile));
10149 np->type = NAPPEND;
10151 np->type = NCLOBBER;
10158 } else { /* c == '<' */
10163 if (sizeof(struct nfile) != sizeof(struct nhere)) {
10164 np = stalloc(sizeof(struct nhere));
10168 heredoc = stalloc(sizeof(struct heredoc));
10169 heredoc->here = np;
10172 heredoc->striptabs = 1;
10174 heredoc->striptabs = 0;
10180 np->type = NFROMFD;
10184 np->type = NFROMTO;
10194 np->nfile.fd = fd - '0';
10196 goto parseredir_return;
10201 * Parse a substitution. At this point, we have read the dollar sign
10202 * and nothing else.
10209 static const char types[] = "}-+?=";
10213 c <= PEOA_OR_PEOF ||
10214 (c != '(' && c != '{' && !is_name(c) && !is_special(c))
10218 } else if (c == '(') { /* $(command) or $((arith)) */
10219 if (pgetc() == '(') {
10220 #if ENABLE_ASH_MATH_SUPPORT
10223 raise_error_syntax("We unsupport $((arith))");
10230 USTPUTC(CTLVAR, out);
10231 typeloc = out - (char *)stackblock();
10232 USTPUTC(VSNORMAL, out);
10233 subtype = VSNORMAL;
10241 subtype = VSLENGTH;
10245 if (c > PEOA_OR_PEOF && is_name(c)) {
10249 } while (c > PEOA_OR_PEOF && is_in_name(c));
10250 } else if (isdigit(c)) {
10254 } while (isdigit(c));
10255 } else if (is_special(c)) {
10259 badsub: raise_error_syntax("Bad substitution");
10263 if (subtype == 0) {
10270 p = strchr(types, c);
10273 subtype = p - types + VSNORMAL;
10279 subtype = c == '#' ? VSTRIMLEFT :
10292 if (dblquote || arinest)
10294 *((char *)stackblock() + typeloc) = subtype | flags;
10295 if (subtype != VSNORMAL) {
10297 if (dblquote || arinest) {
10302 goto parsesub_return;
10307 * Called to parse command substitutions. Newstyle is set if the command
10308 * is enclosed inside $(...); nlpp is a pointer to the head of the linked
10309 * list of commands (passed by reference), and savelen is the number of
10310 * characters on the top of the stack which must be preserved.
10313 struct nodelist **nlpp;
10316 char *volatile str;
10317 struct jmploc jmploc;
10318 struct jmploc *volatile savehandler;
10320 int saveprompt = 0;
10322 (void) &saveprompt;
10325 savepbq = parsebackquote;
10326 if (setjmp(jmploc.loc)) {
10329 parsebackquote = 0;
10330 exception_handler = savehandler;
10331 longjmp(exception_handler->loc, 1);
10335 savelen = out - (char *)stackblock();
10337 str = ckmalloc(savelen);
10338 memcpy(str, stackblock(), savelen);
10340 savehandler = exception_handler;
10341 exception_handler = &jmploc;
10344 /* We must read until the closing backquote, giving special
10345 treatment to some slashes, and then push the string and
10346 reread it as input, interpreting it normally. */
10353 STARTSTACKSTR(pout);
10370 * If eating a newline, avoid putting
10371 * the newline into the new character
10372 * stream (via the STPUTC after the
10377 if (pc != '\\' && pc != '`' && pc != '$'
10378 && (!dblquote || pc != '"'))
10379 STPUTC('\\', pout);
10380 if (pc > PEOA_OR_PEOF) {
10386 #if ENABLE_ASH_ALIAS
10389 startlinno = plinno;
10390 raise_error_syntax("EOF in backquote substitution");
10394 needprompt = doprompt;
10403 STPUTC('\0', pout);
10404 psavelen = pout - (char *)stackblock();
10405 if (psavelen > 0) {
10406 pstr = grabstackstr(pout);
10407 setinputstring(pstr);
10412 nlpp = &(*nlpp)->next;
10413 *nlpp = stalloc(sizeof(**nlpp));
10414 (*nlpp)->next = NULL;
10415 parsebackquote = oldstyle;
10418 saveprompt = doprompt;
10425 doprompt = saveprompt;
10426 else if (readtoken() != TRP)
10427 raise_error_unexpected_syntax(TRP);
10432 * Start reading from old file again, ignoring any pushed back
10433 * tokens left from the backquote parsing
10438 while (stackblocksize() <= savelen)
10440 STARTSTACKSTR(out);
10442 memcpy(out, str, savelen);
10443 STADJUST(savelen, out);
10449 parsebackquote = savepbq;
10450 exception_handler = savehandler;
10451 if (arinest || dblquote)
10452 USTPUTC(CTLBACKQ | CTLQUOTE, out);
10454 USTPUTC(CTLBACKQ, out);
10456 goto parsebackq_oldreturn;
10457 goto parsebackq_newreturn;
10460 #if ENABLE_ASH_MATH_SUPPORT
10462 * Parse an arithmetic expansion (indicate start of one and set state)
10465 if (++arinest == 1) {
10466 prevsyntax = syntax;
10467 syntax = ARISYNTAX;
10468 USTPUTC(CTLARI, out);
10475 * we collapse embedded arithmetic expansion to
10476 * parenthesis, which should be equivalent
10480 goto parsearith_return;
10484 } /* end of readtoken */
10487 * Read the next input token.
10488 * If the token is a word, we set backquotelist to the list of cmds in
10489 * backquotes. We set quoteflag to true if any part of the word was
10491 * If the token is TREDIR, then we set redirnode to a structure containing
10493 * In all cases, the variable startlinno is set to the number of the line
10494 * on which the token starts.
10496 * [Change comment: here documents and internal procedures]
10497 * [Readtoken shouldn't have any arguments. Perhaps we should make the
10498 * word parsing code into a separate routine. In this case, readtoken
10499 * doesn't need to have any internal procedures, but parseword does.
10500 * We could also make parseoperator in essence the main routine, and
10501 * have parseword (readtoken1?) handle both words and redirection.]
10503 #define NEW_xxreadtoken
10504 #ifdef NEW_xxreadtoken
10505 /* singles must be first! */
10506 static const char xxreadtoken_chars[7] = { '\n', '(', ')', '&', '|', ';', 0 };
10508 static const char xxreadtoken_tokens[] = {
10509 TNL, TLP, TRP, /* only single occurrence allowed */
10510 TBACKGND, TPIPE, TSEMI, /* if single occurrence */
10511 TEOF, /* corresponds to trailing nul */
10512 TAND, TOR, TENDCASE, /* if double occurrence */
10515 #define xxreadtoken_doubles \
10516 (sizeof(xxreadtoken_tokens) - sizeof(xxreadtoken_chars))
10517 #define xxreadtoken_singles \
10518 (sizeof(xxreadtoken_chars) - xxreadtoken_doubles - 1)
10532 startlinno = plinno;
10533 for (;;) { /* until token or start of word found */
10536 if ((c != ' ') && (c != '\t')
10537 #if ENABLE_ASH_ALIAS
10542 while ((c = pgetc()) != '\n' && c != PEOF);
10544 } else if (c == '\\') {
10545 if (pgetc() != '\n') {
10549 startlinno = ++plinno;
10554 = xxreadtoken_chars + sizeof(xxreadtoken_chars) - 1;
10559 needprompt = doprompt;
10562 p = strchr(xxreadtoken_chars, c);
10565 return readtoken1(c, BASESYNTAX, (char *) NULL, 0);
10568 if (p - xxreadtoken_chars >= xxreadtoken_singles) {
10569 if (pgetc() == *p) { /* double occurrence? */
10570 p += xxreadtoken_doubles + 1;
10576 return lasttoken = xxreadtoken_tokens[p - xxreadtoken_chars];
10582 #define RETURN(token) return lasttoken = token
10595 startlinno = plinno;
10596 for (;;) { /* until token or start of word found */
10599 case ' ': case '\t':
10600 #if ENABLE_ASH_ALIAS
10605 while ((c = pgetc()) != '\n' && c != PEOF);
10609 if (pgetc() == '\n') {
10610 startlinno = ++plinno;
10619 needprompt = doprompt;
10624 if (pgetc() == '&')
10629 if (pgetc() == '|')
10634 if (pgetc() == ';')
10647 return readtoken1(c, BASESYNTAX, (char *)NULL, 0);
10650 #endif /* NEW_xxreadtoken */
10657 int alreadyseen = tokpushback;
10660 #if ENABLE_ASH_ALIAS
10669 if (checkkwd & CHKNL) {
10676 if (t != TWORD || quoteflag) {
10681 * check for keywords
10683 if (checkkwd & CHKKWD) {
10684 const char *const *pp;
10686 pp = findkwd(wordtext);
10688 lasttoken = t = pp - tokname_array;
10689 TRACE(("keyword %s recognized\n", tokname(t)));
10694 if (checkkwd & CHKALIAS) {
10695 #if ENABLE_ASH_ALIAS
10697 ap = lookupalias(wordtext, 1);
10700 pushstring(ap->val, ap);
10710 TRACE(("token %s %s\n", tokname(t), t == TWORD ? wordtext : ""));
10712 TRACE(("reread token %s %s\n", tokname(t), t == TWORD ? wordtext : ""));
10724 return tokname_array[t][0];
10728 * Read and parse a command. Returns NEOF on end of file. (NULL is a
10729 * valid parse tree indicating a blank line.)
10731 static union node *
10732 parsecmd(int interact)
10737 doprompt = interact;
10739 setprompt(doprompt);
10751 * Input any here documents.
10756 struct heredoc *here;
10759 here = heredoclist;
10766 readtoken1(pgetc(), here->here->type == NHERE? SQSYNTAX : DQSYNTAX,
10767 here->eofmark, here->striptabs);
10768 n = stalloc(sizeof(struct narg));
10769 n->narg.type = NARG;
10770 n->narg.next = NULL;
10771 n->narg.text = wordtext;
10772 n->narg.backquote = backquotelist;
10773 here->here->nhere.doc = n;
10780 * called by editline -- any expansions to the prompt
10781 * should be added here.
10783 #if ENABLE_ASH_EXPAND_PRMT
10784 static const char *
10785 expandstr(const char *ps)
10789 /* XXX Fix (char *) cast. */
10790 setinputstring((char *)ps);
10791 readtoken1(pgetc(), DQSYNTAX, nullstr, 0);
10794 n.narg.type = NARG;
10795 n.narg.next = NULL;
10796 n.narg.text = wordtext;
10797 n.narg.backquote = backquotelist;
10799 expandarg(&n, NULL, 0);
10800 return stackblock();
10806 * Execute a command or commands contained in a string.
10809 evalstring(char *s, int mask)
10812 struct stackmark smark;
10816 setstackmark(&smark);
10819 while ((n = parsecmd(0)) != NEOF) {
10821 popstackmark(&smark);
10834 * The eval command.
10837 evalcmd(int argc, char **argv)
10846 STARTSTACKSTR(concat);
10849 concat = stack_putstr(p, concat);
10853 STPUTC(' ', concat);
10855 STPUTC('\0', concat);
10856 p = grabstackstr(concat);
10858 evalstring(p, ~SKIPEVAL);
10865 * Read and execute commands. "Top" is nonzero for the top level command
10866 * loop; it turns on prompting if the shell is interactive.
10872 struct stackmark smark;
10876 TRACE(("cmdloop(%d) called\n", top));
10880 setstackmark(&smark);
10883 showjobs(stderr, SHOW_CHANGED);
10886 if (iflag && top) {
10888 #if ENABLE_ASH_MAIL
10892 n = parsecmd(inter);
10893 /* showtree(n); DEBUG */
10895 if (!top || numeof >= 50)
10897 if (!stoppedjobs()) {
10900 out2str("\nUse \"exit\" to leave shell.\n");
10903 } else if (nflag == 0) {
10904 job_warning = (job_warning == 2) ? 1 : 0;
10908 popstackmark(&smark);
10913 return skip & SKIPEVAL;
10920 dotcmd(int argc, char **argv)
10922 struct strlist *sp;
10923 volatile struct shparam saveparam;
10926 for (sp = cmdenviron; sp; sp = sp->next)
10927 setvareq(xstrdup(sp->text), VSTRFIXED | VTEXTFIXED);
10929 if (argc >= 2) { /* That's what SVR2 does */
10932 fullname = find_dot_file(argv[1]);
10935 saveparam = shellparam;
10936 shellparam.malloc = 0;
10937 shellparam.nparam = argc - 2;
10938 shellparam.p = argv + 2;
10941 setinputfile(fullname, INPUT_PUSH_FILE);
10942 commandname = fullname;
10947 freeparam(&shellparam);
10948 shellparam = saveparam;
10950 status = exitstatus;
10956 exitcmd(int argc, char **argv)
10961 exitstatus = number(argv[1]);
10962 raise_exception(EXEXIT);
10966 #if ENABLE_ASH_BUILTIN_ECHO
10968 echocmd(int argc, char **argv)
10970 return bb_echo(argv);
10974 #if ENABLE_ASH_BUILTIN_TEST
10976 testcmd(int argc, char **argv)
10978 return bb_test(argc, argv);
10983 * Read a file containing shell functions.
10986 readcmdfile(char *name)
10988 setinputfile(name, INPUT_PUSH_FILE);
10994 /* ============ redir.c */
10997 * Code for dealing with input/output redirection.
11000 #define EMPTY -2 /* marks an unused slot in redirtab */
11002 # define PIPESIZE 4096 /* amount of buffering in a pipe */
11004 # define PIPESIZE PIPE_BUF
11008 * Open a file in noclobber mode.
11009 * The code was copied from bash.
11012 noclobberopen(const char *fname)
11015 struct stat finfo, finfo2;
11018 * If the file exists and is a regular file, return an error
11021 r = stat(fname, &finfo);
11022 if (r == 0 && S_ISREG(finfo.st_mode)) {
11028 * If the file was not present (r != 0), make sure we open it
11029 * exclusively so that if it is created before we open it, our open
11030 * will fail. Make sure that we do not truncate an existing file.
11031 * Note that we don't turn on O_EXCL unless the stat failed -- if the
11032 * file was not a regular file, we leave O_EXCL off.
11035 return open(fname, O_WRONLY|O_CREAT|O_EXCL, 0666);
11036 fd = open(fname, O_WRONLY|O_CREAT, 0666);
11038 /* If the open failed, return the file descriptor right away. */
11043 * OK, the open succeeded, but the file may have been changed from a
11044 * non-regular file to a regular file between the stat and the open.
11045 * We are assuming that the O_EXCL open handles the case where FILENAME
11046 * did not exist and is symlinked to an existing file between the stat
11051 * If we can open it and fstat the file descriptor, and neither check
11052 * revealed that it was a regular file, and the file has not been
11053 * replaced, return the file descriptor.
11055 if (fstat(fd, &finfo2) == 0 && !S_ISREG(finfo2.st_mode)
11056 && finfo.st_dev == finfo2.st_dev && finfo.st_ino == finfo2.st_ino)
11059 /* The file has been replaced. badness. */
11066 * Handle here documents. Normally we fork off a process to write the
11067 * data to a pipe. If the document is short, we can stuff the data in
11068 * the pipe without forking.
11071 openhere(union node *redir)
11077 ash_msg_and_raise_error("Pipe call failed");
11078 if (redir->type == NHERE) {
11079 len = strlen(redir->nhere.doc->narg.text);
11080 if (len <= PIPESIZE) {
11081 full_write(pip[1], redir->nhere.doc->narg.text, len);
11085 if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) {
11087 signal(SIGINT, SIG_IGN);
11088 signal(SIGQUIT, SIG_IGN);
11089 signal(SIGHUP, SIG_IGN);
11091 signal(SIGTSTP, SIG_IGN);
11093 signal(SIGPIPE, SIG_DFL);
11094 if (redir->type == NHERE)
11095 full_write(pip[1], redir->nhere.doc->narg.text, len);
11097 expandhere(redir->nhere.doc, pip[1]);
11106 openredirect(union node *redir)
11111 switch (redir->nfile.type) {
11113 fname = redir->nfile.expfname;
11114 f = open(fname, O_RDONLY);
11119 fname = redir->nfile.expfname;
11120 f = open(fname, O_RDWR|O_CREAT|O_TRUNC, 0666);
11125 /* Take care of noclobber mode. */
11127 fname = redir->nfile.expfname;
11128 f = noclobberopen(fname);
11135 fname = redir->nfile.expfname;
11136 f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666);
11141 fname = redir->nfile.expfname;
11142 f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666);
11150 /* Fall through to eliminate warning. */
11157 f = openhere(redir);
11163 ash_msg_and_raise_error("cannot create %s: %s", fname, errmsg(errno, "Directory nonexistent"));
11165 ash_msg_and_raise_error("cannot open %s: %s", fname, errmsg(errno, "No such file"));
11169 dupredirect(union node *redir, int f)
11171 int fd = redir->nfile.fd;
11173 if (redir->nfile.type == NTOFD || redir->nfile.type == NFROMFD) {
11174 if (redir->ndup.dupfd >= 0) { /* if not ">&-" */
11175 copyfd(redir->ndup.dupfd, fd);
11188 * Process a list of redirection commands. If the REDIR_PUSH flag is set,
11189 * old file descriptors are stashed away so that the redirection can be
11190 * undone by calling popredir. If the REDIR_BACKQ flag is set, then the
11191 * standard output, and the standard error if it becomes a duplicate of
11192 * stdout, is saved in memory.
11195 redirect(union node *redir, int flags)
11198 struct redirtab *sv;
11209 if (flags & REDIR_PUSH) {
11210 struct redirtab *q;
11211 q = ckmalloc(sizeof(struct redirtab));
11212 q->next = redirlist;
11214 q->nullredirs = nullredirs - 1;
11215 for (i = 0; i < 10; i++)
11216 q->renamed[i] = EMPTY;
11223 if ((n->nfile.type == NTOFD || n->nfile.type == NFROMFD)
11224 && n->ndup.dupfd == fd)
11225 continue; /* redirect from/to same file descriptor */
11227 newfd = openredirect(n);
11230 if (sv && *(p = &sv->renamed[fd]) == EMPTY) {
11231 i = fcntl(fd, F_DUPFD, 10);
11238 ash_msg_and_raise_error("%d: %m", fd);
11248 dupredirect(n, newfd);
11249 } while ((n = n->nfile.next));
11251 if (flags & REDIR_SAVEFD2 && sv && sv->renamed[2] >= 0)
11252 preverrout_fd = sv->renamed[2];
11256 * Undo the effects of the last redirection.
11261 struct redirtab *rp;
11264 if (--nullredirs >= 0)
11268 for (i = 0; i < 10; i++) {
11269 if (rp->renamed[i] != EMPTY) {
11272 copyfd(rp->renamed[i], i);
11274 close(rp->renamed[i]);
11277 redirlist = rp->next;
11278 nullredirs = rp->nullredirs;
11284 * Undo all redirections. Called on error or interrupt.
11288 * Discard all saved file descriptors.
11291 clearredir(int drop)
11302 * Copy a file descriptor to be >= to. Returns -1
11303 * if the source file descriptor is closed, EMPTY if there are no unused
11304 * file descriptors left.
11307 copyfd(int from, int to)
11311 newfd = fcntl(from, F_DUPFD, to);
11313 if (errno == EMFILE)
11315 ash_msg_and_raise_error("%d: %m", from);
11321 redirectsafe(union node *redir, int flags)
11324 volatile int saveint;
11325 struct jmploc *volatile savehandler = exception_handler;
11326 struct jmploc jmploc;
11329 err = setjmp(jmploc.loc) * 2;
11331 exception_handler = &jmploc;
11332 redirect(redir, flags);
11334 exception_handler = savehandler;
11335 if (err && exception != EXERROR)
11336 longjmp(exception_handler->loc, 1);
11337 RESTORE_INT(saveint);
11342 /* ============ trap.c */
11345 * The trap builtin.
11348 trapcmd(int argc, char **argv)
11357 for (signo = 0; signo < NSIG; signo++) {
11358 if (trap[signo] != NULL) {
11361 sn = get_signame(signo);
11362 out1fmt("trap -- %s %s\n",
11363 single_quote(trap[signo]), sn);
11373 signo = get_signum(*ap);
11375 ash_msg_and_raise_error("%s: bad trap", *ap);
11378 if (LONE_DASH(action))
11381 action = ckstrdup(action);
11385 trap[signo] = action;
11395 /* ============ Builtins */
11397 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
11399 * Lists available builtins
11402 helpcmd(int argc, char **argv)
11406 out1fmt("\nBuilt-in commands:\n-------------------\n");
11407 for (col = 0, i = 0; i < NUMBUILTINS; i++) {
11408 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '),
11409 builtincmd[i].name + 1);
11415 #if ENABLE_FEATURE_SH_STANDALONE_SHELL
11416 for (i = 0; i < NUM_APPLETS; i++) {
11417 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '), applets[i].name);
11425 return EXIT_SUCCESS;
11427 #endif /* FEATURE_SH_EXTRA_QUIET */
11430 * The export and readonly commands.
11433 exportcmd(int argc, char **argv)
11439 int flag = argv[0][0] == 'r'? VREADONLY : VEXPORT;
11441 if (nextopt("p") != 'p') {
11446 p = strchr(name, '=');
11450 vp = *findvar(hashvar(name), name);
11456 setvar(name, p, flag);
11457 } while ((name = *++aptr) != NULL);
11461 showvars(argv[0], flag, 0);
11466 * Delete a function if it exists.
11469 unsetfunc(const char *name)
11471 struct tblentry *cmdp;
11473 cmdp = cmdlookup(name, 0);
11474 if (cmdp!= NULL && cmdp->cmdtype == CMDFUNCTION)
11475 delete_cmd_entry();
11479 * The unset builtin command. We unset the function before we unset the
11480 * variable to allow a function to be unset when there is a readonly variable
11481 * with the same name.
11484 unsetcmd(int argc, char **argv)
11491 while ((i = nextopt("vf")) != '\0') {
11495 for (ap = argptr; *ap; ap++) {
11511 #include <sys/times.h>
11513 static const unsigned char timescmd_str[] = {
11514 ' ', offsetof(struct tms, tms_utime),
11515 '\n', offsetof(struct tms, tms_stime),
11516 ' ', offsetof(struct tms, tms_cutime),
11517 '\n', offsetof(struct tms, tms_cstime),
11522 timescmd(int ac, char **av)
11524 long clk_tck, s, t;
11525 const unsigned char *p;
11528 clk_tck = sysconf(_SC_CLK_TCK);
11533 t = *(clock_t *)(((char *) &buf) + p[1]);
11535 out1fmt("%ldm%ld.%.3lds%c",
11537 ((t - s * clk_tck) * 1000) / clk_tck,
11539 } while (*(p += 2));
11544 #if ENABLE_ASH_MATH_SUPPORT
11546 dash_arith(const char *s)
11552 result = arith(s, &errcode);
11555 ash_msg_and_raise_error("exponent less than 0");
11557 ash_msg_and_raise_error("divide by zero");
11559 ash_msg_and_raise_error("expression recursion loop detected");
11560 raise_error_syntax(s);
11568 * The let builtin. partial stolen from GNU Bash, the Bourne Again SHell.
11569 * Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
11571 * Copyright (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
11574 letcmd(int argc, char **argv)
11581 ash_msg_and_raise_error("expression expected");
11582 for (ap = argv + 1; *ap; ap++) {
11583 i = dash_arith(*ap);
11588 #endif /* ASH_MATH_SUPPORT */
11591 /* ============ miscbltin.c
11593 * Miscellaneous builtins.
11598 #if defined(__GLIBC__) && __GLIBC__ == 2 && __GLIBC_MINOR__ < 1
11599 typedef enum __rlimit_resource rlim_t;
11603 * The read builtin. The -e option causes backslashes to escape the
11604 * following character.
11606 * This uses unbuffered input, which may be avoidable in some cases.
11609 readcmd(int argc, char **argv)
11621 #if ENABLE_ASH_READ_NCHARS
11625 struct termios tty, old_tty;
11627 #if ENABLE_ASH_READ_TIMEOUT
11631 ts.tv_sec = ts.tv_usec = 0;
11636 #if ENABLE_ASH_READ_NCHARS && ENABLE_ASH_READ_TIMEOUT
11637 while ((i = nextopt("p:rt:n:s")) != '\0')
11638 #elif ENABLE_ASH_READ_NCHARS
11639 while ((i = nextopt("p:rn:s")) != '\0')
11640 #elif ENABLE_ASH_READ_TIMEOUT
11641 while ((i = nextopt("p:rt:")) != '\0')
11643 while ((i = nextopt("p:r")) != '\0')
11648 prompt = optionarg;
11650 #if ENABLE_ASH_READ_NCHARS
11652 nchars = strtol(optionarg, &p, 10);
11654 ash_msg_and_raise_error("invalid count");
11655 nch_flag = (nchars > 0);
11661 #if ENABLE_ASH_READ_TIMEOUT
11663 ts.tv_sec = strtol(optionarg, &p, 10);
11669 ts.tv_usec = strtol(p, &p2, 10);
11671 ash_msg_and_raise_error("invalid timeout");
11673 /* normalize to usec */
11675 ash_msg_and_raise_error("invalid timeout");
11676 while (scale++ < 6)
11680 ash_msg_and_raise_error("invalid timeout");
11682 if ( ! ts.tv_sec && ! ts.tv_usec)
11683 ash_msg_and_raise_error("invalid timeout");
11693 if (prompt && isatty(0)) {
11698 ash_msg_and_raise_error("arg count");
11699 ifs = bltinlookup("IFS");
11702 #if ENABLE_ASH_READ_NCHARS
11703 if (nch_flag || silent) {
11704 tcgetattr(0, &tty);
11707 tty.c_lflag &= ~ICANON;
11708 tty.c_cc[VMIN] = nchars;
11711 tty.c_lflag &= ~(ECHO|ECHOK|ECHONL);
11714 tcsetattr(0, TCSANOW, &tty);
11717 #if ENABLE_ASH_READ_TIMEOUT
11718 if (ts.tv_sec || ts.tv_usec) {
11722 i = select(FD_SETSIZE, &set, NULL, NULL, &ts);
11724 #if ENABLE_ASH_READ_NCHARS
11726 tcsetattr(0, TCSANOW, &old_tty);
11736 #if ENABLE_ASH_READ_NCHARS
11737 while (!nch_flag || nchars--)
11742 if (read(0, &c, 1) != 1) {
11754 if (!rflag && c == '\\') {
11760 if (startword && *ifs == ' ' && strchr(ifs, c)) {
11764 if (ap[1] != NULL && strchr(ifs, c) != NULL) {
11766 setvar(*ap, stackblock(), 0);
11775 #if ENABLE_ASH_READ_NCHARS
11776 if (nch_flag || silent)
11777 tcsetattr(0, TCSANOW, &old_tty);
11781 /* Remove trailing blanks */
11782 while ((char *)stackblock() <= --p && strchr(ifs, *p) != NULL)
11784 setvar(*ap, stackblock(), 0);
11785 while (*++ap != NULL)
11786 setvar(*ap, nullstr, 0);
11791 umaskcmd(int argc, char **argv)
11793 static const char permuser[3] = "ugo";
11794 static const char permmode[3] = "rwx";
11795 static const short int permmask[] = {
11796 S_IRUSR, S_IWUSR, S_IXUSR,
11797 S_IRGRP, S_IWGRP, S_IXGRP,
11798 S_IROTH, S_IWOTH, S_IXOTH
11804 int symbolic_mode = 0;
11806 while (nextopt("S") != '\0') {
11817 if (symbolic_mode) {
11821 for (i = 0; i < 3; i++) {
11824 *p++ = permuser[i];
11826 for (j = 0; j < 3; j++) {
11827 if ((mask & permmask[3 * i + j]) == 0) {
11828 *p++ = permmode[j];
11836 out1fmt("%.4o\n", mask);
11839 if (isdigit((unsigned char) *ap)) {
11842 if (*ap >= '8' || *ap < '0')
11843 ash_msg_and_raise_error(illnum, argv[1]);
11844 mask = (mask << 3) + (*ap - '0');
11845 } while (*++ap != '\0');
11848 mask = ~mask & 0777;
11849 if (!bb_parse_mode(ap, &mask)) {
11850 ash_msg_and_raise_error("Illegal mode: %s", ap);
11852 umask(~mask & 0777);
11861 * This code, originally by Doug Gwyn, Doug Kingston, Eric Gisin, and
11862 * Michael Rendell was ripped from pdksh 5.0.8 and hacked for use with
11863 * ash by J.T. Conklin.
11871 int factor; /* multiply by to get rlim_{cur,max} values */
11875 static const struct limits limits[] = {
11877 { "time(seconds)", RLIMIT_CPU, 1, 't' },
11879 #ifdef RLIMIT_FSIZE
11880 { "file(blocks)", RLIMIT_FSIZE, 512, 'f' },
11883 { "data(kbytes)", RLIMIT_DATA, 1024, 'd' },
11885 #ifdef RLIMIT_STACK
11886 { "stack(kbytes)", RLIMIT_STACK, 1024, 's' },
11889 { "coredump(blocks)", RLIMIT_CORE, 512, 'c' },
11892 { "memory(kbytes)", RLIMIT_RSS, 1024, 'm' },
11894 #ifdef RLIMIT_MEMLOCK
11895 { "locked memory(kbytes)", RLIMIT_MEMLOCK, 1024, 'l' },
11897 #ifdef RLIMIT_NPROC
11898 { "process", RLIMIT_NPROC, 1, 'p' },
11900 #ifdef RLIMIT_NOFILE
11901 { "nofiles", RLIMIT_NOFILE, 1, 'n' },
11904 { "vmemory(kbytes)", RLIMIT_AS, 1024, 'v' },
11906 #ifdef RLIMIT_LOCKS
11907 { "locks", RLIMIT_LOCKS, 1, 'w' },
11909 { NULL, 0, 0, '\0' }
11912 enum limtype { SOFT = 0x1, HARD = 0x2 };
11915 printlim(enum limtype how, const struct rlimit *limit,
11916 const struct limits *l)
11920 val = limit->rlim_max;
11922 val = limit->rlim_cur;
11924 if (val == RLIM_INFINITY)
11925 out1fmt("unlimited\n");
11928 out1fmt("%lld\n", (long long) val);
11933 ulimitcmd(int argc, char **argv)
11937 enum limtype how = SOFT | HARD;
11938 const struct limits *l;
11941 struct rlimit limit;
11944 while ((optc = nextopt("HSa"
11948 #ifdef RLIMIT_FSIZE
11954 #ifdef RLIMIT_STACK
11963 #ifdef RLIMIT_MEMLOCK
11966 #ifdef RLIMIT_NPROC
11969 #ifdef RLIMIT_NOFILE
11975 #ifdef RLIMIT_LOCKS
11993 for (l = limits; l->option != what; l++)
11996 set = *argptr ? 1 : 0;
12000 if (all || argptr[1])
12001 ash_msg_and_raise_error("too many arguments");
12002 if (strncmp(p, "unlimited\n", 9) == 0)
12003 val = RLIM_INFINITY;
12007 while ((c = *p++) >= '0' && c <= '9') {
12008 val = (val * 10) + (long)(c - '0');
12009 if (val < (rlim_t) 0)
12013 ash_msg_and_raise_error("bad number");
12018 for (l = limits; l->name; l++) {
12019 getrlimit(l->cmd, &limit);
12020 out1fmt("%-20s ", l->name);
12021 printlim(how, &limit, l);
12026 getrlimit(l->cmd, &limit);
12029 limit.rlim_max = val;
12031 limit.rlim_cur = val;
12032 if (setrlimit(l->cmd, &limit) < 0)
12033 ash_msg_and_raise_error("error setting limit (%m)");
12035 printlim(how, &limit, l);
12041 /* ============ Math support */
12043 #if ENABLE_ASH_MATH_SUPPORT
12045 /* Copyright (c) 2001 Aaron Lehmann <aaronl@vitelus.com>
12047 Permission is hereby granted, free of charge, to any person obtaining
12048 a copy of this software and associated documentation files (the
12049 "Software"), to deal in the Software without restriction, including
12050 without limitation the rights to use, copy, modify, merge, publish,
12051 distribute, sublicense, and/or sell copies of the Software, and to
12052 permit persons to whom the Software is furnished to do so, subject to
12053 the following conditions:
12055 The above copyright notice and this permission notice shall be
12056 included in all copies or substantial portions of the Software.
12058 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
12059 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
12060 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
12061 IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
12062 CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
12063 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
12064 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
12067 /* This is my infix parser/evaluator. It is optimized for size, intended
12068 * as a replacement for yacc-based parsers. However, it may well be faster
12069 * than a comparable parser written in yacc. The supported operators are
12070 * listed in #defines below. Parens, order of operations, and error handling
12071 * are supported. This code is thread safe. The exact expression format should
12072 * be that which POSIX specifies for shells. */
12074 /* The code uses a simple two-stack algorithm. See
12075 * http://www.onthenet.com.au/~grahamis/int2008/week02/lect02.html
12076 * for a detailed explanation of the infix-to-postfix algorithm on which
12077 * this is based (this code differs in that it applies operators immediately
12078 * to the stack instead of adding them to a queue to end up with an
12081 /* To use the routine, call it with an expression string and error return
12085 * Aug 24, 2001 Manuel Novoa III
12087 * Reduced the generated code size by about 30% (i386) and fixed several bugs.
12089 * 1) In arith_apply():
12090 * a) Cached values of *numptr and &(numptr[-1]).
12091 * b) Removed redundant test for zero denominator.
12094 * a) Eliminated redundant code for processing operator tokens by moving
12095 * to a table-based implementation. Also folded handling of parens
12097 * b) Combined all 3 loops which called arith_apply to reduce generated
12098 * code size at the cost of speed.
12100 * 3) The following expressions were treated as valid by the original code:
12101 * 1() , 0! , 1 ( *3 ) .
12102 * These bugs have been fixed by internally enclosing the expression in
12103 * parens and then checking that all binary ops and right parens are
12104 * preceded by a valid expression (NUM_TOKEN).
12106 * Note: It may be desirable to replace Aaron's test for whitespace with
12107 * ctype's isspace() if it is used by another busybox applet or if additional
12108 * whitespace chars should be considered. Look below the "#include"s for a
12109 * precompiler test.
12113 * Aug 26, 2001 Manuel Novoa III
12115 * Return 0 for null expressions. Pointed out by Vladimir Oleynik.
12117 * Merge in Aaron's comments previously posted to the busybox list,
12118 * modified slightly to take account of my changes to the code.
12123 * (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
12125 * - allow access to variable,
12126 * used recursive find value indirection (c=2*2; a="c"; $((a+=2)) produce 6)
12127 * - realize assign syntax (VAR=expr, +=, *= etc)
12128 * - realize exponentiation (** operator)
12129 * - realize comma separated - expr, expr
12130 * - realise ++expr --expr expr++ expr--
12131 * - realise expr ? expr : expr (but, second expr calculate always)
12132 * - allow hexadecimal and octal numbers
12133 * - was restored loses XOR operator
12134 * - remove one goto label, added three ;-)
12135 * - protect $((num num)) as true zero expr (Manuel`s error)
12136 * - always use special isspace(), see comment from bash ;-)
12139 #define arith_isspace(arithval) \
12140 (arithval == ' ' || arithval == '\n' || arithval == '\t')
12142 typedef unsigned char operator;
12144 /* An operator's token id is a bit of a bitfield. The lower 5 bits are the
12145 * precedence, and 3 high bits are an ID unique across operators of that
12146 * precedence. The ID portion is so that multiple operators can have the
12147 * same precedence, ensuring that the leftmost one is evaluated first.
12148 * Consider * and /. */
12150 #define tok_decl(prec,id) (((id)<<5)|(prec))
12151 #define PREC(op) ((op) & 0x1F)
12153 #define TOK_LPAREN tok_decl(0,0)
12155 #define TOK_COMMA tok_decl(1,0)
12157 #define TOK_ASSIGN tok_decl(2,0)
12158 #define TOK_AND_ASSIGN tok_decl(2,1)
12159 #define TOK_OR_ASSIGN tok_decl(2,2)
12160 #define TOK_XOR_ASSIGN tok_decl(2,3)
12161 #define TOK_PLUS_ASSIGN tok_decl(2,4)
12162 #define TOK_MINUS_ASSIGN tok_decl(2,5)
12163 #define TOK_LSHIFT_ASSIGN tok_decl(2,6)
12164 #define TOK_RSHIFT_ASSIGN tok_decl(2,7)
12166 #define TOK_MUL_ASSIGN tok_decl(3,0)
12167 #define TOK_DIV_ASSIGN tok_decl(3,1)
12168 #define TOK_REM_ASSIGN tok_decl(3,2)
12170 /* all assign is right associativity and precedence eq, but (7+3)<<5 > 256 */
12171 #define convert_prec_is_assing(prec) do { if (prec == 3) prec = 2; } while (0)
12173 /* conditional is right associativity too */
12174 #define TOK_CONDITIONAL tok_decl(4,0)
12175 #define TOK_CONDITIONAL_SEP tok_decl(4,1)
12177 #define TOK_OR tok_decl(5,0)
12179 #define TOK_AND tok_decl(6,0)
12181 #define TOK_BOR tok_decl(7,0)
12183 #define TOK_BXOR tok_decl(8,0)
12185 #define TOK_BAND tok_decl(9,0)
12187 #define TOK_EQ tok_decl(10,0)
12188 #define TOK_NE tok_decl(10,1)
12190 #define TOK_LT tok_decl(11,0)
12191 #define TOK_GT tok_decl(11,1)
12192 #define TOK_GE tok_decl(11,2)
12193 #define TOK_LE tok_decl(11,3)
12195 #define TOK_LSHIFT tok_decl(12,0)
12196 #define TOK_RSHIFT tok_decl(12,1)
12198 #define TOK_ADD tok_decl(13,0)
12199 #define TOK_SUB tok_decl(13,1)
12201 #define TOK_MUL tok_decl(14,0)
12202 #define TOK_DIV tok_decl(14,1)
12203 #define TOK_REM tok_decl(14,2)
12205 /* exponent is right associativity */
12206 #define TOK_EXPONENT tok_decl(15,1)
12208 /* For now unary operators. */
12209 #define UNARYPREC 16
12210 #define TOK_BNOT tok_decl(UNARYPREC,0)
12211 #define TOK_NOT tok_decl(UNARYPREC,1)
12213 #define TOK_UMINUS tok_decl(UNARYPREC+1,0)
12214 #define TOK_UPLUS tok_decl(UNARYPREC+1,1)
12216 #define PREC_PRE (UNARYPREC+2)
12218 #define TOK_PRE_INC tok_decl(PREC_PRE, 0)
12219 #define TOK_PRE_DEC tok_decl(PREC_PRE, 1)
12221 #define PREC_POST (UNARYPREC+3)
12223 #define TOK_POST_INC tok_decl(PREC_POST, 0)
12224 #define TOK_POST_DEC tok_decl(PREC_POST, 1)
12226 #define SPEC_PREC (UNARYPREC+4)
12228 #define TOK_NUM tok_decl(SPEC_PREC, 0)
12229 #define TOK_RPAREN tok_decl(SPEC_PREC, 1)
12231 #define NUMPTR (*numstackptr)
12234 tok_have_assign(operator op)
12236 operator prec = PREC(op);
12238 convert_prec_is_assing(prec);
12239 return (prec == PREC(TOK_ASSIGN) ||
12240 prec == PREC_PRE || prec == PREC_POST);
12244 is_right_associativity(operator prec)
12246 return (prec == PREC(TOK_ASSIGN) || prec == PREC(TOK_EXPONENT)
12247 || prec == PREC(TOK_CONDITIONAL));
12250 typedef struct ARITCH_VAR_NUM {
12252 arith_t contidional_second_val;
12253 char contidional_second_val_initialized;
12254 char *var; /* if NULL then is regular number,
12255 else is variable name */
12258 typedef struct CHK_VAR_RECURSIVE_LOOPED {
12260 struct CHK_VAR_RECURSIVE_LOOPED *next;
12261 } chk_var_recursive_looped_t;
12263 static chk_var_recursive_looped_t *prev_chk_var_recursive;
12266 arith_lookup_val(v_n_t *t)
12269 const char * p = lookupvar(t->var);
12274 /* recursive try as expression */
12275 chk_var_recursive_looped_t *cur;
12276 chk_var_recursive_looped_t cur_save;
12278 for (cur = prev_chk_var_recursive; cur; cur = cur->next) {
12279 if (strcmp(cur->var, t->var) == 0) {
12280 /* expression recursion loop detected */
12284 /* save current lookuped var name */
12285 cur = prev_chk_var_recursive;
12286 cur_save.var = t->var;
12287 cur_save.next = cur;
12288 prev_chk_var_recursive = &cur_save;
12290 t->val = arith (p, &errcode);
12291 /* restore previous ptr after recursiving */
12292 prev_chk_var_recursive = cur;
12295 /* allow undefined var as 0 */
12301 /* "applying" a token means performing it on the top elements on the integer
12302 * stack. For a unary operator it will only change the top element, but a
12303 * binary operator will pop two arguments and push a result */
12305 arith_apply(operator op, v_n_t *numstack, v_n_t **numstackptr)
12308 arith_t numptr_val, rez;
12309 int ret_arith_lookup_val;
12311 /* There is no operator that can work without arguments */
12312 if (NUMPTR == numstack) goto err;
12313 numptr_m1 = NUMPTR - 1;
12315 /* check operand is var with noninteger value */
12316 ret_arith_lookup_val = arith_lookup_val(numptr_m1);
12317 if (ret_arith_lookup_val)
12318 return ret_arith_lookup_val;
12320 rez = numptr_m1->val;
12321 if (op == TOK_UMINUS)
12323 else if (op == TOK_NOT)
12325 else if (op == TOK_BNOT)
12327 else if (op == TOK_POST_INC || op == TOK_PRE_INC)
12329 else if (op == TOK_POST_DEC || op == TOK_PRE_DEC)
12331 else if (op != TOK_UPLUS) {
12332 /* Binary operators */
12334 /* check and binary operators need two arguments */
12335 if (numptr_m1 == numstack) goto err;
12337 /* ... and they pop one */
12340 if (op == TOK_CONDITIONAL) {
12341 if (! numptr_m1->contidional_second_val_initialized) {
12342 /* protect $((expr1 ? expr2)) without ": expr" */
12345 rez = numptr_m1->contidional_second_val;
12346 } else if (numptr_m1->contidional_second_val_initialized) {
12347 /* protect $((expr1 : expr2)) without "expr ? " */
12350 numptr_m1 = NUMPTR - 1;
12351 if (op != TOK_ASSIGN) {
12352 /* check operand is var with noninteger value for not '=' */
12353 ret_arith_lookup_val = arith_lookup_val(numptr_m1);
12354 if (ret_arith_lookup_val)
12355 return ret_arith_lookup_val;
12357 if (op == TOK_CONDITIONAL) {
12358 numptr_m1->contidional_second_val = rez;
12360 rez = numptr_m1->val;
12361 if (op == TOK_BOR || op == TOK_OR_ASSIGN)
12363 else if (op == TOK_OR)
12364 rez = numptr_val || rez;
12365 else if (op == TOK_BAND || op == TOK_AND_ASSIGN)
12367 else if (op == TOK_BXOR || op == TOK_XOR_ASSIGN)
12369 else if (op == TOK_AND)
12370 rez = rez && numptr_val;
12371 else if (op == TOK_EQ)
12372 rez = (rez == numptr_val);
12373 else if (op == TOK_NE)
12374 rez = (rez != numptr_val);
12375 else if (op == TOK_GE)
12376 rez = (rez >= numptr_val);
12377 else if (op == TOK_RSHIFT || op == TOK_RSHIFT_ASSIGN)
12378 rez >>= numptr_val;
12379 else if (op == TOK_LSHIFT || op == TOK_LSHIFT_ASSIGN)
12380 rez <<= numptr_val;
12381 else if (op == TOK_GT)
12382 rez = (rez > numptr_val);
12383 else if (op == TOK_LT)
12384 rez = (rez < numptr_val);
12385 else if (op == TOK_LE)
12386 rez = (rez <= numptr_val);
12387 else if (op == TOK_MUL || op == TOK_MUL_ASSIGN)
12389 else if (op == TOK_ADD || op == TOK_PLUS_ASSIGN)
12391 else if (op == TOK_SUB || op == TOK_MINUS_ASSIGN)
12393 else if (op == TOK_ASSIGN || op == TOK_COMMA)
12395 else if (op == TOK_CONDITIONAL_SEP) {
12396 if (numptr_m1 == numstack) {
12397 /* protect $((expr : expr)) without "expr ? " */
12400 numptr_m1->contidional_second_val_initialized = op;
12401 numptr_m1->contidional_second_val = numptr_val;
12402 } else if (op == TOK_CONDITIONAL) {
12404 numptr_val : numptr_m1->contidional_second_val;
12405 } else if (op == TOK_EXPONENT) {
12406 if (numptr_val < 0)
12407 return -3; /* exponent less than 0 */
12412 while (numptr_val--)
12416 } else if (numptr_val==0) /* zero divisor check */
12418 else if (op == TOK_DIV || op == TOK_DIV_ASSIGN)
12420 else if (op == TOK_REM || op == TOK_REM_ASSIGN)
12423 if (tok_have_assign(op)) {
12424 char buf[sizeof(arith_t_type)*3 + 2];
12426 if (numptr_m1->var == NULL) {
12430 /* save to shell variable */
12431 #if ENABLE_ASH_MATH_SUPPORT_64
12432 snprintf(buf, sizeof(buf), "%lld", (arith_t_type) rez);
12434 snprintf(buf, sizeof(buf), "%ld", (arith_t_type) rez);
12436 setvar(numptr_m1->var, buf, 0);
12437 /* after saving, make previous value for v++ or v-- */
12438 if (op == TOK_POST_INC)
12440 else if (op == TOK_POST_DEC)
12443 numptr_m1->val = rez;
12444 /* protect geting var value, is number now */
12445 numptr_m1->var = NULL;
12451 /* longest must be first */
12452 static const char op_tokens[] = {
12453 '<','<','=',0, TOK_LSHIFT_ASSIGN,
12454 '>','>','=',0, TOK_RSHIFT_ASSIGN,
12455 '<','<', 0, TOK_LSHIFT,
12456 '>','>', 0, TOK_RSHIFT,
12457 '|','|', 0, TOK_OR,
12458 '&','&', 0, TOK_AND,
12459 '!','=', 0, TOK_NE,
12460 '<','=', 0, TOK_LE,
12461 '>','=', 0, TOK_GE,
12462 '=','=', 0, TOK_EQ,
12463 '|','=', 0, TOK_OR_ASSIGN,
12464 '&','=', 0, TOK_AND_ASSIGN,
12465 '*','=', 0, TOK_MUL_ASSIGN,
12466 '/','=', 0, TOK_DIV_ASSIGN,
12467 '%','=', 0, TOK_REM_ASSIGN,
12468 '+','=', 0, TOK_PLUS_ASSIGN,
12469 '-','=', 0, TOK_MINUS_ASSIGN,
12470 '-','-', 0, TOK_POST_DEC,
12471 '^','=', 0, TOK_XOR_ASSIGN,
12472 '+','+', 0, TOK_POST_INC,
12473 '*','*', 0, TOK_EXPONENT,
12477 '=', 0, TOK_ASSIGN,
12489 '?', 0, TOK_CONDITIONAL,
12490 ':', 0, TOK_CONDITIONAL_SEP,
12491 ')', 0, TOK_RPAREN,
12492 '(', 0, TOK_LPAREN,
12496 #define endexpression &op_tokens[sizeof(op_tokens)-7]
12499 arith(const char *expr, int *perrcode)
12501 char arithval; /* Current character under analysis */
12502 operator lasttok, op;
12505 const char *p = endexpression;
12508 size_t datasizes = strlen(expr) + 2;
12510 /* Stack of integers */
12511 /* The proof that there can be no more than strlen(startbuf)/2+1 integers
12512 * in any given correct or incorrect expression is left as an exercise to
12514 v_n_t *numstack = alloca(((datasizes)/2)*sizeof(v_n_t)),
12515 *numstackptr = numstack;
12516 /* Stack of operator tokens */
12517 operator *stack = alloca((datasizes) * sizeof(operator)),
12520 *stackptr++ = lasttok = TOK_LPAREN; /* start off with a left paren */
12521 *perrcode = errcode = 0;
12525 if (arithval == 0) {
12526 if (p == endexpression) {
12527 /* Null expression. */
12531 /* This is only reached after all tokens have been extracted from the
12532 * input stream. If there are still tokens on the operator stack, they
12533 * are to be applied in order. At the end, there should be a final
12534 * result on the integer stack */
12536 if (expr != endexpression + 1) {
12537 /* If we haven't done so already, */
12538 /* append a closing right paren */
12539 expr = endexpression;
12540 /* and let the loop process it. */
12543 /* At this point, we're done with the expression. */
12544 if (numstackptr != numstack+1) {
12545 /* ... but if there isn't, it's bad */
12547 return (*perrcode = -1);
12549 if (numstack->var) {
12550 /* expression is $((var)) only, lookup now */
12551 errcode = arith_lookup_val(numstack);
12554 *perrcode = errcode;
12555 return numstack->val;
12558 /* Continue processing the expression. */
12559 if (arith_isspace(arithval)) {
12560 /* Skip whitespace */
12563 p = endofname(expr);
12565 size_t var_name_size = (p-expr) + 1; /* trailing zero */
12567 numstackptr->var = alloca(var_name_size);
12568 safe_strncpy(numstackptr->var, expr, var_name_size);
12571 numstackptr->contidional_second_val_initialized = 0;
12576 if (isdigit(arithval)) {
12577 numstackptr->var = NULL;
12578 #if ENABLE_ASH_MATH_SUPPORT_64
12579 numstackptr->val = strtoll(expr, (char **) &expr, 0);
12581 numstackptr->val = strtol(expr, (char **) &expr, 0);
12585 for (p = op_tokens; ; p++) {
12589 /* strange operator not found */
12592 for (o = expr; *p && *o == *p; p++)
12599 /* skip tail uncompared token */
12602 /* skip zero delim */
12607 /* post grammar: a++ reduce to num */
12608 if (lasttok == TOK_POST_INC || lasttok == TOK_POST_DEC)
12611 /* Plus and minus are binary (not unary) _only_ if the last
12612 * token was as number, or a right paren (which pretends to be
12613 * a number, since it evaluates to one). Think about it.
12614 * It makes sense. */
12615 if (lasttok != TOK_NUM) {
12631 /* We don't want a unary operator to cause recursive descent on the
12632 * stack, because there can be many in a row and it could cause an
12633 * operator to be evaluated before its argument is pushed onto the
12634 * integer stack. */
12635 /* But for binary operators, "apply" everything on the operator
12636 * stack until we find an operator with a lesser priority than the
12637 * one we have just extracted. */
12638 /* Left paren is given the lowest priority so it will never be
12639 * "applied" in this way.
12640 * if associativity is right and priority eq, applied also skip
12643 if ((prec > 0 && prec < UNARYPREC) || prec == SPEC_PREC) {
12644 /* not left paren or unary */
12645 if (lasttok != TOK_NUM) {
12646 /* binary op must be preceded by a num */
12649 while (stackptr != stack) {
12650 if (op == TOK_RPAREN) {
12651 /* The algorithm employed here is simple: while we don't
12652 * hit an open paren nor the bottom of the stack, pop
12653 * tokens and apply them */
12654 if (stackptr[-1] == TOK_LPAREN) {
12656 /* Any operator directly after a */
12658 /* close paren should consider itself binary */
12662 operator prev_prec = PREC(stackptr[-1]);
12664 convert_prec_is_assing(prec);
12665 convert_prec_is_assing(prev_prec);
12666 if (prev_prec < prec)
12668 /* check right assoc */
12669 if (prev_prec == prec && is_right_associativity(prec))
12672 errcode = arith_apply(*--stackptr, numstack, &numstackptr);
12673 if (errcode) goto ret;
12675 if (op == TOK_RPAREN) {
12680 /* Push this operator to the stack and remember it. */
12681 *stackptr++ = lasttok = op;
12686 #endif /* ASH_MATH_SUPPORT */
12689 /* ============ main() and helpers */
12692 * Called to exit the shell.
12694 static void exitshell(void) ATTRIBUTE_NORETURN;
12702 status = exitstatus;
12703 TRACE(("pid %d, exitshell(%d)\n", getpid(), status));
12704 if (setjmp(loc.loc)) {
12705 if (exception == EXEXIT)
12706 /* dash bug: it just does _exit(exitstatus) here
12707 * but we have to do setjobctl(0) first!
12708 * (bug is still not fixed in dash-0.5.3 - if you run dash
12709 * under Midnight Commander, on exit from dash MC is backgrounded) */
12710 status = exitstatus;
12713 exception_handler = &loc;
12719 flush_stdout_stderr();
12729 /* from input.c: */
12730 basepf.nextc = basepf.buf = basebuf;
12733 signal(SIGCHLD, SIG_DFL);
12738 char ppid[sizeof(int)*3 + 1];
12740 struct stat st1, st2;
12743 for (envp = environ; envp && *envp; envp++) {
12744 if (strchr(*envp, '=')) {
12745 setvareq(*envp, VEXPORT|VTEXTFIXED);
12749 snprintf(ppid, sizeof(ppid), "%u", (unsigned) getppid());
12750 setvar("PPID", ppid, 0);
12752 p = lookupvar("PWD");
12754 if (*p != '/' || stat(p, &st1) || stat(".", &st2)
12755 || st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino)
12762 * Process the shell command line arguments.
12765 procargs(int argc, char **argv)
12768 const char *xminusc;
12775 for (i = 0; i < NOPTS; i++)
12781 if (*xargv == NULL) {
12783 ash_msg_and_raise_error(bb_msg_requires_arg, "-c");
12786 if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
12790 for (i = 0; i < NOPTS; i++)
12791 if (optlist[i] == 2)
12796 /* POSIX 1003.2: first arg after -c cmd is $0, remainder $1... */
12801 } else if (!sflag) {
12802 setinputfile(*xargv, 0);
12805 commandname = arg0;
12808 shellparam.p = xargv;
12809 #if ENABLE_ASH_GETOPTS
12810 shellparam.optind = 1;
12811 shellparam.optoff = -1;
12813 /* assert(shellparam.malloc == 0 && shellparam.nparam == 0); */
12815 shellparam.nparam++;
12822 * Read /etc/profile or .profile.
12825 read_profile(const char *name)
12829 if (setinputfile(name, INPUT_PUSH_FILE | INPUT_NOFILE_OK) < 0)
12838 * This routine is called when an error or an interrupt occurs in an
12839 * interactive shell and control is returned to the main command loop.
12847 /* from input.c: */
12848 parselleft = parsenleft = 0; /* clear input buffer */
12850 /* from parser.c: */
12853 /* from redir.c: */
12858 static short profile_buf[16384];
12859 extern int etext();
12863 * Main routine. We initialize things, parse the arguments, execute
12864 * profiles if we're a login shell, and then call cmdloop to execute
12865 * commands. The setjmp call sets up the location to jump to when an
12866 * exception occurs. When an exception occurs the variable "state"
12867 * is used to figure out how far we had gotten.
12869 int ash_main(int argc, char **argv);
12870 int ash_main(int argc, char **argv)
12873 volatile int state;
12874 struct jmploc jmploc;
12875 struct stackmark smark;
12878 dash_errno = __errno_location();
12882 monitor(4, etext, profile_buf, sizeof(profile_buf), 50);
12885 #if ENABLE_FEATURE_EDITING
12886 line_input_state = new_line_input_t(FOR_SHELL | WITH_PATH_LOOKUP);
12889 if (setjmp(jmploc.loc)) {
12899 if (e == EXEXIT || s == 0 || iflag == 0 || shlvl)
12903 outcslow('\n', stderr);
12905 popstackmark(&smark);
12906 FORCE_INT_ON; /* enable interrupts */
12915 exception_handler = &jmploc;
12918 trace_puts("Shell args: ");
12919 trace_puts_args(argv);
12921 rootpid = getpid();
12923 #if ENABLE_ASH_RANDOM_SUPPORT
12924 rseed = rootpid + time(NULL);
12927 setstackmark(&smark);
12928 procargs(argc, argv);
12929 #if ENABLE_FEATURE_EDITING_SAVEHISTORY
12931 const char *hp = lookupvar("HISTFILE");
12934 hp = lookupvar("HOME");
12936 char *defhp = concat_path_file(hp, ".ash_history");
12937 setvar("HISTFILE", defhp, 0);
12943 if (argv[0] && argv[0][0] == '-')
12947 read_profile("/etc/profile");
12950 read_profile(".profile");
12956 getuid() == geteuid() && getgid() == getegid() &&
12960 shinit = lookupvar("ENV");
12961 if (shinit != NULL && *shinit != '\0') {
12962 read_profile(shinit);
12968 evalstring(minusc, 0);
12970 if (sflag || minusc == NULL) {
12971 #if ENABLE_FEATURE_EDITING_SAVEHISTORY
12973 const char *hp = lookupvar("HISTFILE");
12976 line_input_state->hist_file = hp;
12979 state4: /* XXX ??? - why isn't this before the "if" statement */
12987 extern void _mcleanup(void);
12996 const char *applet_name = "debug stuff usage";
12997 int main(int argc, char **argv)
12999 return ash_main(argc, argv);
13005 * Copyright (c) 1989, 1991, 1993, 1994
13006 * The Regents of the University of California. All rights reserved.
13008 * This code is derived from software contributed to Berkeley by
13009 * Kenneth Almquist.
13011 * Redistribution and use in source and binary forms, with or without
13012 * modification, are permitted provided that the following conditions
13014 * 1. Redistributions of source code must retain the above copyright
13015 * notice, this list of conditions and the following disclaimer.
13016 * 2. Redistributions in binary form must reproduce the above copyright
13017 * notice, this list of conditions and the following disclaimer in the
13018 * documentation and/or other materials provided with the distribution.
13019 * 3. Neither the name of the University nor the names of its contributors
13020 * may be used to endorse or promote products derived from this software
13021 * without specific prior written permission.
13023 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
13024 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
13025 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
13026 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
13027 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
13028 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
13029 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
13030 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
13031 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
13032 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF