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
56 #include "busybox.h" /* for struct bb_applet */
60 #if JOBS || ENABLE_ASH_READ_NCHARS
63 extern char **environ;
65 #if defined(__uClinux__)
66 #error "Do not even bother, ash will not run on uClinux"
70 /* ============ Misc helpers */
72 #define xbarrier() do { __asm__ __volatile__ ("": : :"memory"); } while (0)
74 /* C99 say: "char" declaration may be signed or unsigned default */
75 #define signed_char2int(sc) ((int)((signed char)sc))
78 /* ============ Shell options */
80 static const char *const optletters_optnames[] = {
101 #define optletters(n) optletters_optnames[(n)][0]
102 #define optnames(n) (&optletters_optnames[(n)][1])
104 enum { NOPTS = ARRAY_SIZE(optletters_optnames) };
106 static char optlist[NOPTS] ALIGN1;
108 #define eflag optlist[0]
109 #define fflag optlist[1]
110 #define Iflag optlist[2]
111 #define iflag optlist[3]
112 #define mflag optlist[4]
113 #define nflag optlist[5]
114 #define sflag optlist[6]
115 #define xflag optlist[7]
116 #define vflag optlist[8]
117 #define Cflag optlist[9]
118 #define aflag optlist[10]
119 #define bflag optlist[11]
120 #define uflag optlist[12]
121 #define viflag optlist[13]
123 #define nolog optlist[14]
124 #define debug optlist[15]
128 /* ============ Misc data */
130 static char nullstr[1] ALIGN1; /* zero length string */
131 static const char homestr[] ALIGN1 = "HOME";
132 static const char snlfmt[] ALIGN1 = "%s\n";
133 static const char illnum[] ALIGN1 = "Illegal number: %s";
135 static char *minusc; /* argument to -c option */
137 /* pid of main shell */
139 /* shell level: 0 for the main shell, 1 for its children, and so on */
141 #define rootshell (!shlvl)
142 /* trap handler commands */
143 static char *trap[NSIG];
144 static smallint isloginsh;
145 /* current value of signal */
146 static char sigmode[NSIG - 1];
147 /* indicates specified signal received */
148 static char gotsig[NSIG - 1];
149 static char *arg0; /* value of $0 */
152 /* ============ Interrupts / exceptions */
155 * We enclose jmp_buf in a structure so that we can declare pointers to
156 * jump locations. The global variable handler contains the location to
157 * jump to when an exception occurs, and the global variable exception
158 * contains a code identifying the exception. To implement nested
159 * exception handlers, the user should save the value of handler on entry
160 * to an inner scope, set handler to point to a jmploc structure for the
161 * inner scope, and restore handler on exit from the scope.
166 static struct jmploc *exception_handler;
167 static int exception;
169 #define EXINT 0 /* SIGINT received */
170 #define EXERROR 1 /* a generic error */
171 #define EXSHELLPROC 2 /* execute a shell procedure */
172 #define EXEXEC 3 /* command execution failed */
173 #define EXEXIT 4 /* exit the shell */
174 #define EXSIG 5 /* trapped signal in wait(1) */
175 static volatile int suppressint;
176 static volatile sig_atomic_t intpending;
177 /* do we generate EXSIG events */
179 /* last pending signal */
180 static volatile sig_atomic_t pendingsig;
183 * Sigmode records the current value of the signal handlers for the various
184 * modes. A value of zero means that the current handler is not known.
185 * S_HARD_IGN indicates that the signal was ignored on entry to the shell,
188 #define S_DFL 1 /* default signal handling (SIG_DFL) */
189 #define S_CATCH 2 /* signal is caught */
190 #define S_IGN 3 /* signal is ignored (SIG_IGN) */
191 #define S_HARD_IGN 4 /* signal is ignored permenantly */
192 #define S_RESET 5 /* temporary - to reset a hard ignored sig */
195 * These macros allow the user to suspend the handling of interrupt signals
196 * over a period of time. This is similar to SIGHOLD to or sigblock, but
197 * much more efficient and portable. (But hacking the kernel is so much
198 * more fun than worrying about efficiency and portability. :-))
207 * Called to raise an exception. Since C doesn't include exceptions, we
208 * just do a longjmp to the exception handler. The type of exception is
209 * stored in the global variable "exception".
211 static void raise_exception(int) ATTRIBUTE_NORETURN;
213 raise_exception(int e)
216 if (exception_handler == NULL)
221 longjmp(exception_handler->loc, 1);
225 * Called from trap.c when a SIGINT is received. (If the user specifies
226 * that SIGINT is to be trapped or ignored using the trap builtin, then
227 * this routine is not called.) Suppressint is nonzero when interrupts
228 * are held using the INT_OFF macro. (The test for iflag is just
229 * defensive programming.)
231 static void raise_interrupt(void) ATTRIBUTE_NORETURN;
233 raise_interrupt(void)
239 /* Signal is not automatically re-enabled after it is raised,
242 sigprocmask(SIG_SETMASK, &mask, 0);
243 /* pendingsig = 0; - now done in onsig() */
246 if (gotsig[SIGINT - 1] && !trap[SIGINT]) {
247 if (!(rootshell && iflag)) {
248 signal(SIGINT, SIG_DFL);
257 #if ENABLE_ASH_OPTIMIZE_FOR_SIZE
261 if (--suppressint == 0 && intpending) {
265 #define INT_ON int_on()
273 #define FORCE_INT_ON force_int_on()
278 if (--suppressint == 0 && intpending) \
281 #define FORCE_INT_ON \
288 #endif /* ASH_OPTIMIZE_FOR_SIZE */
290 #define SAVE_INT(v) ((v) = suppressint)
292 #define RESTORE_INT(v) \
296 if (suppressint == 0 && intpending) \
305 raise_exception(EXSIG); \
307 /* EXSIG is turned off by evalbltin(). */
310 * Ignore a signal. Only one usage site - in forkchild()
315 if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) {
316 signal(signo, SIG_IGN);
318 sigmode[signo - 1] = S_HARD_IGN;
322 * Signal handler. Only one usage site - in setsignal()
327 gotsig[signo - 1] = 1;
330 if (exsig || (signo == SIGINT && !trap[SIGINT])) {
340 /* ============ Stdout/stderr output */
343 outstr(const char *p, FILE *file)
351 flush_stdout_stderr(void)
368 outcslow(int c, FILE *dest)
376 static int out1fmt(const char *, ...) __attribute__((__format__(__printf__,1,2)));
378 out1fmt(const char *fmt, ...)
385 r = vprintf(fmt, ap);
391 static int fmtstr(char *, size_t, const char *, ...) __attribute__((__format__(__printf__,3,4)));
393 fmtstr(char *outbuf, size_t length, const char *fmt, ...)
400 ret = vsnprintf(outbuf, length, fmt, ap);
407 out1str(const char *p)
413 out2str(const char *p)
420 /* ============ Parser structures */
422 /* control characters in argument strings */
423 #define CTLESC '\201' /* escape next character */
424 #define CTLVAR '\202' /* variable defn */
425 #define CTLENDVAR '\203'
426 #define CTLBACKQ '\204'
427 #define CTLQUOTE 01 /* ored with CTLBACKQ code if in quotes */
428 /* CTLBACKQ | CTLQUOTE == '\205' */
429 #define CTLARI '\206' /* arithmetic expression */
430 #define CTLENDARI '\207'
431 #define CTLQUOTEMARK '\210'
433 /* variable substitution byte (follows CTLVAR) */
434 #define VSTYPE 0x0f /* type of variable substitution */
435 #define VSNUL 0x10 /* colon--treat the empty string as unset */
436 #define VSQUOTE 0x80 /* inside double quotes--suppress splitting */
438 /* values of VSTYPE field */
439 #define VSNORMAL 0x1 /* normal variable: $var or ${var} */
440 #define VSMINUS 0x2 /* ${var-text} */
441 #define VSPLUS 0x3 /* ${var+text} */
442 #define VSQUESTION 0x4 /* ${var?message} */
443 #define VSASSIGN 0x5 /* ${var=text} */
444 #define VSTRIMRIGHT 0x6 /* ${var%pattern} */
445 #define VSTRIMRIGHTMAX 0x7 /* ${var%%pattern} */
446 #define VSTRIMLEFT 0x8 /* ${var#pattern} */
447 #define VSTRIMLEFTMAX 0x9 /* ${var##pattern} */
448 #define VSLENGTH 0xa /* ${#var} */
450 static const char dolatstr[] ALIGN1 = {
451 CTLVAR, VSNORMAL|VSQUOTE, '@', '=', '\0'
487 union node *redirect;
493 struct nodelist *cmdlist;
499 union node *redirect;
512 union node *elsepart;
539 struct nodelist *backquote;
574 struct nredir nredir;
575 struct nbinary nbinary;
579 struct nclist nclist;
588 struct nodelist *next;
601 freefunc(struct funcnode *f)
603 if (f && --f->count < 0)
608 /* ============ Debugging output */
612 static FILE *tracefile;
615 trace_printf(const char *fmt, ...)
622 vfprintf(tracefile, fmt, va);
627 trace_vprintf(const char *fmt, va_list va)
631 vfprintf(tracefile, fmt, va);
635 trace_puts(const char *s)
643 trace_puts_quoted(char *s)
650 putc('"', tracefile);
651 for (p = s; *p; p++) {
653 case '\n': c = 'n'; goto backslash;
654 case '\t': c = 't'; goto backslash;
655 case '\r': c = 'r'; goto backslash;
656 case '"': c = '"'; goto backslash;
657 case '\\': c = '\\'; goto backslash;
658 case CTLESC: c = 'e'; goto backslash;
659 case CTLVAR: c = 'v'; goto backslash;
660 case CTLVAR+CTLQUOTE: c = 'V'; goto backslash;
661 case CTLBACKQ: c = 'q'; goto backslash;
662 case CTLBACKQ+CTLQUOTE: c = 'Q'; goto backslash;
664 putc('\\', tracefile);
668 if (*p >= ' ' && *p <= '~')
671 putc('\\', tracefile);
672 putc(*p >> 6 & 03, tracefile);
673 putc(*p >> 3 & 07, tracefile);
674 putc(*p & 07, tracefile);
679 putc('"', tracefile);
683 trace_puts_args(char **ap)
690 trace_puts_quoted(*ap);
692 putc('\n', tracefile);
695 putc(' ', tracefile);
710 /* leave open because libedit might be using it */
713 strcpy(s, "./trace");
715 if (!freopen(s, "a", tracefile)) {
716 fprintf(stderr, "Can't re-open %s\n", s);
721 tracefile = fopen(s, "a");
722 if (tracefile == NULL) {
723 fprintf(stderr, "Can't open %s\n", s);
729 flags = fcntl(fileno(tracefile), F_GETFL);
731 fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND);
733 setlinebuf(tracefile);
734 fputs("\nTracing started.\n", tracefile);
738 indent(int amount, char *pfx, FILE *fp)
742 for (i = 0; i < amount; i++) {
743 if (pfx && i == amount - 1)
749 /* little circular references here... */
750 static void shtree(union node *n, int ind, char *pfx, FILE *fp);
753 sharg(union node *arg, FILE *fp)
756 struct nodelist *bqlist;
759 if (arg->type != NARG) {
760 out1fmt("<node type %d>\n", arg->type);
763 bqlist = arg->narg.backquote;
764 for (p = arg->narg.text; *p; p++) {
773 if (subtype == VSLENGTH)
782 switch (subtype & VSTYPE) {
815 out1fmt("<subtype %d>", subtype);
822 case CTLBACKQ|CTLQUOTE:
825 shtree(bqlist->n, -1, NULL, fp);
836 shcmd(union node *cmd, FILE *fp)
844 for (np = cmd->ncmd.args; np; np = np->narg.next) {
850 for (np = cmd->ncmd.redirect; np; np = np->nfile.next) {
854 switch (np->nfile.type) {
855 case NTO: s = ">>"+1; dftfd = 1; break;
856 case NCLOBBER: s = ">|"; dftfd = 1; break;
857 case NAPPEND: s = ">>"; dftfd = 1; break;
858 case NTOFD: s = ">&"; dftfd = 1; break;
859 case NFROM: s = "<"; break;
860 case NFROMFD: s = "<&"; break;
861 case NFROMTO: s = "<>"; break;
862 default: s = "*error*"; break;
864 if (np->nfile.fd != dftfd)
865 fprintf(fp, "%d", np->nfile.fd);
867 if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) {
868 fprintf(fp, "%d", np->ndup.dupfd);
870 sharg(np->nfile.fname, fp);
877 shtree(union node *n, int ind, char *pfx, FILE *fp)
885 indent(ind, pfx, fp);
896 shtree(n->nbinary.ch1, ind, NULL, fp);
899 shtree(n->nbinary.ch2, ind, NULL, fp);
907 for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
912 if (n->npipe.backgnd)
918 fprintf(fp, "<node type %d>", n->type);
926 showtree(union node *n)
928 trace_puts("showtree called\n");
929 shtree(n, 1, NULL, stdout);
932 #define TRACE(param) trace_printf param
933 #define TRACEV(param) trace_vprintf param
938 #define TRACEV(param)
943 /* ============ Parser data */
946 * ash_vmsg() needs parsefile->fd, hence parsefile definition is moved up.
949 struct strlist *next;
958 struct strpush *prev; /* preceding string on stack */
962 struct alias *ap; /* if push was associated with an alias */
964 char *string; /* remember the string since it may change */
968 struct parsefile *prev; /* preceding file on stack */
969 int linno; /* current line */
970 int fd; /* file descriptor (or -1 if string) */
971 int nleft; /* number of chars left in this line */
972 int lleft; /* number of chars left in this buffer */
973 char *nextc; /* next char in buffer */
974 char *buf; /* input buffer */
975 struct strpush *strpush; /* for pushing strings at this level */
976 struct strpush basestrpush; /* so pushing one is fast */
979 static struct parsefile basepf; /* top level input file */
980 static struct parsefile *parsefile = &basepf; /* current input file */
981 static int startlinno; /* line # where last token started */
982 static char *commandname; /* currently executing command */
983 static struct strlist *cmdenviron; /* environment for builtin command */
984 static int exitstatus; /* exit status of last command */
987 /* ============ Message printing */
990 ash_vmsg(const char *msg, va_list ap)
992 fprintf(stderr, "%s: ", arg0);
994 if (strcmp(arg0, commandname))
995 fprintf(stderr, "%s: ", commandname);
996 if (!iflag || parsefile->fd)
997 fprintf(stderr, "line %d: ", startlinno);
999 vfprintf(stderr, msg, ap);
1000 outcslow('\n', stderr);
1004 * Exverror is called to raise the error exception. If the second argument
1005 * is not NULL then error prints an error message using printf style
1006 * formatting. It then raises the error exception.
1008 static void ash_vmsg_and_raise(int, const char *, va_list) ATTRIBUTE_NORETURN;
1010 ash_vmsg_and_raise(int cond, const char *msg, va_list ap)
1014 TRACE(("ash_vmsg_and_raise(%d, \"", cond));
1016 TRACE(("\") pid=%d\n", getpid()));
1018 TRACE(("ash_vmsg_and_raise(%d, NULL) pid=%d\n", cond, getpid()));
1023 flush_stdout_stderr();
1024 raise_exception(cond);
1028 static void ash_msg_and_raise_error(const char *, ...) ATTRIBUTE_NORETURN;
1030 ash_msg_and_raise_error(const char *msg, ...)
1035 ash_vmsg_and_raise(EXERROR, msg, ap);
1040 static void ash_msg_and_raise(int, const char *, ...) ATTRIBUTE_NORETURN;
1042 ash_msg_and_raise(int cond, const char *msg, ...)
1047 ash_vmsg_and_raise(cond, msg, ap);
1053 * error/warning routines for external builtins
1056 ash_msg(const char *fmt, ...)
1066 * Return a string describing an error. The returned string may be a
1067 * pointer to a static buffer that will be overwritten on the next call.
1068 * Action describes the operation that got the error.
1071 errmsg(int e, const char *em)
1073 if (e == ENOENT || e == ENOTDIR) {
1080 /* ============ Memory allocation */
1083 * It appears that grabstackstr() will barf with such alignments
1084 * because stalloc() will return a string allocated in a new stackblock.
1086 #define SHELL_ALIGN(nbytes) (((nbytes) + SHELL_SIZE) & ~SHELL_SIZE)
1088 /* Most machines require the value returned from malloc to be aligned
1089 * in some way. The following macro will get this right
1090 * on many machines. */
1091 SHELL_SIZE = sizeof(union {int i; char *cp; double d; }) - 1,
1092 /* Minimum size of a block */
1093 MINSIZE = SHELL_ALIGN(504),
1096 struct stack_block {
1097 struct stack_block *prev;
1098 char space[MINSIZE];
1102 struct stack_block *stackp;
1105 struct stackmark *marknext;
1108 static struct stack_block stackbase;
1109 static struct stack_block *stackp = &stackbase;
1110 static struct stackmark *markp;
1111 static char *stacknxt = stackbase.space;
1112 static size_t stacknleft = MINSIZE;
1113 static char *sstrend = stackbase.space + MINSIZE;
1114 static int herefd = -1;
1116 #define stackblock() ((void *)stacknxt)
1117 #define stackblocksize() stacknleft
1120 ckrealloc(void * p, size_t nbytes)
1122 p = realloc(p, nbytes);
1124 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1129 ckmalloc(size_t nbytes)
1131 return ckrealloc(NULL, nbytes);
1135 * Make a copy of a string in safe storage.
1138 ckstrdup(const char *s)
1140 char *p = strdup(s);
1142 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1147 * Parse trees for commands are allocated in lifo order, so we use a stack
1148 * to make this more efficient, and also to avoid all sorts of exception
1149 * handling code to handle interrupts in the middle of a parse.
1151 * The size 504 was chosen because the Ultrix malloc handles that size
1155 stalloc(size_t nbytes)
1160 aligned = SHELL_ALIGN(nbytes);
1161 if (aligned > stacknleft) {
1164 struct stack_block *sp;
1166 blocksize = aligned;
1167 if (blocksize < MINSIZE)
1168 blocksize = MINSIZE;
1169 len = sizeof(struct stack_block) - MINSIZE + blocksize;
1170 if (len < blocksize)
1171 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1175 stacknxt = sp->space;
1176 stacknleft = blocksize;
1177 sstrend = stacknxt + blocksize;
1182 stacknxt += aligned;
1183 stacknleft -= aligned;
1191 if (!p || (stacknxt < (char *)p) || ((char *)p < stackp->space)) {
1192 write(2, "stunalloc\n", 10);
1196 stacknleft += stacknxt - (char *)p;
1201 * Like strdup but works with the ash stack.
1204 ststrdup(const char *p)
1206 size_t len = strlen(p) + 1;
1207 return memcpy(stalloc(len), p, len);
1211 setstackmark(struct stackmark *mark)
1213 mark->stackp = stackp;
1214 mark->stacknxt = stacknxt;
1215 mark->stacknleft = stacknleft;
1216 mark->marknext = markp;
1221 popstackmark(struct stackmark *mark)
1223 struct stack_block *sp;
1229 markp = mark->marknext;
1230 while (stackp != mark->stackp) {
1235 stacknxt = mark->stacknxt;
1236 stacknleft = mark->stacknleft;
1237 sstrend = mark->stacknxt + mark->stacknleft;
1242 * When the parser reads in a string, it wants to stick the string on the
1243 * stack and only adjust the stack pointer when it knows how big the
1244 * string is. Stackblock (defined in stack.h) returns a pointer to a block
1245 * of space on top of the stack and stackblocklen returns the length of
1246 * this block. Growstackblock will grow this space by at least one byte,
1247 * possibly moving it (like realloc). Grabstackblock actually allocates the
1248 * part of the block that has been used.
1251 growstackblock(void)
1255 newlen = stacknleft * 2;
1256 if (newlen < stacknleft)
1257 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1261 if (stacknxt == stackp->space && stackp != &stackbase) {
1262 struct stack_block *oldstackp;
1263 struct stackmark *xmark;
1264 struct stack_block *sp;
1265 struct stack_block *prevstackp;
1271 prevstackp = sp->prev;
1272 grosslen = newlen + sizeof(struct stack_block) - MINSIZE;
1273 sp = ckrealloc(sp, grosslen);
1274 sp->prev = prevstackp;
1276 stacknxt = sp->space;
1277 stacknleft = newlen;
1278 sstrend = sp->space + newlen;
1281 * Stack marks pointing to the start of the old block
1282 * must be relocated to point to the new block
1285 while (xmark != NULL && xmark->stackp == oldstackp) {
1286 xmark->stackp = stackp;
1287 xmark->stacknxt = stacknxt;
1288 xmark->stacknleft = stacknleft;
1289 xmark = xmark->marknext;
1293 char *oldspace = stacknxt;
1294 int oldlen = stacknleft;
1295 char *p = stalloc(newlen);
1297 /* free the space we just allocated */
1298 stacknxt = memcpy(p, oldspace, oldlen);
1299 stacknleft += newlen;
1304 grabstackblock(size_t len)
1306 len = SHELL_ALIGN(len);
1312 * The following routines are somewhat easier to use than the above.
1313 * The user declares a variable of type STACKSTR, which may be declared
1314 * to be a register. The macro STARTSTACKSTR initializes things. Then
1315 * the user uses the macro STPUTC to add characters to the string. In
1316 * effect, STPUTC(c, p) is the same as *p++ = c except that the stack is
1317 * grown as necessary. When the user is done, she can just leave the
1318 * string there and refer to it using stackblock(). Or she can allocate
1319 * the space for it using grabstackstr(). If it is necessary to allow
1320 * someone else to use the stack temporarily and then continue to grow
1321 * the string, the user should use grabstack to allocate the space, and
1322 * then call ungrabstr(p) to return to the previous mode of operation.
1324 * USTPUTC is like STPUTC except that it doesn't check for overflow.
1325 * CHECKSTACKSPACE can be called before USTPUTC to ensure that there
1326 * is space for at least one character.
1331 size_t len = stackblocksize();
1332 if (herefd >= 0 && len >= 1024) {
1333 full_write(herefd, stackblock(), len);
1334 return stackblock();
1337 return stackblock() + len;
1341 * Called from CHECKSTRSPACE.
1344 makestrspace(size_t newlen, char *p)
1346 size_t len = p - stacknxt;
1347 size_t size = stackblocksize();
1352 size = stackblocksize();
1354 if (nleft >= newlen)
1358 return stackblock() + len;
1362 stack_nputstr(const char *s, size_t n, char *p)
1364 p = makestrspace(n, p);
1365 p = memcpy(p, s, n) + n;
1370 stack_putstr(const char *s, char *p)
1372 return stack_nputstr(s, strlen(s), p);
1376 _STPUTC(int c, char *p)
1384 #define STARTSTACKSTR(p) ((p) = stackblock())
1385 #define STPUTC(c, p) ((p) = _STPUTC((c), (p)))
1386 #define CHECKSTRSPACE(n, p) \
1390 size_t m = sstrend - q; \
1392 (p) = makestrspace(l, q); \
1394 #define USTPUTC(c, p) (*p++ = (c))
1395 #define STACKSTRNUL(p) \
1397 if ((p) == sstrend) \
1398 p = growstackstr(); \
1401 #define STUNPUTC(p) (--p)
1402 #define STTOPC(p) (p[-1])
1403 #define STADJUST(amount, p) (p += (amount))
1405 #define grabstackstr(p) stalloc((char *)(p) - (char *)stackblock())
1406 #define ungrabstackstr(s, p) stunalloc((s))
1407 #define stackstrend() ((void *)sstrend)
1410 /* ============ String helpers */
1413 * prefix -- see if pfx is a prefix of string.
1416 prefix(const char *string, const char *pfx)
1419 if (*pfx++ != *string++)
1422 return (char *) string;
1426 * Check for a valid number. This should be elsewhere.
1429 is_number(const char *p)
1434 } while (*++p != '\0');
1439 * Convert a string of digits to an integer, printing an error message on
1443 number(const char *s)
1446 ash_msg_and_raise_error(illnum, s);
1451 * Produce a possibly single quoted string suitable as input to the shell.
1452 * The return string is allocated on the stack.
1455 single_quote(const char *s)
1465 len = strchrnul(s, '\'') - s;
1467 q = p = makestrspace(len + 3, p);
1470 q = memcpy(q, s, len) + len;
1476 len = strspn(s, "'");
1480 q = p = makestrspace(len + 3, p);
1483 q = memcpy(q, s, len) + len;
1492 return stackblock();
1496 /* ============ nextopt */
1498 static char **argptr; /* argument list for builtin commands */
1499 static char *optionarg; /* set by nextopt (like getopt) */
1500 static char *optptr; /* used by nextopt */
1503 * XXX - should get rid of. have all builtins use getopt(3). the
1504 * library getopt must have the BSD extension static variable "optreset"
1505 * otherwise it can't be used within the shell safely.
1507 * Standard option processing (a la getopt) for builtin routines. The
1508 * only argument that is passed to nextopt is the option string; the
1509 * other arguments are unnecessary. It return the character, or '\0' on
1513 nextopt(const char *optstring)
1520 if (p == NULL || *p == '\0') {
1522 if (p == NULL || *p != '-' || *++p == '\0')
1525 if (LONE_DASH(p)) /* check for "--" */
1529 for (q = optstring; *q != c; ) {
1531 ash_msg_and_raise_error("illegal option -%c", c);
1536 if (*p == '\0' && (p = *argptr++) == NULL)
1537 ash_msg_and_raise_error("no arg for -%c option", c);
1546 /* ============ Math support definitions */
1548 #if ENABLE_ASH_MATH_SUPPORT_64
1549 typedef int64_t arith_t;
1550 #define arith_t_type long long
1552 typedef long arith_t;
1553 #define arith_t_type long
1556 #if ENABLE_ASH_MATH_SUPPORT
1557 static arith_t dash_arith(const char *);
1558 static arith_t arith(const char *expr, int *perrcode);
1561 #if ENABLE_ASH_RANDOM_SUPPORT
1562 static unsigned long rseed;
1569 /* ============ Shell variables */
1572 #define VEXPORT 0x01 /* variable is exported */
1573 #define VREADONLY 0x02 /* variable cannot be modified */
1574 #define VSTRFIXED 0x04 /* variable struct is statically allocated */
1575 #define VTEXTFIXED 0x08 /* text is statically allocated */
1576 #define VSTACK 0x10 /* text is allocated on the stack */
1577 #define VUNSET 0x20 /* the variable is not set */
1578 #define VNOFUNC 0x40 /* don't call the callback function */
1579 #define VNOSET 0x80 /* do not set variable - just readonly test */
1580 #define VNOSAVE 0x100 /* when text is on the heap before setvareq */
1582 # define VDYNAMIC 0x200 /* dynamic variable */
1588 static const char defifsvar[] ALIGN1 = "IFS= \t\n";
1589 #define defifs (defifsvar + 4)
1591 static const char defifs[] ALIGN1 = " \t\n";
1595 int nparam; /* # of positional parameters (without $0) */
1596 unsigned char malloc; /* if parameter list dynamically allocated */
1597 char **p; /* parameter list */
1598 #if ENABLE_ASH_GETOPTS
1599 int optind; /* next parameter to be processed by getopts */
1600 int optoff; /* used by getopts */
1604 static struct shparam shellparam; /* $@ current positional parameters */
1607 * Free the list of positional parameters.
1610 freeparam(volatile struct shparam *param)
1614 if (param->malloc) {
1615 for (ap = param->p; *ap; ap++)
1621 #if ENABLE_ASH_GETOPTS
1623 getoptsreset(const char *value)
1625 shellparam.optind = number(value);
1626 shellparam.optoff = -1;
1631 struct var *next; /* next entry in hash list */
1632 int flags; /* flags are defined above */
1633 const char *text; /* name=value */
1634 void (*func)(const char *); /* function to be called when */
1635 /* the variable gets set/unset */
1639 struct localvar *next; /* next local variable in list */
1640 struct var *vp; /* the variable that was made local */
1641 int flags; /* saved flags */
1642 const char *text; /* saved text */
1645 /* Forward decls for varinit[] */
1646 #if ENABLE_LOCALE_SUPPORT
1648 change_lc_all(const char *value)
1650 if (value && *value != '\0')
1651 setlocale(LC_ALL, value);
1654 change_lc_ctype(const char *value)
1656 if (value && *value != '\0')
1657 setlocale(LC_CTYPE, value);
1661 static void chkmail(void);
1662 static void changemail(const char *);
1664 static void changepath(const char *);
1665 #if ENABLE_ASH_RANDOM_SUPPORT
1666 static void change_random(const char *);
1669 static struct var varinit[] = {
1671 { NULL, VSTRFIXED|VTEXTFIXED, defifsvar, NULL },
1673 { NULL, VSTRFIXED|VTEXTFIXED|VUNSET, "IFS\0", NULL },
1676 { NULL, VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL\0", changemail },
1677 { NULL, VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH\0", changemail },
1679 { NULL, VSTRFIXED|VTEXTFIXED, bb_PATH_root_path, changepath },
1680 { NULL, VSTRFIXED|VTEXTFIXED, "PS1=$ ", NULL },
1681 { NULL, VSTRFIXED|VTEXTFIXED, "PS2=> ", NULL },
1682 { NULL, VSTRFIXED|VTEXTFIXED, "PS4=+ ", NULL },
1683 #if ENABLE_ASH_GETOPTS
1684 { NULL, VSTRFIXED|VTEXTFIXED, "OPTIND=1", getoptsreset },
1686 #if ENABLE_ASH_RANDOM_SUPPORT
1687 { NULL, VSTRFIXED|VTEXTFIXED|VUNSET|VDYNAMIC, "RANDOM\0", change_random },
1689 #if ENABLE_LOCALE_SUPPORT
1690 { NULL, VSTRFIXED | VTEXTFIXED | VUNSET, "LC_ALL\0", change_lc_all },
1691 { NULL, VSTRFIXED | VTEXTFIXED | VUNSET, "LC_CTYPE\0", change_lc_ctype },
1693 #if ENABLE_FEATURE_EDITING_SAVEHISTORY
1694 { NULL, VSTRFIXED | VTEXTFIXED | VUNSET, "HISTFILE\0", NULL },
1698 #define vifs varinit[0]
1700 #define vmail (&vifs)[1]
1701 #define vmpath (&vmail)[1]
1705 #define vpath (&vmpath)[1]
1706 #define vps1 (&vpath)[1]
1707 #define vps2 (&vps1)[1]
1708 #define vps4 (&vps2)[1]
1709 #define voptind (&vps4)[1]
1710 #if ENABLE_ASH_GETOPTS
1711 #define vrandom (&voptind)[1]
1713 #define vrandom (&vps4)[1]
1717 * The following macros access the values of the above variables.
1718 * They have to skip over the name. They return the null string
1719 * for unset variables.
1721 #define ifsval() (vifs.text + 4)
1722 #define ifsset() ((vifs.flags & VUNSET) == 0)
1723 #define mailval() (vmail.text + 5)
1724 #define mpathval() (vmpath.text + 9)
1725 #define pathval() (vpath.text + 5)
1726 #define ps1val() (vps1.text + 4)
1727 #define ps2val() (vps2.text + 4)
1728 #define ps4val() (vps4.text + 4)
1729 #define optindval() (voptind.text + 7)
1731 #define mpathset() ((vmpath.flags & VUNSET) == 0)
1734 * The parsefile structure pointed to by the global variable parsefile
1735 * contains information about the current file being read.
1738 struct redirtab *next;
1743 static struct redirtab *redirlist;
1744 static int nullredirs;
1745 static int preverrout_fd; /* save fd2 before print debug if xflag is set. */
1749 static struct var *vartab[VTABSIZE];
1751 #define is_name(c) ((c) == '_' || isalpha((unsigned char)(c)))
1752 #define is_in_name(c) ((c) == '_' || isalnum((unsigned char)(c)))
1755 * Return of a legal variable name (a letter or underscore followed by zero or
1756 * more letters, underscores, and digits).
1759 endofname(const char *name)
1767 if (!is_in_name(*p))
1774 * Compares two strings up to the first = or '\0'. The first
1775 * string must be terminated by '='; the second may be terminated by
1776 * either '=' or '\0'.
1779 varcmp(const char *p, const char *q)
1783 while ((c = *p) == (d = *q)) {
1798 varequal(const char *a, const char *b)
1800 return !varcmp(a, b);
1804 * Find the appropriate entry in the hash table from the name.
1806 static struct var **
1807 hashvar(const char *p)
1811 hashval = ((unsigned char) *p) << 4;
1812 while (*p && *p != '=')
1813 hashval += (unsigned char) *p++;
1814 return &vartab[hashval % VTABSIZE];
1818 vpcmp(const void *a, const void *b)
1820 return varcmp(*(const char **)a, *(const char **)b);
1824 * This routine initializes the builtin variables.
1834 * PS1 depends on uid
1836 #if ENABLE_FEATURE_EDITING && ENABLE_FEATURE_EDITING_FANCY_PROMPT
1837 vps1.text = "PS1=\\w \\$ ";
1840 vps1.text = "PS1=# ";
1843 end = vp + ARRAY_SIZE(varinit);
1845 vpp = hashvar(vp->text);
1848 } while (++vp < end);
1851 static struct var **
1852 findvar(struct var **vpp, const char *name)
1854 for (; *vpp; vpp = &(*vpp)->next) {
1855 if (varequal((*vpp)->text, name)) {
1863 * Find the value of a variable. Returns NULL if not set.
1866 lookupvar(const char *name)
1870 v = *findvar(hashvar(name), name);
1874 * Dynamic variables are implemented roughly the same way they are
1875 * in bash. Namely, they're "special" so long as they aren't unset.
1876 * As soon as they're unset, they're no longer dynamic, and dynamic
1877 * lookup will no longer happen at that point. -- PFM.
1879 if ((v->flags & VDYNAMIC))
1882 if (!(v->flags & VUNSET))
1883 return strchrnul(v->text, '=') + 1;
1889 * Search the environment of a builtin command.
1892 bltinlookup(const char *name)
1896 for (sp = cmdenviron; sp; sp = sp->next) {
1897 if (varequal(sp->text, name))
1898 return strchrnul(sp->text, '=') + 1;
1900 return lookupvar(name);
1904 * Same as setvar except that the variable and value are passed in
1905 * the first argument as name=value. Since the first argument will
1906 * be actually stored in the table, it should not be a string that
1908 * Called with interrupts off.
1911 setvareq(char *s, int flags)
1913 struct var *vp, **vpp;
1916 flags |= (VEXPORT & (((unsigned) (1 - aflag)) - 1));
1917 vp = *findvar(vpp, s);
1919 if ((vp->flags & (VREADONLY|VDYNAMIC)) == VREADONLY) {
1922 if (flags & VNOSAVE)
1925 ash_msg_and_raise_error("%.*s: is read only", strchrnul(n, '=') - n, n);
1931 if (vp->func && (flags & VNOFUNC) == 0)
1932 (*vp->func)(strchrnul(s, '=') + 1);
1934 if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
1935 free((char*)vp->text);
1937 flags |= vp->flags & ~(VTEXTFIXED|VSTACK|VNOSAVE|VUNSET);
1942 vp = ckmalloc(sizeof(*vp));
1947 if (!(flags & (VTEXTFIXED|VSTACK|VNOSAVE)))
1954 * Set the value of a variable. The flags argument is ored with the
1955 * flags of the variable. If val is NULL, the variable is unset.
1958 setvar(const char *name, const char *val, int flags)
1965 q = endofname(name);
1966 p = strchrnul(q, '=');
1968 if (!namelen || p != q)
1969 ash_msg_and_raise_error("%.*s: bad variable name", namelen, name);
1974 vallen = strlen(val);
1977 nameeq = ckmalloc(namelen + vallen + 2);
1978 p = memcpy(nameeq, name, namelen) + namelen;
1981 p = memcpy(p, val, vallen) + vallen;
1984 setvareq(nameeq, flags | VNOSAVE);
1988 #if ENABLE_ASH_GETOPTS
1990 * Safe version of setvar, returns 1 on success 0 on failure.
1993 setvarsafe(const char *name, const char *val, int flags)
1996 volatile int saveint;
1997 struct jmploc *volatile savehandler = exception_handler;
1998 struct jmploc jmploc;
2001 if (setjmp(jmploc.loc))
2004 exception_handler = &jmploc;
2005 setvar(name, val, flags);
2008 exception_handler = savehandler;
2009 RESTORE_INT(saveint);
2015 * Unset the specified variable.
2018 unsetvar(const char *s)
2024 vpp = findvar(hashvar(s), s);
2028 int flags = vp->flags;
2031 if (flags & VREADONLY)
2034 vp->flags &= ~VDYNAMIC;
2038 if ((flags & VSTRFIXED) == 0) {
2040 if ((flags & (VTEXTFIXED|VSTACK)) == 0)
2041 free((char*)vp->text);
2047 vp->flags &= ~VEXPORT;
2057 * Process a linked list of variable assignments.
2060 listsetvar(struct strlist *list_set_var, int flags)
2062 struct strlist *lp = list_set_var;
2068 setvareq(lp->text, flags);
2075 * Generate a list of variables satisfying the given conditions.
2078 listvars(int on, int off, char ***end)
2089 for (vp = *vpp; vp; vp = vp->next) {
2090 if ((vp->flags & mask) == on) {
2091 if (ep == stackstrend())
2092 ep = growstackstr();
2093 *ep++ = (char *) vp->text;
2096 } while (++vpp < vartab + VTABSIZE);
2097 if (ep == stackstrend())
2098 ep = growstackstr();
2102 return grabstackstr(ep);
2106 /* ============ Path search helper
2108 * The variable path (passed by reference) should be set to the start
2109 * of the path before the first call; padvance will update
2110 * this value as it proceeds. Successive calls to padvance will return
2111 * the possible path expansions in sequence. If an option (indicated by
2112 * a percent sign) appears in the path entry then the global variable
2113 * pathopt will be set to point to it; otherwise pathopt will be set to
2116 static const char *pathopt; /* set by padvance */
2119 padvance(const char **path, const char *name)
2129 for (p = start; *p && *p != ':' && *p != '%'; p++);
2130 len = p - start + strlen(name) + 2; /* "2" is for '/' and '\0' */
2131 while (stackblocksize() < len)
2135 memcpy(q, start, p - start);
2143 while (*p && *p != ':') p++;
2149 return stalloc(len);
2153 /* ============ Prompt */
2155 static smallint doprompt; /* if set, prompt the user */
2156 static smallint needprompt; /* true if interactive and at start of line */
2158 #if ENABLE_FEATURE_EDITING
2159 static line_input_t *line_input_state;
2160 static const char *cmdedit_prompt;
2162 putprompt(const char *s)
2164 if (ENABLE_ASH_EXPAND_PRMT) {
2165 free((char*)cmdedit_prompt);
2166 cmdedit_prompt = ckstrdup(s);
2173 putprompt(const char *s)
2179 #if ENABLE_ASH_EXPAND_PRMT
2180 /* expandstr() needs parsing machinery, so it is far away ahead... */
2181 static const char *expandstr(const char *ps);
2183 #define expandstr(s) s
2187 setprompt(int whichprompt)
2190 #if ENABLE_ASH_EXPAND_PRMT
2191 struct stackmark smark;
2196 switch (whichprompt) {
2206 #if ENABLE_ASH_EXPAND_PRMT
2207 setstackmark(&smark);
2208 stalloc(stackblocksize());
2210 putprompt(expandstr(prompt));
2211 #if ENABLE_ASH_EXPAND_PRMT
2212 popstackmark(&smark);
2217 /* ============ The cd and pwd commands */
2219 #define CD_PHYSICAL 1
2222 static int docd(const char *, int);
2224 static char *curdir = nullstr; /* current working directory */
2225 static char *physdir = nullstr; /* physical working directory */
2234 while ((i = nextopt("LP"))) {
2236 flags ^= CD_PHYSICAL;
2245 * Update curdir (the name of the current directory) in response to a
2249 updatepwd(const char *dir)
2256 cdcomppath = ststrdup(dir);
2259 if (curdir == nullstr)
2261 new = stack_putstr(curdir, new);
2263 new = makestrspace(strlen(dir) + 2, new);
2264 lim = stackblock() + 1;
2268 if (new > lim && *lim == '/')
2273 if (dir[1] == '/' && dir[2] != '/') {
2279 p = strtok(cdcomppath, "/");
2283 if (p[1] == '.' && p[2] == '\0') {
2295 new = stack_putstr(p, new);
2303 return stackblock();
2307 * Find out what the current directory is. If we already know the current
2308 * directory, this routine returns immediately.
2313 char *dir = getcwd(0, 0);
2314 return dir ? dir : nullstr;
2318 setpwd(const char *val, int setold)
2322 oldcur = dir = curdir;
2325 setvar("OLDPWD", oldcur, VEXPORT);
2328 if (physdir != nullstr) {
2329 if (physdir != oldcur)
2333 if (oldcur == val || !val) {
2339 dir = ckstrdup(val);
2340 if (oldcur != dir && oldcur != nullstr) {
2345 setvar("PWD", dir, VEXPORT);
2348 static void hashcd(void);
2351 * Actually do the chdir. We also call hashcd to let the routines in exec.c
2352 * know that the current directory has changed.
2355 docd(const char *dest, int flags)
2357 const char *dir = 0;
2360 TRACE(("docd(\"%s\", %d) called\n", dest, flags));
2363 if (!(flags & CD_PHYSICAL)) {
2364 dir = updatepwd(dest);
2379 cdcmd(int argc, char **argv)
2391 dest = bltinlookup(homestr);
2392 else if (LONE_DASH(dest)) {
2393 dest = bltinlookup("OLDPWD");
2415 path = bltinlookup("CDPATH");
2424 p = padvance(&path, dest);
2425 if (stat(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) {
2429 if (!docd(p, flags))
2434 ash_msg_and_raise_error("can't cd to %s", dest);
2437 if (flags & CD_PRINT)
2438 out1fmt(snlfmt, curdir);
2443 pwdcmd(int argc, char **argv)
2446 const char *dir = curdir;
2450 if (physdir == nullstr)
2454 out1fmt(snlfmt, dir);
2459 /* ============ ... */
2461 #define IBUFSIZ COMMON_BUFSIZE
2462 #define basebuf bb_common_bufsiz1 /* buffer for top level input file */
2464 /* Syntax classes */
2465 #define CWORD 0 /* character is nothing special */
2466 #define CNL 1 /* newline character */
2467 #define CBACK 2 /* a backslash character */
2468 #define CSQUOTE 3 /* single quote */
2469 #define CDQUOTE 4 /* double quote */
2470 #define CENDQUOTE 5 /* a terminating quote */
2471 #define CBQUOTE 6 /* backwards single quote */
2472 #define CVAR 7 /* a dollar sign */
2473 #define CENDVAR 8 /* a '}' character */
2474 #define CLP 9 /* a left paren in arithmetic */
2475 #define CRP 10 /* a right paren in arithmetic */
2476 #define CENDFILE 11 /* end of file */
2477 #define CCTL 12 /* like CWORD, except it must be escaped */
2478 #define CSPCL 13 /* these terminate a word */
2479 #define CIGN 14 /* character should be ignored */
2481 #if ENABLE_ASH_ALIAS
2485 #define PEOA_OR_PEOF PEOA
2489 #define PEOA_OR_PEOF PEOF
2492 /* number syntax index */
2493 #define BASESYNTAX 0 /* not in quotes */
2494 #define DQSYNTAX 1 /* in double quotes */
2495 #define SQSYNTAX 2 /* in single quotes */
2496 #define ARISYNTAX 3 /* in arithmetic */
2497 #define PSSYNTAX 4 /* prompt */
2499 #if ENABLE_ASH_OPTIMIZE_FOR_SIZE
2500 #define USE_SIT_FUNCTION
2503 #if ENABLE_ASH_MATH_SUPPORT
2504 static const char S_I_T[][4] = {
2505 #if ENABLE_ASH_ALIAS
2506 { CSPCL, CIGN, CIGN, CIGN }, /* 0, PEOA */
2508 { CSPCL, CWORD, CWORD, CWORD }, /* 1, ' ' */
2509 { CNL, CNL, CNL, CNL }, /* 2, \n */
2510 { CWORD, CCTL, CCTL, CWORD }, /* 3, !*-/:=?[]~ */
2511 { CDQUOTE, CENDQUOTE, CWORD, CWORD }, /* 4, '"' */
2512 { CVAR, CVAR, CWORD, CVAR }, /* 5, $ */
2513 { CSQUOTE, CWORD, CENDQUOTE, CWORD }, /* 6, "'" */
2514 { CSPCL, CWORD, CWORD, CLP }, /* 7, ( */
2515 { CSPCL, CWORD, CWORD, CRP }, /* 8, ) */
2516 { CBACK, CBACK, CCTL, CBACK }, /* 9, \ */
2517 { CBQUOTE, CBQUOTE, CWORD, CBQUOTE }, /* 10, ` */
2518 { CENDVAR, CENDVAR, CWORD, CENDVAR }, /* 11, } */
2519 #ifndef USE_SIT_FUNCTION
2520 { CENDFILE, CENDFILE, CENDFILE, CENDFILE }, /* 12, PEOF */
2521 { CWORD, CWORD, CWORD, CWORD }, /* 13, 0-9A-Za-z */
2522 { CCTL, CCTL, CCTL, CCTL } /* 14, CTLESC ... */
2526 static const char S_I_T[][3] = {
2527 #if ENABLE_ASH_ALIAS
2528 { CSPCL, CIGN, CIGN }, /* 0, PEOA */
2530 { CSPCL, CWORD, CWORD }, /* 1, ' ' */
2531 { CNL, CNL, CNL }, /* 2, \n */
2532 { CWORD, CCTL, CCTL }, /* 3, !*-/:=?[]~ */
2533 { CDQUOTE, CENDQUOTE, CWORD }, /* 4, '"' */
2534 { CVAR, CVAR, CWORD }, /* 5, $ */
2535 { CSQUOTE, CWORD, CENDQUOTE }, /* 6, "'" */
2536 { CSPCL, CWORD, CWORD }, /* 7, ( */
2537 { CSPCL, CWORD, CWORD }, /* 8, ) */
2538 { CBACK, CBACK, CCTL }, /* 9, \ */
2539 { CBQUOTE, CBQUOTE, CWORD }, /* 10, ` */
2540 { CENDVAR, CENDVAR, CWORD }, /* 11, } */
2541 #ifndef USE_SIT_FUNCTION
2542 { CENDFILE, CENDFILE, CENDFILE }, /* 12, PEOF */
2543 { CWORD, CWORD, CWORD }, /* 13, 0-9A-Za-z */
2544 { CCTL, CCTL, CCTL } /* 14, CTLESC ... */
2547 #endif /* ASH_MATH_SUPPORT */
2549 #ifdef USE_SIT_FUNCTION
2552 SIT(int c, int syntax)
2554 static const char spec_symbls[] ALIGN1 = "\t\n !\"$&'()*-/:;<=>?[\\]`|}~";
2555 #if ENABLE_ASH_ALIAS
2556 static const char syntax_index_table[] ALIGN1 = {
2557 1, 2, 1, 3, 4, 5, 1, 6, /* "\t\n !\"$&'" */
2558 7, 8, 3, 3, 3, 3, 1, 1, /* "()*-/:;<" */
2559 3, 1, 3, 3, 9, 3, 10, 1, /* "=>?[\\]`|" */
2563 static const char syntax_index_table[] ALIGN1 = {
2564 0, 1, 0, 2, 3, 4, 0, 5, /* "\t\n !\"$&'" */
2565 6, 7, 2, 2, 2, 2, 0, 0, /* "()*-/:;<" */
2566 2, 0, 2, 2, 8, 2, 9, 0, /* "=>?[\\]`|" */
2573 if (c == PEOF) /* 2^8+2 */
2575 #if ENABLE_ASH_ALIAS
2576 if (c == PEOA) /* 2^8+1 */
2580 #define U_C(c) ((unsigned char)(c))
2582 if ((unsigned char)c >= (unsigned char)(CTLESC)
2583 && (unsigned char)c <= (unsigned char)(CTLQUOTEMARK)
2587 s = strchr(spec_symbls, c);
2588 if (s == NULL || *s == '\0')
2590 indx = syntax_index_table[(s - spec_symbls)];
2592 return S_I_T[indx][syntax];
2595 #else /* !USE_SIT_FUNCTION */
2597 #if ENABLE_ASH_ALIAS
2598 #define CSPCL_CIGN_CIGN_CIGN 0
2599 #define CSPCL_CWORD_CWORD_CWORD 1
2600 #define CNL_CNL_CNL_CNL 2
2601 #define CWORD_CCTL_CCTL_CWORD 3
2602 #define CDQUOTE_CENDQUOTE_CWORD_CWORD 4
2603 #define CVAR_CVAR_CWORD_CVAR 5
2604 #define CSQUOTE_CWORD_CENDQUOTE_CWORD 6
2605 #define CSPCL_CWORD_CWORD_CLP 7
2606 #define CSPCL_CWORD_CWORD_CRP 8
2607 #define CBACK_CBACK_CCTL_CBACK 9
2608 #define CBQUOTE_CBQUOTE_CWORD_CBQUOTE 10
2609 #define CENDVAR_CENDVAR_CWORD_CENDVAR 11
2610 #define CENDFILE_CENDFILE_CENDFILE_CENDFILE 12
2611 #define CWORD_CWORD_CWORD_CWORD 13
2612 #define CCTL_CCTL_CCTL_CCTL 14
2614 #define CSPCL_CWORD_CWORD_CWORD 0
2615 #define CNL_CNL_CNL_CNL 1
2616 #define CWORD_CCTL_CCTL_CWORD 2
2617 #define CDQUOTE_CENDQUOTE_CWORD_CWORD 3
2618 #define CVAR_CVAR_CWORD_CVAR 4
2619 #define CSQUOTE_CWORD_CENDQUOTE_CWORD 5
2620 #define CSPCL_CWORD_CWORD_CLP 6
2621 #define CSPCL_CWORD_CWORD_CRP 7
2622 #define CBACK_CBACK_CCTL_CBACK 8
2623 #define CBQUOTE_CBQUOTE_CWORD_CBQUOTE 9
2624 #define CENDVAR_CENDVAR_CWORD_CENDVAR 10
2625 #define CENDFILE_CENDFILE_CENDFILE_CENDFILE 11
2626 #define CWORD_CWORD_CWORD_CWORD 12
2627 #define CCTL_CCTL_CCTL_CCTL 13
2630 static const char syntax_index_table[258] = {
2631 /* BASESYNTAX_DQSYNTAX_SQSYNTAX_ARISYNTAX */
2632 /* 0 PEOF */ CENDFILE_CENDFILE_CENDFILE_CENDFILE,
2633 #if ENABLE_ASH_ALIAS
2634 /* 1 PEOA */ CSPCL_CIGN_CIGN_CIGN,
2636 /* 2 -128 0x80 */ CWORD_CWORD_CWORD_CWORD,
2637 /* 3 -127 CTLESC */ CCTL_CCTL_CCTL_CCTL,
2638 /* 4 -126 CTLVAR */ CCTL_CCTL_CCTL_CCTL,
2639 /* 5 -125 CTLENDVAR */ CCTL_CCTL_CCTL_CCTL,
2640 /* 6 -124 CTLBACKQ */ CCTL_CCTL_CCTL_CCTL,
2641 /* 7 -123 CTLQUOTE */ CCTL_CCTL_CCTL_CCTL,
2642 /* 8 -122 CTLARI */ CCTL_CCTL_CCTL_CCTL,
2643 /* 9 -121 CTLENDARI */ CCTL_CCTL_CCTL_CCTL,
2644 /* 10 -120 CTLQUOTEMARK */ CCTL_CCTL_CCTL_CCTL,
2645 /* 11 -119 */ CWORD_CWORD_CWORD_CWORD,
2646 /* 12 -118 */ CWORD_CWORD_CWORD_CWORD,
2647 /* 13 -117 */ CWORD_CWORD_CWORD_CWORD,
2648 /* 14 -116 */ CWORD_CWORD_CWORD_CWORD,
2649 /* 15 -115 */ CWORD_CWORD_CWORD_CWORD,
2650 /* 16 -114 */ CWORD_CWORD_CWORD_CWORD,
2651 /* 17 -113 */ CWORD_CWORD_CWORD_CWORD,
2652 /* 18 -112 */ CWORD_CWORD_CWORD_CWORD,
2653 /* 19 -111 */ CWORD_CWORD_CWORD_CWORD,
2654 /* 20 -110 */ CWORD_CWORD_CWORD_CWORD,
2655 /* 21 -109 */ CWORD_CWORD_CWORD_CWORD,
2656 /* 22 -108 */ CWORD_CWORD_CWORD_CWORD,
2657 /* 23 -107 */ CWORD_CWORD_CWORD_CWORD,
2658 /* 24 -106 */ CWORD_CWORD_CWORD_CWORD,
2659 /* 25 -105 */ CWORD_CWORD_CWORD_CWORD,
2660 /* 26 -104 */ CWORD_CWORD_CWORD_CWORD,
2661 /* 27 -103 */ CWORD_CWORD_CWORD_CWORD,
2662 /* 28 -102 */ CWORD_CWORD_CWORD_CWORD,
2663 /* 29 -101 */ CWORD_CWORD_CWORD_CWORD,
2664 /* 30 -100 */ CWORD_CWORD_CWORD_CWORD,
2665 /* 31 -99 */ CWORD_CWORD_CWORD_CWORD,
2666 /* 32 -98 */ CWORD_CWORD_CWORD_CWORD,
2667 /* 33 -97 */ CWORD_CWORD_CWORD_CWORD,
2668 /* 34 -96 */ CWORD_CWORD_CWORD_CWORD,
2669 /* 35 -95 */ CWORD_CWORD_CWORD_CWORD,
2670 /* 36 -94 */ CWORD_CWORD_CWORD_CWORD,
2671 /* 37 -93 */ CWORD_CWORD_CWORD_CWORD,
2672 /* 38 -92 */ CWORD_CWORD_CWORD_CWORD,
2673 /* 39 -91 */ CWORD_CWORD_CWORD_CWORD,
2674 /* 40 -90 */ CWORD_CWORD_CWORD_CWORD,
2675 /* 41 -89 */ CWORD_CWORD_CWORD_CWORD,
2676 /* 42 -88 */ CWORD_CWORD_CWORD_CWORD,
2677 /* 43 -87 */ CWORD_CWORD_CWORD_CWORD,
2678 /* 44 -86 */ CWORD_CWORD_CWORD_CWORD,
2679 /* 45 -85 */ CWORD_CWORD_CWORD_CWORD,
2680 /* 46 -84 */ CWORD_CWORD_CWORD_CWORD,
2681 /* 47 -83 */ CWORD_CWORD_CWORD_CWORD,
2682 /* 48 -82 */ CWORD_CWORD_CWORD_CWORD,
2683 /* 49 -81 */ CWORD_CWORD_CWORD_CWORD,
2684 /* 50 -80 */ CWORD_CWORD_CWORD_CWORD,
2685 /* 51 -79 */ CWORD_CWORD_CWORD_CWORD,
2686 /* 52 -78 */ CWORD_CWORD_CWORD_CWORD,
2687 /* 53 -77 */ CWORD_CWORD_CWORD_CWORD,
2688 /* 54 -76 */ CWORD_CWORD_CWORD_CWORD,
2689 /* 55 -75 */ CWORD_CWORD_CWORD_CWORD,
2690 /* 56 -74 */ CWORD_CWORD_CWORD_CWORD,
2691 /* 57 -73 */ CWORD_CWORD_CWORD_CWORD,
2692 /* 58 -72 */ CWORD_CWORD_CWORD_CWORD,
2693 /* 59 -71 */ CWORD_CWORD_CWORD_CWORD,
2694 /* 60 -70 */ CWORD_CWORD_CWORD_CWORD,
2695 /* 61 -69 */ CWORD_CWORD_CWORD_CWORD,
2696 /* 62 -68 */ CWORD_CWORD_CWORD_CWORD,
2697 /* 63 -67 */ CWORD_CWORD_CWORD_CWORD,
2698 /* 64 -66 */ CWORD_CWORD_CWORD_CWORD,
2699 /* 65 -65 */ CWORD_CWORD_CWORD_CWORD,
2700 /* 66 -64 */ CWORD_CWORD_CWORD_CWORD,
2701 /* 67 -63 */ CWORD_CWORD_CWORD_CWORD,
2702 /* 68 -62 */ CWORD_CWORD_CWORD_CWORD,
2703 /* 69 -61 */ CWORD_CWORD_CWORD_CWORD,
2704 /* 70 -60 */ CWORD_CWORD_CWORD_CWORD,
2705 /* 71 -59 */ CWORD_CWORD_CWORD_CWORD,
2706 /* 72 -58 */ CWORD_CWORD_CWORD_CWORD,
2707 /* 73 -57 */ CWORD_CWORD_CWORD_CWORD,
2708 /* 74 -56 */ CWORD_CWORD_CWORD_CWORD,
2709 /* 75 -55 */ CWORD_CWORD_CWORD_CWORD,
2710 /* 76 -54 */ CWORD_CWORD_CWORD_CWORD,
2711 /* 77 -53 */ CWORD_CWORD_CWORD_CWORD,
2712 /* 78 -52 */ CWORD_CWORD_CWORD_CWORD,
2713 /* 79 -51 */ CWORD_CWORD_CWORD_CWORD,
2714 /* 80 -50 */ CWORD_CWORD_CWORD_CWORD,
2715 /* 81 -49 */ CWORD_CWORD_CWORD_CWORD,
2716 /* 82 -48 */ CWORD_CWORD_CWORD_CWORD,
2717 /* 83 -47 */ CWORD_CWORD_CWORD_CWORD,
2718 /* 84 -46 */ CWORD_CWORD_CWORD_CWORD,
2719 /* 85 -45 */ CWORD_CWORD_CWORD_CWORD,
2720 /* 86 -44 */ CWORD_CWORD_CWORD_CWORD,
2721 /* 87 -43 */ CWORD_CWORD_CWORD_CWORD,
2722 /* 88 -42 */ CWORD_CWORD_CWORD_CWORD,
2723 /* 89 -41 */ CWORD_CWORD_CWORD_CWORD,
2724 /* 90 -40 */ CWORD_CWORD_CWORD_CWORD,
2725 /* 91 -39 */ CWORD_CWORD_CWORD_CWORD,
2726 /* 92 -38 */ CWORD_CWORD_CWORD_CWORD,
2727 /* 93 -37 */ CWORD_CWORD_CWORD_CWORD,
2728 /* 94 -36 */ CWORD_CWORD_CWORD_CWORD,
2729 /* 95 -35 */ CWORD_CWORD_CWORD_CWORD,
2730 /* 96 -34 */ CWORD_CWORD_CWORD_CWORD,
2731 /* 97 -33 */ CWORD_CWORD_CWORD_CWORD,
2732 /* 98 -32 */ CWORD_CWORD_CWORD_CWORD,
2733 /* 99 -31 */ CWORD_CWORD_CWORD_CWORD,
2734 /* 100 -30 */ CWORD_CWORD_CWORD_CWORD,
2735 /* 101 -29 */ CWORD_CWORD_CWORD_CWORD,
2736 /* 102 -28 */ CWORD_CWORD_CWORD_CWORD,
2737 /* 103 -27 */ CWORD_CWORD_CWORD_CWORD,
2738 /* 104 -26 */ CWORD_CWORD_CWORD_CWORD,
2739 /* 105 -25 */ CWORD_CWORD_CWORD_CWORD,
2740 /* 106 -24 */ CWORD_CWORD_CWORD_CWORD,
2741 /* 107 -23 */ CWORD_CWORD_CWORD_CWORD,
2742 /* 108 -22 */ CWORD_CWORD_CWORD_CWORD,
2743 /* 109 -21 */ CWORD_CWORD_CWORD_CWORD,
2744 /* 110 -20 */ CWORD_CWORD_CWORD_CWORD,
2745 /* 111 -19 */ CWORD_CWORD_CWORD_CWORD,
2746 /* 112 -18 */ CWORD_CWORD_CWORD_CWORD,
2747 /* 113 -17 */ CWORD_CWORD_CWORD_CWORD,
2748 /* 114 -16 */ CWORD_CWORD_CWORD_CWORD,
2749 /* 115 -15 */ CWORD_CWORD_CWORD_CWORD,
2750 /* 116 -14 */ CWORD_CWORD_CWORD_CWORD,
2751 /* 117 -13 */ CWORD_CWORD_CWORD_CWORD,
2752 /* 118 -12 */ CWORD_CWORD_CWORD_CWORD,
2753 /* 119 -11 */ CWORD_CWORD_CWORD_CWORD,
2754 /* 120 -10 */ CWORD_CWORD_CWORD_CWORD,
2755 /* 121 -9 */ CWORD_CWORD_CWORD_CWORD,
2756 /* 122 -8 */ CWORD_CWORD_CWORD_CWORD,
2757 /* 123 -7 */ CWORD_CWORD_CWORD_CWORD,
2758 /* 124 -6 */ CWORD_CWORD_CWORD_CWORD,
2759 /* 125 -5 */ CWORD_CWORD_CWORD_CWORD,
2760 /* 126 -4 */ CWORD_CWORD_CWORD_CWORD,
2761 /* 127 -3 */ CWORD_CWORD_CWORD_CWORD,
2762 /* 128 -2 */ CWORD_CWORD_CWORD_CWORD,
2763 /* 129 -1 */ CWORD_CWORD_CWORD_CWORD,
2764 /* 130 0 */ CWORD_CWORD_CWORD_CWORD,
2765 /* 131 1 */ CWORD_CWORD_CWORD_CWORD,
2766 /* 132 2 */ CWORD_CWORD_CWORD_CWORD,
2767 /* 133 3 */ CWORD_CWORD_CWORD_CWORD,
2768 /* 134 4 */ CWORD_CWORD_CWORD_CWORD,
2769 /* 135 5 */ CWORD_CWORD_CWORD_CWORD,
2770 /* 136 6 */ CWORD_CWORD_CWORD_CWORD,
2771 /* 137 7 */ CWORD_CWORD_CWORD_CWORD,
2772 /* 138 8 */ CWORD_CWORD_CWORD_CWORD,
2773 /* 139 9 "\t" */ CSPCL_CWORD_CWORD_CWORD,
2774 /* 140 10 "\n" */ CNL_CNL_CNL_CNL,
2775 /* 141 11 */ CWORD_CWORD_CWORD_CWORD,
2776 /* 142 12 */ CWORD_CWORD_CWORD_CWORD,
2777 /* 143 13 */ CWORD_CWORD_CWORD_CWORD,
2778 /* 144 14 */ CWORD_CWORD_CWORD_CWORD,
2779 /* 145 15 */ CWORD_CWORD_CWORD_CWORD,
2780 /* 146 16 */ CWORD_CWORD_CWORD_CWORD,
2781 /* 147 17 */ CWORD_CWORD_CWORD_CWORD,
2782 /* 148 18 */ CWORD_CWORD_CWORD_CWORD,
2783 /* 149 19 */ CWORD_CWORD_CWORD_CWORD,
2784 /* 150 20 */ CWORD_CWORD_CWORD_CWORD,
2785 /* 151 21 */ CWORD_CWORD_CWORD_CWORD,
2786 /* 152 22 */ CWORD_CWORD_CWORD_CWORD,
2787 /* 153 23 */ CWORD_CWORD_CWORD_CWORD,
2788 /* 154 24 */ CWORD_CWORD_CWORD_CWORD,
2789 /* 155 25 */ CWORD_CWORD_CWORD_CWORD,
2790 /* 156 26 */ CWORD_CWORD_CWORD_CWORD,
2791 /* 157 27 */ CWORD_CWORD_CWORD_CWORD,
2792 /* 158 28 */ CWORD_CWORD_CWORD_CWORD,
2793 /* 159 29 */ CWORD_CWORD_CWORD_CWORD,
2794 /* 160 30 */ CWORD_CWORD_CWORD_CWORD,
2795 /* 161 31 */ CWORD_CWORD_CWORD_CWORD,
2796 /* 162 32 " " */ CSPCL_CWORD_CWORD_CWORD,
2797 /* 163 33 "!" */ CWORD_CCTL_CCTL_CWORD,
2798 /* 164 34 """ */ CDQUOTE_CENDQUOTE_CWORD_CWORD,
2799 /* 165 35 "#" */ CWORD_CWORD_CWORD_CWORD,
2800 /* 166 36 "$" */ CVAR_CVAR_CWORD_CVAR,
2801 /* 167 37 "%" */ CWORD_CWORD_CWORD_CWORD,
2802 /* 168 38 "&" */ CSPCL_CWORD_CWORD_CWORD,
2803 /* 169 39 "'" */ CSQUOTE_CWORD_CENDQUOTE_CWORD,
2804 /* 170 40 "(" */ CSPCL_CWORD_CWORD_CLP,
2805 /* 171 41 ")" */ CSPCL_CWORD_CWORD_CRP,
2806 /* 172 42 "*" */ CWORD_CCTL_CCTL_CWORD,
2807 /* 173 43 "+" */ CWORD_CWORD_CWORD_CWORD,
2808 /* 174 44 "," */ CWORD_CWORD_CWORD_CWORD,
2809 /* 175 45 "-" */ CWORD_CCTL_CCTL_CWORD,
2810 /* 176 46 "." */ CWORD_CWORD_CWORD_CWORD,
2811 /* 177 47 "/" */ CWORD_CCTL_CCTL_CWORD,
2812 /* 178 48 "0" */ CWORD_CWORD_CWORD_CWORD,
2813 /* 179 49 "1" */ CWORD_CWORD_CWORD_CWORD,
2814 /* 180 50 "2" */ CWORD_CWORD_CWORD_CWORD,
2815 /* 181 51 "3" */ CWORD_CWORD_CWORD_CWORD,
2816 /* 182 52 "4" */ CWORD_CWORD_CWORD_CWORD,
2817 /* 183 53 "5" */ CWORD_CWORD_CWORD_CWORD,
2818 /* 184 54 "6" */ CWORD_CWORD_CWORD_CWORD,
2819 /* 185 55 "7" */ CWORD_CWORD_CWORD_CWORD,
2820 /* 186 56 "8" */ CWORD_CWORD_CWORD_CWORD,
2821 /* 187 57 "9" */ CWORD_CWORD_CWORD_CWORD,
2822 /* 188 58 ":" */ CWORD_CCTL_CCTL_CWORD,
2823 /* 189 59 ";" */ CSPCL_CWORD_CWORD_CWORD,
2824 /* 190 60 "<" */ CSPCL_CWORD_CWORD_CWORD,
2825 /* 191 61 "=" */ CWORD_CCTL_CCTL_CWORD,
2826 /* 192 62 ">" */ CSPCL_CWORD_CWORD_CWORD,
2827 /* 193 63 "?" */ CWORD_CCTL_CCTL_CWORD,
2828 /* 194 64 "@" */ CWORD_CWORD_CWORD_CWORD,
2829 /* 195 65 "A" */ CWORD_CWORD_CWORD_CWORD,
2830 /* 196 66 "B" */ CWORD_CWORD_CWORD_CWORD,
2831 /* 197 67 "C" */ CWORD_CWORD_CWORD_CWORD,
2832 /* 198 68 "D" */ CWORD_CWORD_CWORD_CWORD,
2833 /* 199 69 "E" */ CWORD_CWORD_CWORD_CWORD,
2834 /* 200 70 "F" */ CWORD_CWORD_CWORD_CWORD,
2835 /* 201 71 "G" */ CWORD_CWORD_CWORD_CWORD,
2836 /* 202 72 "H" */ CWORD_CWORD_CWORD_CWORD,
2837 /* 203 73 "I" */ CWORD_CWORD_CWORD_CWORD,
2838 /* 204 74 "J" */ CWORD_CWORD_CWORD_CWORD,
2839 /* 205 75 "K" */ CWORD_CWORD_CWORD_CWORD,
2840 /* 206 76 "L" */ CWORD_CWORD_CWORD_CWORD,
2841 /* 207 77 "M" */ CWORD_CWORD_CWORD_CWORD,
2842 /* 208 78 "N" */ CWORD_CWORD_CWORD_CWORD,
2843 /* 209 79 "O" */ CWORD_CWORD_CWORD_CWORD,
2844 /* 210 80 "P" */ CWORD_CWORD_CWORD_CWORD,
2845 /* 211 81 "Q" */ CWORD_CWORD_CWORD_CWORD,
2846 /* 212 82 "R" */ CWORD_CWORD_CWORD_CWORD,
2847 /* 213 83 "S" */ CWORD_CWORD_CWORD_CWORD,
2848 /* 214 84 "T" */ CWORD_CWORD_CWORD_CWORD,
2849 /* 215 85 "U" */ CWORD_CWORD_CWORD_CWORD,
2850 /* 216 86 "V" */ CWORD_CWORD_CWORD_CWORD,
2851 /* 217 87 "W" */ CWORD_CWORD_CWORD_CWORD,
2852 /* 218 88 "X" */ CWORD_CWORD_CWORD_CWORD,
2853 /* 219 89 "Y" */ CWORD_CWORD_CWORD_CWORD,
2854 /* 220 90 "Z" */ CWORD_CWORD_CWORD_CWORD,
2855 /* 221 91 "[" */ CWORD_CCTL_CCTL_CWORD,
2856 /* 222 92 "\" */ CBACK_CBACK_CCTL_CBACK,
2857 /* 223 93 "]" */ CWORD_CCTL_CCTL_CWORD,
2858 /* 224 94 "^" */ CWORD_CWORD_CWORD_CWORD,
2859 /* 225 95 "_" */ CWORD_CWORD_CWORD_CWORD,
2860 /* 226 96 "`" */ CBQUOTE_CBQUOTE_CWORD_CBQUOTE,
2861 /* 227 97 "a" */ CWORD_CWORD_CWORD_CWORD,
2862 /* 228 98 "b" */ CWORD_CWORD_CWORD_CWORD,
2863 /* 229 99 "c" */ CWORD_CWORD_CWORD_CWORD,
2864 /* 230 100 "d" */ CWORD_CWORD_CWORD_CWORD,
2865 /* 231 101 "e" */ CWORD_CWORD_CWORD_CWORD,
2866 /* 232 102 "f" */ CWORD_CWORD_CWORD_CWORD,
2867 /* 233 103 "g" */ CWORD_CWORD_CWORD_CWORD,
2868 /* 234 104 "h" */ CWORD_CWORD_CWORD_CWORD,
2869 /* 235 105 "i" */ CWORD_CWORD_CWORD_CWORD,
2870 /* 236 106 "j" */ CWORD_CWORD_CWORD_CWORD,
2871 /* 237 107 "k" */ CWORD_CWORD_CWORD_CWORD,
2872 /* 238 108 "l" */ CWORD_CWORD_CWORD_CWORD,
2873 /* 239 109 "m" */ CWORD_CWORD_CWORD_CWORD,
2874 /* 240 110 "n" */ CWORD_CWORD_CWORD_CWORD,
2875 /* 241 111 "o" */ CWORD_CWORD_CWORD_CWORD,
2876 /* 242 112 "p" */ CWORD_CWORD_CWORD_CWORD,
2877 /* 243 113 "q" */ CWORD_CWORD_CWORD_CWORD,
2878 /* 244 114 "r" */ CWORD_CWORD_CWORD_CWORD,
2879 /* 245 115 "s" */ CWORD_CWORD_CWORD_CWORD,
2880 /* 246 116 "t" */ CWORD_CWORD_CWORD_CWORD,
2881 /* 247 117 "u" */ CWORD_CWORD_CWORD_CWORD,
2882 /* 248 118 "v" */ CWORD_CWORD_CWORD_CWORD,
2883 /* 249 119 "w" */ CWORD_CWORD_CWORD_CWORD,
2884 /* 250 120 "x" */ CWORD_CWORD_CWORD_CWORD,
2885 /* 251 121 "y" */ CWORD_CWORD_CWORD_CWORD,
2886 /* 252 122 "z" */ CWORD_CWORD_CWORD_CWORD,
2887 /* 253 123 "{" */ CWORD_CWORD_CWORD_CWORD,
2888 /* 254 124 "|" */ CSPCL_CWORD_CWORD_CWORD,
2889 /* 255 125 "}" */ CENDVAR_CENDVAR_CWORD_CENDVAR,
2890 /* 256 126 "~" */ CWORD_CCTL_CCTL_CWORD,
2891 /* 257 127 */ CWORD_CWORD_CWORD_CWORD,
2894 #define SIT(c, syntax) (S_I_T[(int)syntax_index_table[((int)c)+SYNBASE]][syntax])
2896 #endif /* USE_SIT_FUNCTION */
2899 /* ============ Alias handling */
2901 #if ENABLE_ASH_ALIAS
2903 #define ALIASINUSE 1
2915 static struct alias *atab[ATABSIZE];
2917 static struct alias **
2918 __lookupalias(const char *name) {
2919 unsigned int hashval;
2926 ch = (unsigned char)*p;
2930 ch = (unsigned char)*++p;
2932 app = &atab[hashval % ATABSIZE];
2934 for (; *app; app = &(*app)->next) {
2935 if (strcmp(name, (*app)->name) == 0) {
2943 static struct alias *
2944 lookupalias(const char *name, int check)
2946 struct alias *ap = *__lookupalias(name);
2948 if (check && ap && (ap->flag & ALIASINUSE))
2953 static struct alias *
2954 freealias(struct alias *ap)
2958 if (ap->flag & ALIASINUSE) {
2959 ap->flag |= ALIASDEAD;
2971 setalias(const char *name, const char *val)
2973 struct alias *ap, **app;
2975 app = __lookupalias(name);
2979 if (!(ap->flag & ALIASINUSE)) {
2982 ap->val = ckstrdup(val);
2983 ap->flag &= ~ALIASDEAD;
2986 ap = ckmalloc(sizeof(struct alias));
2987 ap->name = ckstrdup(name);
2988 ap->val = ckstrdup(val);
2997 unalias(const char *name)
3001 app = __lookupalias(name);
3005 *app = freealias(*app);
3016 struct alias *ap, **app;
3020 for (i = 0; i < ATABSIZE; i++) {
3022 for (ap = *app; ap; ap = *app) {
3023 *app = freealias(*app);
3033 printalias(const struct alias *ap)
3035 out1fmt("%s=%s\n", ap->name, single_quote(ap->val));
3039 * TODO - sort output
3042 aliascmd(int argc, char **argv)
3051 for (i = 0; i < ATABSIZE; i++)
3052 for (ap = atab[i]; ap; ap = ap->next) {
3057 while ((n = *++argv) != NULL) {
3058 v = strchr(n+1, '=');
3059 if (v == NULL) { /* n+1: funny ksh stuff */
3060 ap = *__lookupalias(n);
3062 fprintf(stderr, "%s: %s not found\n", "alias", n);
3076 unaliascmd(int argc, char **argv)
3080 while ((i = nextopt("a")) != '\0') {
3086 for (i = 0; *argptr; argptr++) {
3087 if (unalias(*argptr)) {
3088 fprintf(stderr, "%s: %s not found\n", "unalias", *argptr);
3096 #endif /* ASH_ALIAS */
3099 /* ============ jobs.c */
3101 /* Mode argument to forkshell. Don't change FORK_FG or FORK_BG. */
3104 #define FORK_NOJOB 2
3106 /* mode flags for showjob(s) */
3107 #define SHOW_PGID 0x01 /* only show pgid - for jobs -p */
3108 #define SHOW_PID 0x04 /* include process pid */
3109 #define SHOW_CHANGED 0x08 /* only jobs whose state has changed */
3112 * A job structure contains information about a job. A job is either a
3113 * single process or a set of processes contained in a pipeline. In the
3114 * latter case, pidlist will be non-NULL, and will point to a -1 terminated
3119 pid_t pid; /* process id */
3120 int status; /* last process status from wait() */
3121 char *cmd; /* text of command being run */
3125 struct procstat ps0; /* status of process */
3126 struct procstat *ps; /* status or processes when more than one */
3128 int stopstatus; /* status of a stopped job */
3131 nprocs: 16, /* number of processes */
3133 #define JOBRUNNING 0 /* at least one proc running */
3134 #define JOBSTOPPED 1 /* all procs are stopped */
3135 #define JOBDONE 2 /* all procs are completed */
3137 sigint: 1, /* job was killed by SIGINT */
3138 jobctl: 1, /* job running under job control */
3140 waited: 1, /* true if this entry has been waited for */
3141 used: 1, /* true if this entry is in used */
3142 changed: 1; /* true if status has changed */
3143 struct job *prev_job; /* previous job */
3146 static pid_t backgndpid; /* pid of last background process */
3147 static smallint job_warning; /* user was warned about stopped jobs (can be 2, 1 or 0). */
3149 static struct job *makejob(union node *, int);
3150 static int forkshell(struct job *, union node *, int);
3151 static int waitforjob(struct job *);
3154 enum { jobctl = 0 };
3155 #define setjobctl(on) do {} while (0)
3157 static smallint jobctl; /* true if doing job control */
3158 static void setjobctl(int);
3162 * Set the signal handler for the specified signal. The routine figures
3163 * out what it should be set to.
3166 setsignal(int signo)
3170 struct sigaction act;
3175 else if (*t != '\0')
3179 if (rootshell && action == S_DFL) {
3182 if (iflag || minusc || sflag == 0)
3205 t = &sigmode[signo - 1];
3209 * current setting unknown
3211 if (sigaction(signo, 0, &act) == -1) {
3213 * Pretend it worked; maybe we should give a warning
3214 * here, but other shells don't. We don't alter
3215 * sigmode, so that we retry every time.
3219 if (act.sa_handler == SIG_IGN) {
3221 && (signo == SIGTSTP || signo == SIGTTIN || signo == SIGTTOU)
3223 tsig = S_IGN; /* don't hard ignore these */
3227 tsig = S_RESET; /* force to be set */
3230 if (tsig == S_HARD_IGN || tsig == action)
3234 act.sa_handler = onsig;
3237 act.sa_handler = SIG_IGN;
3240 act.sa_handler = SIG_DFL;
3244 sigfillset(&act.sa_mask);
3245 sigaction(signo, &act, 0);
3248 /* mode flags for set_curjob */
3249 #define CUR_DELETE 2
3250 #define CUR_RUNNING 1
3251 #define CUR_STOPPED 0
3253 /* mode flags for dowait */
3254 #define DOWAIT_NORMAL 0
3255 #define DOWAIT_BLOCK 1
3258 /* pgrp of shell on invocation */
3259 static int initialpgrp;
3260 static int ttyfd = -1;
3263 static struct job *jobtab;
3265 static unsigned njobs;
3267 static struct job *curjob;
3268 /* number of presumed living untracked jobs */
3272 set_curjob(struct job *jp, unsigned mode)
3275 struct job **jpp, **curp;
3277 /* first remove from list */
3278 jpp = curp = &curjob;
3283 jpp = &jp1->prev_job;
3285 *jpp = jp1->prev_job;
3287 /* Then re-insert in correct position */
3295 /* job being deleted */
3298 /* newly created job or backgrounded job,
3299 put after all stopped jobs. */
3303 if (!jp1 || jp1->state != JOBSTOPPED)
3306 jpp = &jp1->prev_job;
3312 /* newly stopped job - becomes curjob */
3313 jp->prev_job = *jpp;
3321 jobno(const struct job *jp)
3323 return jp - jobtab + 1;
3328 * Convert a job name to a job structure.
3331 getjob(const char *name, int getctl)
3335 const char *err_msg = "No such job: %s";
3339 char *(*match)(const char *, const char *);
3354 if (c == '+' || c == '%') {
3356 err_msg = "No current job";
3362 err_msg = "No previous job";
3373 jp = jobtab + num - 1;
3390 if (match(jp->ps[0].cmd, p)) {
3394 err_msg = "%s: ambiguous";
3401 err_msg = "job %s not created under job control";
3402 if (getctl && jp->jobctl == 0)
3407 ash_msg_and_raise_error(err_msg, name);
3411 * Mark a job structure as unused.
3414 freejob(struct job *jp)
3416 struct procstat *ps;
3420 for (i = jp->nprocs, ps = jp->ps; --i >= 0; ps++) {
3421 if (ps->cmd != nullstr)
3424 if (jp->ps != &jp->ps0)
3427 set_curjob(jp, CUR_DELETE);
3433 xtcsetpgrp(int fd, pid_t pgrp)
3435 if (tcsetpgrp(fd, pgrp))
3436 ash_msg_and_raise_error("cannot set tty process group (%m)");
3440 * Turn job control on and off.
3442 * Note: This code assumes that the third arg to ioctl is a character
3443 * pointer, which is true on Berkeley systems but not System V. Since
3444 * System V doesn't have job control yet, this isn't a problem now.
3446 * Called with interrupts off.
3454 if (on == jobctl || rootshell == 0)
3458 ofd = fd = open(_PATH_TTY, O_RDWR);
3460 /* BTW, bash will try to open(ttyname(0)) if open("/dev/tty") fails.
3461 * That sometimes helps to acquire controlling tty.
3462 * Obviously, a workaround for bugs when someone
3463 * failed to provide a controlling tty to bash! :) */
3465 while (!isatty(fd) && --fd >= 0)
3468 fd = fcntl(fd, F_DUPFD, 10);
3472 fcntl(fd, F_SETFD, FD_CLOEXEC);
3473 do { /* while we are in the background */
3474 pgrp = tcgetpgrp(fd);
3477 ash_msg("can't access tty; job control turned off");
3481 if (pgrp == getpgrp())
3492 xtcsetpgrp(fd, pgrp);
3494 /* turning job control off */
3497 /* was xtcsetpgrp, but this can make exiting ash
3498 * with pty already deleted loop forever */
3499 tcsetpgrp(fd, pgrp);
3513 killcmd(int argc, char **argv)
3515 if (argv[1] && strcmp(argv[1], "-l") != 0) {
3518 if (argv[i][0] == '%') {
3519 struct job *jp = getjob(argv[i], 0);
3520 unsigned pid = jp->ps[0].pid;
3521 /* Enough space for ' -NNN<nul>' */
3522 argv[i] = alloca(sizeof(int)*3 + 3);
3523 /* kill_main has matching code to expect
3524 * leading space. Needed to not confuse
3525 * negative pids with "kill -SIGNAL_NO" syntax */
3526 sprintf(argv[i], " -%u", pid);
3528 } while (argv[++i]);
3530 return kill_main(argc, argv);
3534 showpipe(struct job *jp, FILE *out)
3536 struct procstat *sp;
3537 struct procstat *spend;
3539 spend = jp->ps + jp->nprocs;
3540 for (sp = jp->ps + 1; sp < spend; sp++)
3541 fprintf(out, " | %s", sp->cmd);
3542 outcslow('\n', out);
3543 flush_stdout_stderr();
3548 restartjob(struct job *jp, int mode)
3550 struct procstat *ps;
3556 if (jp->state == JOBDONE)
3558 jp->state = JOBRUNNING;
3560 if (mode == FORK_FG)
3561 xtcsetpgrp(ttyfd, pgid);
3562 killpg(pgid, SIGCONT);
3566 if (WIFSTOPPED(ps->status)) {
3572 status = (mode == FORK_FG) ? waitforjob(jp) : 0;
3578 fg_bgcmd(int argc, char **argv)
3585 mode = (**argv == 'f') ? FORK_FG : FORK_BG;
3590 jp = getjob(*argv, 1);
3591 if (mode == FORK_BG) {
3592 set_curjob(jp, CUR_RUNNING);
3593 fprintf(out, "[%d] ", jobno(jp));
3595 outstr(jp->ps->cmd, out);
3597 retval = restartjob(jp, mode);
3598 } while (*argv && *++argv);
3604 sprint_status(char *s, int status, int sigonly)
3610 if (!WIFEXITED(status)) {
3612 if (WIFSTOPPED(status))
3613 st = WSTOPSIG(status);
3616 st = WTERMSIG(status);
3618 if (st == SIGINT || st == SIGPIPE)
3621 if (WIFSTOPPED(status))
3626 col = fmtstr(s, 32, strsignal(st));
3627 if (WCOREDUMP(status)) {
3628 col += fmtstr(s + col, 16, " (core dumped)");
3630 } else if (!sigonly) {
3631 st = WEXITSTATUS(status);
3633 col = fmtstr(s, 16, "Done(%d)", st);
3635 col = fmtstr(s, 16, "Done");
3642 * Do a wait system call. If job control is compiled in, we accept
3643 * stopped processes. If block is zero, we return a value of zero
3644 * rather than blocking.
3646 * System V doesn't have a non-blocking wait system call. It does
3647 * have a SIGCLD signal that is sent to a process when one of it's
3648 * children dies. The obvious way to use SIGCLD would be to install
3649 * a handler for SIGCLD which simply bumped a counter when a SIGCLD
3650 * was received, and have waitproc bump another counter when it got
3651 * the status of a process. Waitproc would then know that a wait
3652 * system call would not block if the two counters were different.
3653 * This approach doesn't work because if a process has children that
3654 * have not been waited for, System V will send it a SIGCLD when it
3655 * installs a signal handler for SIGCLD. What this means is that when
3656 * a child exits, the shell will be sent SIGCLD signals continuously
3657 * until is runs out of stack space, unless it does a wait call before
3658 * restoring the signal handler. The code below takes advantage of
3659 * this (mis)feature by installing a signal handler for SIGCLD and
3660 * then checking to see whether it was called. If there are any
3661 * children to be waited for, it will be.
3663 * If neither SYSV nor BSD is defined, we don't implement nonblocking
3664 * waits at all. In this case, the user will not be informed when
3665 * a background process until the next time she runs a real program
3666 * (as opposed to running a builtin command or just typing return),
3667 * and the jobs command may give out of date information.
3670 waitproc(int block, int *status)
3680 return wait3(status, flags, (struct rusage *)NULL);
3684 * Wait for a process to terminate.
3687 dowait(int block, struct job *job)
3692 struct job *thisjob;
3695 TRACE(("dowait(%d) called\n", block));
3696 pid = waitproc(block, &status);
3697 TRACE(("wait returns pid %d, status=%d\n", pid, status));
3702 for (jp = curjob; jp; jp = jp->prev_job) {
3703 struct procstat *sp;
3704 struct procstat *spend;
3705 if (jp->state == JOBDONE)
3708 spend = jp->ps + jp->nprocs;
3711 if (sp->pid == pid) {
3712 TRACE(("Job %d: changing status of proc %d "
3713 "from 0x%x to 0x%x\n",
3714 jobno(jp), pid, sp->status, status));
3715 sp->status = status;
3718 if (sp->status == -1)
3721 if (state == JOBRUNNING)
3723 if (WIFSTOPPED(sp->status)) {
3724 jp->stopstatus = sp->status;
3728 } while (++sp < spend);
3733 if (!WIFSTOPPED(status))
3740 if (state != JOBRUNNING) {
3741 thisjob->changed = 1;
3743 if (thisjob->state != state) {
3744 TRACE(("Job %d: changing state from %d to %d\n",
3745 jobno(thisjob), thisjob->state, state));
3746 thisjob->state = state;
3748 if (state == JOBSTOPPED) {
3749 set_curjob(thisjob, CUR_STOPPED);
3758 if (thisjob && thisjob == job) {
3762 len = sprint_status(s, status, 1);
3774 showjob(FILE *out, struct job *jp, int mode)
3776 struct procstat *ps;
3777 struct procstat *psend;
3784 if (mode & SHOW_PGID) {
3785 /* just output process (group) id of pipeline */
3786 fprintf(out, "%d\n", ps->pid);
3790 col = fmtstr(s, 16, "[%d] ", jobno(jp));
3795 else if (curjob && jp == curjob->prev_job)
3798 if (mode & SHOW_PID)
3799 col += fmtstr(s + col, 16, "%d ", ps->pid);
3801 psend = ps + jp->nprocs;
3803 if (jp->state == JOBRUNNING) {
3804 strcpy(s + col, "Running");
3805 col += sizeof("Running") - 1;
3807 int status = psend[-1].status;
3808 if (jp->state == JOBSTOPPED)
3809 status = jp->stopstatus;
3810 col += sprint_status(s + col, status, 0);
3816 /* for each process */
3817 col = fmtstr(s, 48, " |\n%*c%d ", indent_col, ' ', ps->pid) - 3;
3819 fprintf(out, "%s%*c%s",
3820 s, 33 - col >= 0 ? 33 - col : 0, ' ', ps->cmd
3822 if (!(mode & SHOW_PID)) {
3826 if (++ps == psend) {
3827 outcslow('\n', out);
3834 if (jp->state == JOBDONE) {
3835 TRACE(("showjob: freeing job %d\n", jobno(jp)));
3841 * Print a list of jobs. If "change" is nonzero, only print jobs whose
3842 * statuses have changed since the last call to showjobs.
3845 showjobs(FILE *out, int mode)
3849 TRACE(("showjobs(%x) called\n", mode));
3851 /* If not even one one job changed, there is nothing to do */
3852 while (dowait(DOWAIT_NORMAL, NULL) > 0)
3855 for (jp = curjob; jp; jp = jp->prev_job) {
3856 if (!(mode & SHOW_CHANGED) || jp->changed) {
3857 showjob(out, jp, mode);
3863 jobscmd(int argc, char **argv)
3868 while ((m = nextopt("lp"))) {
3878 showjob(stdout, getjob(*argv,0), mode);
3881 showjobs(stdout, mode);
3888 getstatus(struct job *job)
3893 status = job->ps[job->nprocs - 1].status;
3894 retval = WEXITSTATUS(status);
3895 if (!WIFEXITED(status)) {
3897 retval = WSTOPSIG(status);
3898 if (!WIFSTOPPED(status))
3901 /* XXX: limits number of signals */
3902 retval = WTERMSIG(status);
3904 if (retval == SIGINT)