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.
49 #define JOBS ENABLE_ASH_JOB_CONTROL
57 #include "busybox.h" /* for applet_names */
61 #if JOBS || ENABLE_ASH_READ_NCHARS
65 #if defined(__uClinux__)
66 #error "Do not even bother, ash will not run on uClinux"
70 /* ============ Hash table sizes. Configurable. */
74 #define CMDTABLESIZE 31 /* should be prime */
77 /* ============ Misc helpers */
79 #define xbarrier() do { __asm__ __volatile__ ("": : :"memory"); } while (0)
81 /* C99 say: "char" declaration may be signed or unsigned default */
82 #define signed_char2int(sc) ((int)((signed char)sc))
85 /* ============ Shell options */
87 static const char *const optletters_optnames[] = {
108 #define optletters(n) optletters_optnames[(n)][0]
109 #define optnames(n) (&optletters_optnames[(n)][1])
111 enum { NOPTS = ARRAY_SIZE(optletters_optnames) };
114 /* ============ Misc data */
116 static const char homestr[] ALIGN1 = "HOME";
117 static const char snlfmt[] ALIGN1 = "%s\n";
118 static const char illnum[] ALIGN1 = "Illegal number: %s";
121 * We enclose jmp_buf in a structure so that we can declare pointers to
122 * jump locations. The global variable handler contains the location to
123 * jump to when an exception occurs, and the global variable exception
124 * contains a code identifying the exception. To implement nested
125 * exception handlers, the user should save the value of handler on entry
126 * to an inner scope, set handler to point to a jmploc structure for the
127 * inner scope, and restore handler on exit from the scope.
133 struct globals_misc {
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 char *minusc; /* argument to -c option */
141 char *curdir; // = nullstr; /* current working directory */
142 char *physdir; // = nullstr; /* physical working directory */
144 char *arg0; /* value of $0 */
146 struct jmploc *exception_handler;
148 // disabled by vda: cannot understand how it was supposed to work -
149 // cannot fix bugs. That's why you have to explain your non-trivial designs!
150 // /* do we generate EXSIG events */
151 // int exsig; /* counter */
152 volatile int suppressint; /* counter */
153 volatile /*sig_atomic_t*/ smallint intpending; /* 1 = got SIGINT */
154 /* last pending signal */
155 volatile /*sig_atomic_t*/ smallint pendingsig;
156 smallint exception; /* kind of exception (0..5) */
158 #define EXINT 0 /* SIGINT received */
159 #define EXERROR 1 /* a generic error */
160 #define EXSHELLPROC 2 /* execute a shell procedure */
161 #define EXEXEC 3 /* command execution failed */
162 #define EXEXIT 4 /* exit the shell */
163 #define EXSIG 5 /* trapped signal in wait(1) */
166 char nullstr[1]; /* zero length string */
169 #define eflag optlist[0]
170 #define fflag optlist[1]
171 #define Iflag optlist[2]
172 #define iflag optlist[3]
173 #define mflag optlist[4]
174 #define nflag optlist[5]
175 #define sflag optlist[6]
176 #define xflag optlist[7]
177 #define vflag optlist[8]
178 #define Cflag optlist[9]
179 #define aflag optlist[10]
180 #define bflag optlist[11]
181 #define uflag optlist[12]
182 #define viflag optlist[13]
184 #define nolog optlist[14]
185 #define debug optlist[15]
188 /* trap handler commands */
190 * Sigmode records the current value of the signal handlers for the various
191 * modes. A value of zero means that the current handler is not known.
192 * S_HARD_IGN indicates that the signal was ignored on entry to the shell,
194 char sigmode[NSIG - 1];
195 #define S_DFL 1 /* default signal handling (SIG_DFL) */
196 #define S_CATCH 2 /* signal is caught */
197 #define S_IGN 3 /* signal is ignored (SIG_IGN) */
198 #define S_HARD_IGN 4 /* signal is ignored permenantly */
199 #define S_RESET 5 /* temporary - to reset a hard ignored sig */
201 /* indicates specified signal received */
202 char gotsig[NSIG - 1];
205 /* Rarely referenced stuff */
206 #if ENABLE_ASH_RANDOM_SUPPORT
207 int32_t random_galois_LFSR; /* Galois LFSR (fast but weak) */
208 uint32_t random_LCG; /* LCG1 (fast but weak) */
210 pid_t backgndpid; /* pid of last background process */
211 smallint job_warning; /* user was warned about stopped jobs (can be 2, 1 or 0). */
213 extern struct globals_misc *const ash_ptr_to_globals_misc;
214 #define G_misc (*ash_ptr_to_globals_misc)
215 #define rootpid (G_misc.rootpid )
216 #define shlvl (G_misc.shlvl )
217 #define minusc (G_misc.minusc )
218 #define curdir (G_misc.curdir )
219 #define physdir (G_misc.physdir )
220 #define arg0 (G_misc.arg0 )
221 #define exception_handler (G_misc.exception_handler)
222 #define exception (G_misc.exception )
223 #define suppressint (G_misc.suppressint )
224 #define intpending (G_misc.intpending )
225 //#define exsig (G_misc.exsig )
226 #define pendingsig (G_misc.pendingsig )
227 #define isloginsh (G_misc.isloginsh )
228 #define nullstr (G_misc.nullstr )
229 #define optlist (G_misc.optlist )
230 #define sigmode (G_misc.sigmode )
231 #define gotsig (G_misc.gotsig )
232 #define trap (G_misc.trap )
233 #define random_galois_LFSR (G_misc.random_galois_LFSR)
234 #define random_LCG (G_misc.random_LCG )
235 #define backgndpid (G_misc.backgndpid )
236 #define job_warning (G_misc.job_warning)
237 #define INIT_G_misc() do { \
238 (*(struct globals_misc**)&ash_ptr_to_globals_misc) = xzalloc(sizeof(G_misc)); \
245 /* ============ Interrupts / exceptions */
248 * These macros allow the user to suspend the handling of interrupt signals
249 * over a period of time. This is similar to SIGHOLD or to sigblock, but
250 * much more efficient and portable. (But hacking the kernel is so much
251 * more fun than worrying about efficiency and portability. :-))
253 #define INT_OFF do { \
259 * Called to raise an exception. Since C doesn't include exceptions, we
260 * just do a longjmp to the exception handler. The type of exception is
261 * stored in the global variable "exception".
263 static void raise_exception(int) ATTRIBUTE_NORETURN;
265 raise_exception(int e)
268 if (exception_handler == NULL)
273 longjmp(exception_handler->loc, 1);
277 * Called from trap.c when a SIGINT is received. (If the user specifies
278 * that SIGINT is to be trapped or ignored using the trap builtin, then
279 * this routine is not called.) Suppressint is nonzero when interrupts
280 * are held using the INT_OFF macro. (The test for iflag is just
281 * defensive programming.)
283 static void raise_interrupt(void) ATTRIBUTE_NORETURN;
285 raise_interrupt(void)
290 /* Signal is not automatically unmasked after it is raised,
291 * do it ourself - unmask all signals */
292 sigprocmask_allsigs(SIG_UNBLOCK);
293 /* pendingsig = 0; - now done in onsig() */
296 if (gotsig[SIGINT - 1] && !trap[SIGINT]) {
297 if (!(rootshell && iflag)) {
298 /* Kill ourself with SIGINT */
299 signal(SIGINT, SIG_DFL);
308 #if ENABLE_ASH_OPTIMIZE_FOR_SIZE
312 if (--suppressint == 0 && intpending) {
316 #define INT_ON int_on()
324 #define FORCE_INT_ON force_int_on()
326 #define INT_ON do { \
328 if (--suppressint == 0 && intpending) \
331 #define FORCE_INT_ON do { \
337 #endif /* ASH_OPTIMIZE_FOR_SIZE */
339 #define SAVE_INT(v) ((v) = suppressint)
341 #define RESTORE_INT(v) do { \
344 if (suppressint == 0 && intpending) \
349 * Ignore a signal. Only one usage site - in forkchild()
354 if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) {
355 signal(signo, SIG_IGN);
357 sigmode[signo - 1] = S_HARD_IGN;
361 * Signal handler. Only one usage site - in setsignal()
366 gotsig[signo - 1] = 1;
369 if (/* exsig || */ (signo == SIGINT && !trap[SIGINT])) {
372 raise_interrupt(); /* does not return */
379 /* ============ Stdout/stderr output */
382 outstr(const char *p, FILE *file)
390 flush_stdout_stderr(void)
407 outcslow(int c, FILE *dest)
415 static int out1fmt(const char *, ...) __attribute__((__format__(__printf__,1,2)));
417 out1fmt(const char *fmt, ...)
424 r = vprintf(fmt, ap);
430 static int fmtstr(char *, size_t, const char *, ...) __attribute__((__format__(__printf__,3,4)));
432 fmtstr(char *outbuf, size_t length, const char *fmt, ...)
439 ret = vsnprintf(outbuf, length, fmt, ap);
446 out1str(const char *p)
452 out2str(const char *p)
459 /* ============ Parser structures */
461 /* control characters in argument strings */
462 #define CTLESC '\201' /* escape next character */
463 #define CTLVAR '\202' /* variable defn */
464 #define CTLENDVAR '\203'
465 #define CTLBACKQ '\204'
466 #define CTLQUOTE 01 /* ored with CTLBACKQ code if in quotes */
467 /* CTLBACKQ | CTLQUOTE == '\205' */
468 #define CTLARI '\206' /* arithmetic expression */
469 #define CTLENDARI '\207'
470 #define CTLQUOTEMARK '\210'
472 /* variable substitution byte (follows CTLVAR) */
473 #define VSTYPE 0x0f /* type of variable substitution */
474 #define VSNUL 0x10 /* colon--treat the empty string as unset */
475 #define VSQUOTE 0x80 /* inside double quotes--suppress splitting */
477 /* values of VSTYPE field */
478 #define VSNORMAL 0x1 /* normal variable: $var or ${var} */
479 #define VSMINUS 0x2 /* ${var-text} */
480 #define VSPLUS 0x3 /* ${var+text} */
481 #define VSQUESTION 0x4 /* ${var?message} */
482 #define VSASSIGN 0x5 /* ${var=text} */
483 #define VSTRIMRIGHT 0x6 /* ${var%pattern} */
484 #define VSTRIMRIGHTMAX 0x7 /* ${var%%pattern} */
485 #define VSTRIMLEFT 0x8 /* ${var#pattern} */
486 #define VSTRIMLEFTMAX 0x9 /* ${var##pattern} */
487 #define VSLENGTH 0xa /* ${#var} */
488 #if ENABLE_ASH_BASH_COMPAT
489 #define VSSUBSTR 0xc /* ${var:position:length} */
490 #define VSREPLACE 0xd /* ${var/pattern/replacement} */
491 #define VSREPLACEALL 0xe /* ${var//pattern/replacement} */
494 static const char dolatstr[] ALIGN1 = {
495 CTLVAR, VSNORMAL|VSQUOTE, '@', '=', '\0'
531 union node *redirect;
537 struct nodelist *cmdlist;
543 union node *redirect;
556 union node *elsepart;
583 struct nodelist *backquote;
618 struct nredir nredir;
619 struct nbinary nbinary;
623 struct nclist nclist;
632 struct nodelist *next;
645 freefunc(struct funcnode *f)
647 if (f && --f->count < 0)
652 /* ============ Debugging output */
656 static FILE *tracefile;
659 trace_printf(const char *fmt, ...)
666 vfprintf(tracefile, fmt, va);
671 trace_vprintf(const char *fmt, va_list va)
675 vfprintf(tracefile, fmt, va);
679 trace_puts(const char *s)
687 trace_puts_quoted(char *s)
694 putc('"', tracefile);
695 for (p = s; *p; p++) {
697 case '\n': c = 'n'; goto backslash;
698 case '\t': c = 't'; goto backslash;
699 case '\r': c = 'r'; goto backslash;
700 case '"': c = '"'; goto backslash;
701 case '\\': c = '\\'; goto backslash;
702 case CTLESC: c = 'e'; goto backslash;
703 case CTLVAR: c = 'v'; goto backslash;
704 case CTLVAR+CTLQUOTE: c = 'V'; goto backslash;
705 case CTLBACKQ: c = 'q'; goto backslash;
706 case CTLBACKQ+CTLQUOTE: c = 'Q'; goto backslash;
708 putc('\\', tracefile);
712 if (*p >= ' ' && *p <= '~')
715 putc('\\', tracefile);
716 putc(*p >> 6 & 03, tracefile);
717 putc(*p >> 3 & 07, tracefile);
718 putc(*p & 07, tracefile);
723 putc('"', tracefile);
727 trace_puts_args(char **ap)
734 trace_puts_quoted(*ap);
736 putc('\n', tracefile);
739 putc(' ', tracefile);
754 /* leave open because libedit might be using it */
757 strcpy(s, "./trace");
759 if (!freopen(s, "a", tracefile)) {
760 fprintf(stderr, "Can't re-open %s\n", s);
765 tracefile = fopen(s, "a");
766 if (tracefile == NULL) {
767 fprintf(stderr, "Can't open %s\n", s);
773 flags = fcntl(fileno(tracefile), F_GETFL);
775 fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND);
777 setlinebuf(tracefile);
778 fputs("\nTracing started.\n", tracefile);
782 indent(int amount, char *pfx, FILE *fp)
786 for (i = 0; i < amount; i++) {
787 if (pfx && i == amount - 1)
793 /* little circular references here... */
794 static void shtree(union node *n, int ind, char *pfx, FILE *fp);
797 sharg(union node *arg, FILE *fp)
800 struct nodelist *bqlist;
803 if (arg->type != NARG) {
804 out1fmt("<node type %d>\n", arg->type);
807 bqlist = arg->narg.backquote;
808 for (p = arg->narg.text; *p; p++) {
817 if (subtype == VSLENGTH)
826 switch (subtype & VSTYPE) {
859 out1fmt("<subtype %d>", subtype);
866 case CTLBACKQ|CTLQUOTE:
869 shtree(bqlist->n, -1, NULL, fp);
880 shcmd(union node *cmd, FILE *fp)
888 for (np = cmd->ncmd.args; np; np = np->narg.next) {
894 for (np = cmd->ncmd.redirect; np; np = np->nfile.next) {
898 switch (np->nfile.type) {
899 case NTO: s = ">>"+1; dftfd = 1; break;
900 case NCLOBBER: s = ">|"; dftfd = 1; break;
901 case NAPPEND: s = ">>"; dftfd = 1; break;
902 case NTOFD: s = ">&"; dftfd = 1; break;
903 case NFROM: s = "<"; break;
904 case NFROMFD: s = "<&"; break;
905 case NFROMTO: s = "<>"; break;
906 default: s = "*error*"; break;
908 if (np->nfile.fd != dftfd)
909 fprintf(fp, "%d", np->nfile.fd);
911 if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) {
912 fprintf(fp, "%d", np->ndup.dupfd);
914 sharg(np->nfile.fname, fp);
921 shtree(union node *n, int ind, char *pfx, FILE *fp)
929 indent(ind, pfx, fp);
940 shtree(n->nbinary.ch1, ind, NULL, fp);
943 shtree(n->nbinary.ch2, ind, NULL, fp);
951 for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
956 if (n->npipe.backgnd)
962 fprintf(fp, "<node type %d>", n->type);
970 showtree(union node *n)
972 trace_puts("showtree called\n");
973 shtree(n, 1, NULL, stdout);
976 #define TRACE(param) trace_printf param
977 #define TRACEV(param) trace_vprintf param
982 #define TRACEV(param)
987 /* ============ Parser data */
990 * ash_vmsg() needs parsefile->fd, hence parsefile definition is moved up.
993 struct strlist *next;
1000 struct strpush *prev; /* preceding string on stack */
1003 #if ENABLE_ASH_ALIAS
1004 struct alias *ap; /* if push was associated with an alias */
1006 char *string; /* remember the string since it may change */
1010 struct parsefile *prev; /* preceding file on stack */
1011 int linno; /* current line */
1012 int fd; /* file descriptor (or -1 if string) */
1013 int nleft; /* number of chars left in this line */
1014 int lleft; /* number of chars left in this buffer */
1015 char *nextc; /* next char in buffer */
1016 char *buf; /* input buffer */
1017 struct strpush *strpush; /* for pushing strings at this level */
1018 struct strpush basestrpush; /* so pushing one is fast */
1021 static struct parsefile basepf; /* top level input file */
1022 static struct parsefile *g_parsefile = &basepf; /* current input file */
1023 static int startlinno; /* line # where last token started */
1024 static char *commandname; /* currently executing command */
1025 static struct strlist *cmdenviron; /* environment for builtin command */
1026 static uint8_t exitstatus; /* exit status of last command */
1029 /* ============ Message printing */
1032 ash_vmsg(const char *msg, va_list ap)
1034 fprintf(stderr, "%s: ", arg0);
1036 if (strcmp(arg0, commandname))
1037 fprintf(stderr, "%s: ", commandname);
1038 if (!iflag || g_parsefile->fd)
1039 fprintf(stderr, "line %d: ", startlinno);
1041 vfprintf(stderr, msg, ap);
1042 outcslow('\n', stderr);
1046 * Exverror is called to raise the error exception. If the second argument
1047 * is not NULL then error prints an error message using printf style
1048 * formatting. It then raises the error exception.
1050 static void ash_vmsg_and_raise(int, const char *, va_list) ATTRIBUTE_NORETURN;
1052 ash_vmsg_and_raise(int cond, const char *msg, va_list ap)
1056 TRACE(("ash_vmsg_and_raise(%d, \"", cond));
1058 TRACE(("\") pid=%d\n", getpid()));
1060 TRACE(("ash_vmsg_and_raise(%d, NULL) pid=%d\n", cond, getpid()));
1065 flush_stdout_stderr();
1066 raise_exception(cond);
1070 static void ash_msg_and_raise_error(const char *, ...) ATTRIBUTE_NORETURN;
1072 ash_msg_and_raise_error(const char *msg, ...)
1077 ash_vmsg_and_raise(EXERROR, msg, ap);
1082 static void ash_msg_and_raise(int, const char *, ...) ATTRIBUTE_NORETURN;
1084 ash_msg_and_raise(int cond, const char *msg, ...)
1089 ash_vmsg_and_raise(cond, msg, ap);
1095 * error/warning routines for external builtins
1098 ash_msg(const char *fmt, ...)
1108 * Return a string describing an error. The returned string may be a
1109 * pointer to a static buffer that will be overwritten on the next call.
1110 * Action describes the operation that got the error.
1113 errmsg(int e, const char *em)
1115 if (e == ENOENT || e == ENOTDIR) {
1122 /* ============ Memory allocation */
1125 * It appears that grabstackstr() will barf with such alignments
1126 * because stalloc() will return a string allocated in a new stackblock.
1128 #define SHELL_ALIGN(nbytes) (((nbytes) + SHELL_SIZE) & ~SHELL_SIZE)
1130 /* Most machines require the value returned from malloc to be aligned
1131 * in some way. The following macro will get this right
1132 * on many machines. */
1133 SHELL_SIZE = sizeof(union {int i; char *cp; double d; }) - 1,
1134 /* Minimum size of a block */
1135 MINSIZE = SHELL_ALIGN(504),
1138 struct stack_block {
1139 struct stack_block *prev;
1140 char space[MINSIZE];
1144 struct stack_block *stackp;
1147 struct stackmark *marknext;
1151 struct globals_memstack {
1152 struct stack_block *g_stackp; // = &stackbase;
1153 struct stackmark *markp;
1154 char *g_stacknxt; // = stackbase.space;
1155 char *sstrend; // = stackbase.space + MINSIZE;
1156 size_t g_stacknleft; // = MINSIZE;
1157 int herefd; // = -1;
1158 struct stack_block stackbase;
1160 extern struct globals_memstack *const ash_ptr_to_globals_memstack;
1161 #define G_memstack (*ash_ptr_to_globals_memstack)
1162 #define g_stackp (G_memstack.g_stackp )
1163 #define markp (G_memstack.markp )
1164 #define g_stacknxt (G_memstack.g_stacknxt )
1165 #define sstrend (G_memstack.sstrend )
1166 #define g_stacknleft (G_memstack.g_stacknleft)
1167 #define herefd (G_memstack.herefd )
1168 #define stackbase (G_memstack.stackbase )
1169 #define INIT_G_memstack() do { \
1170 (*(struct globals_memstack**)&ash_ptr_to_globals_memstack) = xzalloc(sizeof(G_memstack)); \
1172 g_stackp = &stackbase; \
1173 g_stacknxt = stackbase.space; \
1174 g_stacknleft = MINSIZE; \
1175 sstrend = stackbase.space + MINSIZE; \
1179 #define stackblock() ((void *)g_stacknxt)
1180 #define stackblocksize() g_stacknleft
1184 ckrealloc(void * p, size_t nbytes)
1186 p = realloc(p, nbytes);
1188 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1193 ckmalloc(size_t nbytes)
1195 return ckrealloc(NULL, nbytes);
1199 ckzalloc(size_t nbytes)
1201 return memset(ckmalloc(nbytes), 0, nbytes);
1205 * Make a copy of a string in safe storage.
1208 ckstrdup(const char *s)
1210 char *p = strdup(s);
1212 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1217 * Parse trees for commands are allocated in lifo order, so we use a stack
1218 * to make this more efficient, and also to avoid all sorts of exception
1219 * handling code to handle interrupts in the middle of a parse.
1221 * The size 504 was chosen because the Ultrix malloc handles that size
1225 stalloc(size_t nbytes)
1230 aligned = SHELL_ALIGN(nbytes);
1231 if (aligned > g_stacknleft) {
1234 struct stack_block *sp;
1236 blocksize = aligned;
1237 if (blocksize < MINSIZE)
1238 blocksize = MINSIZE;
1239 len = sizeof(struct stack_block) - MINSIZE + blocksize;
1240 if (len < blocksize)
1241 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1244 sp->prev = g_stackp;
1245 g_stacknxt = sp->space;
1246 g_stacknleft = blocksize;
1247 sstrend = g_stacknxt + blocksize;
1252 g_stacknxt += aligned;
1253 g_stacknleft -= aligned;
1258 stzalloc(size_t nbytes)
1260 return memset(stalloc(nbytes), 0, nbytes);
1267 if (!p || (g_stacknxt < (char *)p) || ((char *)p < g_stackp->space)) {
1268 write(STDERR_FILENO, "stunalloc\n", 10);
1272 g_stacknleft += g_stacknxt - (char *)p;
1277 * Like strdup but works with the ash stack.
1280 ststrdup(const char *p)
1282 size_t len = strlen(p) + 1;
1283 return memcpy(stalloc(len), p, len);
1287 setstackmark(struct stackmark *mark)
1289 mark->stackp = g_stackp;
1290 mark->stacknxt = g_stacknxt;
1291 mark->stacknleft = g_stacknleft;
1292 mark->marknext = markp;
1297 popstackmark(struct stackmark *mark)
1299 struct stack_block *sp;
1305 markp = mark->marknext;
1306 while (g_stackp != mark->stackp) {
1308 g_stackp = sp->prev;
1311 g_stacknxt = mark->stacknxt;
1312 g_stacknleft = mark->stacknleft;
1313 sstrend = mark->stacknxt + mark->stacknleft;
1318 * When the parser reads in a string, it wants to stick the string on the
1319 * stack and only adjust the stack pointer when it knows how big the
1320 * string is. Stackblock (defined in stack.h) returns a pointer to a block
1321 * of space on top of the stack and stackblocklen returns the length of
1322 * this block. Growstackblock will grow this space by at least one byte,
1323 * possibly moving it (like realloc). Grabstackblock actually allocates the
1324 * part of the block that has been used.
1327 growstackblock(void)
1331 newlen = g_stacknleft * 2;
1332 if (newlen < g_stacknleft)
1333 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1337 if (g_stacknxt == g_stackp->space && g_stackp != &stackbase) {
1338 struct stack_block *oldstackp;
1339 struct stackmark *xmark;
1340 struct stack_block *sp;
1341 struct stack_block *prevstackp;
1345 oldstackp = g_stackp;
1347 prevstackp = sp->prev;
1348 grosslen = newlen + sizeof(struct stack_block) - MINSIZE;
1349 sp = ckrealloc(sp, grosslen);
1350 sp->prev = prevstackp;
1352 g_stacknxt = sp->space;
1353 g_stacknleft = newlen;
1354 sstrend = sp->space + newlen;
1357 * Stack marks pointing to the start of the old block
1358 * must be relocated to point to the new block
1361 while (xmark != NULL && xmark->stackp == oldstackp) {
1362 xmark->stackp = g_stackp;
1363 xmark->stacknxt = g_stacknxt;
1364 xmark->stacknleft = g_stacknleft;
1365 xmark = xmark->marknext;
1369 char *oldspace = g_stacknxt;
1370 size_t oldlen = g_stacknleft;
1371 char *p = stalloc(newlen);
1373 /* free the space we just allocated */
1374 g_stacknxt = memcpy(p, oldspace, oldlen);
1375 g_stacknleft += newlen;
1380 grabstackblock(size_t len)
1382 len = SHELL_ALIGN(len);
1384 g_stacknleft -= len;
1388 * The following routines are somewhat easier to use than the above.
1389 * The user declares a variable of type STACKSTR, which may be declared
1390 * to be a register. The macro STARTSTACKSTR initializes things. Then
1391 * the user uses the macro STPUTC to add characters to the string. In
1392 * effect, STPUTC(c, p) is the same as *p++ = c except that the stack is
1393 * grown as necessary. When the user is done, she can just leave the
1394 * string there and refer to it using stackblock(). Or she can allocate
1395 * the space for it using grabstackstr(). If it is necessary to allow
1396 * someone else to use the stack temporarily and then continue to grow
1397 * the string, the user should use grabstack to allocate the space, and
1398 * then call ungrabstr(p) to return to the previous mode of operation.
1400 * USTPUTC is like STPUTC except that it doesn't check for overflow.
1401 * CHECKSTACKSPACE can be called before USTPUTC to ensure that there
1402 * is space for at least one character.
1407 size_t len = stackblocksize();
1408 if (herefd >= 0 && len >= 1024) {
1409 full_write(herefd, stackblock(), len);
1410 return stackblock();
1413 return (char *)stackblock() + len;
1417 * Called from CHECKSTRSPACE.
1420 makestrspace(size_t newlen, char *p)
1422 size_t len = p - g_stacknxt;
1423 size_t size = stackblocksize();
1428 size = stackblocksize();
1430 if (nleft >= newlen)
1434 return (char *)stackblock() + len;
1438 stack_nputstr(const char *s, size_t n, char *p)
1440 p = makestrspace(n, p);
1441 p = (char *)memcpy(p, s, n) + n;
1446 stack_putstr(const char *s, char *p)
1448 return stack_nputstr(s, strlen(s), p);
1452 _STPUTC(int c, char *p)
1460 #define STARTSTACKSTR(p) ((p) = stackblock())
1461 #define STPUTC(c, p) ((p) = _STPUTC((c), (p)))
1462 #define CHECKSTRSPACE(n, p) do { \
1465 size_t m = sstrend - q; \
1467 (p) = makestrspace(l, q); \
1469 #define USTPUTC(c, p) (*(p)++ = (c))
1470 #define STACKSTRNUL(p) do { \
1471 if ((p) == sstrend) \
1472 (p) = growstackstr(); \
1475 #define STUNPUTC(p) (--(p))
1476 #define STTOPC(p) ((p)[-1])
1477 #define STADJUST(amount, p) ((p) += (amount))
1479 #define grabstackstr(p) stalloc((char *)(p) - (char *)stackblock())
1480 #define ungrabstackstr(s, p) stunalloc(s)
1481 #define stackstrend() ((void *)sstrend)
1484 /* ============ String helpers */
1487 * prefix -- see if pfx is a prefix of string.
1490 prefix(const char *string, const char *pfx)
1493 if (*pfx++ != *string++)
1496 return (char *) string;
1500 * Check for a valid number. This should be elsewhere.
1503 is_number(const char *p)
1508 } while (*++p != '\0');
1513 * Convert a string of digits to an integer, printing an error message on
1517 number(const char *s)
1520 ash_msg_and_raise_error(illnum, s);
1525 * Produce a possibly single quoted string suitable as input to the shell.
1526 * The return string is allocated on the stack.
1529 single_quote(const char *s)
1539 len = strchrnul(s, '\'') - s;
1541 q = p = makestrspace(len + 3, p);
1544 q = (char *)memcpy(q, s, len) + len;
1550 len = strspn(s, "'");
1554 q = p = makestrspace(len + 3, p);
1557 q = (char *)memcpy(q, s, len) + len;
1566 return stackblock();
1570 /* ============ nextopt */
1572 static char **argptr; /* argument list for builtin commands */
1573 static char *optionarg; /* set by nextopt (like getopt) */
1574 static char *optptr; /* used by nextopt */
1577 * XXX - should get rid of. have all builtins use getopt(3). the
1578 * library getopt must have the BSD extension static variable "optreset"
1579 * otherwise it can't be used within the shell safely.
1581 * Standard option processing (a la getopt) for builtin routines. The
1582 * only argument that is passed to nextopt is the option string; the
1583 * other arguments are unnecessary. It return the character, or '\0' on
1587 nextopt(const char *optstring)
1594 if (p == NULL || *p == '\0') {
1596 if (p == NULL || *p != '-' || *++p == '\0')
1599 if (LONE_DASH(p)) /* check for "--" */
1603 for (q = optstring; *q != c;) {
1605 ash_msg_and_raise_error("illegal option -%c", c);
1610 if (*p == '\0' && (p = *argptr++) == NULL)
1611 ash_msg_and_raise_error("no arg for -%c option", c);
1620 /* ============ Shell variables */
1623 * The parsefile structure pointed to by the global variable parsefile
1624 * contains information about the current file being read.
1627 struct redirtab *next;
1633 int nparam; /* # of positional parameters (without $0) */
1634 #if ENABLE_ASH_GETOPTS
1635 int optind; /* next parameter to be processed by getopts */
1636 int optoff; /* used by getopts */
1638 unsigned char malloced; /* if parameter list dynamically allocated */
1639 char **p; /* parameter list */
1643 * Free the list of positional parameters.
1646 freeparam(volatile struct shparam *param)
1650 if (param->malloced) {
1651 for (ap = param->p; *ap; ap++)
1657 #if ENABLE_ASH_GETOPTS
1658 static void getoptsreset(const char *value);
1662 struct var *next; /* next entry in hash list */
1663 int flags; /* flags are defined above */
1664 const char *text; /* name=value */
1665 void (*func)(const char *); /* function to be called when */
1666 /* the variable gets set/unset */
1670 struct localvar *next; /* next local variable in list */
1671 struct var *vp; /* the variable that was made local */
1672 int flags; /* saved flags */
1673 const char *text; /* saved text */
1677 #define VEXPORT 0x01 /* variable is exported */
1678 #define VREADONLY 0x02 /* variable cannot be modified */
1679 #define VSTRFIXED 0x04 /* variable struct is statically allocated */
1680 #define VTEXTFIXED 0x08 /* text is statically allocated */
1681 #define VSTACK 0x10 /* text is allocated on the stack */
1682 #define VUNSET 0x20 /* the variable is not set */
1683 #define VNOFUNC 0x40 /* don't call the callback function */
1684 #define VNOSET 0x80 /* do not set variable - just readonly test */
1685 #define VNOSAVE 0x100 /* when text is on the heap before setvareq */
1686 #if ENABLE_ASH_RANDOM_SUPPORT
1687 # define VDYNAMIC 0x200 /* dynamic variable */
1693 static const char defifsvar[] ALIGN1 = "IFS= \t\n";
1694 #define defifs (defifsvar + 4)
1696 static const char defifs[] ALIGN1 = " \t\n";
1700 /* Need to be before varinit_data[] */
1701 #if ENABLE_LOCALE_SUPPORT
1703 change_lc_all(const char *value)
1705 if (value && *value != '\0')
1706 setlocale(LC_ALL, value);
1709 change_lc_ctype(const char *value)
1711 if (value && *value != '\0')
1712 setlocale(LC_CTYPE, value);
1716 static void chkmail(void);
1717 static void changemail(const char *);
1719 static void changepath(const char *);
1720 #if ENABLE_ASH_RANDOM_SUPPORT
1721 static void change_random(const char *);
1724 static const struct {
1727 void (*func)(const char *);
1728 } varinit_data[] = {
1730 { VSTRFIXED|VTEXTFIXED , defifsvar , NULL },
1732 { VSTRFIXED|VTEXTFIXED|VUNSET, "IFS\0" , NULL },
1735 { VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL\0" , changemail },
1736 { VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH\0", changemail },
1738 { VSTRFIXED|VTEXTFIXED , bb_PATH_root_path, changepath },
1739 { VSTRFIXED|VTEXTFIXED , "PS1=$ " , NULL },
1740 { VSTRFIXED|VTEXTFIXED , "PS2=> " , NULL },
1741 { VSTRFIXED|VTEXTFIXED , "PS4=+ " , NULL },
1742 #if ENABLE_ASH_GETOPTS
1743 { VSTRFIXED|VTEXTFIXED , "OPTIND=1" , getoptsreset },
1745 #if ENABLE_ASH_RANDOM_SUPPORT
1746 { VSTRFIXED|VTEXTFIXED|VUNSET|VDYNAMIC, "RANDOM\0", change_random },
1748 #if ENABLE_LOCALE_SUPPORT
1749 { VSTRFIXED|VTEXTFIXED|VUNSET, "LC_ALL\0" , change_lc_all },
1750 { VSTRFIXED|VTEXTFIXED|VUNSET, "LC_CTYPE\0", change_lc_ctype },
1752 #if ENABLE_FEATURE_EDITING_SAVEHISTORY
1753 { VSTRFIXED|VTEXTFIXED|VUNSET, "HISTFILE\0", NULL },
1758 struct globals_var {
1759 struct shparam shellparam; /* $@ current positional parameters */
1760 struct redirtab *redirlist;
1762 int preverrout_fd; /* save fd2 before print debug if xflag is set. */
1763 struct var *vartab[VTABSIZE];
1764 struct var varinit[ARRAY_SIZE(varinit_data)];
1766 extern struct globals_var *const ash_ptr_to_globals_var;
1767 #define G_var (*ash_ptr_to_globals_var)
1768 #define shellparam (G_var.shellparam )
1769 #define redirlist (G_var.redirlist )
1770 #define g_nullredirs (G_var.g_nullredirs )
1771 #define preverrout_fd (G_var.preverrout_fd)
1772 #define vartab (G_var.vartab )
1773 #define varinit (G_var.varinit )
1774 #define INIT_G_var() do { \
1776 (*(struct globals_var**)&ash_ptr_to_globals_var) = xzalloc(sizeof(G_var)); \
1778 for (i = 0; i < ARRAY_SIZE(varinit_data); i++) { \
1779 varinit[i].flags = varinit_data[i].flags; \
1780 varinit[i].text = varinit_data[i].text; \
1781 varinit[i].func = varinit_data[i].func; \
1785 #define vifs varinit[0]
1787 # define vmail (&vifs)[1]
1788 # define vmpath (&vmail)[1]
1789 # define vpath (&vmpath)[1]
1791 # define vpath (&vifs)[1]
1793 #define vps1 (&vpath)[1]
1794 #define vps2 (&vps1)[1]
1795 #define vps4 (&vps2)[1]
1796 #if ENABLE_ASH_GETOPTS
1797 # define voptind (&vps4)[1]
1798 # if ENABLE_ASH_RANDOM_SUPPORT
1799 # define vrandom (&voptind)[1]
1802 # if ENABLE_ASH_RANDOM_SUPPORT
1803 # define vrandom (&vps4)[1]
1808 * The following macros access the values of the above variables.
1809 * They have to skip over the name. They return the null string
1810 * for unset variables.
1812 #define ifsval() (vifs.text + 4)
1813 #define ifsset() ((vifs.flags & VUNSET) == 0)
1815 # define mailval() (vmail.text + 5)
1816 # define mpathval() (vmpath.text + 9)
1817 # define mpathset() ((vmpath.flags & VUNSET) == 0)
1819 #define pathval() (vpath.text + 5)
1820 #define ps1val() (vps1.text + 4)
1821 #define ps2val() (vps2.text + 4)
1822 #define ps4val() (vps4.text + 4)
1823 #if ENABLE_ASH_GETOPTS
1824 # define optindval() (voptind.text + 7)
1828 #define is_name(c) ((c) == '_' || isalpha((unsigned char)(c)))
1829 #define is_in_name(c) ((c) == '_' || isalnum((unsigned char)(c)))
1831 #if ENABLE_ASH_GETOPTS
1833 getoptsreset(const char *value)
1835 shellparam.optind = number(value);
1836 shellparam.optoff = -1;
1841 * Return of a legal variable name (a letter or underscore followed by zero or
1842 * more letters, underscores, and digits).
1845 endofname(const char *name)
1853 if (!is_in_name(*p))
1860 * Compares two strings up to the first = or '\0'. The first
1861 * string must be terminated by '='; the second may be terminated by
1862 * either '=' or '\0'.
1865 varcmp(const char *p, const char *q)
1869 while ((c = *p) == (d = *q)) {
1884 varequal(const char *a, const char *b)
1886 return !varcmp(a, b);
1890 * Find the appropriate entry in the hash table from the name.
1892 static struct var **
1893 hashvar(const char *p)
1897 hashval = ((unsigned char) *p) << 4;
1898 while (*p && *p != '=')
1899 hashval += (unsigned char) *p++;
1900 return &vartab[hashval % VTABSIZE];
1904 vpcmp(const void *a, const void *b)
1906 return varcmp(*(const char **)a, *(const char **)b);
1910 * This routine initializes the builtin variables.
1920 * PS1 depends on uid
1922 #if ENABLE_FEATURE_EDITING && ENABLE_FEATURE_EDITING_FANCY_PROMPT
1923 vps1.text = "PS1=\\w \\$ ";
1926 vps1.text = "PS1=# ";
1929 end = vp + ARRAY_SIZE(varinit);
1931 vpp = hashvar(vp->text);
1934 } while (++vp < end);
1937 static struct var **
1938 findvar(struct var **vpp, const char *name)
1940 for (; *vpp; vpp = &(*vpp)->next) {
1941 if (varequal((*vpp)->text, name)) {
1949 * Find the value of a variable. Returns NULL if not set.
1952 lookupvar(const char *name)
1956 v = *findvar(hashvar(name), name);
1958 #if ENABLE_ASH_RANDOM_SUPPORT
1960 * Dynamic variables are implemented roughly the same way they are
1961 * in bash. Namely, they're "special" so long as they aren't unset.
1962 * As soon as they're unset, they're no longer dynamic, and dynamic
1963 * lookup will no longer happen at that point. -- PFM.
1965 if ((v->flags & VDYNAMIC))
1968 if (!(v->flags & VUNSET))
1969 return strchrnul(v->text, '=') + 1;
1975 * Search the environment of a builtin command.
1978 bltinlookup(const char *name)
1982 for (sp = cmdenviron; sp; sp = sp->next) {
1983 if (varequal(sp->text, name))
1984 return strchrnul(sp->text, '=') + 1;
1986 return lookupvar(name);
1990 * Same as setvar except that the variable and value are passed in
1991 * the first argument as name=value. Since the first argument will
1992 * be actually stored in the table, it should not be a string that
1994 * Called with interrupts off.
1997 setvareq(char *s, int flags)
1999 struct var *vp, **vpp;
2002 flags |= (VEXPORT & (((unsigned) (1 - aflag)) - 1));
2003 vp = *findvar(vpp, s);
2005 if ((vp->flags & (VREADONLY|VDYNAMIC)) == VREADONLY) {
2008 if (flags & VNOSAVE)
2011 ash_msg_and_raise_error("%.*s: is read only", strchrnul(n, '=') - n, n);
2017 if (vp->func && (flags & VNOFUNC) == 0)
2018 (*vp->func)(strchrnul(s, '=') + 1);
2020 if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
2021 free((char*)vp->text);
2023 flags |= vp->flags & ~(VTEXTFIXED|VSTACK|VNOSAVE|VUNSET);
2028 vp = ckzalloc(sizeof(*vp));
2030 /*vp->func = NULL; - ckzalloc did it */
2033 if (!(flags & (VTEXTFIXED|VSTACK|VNOSAVE)))
2040 * Set the value of a variable. The flags argument is ored with the
2041 * flags of the variable. If val is NULL, the variable is unset.
2044 setvar(const char *name, const char *val, int flags)
2051 q = endofname(name);
2052 p = strchrnul(q, '=');
2054 if (!namelen || p != q)
2055 ash_msg_and_raise_error("%.*s: bad variable name", namelen, name);
2060 vallen = strlen(val);
2063 nameeq = ckmalloc(namelen + vallen + 2);
2064 p = (char *)memcpy(nameeq, name, namelen) + namelen;
2067 p = (char *)memcpy(p, val, vallen) + vallen;
2070 setvareq(nameeq, flags | VNOSAVE);
2074 #if ENABLE_ASH_GETOPTS
2076 * Safe version of setvar, returns 1 on success 0 on failure.
2079 setvarsafe(const char *name, const char *val, int flags)
2082 volatile int saveint;
2083 struct jmploc *volatile savehandler = exception_handler;
2084 struct jmploc jmploc;
2087 if (setjmp(jmploc.loc))
2090 exception_handler = &jmploc;
2091 setvar(name, val, flags);
2094 exception_handler = savehandler;
2095 RESTORE_INT(saveint);
2101 * Unset the specified variable.
2104 unsetvar(const char *s)
2110 vpp = findvar(hashvar(s), s);
2114 int flags = vp->flags;
2117 if (flags & VREADONLY)
2119 #if ENABLE_ASH_RANDOM_SUPPORT
2120 vp->flags &= ~VDYNAMIC;
2124 if ((flags & VSTRFIXED) == 0) {
2126 if ((flags & (VTEXTFIXED|VSTACK)) == 0)
2127 free((char*)vp->text);
2133 vp->flags &= ~VEXPORT;
2143 * Process a linked list of variable assignments.
2146 listsetvar(struct strlist *list_set_var, int flags)
2148 struct strlist *lp = list_set_var;
2154 setvareq(lp->text, flags);
2161 * Generate a list of variables satisfying the given conditions.
2164 listvars(int on, int off, char ***end)
2175 for (vp = *vpp; vp; vp = vp->next) {
2176 if ((vp->flags & mask) == on) {
2177 if (ep == stackstrend())
2178 ep = growstackstr();
2179 *ep++ = (char *) vp->text;
2182 } while (++vpp < vartab + VTABSIZE);
2183 if (ep == stackstrend())
2184 ep = growstackstr();
2188 return grabstackstr(ep);
2192 /* ============ Path search helper
2194 * The variable path (passed by reference) should be set to the start
2195 * of the path before the first call; padvance will update
2196 * this value as it proceeds. Successive calls to padvance will return
2197 * the possible path expansions in sequence. If an option (indicated by
2198 * a percent sign) appears in the path entry then the global variable
2199 * pathopt will be set to point to it; otherwise pathopt will be set to
2202 static const char *pathopt; /* set by padvance */
2205 padvance(const char **path, const char *name)
2215 for (p = start; *p && *p != ':' && *p != '%'; p++)
2217 len = p - start + strlen(name) + 2; /* "2" is for '/' and '\0' */
2218 while (stackblocksize() < len)
2222 memcpy(q, start, p - start);
2230 while (*p && *p != ':')
2237 return stalloc(len);
2241 /* ============ Prompt */
2243 static smallint doprompt; /* if set, prompt the user */
2244 static smallint needprompt; /* true if interactive and at start of line */
2246 #if ENABLE_FEATURE_EDITING
2247 static line_input_t *line_input_state;
2248 static const char *cmdedit_prompt;
2250 putprompt(const char *s)
2252 if (ENABLE_ASH_EXPAND_PRMT) {
2253 free((char*)cmdedit_prompt);
2254 cmdedit_prompt = ckstrdup(s);
2261 putprompt(const char *s)
2267 #if ENABLE_ASH_EXPAND_PRMT
2268 /* expandstr() needs parsing machinery, so it is far away ahead... */
2269 static const char *expandstr(const char *ps);
2271 #define expandstr(s) s
2275 setprompt(int whichprompt)
2278 #if ENABLE_ASH_EXPAND_PRMT
2279 struct stackmark smark;
2284 switch (whichprompt) {
2294 #if ENABLE_ASH_EXPAND_PRMT
2295 setstackmark(&smark);
2296 stalloc(stackblocksize());
2298 putprompt(expandstr(prompt));
2299 #if ENABLE_ASH_EXPAND_PRMT
2300 popstackmark(&smark);
2305 /* ============ The cd and pwd commands */
2307 #define CD_PHYSICAL 1
2310 static int docd(const char *, int);
2319 while ((i = nextopt("LP"))) {
2321 flags ^= CD_PHYSICAL;
2330 * Update curdir (the name of the current directory) in response to a
2334 updatepwd(const char *dir)
2341 cdcomppath = ststrdup(dir);
2344 if (curdir == nullstr)
2346 new = stack_putstr(curdir, new);
2348 new = makestrspace(strlen(dir) + 2, new);
2349 lim = (char *)stackblock() + 1;
2353 if (new > lim && *lim == '/')
2358 if (dir[1] == '/' && dir[2] != '/') {
2364 p = strtok(cdcomppath, "/");
2368 if (p[1] == '.' && p[2] == '\0') {
2380 new = stack_putstr(p, new);
2388 return stackblock();
2392 * Find out what the current directory is. If we already know the current
2393 * directory, this routine returns immediately.
2398 char *dir = getcwd(NULL, 0); /* huh, using glibc extension? */
2399 return dir ? dir : nullstr;
2403 setpwd(const char *val, int setold)
2407 oldcur = dir = curdir;
2410 setvar("OLDPWD", oldcur, VEXPORT);
2413 if (physdir != nullstr) {
2414 if (physdir != oldcur)
2418 if (oldcur == val || !val) {
2424 dir = ckstrdup(val);
2425 if (oldcur != dir && oldcur != nullstr) {
2430 setvar("PWD", dir, VEXPORT);
2433 static void hashcd(void);
2436 * Actually do the chdir. We also call hashcd to let the routines in exec.c
2437 * know that the current directory has changed.
2440 docd(const char *dest, int flags)
2442 const char *dir = 0;
2445 TRACE(("docd(\"%s\", %d) called\n", dest, flags));
2448 if (!(flags & CD_PHYSICAL)) {
2449 dir = updatepwd(dest);
2464 cdcmd(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED)
2476 dest = bltinlookup(homestr);
2477 else if (LONE_DASH(dest)) {
2478 dest = bltinlookup("OLDPWD");
2500 path = bltinlookup("CDPATH");
2509 p = padvance(&path, dest);
2510 if (stat(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) {
2514 if (!docd(p, flags))
2519 ash_msg_and_raise_error("can't cd to %s", dest);
2522 if (flags & CD_PRINT)
2523 out1fmt(snlfmt, curdir);
2528 pwdcmd(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED)
2531 const char *dir = curdir;
2535 if (physdir == nullstr)
2539 out1fmt(snlfmt, dir);
2544 /* ============ ... */
2546 #define IBUFSIZ COMMON_BUFSIZE
2547 #define basebuf bb_common_bufsiz1 /* buffer for top level input file */
2549 /* Syntax classes */
2550 #define CWORD 0 /* character is nothing special */
2551 #define CNL 1 /* newline character */
2552 #define CBACK 2 /* a backslash character */
2553 #define CSQUOTE 3 /* single quote */
2554 #define CDQUOTE 4 /* double quote */
2555 #define CENDQUOTE 5 /* a terminating quote */
2556 #define CBQUOTE 6 /* backwards single quote */
2557 #define CVAR 7 /* a dollar sign */
2558 #define CENDVAR 8 /* a '}' character */
2559 #define CLP 9 /* a left paren in arithmetic */
2560 #define CRP 10 /* a right paren in arithmetic */
2561 #define CENDFILE 11 /* end of file */
2562 #define CCTL 12 /* like CWORD, except it must be escaped */
2563 #define CSPCL 13 /* these terminate a word */
2564 #define CIGN 14 /* character should be ignored */
2566 #if ENABLE_ASH_ALIAS
2570 #define PEOA_OR_PEOF PEOA
2574 #define PEOA_OR_PEOF PEOF
2577 /* number syntax index */
2578 #define BASESYNTAX 0 /* not in quotes */
2579 #define DQSYNTAX 1 /* in double quotes */
2580 #define SQSYNTAX 2 /* in single quotes */
2581 #define ARISYNTAX 3 /* in arithmetic */
2582 #define PSSYNTAX 4 /* prompt */
2584 #if ENABLE_ASH_OPTIMIZE_FOR_SIZE
2585 #define USE_SIT_FUNCTION
2588 #if ENABLE_ASH_MATH_SUPPORT
2589 static const char S_I_T[][4] = {
2590 #if ENABLE_ASH_ALIAS
2591 { CSPCL, CIGN, CIGN, CIGN }, /* 0, PEOA */
2593 { CSPCL, CWORD, CWORD, CWORD }, /* 1, ' ' */
2594 { CNL, CNL, CNL, CNL }, /* 2, \n */
2595 { CWORD, CCTL, CCTL, CWORD }, /* 3, !*-/:=?[]~ */
2596 { CDQUOTE, CENDQUOTE, CWORD, CWORD }, /* 4, '"' */
2597 { CVAR, CVAR, CWORD, CVAR }, /* 5, $ */
2598 { CSQUOTE, CWORD, CENDQUOTE, CWORD }, /* 6, "'" */
2599 { CSPCL, CWORD, CWORD, CLP }, /* 7, ( */
2600 { CSPCL, CWORD, CWORD, CRP }, /* 8, ) */
2601 { CBACK, CBACK, CCTL, CBACK }, /* 9, \ */
2602 { CBQUOTE, CBQUOTE, CWORD, CBQUOTE }, /* 10, ` */
2603 { CENDVAR, CENDVAR, CWORD, CENDVAR }, /* 11, } */
2604 #ifndef USE_SIT_FUNCTION
2605 { CENDFILE, CENDFILE, CENDFILE, CENDFILE }, /* 12, PEOF */
2606 { CWORD, CWORD, CWORD, CWORD }, /* 13, 0-9A-Za-z */
2607 { CCTL, CCTL, CCTL, CCTL } /* 14, CTLESC ... */
2611 static const char S_I_T[][3] = {
2612 #if ENABLE_ASH_ALIAS
2613 { CSPCL, CIGN, CIGN }, /* 0, PEOA */
2615 { CSPCL, CWORD, CWORD }, /* 1, ' ' */
2616 { CNL, CNL, CNL }, /* 2, \n */
2617 { CWORD, CCTL, CCTL }, /* 3, !*-/:=?[]~ */
2618 { CDQUOTE, CENDQUOTE, CWORD }, /* 4, '"' */
2619 { CVAR, CVAR, CWORD }, /* 5, $ */
2620 { CSQUOTE, CWORD, CENDQUOTE }, /* 6, "'" */
2621 { CSPCL, CWORD, CWORD }, /* 7, ( */
2622 { CSPCL, CWORD, CWORD }, /* 8, ) */
2623 { CBACK, CBACK, CCTL }, /* 9, \ */
2624 { CBQUOTE, CBQUOTE, CWORD }, /* 10, ` */
2625 { CENDVAR, CENDVAR, CWORD }, /* 11, } */
2626 #ifndef USE_SIT_FUNCTION
2627 { CENDFILE, CENDFILE, CENDFILE }, /* 12, PEOF */
2628 { CWORD, CWORD, CWORD }, /* 13, 0-9A-Za-z */
2629 { CCTL, CCTL, CCTL } /* 14, CTLESC ... */
2632 #endif /* ASH_MATH_SUPPORT */
2634 #ifdef USE_SIT_FUNCTION
2637 SIT(int c, int syntax)
2639 static const char spec_symbls[] ALIGN1 = "\t\n !\"$&'()*-/:;<=>?[\\]`|}~";
2640 #if ENABLE_ASH_ALIAS
2641 static const char syntax_index_table[] ALIGN1 = {
2642 1, 2, 1, 3, 4, 5, 1, 6, /* "\t\n !\"$&'" */
2643 7, 8, 3, 3, 3, 3, 1, 1, /* "()*-/:;<" */
2644 3, 1, 3, 3, 9, 3, 10, 1, /* "=>?[\\]`|" */
2648 static const char syntax_index_table[] ALIGN1 = {
2649 0, 1, 0, 2, 3, 4, 0, 5, /* "\t\n !\"$&'" */
2650 6, 7, 2, 2, 2, 2, 0, 0, /* "()*-/:;<" */
2651 2, 0, 2, 2, 8, 2, 9, 0, /* "=>?[\\]`|" */
2658 if (c == PEOF) /* 2^8+2 */
2660 #if ENABLE_ASH_ALIAS
2661 if (c == PEOA) /* 2^8+1 */
2665 #define U_C(c) ((unsigned char)(c))
2667 if ((unsigned char)c >= (unsigned char)(CTLESC)
2668 && (unsigned char)c <= (unsigned char)(CTLQUOTEMARK)
2672 s = strchrnul(spec_symbls, c);
2675 indx = syntax_index_table[s - spec_symbls];
2677 return S_I_T[indx][syntax];
2680 #else /* !USE_SIT_FUNCTION */
2682 #if ENABLE_ASH_ALIAS
2683 #define CSPCL_CIGN_CIGN_CIGN 0
2684 #define CSPCL_CWORD_CWORD_CWORD 1
2685 #define CNL_CNL_CNL_CNL 2
2686 #define CWORD_CCTL_CCTL_CWORD 3
2687 #define CDQUOTE_CENDQUOTE_CWORD_CWORD 4
2688 #define CVAR_CVAR_CWORD_CVAR 5
2689 #define CSQUOTE_CWORD_CENDQUOTE_CWORD 6
2690 #define CSPCL_CWORD_CWORD_CLP 7
2691 #define CSPCL_CWORD_CWORD_CRP 8
2692 #define CBACK_CBACK_CCTL_CBACK 9
2693 #define CBQUOTE_CBQUOTE_CWORD_CBQUOTE 10
2694 #define CENDVAR_CENDVAR_CWORD_CENDVAR 11
2695 #define CENDFILE_CENDFILE_CENDFILE_CENDFILE 12
2696 #define CWORD_CWORD_CWORD_CWORD 13
2697 #define CCTL_CCTL_CCTL_CCTL 14
2699 #define CSPCL_CWORD_CWORD_CWORD 0
2700 #define CNL_CNL_CNL_CNL 1
2701 #define CWORD_CCTL_CCTL_CWORD 2
2702 #define CDQUOTE_CENDQUOTE_CWORD_CWORD 3
2703 #define CVAR_CVAR_CWORD_CVAR 4
2704 #define CSQUOTE_CWORD_CENDQUOTE_CWORD 5
2705 #define CSPCL_CWORD_CWORD_CLP 6
2706 #define CSPCL_CWORD_CWORD_CRP 7
2707 #define CBACK_CBACK_CCTL_CBACK 8
2708 #define CBQUOTE_CBQUOTE_CWORD_CBQUOTE 9
2709 #define CENDVAR_CENDVAR_CWORD_CENDVAR 10
2710 #define CENDFILE_CENDFILE_CENDFILE_CENDFILE 11
2711 #define CWORD_CWORD_CWORD_CWORD 12
2712 #define CCTL_CCTL_CCTL_CCTL 13
2715 static const char syntax_index_table[258] = {
2716 /* BASESYNTAX_DQSYNTAX_SQSYNTAX_ARISYNTAX */
2717 /* 0 PEOF */ CENDFILE_CENDFILE_CENDFILE_CENDFILE,
2718 #if ENABLE_ASH_ALIAS
2719 /* 1 PEOA */ CSPCL_CIGN_CIGN_CIGN,
2721 /* 2 -128 0x80 */ CWORD_CWORD_CWORD_CWORD,
2722 /* 3 -127 CTLESC */ CCTL_CCTL_CCTL_CCTL,
2723 /* 4 -126 CTLVAR */ CCTL_CCTL_CCTL_CCTL,
2724 /* 5 -125 CTLENDVAR */ CCTL_CCTL_CCTL_CCTL,
2725 /* 6 -124 CTLBACKQ */ CCTL_CCTL_CCTL_CCTL,
2726 /* 7 -123 CTLQUOTE */ CCTL_CCTL_CCTL_CCTL,
2727 /* 8 -122 CTLARI */ CCTL_CCTL_CCTL_CCTL,
2728 /* 9 -121 CTLENDARI */ CCTL_CCTL_CCTL_CCTL,
2729 /* 10 -120 CTLQUOTEMARK */ CCTL_CCTL_CCTL_CCTL,
2730 /* 11 -119 */ CWORD_CWORD_CWORD_CWORD,
2731 /* 12 -118 */ CWORD_CWORD_CWORD_CWORD,
2732 /* 13 -117 */ CWORD_CWORD_CWORD_CWORD,
2733 /* 14 -116 */ CWORD_CWORD_CWORD_CWORD,
2734 /* 15 -115 */ CWORD_CWORD_CWORD_CWORD,
2735 /* 16 -114 */ CWORD_CWORD_CWORD_CWORD,
2736 /* 17 -113 */ CWORD_CWORD_CWORD_CWORD,
2737 /* 18 -112 */ CWORD_CWORD_CWORD_CWORD,
2738 /* 19 -111 */ CWORD_CWORD_CWORD_CWORD,
2739 /* 20 -110 */ CWORD_CWORD_CWORD_CWORD,
2740 /* 21 -109 */ CWORD_CWORD_CWORD_CWORD,
2741 /* 22 -108 */ CWORD_CWORD_CWORD_CWORD,
2742 /* 23 -107 */ CWORD_CWORD_CWORD_CWORD,
2743 /* 24 -106 */ CWORD_CWORD_CWORD_CWORD,
2744 /* 25 -105 */ CWORD_CWORD_CWORD_CWORD,
2745 /* 26 -104 */ CWORD_CWORD_CWORD_CWORD,
2746 /* 27 -103 */ CWORD_CWORD_CWORD_CWORD,
2747 /* 28 -102 */ CWORD_CWORD_CWORD_CWORD,
2748 /* 29 -101 */ CWORD_CWORD_CWORD_CWORD,
2749 /* 30 -100 */ CWORD_CWORD_CWORD_CWORD,
2750 /* 31 -99 */ CWORD_CWORD_CWORD_CWORD,
2751 /* 32 -98 */ CWORD_CWORD_CWORD_CWORD,
2752 /* 33 -97 */ CWORD_CWORD_CWORD_CWORD,
2753 /* 34 -96 */ CWORD_CWORD_CWORD_CWORD,
2754 /* 35 -95 */ CWORD_CWORD_CWORD_CWORD,
2755 /* 36 -94 */ CWORD_CWORD_CWORD_CWORD,
2756 /* 37 -93 */ CWORD_CWORD_CWORD_CWORD,
2757 /* 38 -92 */ CWORD_CWORD_CWORD_CWORD,
2758 /* 39 -91 */ CWORD_CWORD_CWORD_CWORD,
2759 /* 40 -90 */ CWORD_CWORD_CWORD_CWORD,
2760 /* 41 -89 */ CWORD_CWORD_CWORD_CWORD,
2761 /* 42 -88 */ CWORD_CWORD_CWORD_CWORD,
2762 /* 43 -87 */ CWORD_CWORD_CWORD_CWORD,
2763 /* 44 -86 */ CWORD_CWORD_CWORD_CWORD,
2764 /* 45 -85 */ CWORD_CWORD_CWORD_CWORD,
2765 /* 46 -84 */ CWORD_CWORD_CWORD_CWORD,
2766 /* 47 -83 */ CWORD_CWORD_CWORD_CWORD,
2767 /* 48 -82 */ CWORD_CWORD_CWORD_CWORD,
2768 /* 49 -81 */ CWORD_CWORD_CWORD_CWORD,
2769 /* 50 -80 */ CWORD_CWORD_CWORD_CWORD,
2770 /* 51 -79 */ CWORD_CWORD_CWORD_CWORD,
2771 /* 52 -78 */ CWORD_CWORD_CWORD_CWORD,
2772 /* 53 -77 */ CWORD_CWORD_CWORD_CWORD,
2773 /* 54 -76 */ CWORD_CWORD_CWORD_CWORD,
2774 /* 55 -75 */ CWORD_CWORD_CWORD_CWORD,
2775 /* 56 -74 */ CWORD_CWORD_CWORD_CWORD,
2776 /* 57 -73 */ CWORD_CWORD_CWORD_CWORD,
2777 /* 58 -72 */ CWORD_CWORD_CWORD_CWORD,
2778 /* 59 -71 */ CWORD_CWORD_CWORD_CWORD,
2779 /* 60 -70 */ CWORD_CWORD_CWORD_CWORD,
2780 /* 61 -69 */ CWORD_CWORD_CWORD_CWORD,
2781 /* 62 -68 */ CWORD_CWORD_CWORD_CWORD,
2782 /* 63 -67 */ CWORD_CWORD_CWORD_CWORD,
2783 /* 64 -66 */ CWORD_CWORD_CWORD_CWORD,
2784 /* 65 -65 */ CWORD_CWORD_CWORD_CWORD,
2785 /* 66 -64 */ CWORD_CWORD_CWORD_CWORD,
2786 /* 67 -63 */ CWORD_CWORD_CWORD_CWORD,
2787 /* 68 -62 */ CWORD_CWORD_CWORD_CWORD,
2788 /* 69 -61 */ CWORD_CWORD_CWORD_CWORD,
2789 /* 70 -60 */ CWORD_CWORD_CWORD_CWORD,
2790 /* 71 -59 */ CWORD_CWORD_CWORD_CWORD,
2791 /* 72 -58 */ CWORD_CWORD_CWORD_CWORD,
2792 /* 73 -57 */ CWORD_CWORD_CWORD_CWORD,
2793 /* 74 -56 */ CWORD_CWORD_CWORD_CWORD,
2794 /* 75 -55 */ CWORD_CWORD_CWORD_CWORD,
2795 /* 76 -54 */ CWORD_CWORD_CWORD_CWORD,
2796 /* 77 -53 */ CWORD_CWORD_CWORD_CWORD,
2797 /* 78 -52 */ CWORD_CWORD_CWORD_CWORD,
2798 /* 79 -51 */ CWORD_CWORD_CWORD_CWORD,
2799 /* 80 -50 */ CWORD_CWORD_CWORD_CWORD,
2800 /* 81 -49 */ CWORD_CWORD_CWORD_CWORD,
2801 /* 82 -48 */ CWORD_CWORD_CWORD_CWORD,
2802 /* 83 -47 */ CWORD_CWORD_CWORD_CWORD,
2803 /* 84 -46 */ CWORD_CWORD_CWORD_CWORD,
2804 /* 85 -45 */ CWORD_CWORD_CWORD_CWORD,
2805 /* 86 -44 */ CWORD_CWORD_CWORD_CWORD,
2806 /* 87 -43 */ CWORD_CWORD_CWORD_CWORD,
2807 /* 88 -42 */ CWORD_CWORD_CWORD_CWORD,
2808 /* 89 -41 */ CWORD_CWORD_CWORD_CWORD,
2809 /* 90 -40 */ CWORD_CWORD_CWORD_CWORD,
2810 /* 91 -39 */ CWORD_CWORD_CWORD_CWORD,
2811 /* 92 -38 */ CWORD_CWORD_CWORD_CWORD,
2812 /* 93 -37 */ CWORD_CWORD_CWORD_CWORD,
2813 /* 94 -36 */ CWORD_CWORD_CWORD_CWORD,
2814 /* 95 -35 */ CWORD_CWORD_CWORD_CWORD,
2815 /* 96 -34 */ CWORD_CWORD_CWORD_CWORD,
2816 /* 97 -33 */ CWORD_CWORD_CWORD_CWORD,
2817 /* 98 -32 */ CWORD_CWORD_CWORD_CWORD,
2818 /* 99 -31 */ CWORD_CWORD_CWORD_CWORD,
2819 /* 100 -30 */ CWORD_CWORD_CWORD_CWORD,
2820 /* 101 -29 */ CWORD_CWORD_CWORD_CWORD,
2821 /* 102 -28 */ CWORD_CWORD_CWORD_CWORD,
2822 /* 103 -27 */ CWORD_CWORD_CWORD_CWORD,
2823 /* 104 -26 */ CWORD_CWORD_CWORD_CWORD,
2824 /* 105 -25 */ CWORD_CWORD_CWORD_CWORD,
2825 /* 106 -24 */ CWORD_CWORD_CWORD_CWORD,
2826 /* 107 -23 */ CWORD_CWORD_CWORD_CWORD,
2827 /* 108 -22 */ CWORD_CWORD_CWORD_CWORD,
2828 /* 109 -21 */ CWORD_CWORD_CWORD_CWORD,
2829 /* 110 -20 */ CWORD_CWORD_CWORD_CWORD,
2830 /* 111 -19 */ CWORD_CWORD_CWORD_CWORD,
2831 /* 112 -18 */ CWORD_CWORD_CWORD_CWORD,
2832 /* 113 -17 */ CWORD_CWORD_CWORD_CWORD,
2833 /* 114 -16 */ CWORD_CWORD_CWORD_CWORD,
2834 /* 115 -15 */ CWORD_CWORD_CWORD_CWORD,
2835 /* 116 -14 */ CWORD_CWORD_CWORD_CWORD,
2836 /* 117 -13 */ CWORD_CWORD_CWORD_CWORD,
2837 /* 118 -12 */ CWORD_CWORD_CWORD_CWORD,
2838 /* 119 -11 */ CWORD_CWORD_CWORD_CWORD,
2839 /* 120 -10 */ CWORD_CWORD_CWORD_CWORD,
2840 /* 121 -9 */ CWORD_CWORD_CWORD_CWORD,
2841 /* 122 -8 */ CWORD_CWORD_CWORD_CWORD,
2842 /* 123 -7 */ CWORD_CWORD_CWORD_CWORD,
2843 /* 124 -6 */ CWORD_CWORD_CWORD_CWORD,
2844 /* 125 -5 */ CWORD_CWORD_CWORD_CWORD,
2845 /* 126 -4 */ CWORD_CWORD_CWORD_CWORD,
2846 /* 127 -3 */ CWORD_CWORD_CWORD_CWORD,
2847 /* 128 -2 */ CWORD_CWORD_CWORD_CWORD,
2848 /* 129 -1 */ CWORD_CWORD_CWORD_CWORD,
2849 /* 130 0 */ CWORD_CWORD_CWORD_CWORD,
2850 /* 131 1 */ CWORD_CWORD_CWORD_CWORD,
2851 /* 132 2 */ CWORD_CWORD_CWORD_CWORD,
2852 /* 133 3 */ CWORD_CWORD_CWORD_CWORD,
2853 /* 134 4 */ CWORD_CWORD_CWORD_CWORD,
2854 /* 135 5 */ CWORD_CWORD_CWORD_CWORD,
2855 /* 136 6 */ CWORD_CWORD_CWORD_CWORD,
2856 /* 137 7 */ CWORD_CWORD_CWORD_CWORD,
2857 /* 138 8 */ CWORD_CWORD_CWORD_CWORD,
2858 /* 139 9 "\t" */ CSPCL_CWORD_CWORD_CWORD,
2859 /* 140 10 "\n" */ CNL_CNL_CNL_CNL,
2860 /* 141 11 */ CWORD_CWORD_CWORD_CWORD,
2861 /* 142 12 */ CWORD_CWORD_CWORD_CWORD,
2862 /* 143 13 */ CWORD_CWORD_CWORD_CWORD,
2863 /* 144 14 */ CWORD_CWORD_CWORD_CWORD,
2864 /* 145 15 */ CWORD_CWORD_CWORD_CWORD,
2865 /* 146 16 */ CWORD_CWORD_CWORD_CWORD,
2866 /* 147 17 */ CWORD_CWORD_CWORD_CWORD,
2867 /* 148 18 */ CWORD_CWORD_CWORD_CWORD,
2868 /* 149 19 */ CWORD_CWORD_CWORD_CWORD,
2869 /* 150 20 */ CWORD_CWORD_CWORD_CWORD,
2870 /* 151 21 */ CWORD_CWORD_CWORD_CWORD,
2871 /* 152 22 */ CWORD_CWORD_CWORD_CWORD,
2872 /* 153 23 */ CWORD_CWORD_CWORD_CWORD,
2873 /* 154 24 */ CWORD_CWORD_CWORD_CWORD,
2874 /* 155 25 */ CWORD_CWORD_CWORD_CWORD,
2875 /* 156 26 */ CWORD_CWORD_CWORD_CWORD,
2876 /* 157 27 */ CWORD_CWORD_CWORD_CWORD,
2877 /* 158 28 */ CWORD_CWORD_CWORD_CWORD,
2878 /* 159 29 */ CWORD_CWORD_CWORD_CWORD,
2879 /* 160 30 */ CWORD_CWORD_CWORD_CWORD,
2880 /* 161 31 */ CWORD_CWORD_CWORD_CWORD,
2881 /* 162 32 " " */ CSPCL_CWORD_CWORD_CWORD,
2882 /* 163 33 "!" */ CWORD_CCTL_CCTL_CWORD,
2883 /* 164 34 """ */ CDQUOTE_CENDQUOTE_CWORD_CWORD,
2884 /* 165 35 "#" */ CWORD_CWORD_CWORD_CWORD,
2885 /* 166 36 "$" */ CVAR_CVAR_CWORD_CVAR,
2886 /* 167 37 "%" */ CWORD_CWORD_CWORD_CWORD,
2887 /* 168 38 "&" */ CSPCL_CWORD_CWORD_CWORD,
2888 /* 169 39 "'" */ CSQUOTE_CWORD_CENDQUOTE_CWORD,
2889 /* 170 40 "(" */ CSPCL_CWORD_CWORD_CLP,
2890 /* 171 41 ")" */ CSPCL_CWORD_CWORD_CRP,
2891 /* 172 42 "*" */ CWORD_CCTL_CCTL_CWORD,
2892 /* 173 43 "+" */ CWORD_CWORD_CWORD_CWORD,
2893 /* 174 44 "," */ CWORD_CWORD_CWORD_CWORD,
2894 /* 175 45 "-" */ CWORD_CCTL_CCTL_CWORD,
2895 /* 176 46 "." */ CWORD_CWORD_CWORD_CWORD,
2896 /* 177 47 "/" */ CWORD_CCTL_CCTL_CWORD,
2897 /* 178 48 "0" */ CWORD_CWORD_CWORD_CWORD,
2898 /* 179 49 "1" */ CWORD_CWORD_CWORD_CWORD,
2899 /* 180 50 "2" */ CWORD_CWORD_CWORD_CWORD,
2900 /* 181 51 "3" */ CWORD_CWORD_CWORD_CWORD,
2901 /* 182 52 "4" */ CWORD_CWORD_CWORD_CWORD,
2902 /* 183 53 "5" */ CWORD_CWORD_CWORD_CWORD,
2903 /* 184 54 "6" */ CWORD_CWORD_CWORD_CWORD,
2904 /* 185 55 "7" */ CWORD_CWORD_CWORD_CWORD,
2905 /* 186 56 "8" */ CWORD_CWORD_CWORD_CWORD,
2906 /* 187 57 "9" */ CWORD_CWORD_CWORD_CWORD,
2907 /* 188 58 ":" */ CWORD_CCTL_CCTL_CWORD,
2908 /* 189 59 ";" */ CSPCL_CWORD_CWORD_CWORD,
2909 /* 190 60 "<" */ CSPCL_CWORD_CWORD_CWORD,
2910 /* 191 61 "=" */ CWORD_CCTL_CCTL_CWORD,
2911 /* 192 62 ">" */ CSPCL_CWORD_CWORD_CWORD,
2912 /* 193 63 "?" */ CWORD_CCTL_CCTL_CWORD,
2913 /* 194 64 "@" */ CWORD_CWORD_CWORD_CWORD,
2914 /* 195 65 "A" */ CWORD_CWORD_CWORD_CWORD,
2915 /* 196 66 "B" */ CWORD_CWORD_CWORD_CWORD,
2916 /* 197 67 "C" */ CWORD_CWORD_CWORD_CWORD,
2917 /* 198 68 "D" */ CWORD_CWORD_CWORD_CWORD,
2918 /* 199 69 "E" */ CWORD_CWORD_CWORD_CWORD,
2919 /* 200 70 "F" */ CWORD_CWORD_CWORD_CWORD,
2920 /* 201 71 "G" */ CWORD_CWORD_CWORD_CWORD,
2921 /* 202 72 "H" */ CWORD_CWORD_CWORD_CWORD,
2922 /* 203 73 "I" */ CWORD_CWORD_CWORD_CWORD,
2923 /* 204 74 "J" */ CWORD_CWORD_CWORD_CWORD,
2924 /* 205 75 "K" */ CWORD_CWORD_CWORD_CWORD,
2925 /* 206 76 "L" */ CWORD_CWORD_CWORD_CWORD,
2926 /* 207 77 "M" */ CWORD_CWORD_CWORD_CWORD,
2927 /* 208 78 "N" */ CWORD_CWORD_CWORD_CWORD,
2928 /* 209 79 "O" */ CWORD_CWORD_CWORD_CWORD,
2929 /* 210 80 "P" */ CWORD_CWORD_CWORD_CWORD,
2930 /* 211 81 "Q" */ CWORD_CWORD_CWORD_CWORD,
2931 /* 212 82 "R" */ CWORD_CWORD_CWORD_CWORD,
2932 /* 213 83 "S" */ CWORD_CWORD_CWORD_CWORD,
2933 /* 214 84 "T" */ CWORD_CWORD_CWORD_CWORD,
2934 /* 215 85 "U" */ CWORD_CWORD_CWORD_CWORD,
2935 /* 216 86 "V" */ CWORD_CWORD_CWORD_CWORD,
2936 /* 217 87 "W" */ CWORD_CWORD_CWORD_CWORD,
2937 /* 218 88 "X" */ CWORD_CWORD_CWORD_CWORD,
2938 /* 219 89 "Y" */ CWORD_CWORD_CWORD_CWORD,
2939 /* 220 90 "Z" */ CWORD_CWORD_CWORD_CWORD,
2940 /* 221 91 "[" */ CWORD_CCTL_CCTL_CWORD,
2941 /* 222 92 "\" */ CBACK_CBACK_CCTL_CBACK,
2942 /* 223 93 "]" */ CWORD_CCTL_CCTL_CWORD,
2943 /* 224 94 "^" */ CWORD_CWORD_CWORD_CWORD,
2944 /* 225 95 "_" */ CWORD_CWORD_CWORD_CWORD,
2945 /* 226 96 "`" */ CBQUOTE_CBQUOTE_CWORD_CBQUOTE,
2946 /* 227 97 "a" */ CWORD_CWORD_CWORD_CWORD,
2947 /* 228 98 "b" */ CWORD_CWORD_CWORD_CWORD,
2948 /* 229 99 "c" */ CWORD_CWORD_CWORD_CWORD,
2949 /* 230 100 "d" */ CWORD_CWORD_CWORD_CWORD,
2950 /* 231 101 "e" */ CWORD_CWORD_CWORD_CWORD,
2951 /* 232 102 "f" */ CWORD_CWORD_CWORD_CWORD,
2952 /* 233 103 "g" */ CWORD_CWORD_CWORD_CWORD,
2953 /* 234 104 "h" */ CWORD_CWORD_CWORD_CWORD,
2954 /* 235 105 "i" */ CWORD_CWORD_CWORD_CWORD,
2955 /* 236 106 "j" */ CWORD_CWORD_CWORD_CWORD,
2956 /* 237 107 "k" */ CWORD_CWORD_CWORD_CWORD,
2957 /* 238 108 "l" */ CWORD_CWORD_CWORD_CWORD,
2958 /* 239 109 "m" */ CWORD_CWORD_CWORD_CWORD,
2959 /* 240 110 "n" */ CWORD_CWORD_CWORD_CWORD,
2960 /* 241 111 "o" */ CWORD_CWORD_CWORD_CWORD,
2961 /* 242 112 "p" */ CWORD_CWORD_CWORD_CWORD,
2962 /* 243 113 "q" */ CWORD_CWORD_CWORD_CWORD,
2963 /* 244 114 "r" */ CWORD_CWORD_CWORD_CWORD,
2964 /* 245 115 "s" */ CWORD_CWORD_CWORD_CWORD,
2965 /* 246 116 "t" */ CWORD_CWORD_CWORD_CWORD,
2966 /* 247 117 "u" */ CWORD_CWORD_CWORD_CWORD,
2967 /* 248 118 "v" */ CWORD_CWORD_CWORD_CWORD,
2968 /* 249 119 "w" */ CWORD_CWORD_CWORD_CWORD,
2969 /* 250 120 "x" */ CWORD_CWORD_CWORD_CWORD,
2970 /* 251 121 "y" */ CWORD_CWORD_CWORD_CWORD,
2971 /* 252 122 "z" */ CWORD_CWORD_CWORD_CWORD,
2972 /* 253 123 "{" */ CWORD_CWORD_CWORD_CWORD,
2973 /* 254 124 "|" */ CSPCL_CWORD_CWORD_CWORD,
2974 /* 255 125 "}" */ CENDVAR_CENDVAR_CWORD_CENDVAR,
2975 /* 256 126 "~" */ CWORD_CCTL_CCTL_CWORD,
2976 /* 257 127 */ CWORD_CWORD_CWORD_CWORD,
2979 #define SIT(c, syntax) (S_I_T[(int)syntax_index_table[((int)c)+SYNBASE]][syntax])
2981 #endif /* USE_SIT_FUNCTION */
2984 /* ============ Alias handling */
2986 #if ENABLE_ASH_ALIAS
2988 #define ALIASINUSE 1
2999 static struct alias **atab; // [ATABSIZE];
3000 #define INIT_G_alias() do { \
3001 atab = xzalloc(ATABSIZE * sizeof(atab[0])); \
3005 static struct alias **
3006 __lookupalias(const char *name) {
3007 unsigned int hashval;
3014 ch = (unsigned char)*p;
3018 ch = (unsigned char)*++p;
3020 app = &atab[hashval % ATABSIZE];
3022 for (; *app; app = &(*app)->next) {
3023 if (strcmp(name, (*app)->name) == 0) {
3031 static struct alias *
3032 lookupalias(const char *name, int check)
3034 struct alias *ap = *__lookupalias(name);
3036 if (check && ap && (ap->flag & ALIASINUSE))
3041 static struct alias *
3042 freealias(struct alias *ap)
3046 if (ap->flag & ALIASINUSE) {
3047 ap->flag |= ALIASDEAD;
3059 setalias(const char *name, const char *val)
3061 struct alias *ap, **app;
3063 app = __lookupalias(name);
3067 if (!(ap->flag & ALIASINUSE)) {
3070 ap->val = ckstrdup(val);
3071 ap->flag &= ~ALIASDEAD;
3074 ap = ckzalloc(sizeof(struct alias));
3075 ap->name = ckstrdup(name);
3076 ap->val = ckstrdup(val);
3077 /*ap->flag = 0; - ckzalloc did it */
3078 /*ap->next = NULL;*/
3085 unalias(const char *name)
3089 app = __lookupalias(name);
3093 *app = freealias(*app);
3104 struct alias *ap, **app;
3108 for (i = 0; i < ATABSIZE; i++) {
3110 for (ap = *app; ap; ap = *app) {
3111 *app = freealias(*app);
3121 printalias(const struct alias *ap)
3123 out1fmt("%s=%s\n", ap->name, single_quote(ap->val));
3127 * TODO - sort output
3130 aliascmd(int argc ATTRIBUTE_UNUSED, char **argv)
3139 for (i = 0; i < ATABSIZE; i++) {
3140 for (ap = atab[i]; ap; ap = ap->next) {
3146 while ((n = *++argv) != NULL) {
3147 v = strchr(n+1, '=');
3148 if (v == NULL) { /* n+1: funny ksh stuff */
3149 ap = *__lookupalias(n);
3151 fprintf(stderr, "%s: %s not found\n", "alias", n);
3165 unaliascmd(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED)
3169 while ((i = nextopt("a")) != '\0') {
3175 for (i = 0; *argptr; argptr++) {
3176 if (unalias(*argptr)) {
3177 fprintf(stderr, "%s: %s not found\n", "unalias", *argptr);
3185 #endif /* ASH_ALIAS */
3188 /* ============ jobs.c */
3190 /* Mode argument to forkshell. Don't change FORK_FG or FORK_BG. */
3193 #define FORK_NOJOB 2
3195 /* mode flags for showjob(s) */
3196 #define SHOW_PGID 0x01 /* only show pgid - for jobs -p */
3197 #define SHOW_PID 0x04 /* include process pid */
3198 #define SHOW_CHANGED 0x08 /* only jobs whose state has changed */
3201 * A job structure contains information about a job. A job is either a
3202 * single process or a set of processes contained in a pipeline. In the
3203 * latter case, pidlist will be non-NULL, and will point to a -1 terminated
3208 pid_t pid; /* process id */
3209 int status; /* last process status from wait() */
3210 char *cmd; /* text of command being run */
3214 struct procstat ps0; /* status of process */
3215 struct procstat *ps; /* status or processes when more than one */
3217 int stopstatus; /* status of a stopped job */
3220 nprocs: 16, /* number of processes */
3222 #define JOBRUNNING 0 /* at least one proc running */
3223 #define JOBSTOPPED 1 /* all procs are stopped */
3224 #define JOBDONE 2 /* all procs are completed */
3226 sigint: 1, /* job was killed by SIGINT */
3227 jobctl: 1, /* job running under job control */
3229 waited: 1, /* true if this entry has been waited for */
3230 used: 1, /* true if this entry is in used */
3231 changed: 1; /* true if status has changed */
3232 struct job *prev_job; /* previous job */
3235 static struct job *makejob(/*union node *,*/ int);
3237 #define forkshell(job, node, mode) forkshell(job, mode)
3239 static int forkshell(struct job *, union node *, int);
3240 static int waitforjob(struct job *);
3243 enum { doing_jobctl = 0 };
3244 #define setjobctl(on) do {} while (0)
3246 static smallint doing_jobctl; //references:8
3247 static void setjobctl(int);
3251 * Set the signal handler for the specified signal. The routine figures
3252 * out what it should be set to.
3255 setsignal(int signo)
3259 struct sigaction act;
3265 else if (*t != '\0')
3267 if (rootshell && action == S_DFL) {
3270 if (iflag || minusc || sflag == 0)
3293 t = &sigmode[signo - 1];
3297 * current setting unknown
3299 if (sigaction(signo, NULL, &act) == -1) {
3301 * Pretend it worked; maybe we should give a warning
3302 * here, but other shells don't. We don't alter
3303 * sigmode, so that we retry every time.
3307 tsig = S_RESET; /* force to be set */
3308 if (act.sa_handler == SIG_IGN) {
3311 && (signo == SIGTSTP || signo == SIGTTIN || signo == SIGTTOU)
3313 tsig = S_IGN; /* don't hard ignore these */
3317 if (tsig == S_HARD_IGN || tsig == action)
3319 act.sa_handler = SIG_DFL;
3322 act.sa_handler = onsig;
3325 act.sa_handler = SIG_IGN;
3330 sigfillset(&act.sa_mask);
3331 sigaction_set(signo, &act);
3334 /* mode flags for set_curjob */
3335 #define CUR_DELETE 2
3336 #define CUR_RUNNING 1
3337 #define CUR_STOPPED 0
3339 /* mode flags for dowait */
3340 #define DOWAIT_NONBLOCK WNOHANG
3341 #define DOWAIT_BLOCK 0
3344 /* pgrp of shell on invocation */
3345 static int initialpgrp; //references:2
3346 static int ttyfd = -1; //5
3349 static struct job *jobtab; //5
3351 static unsigned njobs; //4
3353 static struct job *curjob; //lots
3354 /* number of presumed living untracked jobs */
3355 static int jobless; //4
3358 set_curjob(struct job *jp, unsigned mode)
3361 struct job **jpp, **curp;
3363 /* first remove from list */
3364 jpp = curp = &curjob;
3369 jpp = &jp1->prev_job;
3371 *jpp = jp1->prev_job;
3373 /* Then re-insert in correct position */
3381 /* job being deleted */
3384 /* newly created job or backgrounded job,
3385 put after all stopped jobs. */
3389 if (!jp1 || jp1->state != JOBSTOPPED)
3392 jpp = &jp1->prev_job;
3398 /* newly stopped job - becomes curjob */
3399 jp->prev_job = *jpp;
3407 jobno(const struct job *jp)
3409 return jp - jobtab + 1;
3414 * Convert a job name to a job structure.
3417 #define getjob(name, getctl) getjob(name)
3420 getjob(const char *name, int getctl)
3424 const char *err_msg = "No such job: %s";
3428 char *(*match)(const char *, const char *);
3443 if (c == '+' || c == '%') {
3445 err_msg = "No current job";
3451 err_msg = "No previous job";
3460 // TODO: number() instead? It does error checking...
3463 jp = jobtab + num - 1;
3480 if (match(jp->ps[0].cmd, p)) {
3484 err_msg = "%s: ambiguous";
3491 err_msg = "job %s not created under job control";
3492 if (getctl && jp->jobctl == 0)
3497 ash_msg_and_raise_error(err_msg, name);
3501 * Mark a job structure as unused.
3504 freejob(struct job *jp)
3506 struct procstat *ps;
3510 for (i = jp->nprocs, ps = jp->ps; --i >= 0; ps++) {
3511 if (ps->cmd != nullstr)
3514 if (jp->ps != &jp->ps0)
3517 set_curjob(jp, CUR_DELETE);
3523 xtcsetpgrp(int fd, pid_t pgrp)
3525 if (tcsetpgrp(fd, pgrp))
3526 ash_msg_and_raise_error("cannot set tty process group (%m)");
3530 * Turn job control on and off.
3532 * Note: This code assumes that the third arg to ioctl is a character
3533 * pointer, which is true on Berkeley systems but not System V. Since
3534 * System V doesn't have job control yet, this isn't a problem now.
3536 * Called with interrupts off.
3544 if (on == doing_jobctl || rootshell == 0)
3548 ofd = fd = open(_PATH_TTY, O_RDWR);
3550 /* BTW, bash will try to open(ttyname(0)) if open("/dev/tty") fails.
3551 * That sometimes helps to acquire controlling tty.
3552 * Obviously, a workaround for bugs when someone
3553 * failed to provide a controlling tty to bash! :) */
3559 fd = fcntl(fd, F_DUPFD, 10);
3564 /* fd is a tty at this point */
3565 close_on_exec_on(fd);
3566 do { /* while we are in the background */
3567 pgrp = tcgetpgrp(fd);
3570 ash_msg("can't access tty; job control turned off");
3574 if (pgrp == getpgrp())
3585 xtcsetpgrp(fd, pgrp);
3587 /* turning job control off */
3590 /* was xtcsetpgrp, but this can make exiting ash
3591 * loop forever if pty is already deleted */
3592 tcsetpgrp(fd, pgrp);
3607 killcmd(int argc, char **argv)
3610 if (argv[1] && strcmp(argv[1], "-l") != 0) {
3612 if (argv[i][0] == '%') {
3613 struct job *jp = getjob(argv[i], 0);
3614 unsigned pid = jp->ps[0].pid;
3615 /* Enough space for ' -NNN<nul>' */
3616 argv[i] = alloca(sizeof(int)*3 + 3);
3617 /* kill_main has matching code to expect
3618 * leading space. Needed to not confuse
3619 * negative pids with "kill -SIGNAL_NO" syntax */
3620 sprintf(argv[i], " -%u", pid);
3622 } while (argv[++i]);
3624 return kill_main(argc, argv);
3628 showpipe(struct job *jp, FILE *out)
3630 struct procstat *sp;
3631 struct procstat *spend;
3633 spend = jp->ps + jp->nprocs;
3634 for (sp = jp->ps + 1; sp < spend; sp++)
3635 fprintf(out, " | %s", sp->cmd);
3636 outcslow('\n', out);
3637 flush_stdout_stderr();
3642 restartjob(struct job *jp, int mode)
3644 struct procstat *ps;
3650 if (jp->state == JOBDONE)
3652 jp->state = JOBRUNNING;
3654 if (mode == FORK_FG)
3655 xtcsetpgrp(ttyfd, pgid);
3656 killpg(pgid, SIGCONT);
3660 if (WIFSTOPPED(ps->status)) {
3666 status = (mode == FORK_FG) ? waitforjob(jp) : 0;
3672 fg_bgcmd(int argc ATTRIBUTE_UNUSED, char **argv)
3679 mode = (**argv == 'f') ? FORK_FG : FORK_BG;
3684 jp = getjob(*argv, 1);
3685 if (mode == FORK_BG) {
3686 set_curjob(jp, CUR_RUNNING);
3687 fprintf(out, "[%d] ", jobno(jp));
3689 outstr(jp->ps->cmd, out);
3691 retval = restartjob(jp, mode);
3692 } while (*argv && *++argv);
3698 sprint_status(char *s, int status, int sigonly)
3704 if (!WIFEXITED(status)) {
3706 if (WIFSTOPPED(status))
3707 st = WSTOPSIG(status);
3710 st = WTERMSIG(status);
3712 if (st == SIGINT || st == SIGPIPE)
3715 if (WIFSTOPPED(status))
3720 col = fmtstr(s, 32, strsignal(st));
3721 if (WCOREDUMP(status)) {
3722 col += fmtstr(s + col, 16, " (core dumped)");
3724 } else if (!sigonly) {
3725 st = WEXITSTATUS(status);
3727 col = fmtstr(s, 16, "Done(%d)", st);
3729 col = fmtstr(s, 16, "Done");
3736 * Do a wait system call. If job control is compiled in, we accept
3737 * stopped processes. If block is zero, we return a value of zero
3738 * rather than blocking.
3740 * System V doesn't have a non-blocking wait system call. It does
3741 * have a SIGCLD signal that is sent to a process when one of it's
3742 * children dies. The obvious way to use SIGCLD would be to install
3743 * a handler for SIGCLD which simply bumped a counter when a SIGCLD
3744 * was received, and have waitproc bump another counter when it got
3745 * the status of a process. Waitproc would then know that a wait
3746 * system call would not block if the two counters were different.
3747 * This approach doesn't work because if a process has children that
3748 * have not been waited for, System V will send it a SIGCLD when it
3749 * installs a signal handler for SIGCLD. What this means is that when
3750 * a child exits, the shell will be sent SIGCLD signals continuously
3751 * until is runs out of stack space, unless it does a wait call before
3752 * restoring the signal handler. The code below takes advantage of
3753 * this (mis)feature by installing a signal handler for SIGCLD and
3754 * then checking to see whether it was called. If there are any
3755 * children to be waited for, it will be.
3757 * If neither SYSV nor BSD is defined, we don't implement nonblocking
3758 * waits at all. In this case, the user will not be informed when
3759 * a background process until the next time she runs a real program
3760 * (as opposed to running a builtin command or just typing return),
3761 * and the jobs command may give out of date information.
3764 waitproc(int wait_flags, int *status)
3768 wait_flags |= WUNTRACED;
3770 /* NB: _not_ safe_waitpid, we need to detect EINTR */
3771 return waitpid(-1, status, wait_flags);
3775 * Wait for a process to terminate.
3778 dowait(int wait_flags, struct job *job)
3783 struct job *thisjob;
3786 TRACE(("dowait(%d) called\n", wait_flags));
3787 pid = waitproc(wait_flags, &status);
3788 TRACE(("wait returns pid=%d, status=%d\n", pid, status));
3790 /* If we were doing blocking wait and (probably) got EINTR,
3791 * check for pending sigs received while waiting.
3792 * (NB: can be moved into callers if needed) */
3793 if (wait_flags == DOWAIT_BLOCK && pendingsig)
3794 raise_exception(EXSIG);
3799 for (jp = curjob; jp; jp = jp->prev_job) {
3800 struct procstat *sp;
3801 struct procstat *spend;
3802 if (jp->state == JOBDONE)
3805 spend = jp->ps + jp->nprocs;
3808 if (sp->pid == pid) {
3809 TRACE(("Job %d: changing status of proc %d "
3810 "from 0x%x to 0x%x\n",
3811 jobno(jp), pid, sp->status, status));
3812 sp->status = status;
3815 if (sp->status == -1)
3818 if (state == JOBRUNNING)
3820 if (WIFSTOPPED(sp->status)) {
3821 jp->stopstatus = sp->status;
3825 } while (++sp < spend);
3830 if (!WIFSTOPPED(status))
3836 if (state != JOBRUNNING) {
3837 thisjob->changed = 1;
3839 if (thisjob->state != state) {
3840 TRACE(("Job %d: changing state from %d to %d\n",
3841 jobno(thisjob), thisjob->state, state));
3842 thisjob->state = state;
3844 if (state == JOBSTOPPED) {
3845 set_curjob(thisjob, CUR_STOPPED);
3854 if (thisjob && thisjob == job) {
3858 len = sprint_status(s, status, 1);
3870 showjob(FILE *out, struct job *jp, int mode)
3872 struct procstat *ps;
3873 struct procstat *psend;
3880 if (mode & SHOW_PGID) {
3881 /* just output process (group) id of pipeline */
3882 fprintf(out, "%d\n", ps->pid);
3886 col = fmtstr(s, 16, "[%d] ", jobno(jp));
3891 else if (curjob && jp == curjob->prev_job)
3894 if (mode & SHOW_PID)
3895 col += fmtstr(s + col, 16, "%d ", ps->pid);
3897 psend = ps + jp->nprocs;
3899 if (jp->state == JOBRUNNING) {
3900 strcpy(s + col, "Running");
3901 col += sizeof("Running") - 1;
3903 int status = psend[-1].status;
3904 if (jp->state == JOBSTOPPED)
3905 status = jp->stopstatus;
3906 col += sprint_status(s + col, status, 0);
3912 /* for each process */
3913 col = fmtstr(s, 48, " |\n%*c%d ", indent_col, ' ', ps->pid) - 3;
3915 fprintf(out, "%s%*c%s",
3916 s, 33 - col >= 0 ? 33 - col : 0, ' ', ps->cmd
3918 if (!(mode & SHOW_PID)) {
3922 if (++ps == psend) {
3923 outcslow('\n', out);
3930 if (jp->state == JOBDONE) {
3931 TRACE(("showjob: freeing job %d\n", jobno(jp)));
3937 * Print a list of jobs. If "change" is nonzero, only print jobs whose
3938 * statuses have changed since the last call to showjobs.
3941 showjobs(FILE *out, int mode)
3945 TRACE(("showjobs(%x) called\n", mode));
3947 /* If not even one job changed, there is nothing to do */
3948 while (dowait(DOWAIT_NONBLOCK, NULL) > 0)
3951 for (jp = curjob; jp; jp = jp->prev_job) {
3952 if (!(mode & SHOW_CHANGED) || jp->changed) {
3953 showjob(out, jp, mode);
3959 jobscmd(int argc ATTRIBUTE_UNUSED, char **argv)
3964 while ((m = nextopt("lp"))) {
3974 showjob(stdout, getjob(*argv,0), mode);
3977 showjobs(stdout, mode);
3984 getstatus(struct job *job)
3989 status = job->ps[job->nprocs - 1].status;
3990 retval = WEXITSTATUS(status);
3991 if (!WIFEXITED(status)) {
3993 retval = WSTOPSIG(status);
3994 if (!WIFSTOPPED(status))
3997 /* XXX: limits number of signals */
3998 retval = WTERMSIG(status);
4000 if (retval == SIGINT)
4006 TRACE(("getstatus: job %d, nproc %d, status %x, retval %x\n",
4007 jobno(job), job->nprocs, status, retval));
4012 waitcmd(int argc ATTRIBUTE_UNUSED, char **argv)
4021 raise_exception(EXSIG);
4028 /* wait for all jobs */
4032 if (!jp) /* no running procs */
4034 if (jp->state == JOBRUNNING)
4039 dowait(DOWAIT_BLOCK, NULL);
4045 if (**argv != '%') {
4046 pid_t pid = number(*argv);
4051 if (job->ps[job->nprocs - 1].pid == pid)
4053 job = job->prev_job;
4056 job = getjob(*argv, 0);
4057 /* loop until process terminated or stopped */
4058 while (job->state == JOBRUNNING)
4059 dowait(DOWAIT_BLOCK, NULL);
4061 retval = getstatus(job);
4075 struct job *jp, *jq;
4077 len = njobs * sizeof(*jp);
4079 jp = ckrealloc(jq, len + 4 * sizeof(*jp));
4081 offset = (char *)jp - (char *)jq;
4083 /* Relocate pointers */
4086 jq = (struct job *)((char *)jq + l);
4090 #define joff(p) ((struct job *)((char *)(p) + l))
4091 #define jmove(p) (p) = (void *)((char *)(p) + offset)
4092 if (joff(jp)->ps == &jq->ps0)
4093 jmove(joff(jp)->ps);
4094 if (joff(jp)->prev_job)
4095 jmove(joff(jp)->prev_job);
4105 jp = (struct job *)((char *)jp + len);
4109 } while (--jq >= jp);
4114 * Return a new job structure.
4115 * Called with interrupts off.
4118 makejob(/*union node *node,*/ int nprocs)
4123 for (i = njobs, jp = jobtab; ; jp++) {
4130 if (jp->state != JOBDONE || !jp->waited)
4139 memset(jp, 0, sizeof(*jp));
4141 /* jp->jobctl is a bitfield.
4142 * "jp->jobctl |= jobctl" likely to give awful code */
4146 jp->prev_job = curjob;
4151 jp->ps = ckmalloc(nprocs * sizeof(struct procstat));
4153 TRACE(("makejob(%d) returns %%%d\n", nprocs,
4160 * Return a string identifying a command (to be printed by the
4163 static char *cmdnextc;
4166 cmdputs(const char *s)
4168 static const char vstype[VSTYPE + 1][3] = {
4169 "", "}", "-", "+", "?", "=",
4170 "%", "%%", "#", "##"
4171 USE_ASH_BASH_COMPAT(, ":", "/", "//")
4174 const char *p, *str;
4175 char c, cc[2] = " ";
4180 nextc = makestrspace((strlen(s) + 1) * 8, cmdnextc);
4182 while ((c = *p++) != 0) {
4190 if ((subtype & VSTYPE) == VSLENGTH)
4194 if (!(subtype & VSQUOTE) == !(quoted & 1))
4200 str = "\"}" + !(quoted & 1);
4207 case CTLBACKQ+CTLQUOTE:
4210 #if ENABLE_ASH_MATH_SUPPORT
4225 if ((subtype & VSTYPE) != VSNORMAL)
4227 str = vstype[subtype & VSTYPE];
4228 if (subtype & VSNUL)
4237 /* These can only happen inside quotes */
4250 while ((c = *str++)) {
4255 USTPUTC('"', nextc);
4261 /* cmdtxt() and cmdlist() call each other */
4262 static void cmdtxt(union node *n);
4265 cmdlist(union node *np, int sep)
4267 for (; np; np = np->narg.next) {
4271 if (sep && np->narg.next)
4277 cmdtxt(union node *n)
4280 struct nodelist *lp;
4292 lp = n->npipe.cmdlist;
4310 cmdtxt(n->nbinary.ch1);
4326 cmdtxt(n->nif.test);
4329 if (n->nif.elsepart) {
4332 n = n->nif.elsepart;
4348 cmdtxt(n->nbinary.ch1);
4358 cmdputs(n->nfor.var);
4360 cmdlist(n->nfor.args, 1);
4365 cmdputs(n->narg.text);
4369 cmdlist(n->ncmd.args, 1);
4370 cmdlist(n->ncmd.redirect, 0);
4383 cmdputs(n->ncase.expr->narg.text);
4385 for (np = n->ncase.cases; np; np = np->nclist.next) {
4386 cmdtxt(np->nclist.pattern);
4388 cmdtxt(np->nclist.body);
4414 s[0] = n->nfile.fd + '0';
4418 if (n->type == NTOFD || n->type == NFROMFD) {
4419 s[0] = n->ndup.dupfd + '0';
4429 commandtext(union node *n)
4433 STARTSTACKSTR(cmdnextc);
4435 name = stackblock();
4436 TRACE(("commandtext: name %p, end %p\n\t\"%s\"\n",
4437 name, cmdnextc, cmdnextc));
4438 return ckstrdup(name);
4443 * Fork off a subshell. If we are doing job control, give the subshell its
4444 * own process group. Jp is a job structure that the job is to be added to.
4445 * N is the command that will be evaluated by the child. Both jp and n may
4446 * be NULL. The mode parameter can be one of the following:
4447 * FORK_FG - Fork off a foreground process.
4448 * FORK_BG - Fork off a background process.
4449 * FORK_NOJOB - Like FORK_FG, but don't give the process its own
4450 * process group even if job control is on.
4452 * When job control is turned off, background processes have their standard
4453 * input redirected to /dev/null (except for the second and later processes
4456 * Called with interrupts off.
4459 * Clear traps on a fork.
4466 for (tp = trap; tp < &trap[NSIG]; tp++) {
4467 if (*tp && **tp) { /* trap not NULL or "" (SIG_IGN) */
4472 setsignal(tp - trap);
4478 /* Lives far away from here, needed for forkchild */
4479 static void closescript(void);
4481 /* Called after fork(), in child */
4483 forkchild(struct job *jp, /*union node *n,*/ int mode)
4487 TRACE(("Child shell %d\n", getpid()));
4494 /* do job control only in root shell */
4496 if (mode != FORK_NOJOB && jp->jobctl && !oldlvl) {
4499 if (jp->nprocs == 0)
4502 pgrp = jp->ps[0].pid;
4503 /* This can fail because we are doing it in the parent also */
4504 (void)setpgid(0, pgrp);
4505 if (mode == FORK_FG)
4506 xtcsetpgrp(ttyfd, pgrp);
4511 if (mode == FORK_BG) {
4514 if (jp->nprocs == 0) {
4516 if (open(bb_dev_null, O_RDONLY) != 0)
4517 ash_msg_and_raise_error("can't open %s", bb_dev_null);
4520 if (!oldlvl && iflag) {
4525 for (jp = curjob; jp; jp = jp->prev_job)
4530 /* Called after fork(), in parent */
4532 #define forkparent(jp, n, mode, pid) forkparent(jp, mode, pid)
4535 forkparent(struct job *jp, union node *n, int mode, pid_t pid)
4537 TRACE(("In parent shell: child = %d\n", pid));
4539 while (jobless && dowait(DOWAIT_NONBLOCK, NULL) > 0)
4545 if (mode != FORK_NOJOB && jp->jobctl) {
4548 if (jp->nprocs == 0)
4551 pgrp = jp->ps[0].pid;
4552 /* This can fail because we are doing it in the child also */
4556 if (mode == FORK_BG) {
4557 backgndpid = pid; /* set $! */
4558 set_curjob(jp, CUR_RUNNING);
4561 struct procstat *ps = &jp->ps[jp->nprocs++];
4566 if (doing_jobctl && n)
4567 ps->cmd = commandtext(n);
4573 forkshell(struct job *jp, union node *n, int mode)
4577 TRACE(("forkshell(%%%d, %p, %d) called\n", jobno(jp), n, mode));
4580 TRACE(("Fork failed, errno=%d", errno));
4583 ash_msg_and_raise_error("cannot fork");
4586 forkchild(jp, /*n,*/ mode);
4588 forkparent(jp, n, mode, pid);
4593 * Wait for job to finish.
4595 * Under job control we have the problem that while a child process is
4596 * running interrupts generated by the user are sent to the child but not
4597 * to the shell. This means that an infinite loop started by an inter-
4598 * active user may be hard to kill. With job control turned off, an
4599 * interactive user may place an interactive program inside a loop. If
4600 * the interactive program catches interrupts, the user doesn't want
4601 * these interrupts to also abort the loop. The approach we take here
4602 * is to have the shell ignore interrupt signals while waiting for a
4603 * foreground process to terminate, and then send itself an interrupt
4604 * signal if the child process was terminated by an interrupt signal.
4605 * Unfortunately, some programs want to do a bit of cleanup and then
4606 * exit on interrupt; unless these processes terminate themselves by
4607 * sending a signal to themselves (instead of calling exit) they will
4608 * confuse this approach.
4610 * Called with interrupts off.
4613 waitforjob(struct job *jp)
4617 TRACE(("waitforjob(%%%d) called\n", jobno(jp)));
4618 while (jp->state == JOBRUNNING) {
4619 dowait(DOWAIT_BLOCK, jp);
4624 xtcsetpgrp(ttyfd, rootpid);
4626 * This is truly gross.
4627 * If we're doing job control, then we did a TIOCSPGRP which
4628 * caused us (the shell) to no longer be in the controlling
4629 * session -- so we wouldn't have seen any ^C/SIGINT. So, we
4630 * intuit from the subprocess exit status whether a SIGINT
4631 * occurred, and if so interrupt ourselves. Yuck. - mycroft
4633 if (jp->sigint) /* TODO: do the same with all signals */
4634 raise(SIGINT); /* ... by raise(jp->sig) instead? */
4636 if (jp->state == JOBDONE)
4643 * return 1 if there are stopped jobs, otherwise 0
4655 if (jp && jp->state == JOBSTOPPED) {
4656 out2str("You have stopped jobs.\n");
4665 /* ============ redir.c
4667 * Code for dealing with input/output redirection.
4670 #define EMPTY -2 /* marks an unused slot in redirtab */
4671 #define CLOSED -3 /* marks a slot of previously-closed fd */
4673 # define PIPESIZE 4096 /* amount of buffering in a pipe */
4675 # define PIPESIZE PIPE_BUF
4679 * Open a file in noclobber mode.
4680 * The code was copied from bash.
4683 noclobberopen(const char *fname)
4686 struct stat finfo, finfo2;
4689 * If the file exists and is a regular file, return an error
4692 r = stat(fname, &finfo);
4693 if (r == 0 && S_ISREG(finfo.st_mode)) {
4699 * If the file was not present (r != 0), make sure we open it
4700 * exclusively so that if it is created before we open it, our open
4701 * will fail. Make sure that we do not truncate an existing file.
4702 * Note that we don't turn on O_EXCL unless the stat failed -- if the
4703 * file was not a regular file, we leave O_EXCL off.
4706 return open(fname, O_WRONLY|O_CREAT|O_EXCL, 0666);
4707 fd = open(fname, O_WRONLY|O_CREAT, 0666);
4709 /* If the open failed, return the file descriptor right away. */
4714 * OK, the open succeeded, but the file may have been changed from a
4715 * non-regular file to a regular file between the stat and the open.
4716 * We are assuming that the O_EXCL open handles the case where FILENAME
4717 * did not exist and is symlinked to an existing file between the stat
4722 * If we can open it and fstat the file descriptor, and neither check
4723 * revealed that it was a regular file, and the file has not been
4724 * replaced, return the file descriptor.
4726 if (fstat(fd, &finfo2) == 0 && !S_ISREG(finfo2.st_mode)
4727 && finfo.st_dev == finfo2.st_dev && finfo.st_ino == finfo2.st_ino)
4730 /* The file has been replaced. badness. */
4737 * Handle here documents. Normally we fork off a process to write the
4738 * data to a pipe. If the document is short, we can stuff the data in
4739 * the pipe without forking.
4741 /* openhere needs this forward reference */
4742 static void expandhere(union node *arg, int fd);
4744 openhere(union node *redir)
4750 ash_msg_and_raise_error("pipe call failed");
4751 if (redir->type == NHERE) {
4752 len = strlen(redir->nhere.doc->narg.text);
4753 if (len <= PIPESIZE) {
4754 full_write(pip[1], redir->nhere.doc->narg.text, len);
4758 if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) {
4760 signal(SIGINT, SIG_IGN);
4761 signal(SIGQUIT, SIG_IGN);
4762 signal(SIGHUP, SIG_IGN);
4764 signal(SIGTSTP, SIG_IGN);
4766 signal(SIGPIPE, SIG_DFL);
4767 if (redir->type == NHERE)
4768 full_write(pip[1], redir->nhere.doc->narg.text, len);
4770 expandhere(redir->nhere.doc, pip[1]);
4771 _exit(EXIT_SUCCESS);
4779 openredirect(union node *redir)
4784 switch (redir->nfile.type) {
4786 fname = redir->nfile.expfname;
4787 f = open(fname, O_RDONLY);
4792 fname = redir->nfile.expfname;
4793 f = open(fname, O_RDWR|O_CREAT|O_TRUNC, 0666);
4798 /* Take care of noclobber mode. */
4800 fname = redir->nfile.expfname;
4801 f = noclobberopen(fname);
4808 fname = redir->nfile.expfname;
4809 f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666);
4814 fname = redir->nfile.expfname;
4815 f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666);
4823 /* Fall through to eliminate warning. */
4830 f = openhere(redir);
4836 ash_msg_and_raise_error("cannot create %s: %s", fname, errmsg(errno, "nonexistent directory"));
4838 ash_msg_and_raise_error("cannot open %s: %s", fname, errmsg(errno, "no such file"));
4842 * Copy a file descriptor to be >= to. Returns -1
4843 * if the source file descriptor is closed, EMPTY if there are no unused
4844 * file descriptors left.
4847 copyfd(int from, int to)
4851 newfd = fcntl(from, F_DUPFD, to);
4853 if (errno == EMFILE)
4855 ash_msg_and_raise_error("%d: %m", from);
4861 dupredirect(union node *redir, int f)
4863 int fd = redir->nfile.fd;
4865 if (redir->nfile.type == NTOFD || redir->nfile.type == NFROMFD) {
4866 if (redir->ndup.dupfd >= 0) { /* if not ">&-" */
4867 copyfd(redir->ndup.dupfd, fd);
4879 * Process a list of redirection commands. If the REDIR_PUSH flag is set,
4880 * old file descriptors are stashed away so that the redirection can be
4881 * undone by calling popredir. If the REDIR_BACKQ flag is set, then the
4882 * standard output, and the standard error if it becomes a duplicate of
4883 * stdout, is saved in memory.
4885 /* flags passed to redirect */
4886 #define REDIR_PUSH 01 /* save previous values of file descriptors */
4887 #define REDIR_SAVEFD2 03 /* set preverrout */
4889 redirect(union node *redir, int flags)
4892 struct redirtab *sv;
4903 if (flags & REDIR_PUSH) {
4904 sv = ckmalloc(sizeof(*sv));
4905 sv->next = redirlist;
4907 sv->nullredirs = g_nullredirs - 1;
4908 for (i = 0; i < 10; i++)
4909 sv->renamed[i] = EMPTY;
4915 if ((n->nfile.type == NTOFD || n->nfile.type == NFROMFD)
4916 && n->ndup.dupfd == fd)
4917 continue; /* redirect from/to same file descriptor */
4919 newfd = openredirect(n);
4921 /* Descriptor wasn't open before redirect.
4922 * Mark it for close in the future */
4923 if (sv && sv->renamed[fd] == EMPTY)
4924 sv->renamed[fd] = CLOSED;
4927 if (sv && sv->renamed[fd] == EMPTY) {
4928 i = fcntl(fd, F_DUPFD, 10);
4935 ash_msg_and_raise_error("%d: %m", fd);
4939 sv->renamed[fd] = i;
4945 dupredirect(n, newfd);
4946 } while ((n = n->nfile.next));
4948 if ((flags & REDIR_SAVEFD2) && sv && sv->renamed[2] >= 0)
4949 preverrout_fd = sv->renamed[2];
4953 * Undo the effects of the last redirection.
4958 struct redirtab *rp;
4961 if (--g_nullredirs >= 0)
4965 for (i = 0; i < 10; i++) {
4966 if (rp->renamed[i] == CLOSED) {
4971 if (rp->renamed[i] != EMPTY) {
4974 copyfd(rp->renamed[i], i);
4976 close(rp->renamed[i]);
4979 redirlist = rp->next;
4980 g_nullredirs = rp->nullredirs;
4986 * Undo all redirections. Called on error or interrupt.
4990 * Discard all saved file descriptors.
4993 clearredir(int drop)
5004 redirectsafe(union node *redir, int flags)
5007 volatile int saveint;
5008 struct jmploc *volatile savehandler = exception_handler;
5009 struct jmploc jmploc;
5012 err = setjmp(jmploc.loc) * 2;
5014 exception_handler = &jmploc;
5015 redirect(redir, flags);
5017 exception_handler = savehandler;
5018 if (err && exception != EXERROR)
5019 longjmp(exception_handler->loc, 1);
5020 RESTORE_INT(saveint);
5025 /* ============ Routines to expand arguments to commands
5027 * We have to deal with backquotes, shell variables, and file metacharacters.
5030 #if ENABLE_ASH_MATH_SUPPORT_64
5031 typedef int64_t arith_t;
5032 #define arith_t_type long long
5034 typedef long arith_t;
5035 #define arith_t_type long
5038 #if ENABLE_ASH_MATH_SUPPORT
5039 static arith_t dash_arith(const char *);
5040 static arith_t arith(const char *expr, int *perrcode);
5046 #define EXP_FULL 0x1 /* perform word splitting & file globbing */
5047 #define EXP_TILDE 0x2 /* do normal tilde expansion */
5048 #define EXP_VARTILDE 0x4 /* expand tildes in an assignment */
5049 #define EXP_REDIR 0x8 /* file glob for a redirection (1 match only) */
5050 #define EXP_CASE 0x10 /* keeps quotes around for CASE pattern */
5051 #define EXP_RECORD 0x20 /* need to record arguments for ifs breakup */
5052 #define EXP_VARTILDE2 0x40 /* expand tildes after colons only */
5053 #define EXP_WORD 0x80 /* expand word in parameter expansion */
5054 #define EXP_QWORD 0x100 /* expand word in quoted parameter expansion */
5058 #define RMESCAPE_ALLOC 0x1 /* Allocate a new string */
5059 #define RMESCAPE_GLOB 0x2 /* Add backslashes for glob */
5060 #define RMESCAPE_QUOTED 0x4 /* Remove CTLESC unless in quotes */
5061 #define RMESCAPE_GROW 0x8 /* Grow strings instead of stalloc */
5062 #define RMESCAPE_HEAP 0x10 /* Malloc strings instead of stalloc */
5065 * Structure specifying which parts of the string should be searched
5066 * for IFS characters.
5069 struct ifsregion *next; /* next region in list */
5070 int begoff; /* offset of start of region */
5071 int endoff; /* offset of end of region */
5072 int nulonly; /* search for nul bytes only */
5076 struct strlist *list;
5077 struct strlist **lastp;
5080 /* output of current string */
5081 static char *expdest;
5082 /* list of back quote expressions */
5083 static struct nodelist *argbackq;
5084 /* first struct in list of ifs regions */
5085 static struct ifsregion ifsfirst;
5086 /* last struct in list */
5087 static struct ifsregion *ifslastp;
5088 /* holds expanded arg list */
5089 static struct arglist exparg;
5099 expdest = makestrspace(32, expdest);
5100 #if ENABLE_ASH_MATH_SUPPORT_64
5101 len = fmtstr(expdest, 32, "%lld", (long long) num);
5103 len = fmtstr(expdest, 32, "%ld", num);
5105 STADJUST(len, expdest);
5110 esclen(const char *start, const char *p)
5114 while (p > start && *--p == CTLESC) {
5121 * Remove any CTLESC characters from a string.
5124 _rmescapes(char *str, int flag)
5126 static const char qchars[] ALIGN1 = { CTLESC, CTLQUOTEMARK, '\0' };
5133 p = strpbrk(str, qchars);
5139 if (flag & RMESCAPE_ALLOC) {
5140 size_t len = p - str;
5141 size_t fulllen = len + strlen(p) + 1;
5143 if (flag & RMESCAPE_GROW) {
5144 r = makestrspace(fulllen, expdest);
5145 } else if (flag & RMESCAPE_HEAP) {
5146 r = ckmalloc(fulllen);
5148 r = stalloc(fulllen);
5152 q = (char *)memcpy(q, str, len) + len;
5155 inquotes = (flag & RMESCAPE_QUOTED) ^ RMESCAPE_QUOTED;
5156 globbing = flag & RMESCAPE_GLOB;
5157 notescaped = globbing;
5159 if (*p == CTLQUOTEMARK) {
5160 inquotes = ~inquotes;
5162 notescaped = globbing;
5166 /* naked back slash */
5172 if (notescaped && inquotes && *p != '/') {
5176 notescaped = globbing;
5181 if (flag & RMESCAPE_GROW) {
5183 STADJUST(q - r + 1, expdest);
5187 #define rmescapes(p) _rmescapes((p), 0)
5189 #define pmatch(a, b) !fnmatch((a), (b), 0)
5192 * Prepare a pattern for a expmeta (internal glob(3)) call.
5194 * Returns an stalloced string.
5197 preglob(const char *pattern, int quoted, int flag)
5199 flag |= RMESCAPE_GLOB;
5201 flag |= RMESCAPE_QUOTED;
5203 return _rmescapes((char *)pattern, flag);
5207 * Put a string on the stack.
5210 memtodest(const char *p, size_t len, int syntax, int quotes)
5214 q = makestrspace(len * 2, q);
5217 int c = signed_char2int(*p++);
5220 if (quotes && (SIT(c, syntax) == CCTL || SIT(c, syntax) == CBACK))
5229 strtodest(const char *p, int syntax, int quotes)
5231 memtodest(p, strlen(p), syntax, quotes);
5235 * Record the fact that we have to scan this region of the
5236 * string for IFS characters.
5239 recordregion(int start, int end, int nulonly)
5241 struct ifsregion *ifsp;
5243 if (ifslastp == NULL) {
5247 ifsp = ckzalloc(sizeof(*ifsp));
5248 /*ifsp->next = NULL; - ckzalloc did it */
5249 ifslastp->next = ifsp;
5253 ifslastp->begoff = start;
5254 ifslastp->endoff = end;
5255 ifslastp->nulonly = nulonly;
5259 removerecordregions(int endoff)
5261 if (ifslastp == NULL)
5264 if (ifsfirst.endoff > endoff) {
5265 while (ifsfirst.next != NULL) {
5266 struct ifsregion *ifsp;
5268 ifsp = ifsfirst.next->next;
5269 free(ifsfirst.next);
5270 ifsfirst.next = ifsp;
5273 if (ifsfirst.begoff > endoff)
5276 ifslastp = &ifsfirst;
5277 ifsfirst.endoff = endoff;
5282 ifslastp = &ifsfirst;
5283 while (ifslastp->next && ifslastp->next->begoff < endoff)
5284 ifslastp=ifslastp->next;
5285 while (ifslastp->next != NULL) {
5286 struct ifsregion *ifsp;
5288 ifsp = ifslastp->next->next;
5289 free(ifslastp->next);
5290 ifslastp->next = ifsp;
5293 if (ifslastp->endoff > endoff)
5294 ifslastp->endoff = endoff;
5298 exptilde(char *startp, char *p, int flag)
5304 int quotes = flag & (EXP_FULL | EXP_CASE);
5309 while ((c = *++p) != '\0') {
5316 if (flag & EXP_VARTILDE)
5326 if (*name == '\0') {
5327 home = lookupvar(homestr);
5329 pw = getpwnam(name);
5334 if (!home || !*home)
5337 startloc = expdest - (char *)stackblock();
5338 strtodest(home, SQSYNTAX, quotes);
5339 recordregion(startloc, expdest - (char *)stackblock(), 0);
5347 * Execute a command inside back quotes. If it's a builtin command, we
5348 * want to save its output in a block obtained from malloc. Otherwise
5349 * we fork off a subprocess and get the output of the command via a pipe.
5350 * Should be called with interrupts off.
5352 struct backcmd { /* result of evalbackcmd */
5353 int fd; /* file descriptor to read from */
5354 int nleft; /* number of chars in buffer */
5355 char *buf; /* buffer */
5356 struct job *jp; /* job structure for command */
5359 /* These forward decls are needed to use "eval" code for backticks handling: */
5360 static uint8_t back_exitstatus; /* exit status of backquoted command */
5361 #define EV_EXIT 01 /* exit after evaluating tree */
5362 static void evaltree(union node *, int);
5365 evalbackcmd(union node *n, struct backcmd *result)
5377 saveherefd = herefd;
5385 ash_msg_and_raise_error("pipe call failed");
5386 jp = makejob(/*n,*/ 1);
5387 if (forkshell(jp, n, FORK_NOJOB) == 0) {
5396 evaltree(n, EV_EXIT); /* actually evaltreenr... */
5400 result->fd = pip[0];
5403 herefd = saveherefd;
5405 TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n",
5406 result->fd, result->buf, result->nleft, result->jp));
5410 * Expand stuff in backwards quotes.
5413 expbackq(union node *cmd, int quoted, int quotes)
5421 int syntax = quoted ? DQSYNTAX : BASESYNTAX;
5422 struct stackmark smark;
5425 setstackmark(&smark);
5427 startloc = dest - (char *)stackblock();
5429 evalbackcmd(cmd, &in);
5430 popstackmark(&smark);
5437 memtodest(p, i, syntax, quotes);
5441 i = nonblock_safe_read(in.fd, buf, sizeof(buf));
5442 TRACE(("expbackq: read returns %d\n", i));
5451 back_exitstatus = waitforjob(in.jp);
5455 /* Eat all trailing newlines */
5457 for (; dest > (char *)stackblock() && dest[-1] == '\n';)
5462 recordregion(startloc, dest - (char *)stackblock(), 0);
5463 TRACE(("evalbackq: size=%d: \"%.*s\"\n",
5464 (dest - (char *)stackblock()) - startloc,
5465 (dest - (char *)stackblock()) - startloc,
5466 stackblock() + startloc));
5469 #if ENABLE_ASH_MATH_SUPPORT
5471 * Expand arithmetic expression. Backup to start of expression,
5472 * evaluate, place result in (backed up) result, adjust string position.
5485 * This routine is slightly over-complicated for
5486 * efficiency. Next we scan backwards looking for the
5487 * start of arithmetic.
5489 start = stackblock();
5496 while (*p != CTLARI) {
5500 ash_msg_and_raise_error("missing CTLARI (shouldn't happen)");
5505 esc = esclen(start, p);
5515 removerecordregions(begoff);
5524 len = cvtnum(dash_arith(p + 2));
5527 recordregion(begoff, begoff + len, 0);
5531 /* argstr needs it */
5532 static char *evalvar(char *p, int flag, struct strlist *var_str_list);
5535 * Perform variable and command substitution. If EXP_FULL is set, output CTLESC
5536 * characters to allow for further processing. Otherwise treat
5537 * $@ like $* since no splitting will be performed.
5539 * var_str_list (can be NULL) is a list of "VAR=val" strings which take precedence
5540 * over shell varables. Needed for "A=a B=$A; echo $B" case - we use it
5541 * for correct expansion of "B=$A" word.
5544 argstr(char *p, int flag, struct strlist *var_str_list)
5546 static const char spclchars[] ALIGN1 = {
5554 CTLBACKQ | CTLQUOTE,
5555 #if ENABLE_ASH_MATH_SUPPORT
5560 const char *reject = spclchars;
5562 int quotes = flag & (EXP_FULL | EXP_CASE); /* do CTLESC */
5563 int breakall = flag & EXP_WORD;
5568 if (!(flag & EXP_VARTILDE)) {
5570 } else if (flag & EXP_VARTILDE2) {
5575 if (flag & EXP_TILDE) {
5581 if (*q == CTLESC && (flag & EXP_QWORD))
5584 p = exptilde(p, q, flag);
5587 startloc = expdest - (char *)stackblock();
5589 length += strcspn(p + length, reject);
5591 if (c && (!(c & 0x80)
5592 #if ENABLE_ASH_MATH_SUPPORT
5596 /* c == '=' || c == ':' || c == CTLENDARI */
5601 expdest = stack_nputstr(p, length, expdest);
5602 newloc = expdest - (char *)stackblock();
5603 if (breakall && !inquotes && newloc > startloc) {
5604 recordregion(startloc, newloc, 0);
5615 if (flag & EXP_VARTILDE2) {
5619 flag |= EXP_VARTILDE2;
5624 * sort of a hack - expand tildes in variable
5625 * assignments (after the first '=' and after ':'s).
5634 case CTLENDVAR: /* ??? */
5637 /* "$@" syntax adherence hack */
5640 !memcmp(p, dolatstr, 4) &&
5641 (p[4] == CTLQUOTEMARK || (
5642 p[4] == CTLENDVAR &&
5643 p[5] == CTLQUOTEMARK
5646 p = evalvar(p + 1, flag, /* var_str_list: */ NULL) + 1;
5649 inquotes = !inquotes;
5662 p = evalvar(p, flag, var_str_list);
5666 case CTLBACKQ|CTLQUOTE:
5667 expbackq(argbackq->n, c, quotes);
5668 argbackq = argbackq->next;
5670 #if ENABLE_ASH_MATH_SUPPORT
5683 scanleft(char *startp, char *rmesc, char *rmescend ATTRIBUTE_UNUSED, char *str, int quotes,
5686 // This commented out code was added by James Simmons <jsimmons@infradead.org>
5687 // as part of a larger change when he added support for ${var/a/b}.
5688 // However, it broke # and % operators:
5692 //echo ${var#ab} abcdcd abcdcd
5693 //echo ${var##ab} abcdcd abcdcd
5694 //echo ${var#a*b} abcdcd ababcdcd (!)
5695 //echo ${var##a*b} cdcd cdcd
5696 //echo ${var#?} babcdcd ababcdcd (!)
5697 //echo ${var##?} babcdcd babcdcd
5698 //echo ${var#*} ababcdcd babcdcd (!)
5700 //echo ${var%cd} ababcd ababcd
5701 //echo ${var%%cd} ababcd abab (!)
5702 //echo ${var%c*d} ababcd ababcd
5703 //echo ${var%%c*d} abab ababcdcd (!)
5704 //echo ${var%?} ababcdc ababcdc
5705 //echo ${var%%?} ababcdc ababcdcd (!)
5706 //echo ${var%*} ababcdcd ababcdcd
5709 // Commenting it back out helped. Remove it completely if it really
5712 char *loc, *loc2; //, *full;
5718 int match; // = strlen(str);
5719 const char *s = loc2;
5726 match = pmatch(str, s); // this line was deleted
5728 // // chop off end if its '*'
5729 // full = strrchr(str, '*');
5730 // if (full && full != str)
5733 // // If str starts with '*' replace with s.
5734 // if ((*str == '*') && strlen(s) >= match) {
5735 // full = xstrdup(s);
5736 // strncpy(full+strlen(s)-match+1, str+1, match-1);
5738 // full = xstrndup(str, match);
5739 // match = strncmp(s, full, strlen(full));
5743 if (match) // if (!match)
5745 if (quotes && *loc == CTLESC)
5754 scanright(char *startp, char *rmesc, char *rmescend, char *str, int quotes,
5761 for (loc = str - 1, loc2 = rmescend; loc >= startp; loc2--) {
5764 const char *s = loc2;
5769 match = pmatch(str, s);
5776 esc = esclen(startp, loc);
5787 static void varunset(const char *, const char *, const char *, int) ATTRIBUTE_NORETURN;
5789 varunset(const char *end, const char *var, const char *umsg, int varflags)
5795 msg = "parameter not set";
5797 if (*end == CTLENDVAR) {
5798 if (varflags & VSNUL)
5803 ash_msg_and_raise_error("%.*s: %s%s", end - var - 1, var, msg, tail);
5806 #if ENABLE_ASH_BASH_COMPAT
5808 parse_sub_pattern(char *arg, int inquotes)
5810 char *idx, *repl = NULL;
5819 /* Only the first '/' seen is our separator */
5826 if (!inquotes && c == '\\' && arg[1] == '\\')
5827 arg++; /* skip both \\, not just first one */
5834 #endif /* ENABLE_ASH_BASH_COMPAT */
5837 subevalvar(char *p, char *str, int strloc, int subtype,
5838 int startloc, int varflags, int quotes, struct strlist *var_str_list)
5840 struct nodelist *saveargbackq = argbackq;
5843 char *rmesc, *rmescend;
5844 USE_ASH_BASH_COMPAT(char *repl = NULL;)
5845 USE_ASH_BASH_COMPAT(char null = '\0';)
5846 USE_ASH_BASH_COMPAT(int pos, len, orig_len;)
5847 int saveherefd = herefd;
5848 int amount, workloc, resetloc;
5850 char *(*scan)(char*, char*, char*, char*, int, int);
5853 argstr(p, (subtype != VSASSIGN && subtype != VSQUESTION) ? EXP_CASE : 0,
5855 STPUTC('\0', expdest);
5856 herefd = saveherefd;
5857 argbackq = saveargbackq;
5858 startp = (char *)stackblock() + startloc;
5862 setvar(str, startp, 0);
5863 amount = startp - expdest;
5864 STADJUST(amount, expdest);
5867 #if ENABLE_ASH_BASH_COMPAT
5869 loc = str = stackblock() + strloc;
5870 // TODO: number() instead? It does error checking...
5872 len = str - startp - 1;
5874 /* *loc != '\0', guaranteed by parser */
5878 /* We must adjust the length by the number of escapes we find. */
5879 for (ptr = startp; ptr < (str - 1); ptr++) {
5880 if(*ptr == CTLESC) {
5888 if (*loc++ == ':') {
5889 // TODO: number() instead? It does error checking...
5893 while (*loc && *loc != ':')
5896 // TODO: number() instead? It does error checking...
5899 if (pos >= orig_len) {
5903 if (len > (orig_len - pos))
5904 len = orig_len - pos;
5906 for (str = startp; pos; str++, pos--) {
5907 if (quotes && *str == CTLESC)
5910 for (loc = startp; len; len--) {
5911 if (quotes && *str == CTLESC)
5916 amount = loc - expdest;
5917 STADJUST(amount, expdest);
5922 varunset(p, str, startp, varflags);
5925 resetloc = expdest - (char *)stackblock();
5927 /* We'll comeback here if we grow the stack while handling
5928 * a VSREPLACE or VSREPLACEALL, since our pointers into the
5929 * stack will need rebasing, and we'll need to remove our work
5932 USE_ASH_BASH_COMPAT(restart:)
5934 amount = expdest - ((char *)stackblock() + resetloc);
5935 STADJUST(-amount, expdest);
5936 startp = (char *)stackblock() + startloc;
5939 rmescend = (char *)stackblock() + strloc;
5941 rmesc = _rmescapes(startp, RMESCAPE_ALLOC | RMESCAPE_GROW);
5942 if (rmesc != startp) {
5944 startp = (char *)stackblock() + startloc;
5948 str = (char *)stackblock() + strloc;
5949 preglob(str, varflags & VSQUOTE, 0);
5950 workloc = expdest - (char *)stackblock();
5952 #if ENABLE_ASH_BASH_COMPAT
5953 if (subtype == VSREPLACE || subtype == VSREPLACEALL) {
5954 char *idx, *end, *restart_detect;
5957 repl = parse_sub_pattern(str, varflags & VSQUOTE);
5962 /* If there's no pattern to match, return the expansion unmolested */
5970 loc = scanright(idx, rmesc, rmescend, str, quotes, 1);
5972 /* No match, advance */
5973 restart_detect = stackblock();
5974 STPUTC(*idx, expdest);
5975 if (quotes && *idx == CTLESC) {
5978 STPUTC(*idx, expdest);
5980 if (stackblock() != restart_detect)
5988 if (subtype == VSREPLACEALL) {
5990 if (quotes && *idx == CTLESC)
5998 for (loc = repl; *loc; loc++) {
5999 restart_detect = stackblock();
6000 STPUTC(*loc, expdest);
6001 if (stackblock() != restart_detect)
6006 if (subtype == VSREPLACE) {
6008 restart_detect = stackblock();
6009 STPUTC(*idx, expdest);
6010 if (stackblock() != restart_detect)
6019 /* We've put the replaced text into a buffer at workloc, now
6020 * move it to the right place and adjust the stack.
6022 startp = stackblock() + startloc;
6023 STPUTC('\0', expdest);
6024 memmove(startp, stackblock() + workloc, len);
6025 startp[len++] = '\0';
6026 amount = expdest - ((char *)stackblock() + startloc + len - 1);
6027 STADJUST(-amount, expdest);
6030 #endif /* ENABLE_ASH_BASH_COMPAT */
6032 subtype -= VSTRIMRIGHT;
6034 if (subtype < 0 || subtype > 7)
6037 /* zero = subtype == VSTRIMLEFT || subtype == VSTRIMLEFTMAX */
6038 zero = subtype >> 1;
6039 /* VSTRIMLEFT/VSTRIMRIGHTMAX -> scanleft */
6040 scan = (subtype & 1) ^ zero ? scanleft : scanright;
6042 loc = scan(startp, rmesc, rmescend, str, quotes, zero);
6045 memmove(startp, loc, str - loc);
6046 loc = startp + (str - loc) - 1;
6049 amount = loc - expdest;
6050 STADJUST(amount, expdest);
6056 * Add the value of a specialized variable to the stack string.
6059 varvalue(char *name, int varflags, int flags, struct strlist *var_str_list)
6069 int quoted = varflags & VSQUOTE;
6070 int subtype = varflags & VSTYPE;
6071 int quotes = flags & (EXP_FULL | EXP_CASE);
6073 if (quoted && (flags & EXP_FULL))
6074 sep = 1 << CHAR_BIT;
6076 syntax = quoted ? DQSYNTAX : BASESYNTAX;
6085 num = shellparam.nparam;
6095 p = makestrspace(NOPTS, expdest);
6096 for (i = NOPTS - 1; i >= 0; i--) {
6098 USTPUTC(optletters(i), p);
6109 sep = ifsset() ? signed_char2int(ifsval()[0]) : ' ';
6110 if (quotes && (SIT(sep, syntax) == CCTL || SIT(sep, syntax) == CBACK))
6116 while ((p = *ap++)) {
6119 partlen = strlen(p);
6122 if (!(subtype == VSPLUS || subtype == VSLENGTH))
6123 memtodest(p, partlen, syntax, quotes);
6129 if (subtype == VSPLUS || subtype == VSLENGTH) {
6150 // TODO: number() instead? It does error checking...
6152 if (num < 0 || num > shellparam.nparam)
6154 p = num ? shellparam.p[num - 1] : arg0;
6157 /* NB: name has form "VAR=..." */
6159 /* "A=a B=$A" case: var_str_list is a list of "A=a" strings
6160 * which should be considered before we check variables. */
6162 unsigned name_len = (strchrnul(name, '=') - name) + 1;
6166 str = var_str_list->text;
6167 eq = strchr(str, '=');
6168 if (!eq) /* stop at first non-assignment */
6171 if (name_len == (unsigned)(eq - str)
6172 && strncmp(str, name, name_len) == 0) {
6174 /* goto value; - WRONG! */
6175 /* think "A=1 A=2 B=$A" */
6177 var_str_list = var_str_list->next;
6178 } while (var_str_list);
6182 p = lookupvar(name);
6188 if (!(subtype == VSPLUS || subtype == VSLENGTH))
6189 memtodest(p, len, syntax, quotes);
6193 if (subtype == VSPLUS || subtype == VSLENGTH)
6194 STADJUST(-len, expdest);
6199 * Expand a variable, and return a pointer to the next character in the
6203 evalvar(char *p, int flag, struct strlist *var_str_list)
6215 subtype = varflags & VSTYPE;
6216 quoted = varflags & VSQUOTE;
6218 easy = (!quoted || (*var == '@' && shellparam.nparam));
6219 startloc = expdest - (char *)stackblock();
6220 p = strchr(p, '=') + 1;
6223 varlen = varvalue(var, varflags, flag, var_str_list);
6224 if (varflags & VSNUL)
6227 if (subtype == VSPLUS) {
6228 varlen = -1 - varlen;
6232 if (subtype == VSMINUS) {
6236 p, flag | EXP_TILDE |
6237 (quoted ? EXP_QWORD : EXP_WORD),
6247 if (subtype == VSASSIGN || subtype == VSQUESTION) {
6249 if (subevalvar(p, var, /* strloc: */ 0,
6250 subtype, startloc, varflags,
6256 * Remove any recorded regions beyond
6259 removerecordregions(startloc);
6269 if (varlen < 0 && uflag)
6270 varunset(p, var, 0, 0);
6272 if (subtype == VSLENGTH) {
6273 cvtnum(varlen > 0 ? varlen : 0);
6277 if (subtype == VSNORMAL) {
6288 case VSTRIMRIGHTMAX:
6289 #if ENABLE_ASH_BASH_COMPAT
6302 * Terminate the string and start recording the pattern
6305 STPUTC('\0', expdest);
6306 patloc = expdest - (char *)stackblock();
6307 if (0 == subevalvar(p, /* str: */ NULL, patloc, subtype,
6309 /* quotes: */ flag & (EXP_FULL | EXP_CASE),
6312 int amount = expdest - (
6313 (char *)stackblock() + patloc - 1
6315 STADJUST(-amount, expdest);
6317 /* Remove any recorded regions beyond start of variable */
6318 removerecordregions(startloc);
6320 recordregion(startloc, expdest - (char *)stackblock(), quoted);
6324 if (subtype != VSNORMAL) { /* skip to end of alternative */
6330 else if (c == CTLBACKQ || c == (CTLBACKQ|CTLQUOTE)) {
6332 argbackq = argbackq->next;
6333 } else if (c == CTLVAR) {
6334 if ((*p++ & VSTYPE) != VSNORMAL)
6336 } else if (c == CTLENDVAR) {
6346 * Break the argument string into pieces based upon IFS and add the
6347 * strings to the argument list. The regions of the string to be
6348 * searched for IFS characters have been stored by recordregion.
6351 ifsbreakup(char *string, struct arglist *arglist)
6353 struct ifsregion *ifsp;
6358 const char *ifs, *realifs;
6363 if (ifslastp != NULL) {
6366 realifs = ifsset() ? ifsval() : defifs;
6369 p = string + ifsp->begoff;
6370 nulonly = ifsp->nulonly;
6371 ifs = nulonly ? nullstr : realifs;
6373 while (p < string + ifsp->endoff) {
6377 if (!strchr(ifs, *p)) {
6382 ifsspc = (strchr(defifs, *p) != NULL);
6383 /* Ignore IFS whitespace at start */
6384 if (q == start && ifsspc) {
6390 sp = stzalloc(sizeof(*sp));
6392 *arglist->lastp = sp;
6393 arglist->lastp = &sp->next;
6397 if (p >= string + ifsp->endoff) {
6403 if (strchr(ifs, *p) == NULL) {
6407 if (strchr(defifs, *p) == NULL) {
6422 } while (ifsp != NULL);
6431 sp = stzalloc(sizeof(*sp));
6433 *arglist->lastp = sp;
6434 arglist->lastp = &sp->next;
6440 struct ifsregion *p;
6445 struct ifsregion *ifsp;
6451 ifsfirst.next = NULL;
6456 * Add a file name to the list.
6459 addfname(const char *name)
6463 sp = stzalloc(sizeof(*sp));
6464 sp->text = ststrdup(name);
6466 exparg.lastp = &sp->next;
6469 static char *expdir;
6472 * Do metacharacter (i.e. *, ?, [...]) expansion.
6475 expmeta(char *enddir, char *name)
6490 for (p = name; *p; p++) {
6491 if (*p == '*' || *p == '?')
6493 else if (*p == '[') {
6500 if (*q == '/' || *q == '\0')
6507 } else if (*p == '\\')
6509 else if (*p == '/') {
6516 if (metaflag == 0) { /* we've reached the end of the file name */
6517 if (enddir != expdir)
6525 if (metaflag == 0 || lstat(expdir, &statb) >= 0)
6536 } while (p < start);
6538 if (enddir == expdir) {
6540 } else if (enddir == expdir + 1 && *expdir == '/') {
6549 if (enddir != expdir)
6551 if (*endname == 0) {
6563 while (!intpending && (dp = readdir(dirp)) != NULL) {
6564 if (dp->d_name[0] == '.' && ! matchdot)
6566 if (pmatch(start, dp->d_name)) {
6568 strcpy(enddir, dp->d_name);
6571 for (p = enddir, cp = dp->d_name; (*p++ = *cp++) != '\0';)
6574 expmeta(p, endname);
6583 static struct strlist *
6584 msort(struct strlist *list, int len)
6586 struct strlist *p, *q = NULL;
6587 struct strlist **lpp;
6595 for (n = half; --n >= 0;) {
6599 q->next = NULL; /* terminate first half of list */
6600 q = msort(list, half); /* sort first half of list */
6601 p = msort(p, len - half); /* sort second half */
6604 #if ENABLE_LOCALE_SUPPORT
6605 if (strcoll(p->text, q->text) < 0)
6607 if (strcmp(p->text, q->text) < 0)
6631 * Sort the results of file name expansion. It calculates the number of
6632 * strings to sort and then calls msort (short for merge sort) to do the
6635 static struct strlist *
6636 expsort(struct strlist *str)
6642 for (sp = str; sp; sp = sp->next)
6644 return msort(str, len);
6648 expandmeta(struct strlist *str /*, int flag*/)
6650 static const char metachars[] ALIGN1 = {
6653 /* TODO - EXP_REDIR */
6656 struct strlist **savelastp;
6662 if (!strpbrk(str->text, metachars))
6664 savelastp = exparg.lastp;
6667 p = preglob(str->text, 0, RMESCAPE_ALLOC | RMESCAPE_HEAP);
6669 int i = strlen(str->text);
6670 expdir = ckmalloc(i < 2048 ? 2048 : i); /* XXX */
6678 if (exparg.lastp == savelastp) {
6683 *exparg.lastp = str;
6684 rmescapes(str->text);
6685 exparg.lastp = &str->next;
6687 *exparg.lastp = NULL;
6688 *savelastp = sp = expsort(*savelastp);
6689 while (sp->next != NULL)
6691 exparg.lastp = &sp->next;
6698 * Perform variable substitution and command substitution on an argument,
6699 * placing the resulting list of arguments in arglist. If EXP_FULL is true,
6700 * perform splitting and file name expansion. When arglist is NULL, perform
6701 * here document expansion.
6704 expandarg(union node *arg, struct arglist *arglist, int flag)
6709 argbackq = arg->narg.backquote;
6710 STARTSTACKSTR(expdest);
6711 ifsfirst.next = NULL;
6713 argstr(arg->narg.text, flag,
6714 /* var_str_list: */ arglist ? arglist->list : NULL);
6715 p = _STPUTC('\0', expdest);
6717 if (arglist == NULL) {
6718 return; /* here document expanded */
6720 p = grabstackstr(p);
6721 exparg.lastp = &exparg.list;
6725 if (flag & EXP_FULL) {
6726 ifsbreakup(p, &exparg);
6727 *exparg.lastp = NULL;
6728 exparg.lastp = &exparg.list;
6729 expandmeta(exparg.list /*, flag*/);
6731 if (flag & EXP_REDIR) /*XXX - for now, just remove escapes */
6733 sp = stzalloc(sizeof(*sp));
6736 exparg.lastp = &sp->next;
6740 *exparg.lastp = NULL;
6742 *arglist->lastp = exparg.list;
6743 arglist->lastp = exparg.lastp;
6748 * Expand shell variables and backquotes inside a here document.
6751 expandhere(union node *arg, int fd)
6754 expandarg(arg, (struct arglist *)NULL, 0);
6755 full_write(fd, stackblock(), expdest - (char *)stackblock());
6759 * Returns true if the pattern matches the string.
6762 patmatch(char *pattern, const char *string)
6764 return pmatch(preglob(pattern, 0, 0), string);
6768 * See if a pattern matches in a case statement.
6771 casematch(union node *pattern, char *val)
6773 struct stackmark smark;
6776 setstackmark(&smark);
6777 argbackq = pattern->narg.backquote;
6778 STARTSTACKSTR(expdest);
6780 argstr(pattern->narg.text, EXP_TILDE | EXP_CASE,
6781 /* var_str_list: */ NULL);
6782 STACKSTRNUL(expdest);
6783 result = patmatch(stackblock(), val);
6784 popstackmark(&smark);
6789 /* ============ find_command */
6793 int (*builtin)(int, char **);
6794 /* unsigned flags; */
6796 #define IS_BUILTIN_SPECIAL(b) ((b)->name[0] & 1)
6797 /* "regular" builtins always take precedence over commands,
6798 * regardless of PATH=....%builtin... position */
6799 #define IS_BUILTIN_REGULAR(b) ((b)->name[0] & 2)
6800 #define IS_BUILTIN_ASSIGN(b) ((b)->name[0] & 4)
6803 smallint cmdtype; /* CMDxxx */
6806 /* index >= 0 for commands without path (slashes) */
6807 /* (TODO: what exactly does the value mean? PATH position?) */
6808 /* index == -1 for commands with slashes */
6809 /* index == (-2 - applet_no) for NOFORK applets */
6810 const struct builtincmd *cmd;
6811 struct funcnode *func;
6814 /* values of cmdtype */
6815 #define CMDUNKNOWN -1 /* no entry in table for command */
6816 #define CMDNORMAL 0 /* command is an executable program */
6817 #define CMDFUNCTION 1 /* command is a shell function */
6818 #define CMDBUILTIN 2 /* command is a shell builtin */
6820 /* action to find_command() */
6821 #define DO_ERR 0x01 /* prints errors */
6822 #define DO_ABS 0x02 /* checks absolute paths */
6823 #define DO_NOFUNC 0x04 /* don't return shell functions, for command */
6824 #define DO_ALTPATH 0x08 /* using alternate path */
6825 #define DO_ALTBLTIN 0x20 /* %builtin in alt. path */
6827 static void find_command(char *, struct cmdentry *, int, const char *);
6830 /* ============ Hashing commands */
6833 * When commands are first encountered, they are entered in a hash table.
6834 * This ensures that a full path search will not have to be done for them
6835 * on each invocation.
6837 * We should investigate converting to a linear search, even though that
6838 * would make the command name "hash" a misnomer.
6842 struct tblentry *next; /* next entry in hash chain */
6843 union param param; /* definition of builtin function */
6844 smallint cmdtype; /* CMDxxx */
6845 char rehash; /* if set, cd done since entry created */
6846 char cmdname[1]; /* name of command */
6849 static struct tblentry **cmdtable;
6850 #define INIT_G_cmdtable() do { \
6851 cmdtable = xzalloc(CMDTABLESIZE * sizeof(cmdtable[0])); \
6854 static int builtinloc = -1; /* index in path of %builtin, or -1 */
6858 tryexec(USE_FEATURE_SH_STANDALONE(int applet_no,) char *cmd, char **argv, char **envp)
6862 #if ENABLE_FEATURE_SH_STANDALONE
6863 if (applet_no >= 0) {
6864 if (APPLET_IS_NOEXEC(applet_no))
6865 run_applet_no_and_exit(applet_no, argv);
6866 /* re-exec ourselves with the new arguments */
6867 execve(bb_busybox_exec_path, argv, envp);
6868 /* If they called chroot or otherwise made the binary no longer
6869 * executable, fall through */
6876 execve(cmd, argv, envp);
6877 } while (errno == EINTR);
6879 execve(cmd, argv, envp);
6885 if (errno == ENOEXEC) {
6889 for (ap = argv; *ap; ap++)
6891 ap = new = ckmalloc((ap - argv + 2) * sizeof(ap[0]));
6893 ap[0] = cmd = (char *)DEFAULT_SHELL;
6896 while ((*ap++ = *argv++) != NULL)
6905 * Exec a program. Never returns. If you change this routine, you may
6906 * have to change the find_command routine as well.
6908 static void shellexec(char **, const char *, int) ATTRIBUTE_NORETURN;
6910 shellexec(char **argv, const char *path, int idx)
6916 #if ENABLE_FEATURE_SH_STANDALONE
6921 envp = listvars(VEXPORT, VUNSET, 0);
6922 if (strchr(argv[0], '/') != NULL
6923 #if ENABLE_FEATURE_SH_STANDALONE
6924 || (applet_no = find_applet_by_name(argv[0])) >= 0
6927 tryexec(USE_FEATURE_SH_STANDALONE(applet_no,) argv[0], argv, envp);
6931 while ((cmdname = padvance(&path, argv[0])) != NULL) {
6932 if (--idx < 0 && pathopt == NULL) {
6933 tryexec(USE_FEATURE_SH_STANDALONE(-1,) cmdname, argv, envp);
6934 if (errno != ENOENT && errno != ENOTDIR)
6941 /* Map to POSIX errors */
6953 exitstatus = exerrno;
6954 TRACE(("shellexec failed for %s, errno %d, suppressint %d\n",
6955 argv[0], e, suppressint));
6956 ash_msg_and_raise(EXEXEC, "%s: %s", argv[0], errmsg(e, "not found"));
6961 printentry(struct tblentry *cmdp)
6967 idx = cmdp->param.index;
6970 name = padvance(&path, cmdp->cmdname);
6972 } while (--idx >= 0);
6973 out1fmt("%s%s\n", name, (cmdp->rehash ? "*" : nullstr));
6977 * Clear out command entries. The argument specifies the first entry in
6978 * PATH which has changed.
6981 clearcmdentry(int firstchange)
6983 struct tblentry **tblp;
6984 struct tblentry **pp;
6985 struct tblentry *cmdp;
6988 for (tblp = cmdtable; tblp < &cmdtable[CMDTABLESIZE]; tblp++) {
6990 while ((cmdp = *pp) != NULL) {
6991 if ((cmdp->cmdtype == CMDNORMAL &&
6992 cmdp->param.index >= firstchange)
6993 || (cmdp->cmdtype == CMDBUILTIN &&
6994 builtinloc >= firstchange)
7007 * Locate a command in the command hash table. If "add" is nonzero,
7008 * add the command to the table if it is not already present. The
7009 * variable "lastcmdentry" is set to point to the address of the link
7010 * pointing to the entry, so that delete_cmd_entry can delete the
7013 * Interrupts must be off if called with add != 0.
7015 static struct tblentry **lastcmdentry;
7017 static struct tblentry *
7018 cmdlookup(const char *name, int add)
7020 unsigned int hashval;
7022 struct tblentry *cmdp;
7023 struct tblentry **pp;
7026 hashval = (unsigned char)*p << 4;
7028 hashval += (unsigned char)*p++;
7030 pp = &cmdtable[hashval % CMDTABLESIZE];
7031 for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
7032 if (strcmp(cmdp->cmdname, name) == 0)
7036 if (add && cmdp == NULL) {
7037 cmdp = *pp = ckzalloc(sizeof(struct tblentry)
7039 /* + 1 - already done because
7040 * tblentry::cmdname is char[1] */);
7041 /*cmdp->next = NULL; - ckzalloc did it */
7042 cmdp->cmdtype = CMDUNKNOWN;
7043 strcpy(cmdp->cmdname, name);
7050 * Delete the command entry returned on the last lookup.
7053 delete_cmd_entry(void)
7055 struct tblentry *cmdp;
7058 cmdp = *lastcmdentry;
7059 *lastcmdentry = cmdp->next;
7060 if (cmdp->cmdtype == CMDFUNCTION)
7061 freefunc(cmdp->param.func);
7067 * Add a new command entry, replacing any existing command entry for
7068 * the same name - except special builtins.
7071 addcmdentry(char *name, struct cmdentry *entry)
7073 struct tblentry *cmdp;
7075 cmdp = cmdlookup(name, 1);
7076 if (cmdp->cmdtype == CMDFUNCTION) {
7077 freefunc(cmdp->param.func);
7079 cmdp->cmdtype = entry->cmdtype;
7080 cmdp->param = entry->u;
7085 hashcmd(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED)
7087 struct tblentry **pp;
7088 struct tblentry *cmdp;
7090 struct cmdentry entry;
7093 if (nextopt("r") != '\0') {
7098 if (*argptr == NULL) {
7099 for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
7100 for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
7101 if (cmdp->cmdtype == CMDNORMAL)
7109 while ((name = *argptr) != NULL) {
7110 cmdp = cmdlookup(name, 0);
7112 && (cmdp->cmdtype == CMDNORMAL
7113 || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0))
7117 find_command(name, &entry, DO_ERR, pathval());
7118 if (entry.cmdtype == CMDUNKNOWN)
7126 * Called when a cd is done. Marks all commands so the next time they
7127 * are executed they will be rehashed.
7132 struct tblentry **pp;
7133 struct tblentry *cmdp;
7135 for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
7136 for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
7137 if (cmdp->cmdtype == CMDNORMAL
7138 || (cmdp->cmdtype == CMDBUILTIN
7139 && !IS_BUILTIN_REGULAR(cmdp->param.cmd)
7149 * Fix command hash table when PATH changed.
7150 * Called before PATH is changed. The argument is the new value of PATH;
7151 * pathval() still returns the old value at this point.
7152 * Called with interrupts off.
7155 changepath(const char *new)
7163 firstchange = 9999; /* assume no change */
7169 if ((*old == '\0' && *new == ':')
7170 || (*old == ':' && *new == '\0'))
7172 old = new; /* ignore subsequent differences */
7176 if (*new == '%' && idx_bltin < 0 && prefix(new + 1, "builtin"))
7182 if (builtinloc < 0 && idx_bltin >= 0)
7183 builtinloc = idx_bltin; /* zap builtins */
7184 if (builtinloc >= 0 && idx_bltin < 0)
7186 clearcmdentry(firstchange);
7187 builtinloc = idx_bltin;
7202 #define TENDBQUOTE 12
7219 typedef smallint token_id_t;
7221 /* first char is indicating which tokens mark the end of a list */
7222 static const char *const tokname_array[] = {
7236 #define KWDOFFSET 13
7237 /* the following are keywords */
7259 static char buf[16];
7262 //if (tok < TSEMI) return tokname_array[tok] + 1;
7263 //sprintf(buf, "\"%s\"", tokname_array[tok] + 1);
7268 sprintf(buf + (tok >= TSEMI), "%s%c",
7269 tokname_array[tok] + 1, (tok >= TSEMI ? '"' : 0));
7273 /* Wrapper around strcmp for qsort/bsearch/... */
7275 pstrcmp(const void *a, const void *b)
7277 return strcmp((char*) a, (*(char**) b) + 1);
7280 static const char *const *
7281 findkwd(const char *s)
7283 return bsearch(s, tokname_array + KWDOFFSET,
7284 ARRAY_SIZE(tokname_array) - KWDOFFSET,
7285 sizeof(tokname_array[0]), pstrcmp);
7289 * Locate and print what a word is...
7292 describe_command(char *command, int describe_command_verbose)
7294 struct cmdentry entry;
7295 struct tblentry *cmdp;
7296 #if ENABLE_ASH_ALIAS
7297 const struct alias *ap;
7299 const char *path = pathval();
7301 if (describe_command_verbose) {
7305 /* First look at the keywords */
7306 if (findkwd(command)) {
7307 out1str(describe_command_verbose ? " is a shell keyword" : command);
7311 #if ENABLE_ASH_ALIAS
7312 /* Then look at the aliases */
7313 ap = lookupalias(command, 0);
7315 if (!describe_command_verbose) {
7320 out1fmt(" is an alias for %s", ap->val);
7324 /* Then check if it is a tracked alias */
7325 cmdp = cmdlookup(command, 0);
7327 entry.cmdtype = cmdp->cmdtype;
7328 entry.u = cmdp->param;
7330 /* Finally use brute force */
7331 find_command(command, &entry, DO_ABS, path);
7334 switch (entry.cmdtype) {
7336 int j = entry.u.index;
7342 p = padvance(&path, command);
7346 if (describe_command_verbose) {
7348 (cmdp ? " a tracked alias for" : nullstr), p
7357 if (describe_command_verbose) {
7358 out1str(" is a shell function");
7365 if (describe_command_verbose) {
7366 out1fmt(" is a %sshell builtin",
7367 IS_BUILTIN_SPECIAL(entry.u.cmd) ?
7368 "special " : nullstr
7376 if (describe_command_verbose) {
7377 out1str(": not found\n");
7382 outstr("\n", stdout);
7387 typecmd(int argc ATTRIBUTE_UNUSED, char **argv)
7393 /* type -p ... ? (we don't bother checking for 'p') */
7394 if (argv[1] && argv[1][0] == '-') {
7399 err |= describe_command(argv[i++], verbose);
7404 #if ENABLE_ASH_CMDCMD
7406 commandcmd(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED)
7414 while ((c = nextopt("pvV")) != '\0')
7416 verify |= VERIFY_VERBOSE;
7418 verify |= VERIFY_BRIEF;
7424 return describe_command(*argptr, verify - VERIFY_BRIEF);
7431 /* ============ eval.c */
7433 static int funcblocksize; /* size of structures in function */
7434 static int funcstringsize; /* size of strings in node */
7435 static void *funcblock; /* block to allocate function from */
7436 static char *funcstring; /* block to allocate strings from */
7438 /* flags in argument to evaltree */
7439 #define EV_EXIT 01 /* exit after evaluating tree */
7440 #define EV_TESTED 02 /* exit status is checked; ignore -e flag */
7441 #define EV_BACKCMD 04 /* command executing within back quotes */
7443 static const short nodesize[26] = {
7444 SHELL_ALIGN(sizeof(struct ncmd)),
7445 SHELL_ALIGN(sizeof(struct npipe)),
7446 SHELL_ALIGN(sizeof(struct nredir)),
7447 SHELL_ALIGN(sizeof(struct nredir)),
7448 SHELL_ALIGN(sizeof(struct nredir)),
7449 SHELL_ALIGN(sizeof(struct nbinary)),
7450 SHELL_ALIGN(sizeof(struct nbinary)),
7451 SHELL_ALIGN(sizeof(struct nbinary)),
7452 SHELL_ALIGN(sizeof(struct nif)),
7453 SHELL_ALIGN(sizeof(struct nbinary)),
7454 SHELL_ALIGN(sizeof(struct nbinary)),
7455 SHELL_ALIGN(sizeof(struct nfor)),
7456 SHELL_ALIGN(sizeof(struct ncase)),
7457 SHELL_ALIGN(sizeof(struct nclist)),
7458 SHELL_ALIGN(sizeof(struct narg)),
7459 SHELL_ALIGN(sizeof(struct narg)),
7460 SHELL_ALIGN(sizeof(struct nfile)),
7461 SHELL_ALIGN(sizeof(struct nfile)),
7462 SHELL_ALIGN(sizeof(struct nfile)),
7463 SHELL_ALIGN(sizeof(struct nfile)),
7464 SHELL_ALIGN(sizeof(struct nfile)),
7465 SHELL_ALIGN(sizeof(struct ndup)),
7466 SHELL_ALIGN(sizeof(struct ndup)),
7467 SHELL_ALIGN(sizeof(struct nhere)),
7468 SHELL_ALIGN(sizeof(struct nhere)),
7469 SHELL_ALIGN(sizeof(struct nnot)),
7472 static void calcsize(union node *n);
7475 sizenodelist(struct nodelist *lp)
7478 funcblocksize += SHELL_ALIGN(sizeof(struct nodelist));
7485 calcsize(union node *n)
7489 funcblocksize += nodesize[n->type];
7492 calcsize(n->ncmd.redirect);
7493 calcsize(n->ncmd.args);
7494 calcsize(n->ncmd.assign);
7497 sizenodelist(n->npipe.cmdlist);
7502 calcsize(n->nredir.redirect);
7503 calcsize(n->nredir.n);
7510 calcsize(n->nbinary.ch2);
7511 calcsize(n->nbinary.ch1);
7514 calcsize(n->nif.elsepart);
7515 calcsize(n->nif.ifpart);
7516 calcsize(n->nif.test);
7519 funcstringsize += strlen(n->nfor.var) + 1;
7520 calcsize(n->nfor.body);
7521 calcsize(n->nfor.args);
7524 calcsize(n->ncase.cases);
7525 calcsize(n->ncase.expr);
7528 calcsize(n->nclist.body);
7529 calcsize(n->nclist.pattern);
7530 calcsize(n->nclist.next);
7534 sizenodelist(n->narg.backquote);
7535 funcstringsize += strlen(n->narg.text) + 1;
7536 calcsize(n->narg.next);
7543 calcsize(n->nfile.fname);
7544 calcsize(n->nfile.next);
7548 calcsize(n->ndup.vname);
7549 calcsize(n->ndup.next);
7553 calcsize(n->nhere.doc);
7554 calcsize(n->nhere.next);
7557 calcsize(n->nnot.com);
7563 nodeckstrdup(char *s)
7565 char *rtn = funcstring;
7567 strcpy(funcstring, s);
7568 funcstring += strlen(s) + 1;
7572 static union node *copynode(union node *);
7574 static struct nodelist *
7575 copynodelist(struct nodelist *lp)
7577 struct nodelist *start;
7578 struct nodelist **lpp;
7583 funcblock = (char *) funcblock + SHELL_ALIGN(sizeof(struct nodelist));
7584 (*lpp)->n = copynode(lp->n);
7586 lpp = &(*lpp)->next;
7593 copynode(union node *n)
7600 funcblock = (char *) funcblock + nodesize[n->type];
7604 new->ncmd.redirect = copynode(n->ncmd.redirect);
7605 new->ncmd.args = copynode(n->ncmd.args);
7606 new->ncmd.assign = copynode(n->ncmd.assign);
7609 new->npipe.cmdlist = copynodelist(n->npipe.cmdlist);
7610 new->npipe.backgnd = n->npipe.backgnd;
7615 new->nredir.redirect = copynode(n->nredir.redirect);
7616 new->nredir.n = copynode(n->nredir.n);
7623 new->nbinary.ch2 = copynode(n->nbinary.ch2);
7624 new->nbinary.ch1 = copynode(n->nbinary.ch1);
7627 new->nif.elsepart = copynode(n->nif.elsepart);
7628 new->nif.ifpart = copynode(n->nif.ifpart);
7629 new->nif.test = copynode(n->nif.test);
7632 new->nfor.var = nodeckstrdup(n->nfor.var);
7633 new->nfor.body = copynode(n->nfor.body);
7634 new->nfor.args = copynode(n->nfor.args);
7637 new->ncase.cases = copynode(n->ncase.cases);
7638 new->ncase.expr = copynode(n->ncase.expr);
7641 new->nclist.body = copynode(n->nclist.body);
7642 new->nclist.pattern = copynode(n->nclist.pattern);
7643 new->nclist.next = copynode(n->nclist.next);
7647 new->narg.backquote = copynodelist(n->narg.backquote);
7648 new->narg.text = nodeckstrdup(n->narg.text);
7649 new->narg.next = copynode(n->narg.next);
7656 new->nfile.fname = copynode(n->nfile.fname);
7657 new->nfile.fd = n->nfile.fd;
7658 new->nfile.next = copynode(n->nfile.next);
7662 new->ndup.vname = copynode(n->ndup.vname);
7663 new->ndup.dupfd = n->ndup.dupfd;
7664 new->ndup.fd = n->ndup.fd;
7665 new->ndup.next = copynode(n->ndup.next);
7669 new->nhere.doc = copynode(n->nhere.doc);
7670 new->nhere.fd = n->nhere.fd;
7671 new->nhere.next = copynode(n->nhere.next);
7674 new->nnot.com = copynode(n->nnot.com);
7677 new->type = n->type;
7682 * Make a copy of a parse tree.
7684 static struct funcnode *
7685 copyfunc(union node *n)
7690 funcblocksize = offsetof(struct funcnode, n);
7693 blocksize = funcblocksize;
7694 f = ckmalloc(blocksize + funcstringsize);
7695 funcblock = (char *) f + offsetof(struct funcnode, n);
7696 funcstring = (char *) f + blocksize;
7703 * Define a shell function.
7706 defun(char *name, union node *func)
7708 struct cmdentry entry;
7711 entry.cmdtype = CMDFUNCTION;
7712 entry.u.func = copyfunc(func);
7713 addcmdentry(name, &entry);
7717 static int evalskip; /* set if we are skipping commands */
7718 /* reasons for skipping commands (see comment on breakcmd routine) */
7719 #define SKIPBREAK (1 << 0)
7720 #define SKIPCONT (1 << 1)
7721 #define SKIPFUNC (1 << 2)
7722 #define SKIPFILE (1 << 3)
7723 #define SKIPEVAL (1 << 4)
7724 static int skipcount; /* number of levels to skip */
7725 static int funcnest; /* depth of function calls */
7726 static int loopnest; /* current loop nesting level */
7728 /* forward decl way out to parsing code - dotrap needs it */
7729 static int evalstring(char *s, int mask);
7732 * Called to execute a trap. Perhaps we should avoid entering new trap
7733 * handlers while we are executing a trap handler.
7744 savestatus = exitstatus;
7748 for (i = 0, q = gotsig; i < NSIG - 1; i++, q++) {
7756 skip = evalstring(p, SKIPEVAL);
7757 exitstatus = savestatus;
7765 /* forward declarations - evaluation is fairly recursive business... */
7766 static void evalloop(union node *, int);
7767 static void evalfor(union node *, int);
7768 static void evalcase(union node *, int);
7769 static void evalsubshell(union node *, int);
7770 static void expredir(union node *);
7771 static void evalpipe(union node *, int);
7772 static void evalcommand(union node *, int);
7773 static int evalbltin(const struct builtincmd *, int, char **);
7774 static void prehash(union node *);
7777 * Evaluate a parse tree. The value is left in the global variable
7781 evaltree(union node *n, int flags)
7784 void (*evalfn)(union node *, int);
7788 TRACE(("evaltree(NULL) called\n"));
7791 TRACE(("pid %d, evaltree(%p: %d, %d) called\n",
7792 getpid(), n, n->type, flags));
7796 out1fmt("Node type = %d\n", n->type);
7801 evaltree(n->nnot.com, EV_TESTED);
7802 status = !exitstatus;
7805 expredir(n->nredir.redirect);
7806 status = redirectsafe(n->nredir.redirect, REDIR_PUSH);
7808 evaltree(n->nredir.n, flags & EV_TESTED);
7809 status = exitstatus;
7814 evalfn = evalcommand;
7816 if (eflag && !(flags & EV_TESTED))
7828 evalfn = evalsubshell;
7840 #error NAND + 1 != NOR
7842 #if NOR + 1 != NSEMI
7843 #error NOR + 1 != NSEMI
7845 isor = n->type - NAND;
7848 (flags | ((isor >> 1) - 1)) & EV_TESTED
7850 if (!exitstatus == isor)
7862 evaltree(n->nif.test, EV_TESTED);
7865 if (exitstatus == 0) {
7868 } else if (n->nif.elsepart) {
7869 n = n->nif.elsepart;
7874 defun(n->narg.text, n->narg.next);
7878 exitstatus = status;
7882 if ((checkexit & exitstatus))
7883 evalskip |= SKIPEVAL;
7884 else if (pendingsig && dotrap())
7887 if (flags & EV_EXIT) {
7889 raise_exception(EXEXIT);
7893 #if !defined(__alpha__) || (defined(__GNUC__) && __GNUC__ >= 3)
7896 void evaltreenr(union node *, int) __attribute__ ((alias("evaltree"),__noreturn__));
7899 evalloop(union node *n, int flags)
7909 evaltree(n->nbinary.ch1, EV_TESTED);
7912 if (evalskip == SKIPCONT && --skipcount <= 0) {
7916 if (evalskip == SKIPBREAK && --skipcount <= 0)
7921 if (n->type != NWHILE)
7925 evaltree(n->nbinary.ch2, flags);
7926 status = exitstatus;
7931 exitstatus = status;
7935 evalfor(union node *n, int flags)
7937 struct arglist arglist;
7940 struct stackmark smark;
7942 setstackmark(&smark);
7943 arglist.list = NULL;
7944 arglist.lastp = &arglist.list;
7945 for (argp = n->nfor.args; argp; argp = argp->narg.next) {
7946 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE | EXP_RECORD);
7951 *arglist.lastp = NULL;
7956 for (sp = arglist.list; sp; sp = sp->next) {
7957 setvar(n->nfor.var, sp->text, 0);
7958 evaltree(n->nfor.body, flags);
7960 if (evalskip == SKIPCONT && --skipcount <= 0) {
7964 if (evalskip == SKIPBREAK && --skipcount <= 0)
7971 popstackmark(&smark);
7975 evalcase(union node *n, int flags)
7979 struct arglist arglist;
7980 struct stackmark smark;
7982 setstackmark(&smark);
7983 arglist.list = NULL;
7984 arglist.lastp = &arglist.list;
7985 expandarg(n->ncase.expr, &arglist, EXP_TILDE);
7987 for (cp = n->ncase.cases; cp && evalskip == 0; cp = cp->nclist.next) {
7988 for (patp = cp->nclist.pattern; patp; patp = patp->narg.next) {
7989 if (casematch(patp, arglist.list->text)) {
7990 if (evalskip == 0) {
7991 evaltree(cp->nclist.body, flags);
7998 popstackmark(&smark);
8002 * Kick off a subshell to evaluate a tree.
8005 evalsubshell(union node *n, int flags)
8008 int backgnd = (n->type == NBACKGND);
8011 expredir(n->nredir.redirect);
8012 if (!backgnd && flags & EV_EXIT && !trap[0])
8015 jp = makejob(/*n,*/ 1);
8016 if (forkshell(jp, n, backgnd) == 0) {
8020 flags &=~ EV_TESTED;
8022 redirect(n->nredir.redirect, 0);
8023 evaltreenr(n->nredir.n, flags);
8028 status = waitforjob(jp);
8029 exitstatus = status;
8034 * Compute the names of the files in a redirection list.
8036 static void fixredir(union node *, const char *, int);
8038 expredir(union node *n)
8042 for (redir = n; redir; redir = redir->nfile.next) {
8046 fn.lastp = &fn.list;
8047 switch (redir->type) {
8053 expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
8054 redir->nfile.expfname = fn.list->text;
8058 if (redir->ndup.vname) {
8059 expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE);
8060 if (fn.list == NULL)
8061 ash_msg_and_raise_error("redir error");
8062 fixredir(redir, fn.list->text, 1);
8070 * Evaluate a pipeline. All the processes in the pipeline are children
8071 * of the process creating the pipeline. (This differs from some versions
8072 * of the shell, which make the last process in a pipeline the parent
8076 evalpipe(union node *n, int flags)
8079 struct nodelist *lp;
8084 TRACE(("evalpipe(0x%lx) called\n", (long)n));
8086 for (lp = n->npipe.cmdlist; lp; lp = lp->next)
8090 jp = makejob(/*n,*/ pipelen);
8092 for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
8096 if (pipe(pip) < 0) {
8098 ash_msg_and_raise_error("pipe call failed");
8101 if (forkshell(jp, lp->n, n->npipe.backgnd) == 0) {
8114 evaltreenr(lp->n, flags);
8122 if (n->npipe.backgnd == 0) {
8123 exitstatus = waitforjob(jp);
8124 TRACE(("evalpipe: job done exit status %d\n", exitstatus));
8130 * Controls whether the shell is interactive or not.
8133 setinteractive(int on)
8135 static smallint is_interactive;
8137 if (++on == is_interactive)
8139 is_interactive = on;
8143 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
8144 if (is_interactive > 1) {
8145 /* Looks like they want an interactive shell */
8146 static smallint did_banner;
8151 "%s built-in shell (ash)\n"
8152 "Enter 'help' for a list of built-in commands."
8167 setinteractive(iflag);
8169 #if ENABLE_FEATURE_EDITING_VI
8171 line_input_state->flags |= VI_MODE;
8173 line_input_state->flags &= ~VI_MODE;
8175 viflag = 0; /* forcibly keep the option off */
8179 static struct localvar *localvars;
8182 * Called after a function returns.
8183 * Interrupts must be off.
8188 struct localvar *lvp;
8191 while ((lvp = localvars) != NULL) {
8192 localvars = lvp->next;
8194 TRACE(("poplocalvar %s", vp ? vp->text : "-"));
8195 if (vp == NULL) { /* $- saved */
8196 memcpy(optlist, lvp->text, sizeof(optlist));
8197 free((char*)lvp->text);
8199 } else if ((lvp->flags & (VUNSET|VSTRFIXED)) == VUNSET) {
8203 (*vp->func)(strchrnul(lvp->text, '=') + 1);
8204 if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
8205 free((char*)vp->text);
8206 vp->flags = lvp->flags;
8207 vp->text = lvp->text;
8214 evalfun(struct funcnode *func, int argc, char **argv, int flags)
8216 volatile struct shparam saveparam;
8217 struct localvar *volatile savelocalvars;
8218 struct jmploc *volatile savehandler;
8219 struct jmploc jmploc;
8222 saveparam = shellparam;
8223 savelocalvars = localvars;
8224 e = setjmp(jmploc.loc);
8229 savehandler = exception_handler;
8230 exception_handler = &jmploc;
8232 shellparam.malloced = 0;
8236 shellparam.nparam = argc - 1;
8237 shellparam.p = argv + 1;
8238 #if ENABLE_ASH_GETOPTS
8239 shellparam.optind = 1;
8240 shellparam.optoff = -1;
8242 evaltree(&func->n, flags & EV_TESTED);
8248 localvars = savelocalvars;
8249 freeparam(&shellparam);
8250 shellparam = saveparam;
8251 exception_handler = savehandler;
8253 evalskip &= ~SKIPFUNC;
8257 #if ENABLE_ASH_CMDCMD
8259 parse_command_args(char **argv, const char **path)
8272 if (c == '-' && !*cp) {
8279 *path = bb_default_path;
8282 /* run 'typecmd' for other options */
8293 * Make a variable a local variable. When a variable is made local, it's
8294 * value and flags are saved in a localvar structure. The saved values
8295 * will be restored when the shell function returns. We handle the name
8296 * "-" as a special case.
8301 struct localvar *lvp;
8306 lvp = ckzalloc(sizeof(struct localvar));
8307 if (LONE_DASH(name)) {
8309 p = ckmalloc(sizeof(optlist));
8310 lvp->text = memcpy(p, optlist, sizeof(optlist));
8315 vpp = hashvar(name);
8316 vp = *findvar(vpp, name);
8317 eq = strchr(name, '=');
8320 setvareq(name, VSTRFIXED);
8322 setvar(name, NULL, VSTRFIXED);
8323 vp = *vpp; /* the new variable */
8324 lvp->flags = VUNSET;
8326 lvp->text = vp->text;
8327 lvp->flags = vp->flags;
8328 vp->flags |= VSTRFIXED|VTEXTFIXED;
8334 lvp->next = localvars;
8340 * The "local" command.
8343 localcmd(int argc ATTRIBUTE_UNUSED, char **argv)
8348 while ((name = *argv++) != NULL) {
8355 falsecmd(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED)
8361 truecmd(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED)
8367 execcmd(int argc ATTRIBUTE_UNUSED, char **argv)
8370 iflag = 0; /* exit on error */
8373 shellexec(argv + 1, pathval(), 0);
8379 * The return command.
8382 returncmd(int argc ATTRIBUTE_UNUSED, char **argv)
8385 * If called outside a function, do what ksh does;
8386 * skip the rest of the file.
8388 evalskip = funcnest ? SKIPFUNC : SKIPFILE;
8389 return argv[1] ? number(argv[1]) : exitstatus;
8392 /* Forward declarations for builtintab[] */
8393 static int breakcmd(int, char **);
8394 static int dotcmd(int, char **);
8395 static int evalcmd(int, char **);
8396 static int exitcmd(int, char **);
8397 static int exportcmd(int, char **);
8398 #if ENABLE_ASH_GETOPTS
8399 static int getoptscmd(int, char **);
8401 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
8402 static int helpcmd(int, char **);
8404 #if ENABLE_ASH_MATH_SUPPORT
8405 static int letcmd(int, char **);
8407 static int readcmd(int, char **);
8408 static int setcmd(int, char **);
8409 static int shiftcmd(int, char **);
8410 static int timescmd(int, char **);
8411 static int trapcmd(int, char **);
8412 static int umaskcmd(int, char **);
8413 static int unsetcmd(int, char **);
8414 static int ulimitcmd(int, char **);
8416 #define BUILTIN_NOSPEC "0"
8417 #define BUILTIN_SPECIAL "1"
8418 #define BUILTIN_REGULAR "2"
8419 #define BUILTIN_SPEC_REG "3"
8420 #define BUILTIN_ASSIGN "4"
8421 #define BUILTIN_SPEC_ASSG "5"
8422 #define BUILTIN_REG_ASSG "6"
8423 #define BUILTIN_SPEC_REG_ASSG "7"
8425 /* We do not handle [[ expr ]] bashism bash-compatibly,
8426 * we make it a synonym of [ expr ].
8427 * Basically, word splitting and pathname expansion should NOT be performed
8429 * no word splitting: a="a b"; [[ $a = "a b" ]]; echo $? should print "0"
8430 * no pathname expansion: [[ /bin/m* = "/bin/m*" ]]; echo $? should print "0"
8431 * Additional operators:
8432 * || and && should work as -o and -a
8434 * Apart from the above, [[ expr ]] should work as [ expr ]
8437 #define echocmd echo_main
8438 #define printfcmd printf_main
8439 #define testcmd test_main
8441 /* Keep these in proper order since it is searched via bsearch() */
8442 static const struct builtincmd builtintab[] = {
8443 { BUILTIN_SPEC_REG ".", dotcmd },
8444 { BUILTIN_SPEC_REG ":", truecmd },
8445 #if ENABLE_ASH_BUILTIN_TEST
8446 { BUILTIN_REGULAR "[", testcmd },
8447 #if ENABLE_ASH_BASH_COMPAT
8448 { BUILTIN_REGULAR "[[", testcmd },
8451 #if ENABLE_ASH_ALIAS
8452 { BUILTIN_REG_ASSG "alias", aliascmd },
8455 { BUILTIN_REGULAR "bg", fg_bgcmd },
8457 { BUILTIN_SPEC_REG "break", breakcmd },
8458 { BUILTIN_REGULAR "cd", cdcmd },
8459 { BUILTIN_NOSPEC "chdir", cdcmd },
8460 #if ENABLE_ASH_CMDCMD
8461 { BUILTIN_REGULAR "command", commandcmd },
8463 { BUILTIN_SPEC_REG "continue", breakcmd },
8464 #if ENABLE_ASH_BUILTIN_ECHO
8465 { BUILTIN_REGULAR "echo", echocmd },
8467 { BUILTIN_SPEC_REG "eval", evalcmd },
8468 { BUILTIN_SPEC_REG "exec", execcmd },
8469 { BUILTIN_SPEC_REG "exit", exitcmd },
8470 { BUILTIN_SPEC_REG_ASSG "export", exportcmd },
8471 { BUILTIN_REGULAR "false", falsecmd },
8473 { BUILTIN_REGULAR "fg", fg_bgcmd },
8475 #if ENABLE_ASH_GETOPTS
8476 { BUILTIN_REGULAR "getopts", getoptscmd },
8478 { BUILTIN_NOSPEC "hash", hashcmd },
8479 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
8480 { BUILTIN_NOSPEC "help", helpcmd },
8483 { BUILTIN_REGULAR "jobs", jobscmd },
8484 { BUILTIN_REGULAR "kill", killcmd },
8486 #if ENABLE_ASH_MATH_SUPPORT
8487 { BUILTIN_NOSPEC "let", letcmd },
8489 { BUILTIN_ASSIGN "local", localcmd },
8490 #if ENABLE_ASH_BUILTIN_PRINTF
8491 { BUILTIN_REGULAR "printf", printfcmd },
8493 { BUILTIN_NOSPEC "pwd", pwdcmd },
8494 { BUILTIN_REGULAR "read", readcmd },
8495 { BUILTIN_SPEC_REG_ASSG "readonly", exportcmd },
8496 { BUILTIN_SPEC_REG "return", returncmd },
8497 { BUILTIN_SPEC_REG "set", setcmd },
8498 { BUILTIN_SPEC_REG "shift", shiftcmd },
8499 { BUILTIN_SPEC_REG "source", dotcmd },
8500 #if ENABLE_ASH_BUILTIN_TEST
8501 { BUILTIN_REGULAR "test", testcmd },
8503 { BUILTIN_SPEC_REG "times", timescmd },
8504 { BUILTIN_SPEC_REG "trap", trapcmd },
8505 { BUILTIN_REGULAR "true", truecmd },
8506 { BUILTIN_NOSPEC "type", typecmd },
8507 { BUILTIN_NOSPEC "ulimit", ulimitcmd },
8508 { BUILTIN_REGULAR "umask", umaskcmd },
8509 #if ENABLE_ASH_ALIAS
8510 { BUILTIN_REGULAR "unalias", unaliascmd },
8512 { BUILTIN_SPEC_REG "unset", unsetcmd },
8513 { BUILTIN_REGULAR "wait", waitcmd },
8516 /* Should match the above table! */
8517 #define COMMANDCMD (builtintab + \
8519 1 * ENABLE_ASH_BUILTIN_TEST + \
8520 1 * ENABLE_ASH_BUILTIN_TEST * ENABLE_ASH_BASH_COMPAT + \
8521 1 * ENABLE_ASH_ALIAS + \
8522 1 * ENABLE_ASH_JOB_CONTROL + \
8524 #define EXECCMD (builtintab + \
8526 1 * ENABLE_ASH_BUILTIN_TEST + \
8527 1 * ENABLE_ASH_BUILTIN_TEST * ENABLE_ASH_BASH_COMPAT + \
8528 1 * ENABLE_ASH_ALIAS + \
8529 1 * ENABLE_ASH_JOB_CONTROL + \
8531 1 * ENABLE_ASH_CMDCMD + \
8533 ENABLE_ASH_BUILTIN_ECHO + \
8537 * Search the table of builtin commands.
8539 static struct builtincmd *
8540 find_builtin(const char *name)
8542 struct builtincmd *bp;
8545 name, builtintab, ARRAY_SIZE(builtintab), sizeof(builtintab[0]),
8552 * Execute a simple command.
8555 isassignment(const char *p)
8557 const char *q = endofname(p);
8563 bltincmd(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED)
8565 /* Preserve exitstatus of a previous possible redirection
8566 * as POSIX mandates */
8567 return back_exitstatus;
8570 evalcommand(union node *cmd, int flags)
8572 static const struct builtincmd null_bltin = {
8573 "\0\0", bltincmd /* why three NULs? */
8575 struct stackmark smark;
8577 struct arglist arglist;
8578 struct arglist varlist;
8581 const struct strlist *sp;
8582 struct cmdentry cmdentry;
8590 struct builtincmd *bcmd;
8591 int pseudovarflag = 0;
8593 /* First expand the arguments. */
8594 TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
8595 setstackmark(&smark);
8596 back_exitstatus = 0;
8598 cmdentry.cmdtype = CMDBUILTIN;
8599 cmdentry.u.cmd = &null_bltin;
8600 varlist.lastp = &varlist.list;
8601 *varlist.lastp = NULL;
8602 arglist.lastp = &arglist.list;
8603 *arglist.lastp = NULL;
8606 if (cmd->ncmd.args) {
8607 bcmd = find_builtin(cmd->ncmd.args->narg.text);
8608 pseudovarflag = bcmd && IS_BUILTIN_ASSIGN(bcmd);
8611 for (argp = cmd->ncmd.args; argp; argp = argp->narg.next) {
8612 struct strlist **spp;
8614 spp = arglist.lastp;
8615 if (pseudovarflag && isassignment(argp->narg.text))
8616 expandarg(argp, &arglist, EXP_VARTILDE);
8618 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
8620 for (sp = *spp; sp; sp = sp->next)
8624 argv = nargv = stalloc(sizeof(char *) * (argc + 1));
8625 for (sp = arglist.list; sp; sp = sp->next) {
8626 TRACE(("evalcommand arg: %s\n", sp->text));
8627 *nargv++ = sp->text;
8632 if (iflag && funcnest == 0 && argc > 0)
8633 lastarg = nargv[-1];
8636 expredir(cmd->ncmd.redirect);
8637 status = redirectsafe(cmd->ncmd.redirect, REDIR_PUSH | REDIR_SAVEFD2);
8640 for (argp = cmd->ncmd.assign; argp; argp = argp->narg.next) {
8641 struct strlist **spp;
8644 spp = varlist.lastp;
8645 expandarg(argp, &varlist, EXP_VARTILDE);
8648 * Modify the command lookup path, if a PATH= assignment
8652 if (varequal(p, path))
8656 /* Print the command if xflag is set. */
8659 const char *p = " %s";
8662 fdprintf(preverrout_fd, p, expandstr(ps4val()));
8665 for (n = 0; n < 2; n++) {
8667 fdprintf(preverrout_fd, p, sp->text);
8675 safe_write(preverrout_fd, "\n", 1);
8681 /* Now locate the command. */
8683 const char *oldpath;
8684 int cmd_flag = DO_ERR;
8689 find_command(argv[0], &cmdentry, cmd_flag, path);
8690 if (cmdentry.cmdtype == CMDUNKNOWN) {
8696 /* implement bltin and command here */
8697 if (cmdentry.cmdtype != CMDBUILTIN)
8700 spclbltin = IS_BUILTIN_SPECIAL(cmdentry.u.cmd);
8701 if (cmdentry.u.cmd == EXECCMD)
8703 #if ENABLE_ASH_CMDCMD
8704 if (cmdentry.u.cmd == COMMANDCMD) {
8706 nargv = parse_command_args(argv, &path);
8709 argc -= nargv - argv;
8711 cmd_flag |= DO_NOFUNC;
8719 /* We have a redirection error. */
8721 raise_exception(EXERROR);
8723 exitstatus = status;
8727 /* Execute the command. */
8728 switch (cmdentry.cmdtype) {
8730 #if ENABLE_FEATURE_SH_NOFORK
8732 /* find_command() encodes applet_no as (-2 - applet_no) */
8733 int applet_no = (- cmdentry.u.index - 2);
8734 if (applet_no >= 0 && APPLET_IS_NOFORK(applet_no)) {
8735 listsetvar(varlist.list, VEXPORT|VSTACK);
8736 /* run <applet>_main() */
8737 exitstatus = run_nofork_applet(applet_no, argv);
8743 /* Fork off a child process if necessary. */
8744 if (!(flags & EV_EXIT) || trap[0]) {
8746 jp = makejob(/*cmd,*/ 1);
8747 if (forkshell(jp, cmd, FORK_FG) != 0) {
8748 exitstatus = waitforjob(jp);
8754 listsetvar(varlist.list, VEXPORT|VSTACK);
8755 shellexec(argv, path, cmdentry.u.index);
8759 cmdenviron = varlist.list;
8761 struct strlist *list = cmdenviron;
8763 if (spclbltin > 0 || argc == 0) {
8765 if (cmd_is_exec && argc > 1)
8768 listsetvar(list, i);
8770 if (evalbltin(cmdentry.u.cmd, argc, argv)) {
8777 exit_status = 128 + SIGINT;
8779 exit_status = 128 + pendingsig;
8780 exitstatus = exit_status;
8781 if (i == EXINT || spclbltin > 0) {
8783 longjmp(exception_handler->loc, 1);
8790 listsetvar(varlist.list, 0);
8791 if (evalfun(cmdentry.u.func, argc, argv, flags))
8797 popredir(cmd_is_exec);
8799 /* dsl: I think this is intended to be used to support
8800 * '_' in 'vi' command mode during line editing...
8801 * However I implemented that within libedit itself.
8803 setvar("_", lastarg, 0);
8804 popstackmark(&smark);
8808 evalbltin(const struct builtincmd *cmd, int argc, char **argv)
8810 char *volatile savecmdname;
8811 struct jmploc *volatile savehandler;
8812 struct jmploc jmploc;
8815 savecmdname = commandname;
8816 i = setjmp(jmploc.loc);
8819 savehandler = exception_handler;
8820 exception_handler = &jmploc;
8821 commandname = argv[0];
8823 optptr = NULL; /* initialize nextopt */
8824 exitstatus = (*cmd->builtin)(argc, argv);
8825 flush_stdout_stderr();
8827 exitstatus |= ferror(stdout);
8829 commandname = savecmdname;
8831 exception_handler = savehandler;
8837 goodname(const char *p)
8839 return !*endofname(p);
8844 * Search for a command. This is called before we fork so that the
8845 * location of the command will be available in the parent as well as
8846 * the child. The check for "goodname" is an overly conservative
8847 * check that the name will not be subject to expansion.
8850 prehash(union node *n)
8852 struct cmdentry entry;
8854 if (n->type == NCMD && n->ncmd.args && goodname(n->ncmd.args->narg.text))
8855 find_command(n->ncmd.args->narg.text, &entry, 0, pathval());
8859 /* ============ Builtin commands
8861 * Builtin commands whose functions are closely tied to evaluation
8862 * are implemented here.
8866 * Handle break and continue commands. Break, continue, and return are
8867 * all handled by setting the evalskip flag. The evaluation routines
8868 * above all check this flag, and if it is set they start skipping
8869 * commands rather than executing them. The variable skipcount is
8870 * the number of loops to break/continue, or the number of function
8871 * levels to return. (The latter is always 1.) It should probably
8872 * be an error to break out of more loops than exist, but it isn't
8873 * in the standard shell so we don't make it one here.
8876 breakcmd(int argc ATTRIBUTE_UNUSED, char **argv)
8878 int n = argv[1] ? number(argv[1]) : 1;
8881 ash_msg_and_raise_error(illnum, argv[1]);
8885 evalskip = (**argv == 'c') ? SKIPCONT : SKIPBREAK;
8892 /* ============ input.c
8894 * This implements the input routines used by the parser.
8897 #define EOF_NLEFT -99 /* value of parsenleft when EOF pushed back */
8900 INPUT_PUSH_FILE = 1,
8901 INPUT_NOFILE_OK = 2,
8904 static int plinno = 1; /* input line number */
8905 /* number of characters left in input buffer */
8906 static int parsenleft; /* copy of parsefile->nleft */
8907 static int parselleft; /* copy of parsefile->lleft */
8908 /* next character in input buffer */
8909 static char *parsenextc; /* copy of parsefile->nextc */
8911 static smallint checkkwd;
8912 /* values of checkkwd variable */
8913 #define CHKALIAS 0x1
8920 struct strpush *sp = g_parsefile->strpush;
8923 #if ENABLE_ASH_ALIAS
8925 if (parsenextc[-1] == ' ' || parsenextc[-1] == '\t') {
8926 checkkwd |= CHKALIAS;
8928 if (sp->string != sp->ap->val) {
8931 sp->ap->flag &= ~ALIASINUSE;
8932 if (sp->ap->flag & ALIASDEAD) {
8933 unalias(sp->ap->name);
8937 parsenextc = sp->prevstring;
8938 parsenleft = sp->prevnleft;
8939 /*dprintf("*** calling popstring: restoring to '%s'\n", parsenextc);*/
8940 g_parsefile->strpush = sp->prev;
8941 if (sp != &(g_parsefile->basestrpush))
8950 char *buf = g_parsefile->buf;
8953 #if ENABLE_FEATURE_EDITING
8955 if (!iflag || g_parsefile->fd)
8956 nr = nonblock_safe_read(g_parsefile->fd, buf, BUFSIZ - 1);
8958 #if ENABLE_FEATURE_TAB_COMPLETION
8959 line_input_state->path_lookup = pathval();
8961 nr = read_line_input(cmdedit_prompt, buf, BUFSIZ, line_input_state);
8963 /* Ctrl+C pressed */
8972 if (nr < 0 && errno == 0) {
8973 /* Ctrl+D pressed */
8978 nr = nonblock_safe_read(g_parsefile->fd, buf, BUFSIZ - 1);
8982 /* nonblock_safe_read() handles this problem */
8984 if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
8985 int flags = fcntl(0, F_GETFL);
8986 if (flags >= 0 && (flags & O_NONBLOCK)) {
8987 flags &= ~O_NONBLOCK;
8988 if (fcntl(0, F_SETFL, flags) >= 0) {
8989 out2str("sh: turning off NDELAY mode\n");
9000 * Refill the input buffer and return the next input character:
9002 * 1) If a string was pushed back on the input, pop it;
9003 * 2) If an EOF was pushed back (parsenleft == EOF_NLEFT) or we are reading
9004 * from a string so we can't refill the buffer, return EOF.
9005 * 3) If the is more stuff in this buffer, use it else call read to fill it.
9006 * 4) Process input up to the next newline, deleting nul characters.
9015 while (g_parsefile->strpush) {
9016 #if ENABLE_ASH_ALIAS
9017 if (parsenleft == -1 && g_parsefile->strpush->ap &&
9018 parsenextc[-1] != ' ' && parsenextc[-1] != '\t') {
9023 if (--parsenleft >= 0)
9024 return signed_char2int(*parsenextc++);
9026 if (parsenleft == EOF_NLEFT || g_parsefile->buf == NULL)
9028 flush_stdout_stderr();
9035 parselleft = parsenleft = EOF_NLEFT;
9042 /* delete nul characters */
9050 memmove(q, q + 1, more);
9054 parsenleft = q - parsenextc - 1;
9060 parsenleft = q - parsenextc - 1;
9072 out2str(parsenextc);
9077 return signed_char2int(*parsenextc++);
9080 #define pgetc_as_macro() (--parsenleft >= 0? signed_char2int(*parsenextc++) : preadbuffer())
9084 return pgetc_as_macro();
9087 #if ENABLE_ASH_OPTIMIZE_FOR_SIZE
9088 #define pgetc_macro() pgetc()
9090 #define pgetc_macro() pgetc_as_macro()
9094 * Same as pgetc(), but ignores PEOA.
9096 #if ENABLE_ASH_ALIAS
9104 } while (c == PEOA);
9111 return pgetc_macro();
9116 * Read a line from the script.
9119 pfgets(char *line, int len)
9125 while (--nleft > 0) {
9141 * Undo the last call to pgetc. Only one character may be pushed back.
9142 * PEOF may be pushed back.
9152 * Push a string back onto the input at this current parsefile level.
9153 * We handle aliases this way.
9155 #if !ENABLE_ASH_ALIAS
9156 #define pushstring(s, ap) pushstring(s)
9159 pushstring(char *s, struct alias *ap)
9166 /*dprintf("*** calling pushstring: %s, %d\n", s, len);*/
9167 if (g_parsefile->strpush) {
9168 sp = ckzalloc(sizeof(struct strpush));
9169 sp->prev = g_parsefile->strpush;
9170 g_parsefile->strpush = sp;
9172 sp = g_parsefile->strpush = &(g_parsefile->basestrpush);
9173 sp->prevstring = parsenextc;
9174 sp->prevnleft = parsenleft;
9175 #if ENABLE_ASH_ALIAS
9178 ap->flag |= ALIASINUSE;
9188 * To handle the "." command, a stack of input files is used. Pushfile
9189 * adds a new entry to the stack and popfile restores the previous level.
9194 struct parsefile *pf;
9196 g_parsefile->nleft = parsenleft;
9197 g_parsefile->lleft = parselleft;
9198 g_parsefile->nextc = parsenextc;
9199 g_parsefile->linno = plinno;
9200 pf = ckzalloc(sizeof(*pf));
9201 pf->prev = g_parsefile;
9203 /*pf->strpush = NULL; - ckzalloc did it */
9204 /*pf->basestrpush.prev = NULL;*/
9211 struct parsefile *pf = g_parsefile;
9219 g_parsefile = pf->prev;
9221 parsenleft = g_parsefile->nleft;
9222 parselleft = g_parsefile->lleft;
9223 parsenextc = g_parsefile->nextc;
9224 plinno = g_parsefile->linno;
9229 * Return to top level.
9234 while (g_parsefile != &basepf)
9239 * Close the file(s) that the shell is reading commands from. Called
9240 * after a fork is done.
9246 if (g_parsefile->fd > 0) {
9247 close(g_parsefile->fd);
9248 g_parsefile->fd = 0;
9253 * Like setinputfile, but takes an open file descriptor. Call this with
9257 setinputfd(int fd, int push)
9259 close_on_exec_on(fd);
9262 g_parsefile->buf = 0;
9264 g_parsefile->fd = fd;
9265 if (g_parsefile->buf == NULL)
9266 g_parsefile->buf = ckmalloc(IBUFSIZ);
9267 parselleft = parsenleft = 0;
9272 * Set the input to take input from a file. If push is set, push the
9273 * old input onto the stack first.
9276 setinputfile(const char *fname, int flags)
9282 fd = open(fname, O_RDONLY);
9284 if (flags & INPUT_NOFILE_OK)
9286 ash_msg_and_raise_error("can't open %s", fname);
9289 fd2 = copyfd(fd, 10);
9292 ash_msg_and_raise_error("out of file descriptors");
9295 setinputfd(fd, flags & INPUT_PUSH_FILE);
9302 * Like setinputfile, but takes input from a string.
9305 setinputstring(char *string)
9309 parsenextc = string;
9310 parsenleft = strlen(string);
9311 g_parsefile->buf = NULL;
9317 /* ============ mail.c
9319 * Routines to check for mail.
9324 #define MAXMBOXES 10
9326 /* times of mailboxes */
9327 static time_t mailtime[MAXMBOXES];
9328 /* Set if MAIL or MAILPATH is changed. */
9329 static smallint mail_var_path_changed;
9332 * Print appropriate message(s) if mail has arrived.
9333 * If mail_var_path_changed is set,
9334 * then the value of MAIL has mail_var_path_changed,
9335 * so we just update the values.
9344 struct stackmark smark;
9347 setstackmark(&smark);
9348 mpath = mpathset() ? mpathval() : mailval();
9349 for (mtp = mailtime; mtp < mailtime + MAXMBOXES; mtp++) {
9350 p = padvance(&mpath, nullstr);
9355 for (q = p; *q; q++)
9361 q[-1] = '\0'; /* delete trailing '/' */
9362 if (stat(p, &statb) < 0) {
9366 if (!mail_var_path_changed && statb.st_mtime != *mtp) {
9369 pathopt ? pathopt : "you have mail"
9372 *mtp = statb.st_mtime;
9374 mail_var_path_changed = 0;
9375 popstackmark(&smark);
9379 changemail(const char *val ATTRIBUTE_UNUSED)
9381 mail_var_path_changed = 1;
9384 #endif /* ASH_MAIL */
9387 /* ============ ??? */
9390 * Set the shell parameters.
9393 setparam(char **argv)
9399 for (nparam = 0; argv[nparam]; nparam++)
9401 ap = newparam = ckmalloc((nparam + 1) * sizeof(*ap));
9403 *ap++ = ckstrdup(*argv++);
9406 freeparam(&shellparam);
9407 shellparam.malloced = 1;
9408 shellparam.nparam = nparam;
9409 shellparam.p = newparam;
9410 #if ENABLE_ASH_GETOPTS
9411 shellparam.optind = 1;
9412 shellparam.optoff = -1;
9417 * Process shell options. The global variable argptr contains a pointer
9418 * to the argument list; we advance it past the options.
9420 * SUSv3 section 2.8.1 "Consequences of Shell Errors" says:
9421 * For a non-interactive shell, an error condition encountered
9422 * by a special built-in ... shall cause the shell to write a diagnostic message
9423 * to standard error and exit as shown in the following table:
9424 * Error Special Built-In
9426 * Utility syntax error (option or operand error) Shall exit
9428 * However, in bug 1142 (http://busybox.net/bugs/view.php?id=1142)
9429 * we see that bash does not do that (set "finishes" with error code 1 instead,
9430 * and shell continues), and people rely on this behavior!
9432 * set -o barfoo 2>/dev/null
9435 * Oh well. Let's mimic that.
9438 plus_minus_o(char *name, int val)
9443 for (i = 0; i < NOPTS; i++) {
9444 if (strcmp(name, optnames(i)) == 0) {
9449 ash_msg("illegal option %co %s", val ? '-' : '+', name);
9452 for (i = 0; i < NOPTS; i++) {
9454 out1fmt("%-16s%s\n", optnames(i), optlist[i] ? "on" : "off");
9456 out1fmt("set %co %s\n", optlist[i] ? '-' : '+', optnames(i));
9462 setoption(int flag, int val)
9466 for (i = 0; i < NOPTS; i++) {
9467 if (optletters(i) == flag) {
9472 ash_msg_and_raise_error("illegal option %c%c", val ? '-' : '+', flag);
9476 options(int cmdline)
9484 while ((p = *argptr) != NULL) {
9486 if (c != '-' && c != '+')
9489 val = 0; /* val = 0 if c == '+' */
9492 if (p[0] == '\0' || LONE_DASH(p)) {
9494 /* "-" means turn off -x and -v */
9497 /* "--" means reset params */
9498 else if (*argptr == NULL)
9501 break; /* "-" or "--" terminates options */
9504 /* first char was + or - */
9505 while ((c = *p++) != '\0') {
9506 /* bash 3.2 indeed handles -c CMD and +c CMD the same */
9507 if (c == 'c' && cmdline) {
9508 minusc = p; /* command is after shell args */
9509 } else if (c == 'o') {
9510 if (plus_minus_o(*argptr, val)) {
9511 /* it already printed err message */
9512 return 1; /* error */
9516 } else if (cmdline && (c == 'l')) { /* -l or +l == --login */
9518 /* bash does not accept +-login, we also won't */
9519 } else if (cmdline && val && (c == '-')) { /* long options */
9520 if (strcmp(p, "login") == 0)
9532 * The shift builtin command.
9535 shiftcmd(int argc ATTRIBUTE_UNUSED, char **argv)
9542 n = number(argv[1]);
9543 if (n > shellparam.nparam)
9544 n = shellparam.nparam;
9546 shellparam.nparam -= n;
9547 for (ap1 = shellparam.p; --n >= 0; ap1++) {
9548 if (shellparam.malloced)
9552 while ((*ap2++ = *ap1++) != NULL)
9554 #if ENABLE_ASH_GETOPTS
9555 shellparam.optind = 1;
9556 shellparam.optoff = -1;
9563 * POSIX requires that 'set' (but not export or readonly) output the
9564 * variables in lexicographic order - by the locale's collating order (sigh).
9565 * Maybe we could keep them in an ordered balanced binary tree
9566 * instead of hashed lists.
9567 * For now just roll 'em through qsort for printing...
9570 showvars(const char *sep_prefix, int on, int off)
9575 ep = listvars(on, off, &epend);
9576 qsort(ep, epend - ep, sizeof(char *), vpcmp);
9578 sep = *sep_prefix ? " " : sep_prefix;
9580 for (; ep < epend; ep++) {
9584 p = strchrnul(*ep, '=');
9587 q = single_quote(++p);
9588 out1fmt("%s%s%.*s%s\n", sep_prefix, sep, (int)(p - *ep), *ep, q);
9594 * The set command builtin.
9597 setcmd(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED)
9602 return showvars(nullstr, 0, VUNSET);
9605 if (!options(0)) { /* if no parse error... */
9608 if (*argptr != NULL) {
9616 #if ENABLE_ASH_RANDOM_SUPPORT
9617 /* Roughly copied from bash.. */
9619 change_random(const char *value)
9621 /* Galois LFSR parameter */
9622 /* Taps at 32 31 29 1: */
9623 enum { MASK = 0x8000000b };
9624 /* Another example - taps at 32 31 30 10: */
9625 /* MASK = 0x00400007 */
9627 if (value == NULL) {
9628 /* "get", generate */
9631 /* LCG has period of 2^32 and alternating lowest bit */
9632 random_LCG = 1664525 * random_LCG + 1013904223;
9633 /* Galois LFSR has period of 2^32-1 = 3 * 5 * 17 * 257 * 65537 */
9634 t = (random_galois_LFSR << 1);
9635 if (random_galois_LFSR < 0) /* if we just shifted 1 out of msb... */
9637 random_galois_LFSR = t;
9638 /* Both are weak, xoring them gives better randomness
9639 * and ~2^64 period. & 0x7fff is probably bash compat
9640 * for $RANDOM range. */
9641 t = (t ^ random_LCG) & 0x7fff;
9642 /* set without recursion */
9643 setvar(vrandom.text, utoa(t), VNOFUNC);
9644 vrandom.flags &= ~VNOFUNC;
9647 random_galois_LFSR = random_LCG = strtoul(value, (char **)NULL, 10);
9652 #if ENABLE_ASH_GETOPTS
9654 getopts(char *optstr, char *optvar, char **optfirst, int *param_optind, int *optoff)
9663 if (*param_optind < 1)
9665 optnext = optfirst + *param_optind - 1;
9667 if (*param_optind <= 1 || *optoff < 0 || (int)strlen(optnext[-1]) < *optoff)
9670 p = optnext[-1] + *optoff;
9671 if (p == NULL || *p == '\0') {
9672 /* Current word is done, advance */
9674 if (p == NULL || *p != '-' || *++p == '\0') {
9681 if (LONE_DASH(p)) /* check for "--" */
9686 for (q = optstr; *q != c;) {
9688 if (optstr[0] == ':') {
9691 err |= setvarsafe("OPTARG", s, 0);
9693 fprintf(stderr, "Illegal option -%c\n", c);
9704 if (*p == '\0' && (p = *optnext) == NULL) {
9705 if (optstr[0] == ':') {
9708 err |= setvarsafe("OPTARG", s, 0);
9711 fprintf(stderr, "No arg for -%c option\n", c);
9720 err |= setvarsafe("OPTARG", p, 0);
9723 err |= setvarsafe("OPTARG", nullstr, 0);
9725 *optoff = p ? p - *(optnext - 1) : -1;
9726 *param_optind = optnext - optfirst + 1;
9727 fmtstr(s, sizeof(s), "%d", *param_optind);
9728 err |= setvarsafe("OPTIND", s, VNOFUNC);
9731 err |= setvarsafe(optvar, s, 0);
9735 flush_stdout_stderr();
9736 raise_exception(EXERROR);
9742 * The getopts builtin. Shellparam.optnext points to the next argument
9743 * to be processed. Shellparam.optptr points to the next character to
9744 * be processed in the current argument. If shellparam.optnext is NULL,
9745 * then it's the first time getopts has been called.
9748 getoptscmd(int argc, char **argv)
9753 ash_msg_and_raise_error("usage: getopts optstring var [arg]");
9755 optbase = shellparam.p;
9756 if (shellparam.optind > shellparam.nparam + 1) {
9757 shellparam.optind = 1;
9758 shellparam.optoff = -1;
9762 if (shellparam.optind > argc - 2) {
9763 shellparam.optind = 1;
9764 shellparam.optoff = -1;
9768 return getopts(argv[1], argv[2], optbase, &shellparam.optind,
9769 &shellparam.optoff);
9771 #endif /* ASH_GETOPTS */
9774 /* ============ Shell parser */
9777 struct heredoc *next; /* next here document in list */
9778 union node *here; /* redirection node */
9779 char *eofmark; /* string indicating end of input */
9780 smallint striptabs; /* if set, strip leading tabs */
9783 static smallint tokpushback; /* last token pushed back */
9784 static smallint parsebackquote; /* nonzero if we are inside backquotes */
9785 static smallint quoteflag; /* set if (part of) last token was quoted */
9786 static token_id_t lasttoken; /* last token read (integer id Txxx) */
9787 static struct heredoc *heredoclist; /* list of here documents to read */
9788 static char *wordtext; /* text of last word returned by readtoken */
9789 static struct nodelist *backquotelist;
9790 static union node *redirnode;
9791 static struct heredoc *heredoc;
9793 * NEOF is returned by parsecmd when it encounters an end of file. It
9794 * must be distinct from NULL, so we use the address of a variable that
9795 * happens to be handy.
9797 #define NEOF ((union node *)&tokpushback)
9799 static void raise_error_syntax(const char *) ATTRIBUTE_NORETURN;
9801 raise_error_syntax(const char *msg)
9803 ash_msg_and_raise_error("syntax error: %s", msg);
9808 * Called when an unexpected token is read during the parse. The argument
9809 * is the token that is expected, or -1 if more than one type of token can
9810 * occur at this point.
9812 static void raise_error_unexpected_syntax(int) ATTRIBUTE_NORETURN;
9814 raise_error_unexpected_syntax(int token)
9819 l = sprintf(msg, "%s unexpected", tokname(lasttoken));
9821 sprintf(msg + l, " (expecting %s)", tokname(token));
9822 raise_error_syntax(msg);
9826 #define EOFMARKLEN 79
9828 /* parsing is heavily cross-recursive, need these forward decls */
9829 static union node *andor(void);
9830 static union node *pipeline(void);
9831 static union node *parse_command(void);
9832 static void parseheredoc(void);
9833 static char peektoken(void);
9834 static int readtoken(void);
9839 union node *n1, *n2, *n3;
9842 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9843 if (nlflag == 2 && peektoken())
9849 if (tok == TBACKGND) {
9850 if (n2->type == NPIPE) {
9851 n2->npipe.backgnd = 1;
9853 if (n2->type != NREDIR) {
9854 n3 = stzalloc(sizeof(struct nredir));
9856 /*n3->nredir.redirect = NULL; - stzalloc did it */
9859 n2->type = NBACKGND;
9865 n3 = stzalloc(sizeof(struct nbinary));
9867 n3->nbinary.ch1 = n1;
9868 n3->nbinary.ch2 = n2;
9884 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9892 pungetc(); /* push back EOF on input */
9896 raise_error_unexpected_syntax(-1);
9906 union node *n1, *n2, *n3;
9914 } else if (t == TOR) {
9920 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9922 n3 = stzalloc(sizeof(struct nbinary));
9924 n3->nbinary.ch1 = n1;
9925 n3->nbinary.ch2 = n2;
9933 union node *n1, *n2, *pipenode;
9934 struct nodelist *lp, *prev;
9938 TRACE(("pipeline: entered\n"));
9939 if (readtoken() == TNOT) {
9941 checkkwd = CHKKWD | CHKALIAS;
9944 n1 = parse_command();
9945 if (readtoken() == TPIPE) {
9946 pipenode = stzalloc(sizeof(struct npipe));
9947 pipenode->type = NPIPE;
9948 /*pipenode->npipe.backgnd = 0; - stzalloc did it */
9949 lp = stzalloc(sizeof(struct nodelist));
9950 pipenode->npipe.cmdlist = lp;
9954 lp = stzalloc(sizeof(struct nodelist));
9955 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9956 lp->n = parse_command();
9958 } while (readtoken() == TPIPE);
9964 n2 = stzalloc(sizeof(struct nnot));
9977 n = stzalloc(sizeof(struct narg));
9979 /*n->narg.next = NULL; - stzalloc did it */
9980 n->narg.text = wordtext;
9981 n->narg.backquote = backquotelist;
9986 fixredir(union node *n, const char *text, int err)
9988 TRACE(("Fix redir %s %d\n", text, err));
9990 n->ndup.vname = NULL;
9992 if (isdigit(text[0]) && text[1] == '\0')
9993 n->ndup.dupfd = text[0] - '0';
9994 else if (LONE_DASH(text))
9998 raise_error_syntax("Bad fd number");
9999 n->ndup.vname = makename();
10004 * Returns true if the text contains nothing to expand (no dollar signs
10008 noexpand(char *text)
10014 while ((c = *p++) != '\0') {
10015 if (c == CTLQUOTEMARK)
10019 else if (SIT(c, BASESYNTAX) == CCTL)
10028 union node *n = redirnode;
10030 if (readtoken() != TWORD)
10031 raise_error_unexpected_syntax(-1);
10032 if (n->type == NHERE) {
10033 struct heredoc *here = heredoc;
10037 if (quoteflag == 0)
10039 TRACE(("Here document %d\n", n->type));
10040 if (!noexpand(wordtext) || (i = strlen(wordtext)) == 0 || i > EOFMARKLEN)
10041 raise_error_syntax("Illegal eof marker for << redirection");
10042 rmescapes(wordtext);
10043 here->eofmark = wordtext;
10045 if (heredoclist == NULL)
10046 heredoclist = here;
10048 for (p = heredoclist; p->next; p = p->next)
10052 } else if (n->type == NTOFD || n->type == NFROMFD) {
10053 fixredir(n, wordtext, 0);
10055 n->nfile.fname = makename();
10059 static union node *
10062 union node *args, **app;
10063 union node *n = NULL;
10064 union node *vars, **vpp;
10065 union node **rpp, *redir;
10067 #if ENABLE_ASH_BASH_COMPAT
10068 smallint double_brackets_flag = 0;
10078 savecheckkwd = CHKALIAS;
10081 checkkwd = savecheckkwd;
10084 #if ENABLE_ASH_BASH_COMPAT
10085 case TAND: /* "&&" */
10086 case TOR: /* "||" */
10087 if (!double_brackets_flag) {
10091 wordtext = (char *) (t == TAND ? "-a" : "-o");
10094 n = stzalloc(sizeof(struct narg));
10096 /*n->narg.next = NULL; - stzalloc did it */
10097 n->narg.text = wordtext;
10098 #if ENABLE_ASH_BASH_COMPAT
10099 if (strcmp("[[", wordtext) == 0)
10100 double_brackets_flag = 1;
10101 else if (strcmp("]]", wordtext) == 0)
10102 double_brackets_flag = 0;
10104 n->narg.backquote = backquotelist;
10105 if (savecheckkwd && isassignment(wordtext)) {
10107 vpp = &n->narg.next;
10110 app = &n->narg.next;
10115 *rpp = n = redirnode;
10116 rpp = &n->nfile.next;
10117 parsefname(); /* read name of redirection file */
10120 if (args && app == &args->narg.next
10123 struct builtincmd *bcmd;
10126 /* We have a function */
10127 if (readtoken() != TRP)
10128 raise_error_unexpected_syntax(TRP);
10129 name = n->narg.text;
10130 if (!goodname(name)
10131 || ((bcmd = find_builtin(name)) && IS_BUILTIN_SPECIAL(bcmd))
10133 raise_error_syntax("Bad function name");
10136 checkkwd = CHKNL | CHKKWD | CHKALIAS;
10137 n->narg.next = parse_command();
10150 n = stzalloc(sizeof(struct ncmd));
10152 n->ncmd.args = args;
10153 n->ncmd.assign = vars;
10154 n->ncmd.redirect = redir;
10158 static union node *
10159 parse_command(void)
10161 union node *n1, *n2;
10162 union node *ap, **app;
10163 union node *cp, **cpp;
10164 union node *redir, **rpp;
10171 switch (readtoken()) {
10173 raise_error_unexpected_syntax(-1);
10176 n1 = stzalloc(sizeof(struct nif));
10178 n1->nif.test = list(0);
10179 if (readtoken() != TTHEN)
10180 raise_error_unexpected_syntax(TTHEN);
10181 n1->nif.ifpart = list(0);
10183 while (readtoken() == TELIF) {
10184 n2->nif.elsepart = stzalloc(sizeof(struct nif));
10185 n2 = n2->nif.elsepart;
10187 n2->nif.test = list(0);
10188 if (readtoken() != TTHEN)
10189 raise_error_unexpected_syntax(TTHEN);
10190 n2->nif.ifpart = list(0);
10192 if (lasttoken == TELSE)
10193 n2->nif.elsepart = list(0);
10195 n2->nif.elsepart = NULL;
10203 n1 = stzalloc(sizeof(struct nbinary));
10204 n1->type = (lasttoken == TWHILE) ? NWHILE : NUNTIL;
10205 n1->nbinary.ch1 = list(0);
10208 TRACE(("expecting DO got %s %s\n", tokname(got),
10209 got == TWORD ? wordtext : ""));
10210 raise_error_unexpected_syntax(TDO);
10212 n1->nbinary.ch2 = list(0);
10217 if (readtoken() != TWORD || quoteflag || ! goodname(wordtext))
10218 raise_error_syntax("Bad for loop variable");
10219 n1 = stzalloc(sizeof(struct nfor));
10221 n1->nfor.var = wordtext;
10222 checkkwd = CHKKWD | CHKALIAS;
10223 if (readtoken() == TIN) {
10225 while (readtoken() == TWORD) {
10226 n2 = stzalloc(sizeof(struct narg));
10228 /*n2->narg.next = NULL; - stzalloc did it */
10229 n2->narg.text = wordtext;
10230 n2->narg.backquote = backquotelist;
10232 app = &n2->narg.next;
10235 n1->nfor.args = ap;
10236 if (lasttoken != TNL && lasttoken != TSEMI)
10237 raise_error_unexpected_syntax(-1);
10239 n2 = stzalloc(sizeof(struct narg));
10241 /*n2->narg.next = NULL; - stzalloc did it */
10242 n2->narg.text = (char *)dolatstr;
10243 /*n2->narg.backquote = NULL;*/
10244 n1->nfor.args = n2;
10246 * Newline or semicolon here is optional (but note
10247 * that the original Bourne shell only allowed NL).
10249 if (lasttoken != TNL && lasttoken != TSEMI)
10252 checkkwd = CHKNL | CHKKWD | CHKALIAS;
10253 if (readtoken() != TDO)
10254 raise_error_unexpected_syntax(TDO);
10255 n1->nfor.body = list(0);
10259 n1 = stzalloc(sizeof(struct ncase));
10261 if (readtoken() != TWORD)
10262 raise_error_unexpected_syntax(TWORD);
10263 n1->ncase.expr = n2 = stzalloc(sizeof(struct narg));
10265 /*n2->narg.next = NULL; - stzalloc did it */
10266 n2->narg.text = wordtext;
10267 n2->narg.backquote = backquotelist;
10269 checkkwd = CHKKWD | CHKALIAS;
10270 } while (readtoken() == TNL);
10271 if (lasttoken != TIN)
10272 raise_error_unexpected_syntax(TIN);
10273 cpp = &n1->ncase.cases;
10275 checkkwd = CHKNL | CHKKWD;
10277 while (t != TESAC) {
10278 if (lasttoken == TLP)
10280 *cpp = cp = stzalloc(sizeof(struct nclist));
10282 app = &cp->nclist.pattern;
10284 *app = ap = stzalloc(sizeof(struct narg));
10286 /*ap->narg.next = NULL; - stzalloc did it */
10287 ap->narg.text = wordtext;
10288 ap->narg.backquote = backquotelist;
10289 if (readtoken() != TPIPE)
10291 app = &ap->narg.next;
10294 //ap->narg.next = NULL;
10295 if (lasttoken != TRP)
10296 raise_error_unexpected_syntax(TRP);
10297 cp->nclist.body = list(2);
10299 cpp = &cp->nclist.next;
10301 checkkwd = CHKNL | CHKKWD;
10305 raise_error_unexpected_syntax(TENDCASE);
10312 n1 = stzalloc(sizeof(struct nredir));
10313 n1->type = NSUBSHELL;
10314 n1->nredir.n = list(0);
10315 /*n1->nredir.redirect = NULL; - stzalloc did it */
10325 return simplecmd();
10328 if (readtoken() != t)
10329 raise_error_unexpected_syntax(t);
10332 /* Now check for redirection which may follow command */
10333 checkkwd = CHKKWD | CHKALIAS;
10335 while (readtoken() == TREDIR) {
10336 *rpp = n2 = redirnode;
10337 rpp = &n2->nfile.next;
10343 if (n1->type != NSUBSHELL) {
10344 n2 = stzalloc(sizeof(struct nredir));
10349 n1->nredir.redirect = redir;
10354 #if ENABLE_ASH_BASH_COMPAT
10355 static int decode_dollar_squote(void)
10357 static const char C_escapes[] ALIGN1 = "nrbtfav""x\\01234567";
10363 p = strchr(C_escapes, c);
10368 if ((unsigned char)(c - '0') <= 7) { /* \ooo */
10372 } while ((unsigned char)(c - '0') <= 7 && --cnt);
10374 } else if (c == 'x') { /* \xHH */
10378 } while (isxdigit(c) && --cnt);
10380 if (cnt == 3) { /* \x but next char is "bad" */
10384 } else { /* simple seq like \\ or \t */
10389 c = bb_process_escape_sequence((void*)&p);
10390 } else { /* unrecognized "\z": print both chars unless ' or " */
10391 if (c != '\'' && c != '"') {
10393 c |= 0x100; /* "please encode \, then me" */
10401 * If eofmark is NULL, read a word or a redirection symbol. If eofmark
10402 * is not NULL, read a here document. In the latter case, eofmark is the
10403 * word which marks the end of the document and striptabs is true if
10404 * leading tabs should be stripped from the document. The argument firstc
10405 * is the first character of the input token or document.
10407 * Because C does not have internal subroutines, I have simulated them
10408 * using goto's to implement the subroutine linkage. The following macros
10409 * will run code that appears at the end of readtoken1.
10411 #define CHECKEND() {goto checkend; checkend_return:;}
10412 #define PARSEREDIR() {goto parseredir; parseredir_return:;}
10413 #define PARSESUB() {goto parsesub; parsesub_return:;}
10414 #define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
10415 #define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
10416 #define PARSEARITH() {goto parsearith; parsearith_return:;}
10418 readtoken1(int firstc, int syntax, char *eofmark, int striptabs)
10420 /* NB: syntax parameter fits into smallint */
10424 char line[EOFMARKLEN + 1];
10425 struct nodelist *bqlist;
10429 smallint prevsyntax; /* syntax before arithmetic */
10430 #if ENABLE_ASH_EXPAND_PRMT
10431 smallint pssyntax; /* we are expanding a prompt string */
10433 int varnest; /* levels of variables expansion */
10434 int arinest; /* levels of arithmetic expansion */
10435 int parenlevel; /* levels of parens in arithmetic */
10436 int dqvarnest; /* levels of variables expansion within double quotes */
10438 USE_ASH_BASH_COMPAT(smallint bash_dollar_squote = 0;)
10441 /* Avoid longjmp clobbering */
10447 (void) &parenlevel;
10450 (void) &prevsyntax;
10453 startlinno = plinno;
10458 #if ENABLE_ASH_EXPAND_PRMT
10459 pssyntax = (syntax == PSSYNTAX);
10463 dblquote = (syntax == DQSYNTAX);
10469 STARTSTACKSTR(out);
10470 loop: { /* for each line, until end of word */
10471 CHECKEND(); /* set c to PEOF if at end of here document */
10472 for (;;) { /* until end of line or end of word */
10473 CHECKSTRSPACE(4, out); /* permit 4 calls to USTPUTC */
10474 switch (SIT(c, syntax)) {
10475 case CNL: /* '\n' */
10476 if (syntax == BASESYNTAX)
10477 goto endword; /* exit outer loop */
10483 goto loop; /* continue outer loop */
10488 if (eofmark == NULL || dblquote)
10489 USTPUTC(CTLESC, out);
10490 #if ENABLE_ASH_BASH_COMPAT
10491 if (c == '\\' && bash_dollar_squote) {
10492 c = decode_dollar_squote();
10494 USTPUTC('\\', out);
10495 c = (unsigned char)c;
10501 case CBACK: /* backslash */
10504 USTPUTC(CTLESC, out);
10505 USTPUTC('\\', out);
10507 } else if (c == '\n') {
10511 #if ENABLE_ASH_EXPAND_PRMT
10512 if (c == '$' && pssyntax) {
10513 USTPUTC(CTLESC, out);
10514 USTPUTC('\\', out);
10517 if (dblquote && c != '\\'
10518 && c != '`' && c != '$'
10519 && (c != '"' || eofmark != NULL)
10521 USTPUTC(CTLESC, out);
10522 USTPUTC('\\', out);
10524 if (SIT(c, SQSYNTAX) == CCTL)
10525 USTPUTC(CTLESC, out);
10533 if (eofmark == NULL) {
10534 USTPUTC(CTLQUOTEMARK, out);
10542 USE_ASH_BASH_COMPAT(bash_dollar_squote = 0;)
10543 if (eofmark != NULL && arinest == 0
10548 if (dqvarnest == 0) {
10549 syntax = BASESYNTAX;
10556 case CVAR: /* '$' */
10557 PARSESUB(); /* parse substitution */
10559 case CENDVAR: /* '}' */
10562 if (dqvarnest > 0) {
10565 USTPUTC(CTLENDVAR, out);
10570 #if ENABLE_ASH_MATH_SUPPORT
10571 case CLP: /* '(' in arithmetic */
10575 case CRP: /* ')' in arithmetic */
10576 if (parenlevel > 0) {
10580 if (pgetc() == ')') {
10581 if (--arinest == 0) {
10582 USTPUTC(CTLENDARI, out);
10583 syntax = prevsyntax;
10584 dblquote = (syntax == DQSYNTAX);
10589 * unbalanced parens
10590 * (don't 2nd guess - no error)
10598 case CBQUOTE: /* '`' */
10602 goto endword; /* exit outer loop */
10607 goto endword; /* exit outer loop */
10608 #if ENABLE_ASH_ALIAS
10618 #if ENABLE_ASH_MATH_SUPPORT
10619 if (syntax == ARISYNTAX)
10620 raise_error_syntax("Missing '))'");
10622 if (syntax != BASESYNTAX && !parsebackquote && eofmark == NULL)
10623 raise_error_syntax("Unterminated quoted string");
10624 if (varnest != 0) {
10625 startlinno = plinno;
10627 raise_error_syntax("Missing '}'");
10629 USTPUTC('\0', out);
10630 len = out - (char *)stackblock();
10631 out = stackblock();
10632 if (eofmark == NULL) {
10633 if ((c == '>' || c == '<')
10636 && (*out == '\0' || isdigit(*out))
10639 lasttoken = TREDIR;
10644 quoteflag = quotef;
10645 backquotelist = bqlist;
10646 grabstackblock(len);
10650 /* end of readtoken routine */
10653 * Check to see whether we are at the end of the here document. When this
10654 * is called, c is set to the first character of the next input line. If
10655 * we are at the end of the here document, this routine sets the c to PEOF.
10659 #if ENABLE_ASH_ALIAS
10665 while (c == '\t') {
10669 if (c == *eofmark) {
10670 if (pfgets(line, sizeof(line)) != NULL) {
10674 for (q = eofmark + 1; *q && *p == *q; p++, q++)
10676 if (*p == '\n' && *q == '\0') {
10679 needprompt = doprompt;
10681 pushstring(line, NULL);
10686 goto checkend_return;
10690 * Parse a redirection operator. The variable "out" points to a string
10691 * specifying the fd to be redirected. The variable "c" contains the
10692 * first character of the redirection operator.
10698 np = stzalloc(sizeof(struct nfile));
10703 np->type = NAPPEND;
10705 np->type = NCLOBBER;
10712 } else { /* c == '<' */
10713 /*np->nfile.fd = 0; - stzalloc did it */
10717 if (sizeof(struct nfile) != sizeof(struct nhere)) {
10718 np = stzalloc(sizeof(struct nhere));
10719 /*np->nfile.fd = 0; - stzalloc did it */
10722 heredoc = stzalloc(sizeof(struct heredoc));
10723 heredoc->here = np;
10726 heredoc->striptabs = 1;
10728 /*heredoc->striptabs = 0; - stzalloc did it */
10734 np->type = NFROMFD;
10738 np->type = NFROMTO;
10748 np->nfile.fd = fd - '0';
10750 goto parseredir_return;
10754 * Parse a substitution. At this point, we have read the dollar sign
10755 * and nothing else.
10758 /* is_special(c) evaluates to 1 for c in "!#$*-0123456789?@"; 0 otherwise
10759 * (assuming ascii char codes, as the original implementation did) */
10760 #define is_special(c) \
10761 (((unsigned)(c) - 33 < 32) \
10762 && ((0xc1ff920dU >> ((unsigned)(c) - 33)) & 1))
10768 static const char types[] ALIGN1 = "}-+?=";
10771 if (c <= PEOA_OR_PEOF
10772 || (c != '(' && c != '{' && !is_name(c) && !is_special(c))
10774 #if ENABLE_ASH_BASH_COMPAT
10776 bash_dollar_squote = 1;
10781 } else if (c == '(') { /* $(command) or $((arith)) */
10782 if (pgetc() == '(') {
10783 #if ENABLE_ASH_MATH_SUPPORT
10786 raise_error_syntax("you disabled math support for $((arith)) syntax");
10793 USTPUTC(CTLVAR, out);
10794 typeloc = out - (char *)stackblock();
10795 USTPUTC(VSNORMAL, out);
10796 subtype = VSNORMAL;
10804 subtype = VSLENGTH;
10808 if (c > PEOA_OR_PEOF && is_name(c)) {
10812 } while (c > PEOA_OR_PEOF && is_in_name(c));
10813 } else if (isdigit(c)) {
10817 } while (isdigit(c));
10818 } else if (is_special(c)) {
10822 badsub: raise_error_syntax("Bad substitution");
10826 if (subtype == 0) {
10830 #if ENABLE_ASH_BASH_COMPAT
10831 if (c == ':' || c == '$' || isdigit(c)) {
10833 subtype = VSSUBSTR;
10840 p = strchr(types, c);
10843 subtype = p - types + VSNORMAL;
10848 subtype = c == '#' ? VSTRIMLEFT : VSTRIMRIGHT;
10856 #if ENABLE_ASH_BASH_COMPAT
10858 subtype = VSREPLACE;
10861 subtype++; /* VSREPLACEALL */
10870 if (dblquote || arinest)
10872 *((char *)stackblock() + typeloc) = subtype | flags;
10873 if (subtype != VSNORMAL) {
10875 if (dblquote || arinest) {
10880 goto parsesub_return;
10884 * Called to parse command substitutions. Newstyle is set if the command
10885 * is enclosed inside $(...); nlpp is a pointer to the head of the linked
10886 * list of commands (passed by reference), and savelen is the number of
10887 * characters on the top of the stack which must be preserved.
10890 struct nodelist **nlpp;
10893 char *volatile str;
10894 struct jmploc jmploc;
10895 struct jmploc *volatile savehandler;
10897 smallint saveprompt = 0;
10900 (void) &saveprompt;
10902 savepbq = parsebackquote;
10903 if (setjmp(jmploc.loc)) {
10905 parsebackquote = 0;
10906 exception_handler = savehandler;
10907 longjmp(exception_handler->loc, 1);
10911 savelen = out - (char *)stackblock();
10913 str = ckmalloc(savelen);
10914 memcpy(str, stackblock(), savelen);
10916 savehandler = exception_handler;
10917 exception_handler = &jmploc;
10920 /* We must read until the closing backquote, giving special
10921 treatment to some slashes, and then push the string and
10922 reread it as input, interpreting it normally. */
10929 STARTSTACKSTR(pout);
10946 * If eating a newline, avoid putting
10947 * the newline into the new character
10948 * stream (via the STPUTC after the
10953 if (pc != '\\' && pc != '`' && pc != '$'
10954 && (!dblquote || pc != '"'))
10955 STPUTC('\\', pout);
10956 if (pc > PEOA_OR_PEOF) {
10962 #if ENABLE_ASH_ALIAS
10965 startlinno = plinno;
10966 raise_error_syntax("EOF in backquote substitution");
10970 needprompt = doprompt;
10979 STPUTC('\0', pout);
10980 psavelen = pout - (char *)stackblock();
10981 if (psavelen > 0) {
10982 pstr = grabstackstr(pout);
10983 setinputstring(pstr);
10988 nlpp = &(*nlpp)->next;
10989 *nlpp = stzalloc(sizeof(**nlpp));
10990 /* (*nlpp)->next = NULL; - stzalloc did it */
10991 parsebackquote = oldstyle;
10994 saveprompt = doprompt;
11001 doprompt = saveprompt;
11002 else if (readtoken() != TRP)
11003 raise_error_unexpected_syntax(TRP);
11008 * Start reading from old file again, ignoring any pushed back
11009 * tokens left from the backquote parsing
11014 while (stackblocksize() <= savelen)
11016 STARTSTACKSTR(out);
11018 memcpy(out, str, savelen);
11019 STADJUST(savelen, out);
11025 parsebackquote = savepbq;
11026 exception_handler = savehandler;
11027 if (arinest || dblquote)
11028 USTPUTC(CTLBACKQ | CTLQUOTE, out);
11030 USTPUTC(CTLBACKQ, out);
11032 goto parsebackq_oldreturn;
11033 goto parsebackq_newreturn;
11036 #if ENABLE_ASH_MATH_SUPPORT
11038 * Parse an arithmetic expansion (indicate start of one and set state)
11041 if (++arinest == 1) {
11042 prevsyntax = syntax;
11043 syntax = ARISYNTAX;
11044 USTPUTC(CTLARI, out);
11051 * we collapse embedded arithmetic expansion to
11052 * parenthesis, which should be equivalent
11056 goto parsearith_return;
11060 } /* end of readtoken */
11063 * Read the next input token.
11064 * If the token is a word, we set backquotelist to the list of cmds in
11065 * backquotes. We set quoteflag to true if any part of the word was
11067 * If the token is TREDIR, then we set redirnode to a structure containing
11069 * In all cases, the variable startlinno is set to the number of the line
11070 * on which the token starts.
11072 * [Change comment: here documents and internal procedures]
11073 * [Readtoken shouldn't have any arguments. Perhaps we should make the
11074 * word parsing code into a separate routine. In this case, readtoken
11075 * doesn't need to have any internal procedures, but parseword does.
11076 * We could also make parseoperator in essence the main routine, and
11077 * have parseword (readtoken1?) handle both words and redirection.]
11079 #define NEW_xxreadtoken
11080 #ifdef NEW_xxreadtoken
11081 /* singles must be first! */
11082 static const char xxreadtoken_chars[7] ALIGN1 = {
11083 '\n', '(', ')', '&', '|', ';', 0
11086 static const char xxreadtoken_tokens[] ALIGN1 = {
11087 TNL, TLP, TRP, /* only single occurrence allowed */
11088 TBACKGND, TPIPE, TSEMI, /* if single occurrence */
11089 TEOF, /* corresponds to trailing nul */
11090 TAND, TOR, TENDCASE /* if double occurrence */
11093 #define xxreadtoken_doubles \
11094 (sizeof(xxreadtoken_tokens) - sizeof(xxreadtoken_chars))
11095 #define xxreadtoken_singles \
11096 (sizeof(xxreadtoken_chars) - xxreadtoken_doubles - 1)
11110 startlinno = plinno;
11111 for (;;) { /* until token or start of word found */
11114 if ((c != ' ') && (c != '\t')
11115 #if ENABLE_ASH_ALIAS
11120 while ((c = pgetc()) != '\n' && c != PEOF)
11123 } else if (c == '\\') {
11124 if (pgetc() != '\n') {
11128 startlinno = ++plinno;
11133 = xxreadtoken_chars + sizeof(xxreadtoken_chars) - 1;
11138 needprompt = doprompt;
11141 p = strchr(xxreadtoken_chars, c);
11144 return readtoken1(c, BASESYNTAX, (char *) NULL, 0);
11147 if ((size_t)(p - xxreadtoken_chars) >= xxreadtoken_singles) {
11148 if (pgetc() == *p) { /* double occurrence? */
11149 p += xxreadtoken_doubles + 1;
11155 lasttoken = xxreadtoken_tokens[p - xxreadtoken_chars];
11162 #define RETURN(token) return lasttoken = token
11175 startlinno = plinno;
11176 for (;;) { /* until token or start of word found */
11179 case ' ': case '\t':
11180 #if ENABLE_ASH_ALIAS
11185 while ((c = pgetc()) != '\n' && c != PEOF)
11190 if (pgetc() == '\n') {
11191 startlinno = ++plinno;
11200 needprompt = doprompt;
11205 if (pgetc() == '&')
11210 if (pgetc() == '|')
11215 if (pgetc() == ';')
11228 return readtoken1(c, BASESYNTAX, (char *)NULL, 0);
11231 #endif /* NEW_xxreadtoken */
11238 smallint alreadyseen = tokpushback;
11241 #if ENABLE_ASH_ALIAS
11250 if (checkkwd & CHKNL) {
11257 if (t != TWORD || quoteflag) {
11262 * check for keywords
11264 if (checkkwd & CHKKWD) {
11265 const char *const *pp;
11267 pp = findkwd(wordtext);
11269 lasttoken = t = pp - tokname_array;
11270 TRACE(("keyword %s recognized\n", tokname(t)));
11275 if (checkkwd & CHKALIAS) {
11276 #if ENABLE_ASH_ALIAS
11278 ap = lookupalias(wordtext, 1);
11281 pushstring(ap->val, ap);
11291 TRACE(("token %s %s\n", tokname(t), t == TWORD ? wordtext : ""));
11293 TRACE(("reread token %s %s\n", tokname(t), t == TWORD ? wordtext : ""));
11305 return tokname_array[t][0];
11309 * Read and parse a command. Returns NEOF on end of file. (NULL is a
11310 * valid parse tree indicating a blank line.)
11312 static union node *
11313 parsecmd(int interact)
11318 doprompt = interact;
11320 setprompt(doprompt);
11332 * Input any here documents.
11337 struct heredoc *here;
11340 here = heredoclist;
11341 heredoclist = NULL;
11347 readtoken1(pgetc(), here->here->type == NHERE? SQSYNTAX : DQSYNTAX,
11348 here->eofmark, here->striptabs);
11349 n = stzalloc(sizeof(struct narg));
11350 n->narg.type = NARG;
11351 /*n->narg.next = NULL; - stzalloc did it */
11352 n->narg.text = wordtext;
11353 n->narg.backquote = backquotelist;
11354 here->here->nhere.doc = n;
11361 * called by editline -- any expansions to the prompt should be added here.
11363 #if ENABLE_ASH_EXPAND_PRMT
11364 static const char *
11365 expandstr(const char *ps)
11369 /* XXX Fix (char *) cast. */
11370 setinputstring((char *)ps);
11371 readtoken1(pgetc(), PSSYNTAX, nullstr, 0);
11374 n.narg.type = NARG;
11375 n.narg.next = NULL;
11376 n.narg.text = wordtext;
11377 n.narg.backquote = backquotelist;
11379 expandarg(&n, NULL, 0);
11380 return stackblock();
11385 * Execute a command or commands contained in a string.
11388 evalstring(char *s, int mask)
11391 struct stackmark smark;
11395 setstackmark(&smark);
11398 while ((n = parsecmd(0)) != NEOF) {
11400 popstackmark(&smark);
11413 * The eval command.
11416 evalcmd(int argc ATTRIBUTE_UNUSED, char **argv)
11425 STARTSTACKSTR(concat);
11427 concat = stack_putstr(p, concat);
11431 STPUTC(' ', concat);
11433 STPUTC('\0', concat);
11434 p = grabstackstr(concat);
11436 evalstring(p, ~SKIPEVAL);
11443 * Read and execute commands. "Top" is nonzero for the top level command
11444 * loop; it turns on prompting if the shell is interactive.
11450 struct stackmark smark;
11454 TRACE(("cmdloop(%d) called\n", top));
11458 setstackmark(&smark);
11461 showjobs(stderr, SHOW_CHANGED);
11464 if (iflag && top) {
11466 #if ENABLE_ASH_MAIL
11470 n = parsecmd(inter);
11471 /* showtree(n); DEBUG */
11473 if (!top || numeof >= 50)
11475 if (!stoppedjobs()) {
11478 out2str("\nUse \"exit\" to leave shell.\n");
11481 } else if (nflag == 0) {
11482 /* job_warning can only be 2,1,0. Here 2->1, 1/0->0 */
11487 popstackmark(&smark);
11492 return skip & SKIPEVAL;
11499 * Take commands from a file. To be compatible we should do a path
11500 * search for the file, which is necessary to find sub-commands.
11503 find_dot_file(char *name)
11506 const char *path = pathval();
11509 /* don't try this for absolute or relative paths */
11510 if (strchr(name, '/'))
11513 while ((fullname = padvance(&path, name)) != NULL) {
11514 if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) {
11516 * Don't bother freeing here, since it will
11517 * be freed by the caller.
11521 stunalloc(fullname);
11524 /* not found in the PATH */
11525 ash_msg_and_raise_error("%s: not found", name);
11530 dotcmd(int argc, char **argv)
11532 struct strlist *sp;
11533 volatile struct shparam saveparam;
11536 for (sp = cmdenviron; sp; sp = sp->next)
11537 setvareq(ckstrdup(sp->text), VSTRFIXED | VTEXTFIXED);
11539 if (argv[1]) { /* That's what SVR2 does */
11540 char *fullname = find_dot_file(argv[1]);
11543 if (argc) { /* argc > 0, argv[0] != NULL */
11544 saveparam = shellparam;
11545 shellparam.malloced = 0;
11546 shellparam.nparam = argc;
11547 shellparam.p = argv;
11550 setinputfile(fullname, INPUT_PUSH_FILE);
11551 commandname = fullname;
11556 freeparam(&shellparam);
11557 shellparam = saveparam;
11559 status = exitstatus;
11565 exitcmd(int argc ATTRIBUTE_UNUSED, char **argv)
11570 exitstatus = number(argv[1]);
11571 raise_exception(EXEXIT);
11576 * Read a file containing shell functions.
11579 readcmdfile(char *name)
11581 setinputfile(name, INPUT_PUSH_FILE);
11587 /* ============ find_command inplementation */
11590 * Resolve a command name. If you change this routine, you may have to
11591 * change the shellexec routine as well.
11594 find_command(char *name, struct cmdentry *entry, int act, const char *path)
11596 struct tblentry *cmdp;
11603 struct builtincmd *bcmd;
11605 /* If name contains a slash, don't use PATH or hash table */
11606 if (strchr(name, '/') != NULL) {
11607 entry->u.index = -1;
11608 if (act & DO_ABS) {
11609 while (stat(name, &statb) < 0) {
11611 if (errno == EINTR)
11614 entry->cmdtype = CMDUNKNOWN;
11618 entry->cmdtype = CMDNORMAL;
11622 /* #if ENABLE_FEATURE_SH_STANDALONE... moved after builtin check */
11624 updatetbl = (path == pathval());
11627 if (strstr(path, "%builtin") != NULL)
11628 act |= DO_ALTBLTIN;
11631 /* If name is in the table, check answer will be ok */
11632 cmdp = cmdlookup(name, 0);
11633 if (cmdp != NULL) {
11636 switch (cmdp->cmdtype) {
11654 } else if (cmdp->rehash == 0)
11655 /* if not invalidated by cd, we're done */
11659 /* If %builtin not in path, check for builtin next */
11660 bcmd = find_builtin(name);
11662 if (IS_BUILTIN_REGULAR(bcmd))
11663 goto builtin_success;
11664 if (act & DO_ALTPATH) {
11665 if (!(act & DO_ALTBLTIN))
11666 goto builtin_success;
11667 } else if (builtinloc <= 0) {
11668 goto builtin_success;
11672 #if ENABLE_FEATURE_SH_STANDALONE
11674 int applet_no = find_applet_by_name(name);
11675 if (applet_no >= 0) {
11676 entry->cmdtype = CMDNORMAL;
11677 entry->u.index = -2 - applet_no;
11683 /* We have to search path. */
11684 prev = -1; /* where to start */
11685 if (cmdp && cmdp->rehash) { /* doing a rehash */
11686 if (cmdp->cmdtype == CMDBUILTIN)
11689 prev = cmdp->param.index;
11695 while ((fullname = padvance(&path, name)) != NULL) {
11696 stunalloc(fullname);
11697 /* NB: code below will still use fullname
11698 * despite it being "unallocated" */
11701 if (prefix(pathopt, "builtin")) {
11703 goto builtin_success;
11706 if ((act & DO_NOFUNC)
11707 || !prefix(pathopt, "func")
11708 ) { /* ignore unimplemented options */
11712 /* if rehash, don't redo absolute path names */
11713 if (fullname[0] == '/' && idx <= prev) {
11716 TRACE(("searchexec \"%s\": no change\n", name));
11719 while (stat(fullname, &statb) < 0) {
11721 if (errno == EINTR)
11724 if (errno != ENOENT && errno != ENOTDIR)
11728 e = EACCES; /* if we fail, this will be the error */
11729 if (!S_ISREG(statb.st_mode))
11731 if (pathopt) { /* this is a %func directory */
11732 stalloc(strlen(fullname) + 1);
11733 /* NB: stalloc will return space pointed by fullname
11734 * (because we don't have any intervening allocations
11735 * between stunalloc above and this stalloc) */
11736 readcmdfile(fullname);
11737 cmdp = cmdlookup(name, 0);
11738 if (cmdp == NULL || cmdp->cmdtype != CMDFUNCTION)
11739 ash_msg_and_raise_error("%s not defined in %s", name, fullname);
11740 stunalloc(fullname);
11743 TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
11745 entry->cmdtype = CMDNORMAL;
11746 entry->u.index = idx;
11750 cmdp = cmdlookup(name, 1);
11751 cmdp->cmdtype = CMDNORMAL;
11752 cmdp->param.index = idx;
11757 /* We failed. If there was an entry for this command, delete it */
11758 if (cmdp && updatetbl)
11759 delete_cmd_entry();
11761 ash_msg("%s: %s", name, errmsg(e, "not found"));
11762 entry->cmdtype = CMDUNKNOWN;
11767 entry->cmdtype = CMDBUILTIN;
11768 entry->u.cmd = bcmd;
11772 cmdp = cmdlookup(name, 1);
11773 cmdp->cmdtype = CMDBUILTIN;
11774 cmdp->param.cmd = bcmd;
11778 entry->cmdtype = cmdp->cmdtype;
11779 entry->u = cmdp->param;
11783 /* ============ trap.c */
11786 * The trap builtin.
11789 trapcmd(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED)
11798 for (signo = 0; signo < NSIG; signo++) {
11799 if (trap[signo] != NULL) {
11802 sn = get_signame(signo);
11803 out1fmt("trap -- %s %s\n",
11804 single_quote(trap[signo]), sn);
11814 signo = get_signum(*ap);
11816 ash_msg_and_raise_error("%s: bad trap", *ap);
11819 if (LONE_DASH(action))
11822 action = ckstrdup(action);
11825 trap[signo] = action;
11835 /* ============ Builtins */
11837 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
11839 * Lists available builtins
11842 helpcmd(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED)
11847 out1fmt("\nBuilt-in commands:\n-------------------\n");
11848 for (col = 0, i = 0; i < ARRAY_SIZE(builtintab); i++) {
11849 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '),
11850 builtintab[i].name + 1);
11856 #if ENABLE_FEATURE_SH_STANDALONE
11858 const char *a = applet_names;
11860 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '), a);
11865 a += strlen(a) + 1;
11870 return EXIT_SUCCESS;
11872 #endif /* FEATURE_SH_EXTRA_QUIET */
11875 * The export and readonly commands.
11878 exportcmd(int argc ATTRIBUTE_UNUSED, char **argv)
11884 int flag = argv[0][0] == 'r'? VREADONLY : VEXPORT;
11886 if (nextopt("p") != 'p') {
11891 p = strchr(name, '=');
11895 vp = *findvar(hashvar(name), name);
11901 setvar(name, p, flag);
11902 } while ((name = *++aptr) != NULL);
11906 showvars(argv[0], flag, 0);
11911 * Delete a function if it exists.
11914 unsetfunc(const char *name)
11916 struct tblentry *cmdp;
11918 cmdp = cmdlookup(name, 0);
11919 if (cmdp!= NULL && cmdp->cmdtype == CMDFUNCTION)
11920 delete_cmd_entry();
11924 * The unset builtin command. We unset the function before we unset the
11925 * variable to allow a function to be unset when there is a readonly variable
11926 * with the same name.
11929 unsetcmd(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED)
11936 while ((i = nextopt("vf")) != '\0') {
11940 for (ap = argptr; *ap; ap++) {
11956 #include <sys/times.h>
11958 static const unsigned char timescmd_str[] ALIGN1 = {
11959 ' ', offsetof(struct tms, tms_utime),
11960 '\n', offsetof(struct tms, tms_stime),
11961 ' ', offsetof(struct tms, tms_cutime),
11962 '\n', offsetof(struct tms, tms_cstime),
11967 timescmd(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED)
11969 long clk_tck, s, t;
11970 const unsigned char *p;
11973 clk_tck = sysconf(_SC_CLK_TCK);
11978 t = *(clock_t *)(((char *) &buf) + p[1]);
11980 out1fmt("%ldm%ld.%.3lds%c",
11982 ((t - s * clk_tck) * 1000) / clk_tck,
11984 } while (*(p += 2));
11989 #if ENABLE_ASH_MATH_SUPPORT
11991 dash_arith(const char *s)
11997 result = arith(s, &errcode);
12000 ash_msg_and_raise_error("exponent less than 0");
12002 ash_msg_and_raise_error("divide by zero");
12004 ash_msg_and_raise_error("expression recursion loop detected");
12005 raise_error_syntax(s);
12013 * The let builtin. partial stolen from GNU Bash, the Bourne Again SHell.
12014 * Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
12016 * Copyright (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
12019 letcmd(int argc ATTRIBUTE_UNUSED, char **argv)
12025 ash_msg_and_raise_error("expression expected");
12027 i = dash_arith(*argv);
12032 #endif /* ASH_MATH_SUPPORT */
12035 /* ============ miscbltin.c
12037 * Miscellaneous builtins.
12042 #if defined(__GLIBC__) && __GLIBC__ == 2 && __GLIBC_MINOR__ < 1
12043 typedef enum __rlimit_resource rlim_t;
12047 * The read builtin. Options:
12048 * -r Do not interpret '\' specially
12049 * -s Turn off echo (tty only)
12050 * -n NCHARS Read NCHARS max
12051 * -p PROMPT Display PROMPT on stderr (if input is from tty)
12052 * -t SECONDS Timeout after SECONDS (tty or pipe only)
12053 * -u FD Read from given FD instead of fd 0
12054 * This uses unbuffered input, which may be avoidable in some cases.
12055 * TODO: bash also has:
12056 * -a ARRAY Read into array[0],[1],etc
12057 * -d DELIM End on DELIM char, not newline
12058 * -e Use line editing (tty only)
12061 readcmd(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED)
12063 static const char *const arg_REPLY[] = { "REPLY", NULL };
12076 #if ENABLE_ASH_READ_NCHARS
12077 int nchars = 0; /* if != 0, -n is in effect */
12079 struct termios tty, old_tty;
12081 #if ENABLE_ASH_READ_TIMEOUT
12082 unsigned end_ms = 0;
12083 unsigned timeout = 0;
12088 while ((i = nextopt("p:u:r"
12089 USE_ASH_READ_TIMEOUT("t:")
12090 USE_ASH_READ_NCHARS("n:s")
12094 prompt = optionarg;
12096 #if ENABLE_ASH_READ_NCHARS
12098 nchars = bb_strtou(optionarg, NULL, 10);
12099 if (nchars < 0 || errno)
12100 ash_msg_and_raise_error("invalid count");
12101 /* nchars == 0: off (bash 3.2 does this too) */
12107 #if ENABLE_ASH_READ_TIMEOUT
12109 timeout = bb_strtou(optionarg, NULL, 10);
12110 if (errno || timeout > UINT_MAX / 2048)
12111 ash_msg_and_raise_error("invalid timeout");
12113 #if 0 /* even bash have no -t N.NNN support */
12114 ts.tv_sec = bb_strtou(optionarg, &p, 10);
12116 /* EINVAL means number is ok, but not terminated by NUL */
12117 if (*p == '.' && errno == EINVAL) {
12121 ts.tv_usec = bb_strtou(p, &p2, 10);
12123 ash_msg_and_raise_error("invalid timeout");
12125 /* normalize to usec */
12127 ash_msg_and_raise_error("invalid timeout");
12128 while (scale++ < 6)
12131 } else if (ts.tv_sec < 0 || errno) {
12132 ash_msg_and_raise_error("invalid timeout");
12134 if (!(ts.tv_sec | ts.tv_usec)) { /* both are 0? */
12135 ash_msg_and_raise_error("invalid timeout");
12144 fd = bb_strtou(optionarg, NULL, 10);
12145 if (fd < 0 || errno)
12146 ash_msg_and_raise_error("invalid file descriptor");
12152 if (prompt && isatty(fd)) {
12157 ap = (char**)arg_REPLY;
12158 ifs = bltinlookup("IFS");
12161 #if ENABLE_ASH_READ_NCHARS
12162 tcgetattr(fd, &tty);
12164 if (nchars || silent) {
12166 tty.c_lflag &= ~ICANON;
12167 tty.c_cc[VMIN] = nchars < 256 ? nchars : 255;
12170 tty.c_lflag &= ~(ECHO | ECHOK | ECHONL);
12172 /* if tcgetattr failed, tcsetattr will fail too.
12173 * Ignoring, it's harmless. */
12174 tcsetattr(fd, TCSANOW, &tty);
12181 #if ENABLE_ASH_READ_TIMEOUT
12182 if (timeout) /* NB: ensuring end_ms is nonzero */
12183 end_ms = ((unsigned)(monotonic_us() / 1000) + timeout) | 1;
12187 #if ENABLE_ASH_READ_TIMEOUT
12189 struct pollfd pfd[1];
12191 pfd[0].events = POLLIN;
12192 timeout = end_ms - (unsigned)(monotonic_us() / 1000);
12193 if ((int)timeout <= 0 /* already late? */
12194 || safe_poll(pfd, 1, timeout) != 1 /* no? wait... */
12195 ) { /* timed out! */
12196 #if ENABLE_ASH_READ_NCHARS
12197 tcsetattr(fd, TCSANOW, &old_tty);
12203 if (nonblock_safe_read(fd, &c, 1) != 1) {
12215 if (!rflag && c == '\\') {
12221 if (startword && *ifs == ' ' && strchr(ifs, c)) {
12225 if (ap[1] != NULL && strchr(ifs, c) != NULL) {
12227 setvar(*ap, stackblock(), 0);
12236 /* end of do {} while: */
12237 #if ENABLE_ASH_READ_NCHARS
12243 #if ENABLE_ASH_READ_NCHARS
12244 tcsetattr(fd, TCSANOW, &old_tty);
12248 /* Remove trailing blanks */
12249 while ((char *)stackblock() <= --p && strchr(ifs, *p) != NULL)
12251 setvar(*ap, stackblock(), 0);
12252 while (*++ap != NULL)
12253 setvar(*ap, nullstr, 0);
12258 umaskcmd(int argc ATTRIBUTE_UNUSED, char **argv)
12260 static const char permuser[3] ALIGN1 = "ugo";
12261 static const char permmode[3] ALIGN1 = "rwx";
12262 static const short permmask[] ALIGN2 = {
12263 S_IRUSR, S_IWUSR, S_IXUSR,
12264 S_IRGRP, S_IWGRP, S_IXGRP,
12265 S_IROTH, S_IWOTH, S_IXOTH
12271 int symbolic_mode = 0;
12273 while (nextopt("S") != '\0') {
12284 if (symbolic_mode) {
12288 for (i = 0; i < 3; i++) {
12291 *p++ = permuser[i];
12293 for (j = 0; j < 3; j++) {
12294 if ((mask & permmask[3 * i + j]) == 0) {
12295 *p++ = permmode[j];
12303 out1fmt("%.4o\n", mask);
12306 if (isdigit((unsigned char) *ap)) {
12309 if (*ap >= '8' || *ap < '0')
12310 ash_msg_and_raise_error(illnum, argv[1]);
12311 mask = (mask << 3) + (*ap - '0');
12312 } while (*++ap != '\0');
12315 mask = ~mask & 0777;
12316 if (!bb_parse_mode(ap, &mask)) {
12317 ash_msg_and_raise_error("illegal mode: %s", ap);
12319 umask(~mask & 0777);
12328 * This code, originally by Doug Gwyn, Doug Kingston, Eric Gisin, and
12329 * Michael Rendell was ripped from pdksh 5.0.8 and hacked for use with
12330 * ash by J.T. Conklin.
12336 uint8_t cmd; /* RLIMIT_xxx fit into it */
12337 uint8_t factor_shift; /* shift by to get rlim_{cur,max} values */
12341 static const struct limits limits_tbl[] = {
12343 { RLIMIT_CPU, 0, 't' },
12345 #ifdef RLIMIT_FSIZE
12346 { RLIMIT_FSIZE, 9, 'f' },
12349 { RLIMIT_DATA, 10, 'd' },
12351 #ifdef RLIMIT_STACK
12352 { RLIMIT_STACK, 10, 's' },
12355 { RLIMIT_CORE, 9, 'c' },
12358 { RLIMIT_RSS, 10, 'm' },
12360 #ifdef RLIMIT_MEMLOCK
12361 { RLIMIT_MEMLOCK, 10, 'l' },
12363 #ifdef RLIMIT_NPROC
12364 { RLIMIT_NPROC, 0, 'p' },
12366 #ifdef RLIMIT_NOFILE
12367 { RLIMIT_NOFILE, 0, 'n' },
12370 { RLIMIT_AS, 10, 'v' },
12372 #ifdef RLIMIT_LOCKS
12373 { RLIMIT_LOCKS, 0, 'w' },
12376 static const char limits_name[] =
12378 "time(seconds)" "\0"
12380 #ifdef RLIMIT_FSIZE
12381 "file(blocks)" "\0"
12386 #ifdef RLIMIT_STACK
12390 "coredump(blocks)" "\0"
12395 #ifdef RLIMIT_MEMLOCK
12396 "locked memory(kb)" "\0"
12398 #ifdef RLIMIT_NPROC
12401 #ifdef RLIMIT_NOFILE
12407 #ifdef RLIMIT_LOCKS
12412 enum limtype { SOFT = 0x1, HARD = 0x2 };
12415 printlim(enum limtype how, const struct rlimit *limit,
12416 const struct limits *l)
12420 val = limit->rlim_max;
12422 val = limit->rlim_cur;
12424 if (val == RLIM_INFINITY)
12425 out1fmt("unlimited\n");
12427 val >>= l->factor_shift;
12428 out1fmt("%lld\n", (long long) val);
12433 ulimitcmd(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED)
12437 enum limtype how = SOFT | HARD;
12438 const struct limits *l;
12441 struct rlimit limit;
12444 while ((optc = nextopt("HSa"
12448 #ifdef RLIMIT_FSIZE
12454 #ifdef RLIMIT_STACK
12463 #ifdef RLIMIT_MEMLOCK
12466 #ifdef RLIMIT_NPROC
12469 #ifdef RLIMIT_NOFILE
12475 #ifdef RLIMIT_LOCKS
12493 for (l = limits_tbl; l->option != what; l++)
12496 set = *argptr ? 1 : 0;
12500 if (all || argptr[1])
12501 ash_msg_and_raise_error("too many arguments");
12502 if (strncmp(p, "unlimited\n", 9) == 0)
12503 val = RLIM_INFINITY;
12507 while ((c = *p++) >= '0' && c <= '9') {
12508 val = (val * 10) + (long)(c - '0');
12509 // val is actually 'unsigned long int' and can't get < 0
12510 if (val < (rlim_t) 0)
12514 ash_msg_and_raise_error("bad number");
12515 val <<= l->factor_shift;
12519 const char *lname = limits_name;
12520 for (l = limits_tbl; l != &limits_tbl[ARRAY_SIZE(limits_tbl)]; l++) {
12521 getrlimit(l->cmd, &limit);
12522 out1fmt("%-20s ", lname);
12523 lname += strlen(lname) + 1;
12524 printlim(how, &limit, l);
12529 getrlimit(l->cmd, &limit);
12532 limit.rlim_max = val;
12534 limit.rlim_cur = val;
12535 if (setrlimit(l->cmd, &limit) < 0)
12536 ash_msg_and_raise_error("error setting limit (%m)");
12538 printlim(how, &limit, l);
12544 /* ============ Math support */
12546 #if ENABLE_ASH_MATH_SUPPORT
12548 /* Copyright (c) 2001 Aaron Lehmann <aaronl@vitelus.com>
12550 Permission is hereby granted, free of charge, to any person obtaining
12551 a copy of this software and associated documentation files (the
12552 "Software"), to deal in the Software without restriction, including
12553 without limitation the rights to use, copy, modify, merge, publish,
12554 distribute, sublicense, and/or sell copies of the Software, and to
12555 permit persons to whom the Software is furnished to do so, subject to
12556 the following conditions:
12558 The above copyright notice and this permission notice shall be
12559 included in all copies or substantial portions of the Software.
12561 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
12562 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
12563 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
12564 IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
12565 CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
12566 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
12567 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
12570 /* This is my infix parser/evaluator. It is optimized for size, intended
12571 * as a replacement for yacc-based parsers. However, it may well be faster
12572 * than a comparable parser written in yacc. The supported operators are
12573 * listed in #defines below. Parens, order of operations, and error handling
12574 * are supported. This code is thread safe. The exact expression format should
12575 * be that which POSIX specifies for shells. */
12577 /* The code uses a simple two-stack algorithm. See
12578 * http://www.onthenet.com.au/~grahamis/int2008/week02/lect02.html
12579 * for a detailed explanation of the infix-to-postfix algorithm on which
12580 * this is based (this code differs in that it applies operators immediately
12581 * to the stack instead of adding them to a queue to end up with an
12584 /* To use the routine, call it with an expression string and error return
12588 * Aug 24, 2001 Manuel Novoa III
12590 * Reduced the generated code size by about 30% (i386) and fixed several bugs.
12592 * 1) In arith_apply():
12593 * a) Cached values of *numptr and &(numptr[-1]).
12594 * b) Removed redundant test for zero denominator.
12597 * a) Eliminated redundant code for processing operator tokens by moving
12598 * to a table-based implementation. Also folded handling of parens
12600 * b) Combined all 3 loops which called arith_apply to reduce generated
12601 * code size at the cost of speed.
12603 * 3) The following expressions were treated as valid by the original code:
12604 * 1() , 0! , 1 ( *3 ) .
12605 * These bugs have been fixed by internally enclosing the expression in
12606 * parens and then checking that all binary ops and right parens are
12607 * preceded by a valid expression (NUM_TOKEN).
12609 * Note: It may be desirable to replace Aaron's test for whitespace with
12610 * ctype's isspace() if it is used by another busybox applet or if additional
12611 * whitespace chars should be considered. Look below the "#include"s for a
12612 * precompiler test.
12616 * Aug 26, 2001 Manuel Novoa III
12618 * Return 0 for null expressions. Pointed out by Vladimir Oleynik.
12620 * Merge in Aaron's comments previously posted to the busybox list,
12621 * modified slightly to take account of my changes to the code.
12626 * (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
12628 * - allow access to variable,
12629 * used recursive find value indirection (c=2*2; a="c"; $((a+=2)) produce 6)
12630 * - realize assign syntax (VAR=expr, +=, *= etc)
12631 * - realize exponentiation (** operator)
12632 * - realize comma separated - expr, expr
12633 * - realise ++expr --expr expr++ expr--
12634 * - realise expr ? expr : expr (but, second expr calculate always)
12635 * - allow hexadecimal and octal numbers
12636 * - was restored loses XOR operator
12637 * - remove one goto label, added three ;-)
12638 * - protect $((num num)) as true zero expr (Manuel`s error)
12639 * - always use special isspace(), see comment from bash ;-)
12642 #define arith_isspace(arithval) \
12643 (arithval == ' ' || arithval == '\n' || arithval == '\t')
12645 typedef unsigned char operator;
12647 /* An operator's token id is a bit of a bitfield. The lower 5 bits are the
12648 * precedence, and 3 high bits are an ID unique across operators of that
12649 * precedence. The ID portion is so that multiple operators can have the
12650 * same precedence, ensuring that the leftmost one is evaluated first.
12651 * Consider * and /. */
12653 #define tok_decl(prec,id) (((id)<<5)|(prec))
12654 #define PREC(op) ((op) & 0x1F)
12656 #define TOK_LPAREN tok_decl(0,0)
12658 #define TOK_COMMA tok_decl(1,0)
12660 #define TOK_ASSIGN tok_decl(2,0)
12661 #define TOK_AND_ASSIGN tok_decl(2,1)
12662 #define TOK_OR_ASSIGN tok_decl(2,2)
12663 #define TOK_XOR_ASSIGN tok_decl(2,3)
12664 #define TOK_PLUS_ASSIGN tok_decl(2,4)
12665 #define TOK_MINUS_ASSIGN tok_decl(2,5)
12666 #define TOK_LSHIFT_ASSIGN tok_decl(2,6)
12667 #define TOK_RSHIFT_ASSIGN tok_decl(2,7)
12669 #define TOK_MUL_ASSIGN tok_decl(3,0)
12670 #define TOK_DIV_ASSIGN tok_decl(3,1)
12671 #define TOK_REM_ASSIGN tok_decl(3,2)
12673 /* all assign is right associativity and precedence eq, but (7+3)<<5 > 256 */
12674 #define convert_prec_is_assing(prec) do { if (prec == 3) prec = 2; } while (0)
12676 /* conditional is right associativity too */
12677 #define TOK_CONDITIONAL tok_decl(4,0)
12678 #define TOK_CONDITIONAL_SEP tok_decl(4,1)
12680 #define TOK_OR tok_decl(5,0)
12682 #define TOK_AND tok_decl(6,0)
12684 #define TOK_BOR tok_decl(7,0)
12686 #define TOK_BXOR tok_decl(8,0)
12688 #define TOK_BAND tok_decl(9,0)
12690 #define TOK_EQ tok_decl(10,0)
12691 #define TOK_NE tok_decl(10,1)
12693 #define TOK_LT tok_decl(11,0)
12694 #define TOK_GT tok_decl(11,1)
12695 #define TOK_GE tok_decl(11,2)
12696 #define TOK_LE tok_decl(11,3)
12698 #define TOK_LSHIFT tok_decl(12,0)
12699 #define TOK_RSHIFT tok_decl(12,1)
12701 #define TOK_ADD tok_decl(13,0)
12702 #define TOK_SUB tok_decl(13,1)
12704 #define TOK_MUL tok_decl(14,0)
12705 #define TOK_DIV tok_decl(14,1)
12706 #define TOK_REM tok_decl(14,2)
12708 /* exponent is right associativity */
12709 #define TOK_EXPONENT tok_decl(15,1)
12711 /* For now unary operators. */
12712 #define UNARYPREC 16
12713 #define TOK_BNOT tok_decl(UNARYPREC,0)
12714 #define TOK_NOT tok_decl(UNARYPREC,1)
12716 #define TOK_UMINUS tok_decl(UNARYPREC+1,0)
12717 #define TOK_UPLUS tok_decl(UNARYPREC+1,1)
12719 #define PREC_PRE (UNARYPREC+2)
12721 #define TOK_PRE_INC tok_decl(PREC_PRE, 0)
12722 #define TOK_PRE_DEC tok_decl(PREC_PRE, 1)
12724 #define PREC_POST (UNARYPREC+3)
12726 #define TOK_POST_INC tok_decl(PREC_POST, 0)
12727 #define TOK_POST_DEC tok_decl(PREC_POST, 1)
12729 #define SPEC_PREC (UNARYPREC+4)
12731 #define TOK_NUM tok_decl(SPEC_PREC, 0)
12732 #define TOK_RPAREN tok_decl(SPEC_PREC, 1)
12734 #define NUMPTR (*numstackptr)
12737 tok_have_assign(operator op)
12739 operator prec = PREC(op);
12741 convert_prec_is_assing(prec);
12742 return (prec == PREC(TOK_ASSIGN) ||
12743 prec == PREC_PRE || prec == PREC_POST);
12747 is_right_associativity(operator prec)
12749 return (prec == PREC(TOK_ASSIGN) || prec == PREC(TOK_EXPONENT)
12750 || prec == PREC(TOK_CONDITIONAL));
12755 arith_t contidional_second_val;
12756 char contidional_second_val_initialized;
12757 char *var; /* if NULL then is regular number,
12758 else is variable name */
12761 typedef struct chk_var_recursive_looped_t {
12763 struct chk_var_recursive_looped_t *next;
12764 } chk_var_recursive_looped_t;
12766 static chk_var_recursive_looped_t *prev_chk_var_recursive;
12769 arith_lookup_val(v_n_t *t)
12772 const char * p = lookupvar(t->var);
12777 /* recursive try as expression */
12778 chk_var_recursive_looped_t *cur;
12779 chk_var_recursive_looped_t cur_save;
12781 for (cur = prev_chk_var_recursive; cur; cur = cur->next) {
12782 if (strcmp(cur->var, t->var) == 0) {
12783 /* expression recursion loop detected */
12787 /* save current lookuped var name */
12788 cur = prev_chk_var_recursive;
12789 cur_save.var = t->var;
12790 cur_save.next = cur;
12791 prev_chk_var_recursive = &cur_save;
12793 t->val = arith (p, &errcode);
12794 /* restore previous ptr after recursiving */
12795 prev_chk_var_recursive = cur;
12798 /* allow undefined var as 0 */
12804 /* "applying" a token means performing it on the top elements on the integer
12805 * stack. For a unary operator it will only change the top element, but a
12806 * binary operator will pop two arguments and push a result */
12808 arith_apply(operator op, v_n_t *numstack, v_n_t **numstackptr)
12811 arith_t numptr_val, rez;
12812 int ret_arith_lookup_val;
12814 /* There is no operator that can work without arguments */
12815 if (NUMPTR == numstack) goto err;
12816 numptr_m1 = NUMPTR - 1;
12818 /* check operand is var with noninteger value */
12819 ret_arith_lookup_val = arith_lookup_val(numptr_m1);
12820 if (ret_arith_lookup_val)
12821 return ret_arith_lookup_val;
12823 rez = numptr_m1->val;
12824 if (op == TOK_UMINUS)
12826 else if (op == TOK_NOT)
12828 else if (op == TOK_BNOT)
12830 else if (op == TOK_POST_INC || op == TOK_PRE_INC)
12832 else if (op == TOK_POST_DEC || op == TOK_PRE_DEC)
12834 else if (op != TOK_UPLUS) {
12835 /* Binary operators */
12837 /* check and binary operators need two arguments */
12838 if (numptr_m1 == numstack) goto err;
12840 /* ... and they pop one */
12843 if (op == TOK_CONDITIONAL) {
12844 if (! numptr_m1->contidional_second_val_initialized) {
12845 /* protect $((expr1 ? expr2)) without ": expr" */
12848 rez = numptr_m1->contidional_second_val;
12849 } else if (numptr_m1->contidional_second_val_initialized) {
12850 /* protect $((expr1 : expr2)) without "expr ? " */
12853 numptr_m1 = NUMPTR - 1;
12854 if (op != TOK_ASSIGN) {
12855 /* check operand is var with noninteger value for not '=' */
12856 ret_arith_lookup_val = arith_lookup_val(numptr_m1);
12857 if (ret_arith_lookup_val)
12858 return ret_arith_lookup_val;
12860 if (op == TOK_CONDITIONAL) {
12861 numptr_m1->contidional_second_val = rez;
12863 rez = numptr_m1->val;
12864 if (op == TOK_BOR || op == TOK_OR_ASSIGN)
12866 else if (op == TOK_OR)
12867 rez = numptr_val || rez;
12868 else if (op == TOK_BAND || op == TOK_AND_ASSIGN)
12870 else if (op == TOK_BXOR || op == TOK_XOR_ASSIGN)
12872 else if (op == TOK_AND)
12873 rez = rez && numptr_val;
12874 else if (op == TOK_EQ)
12875 rez = (rez == numptr_val);
12876 else if (op == TOK_NE)
12877 rez = (rez != numptr_val);
12878 else if (op == TOK_GE)
12879 rez = (rez >= numptr_val);
12880 else if (op == TOK_RSHIFT || op == TOK_RSHIFT_ASSIGN)
12881 rez >>= numptr_val;
12882 else if (op == TOK_LSHIFT || op == TOK_LSHIFT_ASSIGN)
12883 rez <<= numptr_val;
12884 else if (op == TOK_GT)
12885 rez = (rez > numptr_val);
12886 else if (op == TOK_LT)
12887 rez = (rez < numptr_val);
12888 else if (op == TOK_LE)
12889 rez = (rez <= numptr_val);
12890 else if (op == TOK_MUL || op == TOK_MUL_ASSIGN)
12892 else if (op == TOK_ADD || op == TOK_PLUS_ASSIGN)
12894 else if (op == TOK_SUB || op == TOK_MINUS_ASSIGN)
12896 else if (op == TOK_ASSIGN || op == TOK_COMMA)
12898 else if (op == TOK_CONDITIONAL_SEP) {
12899 if (numptr_m1 == numstack) {
12900 /* protect $((expr : expr)) without "expr ? " */
12903 numptr_m1->contidional_second_val_initialized = op;
12904 numptr_m1->contidional_second_val = numptr_val;
12905 } else if (op == TOK_CONDITIONAL) {
12907 numptr_val : numptr_m1->contidional_second_val;
12908 } else if (op == TOK_EXPONENT) {
12909 if (numptr_val < 0)
12910 return -3; /* exponent less than 0 */
12915 while (numptr_val--)
12919 } else if (numptr_val==0) /* zero divisor check */
12921 else if (op == TOK_DIV || op == TOK_DIV_ASSIGN)
12923 else if (op == TOK_REM || op == TOK_REM_ASSIGN)
12926 if (tok_have_assign(op)) {
12927 char buf[sizeof(arith_t_type)*3 + 2];
12929 if (numptr_m1->var == NULL) {
12933 /* save to shell variable */
12934 #if ENABLE_ASH_MATH_SUPPORT_64
12935 snprintf(buf, sizeof(buf), "%lld", (arith_t_type) rez);
12937 snprintf(buf, sizeof(buf), "%ld", (arith_t_type) rez);
12939 setvar(numptr_m1->var, buf, 0);
12940 /* after saving, make previous value for v++ or v-- */
12941 if (op == TOK_POST_INC)
12943 else if (op == TOK_POST_DEC)
12946 numptr_m1->val = rez;
12947 /* protect geting var value, is number now */
12948 numptr_m1->var = NULL;
12954 /* longest must be first */
12955 static const char op_tokens[] ALIGN1 = {
12956 '<','<','=',0, TOK_LSHIFT_ASSIGN,
12957 '>','>','=',0, TOK_RSHIFT_ASSIGN,
12958 '<','<', 0, TOK_LSHIFT,
12959 '>','>', 0, TOK_RSHIFT,
12960 '|','|', 0, TOK_OR,
12961 '&','&', 0, TOK_AND,
12962 '!','=', 0, TOK_NE,
12963 '<','=', 0, TOK_LE,
12964 '>','=', 0, TOK_GE,
12965 '=','=', 0, TOK_EQ,
12966 '|','=', 0, TOK_OR_ASSIGN,
12967 '&','=', 0, TOK_AND_ASSIGN,
12968 '*','=', 0, TOK_MUL_ASSIGN,
12969 '/','=', 0, TOK_DIV_ASSIGN,
12970 '%','=', 0, TOK_REM_ASSIGN,
12971 '+','=', 0, TOK_PLUS_ASSIGN,
12972 '-','=', 0, TOK_MINUS_ASSIGN,
12973 '-','-', 0, TOK_POST_DEC,
12974 '^','=', 0, TOK_XOR_ASSIGN,
12975 '+','+', 0, TOK_POST_INC,
12976 '*','*', 0, TOK_EXPONENT,
12980 '=', 0, TOK_ASSIGN,
12992 '?', 0, TOK_CONDITIONAL,
12993 ':', 0, TOK_CONDITIONAL_SEP,
12994 ')', 0, TOK_RPAREN,
12995 '(', 0, TOK_LPAREN,
12999 #define endexpression (&op_tokens[sizeof(op_tokens)-7])
13002 arith(const char *expr, int *perrcode)
13004 char arithval; /* Current character under analysis */
13005 operator lasttok, op;
13007 operator *stack, *stackptr;
13008 const char *p = endexpression;
13010 v_n_t *numstack, *numstackptr;
13011 unsigned datasizes = strlen(expr) + 2;
13013 /* Stack of integers */
13014 /* The proof that there can be no more than strlen(startbuf)/2+1 integers
13015 * in any given correct or incorrect expression is left as an exercise to
13017 numstackptr = numstack = alloca((datasizes / 2) * sizeof(numstack[0]));
13018 /* Stack of operator tokens */
13019 stackptr = stack = alloca(datasizes * sizeof(stack[0]));
13021 *stackptr++ = lasttok = TOK_LPAREN; /* start off with a left paren */
13022 *perrcode = errcode = 0;
13026 if (arithval == 0) {
13027 if (p == endexpression) {
13028 /* Null expression. */
13032 /* This is only reached after all tokens have been extracted from the
13033 * input stream. If there are still tokens on the operator stack, they
13034 * are to be applied in order. At the end, there should be a final
13035 * result on the integer stack */
13037 if (expr != endexpression + 1) {
13038 /* If we haven't done so already, */
13039 /* append a closing right paren */
13040 expr = endexpression;
13041 /* and let the loop process it. */
13044 /* At this point, we're done with the expression. */
13045 if (numstackptr != numstack+1) {
13046 /* ... but if there isn't, it's bad */
13051 if (numstack->var) {
13052 /* expression is $((var)) only, lookup now */
13053 errcode = arith_lookup_val(numstack);
13056 *perrcode = errcode;
13057 return numstack->val;
13060 /* Continue processing the expression. */
13061 if (arith_isspace(arithval)) {
13062 /* Skip whitespace */
13065 p = endofname(expr);
13067 size_t var_name_size = (p-expr) + 1; /* trailing zero */
13069 numstackptr->var = alloca(var_name_size);
13070 safe_strncpy(numstackptr->var, expr, var_name_size);
13073 numstackptr->contidional_second_val_initialized = 0;
13078 if (isdigit(arithval)) {
13079 numstackptr->var = NULL;
13080 #if ENABLE_ASH_MATH_SUPPORT_64
13081 numstackptr->val = strtoll(expr, (char **) &expr, 0);
13083 numstackptr->val = strtol(expr, (char **) &expr, 0);
13087 for (p = op_tokens; ; p++) {
13091 /* strange operator not found */
13094 for (o = expr; *p && *o == *p; p++)
13101 /* skip tail uncompared token */
13104 /* skip zero delim */
13109 /* post grammar: a++ reduce to num */
13110 if (lasttok == TOK_POST_INC || lasttok == TOK_POST_DEC)
13113 /* Plus and minus are binary (not unary) _only_ if the last
13114 * token was as number, or a right paren (which pretends to be
13115 * a number, since it evaluates to one). Think about it.
13116 * It makes sense. */
13117 if (lasttok != TOK_NUM) {
13133 /* We don't want a unary operator to cause recursive descent on the
13134 * stack, because there can be many in a row and it could cause an
13135 * operator to be evaluated before its argument is pushed onto the
13136 * integer stack. */
13137 /* But for binary operators, "apply" everything on the operator
13138 * stack until we find an operator with a lesser priority than the
13139 * one we have just extracted. */
13140 /* Left paren is given the lowest priority so it will never be
13141 * "applied" in this way.
13142 * if associativity is right and priority eq, applied also skip
13145 if ((prec > 0 && prec < UNARYPREC) || prec == SPEC_PREC) {
13146 /* not left paren or unary */
13147 if (lasttok != TOK_NUM) {
13148 /* binary op must be preceded by a num */
13151 while (stackptr != stack) {
13152 if (op == TOK_RPAREN) {
13153 /* The algorithm employed here is simple: while we don't
13154 * hit an open paren nor the bottom of the stack, pop
13155 * tokens and apply them */
13156 if (stackptr[-1] == TOK_LPAREN) {
13158 /* Any operator directly after a */
13160 /* close paren should consider itself binary */
13164 operator prev_prec = PREC(stackptr[-1]);
13166 convert_prec_is_assing(prec);
13167 convert_prec_is_assing(prev_prec);
13168 if (prev_prec < prec)
13170 /* check right assoc */
13171 if (prev_prec == prec && is_right_associativity(prec))
13174 errcode = arith_apply(*--stackptr, numstack, &numstackptr);
13175 if (errcode) goto ret;
13177 if (op == TOK_RPAREN) {
13182 /* Push this operator to the stack and remember it. */
13183 *stackptr++ = lasttok = op;
13188 #endif /* ASH_MATH_SUPPORT */
13191 /* ============ main() and helpers */
13194 * Called to exit the shell.
13196 static void exitshell(void) ATTRIBUTE_NORETURN;
13204 status = exitstatus;
13205 TRACE(("pid %d, exitshell(%d)\n", getpid(), status));
13206 if (setjmp(loc.loc)) {
13207 if (exception == EXEXIT)
13208 /* dash bug: it just does _exit(exitstatus) here
13209 * but we have to do setjobctl(0) first!
13210 * (bug is still not fixed in dash-0.5.3 - if you run dash
13211 * under Midnight Commander, on exit from dash MC is backgrounded) */
13212 status = exitstatus;
13215 exception_handler = &loc;
13221 flush_stdout_stderr();
13231 /* from input.c: */
13232 basepf.nextc = basepf.buf = basebuf;
13235 signal(SIGCHLD, SIG_DFL);
13240 char ppid[sizeof(int)*3 + 1];
13242 struct stat st1, st2;
13245 for (envp = environ; envp && *envp; envp++) {
13246 if (strchr(*envp, '=')) {
13247 setvareq(*envp, VEXPORT|VTEXTFIXED);
13251 snprintf(ppid, sizeof(ppid), "%u", (unsigned) getppid());
13252 setvar("PPID", ppid, 0);
13254 p = lookupvar("PWD");
13256 if (*p != '/' || stat(p, &st1) || stat(".", &st2)
13257 || st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino)
13264 * Process the shell command line arguments.
13267 procargs(char **argv)
13270 const char *xminusc;
13275 /* if (xargv[0]) - mmm, this is always true! */
13277 for (i = 0; i < NOPTS; i++)
13281 /* it already printed err message */
13282 raise_exception(EXERROR);
13286 if (*xargv == NULL) {
13288 ash_msg_and_raise_error(bb_msg_requires_arg, "-c");
13291 if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
13295 for (i = 0; i < NOPTS; i++)
13296 if (optlist[i] == 2)
13301 /* POSIX 1003.2: first arg after -c cmd is $0, remainder $1... */
13306 } else if (!sflag) {
13307 setinputfile(*xargv, 0);
13310 commandname = arg0;
13313 shellparam.p = xargv;
13314 #if ENABLE_ASH_GETOPTS
13315 shellparam.optind = 1;
13316 shellparam.optoff = -1;
13318 /* assert(shellparam.malloced == 0 && shellparam.nparam == 0); */
13320 shellparam.nparam++;
13327 * Read /etc/profile or .profile.
13330 read_profile(const char *name)
13334 if (setinputfile(name, INPUT_PUSH_FILE | INPUT_NOFILE_OK) < 0)
13343 * This routine is called when an error or an interrupt occurs in an
13344 * interactive shell and control is returned to the main command loop.
13352 /* from input.c: */
13353 parselleft = parsenleft = 0; /* clear input buffer */
13355 /* from parser.c: */
13358 /* from redir.c: */
13363 static short profile_buf[16384];
13364 extern int etext();
13368 * Main routine. We initialize things, parse the arguments, execute
13369 * profiles if we're a login shell, and then call cmdloop to execute
13370 * commands. The setjmp call sets up the location to jump to when an
13371 * exception occurs. When an exception occurs the variable "state"
13372 * is used to figure out how far we had gotten.
13374 int ash_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
13375 int ash_main(int argc ATTRIBUTE_UNUSED, char **argv)
13378 volatile int state;
13379 struct jmploc jmploc;
13380 struct stackmark smark;
13382 /* Initialize global data */
13386 #if ENABLE_ASH_ALIAS
13392 monitor(4, etext, profile_buf, sizeof(profile_buf), 50);
13395 #if ENABLE_FEATURE_EDITING
13396 line_input_state = new_line_input_t(FOR_SHELL | WITH_PATH_LOOKUP);
13399 if (setjmp(jmploc.loc)) {
13409 if (e == EXEXIT || s == 0 || iflag == 0 || shlvl)
13413 outcslow('\n', stderr);
13415 popstackmark(&smark);
13416 FORCE_INT_ON; /* enable interrupts */
13425 exception_handler = &jmploc;
13428 trace_puts("Shell args: ");
13429 trace_puts_args(argv);
13431 rootpid = getpid();
13433 #if ENABLE_ASH_RANDOM_SUPPORT
13434 random_galois_LFSR = random_LCG = rootpid + time(NULL);
13437 setstackmark(&smark);
13440 #if ENABLE_FEATURE_EDITING_SAVEHISTORY
13442 const char *hp = lookupvar("HISTFILE");
13445 hp = lookupvar("HOME");
13447 char *defhp = concat_path_file(hp, ".ash_history");
13448 setvar("HISTFILE", defhp, 0);
13454 if (argv[0] && argv[0][0] == '-')
13458 read_profile("/etc/profile");
13461 read_profile(".profile");
13467 getuid() == geteuid() && getgid() == getegid() &&
13471 shinit = lookupvar("ENV");
13472 if (shinit != NULL && *shinit != '\0') {
13473 read_profile(shinit);
13479 evalstring(minusc, 0);
13481 if (sflag || minusc == NULL) {
13482 #if ENABLE_FEATURE_EDITING_SAVEHISTORY
13484 const char *hp = lookupvar("HISTFILE");
13487 line_input_state->hist_file = hp;
13490 state4: /* XXX ??? - why isn't this before the "if" statement */
13498 extern void _mcleanup(void);
13507 const char *applet_name = "debug stuff usage";
13508 int main(int argc, char **argv)
13510 return ash_main(argc, argv);
13516 * Copyright (c) 1989, 1991, 1993, 1994
13517 * The Regents of the University of California. All rights reserved.
13519 * This code is derived from software contributed to Berkeley by
13520 * Kenneth Almquist.
13522 * Redistribution and use in source and binary forms, with or without
13523 * modification, are permitted provided that the following conditions
13525 * 1. Redistributions of source code must retain the above copyright
13526 * notice, this list of conditions and the following disclaimer.
13527 * 2. Redistributions in binary form must reproduce the above copyright
13528 * notice, this list of conditions and the following disclaimer in the
13529 * documentation and/or other materials provided with the distribution.
13530 * 3. Neither the name of the University nor the names of its contributors
13531 * may be used to endorse or promote products derived from this software
13532 * without specific prior written permission.
13534 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
13535 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
13536 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
13537 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
13538 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
13539 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
13540 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
13541 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
13542 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
13543 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF