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
66 #define PIPE_BUF 4096 /* amount of buffering in a pipe */
69 #if defined(__uClinux__)
70 #error "Do not even bother, ash will not run on uClinux"
74 /* ============ Hash table sizes. Configurable. */
78 #define CMDTABLESIZE 31 /* should be prime */
81 /* ============ Misc helpers */
83 #define xbarrier() do { __asm__ __volatile__ ("": : :"memory"); } while (0)
85 /* C99 say: "char" declaration may be signed or unsigned default */
86 #define signed_char2int(sc) ((int)((signed char)sc))
89 /* ============ Shell options */
91 static const char *const optletters_optnames[] = {
112 #define optletters(n) optletters_optnames[(n)][0]
113 #define optnames(n) (&optletters_optnames[(n)][1])
115 enum { NOPTS = ARRAY_SIZE(optletters_optnames) };
118 /* ============ Misc data */
120 static const char homestr[] ALIGN1 = "HOME";
121 static const char snlfmt[] ALIGN1 = "%s\n";
122 static const char illnum[] ALIGN1 = "Illegal number: %s";
125 * We enclose jmp_buf in a structure so that we can declare pointers to
126 * jump locations. The global variable handler contains the location to
127 * jump to when an exception occurs, and the global variable exception
128 * contains a code identifying the exception. To implement nested
129 * exception handlers, the user should save the value of handler on entry
130 * to an inner scope, set handler to point to a jmploc structure for the
131 * inner scope, and restore handler on exit from the scope.
137 struct globals_misc {
138 /* pid of main shell */
140 /* shell level: 0 for the main shell, 1 for its children, and so on */
142 #define rootshell (!shlvl)
143 char *minusc; /* argument to -c option */
145 char *curdir; // = nullstr; /* current working directory */
146 char *physdir; // = nullstr; /* physical working directory */
148 char *arg0; /* value of $0 */
150 struct jmploc *exception_handler;
152 // disabled by vda: cannot understand how it was supposed to work -
153 // cannot fix bugs. That's why you have to explain your non-trivial designs!
154 // /* do we generate EXSIG events */
155 // int exsig; /* counter */
156 volatile int suppressint; /* counter */
157 volatile /*sig_atomic_t*/ smallint intpending; /* 1 = got SIGINT */
158 /* last pending signal */
159 volatile /*sig_atomic_t*/ smallint pendingsig;
160 smallint exception; /* kind of exception (0..5) */
162 #define EXINT 0 /* SIGINT received */
163 #define EXERROR 1 /* a generic error */
164 #define EXSHELLPROC 2 /* execute a shell procedure */
165 #define EXEXEC 3 /* command execution failed */
166 #define EXEXIT 4 /* exit the shell */
167 #define EXSIG 5 /* trapped signal in wait(1) */
170 char nullstr[1]; /* zero length string */
173 #define eflag optlist[0]
174 #define fflag optlist[1]
175 #define Iflag optlist[2]
176 #define iflag optlist[3]
177 #define mflag optlist[4]
178 #define nflag optlist[5]
179 #define sflag optlist[6]
180 #define xflag optlist[7]
181 #define vflag optlist[8]
182 #define Cflag optlist[9]
183 #define aflag optlist[10]
184 #define bflag optlist[11]
185 #define uflag optlist[12]
186 #define viflag optlist[13]
188 #define nolog optlist[14]
189 #define debug optlist[15]
192 /* trap handler commands */
194 * Sigmode records the current value of the signal handlers for the various
195 * modes. A value of zero means that the current handler is not known.
196 * S_HARD_IGN indicates that the signal was ignored on entry to the shell,
198 char sigmode[NSIG - 1];
199 #define S_DFL 1 /* default signal handling (SIG_DFL) */
200 #define S_CATCH 2 /* signal is caught */
201 #define S_IGN 3 /* signal is ignored (SIG_IGN) */
202 #define S_HARD_IGN 4 /* signal is ignored permenantly */
203 #define S_RESET 5 /* temporary - to reset a hard ignored sig */
205 /* indicates specified signal received */
206 char gotsig[NSIG - 1]; /* offset by 1: "signal" 0 is meaningless */
209 /* Rarely referenced stuff */
210 #if ENABLE_ASH_RANDOM_SUPPORT
211 /* Random number generators */
212 int32_t random_galois_LFSR; /* Galois LFSR (fast but weak). signed! */
213 uint32_t random_LCG; /* LCG (fast but weak) */
215 pid_t backgndpid; /* pid of last background process */
216 smallint job_warning; /* user was warned about stopped jobs (can be 2, 1 or 0). */
218 extern struct globals_misc *const ash_ptr_to_globals_misc;
219 #define G_misc (*ash_ptr_to_globals_misc)
220 #define rootpid (G_misc.rootpid )
221 #define shlvl (G_misc.shlvl )
222 #define minusc (G_misc.minusc )
223 #define curdir (G_misc.curdir )
224 #define physdir (G_misc.physdir )
225 #define arg0 (G_misc.arg0 )
226 #define exception_handler (G_misc.exception_handler)
227 #define exception (G_misc.exception )
228 #define suppressint (G_misc.suppressint )
229 #define intpending (G_misc.intpending )
230 //#define exsig (G_misc.exsig )
231 #define pendingsig (G_misc.pendingsig )
232 #define isloginsh (G_misc.isloginsh )
233 #define nullstr (G_misc.nullstr )
234 #define optlist (G_misc.optlist )
235 #define sigmode (G_misc.sigmode )
236 #define gotsig (G_misc.gotsig )
237 #define trap (G_misc.trap )
238 #define random_galois_LFSR (G_misc.random_galois_LFSR)
239 #define random_LCG (G_misc.random_LCG )
240 #define backgndpid (G_misc.backgndpid )
241 #define job_warning (G_misc.job_warning)
242 #define INIT_G_misc() do { \
243 (*(struct globals_misc**)&ash_ptr_to_globals_misc) = xzalloc(sizeof(G_misc)); \
250 /* ============ Interrupts / exceptions */
253 * These macros allow the user to suspend the handling of interrupt signals
254 * over a period of time. This is similar to SIGHOLD or to sigblock, but
255 * much more efficient and portable. (But hacking the kernel is so much
256 * more fun than worrying about efficiency and portability. :-))
258 #define INT_OFF do { \
264 * Called to raise an exception. Since C doesn't include exceptions, we
265 * just do a longjmp to the exception handler. The type of exception is
266 * stored in the global variable "exception".
268 static void raise_exception(int) NORETURN;
270 raise_exception(int e)
273 if (exception_handler == NULL)
278 longjmp(exception_handler->loc, 1);
282 * Called from trap.c when a SIGINT is received. (If the user specifies
283 * that SIGINT is to be trapped or ignored using the trap builtin, then
284 * this routine is not called.) Suppressint is nonzero when interrupts
285 * are held using the INT_OFF macro. (The test for iflag is just
286 * defensive programming.)
288 static void raise_interrupt(void) NORETURN;
290 raise_interrupt(void)
295 /* Signal is not automatically unmasked after it is raised,
296 * do it ourself - unmask all signals */
297 sigprocmask_allsigs(SIG_UNBLOCK);
298 /* pendingsig = 0; - now done in onsig() */
301 if (gotsig[SIGINT - 1] && !trap[SIGINT]) {
302 if (!(rootshell && iflag)) {
303 /* Kill ourself with SIGINT */
304 signal(SIGINT, SIG_DFL);
313 #if ENABLE_ASH_OPTIMIZE_FOR_SIZE
317 if (--suppressint == 0 && intpending) {
321 #define INT_ON int_on()
329 #define FORCE_INT_ON force_int_on()
331 #define INT_ON do { \
333 if (--suppressint == 0 && intpending) \
336 #define FORCE_INT_ON do { \
342 #endif /* ASH_OPTIMIZE_FOR_SIZE */
344 #define SAVE_INT(v) ((v) = suppressint)
346 #define RESTORE_INT(v) do { \
349 if (suppressint == 0 && intpending) \
354 * Ignore a signal. Only one usage site - in forkchild()
359 if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) {
360 signal(signo, SIG_IGN);
362 sigmode[signo - 1] = S_HARD_IGN;
366 * Signal handler. Only one usage site - in setsignal()
371 gotsig[signo - 1] = 1;
374 if (/* exsig || */ (signo == SIGINT && !trap[SIGINT])) {
377 raise_interrupt(); /* does not return */
384 /* ============ Stdout/stderr output */
387 outstr(const char *p, FILE *file)
395 flush_stdout_stderr(void)
412 outcslow(int c, FILE *dest)
420 static int out1fmt(const char *, ...) __attribute__((__format__(__printf__,1,2)));
422 out1fmt(const char *fmt, ...)
429 r = vprintf(fmt, ap);
435 static int fmtstr(char *, size_t, const char *, ...) __attribute__((__format__(__printf__,3,4)));
437 fmtstr(char *outbuf, size_t length, const char *fmt, ...)
444 ret = vsnprintf(outbuf, length, fmt, ap);
451 out1str(const char *p)
457 out2str(const char *p)
464 /* ============ Parser structures */
466 /* control characters in argument strings */
467 #define CTLESC '\201' /* escape next character */
468 #define CTLVAR '\202' /* variable defn */
469 #define CTLENDVAR '\203'
470 #define CTLBACKQ '\204'
471 #define CTLQUOTE 01 /* ored with CTLBACKQ code if in quotes */
472 /* CTLBACKQ | CTLQUOTE == '\205' */
473 #define CTLARI '\206' /* arithmetic expression */
474 #define CTLENDARI '\207'
475 #define CTLQUOTEMARK '\210'
477 /* variable substitution byte (follows CTLVAR) */
478 #define VSTYPE 0x0f /* type of variable substitution */
479 #define VSNUL 0x10 /* colon--treat the empty string as unset */
480 #define VSQUOTE 0x80 /* inside double quotes--suppress splitting */
482 /* values of VSTYPE field */
483 #define VSNORMAL 0x1 /* normal variable: $var or ${var} */
484 #define VSMINUS 0x2 /* ${var-text} */
485 #define VSPLUS 0x3 /* ${var+text} */
486 #define VSQUESTION 0x4 /* ${var?message} */
487 #define VSASSIGN 0x5 /* ${var=text} */
488 #define VSTRIMRIGHT 0x6 /* ${var%pattern} */
489 #define VSTRIMRIGHTMAX 0x7 /* ${var%%pattern} */
490 #define VSTRIMLEFT 0x8 /* ${var#pattern} */
491 #define VSTRIMLEFTMAX 0x9 /* ${var##pattern} */
492 #define VSLENGTH 0xa /* ${#var} */
493 #if ENABLE_ASH_BASH_COMPAT
494 #define VSSUBSTR 0xc /* ${var:position:length} */
495 #define VSREPLACE 0xd /* ${var/pattern/replacement} */
496 #define VSREPLACEALL 0xe /* ${var//pattern/replacement} */
499 static const char dolatstr[] ALIGN1 = {
500 CTLVAR, VSNORMAL|VSQUOTE, '@', '=', '\0'
533 smallint type; /* Nxxxx */
536 union node *redirect;
541 smallint pipe_backgnd;
542 struct nodelist *cmdlist;
548 union node *redirect;
561 union node *elsepart;
588 struct nodelist *backquote;
601 union node *next; /* must match nfile's layout */
602 int fd; /* must match nfile's layout */
623 struct nredir nredir;
624 struct nbinary nbinary;
628 struct nclist nclist;
637 struct nodelist *next;
650 freefunc(struct funcnode *f)
652 if (f && --f->count < 0)
657 /* ============ Debugging output */
661 static FILE *tracefile;
664 trace_printf(const char *fmt, ...)
671 vfprintf(tracefile, fmt, va);
676 trace_vprintf(const char *fmt, va_list va)
680 vfprintf(tracefile, fmt, va);
684 trace_puts(const char *s)
692 trace_puts_quoted(char *s)
699 putc('"', tracefile);
700 for (p = s; *p; p++) {
702 case '\n': c = 'n'; goto backslash;
703 case '\t': c = 't'; goto backslash;
704 case '\r': c = 'r'; goto backslash;
705 case '"': c = '"'; goto backslash;
706 case '\\': c = '\\'; goto backslash;
707 case CTLESC: c = 'e'; goto backslash;
708 case CTLVAR: c = 'v'; goto backslash;
709 case CTLVAR+CTLQUOTE: c = 'V'; goto backslash;
710 case CTLBACKQ: c = 'q'; goto backslash;
711 case CTLBACKQ+CTLQUOTE: c = 'Q'; goto backslash;
713 putc('\\', tracefile);
717 if (*p >= ' ' && *p <= '~')
720 putc('\\', tracefile);
721 putc(*p >> 6 & 03, tracefile);
722 putc(*p >> 3 & 07, tracefile);
723 putc(*p & 07, tracefile);
728 putc('"', tracefile);
732 trace_puts_args(char **ap)
739 trace_puts_quoted(*ap);
741 putc('\n', tracefile);
744 putc(' ', tracefile);
759 /* leave open because libedit might be using it */
762 strcpy(s, "./trace");
764 if (!freopen(s, "a", tracefile)) {
765 fprintf(stderr, "Can't re-open %s\n", s);
770 tracefile = fopen(s, "a");
771 if (tracefile == NULL) {
772 fprintf(stderr, "Can't open %s\n", s);
778 flags = fcntl(fileno(tracefile), F_GETFL);
780 fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND);
782 setlinebuf(tracefile);
783 fputs("\nTracing started.\n", tracefile);
787 indent(int amount, char *pfx, FILE *fp)
791 for (i = 0; i < amount; i++) {
792 if (pfx && i == amount - 1)
798 /* little circular references here... */
799 static void shtree(union node *n, int ind, char *pfx, FILE *fp);
802 sharg(union node *arg, FILE *fp)
805 struct nodelist *bqlist;
808 if (arg->type != NARG) {
809 out1fmt("<node type %d>\n", arg->type);
812 bqlist = arg->narg.backquote;
813 for (p = arg->narg.text; *p; p++) {
822 if (subtype == VSLENGTH)
831 switch (subtype & VSTYPE) {
864 out1fmt("<subtype %d>", subtype);
871 case CTLBACKQ|CTLQUOTE:
874 shtree(bqlist->n, -1, NULL, fp);
885 shcmd(union node *cmd, FILE *fp)
893 for (np = cmd->ncmd.args; np; np = np->narg.next) {
899 for (np = cmd->ncmd.redirect; np; np = np->nfile.next) {
903 switch (np->nfile.type) {
904 case NTO: s = ">>"+1; dftfd = 1; break;
905 case NCLOBBER: s = ">|"; dftfd = 1; break;
906 case NAPPEND: s = ">>"; dftfd = 1; break;
907 case NTOFD: s = ">&"; dftfd = 1; break;
908 case NFROM: s = "<"; break;
909 case NFROMFD: s = "<&"; break;
910 case NFROMTO: s = "<>"; break;
911 default: s = "*error*"; break;
913 if (np->nfile.fd != dftfd)
914 fprintf(fp, "%d", np->nfile.fd);
916 if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) {
917 fprintf(fp, "%d", np->ndup.dupfd);
919 sharg(np->nfile.fname, fp);
926 shtree(union node *n, int ind, char *pfx, FILE *fp)
934 indent(ind, pfx, fp);
945 shtree(n->nbinary.ch1, ind, NULL, fp);
948 shtree(n->nbinary.ch2, ind, NULL, fp);
956 for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
961 if (n->npipe.pipe_backgnd)
967 fprintf(fp, "<node type %d>", n->type);
975 showtree(union node *n)
977 trace_puts("showtree called\n");
978 shtree(n, 1, NULL, stdout);
981 #define TRACE(param) trace_printf param
982 #define TRACEV(param) trace_vprintf param
987 #define TRACEV(param)
992 /* ============ Parser data */
995 * ash_vmsg() needs parsefile->fd, hence parsefile definition is moved up.
998 struct strlist *next;
1005 struct strpush *prev; /* preceding string on stack */
1008 #if ENABLE_ASH_ALIAS
1009 struct alias *ap; /* if push was associated with an alias */
1011 char *string; /* remember the string since it may change */
1015 struct parsefile *prev; /* preceding file on stack */
1016 int linno; /* current line */
1017 int fd; /* file descriptor (or -1 if string) */
1018 int nleft; /* number of chars left in this line */
1019 int lleft; /* number of chars left in this buffer */
1020 char *nextc; /* next char in buffer */
1021 char *buf; /* input buffer */
1022 struct strpush *strpush; /* for pushing strings at this level */
1023 struct strpush basestrpush; /* so pushing one is fast */
1026 static struct parsefile basepf; /* top level input file */
1027 static struct parsefile *g_parsefile = &basepf; /* current input file */
1028 static int startlinno; /* line # where last token started */
1029 static char *commandname; /* currently executing command */
1030 static struct strlist *cmdenviron; /* environment for builtin command */
1031 static uint8_t exitstatus; /* exit status of last command */
1034 /* ============ Message printing */
1037 ash_vmsg(const char *msg, va_list ap)
1039 fprintf(stderr, "%s: ", arg0);
1041 if (strcmp(arg0, commandname))
1042 fprintf(stderr, "%s: ", commandname);
1043 if (!iflag || g_parsefile->fd)
1044 fprintf(stderr, "line %d: ", startlinno);
1046 vfprintf(stderr, msg, ap);
1047 outcslow('\n', stderr);
1051 * Exverror is called to raise the error exception. If the second argument
1052 * is not NULL then error prints an error message using printf style
1053 * formatting. It then raises the error exception.
1055 static void ash_vmsg_and_raise(int, const char *, va_list) NORETURN;
1057 ash_vmsg_and_raise(int cond, const char *msg, va_list ap)
1061 TRACE(("ash_vmsg_and_raise(%d, \"", cond));
1063 TRACE(("\") pid=%d\n", getpid()));
1065 TRACE(("ash_vmsg_and_raise(%d, NULL) pid=%d\n", cond, getpid()));
1070 flush_stdout_stderr();
1071 raise_exception(cond);
1075 static void ash_msg_and_raise_error(const char *, ...) NORETURN;
1077 ash_msg_and_raise_error(const char *msg, ...)
1082 ash_vmsg_and_raise(EXERROR, msg, ap);
1087 static void ash_msg_and_raise(int, const char *, ...) NORETURN;
1089 ash_msg_and_raise(int cond, const char *msg, ...)
1094 ash_vmsg_and_raise(cond, msg, ap);
1100 * error/warning routines for external builtins
1103 ash_msg(const char *fmt, ...)
1113 * Return a string describing an error. The returned string may be a
1114 * pointer to a static buffer that will be overwritten on the next call.
1115 * Action describes the operation that got the error.
1118 errmsg(int e, const char *em)
1120 if (e == ENOENT || e == ENOTDIR) {
1127 /* ============ Memory allocation */
1130 * It appears that grabstackstr() will barf with such alignments
1131 * because stalloc() will return a string allocated in a new stackblock.
1133 #define SHELL_ALIGN(nbytes) (((nbytes) + SHELL_SIZE) & ~SHELL_SIZE)
1135 /* Most machines require the value returned from malloc to be aligned
1136 * in some way. The following macro will get this right
1137 * on many machines. */
1138 SHELL_SIZE = sizeof(union {int i; char *cp; double d; }) - 1,
1139 /* Minimum size of a block */
1140 MINSIZE = SHELL_ALIGN(504),
1143 struct stack_block {
1144 struct stack_block *prev;
1145 char space[MINSIZE];
1149 struct stack_block *stackp;
1152 struct stackmark *marknext;
1156 struct globals_memstack {
1157 struct stack_block *g_stackp; // = &stackbase;
1158 struct stackmark *markp;
1159 char *g_stacknxt; // = stackbase.space;
1160 char *sstrend; // = stackbase.space + MINSIZE;
1161 size_t g_stacknleft; // = MINSIZE;
1162 int herefd; // = -1;
1163 struct stack_block stackbase;
1165 extern struct globals_memstack *const ash_ptr_to_globals_memstack;
1166 #define G_memstack (*ash_ptr_to_globals_memstack)
1167 #define g_stackp (G_memstack.g_stackp )
1168 #define markp (G_memstack.markp )
1169 #define g_stacknxt (G_memstack.g_stacknxt )
1170 #define sstrend (G_memstack.sstrend )
1171 #define g_stacknleft (G_memstack.g_stacknleft)
1172 #define herefd (G_memstack.herefd )
1173 #define stackbase (G_memstack.stackbase )
1174 #define INIT_G_memstack() do { \
1175 (*(struct globals_memstack**)&ash_ptr_to_globals_memstack) = xzalloc(sizeof(G_memstack)); \
1177 g_stackp = &stackbase; \
1178 g_stacknxt = stackbase.space; \
1179 g_stacknleft = MINSIZE; \
1180 sstrend = stackbase.space + MINSIZE; \
1184 #define stackblock() ((void *)g_stacknxt)
1185 #define stackblocksize() g_stacknleft
1189 ckrealloc(void * p, size_t nbytes)
1191 p = realloc(p, nbytes);
1193 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1198 ckmalloc(size_t nbytes)
1200 return ckrealloc(NULL, nbytes);
1204 ckzalloc(size_t nbytes)
1206 return memset(ckmalloc(nbytes), 0, nbytes);
1210 * Make a copy of a string in safe storage.
1213 ckstrdup(const char *s)
1215 char *p = strdup(s);
1217 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1222 * Parse trees for commands are allocated in lifo order, so we use a stack
1223 * to make this more efficient, and also to avoid all sorts of exception
1224 * handling code to handle interrupts in the middle of a parse.
1226 * The size 504 was chosen because the Ultrix malloc handles that size
1230 stalloc(size_t nbytes)
1235 aligned = SHELL_ALIGN(nbytes);
1236 if (aligned > g_stacknleft) {
1239 struct stack_block *sp;
1241 blocksize = aligned;
1242 if (blocksize < MINSIZE)
1243 blocksize = MINSIZE;
1244 len = sizeof(struct stack_block) - MINSIZE + blocksize;
1245 if (len < blocksize)
1246 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1249 sp->prev = g_stackp;
1250 g_stacknxt = sp->space;
1251 g_stacknleft = blocksize;
1252 sstrend = g_stacknxt + blocksize;
1257 g_stacknxt += aligned;
1258 g_stacknleft -= aligned;
1263 stzalloc(size_t nbytes)
1265 return memset(stalloc(nbytes), 0, nbytes);
1272 if (!p || (g_stacknxt < (char *)p) || ((char *)p < g_stackp->space)) {
1273 write(STDERR_FILENO, "stunalloc\n", 10);
1277 g_stacknleft += g_stacknxt - (char *)p;
1282 * Like strdup but works with the ash stack.
1285 ststrdup(const char *p)
1287 size_t len = strlen(p) + 1;
1288 return memcpy(stalloc(len), p, len);
1292 setstackmark(struct stackmark *mark)
1294 mark->stackp = g_stackp;
1295 mark->stacknxt = g_stacknxt;
1296 mark->stacknleft = g_stacknleft;
1297 mark->marknext = markp;
1302 popstackmark(struct stackmark *mark)
1304 struct stack_block *sp;
1310 markp = mark->marknext;
1311 while (g_stackp != mark->stackp) {
1313 g_stackp = sp->prev;
1316 g_stacknxt = mark->stacknxt;
1317 g_stacknleft = mark->stacknleft;
1318 sstrend = mark->stacknxt + mark->stacknleft;
1323 * When the parser reads in a string, it wants to stick the string on the
1324 * stack and only adjust the stack pointer when it knows how big the
1325 * string is. Stackblock (defined in stack.h) returns a pointer to a block
1326 * of space on top of the stack and stackblocklen returns the length of
1327 * this block. Growstackblock will grow this space by at least one byte,
1328 * possibly moving it (like realloc). Grabstackblock actually allocates the
1329 * part of the block that has been used.
1332 growstackblock(void)
1336 newlen = g_stacknleft * 2;
1337 if (newlen < g_stacknleft)
1338 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1342 if (g_stacknxt == g_stackp->space && g_stackp != &stackbase) {
1343 struct stack_block *oldstackp;
1344 struct stackmark *xmark;
1345 struct stack_block *sp;
1346 struct stack_block *prevstackp;
1350 oldstackp = g_stackp;
1352 prevstackp = sp->prev;
1353 grosslen = newlen + sizeof(struct stack_block) - MINSIZE;
1354 sp = ckrealloc(sp, grosslen);
1355 sp->prev = prevstackp;
1357 g_stacknxt = sp->space;
1358 g_stacknleft = newlen;
1359 sstrend = sp->space + newlen;
1362 * Stack marks pointing to the start of the old block
1363 * must be relocated to point to the new block
1366 while (xmark != NULL && xmark->stackp == oldstackp) {
1367 xmark->stackp = g_stackp;
1368 xmark->stacknxt = g_stacknxt;
1369 xmark->stacknleft = g_stacknleft;
1370 xmark = xmark->marknext;
1374 char *oldspace = g_stacknxt;
1375 size_t oldlen = g_stacknleft;
1376 char *p = stalloc(newlen);
1378 /* free the space we just allocated */
1379 g_stacknxt = memcpy(p, oldspace, oldlen);
1380 g_stacknleft += newlen;
1385 grabstackblock(size_t len)
1387 len = SHELL_ALIGN(len);
1389 g_stacknleft -= len;
1393 * The following routines are somewhat easier to use than the above.
1394 * The user declares a variable of type STACKSTR, which may be declared
1395 * to be a register. The macro STARTSTACKSTR initializes things. Then
1396 * the user uses the macro STPUTC to add characters to the string. In
1397 * effect, STPUTC(c, p) is the same as *p++ = c except that the stack is
1398 * grown as necessary. When the user is done, she can just leave the
1399 * string there and refer to it using stackblock(). Or she can allocate
1400 * the space for it using grabstackstr(). If it is necessary to allow
1401 * someone else to use the stack temporarily and then continue to grow
1402 * the string, the user should use grabstack to allocate the space, and
1403 * then call ungrabstr(p) to return to the previous mode of operation.
1405 * USTPUTC is like STPUTC except that it doesn't check for overflow.
1406 * CHECKSTACKSPACE can be called before USTPUTC to ensure that there
1407 * is space for at least one character.
1412 size_t len = stackblocksize();
1413 if (herefd >= 0 && len >= 1024) {
1414 full_write(herefd, stackblock(), len);
1415 return stackblock();
1418 return (char *)stackblock() + len;
1422 * Called from CHECKSTRSPACE.
1425 makestrspace(size_t newlen, char *p)
1427 size_t len = p - g_stacknxt;
1428 size_t size = stackblocksize();
1433 size = stackblocksize();
1435 if (nleft >= newlen)
1439 return (char *)stackblock() + len;
1443 stack_nputstr(const char *s, size_t n, char *p)
1445 p = makestrspace(n, p);
1446 p = (char *)memcpy(p, s, n) + n;
1451 stack_putstr(const char *s, char *p)
1453 return stack_nputstr(s, strlen(s), p);
1457 _STPUTC(int c, char *p)
1465 #define STARTSTACKSTR(p) ((p) = stackblock())
1466 #define STPUTC(c, p) ((p) = _STPUTC((c), (p)))
1467 #define CHECKSTRSPACE(n, p) do { \
1470 size_t m = sstrend - q; \
1472 (p) = makestrspace(l, q); \
1474 #define USTPUTC(c, p) (*(p)++ = (c))
1475 #define STACKSTRNUL(p) do { \
1476 if ((p) == sstrend) \
1477 (p) = growstackstr(); \
1480 #define STUNPUTC(p) (--(p))
1481 #define STTOPC(p) ((p)[-1])
1482 #define STADJUST(amount, p) ((p) += (amount))
1484 #define grabstackstr(p) stalloc((char *)(p) - (char *)stackblock())
1485 #define ungrabstackstr(s, p) stunalloc(s)
1486 #define stackstrend() ((void *)sstrend)
1489 /* ============ String helpers */
1492 * prefix -- see if pfx is a prefix of string.
1495 prefix(const char *string, const char *pfx)
1498 if (*pfx++ != *string++)
1501 return (char *) string;
1505 * Check for a valid number. This should be elsewhere.
1508 is_number(const char *p)
1513 } while (*++p != '\0');
1518 * Convert a string of digits to an integer, printing an error message on
1522 number(const char *s)
1525 ash_msg_and_raise_error(illnum, s);
1530 * Produce a possibly single quoted string suitable as input to the shell.
1531 * The return string is allocated on the stack.
1534 single_quote(const char *s)
1544 len = strchrnul(s, '\'') - s;
1546 q = p = makestrspace(len + 3, p);
1549 q = (char *)memcpy(q, s, len) + len;
1555 len = strspn(s, "'");
1559 q = p = makestrspace(len + 3, p);
1562 q = (char *)memcpy(q, s, len) + len;
1571 return stackblock();
1575 /* ============ nextopt */
1577 static char **argptr; /* argument list for builtin commands */
1578 static char *optionarg; /* set by nextopt (like getopt) */
1579 static char *optptr; /* used by nextopt */
1582 * XXX - should get rid of. Have all builtins use getopt(3).
1583 * The library getopt must have the BSD extension static variable
1584 * "optreset", otherwise it can't be used within the shell safely.
1586 * Standard option processing (a la getopt) for builtin routines.
1587 * The only argument that is passed to nextopt is the option string;
1588 * the other arguments are unnecessary. It returns the character,
1589 * or '\0' on end of input.
1592 nextopt(const char *optstring)
1599 if (p == NULL || *p == '\0') {
1600 /* We ate entire "-param", take next one */
1606 if (*++p == '\0') /* just "-" ? */
1609 if (LONE_DASH(p)) /* "--" ? */
1611 /* p => next "-param" */
1613 /* p => some option char in the middle of a "-param" */
1615 for (q = optstring; *q != c;) {
1617 ash_msg_and_raise_error("illegal option -%c", c);
1625 ash_msg_and_raise_error("no arg for -%c option", c);
1635 /* ============ Shell variables */
1638 * The parsefile structure pointed to by the global variable parsefile
1639 * contains information about the current file being read.
1642 int nparam; /* # of positional parameters (without $0) */
1643 #if ENABLE_ASH_GETOPTS
1644 int optind; /* next parameter to be processed by getopts */
1645 int optoff; /* used by getopts */
1647 unsigned char malloced; /* if parameter list dynamically allocated */
1648 char **p; /* parameter list */
1652 * Free the list of positional parameters.
1655 freeparam(volatile struct shparam *param)
1657 if (param->malloced) {
1659 ap = ap1 = param->p;
1666 #if ENABLE_ASH_GETOPTS
1667 static void getoptsreset(const char *value);
1671 struct var *next; /* next entry in hash list */
1672 int flags; /* flags are defined above */
1673 const char *text; /* name=value */
1674 void (*func)(const char *); /* function to be called when */
1675 /* the variable gets set/unset */
1679 struct localvar *next; /* next local variable in list */
1680 struct var *vp; /* the variable that was made local */
1681 int flags; /* saved flags */
1682 const char *text; /* saved text */
1686 #define VEXPORT 0x01 /* variable is exported */
1687 #define VREADONLY 0x02 /* variable cannot be modified */
1688 #define VSTRFIXED 0x04 /* variable struct is statically allocated */
1689 #define VTEXTFIXED 0x08 /* text is statically allocated */
1690 #define VSTACK 0x10 /* text is allocated on the stack */
1691 #define VUNSET 0x20 /* the variable is not set */
1692 #define VNOFUNC 0x40 /* don't call the callback function */
1693 #define VNOSET 0x80 /* do not set variable - just readonly test */
1694 #define VNOSAVE 0x100 /* when text is on the heap before setvareq */
1695 #if ENABLE_ASH_RANDOM_SUPPORT
1696 # define VDYNAMIC 0x200 /* dynamic variable */
1702 static const char defifsvar[] ALIGN1 = "IFS= \t\n";
1703 #define defifs (defifsvar + 4)
1705 static const char defifs[] ALIGN1 = " \t\n";
1709 /* Need to be before varinit_data[] */
1710 #if ENABLE_LOCALE_SUPPORT
1712 change_lc_all(const char *value)
1714 if (value && *value != '\0')
1715 setlocale(LC_ALL, value);
1718 change_lc_ctype(const char *value)
1720 if (value && *value != '\0')
1721 setlocale(LC_CTYPE, value);
1725 static void chkmail(void);
1726 static void changemail(const char *);
1728 static void changepath(const char *);
1729 #if ENABLE_ASH_RANDOM_SUPPORT
1730 static void change_random(const char *);
1733 static const struct {
1736 void (*func)(const char *);
1737 } varinit_data[] = {
1739 { VSTRFIXED|VTEXTFIXED , defifsvar , NULL },
1741 { VSTRFIXED|VTEXTFIXED|VUNSET, "IFS\0" , NULL },
1744 { VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL\0" , changemail },
1745 { VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH\0", changemail },
1747 { VSTRFIXED|VTEXTFIXED , bb_PATH_root_path, changepath },
1748 { VSTRFIXED|VTEXTFIXED , "PS1=$ " , NULL },
1749 { VSTRFIXED|VTEXTFIXED , "PS2=> " , NULL },
1750 { VSTRFIXED|VTEXTFIXED , "PS4=+ " , NULL },
1751 #if ENABLE_ASH_GETOPTS
1752 { VSTRFIXED|VTEXTFIXED , "OPTIND=1" , getoptsreset },
1754 #if ENABLE_ASH_RANDOM_SUPPORT
1755 { VSTRFIXED|VTEXTFIXED|VUNSET|VDYNAMIC, "RANDOM\0", change_random },
1757 #if ENABLE_LOCALE_SUPPORT
1758 { VSTRFIXED|VTEXTFIXED|VUNSET, "LC_ALL\0" , change_lc_all },
1759 { VSTRFIXED|VTEXTFIXED|VUNSET, "LC_CTYPE\0", change_lc_ctype },
1761 #if ENABLE_FEATURE_EDITING_SAVEHISTORY
1762 { VSTRFIXED|VTEXTFIXED|VUNSET, "HISTFILE\0", NULL },
1768 struct globals_var {
1769 struct shparam shellparam; /* $@ current positional parameters */
1770 struct redirtab *redirlist;
1772 int preverrout_fd; /* save fd2 before print debug if xflag is set. */
1773 struct var *vartab[VTABSIZE];
1774 struct var varinit[ARRAY_SIZE(varinit_data)];
1776 extern struct globals_var *const ash_ptr_to_globals_var;
1777 #define G_var (*ash_ptr_to_globals_var)
1778 #define shellparam (G_var.shellparam )
1779 //#define redirlist (G_var.redirlist )
1780 #define g_nullredirs (G_var.g_nullredirs )
1781 #define preverrout_fd (G_var.preverrout_fd)
1782 #define vartab (G_var.vartab )
1783 #define varinit (G_var.varinit )
1784 #define INIT_G_var() do { \
1786 (*(struct globals_var**)&ash_ptr_to_globals_var) = xzalloc(sizeof(G_var)); \
1788 for (i = 0; i < ARRAY_SIZE(varinit_data); i++) { \
1789 varinit[i].flags = varinit_data[i].flags; \
1790 varinit[i].text = varinit_data[i].text; \
1791 varinit[i].func = varinit_data[i].func; \
1795 #define vifs varinit[0]
1797 # define vmail (&vifs)[1]
1798 # define vmpath (&vmail)[1]
1799 # define vpath (&vmpath)[1]
1801 # define vpath (&vifs)[1]
1803 #define vps1 (&vpath)[1]
1804 #define vps2 (&vps1)[1]
1805 #define vps4 (&vps2)[1]
1806 #if ENABLE_ASH_GETOPTS
1807 # define voptind (&vps4)[1]
1808 # if ENABLE_ASH_RANDOM_SUPPORT
1809 # define vrandom (&voptind)[1]
1812 # if ENABLE_ASH_RANDOM_SUPPORT
1813 # define vrandom (&vps4)[1]
1818 * The following macros access the values of the above variables.
1819 * They have to skip over the name. They return the null string
1820 * for unset variables.
1822 #define ifsval() (vifs.text + 4)
1823 #define ifsset() ((vifs.flags & VUNSET) == 0)
1825 # define mailval() (vmail.text + 5)
1826 # define mpathval() (vmpath.text + 9)
1827 # define mpathset() ((vmpath.flags & VUNSET) == 0)
1829 #define pathval() (vpath.text + 5)
1830 #define ps1val() (vps1.text + 4)
1831 #define ps2val() (vps2.text + 4)
1832 #define ps4val() (vps4.text + 4)
1833 #if ENABLE_ASH_GETOPTS
1834 # define optindval() (voptind.text + 7)
1838 #define is_name(c) ((c) == '_' || isalpha((unsigned char)(c)))
1839 #define is_in_name(c) ((c) == '_' || isalnum((unsigned char)(c)))
1841 #if ENABLE_ASH_GETOPTS
1843 getoptsreset(const char *value)
1845 shellparam.optind = number(value);
1846 shellparam.optoff = -1;
1851 * Return of a legal variable name (a letter or underscore followed by zero or
1852 * more letters, underscores, and digits).
1855 endofname(const char *name)
1863 if (!is_in_name(*p))
1870 * Compares two strings up to the first = or '\0'. The first
1871 * string must be terminated by '='; the second may be terminated by
1872 * either '=' or '\0'.
1875 varcmp(const char *p, const char *q)
1879 while ((c = *p) == (d = *q)) {
1894 varequal(const char *a, const char *b)
1896 return !varcmp(a, b);
1900 * Find the appropriate entry in the hash table from the name.
1902 static struct var **
1903 hashvar(const char *p)
1907 hashval = ((unsigned char) *p) << 4;
1908 while (*p && *p != '=')
1909 hashval += (unsigned char) *p++;
1910 return &vartab[hashval % VTABSIZE];
1914 vpcmp(const void *a, const void *b)
1916 return varcmp(*(const char **)a, *(const char **)b);
1920 * This routine initializes the builtin variables.
1930 * PS1 depends on uid
1932 #if ENABLE_FEATURE_EDITING && ENABLE_FEATURE_EDITING_FANCY_PROMPT
1933 vps1.text = "PS1=\\w \\$ ";
1936 vps1.text = "PS1=# ";
1939 end = vp + ARRAY_SIZE(varinit);
1941 vpp = hashvar(vp->text);
1944 } while (++vp < end);
1947 static struct var **
1948 findvar(struct var **vpp, const char *name)
1950 for (; *vpp; vpp = &(*vpp)->next) {
1951 if (varequal((*vpp)->text, name)) {
1959 * Find the value of a variable. Returns NULL if not set.
1962 lookupvar(const char *name)
1966 v = *findvar(hashvar(name), name);
1968 #if ENABLE_ASH_RANDOM_SUPPORT
1970 * Dynamic variables are implemented roughly the same way they are
1971 * in bash. Namely, they're "special" so long as they aren't unset.
1972 * As soon as they're unset, they're no longer dynamic, and dynamic
1973 * lookup will no longer happen at that point. -- PFM.
1975 if ((v->flags & VDYNAMIC))
1978 if (!(v->flags & VUNSET))
1979 return strchrnul(v->text, '=') + 1;
1985 * Search the environment of a builtin command.
1988 bltinlookup(const char *name)
1992 for (sp = cmdenviron; sp; sp = sp->next) {
1993 if (varequal(sp->text, name))
1994 return strchrnul(sp->text, '=') + 1;
1996 return lookupvar(name);
2000 * Same as setvar except that the variable and value are passed in
2001 * the first argument as name=value. Since the first argument will
2002 * be actually stored in the table, it should not be a string that
2004 * Called with interrupts off.
2007 setvareq(char *s, int flags)
2009 struct var *vp, **vpp;
2012 flags |= (VEXPORT & (((unsigned) (1 - aflag)) - 1));
2013 vp = *findvar(vpp, s);
2015 if ((vp->flags & (VREADONLY|VDYNAMIC)) == VREADONLY) {
2018 if (flags & VNOSAVE)
2021 ash_msg_and_raise_error("%.*s: is read only", strchrnul(n, '=') - n, n);
2027 if (vp->func && (flags & VNOFUNC) == 0)
2028 (*vp->func)(strchrnul(s, '=') + 1);
2030 if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
2031 free((char*)vp->text);
2033 flags |= vp->flags & ~(VTEXTFIXED|VSTACK|VNOSAVE|VUNSET);
2038 vp = ckzalloc(sizeof(*vp));
2040 /*vp->func = NULL; - ckzalloc did it */
2043 if (!(flags & (VTEXTFIXED|VSTACK|VNOSAVE)))
2050 * Set the value of a variable. The flags argument is ored with the
2051 * flags of the variable. If val is NULL, the variable is unset.
2054 setvar(const char *name, const char *val, int flags)
2061 q = endofname(name);
2062 p = strchrnul(q, '=');
2064 if (!namelen || p != q)
2065 ash_msg_and_raise_error("%.*s: bad variable name", namelen, name);
2070 vallen = strlen(val);
2073 nameeq = ckmalloc(namelen + vallen + 2);
2074 p = (char *)memcpy(nameeq, name, namelen) + namelen;
2077 p = (char *)memcpy(p, val, vallen) + vallen;
2080 setvareq(nameeq, flags | VNOSAVE);
2084 #if ENABLE_ASH_GETOPTS
2086 * Safe version of setvar, returns 1 on success 0 on failure.
2089 setvarsafe(const char *name, const char *val, int flags)
2092 volatile int saveint;
2093 struct jmploc *volatile savehandler = exception_handler;
2094 struct jmploc jmploc;
2097 if (setjmp(jmploc.loc))
2100 exception_handler = &jmploc;
2101 setvar(name, val, flags);
2104 exception_handler = savehandler;
2105 RESTORE_INT(saveint);
2111 * Unset the specified variable.
2114 unsetvar(const char *s)
2120 vpp = findvar(hashvar(s), s);
2124 int flags = vp->flags;
2127 if (flags & VREADONLY)
2129 #if ENABLE_ASH_RANDOM_SUPPORT
2130 vp->flags &= ~VDYNAMIC;
2134 if ((flags & VSTRFIXED) == 0) {
2136 if ((flags & (VTEXTFIXED|VSTACK)) == 0)
2137 free((char*)vp->text);
2143 vp->flags &= ~VEXPORT;
2153 * Process a linked list of variable assignments.
2156 listsetvar(struct strlist *list_set_var, int flags)
2158 struct strlist *lp = list_set_var;
2164 setvareq(lp->text, flags);
2171 * Generate a list of variables satisfying the given conditions.
2174 listvars(int on, int off, char ***end)
2185 for (vp = *vpp; vp; vp = vp->next) {
2186 if ((vp->flags & mask) == on) {
2187 if (ep == stackstrend())
2188 ep = growstackstr();
2189 *ep++ = (char *) vp->text;
2192 } while (++vpp < vartab + VTABSIZE);
2193 if (ep == stackstrend())
2194 ep = growstackstr();
2198 return grabstackstr(ep);
2202 /* ============ Path search helper
2204 * The variable path (passed by reference) should be set to the start
2205 * of the path before the first call; padvance will update
2206 * this value as it proceeds. Successive calls to padvance will return
2207 * the possible path expansions in sequence. If an option (indicated by
2208 * a percent sign) appears in the path entry then the global variable
2209 * pathopt will be set to point to it; otherwise pathopt will be set to
2212 static const char *pathopt; /* set by padvance */
2215 padvance(const char **path, const char *name)
2225 for (p = start; *p && *p != ':' && *p != '%'; p++)
2227 len = p - start + strlen(name) + 2; /* "2" is for '/' and '\0' */
2228 while (stackblocksize() < len)
2232 memcpy(q, start, p - start);
2240 while (*p && *p != ':')
2247 return stalloc(len);
2251 /* ============ Prompt */
2253 static smallint doprompt; /* if set, prompt the user */
2254 static smallint needprompt; /* true if interactive and at start of line */
2256 #if ENABLE_FEATURE_EDITING
2257 static line_input_t *line_input_state;
2258 static const char *cmdedit_prompt;
2260 putprompt(const char *s)
2262 if (ENABLE_ASH_EXPAND_PRMT) {
2263 free((char*)cmdedit_prompt);
2264 cmdedit_prompt = ckstrdup(s);
2271 putprompt(const char *s)
2277 #if ENABLE_ASH_EXPAND_PRMT
2278 /* expandstr() needs parsing machinery, so it is far away ahead... */
2279 static const char *expandstr(const char *ps);
2281 #define expandstr(s) s
2285 setprompt(int whichprompt)
2288 #if ENABLE_ASH_EXPAND_PRMT
2289 struct stackmark smark;
2294 switch (whichprompt) {
2304 #if ENABLE_ASH_EXPAND_PRMT
2305 setstackmark(&smark);
2306 stalloc(stackblocksize());
2308 putprompt(expandstr(prompt));
2309 #if ENABLE_ASH_EXPAND_PRMT
2310 popstackmark(&smark);
2315 /* ============ The cd and pwd commands */
2317 #define CD_PHYSICAL 1
2320 static int docd(const char *, int);
2329 while ((i = nextopt("LP"))) {
2331 flags ^= CD_PHYSICAL;
2340 * Update curdir (the name of the current directory) in response to a
2344 updatepwd(const char *dir)
2351 cdcomppath = ststrdup(dir);
2354 if (curdir == nullstr)
2356 new = stack_putstr(curdir, new);
2358 new = makestrspace(strlen(dir) + 2, new);
2359 lim = (char *)stackblock() + 1;
2363 if (new > lim && *lim == '/')
2368 if (dir[1] == '/' && dir[2] != '/') {
2374 p = strtok(cdcomppath, "/");
2378 if (p[1] == '.' && p[2] == '\0') {
2390 new = stack_putstr(p, new);
2398 return stackblock();
2402 * Find out what the current directory is. If we already know the current
2403 * directory, this routine returns immediately.
2408 char *dir = getcwd(NULL, 0); /* huh, using glibc extension? */
2409 return dir ? dir : nullstr;
2413 setpwd(const char *val, int setold)
2417 oldcur = dir = curdir;
2420 setvar("OLDPWD", oldcur, VEXPORT);
2423 if (physdir != nullstr) {
2424 if (physdir != oldcur)
2428 if (oldcur == val || !val) {
2434 dir = ckstrdup(val);
2435 if (oldcur != dir && oldcur != nullstr) {
2440 setvar("PWD", dir, VEXPORT);
2443 static void hashcd(void);
2446 * Actually do the chdir. We also call hashcd to let the routines in exec.c
2447 * know that the current directory has changed.
2450 docd(const char *dest, int flags)
2452 const char *dir = 0;
2455 TRACE(("docd(\"%s\", %d) called\n", dest, flags));
2458 if (!(flags & CD_PHYSICAL)) {
2459 dir = updatepwd(dest);
2474 cdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
2486 dest = bltinlookup(homestr);
2487 else if (LONE_DASH(dest)) {
2488 dest = bltinlookup("OLDPWD");
2510 path = bltinlookup("CDPATH");
2519 p = padvance(&path, dest);
2520 if (stat(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) {
2524 if (!docd(p, flags))
2529 ash_msg_and_raise_error("can't cd to %s", dest);
2532 if (flags & CD_PRINT)
2533 out1fmt(snlfmt, curdir);
2538 pwdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
2541 const char *dir = curdir;
2545 if (physdir == nullstr)
2549 out1fmt(snlfmt, dir);
2554 /* ============ ... */
2556 #define IBUFSIZ COMMON_BUFSIZE
2557 #define basebuf bb_common_bufsiz1 /* buffer for top level input file */
2559 /* Syntax classes */
2560 #define CWORD 0 /* character is nothing special */
2561 #define CNL 1 /* newline character */
2562 #define CBACK 2 /* a backslash character */
2563 #define CSQUOTE 3 /* single quote */
2564 #define CDQUOTE 4 /* double quote */
2565 #define CENDQUOTE 5 /* a terminating quote */
2566 #define CBQUOTE 6 /* backwards single quote */
2567 #define CVAR 7 /* a dollar sign */
2568 #define CENDVAR 8 /* a '}' character */
2569 #define CLP 9 /* a left paren in arithmetic */
2570 #define CRP 10 /* a right paren in arithmetic */
2571 #define CENDFILE 11 /* end of file */
2572 #define CCTL 12 /* like CWORD, except it must be escaped */
2573 #define CSPCL 13 /* these terminate a word */
2574 #define CIGN 14 /* character should be ignored */
2576 #if ENABLE_ASH_ALIAS
2580 #define PEOA_OR_PEOF PEOA
2584 #define PEOA_OR_PEOF PEOF
2587 /* number syntax index */
2588 #define BASESYNTAX 0 /* not in quotes */
2589 #define DQSYNTAX 1 /* in double quotes */
2590 #define SQSYNTAX 2 /* in single quotes */
2591 #define ARISYNTAX 3 /* in arithmetic */
2592 #define PSSYNTAX 4 /* prompt */
2594 #if ENABLE_ASH_OPTIMIZE_FOR_SIZE
2595 #define USE_SIT_FUNCTION
2598 #if ENABLE_ASH_MATH_SUPPORT
2599 static const char S_I_T[][4] = {
2600 #if ENABLE_ASH_ALIAS
2601 { CSPCL, CIGN, CIGN, CIGN }, /* 0, PEOA */
2603 { CSPCL, CWORD, CWORD, CWORD }, /* 1, ' ' */
2604 { CNL, CNL, CNL, CNL }, /* 2, \n */
2605 { CWORD, CCTL, CCTL, CWORD }, /* 3, !*-/:=?[]~ */
2606 { CDQUOTE, CENDQUOTE, CWORD, CWORD }, /* 4, '"' */
2607 { CVAR, CVAR, CWORD, CVAR }, /* 5, $ */
2608 { CSQUOTE, CWORD, CENDQUOTE, CWORD }, /* 6, "'" */
2609 { CSPCL, CWORD, CWORD, CLP }, /* 7, ( */
2610 { CSPCL, CWORD, CWORD, CRP }, /* 8, ) */
2611 { CBACK, CBACK, CCTL, CBACK }, /* 9, \ */
2612 { CBQUOTE, CBQUOTE, CWORD, CBQUOTE }, /* 10, ` */
2613 { CENDVAR, CENDVAR, CWORD, CENDVAR }, /* 11, } */
2614 #ifndef USE_SIT_FUNCTION
2615 { CENDFILE, CENDFILE, CENDFILE, CENDFILE }, /* 12, PEOF */
2616 { CWORD, CWORD, CWORD, CWORD }, /* 13, 0-9A-Za-z */
2617 { CCTL, CCTL, CCTL, CCTL } /* 14, CTLESC ... */
2621 static const char S_I_T[][3] = {
2622 #if ENABLE_ASH_ALIAS
2623 { CSPCL, CIGN, CIGN }, /* 0, PEOA */
2625 { CSPCL, CWORD, CWORD }, /* 1, ' ' */
2626 { CNL, CNL, CNL }, /* 2, \n */
2627 { CWORD, CCTL, CCTL }, /* 3, !*-/:=?[]~ */
2628 { CDQUOTE, CENDQUOTE, CWORD }, /* 4, '"' */
2629 { CVAR, CVAR, CWORD }, /* 5, $ */
2630 { CSQUOTE, CWORD, CENDQUOTE }, /* 6, "'" */
2631 { CSPCL, CWORD, CWORD }, /* 7, ( */
2632 { CSPCL, CWORD, CWORD }, /* 8, ) */
2633 { CBACK, CBACK, CCTL }, /* 9, \ */
2634 { CBQUOTE, CBQUOTE, CWORD }, /* 10, ` */
2635 { CENDVAR, CENDVAR, CWORD }, /* 11, } */
2636 #ifndef USE_SIT_FUNCTION
2637 { CENDFILE, CENDFILE, CENDFILE }, /* 12, PEOF */
2638 { CWORD, CWORD, CWORD }, /* 13, 0-9A-Za-z */
2639 { CCTL, CCTL, CCTL } /* 14, CTLESC ... */
2642 #endif /* ASH_MATH_SUPPORT */
2644 #ifdef USE_SIT_FUNCTION
2647 SIT(int c, int syntax)
2649 static const char spec_symbls[] ALIGN1 = "\t\n !\"$&'()*-/:;<=>?[\\]`|}~";
2650 #if ENABLE_ASH_ALIAS
2651 static const char syntax_index_table[] ALIGN1 = {
2652 1, 2, 1, 3, 4, 5, 1, 6, /* "\t\n !\"$&'" */
2653 7, 8, 3, 3, 3, 3, 1, 1, /* "()*-/:;<" */
2654 3, 1, 3, 3, 9, 3, 10, 1, /* "=>?[\\]`|" */
2658 static const char syntax_index_table[] ALIGN1 = {
2659 0, 1, 0, 2, 3, 4, 0, 5, /* "\t\n !\"$&'" */
2660 6, 7, 2, 2, 2, 2, 0, 0, /* "()*-/:;<" */
2661 2, 0, 2, 2, 8, 2, 9, 0, /* "=>?[\\]`|" */
2668 if (c == PEOF) /* 2^8+2 */
2670 #if ENABLE_ASH_ALIAS
2671 if (c == PEOA) /* 2^8+1 */
2675 #define U_C(c) ((unsigned char)(c))
2677 if ((unsigned char)c >= (unsigned char)(CTLESC)
2678 && (unsigned char)c <= (unsigned char)(CTLQUOTEMARK)
2682 s = strchrnul(spec_symbls, c);
2685 indx = syntax_index_table[s - spec_symbls];
2687 return S_I_T[indx][syntax];
2690 #else /* !USE_SIT_FUNCTION */
2692 #if ENABLE_ASH_ALIAS
2693 #define CSPCL_CIGN_CIGN_CIGN 0
2694 #define CSPCL_CWORD_CWORD_CWORD 1
2695 #define CNL_CNL_CNL_CNL 2
2696 #define CWORD_CCTL_CCTL_CWORD 3
2697 #define CDQUOTE_CENDQUOTE_CWORD_CWORD 4
2698 #define CVAR_CVAR_CWORD_CVAR 5
2699 #define CSQUOTE_CWORD_CENDQUOTE_CWORD 6
2700 #define CSPCL_CWORD_CWORD_CLP 7
2701 #define CSPCL_CWORD_CWORD_CRP 8
2702 #define CBACK_CBACK_CCTL_CBACK 9
2703 #define CBQUOTE_CBQUOTE_CWORD_CBQUOTE 10
2704 #define CENDVAR_CENDVAR_CWORD_CENDVAR 11
2705 #define CENDFILE_CENDFILE_CENDFILE_CENDFILE 12
2706 #define CWORD_CWORD_CWORD_CWORD 13
2707 #define CCTL_CCTL_CCTL_CCTL 14
2709 #define CSPCL_CWORD_CWORD_CWORD 0
2710 #define CNL_CNL_CNL_CNL 1
2711 #define CWORD_CCTL_CCTL_CWORD 2
2712 #define CDQUOTE_CENDQUOTE_CWORD_CWORD 3
2713 #define CVAR_CVAR_CWORD_CVAR 4
2714 #define CSQUOTE_CWORD_CENDQUOTE_CWORD 5
2715 #define CSPCL_CWORD_CWORD_CLP 6
2716 #define CSPCL_CWORD_CWORD_CRP 7
2717 #define CBACK_CBACK_CCTL_CBACK 8
2718 #define CBQUOTE_CBQUOTE_CWORD_CBQUOTE 9
2719 #define CENDVAR_CENDVAR_CWORD_CENDVAR 10
2720 #define CENDFILE_CENDFILE_CENDFILE_CENDFILE 11
2721 #define CWORD_CWORD_CWORD_CWORD 12
2722 #define CCTL_CCTL_CCTL_CCTL 13
2725 static const char syntax_index_table[258] = {
2726 /* BASESYNTAX_DQSYNTAX_SQSYNTAX_ARISYNTAX */
2727 /* 0 PEOF */ CENDFILE_CENDFILE_CENDFILE_CENDFILE,
2728 #if ENABLE_ASH_ALIAS
2729 /* 1 PEOA */ CSPCL_CIGN_CIGN_CIGN,
2731 /* 2 -128 0x80 */ CWORD_CWORD_CWORD_CWORD,
2732 /* 3 -127 CTLESC */ CCTL_CCTL_CCTL_CCTL,
2733 /* 4 -126 CTLVAR */ CCTL_CCTL_CCTL_CCTL,
2734 /* 5 -125 CTLENDVAR */ CCTL_CCTL_CCTL_CCTL,
2735 /* 6 -124 CTLBACKQ */ CCTL_CCTL_CCTL_CCTL,
2736 /* 7 -123 CTLQUOTE */ CCTL_CCTL_CCTL_CCTL,
2737 /* 8 -122 CTLARI */ CCTL_CCTL_CCTL_CCTL,
2738 /* 9 -121 CTLENDARI */ CCTL_CCTL_CCTL_CCTL,
2739 /* 10 -120 CTLQUOTEMARK */ CCTL_CCTL_CCTL_CCTL,
2740 /* 11 -119 */ CWORD_CWORD_CWORD_CWORD,
2741 /* 12 -118 */ CWORD_CWORD_CWORD_CWORD,
2742 /* 13 -117 */ CWORD_CWORD_CWORD_CWORD,
2743 /* 14 -116 */ CWORD_CWORD_CWORD_CWORD,
2744 /* 15 -115 */ CWORD_CWORD_CWORD_CWORD,
2745 /* 16 -114 */ CWORD_CWORD_CWORD_CWORD,
2746 /* 17 -113 */ CWORD_CWORD_CWORD_CWORD,
2747 /* 18 -112 */ CWORD_CWORD_CWORD_CWORD,
2748 /* 19 -111 */ CWORD_CWORD_CWORD_CWORD,
2749 /* 20 -110 */ CWORD_CWORD_CWORD_CWORD,
2750 /* 21 -109 */ CWORD_CWORD_CWORD_CWORD,
2751 /* 22 -108 */ CWORD_CWORD_CWORD_CWORD,
2752 /* 23 -107 */ CWORD_CWORD_CWORD_CWORD,
2753 /* 24 -106 */ CWORD_CWORD_CWORD_CWORD,
2754 /* 25 -105 */ CWORD_CWORD_CWORD_CWORD,
2755 /* 26 -104 */ CWORD_CWORD_CWORD_CWORD,
2756 /* 27 -103 */ CWORD_CWORD_CWORD_CWORD,
2757 /* 28 -102 */ CWORD_CWORD_CWORD_CWORD,
2758 /* 29 -101 */ CWORD_CWORD_CWORD_CWORD,
2759 /* 30 -100 */ CWORD_CWORD_CWORD_CWORD,
2760 /* 31 -99 */ CWORD_CWORD_CWORD_CWORD,
2761 /* 32 -98 */ CWORD_CWORD_CWORD_CWORD,
2762 /* 33 -97 */ CWORD_CWORD_CWORD_CWORD,
2763 /* 34 -96 */ CWORD_CWORD_CWORD_CWORD,
2764 /* 35 -95 */ CWORD_CWORD_CWORD_CWORD,
2765 /* 36 -94 */ CWORD_CWORD_CWORD_CWORD,
2766 /* 37 -93 */ CWORD_CWORD_CWORD_CWORD,
2767 /* 38 -92 */ CWORD_CWORD_CWORD_CWORD,
2768 /* 39 -91 */ CWORD_CWORD_CWORD_CWORD,
2769 /* 40 -90 */ CWORD_CWORD_CWORD_CWORD,
2770 /* 41 -89 */ CWORD_CWORD_CWORD_CWORD,
2771 /* 42 -88 */ CWORD_CWORD_CWORD_CWORD,
2772 /* 43 -87 */ CWORD_CWORD_CWORD_CWORD,
2773 /* 44 -86 */ CWORD_CWORD_CWORD_CWORD,
2774 /* 45 -85 */ CWORD_CWORD_CWORD_CWORD,
2775 /* 46 -84 */ CWORD_CWORD_CWORD_CWORD,
2776 /* 47 -83 */ CWORD_CWORD_CWORD_CWORD,
2777 /* 48 -82 */ CWORD_CWORD_CWORD_CWORD,
2778 /* 49 -81 */ CWORD_CWORD_CWORD_CWORD,
2779 /* 50 -80 */ CWORD_CWORD_CWORD_CWORD,
2780 /* 51 -79 */ CWORD_CWORD_CWORD_CWORD,
2781 /* 52 -78 */ CWORD_CWORD_CWORD_CWORD,
2782 /* 53 -77 */ CWORD_CWORD_CWORD_CWORD,
2783 /* 54 -76 */ CWORD_CWORD_CWORD_CWORD,
2784 /* 55 -75 */ CWORD_CWORD_CWORD_CWORD,
2785 /* 56 -74 */ CWORD_CWORD_CWORD_CWORD,
2786 /* 57 -73 */ CWORD_CWORD_CWORD_CWORD,
2787 /* 58 -72 */ CWORD_CWORD_CWORD_CWORD,
2788 /* 59 -71 */ CWORD_CWORD_CWORD_CWORD,
2789 /* 60 -70 */ CWORD_CWORD_CWORD_CWORD,
2790 /* 61 -69 */ CWORD_CWORD_CWORD_CWORD,
2791 /* 62 -68 */ CWORD_CWORD_CWORD_CWORD,
2792 /* 63 -67 */ CWORD_CWORD_CWORD_CWORD,
2793 /* 64 -66 */ CWORD_CWORD_CWORD_CWORD,
2794 /* 65 -65 */ CWORD_CWORD_CWORD_CWORD,
2795 /* 66 -64 */ CWORD_CWORD_CWORD_CWORD,
2796 /* 67 -63 */ CWORD_CWORD_CWORD_CWORD,
2797 /* 68 -62 */ CWORD_CWORD_CWORD_CWORD,
2798 /* 69 -61 */ CWORD_CWORD_CWORD_CWORD,
2799 /* 70 -60 */ CWORD_CWORD_CWORD_CWORD,
2800 /* 71 -59 */ CWORD_CWORD_CWORD_CWORD,
2801 /* 72 -58 */ CWORD_CWORD_CWORD_CWORD,
2802 /* 73 -57 */ CWORD_CWORD_CWORD_CWORD,
2803 /* 74 -56 */ CWORD_CWORD_CWORD_CWORD,
2804 /* 75 -55 */ CWORD_CWORD_CWORD_CWORD,
2805 /* 76 -54 */ CWORD_CWORD_CWORD_CWORD,
2806 /* 77 -53 */ CWORD_CWORD_CWORD_CWORD,
2807 /* 78 -52 */ CWORD_CWORD_CWORD_CWORD,
2808 /* 79 -51 */ CWORD_CWORD_CWORD_CWORD,
2809 /* 80 -50 */ CWORD_CWORD_CWORD_CWORD,
2810 /* 81 -49 */ CWORD_CWORD_CWORD_CWORD,
2811 /* 82 -48 */ CWORD_CWORD_CWORD_CWORD,
2812 /* 83 -47 */ CWORD_CWORD_CWORD_CWORD,
2813 /* 84 -46 */ CWORD_CWORD_CWORD_CWORD,
2814 /* 85 -45 */ CWORD_CWORD_CWORD_CWORD,
2815 /* 86 -44 */ CWORD_CWORD_CWORD_CWORD,
2816 /* 87 -43 */ CWORD_CWORD_CWORD_CWORD,
2817 /* 88 -42 */ CWORD_CWORD_CWORD_CWORD,
2818 /* 89 -41 */ CWORD_CWORD_CWORD_CWORD,
2819 /* 90 -40 */ CWORD_CWORD_CWORD_CWORD,
2820 /* 91 -39 */ CWORD_CWORD_CWORD_CWORD,
2821 /* 92 -38 */ CWORD_CWORD_CWORD_CWORD,
2822 /* 93 -37 */ CWORD_CWORD_CWORD_CWORD,
2823 /* 94 -36 */ CWORD_CWORD_CWORD_CWORD,
2824 /* 95 -35 */ CWORD_CWORD_CWORD_CWORD,
2825 /* 96 -34 */ CWORD_CWORD_CWORD_CWORD,
2826 /* 97 -33 */ CWORD_CWORD_CWORD_CWORD,
2827 /* 98 -32 */ CWORD_CWORD_CWORD_CWORD,
2828 /* 99 -31 */ CWORD_CWORD_CWORD_CWORD,
2829 /* 100 -30 */ CWORD_CWORD_CWORD_CWORD,
2830 /* 101 -29 */ CWORD_CWORD_CWORD_CWORD,
2831 /* 102 -28 */ CWORD_CWORD_CWORD_CWORD,
2832 /* 103 -27 */ CWORD_CWORD_CWORD_CWORD,
2833 /* 104 -26 */ CWORD_CWORD_CWORD_CWORD,
2834 /* 105 -25 */ CWORD_CWORD_CWORD_CWORD,
2835 /* 106 -24 */ CWORD_CWORD_CWORD_CWORD,
2836 /* 107 -23 */ CWORD_CWORD_CWORD_CWORD,
2837 /* 108 -22 */ CWORD_CWORD_CWORD_CWORD,
2838 /* 109 -21 */ CWORD_CWORD_CWORD_CWORD,
2839 /* 110 -20 */ CWORD_CWORD_CWORD_CWORD,
2840 /* 111 -19 */ CWORD_CWORD_CWORD_CWORD,
2841 /* 112 -18 */ CWORD_CWORD_CWORD_CWORD,
2842 /* 113 -17 */ CWORD_CWORD_CWORD_CWORD,
2843 /* 114 -16 */ CWORD_CWORD_CWORD_CWORD,
2844 /* 115 -15 */ CWORD_CWORD_CWORD_CWORD,
2845 /* 116 -14 */ CWORD_CWORD_CWORD_CWORD,
2846 /* 117 -13 */ CWORD_CWORD_CWORD_CWORD,
2847 /* 118 -12 */ CWORD_CWORD_CWORD_CWORD,
2848 /* 119 -11 */ CWORD_CWORD_CWORD_CWORD,
2849 /* 120 -10 */ CWORD_CWORD_CWORD_CWORD,
2850 /* 121 -9 */ CWORD_CWORD_CWORD_CWORD,
2851 /* 122 -8 */ CWORD_CWORD_CWORD_CWORD,
2852 /* 123 -7 */ CWORD_CWORD_CWORD_CWORD,
2853 /* 124 -6 */ CWORD_CWORD_CWORD_CWORD,
2854 /* 125 -5 */ CWORD_CWORD_CWORD_CWORD,
2855 /* 126 -4 */ CWORD_CWORD_CWORD_CWORD,
2856 /* 127 -3 */ CWORD_CWORD_CWORD_CWORD,
2857 /* 128 -2 */ CWORD_CWORD_CWORD_CWORD,
2858 /* 129 -1 */ CWORD_CWORD_CWORD_CWORD,
2859 /* 130 0 */ CWORD_CWORD_CWORD_CWORD,
2860 /* 131 1 */ CWORD_CWORD_CWORD_CWORD,
2861 /* 132 2 */ CWORD_CWORD_CWORD_CWORD,
2862 /* 133 3 */ CWORD_CWORD_CWORD_CWORD,
2863 /* 134 4 */ CWORD_CWORD_CWORD_CWORD,
2864 /* 135 5 */ CWORD_CWORD_CWORD_CWORD,
2865 /* 136 6 */ CWORD_CWORD_CWORD_CWORD,
2866 /* 137 7 */ CWORD_CWORD_CWORD_CWORD,
2867 /* 138 8 */ CWORD_CWORD_CWORD_CWORD,
2868 /* 139 9 "\t" */ CSPCL_CWORD_CWORD_CWORD,
2869 /* 140 10 "\n" */ CNL_CNL_CNL_CNL,
2870 /* 141 11 */ CWORD_CWORD_CWORD_CWORD,
2871 /* 142 12 */ CWORD_CWORD_CWORD_CWORD,
2872 /* 143 13 */ CWORD_CWORD_CWORD_CWORD,
2873 /* 144 14 */ CWORD_CWORD_CWORD_CWORD,
2874 /* 145 15 */ CWORD_CWORD_CWORD_CWORD,
2875 /* 146 16 */ CWORD_CWORD_CWORD_CWORD,
2876 /* 147 17 */ CWORD_CWORD_CWORD_CWORD,
2877 /* 148 18 */ CWORD_CWORD_CWORD_CWORD,
2878 /* 149 19 */ CWORD_CWORD_CWORD_CWORD,
2879 /* 150 20 */ CWORD_CWORD_CWORD_CWORD,
2880 /* 151 21 */ CWORD_CWORD_CWORD_CWORD,
2881 /* 152 22 */ CWORD_CWORD_CWORD_CWORD,
2882 /* 153 23 */ CWORD_CWORD_CWORD_CWORD,
2883 /* 154 24 */ CWORD_CWORD_CWORD_CWORD,
2884 /* 155 25 */ CWORD_CWORD_CWORD_CWORD,
2885 /* 156 26 */ CWORD_CWORD_CWORD_CWORD,
2886 /* 157 27 */ CWORD_CWORD_CWORD_CWORD,
2887 /* 158 28 */ CWORD_CWORD_CWORD_CWORD,
2888 /* 159 29 */ CWORD_CWORD_CWORD_CWORD,
2889 /* 160 30 */ CWORD_CWORD_CWORD_CWORD,
2890 /* 161 31 */ CWORD_CWORD_CWORD_CWORD,
2891 /* 162 32 " " */ CSPCL_CWORD_CWORD_CWORD,
2892 /* 163 33 "!" */ CWORD_CCTL_CCTL_CWORD,
2893 /* 164 34 """ */ CDQUOTE_CENDQUOTE_CWORD_CWORD,
2894 /* 165 35 "#" */ CWORD_CWORD_CWORD_CWORD,
2895 /* 166 36 "$" */ CVAR_CVAR_CWORD_CVAR,
2896 /* 167 37 "%" */ CWORD_CWORD_CWORD_CWORD,
2897 /* 168 38 "&" */ CSPCL_CWORD_CWORD_CWORD,
2898 /* 169 39 "'" */ CSQUOTE_CWORD_CENDQUOTE_CWORD,
2899 /* 170 40 "(" */ CSPCL_CWORD_CWORD_CLP,
2900 /* 171 41 ")" */ CSPCL_CWORD_CWORD_CRP,
2901 /* 172 42 "*" */ CWORD_CCTL_CCTL_CWORD,
2902 /* 173 43 "+" */ CWORD_CWORD_CWORD_CWORD,
2903 /* 174 44 "," */ CWORD_CWORD_CWORD_CWORD,
2904 /* 175 45 "-" */ CWORD_CCTL_CCTL_CWORD,
2905 /* 176 46 "." */ CWORD_CWORD_CWORD_CWORD,
2906 /* 177 47 "/" */ CWORD_CCTL_CCTL_CWORD,
2907 /* 178 48 "0" */ CWORD_CWORD_CWORD_CWORD,
2908 /* 179 49 "1" */ CWORD_CWORD_CWORD_CWORD,
2909 /* 180 50 "2" */ CWORD_CWORD_CWORD_CWORD,
2910 /* 181 51 "3" */ CWORD_CWORD_CWORD_CWORD,
2911 /* 182 52 "4" */ CWORD_CWORD_CWORD_CWORD,
2912 /* 183 53 "5" */ CWORD_CWORD_CWORD_CWORD,
2913 /* 184 54 "6" */ CWORD_CWORD_CWORD_CWORD,
2914 /* 185 55 "7" */ CWORD_CWORD_CWORD_CWORD,
2915 /* 186 56 "8" */ CWORD_CWORD_CWORD_CWORD,
2916 /* 187 57 "9" */ CWORD_CWORD_CWORD_CWORD,
2917 /* 188 58 ":" */ CWORD_CCTL_CCTL_CWORD,
2918 /* 189 59 ";" */ CSPCL_CWORD_CWORD_CWORD,
2919 /* 190 60 "<" */ CSPCL_CWORD_CWORD_CWORD,
2920 /* 191 61 "=" */ CWORD_CCTL_CCTL_CWORD,
2921 /* 192 62 ">" */ CSPCL_CWORD_CWORD_CWORD,
2922 /* 193 63 "?" */ CWORD_CCTL_CCTL_CWORD,
2923 /* 194 64 "@" */ CWORD_CWORD_CWORD_CWORD,
2924 /* 195 65 "A" */ CWORD_CWORD_CWORD_CWORD,
2925 /* 196 66 "B" */ CWORD_CWORD_CWORD_CWORD,
2926 /* 197 67 "C" */ CWORD_CWORD_CWORD_CWORD,
2927 /* 198 68 "D" */ CWORD_CWORD_CWORD_CWORD,
2928 /* 199 69 "E" */ CWORD_CWORD_CWORD_CWORD,
2929 /* 200 70 "F" */ CWORD_CWORD_CWORD_CWORD,
2930 /* 201 71 "G" */ CWORD_CWORD_CWORD_CWORD,
2931 /* 202 72 "H" */ CWORD_CWORD_CWORD_CWORD,
2932 /* 203 73 "I" */ CWORD_CWORD_CWORD_CWORD,
2933 /* 204 74 "J" */ CWORD_CWORD_CWORD_CWORD,
2934 /* 205 75 "K" */ CWORD_CWORD_CWORD_CWORD,
2935 /* 206 76 "L" */ CWORD_CWORD_CWORD_CWORD,
2936 /* 207 77 "M" */ CWORD_CWORD_CWORD_CWORD,
2937 /* 208 78 "N" */ CWORD_CWORD_CWORD_CWORD,
2938 /* 209 79 "O" */ CWORD_CWORD_CWORD_CWORD,
2939 /* 210 80 "P" */ CWORD_CWORD_CWORD_CWORD,
2940 /* 211 81 "Q" */ CWORD_CWORD_CWORD_CWORD,
2941 /* 212 82 "R" */ CWORD_CWORD_CWORD_CWORD,
2942 /* 213 83 "S" */ CWORD_CWORD_CWORD_CWORD,
2943 /* 214 84 "T" */ CWORD_CWORD_CWORD_CWORD,
2944 /* 215 85 "U" */ CWORD_CWORD_CWORD_CWORD,
2945 /* 216 86 "V" */ CWORD_CWORD_CWORD_CWORD,
2946 /* 217 87 "W" */ CWORD_CWORD_CWORD_CWORD,
2947 /* 218 88 "X" */ CWORD_CWORD_CWORD_CWORD,
2948 /* 219 89 "Y" */ CWORD_CWORD_CWORD_CWORD,
2949 /* 220 90 "Z" */ CWORD_CWORD_CWORD_CWORD,
2950 /* 221 91 "[" */ CWORD_CCTL_CCTL_CWORD,
2951 /* 222 92 "\" */ CBACK_CBACK_CCTL_CBACK,
2952 /* 223 93 "]" */ CWORD_CCTL_CCTL_CWORD,
2953 /* 224 94 "^" */ CWORD_CWORD_CWORD_CWORD,
2954 /* 225 95 "_" */ CWORD_CWORD_CWORD_CWORD,
2955 /* 226 96 "`" */ CBQUOTE_CBQUOTE_CWORD_CBQUOTE,
2956 /* 227 97 "a" */ CWORD_CWORD_CWORD_CWORD,
2957 /* 228 98 "b" */ CWORD_CWORD_CWORD_CWORD,
2958 /* 229 99 "c" */ CWORD_CWORD_CWORD_CWORD,
2959 /* 230 100 "d" */ CWORD_CWORD_CWORD_CWORD,
2960 /* 231 101 "e" */ CWORD_CWORD_CWORD_CWORD,
2961 /* 232 102 "f" */ CWORD_CWORD_CWORD_CWORD,
2962 /* 233 103 "g" */ CWORD_CWORD_CWORD_CWORD,
2963 /* 234 104 "h" */ CWORD_CWORD_CWORD_CWORD,
2964 /* 235 105 "i" */ CWORD_CWORD_CWORD_CWORD,
2965 /* 236 106 "j" */ CWORD_CWORD_CWORD_CWORD,
2966 /* 237 107 "k" */ CWORD_CWORD_CWORD_CWORD,
2967 /* 238 108 "l" */ CWORD_CWORD_CWORD_CWORD,
2968 /* 239 109 "m" */ CWORD_CWORD_CWORD_CWORD,
2969 /* 240 110 "n" */ CWORD_CWORD_CWORD_CWORD,
2970 /* 241 111 "o" */ CWORD_CWORD_CWORD_CWORD,
2971 /* 242 112 "p" */ CWORD_CWORD_CWORD_CWORD,
2972 /* 243 113 "q" */ CWORD_CWORD_CWORD_CWORD,
2973 /* 244 114 "r" */ CWORD_CWORD_CWORD_CWORD,
2974 /* 245 115 "s" */ CWORD_CWORD_CWORD_CWORD,
2975 /* 246 116 "t" */ CWORD_CWORD_CWORD_CWORD,
2976 /* 247 117 "u" */ CWORD_CWORD_CWORD_CWORD,
2977 /* 248 118 "v" */ CWORD_CWORD_CWORD_CWORD,
2978 /* 249 119 "w" */ CWORD_CWORD_CWORD_CWORD,
2979 /* 250 120 "x" */ CWORD_CWORD_CWORD_CWORD,
2980 /* 251 121 "y" */ CWORD_CWORD_CWORD_CWORD,
2981 /* 252 122 "z" */ CWORD_CWORD_CWORD_CWORD,
2982 /* 253 123 "{" */ CWORD_CWORD_CWORD_CWORD,
2983 /* 254 124 "|" */ CSPCL_CWORD_CWORD_CWORD,
2984 /* 255 125 "}" */ CENDVAR_CENDVAR_CWORD_CENDVAR,
2985 /* 256 126 "~" */ CWORD_CCTL_CCTL_CWORD,
2986 /* 257 127 */ CWORD_CWORD_CWORD_CWORD,
2989 #define SIT(c, syntax) (S_I_T[(int)syntax_index_table[((int)c)+SYNBASE]][syntax])
2991 #endif /* USE_SIT_FUNCTION */
2994 /* ============ Alias handling */
2996 #if ENABLE_ASH_ALIAS
2998 #define ALIASINUSE 1
3009 static struct alias **atab; // [ATABSIZE];
3010 #define INIT_G_alias() do { \
3011 atab = xzalloc(ATABSIZE * sizeof(atab[0])); \
3015 static struct alias **
3016 __lookupalias(const char *name) {
3017 unsigned int hashval;
3024 ch = (unsigned char)*p;
3028 ch = (unsigned char)*++p;
3030 app = &atab[hashval % ATABSIZE];
3032 for (; *app; app = &(*app)->next) {
3033 if (strcmp(name, (*app)->name) == 0) {
3041 static struct alias *
3042 lookupalias(const char *name, int check)
3044 struct alias *ap = *__lookupalias(name);
3046 if (check && ap && (ap->flag & ALIASINUSE))
3051 static struct alias *
3052 freealias(struct alias *ap)
3056 if (ap->flag & ALIASINUSE) {
3057 ap->flag |= ALIASDEAD;
3069 setalias(const char *name, const char *val)
3071 struct alias *ap, **app;
3073 app = __lookupalias(name);
3077 if (!(ap->flag & ALIASINUSE)) {
3080 ap->val = ckstrdup(val);
3081 ap->flag &= ~ALIASDEAD;
3084 ap = ckzalloc(sizeof(struct alias));
3085 ap->name = ckstrdup(name);
3086 ap->val = ckstrdup(val);
3087 /*ap->flag = 0; - ckzalloc did it */
3088 /*ap->next = NULL;*/
3095 unalias(const char *name)
3099 app = __lookupalias(name);
3103 *app = freealias(*app);
3114 struct alias *ap, **app;
3118 for (i = 0; i < ATABSIZE; i++) {
3120 for (ap = *app; ap; ap = *app) {
3121 *app = freealias(*app);
3131 printalias(const struct alias *ap)
3133 out1fmt("%s=%s\n", ap->name, single_quote(ap->val));
3137 * TODO - sort output
3140 aliascmd(int argc UNUSED_PARAM, char **argv)
3149 for (i = 0; i < ATABSIZE; i++) {
3150 for (ap = atab[i]; ap; ap = ap->next) {
3156 while ((n = *++argv) != NULL) {
3157 v = strchr(n+1, '=');
3158 if (v == NULL) { /* n+1: funny ksh stuff */
3159 ap = *__lookupalias(n);
3161 fprintf(stderr, "%s: %s not found\n", "alias", n);
3175 unaliascmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
3179 while ((i = nextopt("a")) != '\0') {
3185 for (i = 0; *argptr; argptr++) {
3186 if (unalias(*argptr)) {
3187 fprintf(stderr, "%s: %s not found\n", "unalias", *argptr);
3195 #endif /* ASH_ALIAS */
3198 /* ============ jobs.c */
3200 /* Mode argument to forkshell. Don't change FORK_FG or FORK_BG. */
3203 #define FORK_NOJOB 2
3205 /* mode flags for showjob(s) */
3206 #define SHOW_PGID 0x01 /* only show pgid - for jobs -p */
3207 #define SHOW_PID 0x04 /* include process pid */
3208 #define SHOW_CHANGED 0x08 /* only jobs whose state has changed */
3211 * A job structure contains information about a job. A job is either a
3212 * single process or a set of processes contained in a pipeline. In the
3213 * latter case, pidlist will be non-NULL, and will point to a -1 terminated
3218 pid_t pid; /* process id */
3219 int status; /* last process status from wait() */
3220 char *cmd; /* text of command being run */
3224 struct procstat ps0; /* status of process */
3225 struct procstat *ps; /* status or processes when more than one */
3227 int stopstatus; /* status of a stopped job */
3230 nprocs: 16, /* number of processes */
3232 #define JOBRUNNING 0 /* at least one proc running */
3233 #define JOBSTOPPED 1 /* all procs are stopped */
3234 #define JOBDONE 2 /* all procs are completed */
3236 sigint: 1, /* job was killed by SIGINT */
3237 jobctl: 1, /* job running under job control */
3239 waited: 1, /* true if this entry has been waited for */
3240 used: 1, /* true if this entry is in used */
3241 changed: 1; /* true if status has changed */
3242 struct job *prev_job; /* previous job */
3245 static struct job *makejob(/*union node *,*/ int);
3247 #define forkshell(job, node, mode) forkshell(job, mode)
3249 static int forkshell(struct job *, union node *, int);
3250 static int waitforjob(struct job *);
3253 enum { doing_jobctl = 0 };
3254 #define setjobctl(on) do {} while (0)
3256 static smallint doing_jobctl; //references:8
3257 static void setjobctl(int);
3261 * Set the signal handler for the specified signal. The routine figures
3262 * out what it should be set to.
3265 setsignal(int signo)
3269 struct sigaction act;
3275 else if (*t != '\0')
3277 if (rootshell && action == S_DFL) {
3280 if (iflag || minusc || sflag == 0)
3303 t = &sigmode[signo - 1];
3307 * current setting unknown
3309 if (sigaction(signo, NULL, &act) == -1) {
3311 * Pretend it worked; maybe we should give a warning
3312 * here, but other shells don't. We don't alter
3313 * sigmode, so that we retry every time.
3317 tsig = S_RESET; /* force to be set */
3318 if (act.sa_handler == SIG_IGN) {
3321 && (signo == SIGTSTP || signo == SIGTTIN || signo == SIGTTOU)
3323 tsig = S_IGN; /* don't hard ignore these */
3327 if (tsig == S_HARD_IGN || tsig == action)
3329 act.sa_handler = SIG_DFL;
3332 act.sa_handler = onsig;
3335 act.sa_handler = SIG_IGN;
3340 sigfillset(&act.sa_mask);
3341 sigaction_set(signo, &act);
3344 /* mode flags for set_curjob */
3345 #define CUR_DELETE 2
3346 #define CUR_RUNNING 1
3347 #define CUR_STOPPED 0
3349 /* mode flags for dowait */
3350 #define DOWAIT_NONBLOCK WNOHANG
3351 #define DOWAIT_BLOCK 0
3354 /* pgrp of shell on invocation */
3355 static int initialpgrp; //references:2
3356 static int ttyfd = -1; //5
3359 static struct job *jobtab; //5
3361 static unsigned njobs; //4
3363 static struct job *curjob; //lots
3364 /* number of presumed living untracked jobs */
3365 static int jobless; //4
3368 set_curjob(struct job *jp, unsigned mode)
3371 struct job **jpp, **curp;
3373 /* first remove from list */
3374 jpp = curp = &curjob;
3379 jpp = &jp1->prev_job;
3381 *jpp = jp1->prev_job;
3383 /* Then re-insert in correct position */
3391 /* job being deleted */
3394 /* newly created job or backgrounded job,
3395 put after all stopped jobs. */
3399 if (!jp1 || jp1->state != JOBSTOPPED)
3402 jpp = &jp1->prev_job;
3408 /* newly stopped job - becomes curjob */
3409 jp->prev_job = *jpp;
3417 jobno(const struct job *jp)
3419 return jp - jobtab + 1;
3424 * Convert a job name to a job structure.
3427 #define getjob(name, getctl) getjob(name)
3430 getjob(const char *name, int getctl)
3434 const char *err_msg = "No such job: %s";
3438 char *(*match)(const char *, const char *);
3453 if (c == '+' || c == '%') {
3455 err_msg = "No current job";
3461 err_msg = "No previous job";
3470 // TODO: number() instead? It does error checking...
3473 jp = jobtab + num - 1;
3490 if (match(jp->ps[0].cmd, p)) {
3494 err_msg = "%s: ambiguous";
3501 err_msg = "job %s not created under job control";
3502 if (getctl && jp->jobctl == 0)
3507 ash_msg_and_raise_error(err_msg, name);
3511 * Mark a job structure as unused.
3514 freejob(struct job *jp)
3516 struct procstat *ps;
3520 for (i = jp->nprocs, ps = jp->ps; --i >= 0; ps++) {
3521 if (ps->cmd != nullstr)
3524 if (jp->ps != &jp->ps0)
3527 set_curjob(jp, CUR_DELETE);
3533 xtcsetpgrp(int fd, pid_t pgrp)
3535 if (tcsetpgrp(fd, pgrp))
3536 ash_msg_and_raise_error("can't set tty process group (%m)");
3540 * Turn job control on and off.
3542 * Note: This code assumes that the third arg to ioctl is a character
3543 * pointer, which is true on Berkeley systems but not System V. Since
3544 * System V doesn't have job control yet, this isn't a problem now.
3546 * Called with interrupts off.
3554 if (on == doing_jobctl || rootshell == 0)
3558 ofd = fd = open(_PATH_TTY, O_RDWR);
3560 /* BTW, bash will try to open(ttyname(0)) if open("/dev/tty") fails.
3561 * That sometimes helps to acquire controlling tty.
3562 * Obviously, a workaround for bugs when someone
3563 * failed to provide a controlling tty to bash! :) */
3569 fd = fcntl(fd, F_DUPFD, 10);
3574 /* fd is a tty at this point */
3575 close_on_exec_on(fd);
3576 do { /* while we are in the background */
3577 pgrp = tcgetpgrp(fd);
3580 ash_msg("can't access tty; job control turned off");
3584 if (pgrp == getpgrp())
3595 xtcsetpgrp(fd, pgrp);
3597 /* turning job control off */
3600 /* was xtcsetpgrp, but this can make exiting ash
3601 * loop forever if pty is already deleted */
3602 tcsetpgrp(fd, pgrp);
3617 killcmd(int argc, char **argv)
3620 if (argv[1] && strcmp(argv[1], "-l") != 0) {
3622 if (argv[i][0] == '%') {
3623 struct job *jp = getjob(argv[i], 0);
3624 unsigned pid = jp->ps[0].pid;
3625 /* Enough space for ' -NNN<nul>' */
3626 argv[i] = alloca(sizeof(int)*3 + 3);
3627 /* kill_main has matching code to expect
3628 * leading space. Needed to not confuse
3629 * negative pids with "kill -SIGNAL_NO" syntax */
3630 sprintf(argv[i], " -%u", pid);
3632 } while (argv[++i]);
3634 return kill_main(argc, argv);
3638 showpipe(struct job *jp, FILE *out)
3640 struct procstat *sp;
3641 struct procstat *spend;
3643 spend = jp->ps + jp->nprocs;
3644 for (sp = jp->ps + 1; sp < spend; sp++)
3645 fprintf(out, " | %s", sp->cmd);
3646 outcslow('\n', out);
3647 flush_stdout_stderr();
3652 restartjob(struct job *jp, int mode)
3654 struct procstat *ps;
3660 if (jp->state == JOBDONE)
3662 jp->state = JOBRUNNING;
3664 if (mode == FORK_FG)
3665 xtcsetpgrp(ttyfd, pgid);
3666 killpg(pgid, SIGCONT);
3670 if (WIFSTOPPED(ps->status)) {
3676 status = (mode == FORK_FG) ? waitforjob(jp) : 0;
3682 fg_bgcmd(int argc UNUSED_PARAM, char **argv)
3689 mode = (**argv == 'f') ? FORK_FG : FORK_BG;
3694 jp = getjob(*argv, 1);
3695 if (mode == FORK_BG) {
3696 set_curjob(jp, CUR_RUNNING);
3697 fprintf(out, "[%d] ", jobno(jp));
3699 outstr(jp->ps->cmd, out);
3701 retval = restartjob(jp, mode);
3702 } while (*argv && *++argv);
3708 sprint_status(char *s, int status, int sigonly)
3714 if (!WIFEXITED(status)) {
3716 if (WIFSTOPPED(status))
3717 st = WSTOPSIG(status);
3720 st = WTERMSIG(status);
3722 if (st == SIGINT || st == SIGPIPE)
3725 if (WIFSTOPPED(status))
3730 col = fmtstr(s, 32, strsignal(st));
3731 if (WCOREDUMP(status)) {
3732 col += fmtstr(s + col, 16, " (core dumped)");
3734 } else if (!sigonly) {
3735 st = WEXITSTATUS(status);
3737 col = fmtstr(s, 16, "Done(%d)", st);
3739 col = fmtstr(s, 16, "Done");
3746 * Do a wait system call. If job control is compiled in, we accept
3747 * stopped processes. If block is zero, we return a value of zero
3748 * rather than blocking.
3750 * System V doesn't have a non-blocking wait system call. It does
3751 * have a SIGCLD signal that is sent to a process when one of it's
3752 * children dies. The obvious way to use SIGCLD would be to install
3753 * a handler for SIGCLD which simply bumped a counter when a SIGCLD
3754 * was received, and have waitproc bump another counter when it got
3755 * the status of a process. Waitproc would then know that a wait
3756 * system call would not block if the two counters were different.
3757 * This approach doesn't work because if a process has children that
3758 * have not been waited for, System V will send it a SIGCLD when it
3759 * installs a signal handler for SIGCLD. What this means is that when
3760 * a child exits, the shell will be sent SIGCLD signals continuously
3761 * until is runs out of stack space, unless it does a wait call before
3762 * restoring the signal handler. The code below takes advantage of
3763 * this (mis)feature by installing a signal handler for SIGCLD and
3764 * then checking to see whether it was called. If there are any
3765 * children to be waited for, it will be.
3767 * If neither SYSV nor BSD is defined, we don't implement nonblocking
3768 * waits at all. In this case, the user will not be informed when
3769 * a background process until the next time she runs a real program
3770 * (as opposed to running a builtin command or just typing return),
3771 * and the jobs command may give out of date information.
3774 waitproc(int wait_flags, int *status)
3778 wait_flags |= WUNTRACED;
3780 /* NB: _not_ safe_waitpid, we need to detect EINTR */
3781 return waitpid(-1, status, wait_flags);
3785 * Wait for a process to terminate.
3788 dowait(int wait_flags, struct job *job)
3793 struct job *thisjob;
3796 TRACE(("dowait(%d) called\n", wait_flags));
3797 pid = waitproc(wait_flags, &status);
3798 TRACE(("wait returns pid=%d, status=%d\n", pid, status));
3800 /* If we were doing blocking wait and (probably) got EINTR,
3801 * check for pending sigs received while waiting.
3802 * (NB: can be moved into callers if needed) */
3803 if (wait_flags == DOWAIT_BLOCK && pendingsig)
3804 raise_exception(EXSIG);
3809 for (jp = curjob; jp; jp = jp->prev_job) {
3810 struct procstat *sp;
3811 struct procstat *spend;
3812 if (jp->state == JOBDONE)
3815 spend = jp->ps + jp->nprocs;
3818 if (sp->pid == pid) {
3819 TRACE(("Job %d: changing status of proc %d "
3820 "from 0x%x to 0x%x\n",
3821 jobno(jp), pid, sp->status, status));
3822 sp->status = status;
3825 if (sp->status == -1)
3828 if (state == JOBRUNNING)
3830 if (WIFSTOPPED(sp->status)) {
3831 jp->stopstatus = sp->status;
3835 } while (++sp < spend);
3840 if (!WIFSTOPPED(status))
3846 if (state != JOBRUNNING) {
3847 thisjob->changed = 1;
3849 if (thisjob->state != state) {
3850 TRACE(("Job %d: changing state from %d to %d\n",
3851 jobno(thisjob), thisjob->state, state));
3852 thisjob->state = state;
3854 if (state == JOBSTOPPED) {
3855 set_curjob(thisjob, CUR_STOPPED);
3864 if (thisjob && thisjob == job) {
3868 len = sprint_status(s, status, 1);
3880 showjob(FILE *out, struct job *jp, int mode)
3882 struct procstat *ps;
3883 struct procstat *psend;
3890 if (mode & SHOW_PGID) {
3891 /* just output process (group) id of pipeline */
3892 fprintf(out, "%d\n", ps->pid);
3896 col = fmtstr(s, 16, "[%d] ", jobno(jp));
3901 else if (curjob && jp == curjob->prev_job)
3904 if (mode & SHOW_PID)
3905 col += fmtstr(s + col, 16, "%d ", ps->pid);
3907 psend = ps + jp->nprocs;
3909 if (jp->state == JOBRUNNING) {
3910 strcpy(s + col, "Running");
3911 col += sizeof("Running") - 1;
3913 int status = psend[-1].status;
3914 if (jp->state == JOBSTOPPED)
3915 status = jp->stopstatus;
3916 col += sprint_status(s + col, status, 0);
3922 /* for each process */
3923 col = fmtstr(s, 48, " |\n%*c%d ", indent_col, ' ', ps->pid) - 3;
3925 fprintf(out, "%s%*c%s",
3926 s, 33 - col >= 0 ? 33 - col : 0, ' ', ps->cmd
3928 if (!(mode & SHOW_PID)) {
3932 if (++ps == psend) {
3933 outcslow('\n', out);
3940 if (jp->state == JOBDONE) {
3941 TRACE(("showjob: freeing job %d\n", jobno(jp)));
3947 * Print a list of jobs. If "change" is nonzero, only print jobs whose
3948 * statuses have changed since the last call to showjobs.
3951 showjobs(FILE *out, int mode)
3955 TRACE(("showjobs(%x) called\n", mode));
3957 /* If not even one job changed, there is nothing to do */
3958 while (dowait(DOWAIT_NONBLOCK, NULL) > 0)
3961 for (jp = curjob; jp; jp = jp->prev_job) {
3962 if (!(mode & SHOW_CHANGED) || jp->changed) {
3963 showjob(out, jp, mode);
3969 jobscmd(int argc UNUSED_PARAM, char **argv)
3974 while ((m = nextopt("lp"))) {
3984 showjob(stdout, getjob(*argv,0), mode);
3987 showjobs(stdout, mode);
3994 getstatus(struct job *job)
3999 status = job->ps[job->nprocs - 1].status;
4000 retval = WEXITSTATUS(status);
4001 if (!WIFEXITED(status)) {
4003 retval = WSTOPSIG(status);
4004 if (!WIFSTOPPED(status))
4007 /* XXX: limits number of signals */
4008 retval = WTERMSIG(status);
4010 if (retval == SIGINT)
4016 TRACE(("getstatus: job %d, nproc %d, status %x, retval %x\n",
4017 jobno(job), job->nprocs, status, retval));
4022 waitcmd(int argc UNUSED_PARAM, char **argv)
4031 raise_exception(EXSIG);
4038 /* wait for all jobs */
4042 if (!jp) /* no running procs */
4044 if (jp->state == JOBRUNNING)
4049 dowait(DOWAIT_BLOCK, NULL);
4055 if (**argv != '%') {
4056 pid_t pid = number(*argv);
4061 if (job->ps[job->nprocs - 1].pid == pid)
4063 job = job->prev_job;
4066 job = getjob(*argv, 0);
4067 /* loop until process terminated or stopped */
4068 while (job->state == JOBRUNNING)
4069 dowait(DOWAIT_BLOCK, NULL);
4071 retval = getstatus(job);
4085 struct job *jp, *jq;
4087 len = njobs * sizeof(*jp);
4089 jp = ckrealloc(jq, len + 4 * sizeof(*jp));
4091 offset = (char *)jp - (char *)jq;
4093 /* Relocate pointers */
4096 jq = (struct job *)((char *)jq + l);
4100 #define joff(p) ((struct job *)((char *)(p) + l))
4101 #define jmove(p) (p) = (void *)((char *)(p) + offset)
4102 if (joff(jp)->ps == &jq->ps0)
4103 jmove(joff(jp)->ps);
4104 if (joff(jp)->prev_job)
4105 jmove(joff(jp)->prev_job);
4115 jp = (struct job *)((char *)jp + len);
4119 } while (--jq >= jp);
4124 * Return a new job structure.
4125 * Called with interrupts off.
4128 makejob(/*union node *node,*/ int nprocs)
4133 for (i = njobs, jp = jobtab; ; jp++) {
4140 if (jp->state != JOBDONE || !jp->waited)
4149 memset(jp, 0, sizeof(*jp));
4151 /* jp->jobctl is a bitfield.
4152 * "jp->jobctl |= jobctl" likely to give awful code */
4156 jp->prev_job = curjob;
4161 jp->ps = ckmalloc(nprocs * sizeof(struct procstat));
4163 TRACE(("makejob(%d) returns %%%d\n", nprocs,
4170 * Return a string identifying a command (to be printed by the
4173 static char *cmdnextc;
4176 cmdputs(const char *s)
4178 static const char vstype[VSTYPE + 1][3] = {
4179 "", "}", "-", "+", "?", "=",
4180 "%", "%%", "#", "##"
4181 USE_ASH_BASH_COMPAT(, ":", "/", "//")
4184 const char *p, *str;
4185 char c, cc[2] = " ";
4190 nextc = makestrspace((strlen(s) + 1) * 8, cmdnextc);
4192 while ((c = *p++) != 0) {
4200 if ((subtype & VSTYPE) == VSLENGTH)
4204 if (!(subtype & VSQUOTE) == !(quoted & 1))
4210 str = "\"}" + !(quoted & 1);
4217 case CTLBACKQ+CTLQUOTE:
4220 #if ENABLE_ASH_MATH_SUPPORT
4235 if ((subtype & VSTYPE) != VSNORMAL)
4237 str = vstype[subtype & VSTYPE];
4238 if (subtype & VSNUL)
4247 /* These can only happen inside quotes */
4260 while ((c = *str++)) {
4265 USTPUTC('"', nextc);
4271 /* cmdtxt() and cmdlist() call each other */
4272 static void cmdtxt(union node *n);
4275 cmdlist(union node *np, int sep)
4277 for (; np; np = np->narg.next) {
4281 if (sep && np->narg.next)
4287 cmdtxt(union node *n)
4290 struct nodelist *lp;
4301 lp = n->npipe.cmdlist;
4319 cmdtxt(n->nbinary.ch1);
4335 cmdtxt(n->nif.test);
4338 if (n->nif.elsepart) {
4341 n = n->nif.elsepart;
4357 cmdtxt(n->nbinary.ch1);
4367 cmdputs(n->nfor.var);
4369 cmdlist(n->nfor.args, 1);
4374 cmdputs(n->narg.text);
4378 cmdlist(n->ncmd.args, 1);
4379 cmdlist(n->ncmd.redirect, 0);
4392 cmdputs(n->ncase.expr->narg.text);
4394 for (np = n->ncase.cases; np; np = np->nclist.next) {
4395 cmdtxt(np->nclist.pattern);
4397 cmdtxt(np->nclist.body);
4423 cmdputs(utoa(n->nfile.fd));
4425 if (n->type == NTOFD || n->type == NFROMFD) {
4426 cmdputs(utoa(n->ndup.dupfd));
4435 commandtext(union node *n)
4439 STARTSTACKSTR(cmdnextc);
4441 name = stackblock();
4442 TRACE(("commandtext: name %p, end %p\n\t\"%s\"\n",
4443 name, cmdnextc, cmdnextc));
4444 return ckstrdup(name);
4449 * Fork off a subshell. If we are doing job control, give the subshell its
4450 * own process group. Jp is a job structure that the job is to be added to.
4451 * N is the command that will be evaluated by the child. Both jp and n may
4452 * be NULL. The mode parameter can be one of the following:
4453 * FORK_FG - Fork off a foreground process.
4454 * FORK_BG - Fork off a background process.
4455 * FORK_NOJOB - Like FORK_FG, but don't give the process its own
4456 * process group even if job control is on.
4458 * When job control is turned off, background processes have their standard
4459 * input redirected to /dev/null (except for the second and later processes
4462 * Called with interrupts off.
4465 * Clear traps on a fork.
4472 for (tp = trap; tp < &trap[NSIG]; tp++) {
4473 if (*tp && **tp) { /* trap not NULL or "" (SIG_IGN) */
4478 setsignal(tp - trap);
4484 /* Lives far away from here, needed for forkchild */
4485 static void closescript(void);
4487 /* Called after fork(), in child */
4489 forkchild(struct job *jp, /*union node *n,*/ int mode)
4493 TRACE(("Child shell %d\n", getpid()));
4500 /* do job control only in root shell */
4502 if (mode != FORK_NOJOB && jp->jobctl && !oldlvl) {
4505 if (jp->nprocs == 0)
4508 pgrp = jp->ps[0].pid;
4509 /* This can fail because we are doing it in the parent also */
4510 (void)setpgid(0, pgrp);
4511 if (mode == FORK_FG)
4512 xtcsetpgrp(ttyfd, pgrp);
4517 if (mode == FORK_BG) {
4520 if (jp->nprocs == 0) {
4522 if (open(bb_dev_null, O_RDONLY) != 0)
4523 ash_msg_and_raise_error("can't open %s", bb_dev_null);
4526 if (!oldlvl && iflag) {
4531 for (jp = curjob; jp; jp = jp->prev_job)
4536 /* Called after fork(), in parent */
4538 #define forkparent(jp, n, mode, pid) forkparent(jp, mode, pid)
4541 forkparent(struct job *jp, union node *n, int mode, pid_t pid)
4543 TRACE(("In parent shell: child = %d\n", pid));
4545 while (jobless && dowait(DOWAIT_NONBLOCK, NULL) > 0)
4551 if (mode != FORK_NOJOB && jp->jobctl) {
4554 if (jp->nprocs == 0)
4557 pgrp = jp->ps[0].pid;
4558 /* This can fail because we are doing it in the child also */
4562 if (mode == FORK_BG) {
4563 backgndpid = pid; /* set $! */
4564 set_curjob(jp, CUR_RUNNING);
4567 struct procstat *ps = &jp->ps[jp->nprocs++];
4572 if (doing_jobctl && n)
4573 ps->cmd = commandtext(n);
4579 forkshell(struct job *jp, union node *n, int mode)
4583 TRACE(("forkshell(%%%d, %p, %d) called\n", jobno(jp), n, mode));
4586 TRACE(("Fork failed, errno=%d", errno));
4589 ash_msg_and_raise_error("can't fork");
4592 forkchild(jp, /*n,*/ mode);
4594 forkparent(jp, n, mode, pid);
4599 * Wait for job to finish.
4601 * Under job control we have the problem that while a child process is
4602 * running interrupts generated by the user are sent to the child but not
4603 * to the shell. This means that an infinite loop started by an inter-
4604 * active user may be hard to kill. With job control turned off, an
4605 * interactive user may place an interactive program inside a loop. If
4606 * the interactive program catches interrupts, the user doesn't want
4607 * these interrupts to also abort the loop. The approach we take here
4608 * is to have the shell ignore interrupt signals while waiting for a
4609 * foreground process to terminate, and then send itself an interrupt
4610 * signal if the child process was terminated by an interrupt signal.
4611 * Unfortunately, some programs want to do a bit of cleanup and then
4612 * exit on interrupt; unless these processes terminate themselves by
4613 * sending a signal to themselves (instead of calling exit) they will
4614 * confuse this approach.
4616 * Called with interrupts off.
4619 waitforjob(struct job *jp)
4623 TRACE(("waitforjob(%%%d) called\n", jobno(jp)));
4624 while (jp->state == JOBRUNNING) {
4625 dowait(DOWAIT_BLOCK, jp);
4630 xtcsetpgrp(ttyfd, rootpid);
4632 * This is truly gross.
4633 * If we're doing job control, then we did a TIOCSPGRP which
4634 * caused us (the shell) to no longer be in the controlling
4635 * session -- so we wouldn't have seen any ^C/SIGINT. So, we
4636 * intuit from the subprocess exit status whether a SIGINT
4637 * occurred, and if so interrupt ourselves. Yuck. - mycroft
4639 if (jp->sigint) /* TODO: do the same with all signals */
4640 raise(SIGINT); /* ... by raise(jp->sig) instead? */
4642 if (jp->state == JOBDONE)
4649 * return 1 if there are stopped jobs, otherwise 0
4661 if (jp && jp->state == JOBSTOPPED) {
4662 out2str("You have stopped jobs.\n");
4671 /* ============ redir.c
4673 * Code for dealing with input/output redirection.
4676 #define EMPTY -2 /* marks an unused slot in redirtab */
4677 #define CLOSED -3 /* marks a slot of previously-closed fd */
4680 * Open a file in noclobber mode.
4681 * The code was copied from bash.
4684 noclobberopen(const char *fname)
4687 struct stat finfo, finfo2;
4690 * If the file exists and is a regular file, return an error
4693 r = stat(fname, &finfo);
4694 if (r == 0 && S_ISREG(finfo.st_mode)) {
4700 * If the file was not present (r != 0), make sure we open it
4701 * exclusively so that if it is created before we open it, our open
4702 * will fail. Make sure that we do not truncate an existing file.
4703 * Note that we don't turn on O_EXCL unless the stat failed -- if the
4704 * file was not a regular file, we leave O_EXCL off.
4707 return open(fname, O_WRONLY|O_CREAT|O_EXCL, 0666);
4708 fd = open(fname, O_WRONLY|O_CREAT, 0666);
4710 /* If the open failed, return the file descriptor right away. */
4715 * OK, the open succeeded, but the file may have been changed from a
4716 * non-regular file to a regular file between the stat and the open.
4717 * We are assuming that the O_EXCL open handles the case where FILENAME
4718 * did not exist and is symlinked to an existing file between the stat
4723 * If we can open it and fstat the file descriptor, and neither check
4724 * revealed that it was a regular file, and the file has not been
4725 * replaced, return the file descriptor.
4727 if (fstat(fd, &finfo2) == 0 && !S_ISREG(finfo2.st_mode)
4728 && finfo.st_dev == finfo2.st_dev && finfo.st_ino == finfo2.st_ino)
4731 /* The file has been replaced. badness. */
4738 * Handle here documents. Normally we fork off a process to write the
4739 * data to a pipe. If the document is short, we can stuff the data in
4740 * the pipe without forking.
4742 /* openhere needs this forward reference */
4743 static void expandhere(union node *arg, int fd);
4745 openhere(union node *redir)
4751 ash_msg_and_raise_error("pipe call failed");
4752 if (redir->type == NHERE) {
4753 len = strlen(redir->nhere.doc->narg.text);
4754 if (len <= PIPE_BUF) {
4755 full_write(pip[1], redir->nhere.doc->narg.text, len);
4759 if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) {
4762 signal(SIGINT, SIG_IGN);
4763 signal(SIGQUIT, SIG_IGN);
4764 signal(SIGHUP, SIG_IGN);
4766 signal(SIGTSTP, SIG_IGN);
4768 signal(SIGPIPE, SIG_DFL);
4769 if (redir->type == NHERE)
4770 full_write(pip[1], redir->nhere.doc->narg.text, len);
4772 expandhere(redir->nhere.doc, pip[1]);
4773 _exit(EXIT_SUCCESS);
4781 openredirect(union node *redir)
4786 switch (redir->nfile.type) {
4788 fname = redir->nfile.expfname;
4789 f = open(fname, O_RDONLY);
4794 fname = redir->nfile.expfname;
4795 f = open(fname, O_RDWR|O_CREAT|O_TRUNC, 0666);
4800 /* Take care of noclobber mode. */
4802 fname = redir->nfile.expfname;
4803 f = noclobberopen(fname);
4810 fname = redir->nfile.expfname;
4811 f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666);
4816 fname = redir->nfile.expfname;
4817 f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666);
4825 /* Fall through to eliminate warning. */
4826 /* Our single caller does this itself */
4833 f = openhere(redir);
4839 ash_msg_and_raise_error("can't create %s: %s", fname, errmsg(errno, "nonexistent directory"));
4841 ash_msg_and_raise_error("can't open %s: %s", fname, errmsg(errno, "no such file"));
4845 * Copy a file descriptor to be >= to. Returns -1
4846 * if the source file descriptor is closed, EMPTY if there are no unused
4847 * file descriptors left.
4849 /* 0x800..00: bit to set in "to" to request dup2 instead of fcntl(F_DUPFD).
4850 * old code was doing close(to) prior to copyfd() to achieve the same */
4852 COPYFD_EXACT = (int)~(INT_MAX),
4853 COPYFD_RESTORE = (int)((unsigned)COPYFD_EXACT >> 1),
4856 copyfd(int from, int to)
4860 if (to & COPYFD_EXACT) {
4861 to &= ~COPYFD_EXACT;
4863 newfd = dup2(from, to);
4865 newfd = fcntl(from, F_DUPFD, to);
4868 if (errno == EMFILE)
4870 /* Happens when source fd is not open: try "echo >&99" */
4871 ash_msg_and_raise_error("%d: %m", from);
4876 /* Struct def and variable are moved down to the first usage site */
4881 struct redirtab *next;
4884 struct two_fd_t two_fd[0];
4886 #define redirlist (G_var.redirlist)
4888 static int need_to_remember(struct redirtab *rp, int fd)
4892 if (!rp) /* remembering was not requested */
4895 for (i = 0; i < rp->pair_count; i++) {
4896 if (rp->two_fd[i].orig == fd) {
4897 /* already remembered */
4904 /* "hidden" fd is a fd used to read scripts, or a copy of such */
4905 static int is_hidden_fd(struct redirtab *rp, int fd)
4908 struct parsefile *pf;
4921 fd |= COPYFD_RESTORE;
4922 for (i = 0; i < rp->pair_count; i++) {
4923 if (rp->two_fd[i].copy == fd) {
4931 * Process a list of redirection commands. If the REDIR_PUSH flag is set,
4932 * old file descriptors are stashed away so that the redirection can be
4933 * undone by calling popredir. If the REDIR_BACKQ flag is set, then the
4934 * standard output, and the standard error if it becomes a duplicate of
4935 * stdout, is saved in memory.
4937 /* flags passed to redirect */
4938 #define REDIR_PUSH 01 /* save previous values of file descriptors */
4939 #define REDIR_SAVEFD2 03 /* set preverrout */
4941 redirect(union node *redir, int flags)
4943 struct redirtab *sv;
4948 int copied_fd2 = -1;
4958 if (flags & REDIR_PUSH) {
4959 union node *tmp = redir;
4962 tmp = tmp->nfile.next;
4964 sv = ckmalloc(sizeof(*sv) + sv_pos * sizeof(sv->two_fd[0]));
4965 sv->next = redirlist;
4966 sv->pair_count = sv_pos;
4968 sv->nullredirs = g_nullredirs - 1;
4970 while (sv_pos > 0) {
4972 sv->two_fd[sv_pos].orig = sv->two_fd[sv_pos].copy = EMPTY;
4977 fd = redir->nfile.fd;
4978 if (redir->nfile.type == NTOFD || redir->nfile.type == NFROMFD) {
4979 int right_fd = redir->ndup.dupfd;
4980 /* redirect from/to same file descriptor? */
4983 /* echo >&10 and 10 is a fd opened to the sh script? */
4984 if (is_hidden_fd(sv, right_fd)) {
4985 errno = EBADF; /* as if it is closed */
4986 ash_msg_and_raise_error("%d: %m", right_fd);
4990 newfd = openredirect(redir); /* always >= 0 */
4992 /* Descriptor wasn't open before redirect.
4993 * Mark it for close in the future */
4994 if (need_to_remember(sv, fd)) {
4995 goto remember_to_close;
5000 if (need_to_remember(sv, fd)) {
5001 /* Copy old descriptor */
5002 i = fcntl(fd, F_DUPFD, 10);
5003 /* You'd expect copy to be CLOEXECed. Currently these extra "saved" fds
5004 * are closed in popredir() in the child, preventing them from leaking
5005 * into child. (popredir() also cleans up the mess in case of failures)
5010 /* Strange error (e.g. "too many files" EMFILE?) */
5014 ash_msg_and_raise_error("%d: %m", fd);
5017 /* EBADF: it is not open - good, remember to close it */
5020 } else { /* fd is open, save its copy */
5021 /* "exec fd>&-" should not close fds
5022 * which point to script file(s).
5023 * Force them to be restored afterwards */
5024 if (is_hidden_fd(sv, fd))
5025 i |= COPYFD_RESTORE;
5029 sv->two_fd[sv_pos].orig = fd;
5030 sv->two_fd[sv_pos].copy = i;
5034 /* NTOFD/NFROMFD: copy redir->ndup.dupfd to fd */
5035 if (redir->ndup.dupfd < 0) { /* "fd>&-" */
5038 copyfd(redir->ndup.dupfd, fd | COPYFD_EXACT);
5040 } else if (fd != newfd) { /* move newfd to fd */
5041 copyfd(newfd, fd | COPYFD_EXACT);
5044 } while ((redir = redir->nfile.next) != NULL);
5047 if ((flags & REDIR_SAVEFD2) && copied_fd2 >= 0)
5048 preverrout_fd = copied_fd2;
5052 * Undo the effects of the last redirection.
5055 popredir(int drop, int restore)
5057 struct redirtab *rp;
5060 if (--g_nullredirs >= 0)
5064 for (i = 0; i < rp->pair_count; i++) {
5065 int fd = rp->two_fd[i].orig;
5066 int copy = rp->two_fd[i].copy;
5067 if (copy == CLOSED) {
5072 if (copy != EMPTY) {
5073 if (!drop || (restore && (copy & COPYFD_RESTORE))) {
5074 copy &= ~COPYFD_RESTORE;
5076 copyfd(copy, fd | COPYFD_EXACT);
5081 redirlist = rp->next;
5082 g_nullredirs = rp->nullredirs;
5088 * Undo all redirections. Called on error or interrupt.
5092 * Discard all saved file descriptors.
5095 clearredir(int drop)
5101 popredir(drop, /*restore:*/ 0);
5106 redirectsafe(union node *redir, int flags)
5109 volatile int saveint;
5110 struct jmploc *volatile savehandler = exception_handler;
5111 struct jmploc jmploc;
5114 /* "echo 9>/dev/null; echo >&9; echo result: $?" - result should be 1, not 2! */
5115 err = setjmp(jmploc.loc); // huh?? was = setjmp(jmploc.loc) * 2;
5117 exception_handler = &jmploc;
5118 redirect(redir, flags);
5120 exception_handler = savehandler;
5121 if (err && exception != EXERROR)
5122 longjmp(exception_handler->loc, 1);
5123 RESTORE_INT(saveint);
5128 /* ============ Routines to expand arguments to commands
5130 * We have to deal with backquotes, shell variables, and file metacharacters.
5133 #if ENABLE_ASH_MATH_SUPPORT_64
5134 typedef int64_t arith_t;
5135 #define arith_t_type long long
5137 typedef long arith_t;
5138 #define arith_t_type long
5141 #if ENABLE_ASH_MATH_SUPPORT
5142 static arith_t dash_arith(const char *);
5143 static arith_t arith(const char *expr, int *perrcode);
5149 #define EXP_FULL 0x1 /* perform word splitting & file globbing */
5150 #define EXP_TILDE 0x2 /* do normal tilde expansion */
5151 #define EXP_VARTILDE 0x4 /* expand tildes in an assignment */
5152 #define EXP_REDIR 0x8 /* file glob for a redirection (1 match only) */
5153 #define EXP_CASE 0x10 /* keeps quotes around for CASE pattern */
5154 #define EXP_RECORD 0x20 /* need to record arguments for ifs breakup */
5155 #define EXP_VARTILDE2 0x40 /* expand tildes after colons only */
5156 #define EXP_WORD 0x80 /* expand word in parameter expansion */
5157 #define EXP_QWORD 0x100 /* expand word in quoted parameter expansion */
5161 #define RMESCAPE_ALLOC 0x1 /* Allocate a new string */
5162 #define RMESCAPE_GLOB 0x2 /* Add backslashes for glob */
5163 #define RMESCAPE_QUOTED 0x4 /* Remove CTLESC unless in quotes */
5164 #define RMESCAPE_GROW 0x8 /* Grow strings instead of stalloc */
5165 #define RMESCAPE_HEAP 0x10 /* Malloc strings instead of stalloc */
5168 * Structure specifying which parts of the string should be searched
5169 * for IFS characters.
5172 struct ifsregion *next; /* next region in list */
5173 int begoff; /* offset of start of region */
5174 int endoff; /* offset of end of region */
5175 int nulonly; /* search for nul bytes only */
5179 struct strlist *list;
5180 struct strlist **lastp;
5183 /* output of current string */
5184 static char *expdest;
5185 /* list of back quote expressions */
5186 static struct nodelist *argbackq;
5187 /* first struct in list of ifs regions */
5188 static struct ifsregion ifsfirst;
5189 /* last struct in list */
5190 static struct ifsregion *ifslastp;
5191 /* holds expanded arg list */
5192 static struct arglist exparg;
5202 expdest = makestrspace(32, expdest);
5203 #if ENABLE_ASH_MATH_SUPPORT_64
5204 len = fmtstr(expdest, 32, "%lld", (long long) num);
5206 len = fmtstr(expdest, 32, "%ld", num);
5208 STADJUST(len, expdest);
5213 esclen(const char *start, const char *p)
5217 while (p > start && *--p == CTLESC) {
5224 * Remove any CTLESC characters from a string.
5227 _rmescapes(char *str, int flag)
5229 static const char qchars[] ALIGN1 = { CTLESC, CTLQUOTEMARK, '\0' };
5236 p = strpbrk(str, qchars);
5242 if (flag & RMESCAPE_ALLOC) {
5243 size_t len = p - str;
5244 size_t fulllen = len + strlen(p) + 1;
5246 if (flag & RMESCAPE_GROW) {
5247 r = makestrspace(fulllen, expdest);
5248 } else if (flag & RMESCAPE_HEAP) {
5249 r = ckmalloc(fulllen);
5251 r = stalloc(fulllen);
5255 q = (char *)memcpy(q, str, len) + len;
5258 inquotes = (flag & RMESCAPE_QUOTED) ^ RMESCAPE_QUOTED;
5259 globbing = flag & RMESCAPE_GLOB;
5260 notescaped = globbing;
5262 if (*p == CTLQUOTEMARK) {
5263 inquotes = ~inquotes;
5265 notescaped = globbing;
5269 /* naked back slash */
5275 if (notescaped && inquotes && *p != '/') {
5279 notescaped = globbing;
5284 if (flag & RMESCAPE_GROW) {
5286 STADJUST(q - r + 1, expdest);
5290 #define rmescapes(p) _rmescapes((p), 0)
5292 #define pmatch(a, b) !fnmatch((a), (b), 0)
5295 * Prepare a pattern for a expmeta (internal glob(3)) call.
5297 * Returns an stalloced string.
5300 preglob(const char *pattern, int quoted, int flag)
5302 flag |= RMESCAPE_GLOB;
5304 flag |= RMESCAPE_QUOTED;
5306 return _rmescapes((char *)pattern, flag);
5310 * Put a string on the stack.
5313 memtodest(const char *p, size_t len, int syntax, int quotes)
5317 q = makestrspace(len * 2, q);
5320 int c = signed_char2int(*p++);
5323 if (quotes && (SIT(c, syntax) == CCTL || SIT(c, syntax) == CBACK))
5332 strtodest(const char *p, int syntax, int quotes)
5334 memtodest(p, strlen(p), syntax, quotes);
5338 * Record the fact that we have to scan this region of the
5339 * string for IFS characters.
5342 recordregion(int start, int end, int nulonly)
5344 struct ifsregion *ifsp;
5346 if (ifslastp == NULL) {
5350 ifsp = ckzalloc(sizeof(*ifsp));
5351 /*ifsp->next = NULL; - ckzalloc did it */
5352 ifslastp->next = ifsp;
5356 ifslastp->begoff = start;
5357 ifslastp->endoff = end;
5358 ifslastp->nulonly = nulonly;
5362 removerecordregions(int endoff)
5364 if (ifslastp == NULL)
5367 if (ifsfirst.endoff > endoff) {
5368 while (ifsfirst.next != NULL) {
5369 struct ifsregion *ifsp;
5371 ifsp = ifsfirst.next->next;
5372 free(ifsfirst.next);
5373 ifsfirst.next = ifsp;
5376 if (ifsfirst.begoff > endoff)
5379 ifslastp = &ifsfirst;
5380 ifsfirst.endoff = endoff;
5385 ifslastp = &ifsfirst;
5386 while (ifslastp->next && ifslastp->next->begoff < endoff)
5387 ifslastp=ifslastp->next;
5388 while (ifslastp->next != NULL) {
5389 struct ifsregion *ifsp;
5391 ifsp = ifslastp->next->next;
5392 free(ifslastp->next);
5393 ifslastp->next = ifsp;
5396 if (ifslastp->endoff > endoff)
5397 ifslastp->endoff = endoff;
5401 exptilde(char *startp, char *p, int flag)
5407 int quotes = flag & (EXP_FULL | EXP_CASE);
5412 while ((c = *++p) != '\0') {
5419 if (flag & EXP_VARTILDE)
5429 if (*name == '\0') {
5430 home = lookupvar(homestr);
5432 pw = getpwnam(name);
5437 if (!home || !*home)
5440 startloc = expdest - (char *)stackblock();
5441 strtodest(home, SQSYNTAX, quotes);
5442 recordregion(startloc, expdest - (char *)stackblock(), 0);
5450 * Execute a command inside back quotes. If it's a builtin command, we
5451 * want to save its output in a block obtained from malloc. Otherwise
5452 * we fork off a subprocess and get the output of the command via a pipe.
5453 * Should be called with interrupts off.
5455 struct backcmd { /* result of evalbackcmd */
5456 int fd; /* file descriptor to read from */
5457 int nleft; /* number of chars in buffer */
5458 char *buf; /* buffer */
5459 struct job *jp; /* job structure for command */
5462 /* These forward decls are needed to use "eval" code for backticks handling: */
5463 static uint8_t back_exitstatus; /* exit status of backquoted command */
5464 #define EV_EXIT 01 /* exit after evaluating tree */
5465 static void evaltree(union node *, int);
5468 evalbackcmd(union node *n, struct backcmd *result)
5480 saveherefd = herefd;
5488 ash_msg_and_raise_error("pipe call failed");
5489 jp = makejob(/*n,*/ 1);
5490 if (forkshell(jp, n, FORK_NOJOB) == 0) {
5495 copyfd(pip[1], 1 | COPYFD_EXACT);
5499 evaltree(n, EV_EXIT); /* actually evaltreenr... */
5503 result->fd = pip[0];
5506 herefd = saveherefd;
5508 TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n",
5509 result->fd, result->buf, result->nleft, result->jp));
5513 * Expand stuff in backwards quotes.
5516 expbackq(union node *cmd, int quoted, int quotes)
5524 int syntax = quoted ? DQSYNTAX : BASESYNTAX;
5525 struct stackmark smark;
5528 setstackmark(&smark);
5530 startloc = dest - (char *)stackblock();
5532 evalbackcmd(cmd, &in);
5533 popstackmark(&smark);
5540 memtodest(p, i, syntax, quotes);
5544 i = nonblock_safe_read(in.fd, buf, sizeof(buf));
5545 TRACE(("expbackq: read returns %d\n", i));
5554 back_exitstatus = waitforjob(in.jp);
5558 /* Eat all trailing newlines */
5560 for (; dest > (char *)stackblock() && dest[-1] == '\n';)
5565 recordregion(startloc, dest - (char *)stackblock(), 0);
5566 TRACE(("evalbackq: size=%d: \"%.*s\"\n",
5567 (dest - (char *)stackblock()) - startloc,
5568 (dest - (char *)stackblock()) - startloc,
5569 stackblock() + startloc));
5572 #if ENABLE_ASH_MATH_SUPPORT
5574 * Expand arithmetic expression. Backup to start of expression,
5575 * evaluate, place result in (backed up) result, adjust string position.
5588 * This routine is slightly over-complicated for
5589 * efficiency. Next we scan backwards looking for the
5590 * start of arithmetic.
5592 start = stackblock();
5599 while (*p != CTLARI) {
5603 ash_msg_and_raise_error("missing CTLARI (shouldn't happen)");
5608 esc = esclen(start, p);
5618 removerecordregions(begoff);
5627 len = cvtnum(dash_arith(p + 2));
5630 recordregion(begoff, begoff + len, 0);
5634 /* argstr needs it */
5635 static char *evalvar(char *p, int flag, struct strlist *var_str_list);
5638 * Perform variable and command substitution. If EXP_FULL is set, output CTLESC
5639 * characters to allow for further processing. Otherwise treat
5640 * $@ like $* since no splitting will be performed.
5642 * var_str_list (can be NULL) is a list of "VAR=val" strings which take precedence
5643 * over shell varables. Needed for "A=a B=$A; echo $B" case - we use it
5644 * for correct expansion of "B=$A" word.
5647 argstr(char *p, int flag, struct strlist *var_str_list)
5649 static const char spclchars[] ALIGN1 = {
5657 CTLBACKQ | CTLQUOTE,
5658 #if ENABLE_ASH_MATH_SUPPORT
5663 const char *reject = spclchars;
5665 int quotes = flag & (EXP_FULL | EXP_CASE); /* do CTLESC */
5666 int breakall = flag & EXP_WORD;
5671 if (!(flag & EXP_VARTILDE)) {
5673 } else if (flag & EXP_VARTILDE2) {
5678 if (flag & EXP_TILDE) {
5684 if (*q == CTLESC && (flag & EXP_QWORD))
5687 p = exptilde(p, q, flag);
5690 startloc = expdest - (char *)stackblock();
5692 length += strcspn(p + length, reject);
5694 if (c && (!(c & 0x80)
5695 #if ENABLE_ASH_MATH_SUPPORT
5699 /* c == '=' || c == ':' || c == CTLENDARI */
5704 expdest = stack_nputstr(p, length, expdest);
5705 newloc = expdest - (char *)stackblock();
5706 if (breakall && !inquotes && newloc > startloc) {
5707 recordregion(startloc, newloc, 0);
5718 if (flag & EXP_VARTILDE2) {
5722 flag |= EXP_VARTILDE2;
5727 * sort of a hack - expand tildes in variable
5728 * assignments (after the first '=' and after ':'s).
5737 case CTLENDVAR: /* ??? */
5740 /* "$@" syntax adherence hack */
5743 !memcmp(p, dolatstr, 4) &&
5744 (p[4] == CTLQUOTEMARK || (
5745 p[4] == CTLENDVAR &&
5746 p[5] == CTLQUOTEMARK
5749 p = evalvar(p + 1, flag, /* var_str_list: */ NULL) + 1;
5752 inquotes = !inquotes;
5765 p = evalvar(p, flag, var_str_list);
5769 case CTLBACKQ|CTLQUOTE:
5770 expbackq(argbackq->n, c, quotes);
5771 argbackq = argbackq->next;
5773 #if ENABLE_ASH_MATH_SUPPORT
5786 scanleft(char *startp, char *rmesc, char *rmescend UNUSED_PARAM, char *str, int quotes,
5789 // This commented out code was added by James Simmons <jsimmons@infradead.org>
5790 // as part of a larger change when he added support for ${var/a/b}.
5791 // However, it broke # and % operators:
5795 //echo ${var#ab} abcdcd abcdcd
5796 //echo ${var##ab} abcdcd abcdcd
5797 //echo ${var#a*b} abcdcd ababcdcd (!)
5798 //echo ${var##a*b} cdcd cdcd
5799 //echo ${var#?} babcdcd ababcdcd (!)
5800 //echo ${var##?} babcdcd babcdcd
5801 //echo ${var#*} ababcdcd babcdcd (!)
5803 //echo ${var%cd} ababcd ababcd
5804 //echo ${var%%cd} ababcd abab (!)
5805 //echo ${var%c*d} ababcd ababcd
5806 //echo ${var%%c*d} abab ababcdcd (!)
5807 //echo ${var%?} ababcdc ababcdc
5808 //echo ${var%%?} ababcdc ababcdcd (!)
5809 //echo ${var%*} ababcdcd ababcdcd
5812 // Commenting it back out helped. Remove it completely if it really
5815 char *loc, *loc2; //, *full;
5821 int match; // = strlen(str);
5822 const char *s = loc2;
5829 match = pmatch(str, s); // this line was deleted
5831 // // chop off end if its '*'
5832 // full = strrchr(str, '*');
5833 // if (full && full != str)
5836 // // If str starts with '*' replace with s.
5837 // if ((*str == '*') && strlen(s) >= match) {
5838 // full = xstrdup(s);
5839 // strncpy(full+strlen(s)-match+1, str+1, match-1);
5841 // full = xstrndup(str, match);
5842 // match = strncmp(s, full, strlen(full));
5846 if (match) // if (!match)
5848 if (quotes && *loc == CTLESC)
5857 scanright(char *startp, char *rmesc, char *rmescend, char *str, int quotes,
5864 for (loc = str - 1, loc2 = rmescend; loc >= startp; loc2--) {
5867 const char *s = loc2;
5872 match = pmatch(str, s);
5879 esc = esclen(startp, loc);
5890 static void varunset(const char *, const char *, const char *, int) NORETURN;
5892 varunset(const char *end, const char *var, const char *umsg, int varflags)
5898 msg = "parameter not set";
5900 if (*end == CTLENDVAR) {
5901 if (varflags & VSNUL)
5906 ash_msg_and_raise_error("%.*s: %s%s", end - var - 1, var, msg, tail);
5909 #if ENABLE_ASH_BASH_COMPAT
5911 parse_sub_pattern(char *arg, int inquotes)
5913 char *idx, *repl = NULL;
5922 /* Only the first '/' seen is our separator */
5929 if (!inquotes && c == '\\' && arg[1] == '\\')
5930 arg++; /* skip both \\, not just first one */
5937 #endif /* ENABLE_ASH_BASH_COMPAT */
5940 subevalvar(char *p, char *str, int strloc, int subtype,
5941 int startloc, int varflags, int quotes, struct strlist *var_str_list)
5943 struct nodelist *saveargbackq = argbackq;
5946 char *rmesc, *rmescend;
5947 USE_ASH_BASH_COMPAT(char *repl = NULL;)
5948 USE_ASH_BASH_COMPAT(char null = '\0';)
5949 USE_ASH_BASH_COMPAT(int pos, len, orig_len;)
5950 int saveherefd = herefd;
5951 int amount, workloc, resetloc;
5953 char *(*scan)(char*, char*, char*, char*, int, int);
5956 argstr(p, (subtype != VSASSIGN && subtype != VSQUESTION) ? EXP_CASE : 0,
5958 STPUTC('\0', expdest);
5959 herefd = saveherefd;
5960 argbackq = saveargbackq;
5961 startp = (char *)stackblock() + startloc;
5965 setvar(str, startp, 0);
5966 amount = startp - expdest;
5967 STADJUST(amount, expdest);
5970 #if ENABLE_ASH_BASH_COMPAT
5972 loc = str = stackblock() + strloc;
5973 // TODO: number() instead? It does error checking...
5975 len = str - startp - 1;
5977 /* *loc != '\0', guaranteed by parser */
5981 /* We must adjust the length by the number of escapes we find. */
5982 for (ptr = startp; ptr < (str - 1); ptr++) {
5983 if (*ptr == CTLESC) {
5991 if (*loc++ == ':') {
5992 // TODO: number() instead? It does error checking...
5996 while (*loc && *loc != ':')
5999 // TODO: number() instead? It does error checking...
6002 if (pos >= orig_len) {
6006 if (len > (orig_len - pos))
6007 len = orig_len - pos;
6009 for (str = startp; pos; str++, pos--) {
6010 if (quotes && *str == CTLESC)
6013 for (loc = startp; len; len--) {
6014 if (quotes && *str == CTLESC)
6019 amount = loc - expdest;
6020 STADJUST(amount, expdest);
6025 varunset(p, str, startp, varflags);
6028 resetloc = expdest - (char *)stackblock();
6030 /* We'll comeback here if we grow the stack while handling
6031 * a VSREPLACE or VSREPLACEALL, since our pointers into the
6032 * stack will need rebasing, and we'll need to remove our work
6035 USE_ASH_BASH_COMPAT(restart:)
6037 amount = expdest - ((char *)stackblock() + resetloc);
6038 STADJUST(-amount, expdest);
6039 startp = (char *)stackblock() + startloc;
6042 rmescend = (char *)stackblock() + strloc;
6044 rmesc = _rmescapes(startp, RMESCAPE_ALLOC | RMESCAPE_GROW);
6045 if (rmesc != startp) {
6047 startp = (char *)stackblock() + startloc;
6051 str = (char *)stackblock() + strloc;
6052 preglob(str, varflags & VSQUOTE, 0);
6053 workloc = expdest - (char *)stackblock();
6055 #if ENABLE_ASH_BASH_COMPAT
6056 if (subtype == VSREPLACE || subtype == VSREPLACEALL) {
6057 char *idx, *end, *restart_detect;
6060 repl = parse_sub_pattern(str, varflags & VSQUOTE);
6065 /* If there's no pattern to match, return the expansion unmolested */
6073 loc = scanright(idx, rmesc, rmescend, str, quotes, 1);
6075 /* No match, advance */
6076 restart_detect = stackblock();
6077 STPUTC(*idx, expdest);
6078 if (quotes && *idx == CTLESC) {
6081 STPUTC(*idx, expdest);
6083 if (stackblock() != restart_detect)
6091 if (subtype == VSREPLACEALL) {
6093 if (quotes && *idx == CTLESC)
6101 for (loc = repl; *loc; loc++) {
6102 restart_detect = stackblock();
6103 STPUTC(*loc, expdest);
6104 if (stackblock() != restart_detect)
6109 if (subtype == VSREPLACE) {
6111 restart_detect = stackblock();
6112 STPUTC(*idx, expdest);
6113 if (stackblock() != restart_detect)
6122 /* We've put the replaced text into a buffer at workloc, now
6123 * move it to the right place and adjust the stack.
6125 startp = stackblock() + startloc;
6126 STPUTC('\0', expdest);
6127 memmove(startp, stackblock() + workloc, len);
6128 startp[len++] = '\0';
6129 amount = expdest - ((char *)stackblock() + startloc + len - 1);
6130 STADJUST(-amount, expdest);
6133 #endif /* ENABLE_ASH_BASH_COMPAT */
6135 subtype -= VSTRIMRIGHT;
6137 if (subtype < 0 || subtype > 7)
6140 /* zero = subtype == VSTRIMLEFT || subtype == VSTRIMLEFTMAX */
6141 zero = subtype >> 1;
6142 /* VSTRIMLEFT/VSTRIMRIGHTMAX -> scanleft */
6143 scan = (subtype & 1) ^ zero ? scanleft : scanright;
6145 loc = scan(startp, rmesc, rmescend, str, quotes, zero);
6148 memmove(startp, loc, str - loc);
6149 loc = startp + (str - loc) - 1;
6152 amount = loc - expdest;
6153 STADJUST(amount, expdest);
6159 * Add the value of a specialized variable to the stack string.
6162 varvalue(char *name, int varflags, int flags, struct strlist *var_str_list)
6172 int quoted = varflags & VSQUOTE;
6173 int subtype = varflags & VSTYPE;
6174 int quotes = flags & (EXP_FULL | EXP_CASE);
6176 if (quoted && (flags & EXP_FULL))
6177 sep = 1 << CHAR_BIT;
6179 syntax = quoted ? DQSYNTAX : BASESYNTAX;
6188 num = shellparam.nparam;
6198 p = makestrspace(NOPTS, expdest);
6199 for (i = NOPTS - 1; i >= 0; i--) {
6201 USTPUTC(optletters(i), p);
6212 sep = ifsset() ? signed_char2int(ifsval()[0]) : ' ';
6213 if (quotes && (SIT(sep, syntax) == CCTL || SIT(sep, syntax) == CBACK))
6219 while ((p = *ap++)) {
6222 partlen = strlen(p);
6225 if (!(subtype == VSPLUS || subtype == VSLENGTH))
6226 memtodest(p, partlen, syntax, quotes);
6232 if (subtype == VSPLUS || subtype == VSLENGTH) {
6253 // TODO: number() instead? It does error checking...
6255 if (num < 0 || num > shellparam.nparam)
6257 p = num ? shellparam.p[num - 1] : arg0;
6260 /* NB: name has form "VAR=..." */
6262 /* "A=a B=$A" case: var_str_list is a list of "A=a" strings
6263 * which should be considered before we check variables. */
6265 unsigned name_len = (strchrnul(name, '=') - name) + 1;
6269 str = var_str_list->text;
6270 eq = strchr(str, '=');
6271 if (!eq) /* stop at first non-assignment */
6274 if (name_len == (unsigned)(eq - str)
6275 && strncmp(str, name, name_len) == 0) {
6277 /* goto value; - WRONG! */
6278 /* think "A=1 A=2 B=$A" */
6280 var_str_list = var_str_list->next;
6281 } while (var_str_list);
6285 p = lookupvar(name);
6291 if (!(subtype == VSPLUS || subtype == VSLENGTH))
6292 memtodest(p, len, syntax, quotes);
6296 if (subtype == VSPLUS || subtype == VSLENGTH)
6297 STADJUST(-len, expdest);
6302 * Expand a variable, and return a pointer to the next character in the
6306 evalvar(char *p, int flag, struct strlist *var_str_list)
6318 subtype = varflags & VSTYPE;
6319 quoted = varflags & VSQUOTE;
6321 easy = (!quoted || (*var == '@' && shellparam.nparam));
6322 startloc = expdest - (char *)stackblock();
6323 p = strchr(p, '=') + 1;
6326 varlen = varvalue(var, varflags, flag, var_str_list);
6327 if (varflags & VSNUL)
6330 if (subtype == VSPLUS) {
6331 varlen = -1 - varlen;
6335 if (subtype == VSMINUS) {
6339 p, flag | EXP_TILDE |
6340 (quoted ? EXP_QWORD : EXP_WORD),
6350 if (subtype == VSASSIGN || subtype == VSQUESTION) {
6352 if (subevalvar(p, var, /* strloc: */ 0,
6353 subtype, startloc, varflags,
6359 * Remove any recorded regions beyond
6362 removerecordregions(startloc);
6372 if (varlen < 0 && uflag)
6373 varunset(p, var, 0, 0);
6375 if (subtype == VSLENGTH) {
6376 cvtnum(varlen > 0 ? varlen : 0);
6380 if (subtype == VSNORMAL) {
6391 case VSTRIMRIGHTMAX:
6392 #if ENABLE_ASH_BASH_COMPAT
6405 * Terminate the string and start recording the pattern
6408 STPUTC('\0', expdest);
6409 patloc = expdest - (char *)stackblock();
6410 if (0 == subevalvar(p, /* str: */ NULL, patloc, subtype,
6412 /* quotes: */ flag & (EXP_FULL | EXP_CASE),
6415 int amount = expdest - (
6416 (char *)stackblock() + patloc - 1
6418 STADJUST(-amount, expdest);
6420 /* Remove any recorded regions beyond start of variable */
6421 removerecordregions(startloc);
6423 recordregion(startloc, expdest - (char *)stackblock(), quoted);
6427 if (subtype != VSNORMAL) { /* skip to end of alternative */
6433 else if (c == CTLBACKQ || c == (CTLBACKQ|CTLQUOTE)) {
6435 argbackq = argbackq->next;
6436 } else if (c == CTLVAR) {
6437 if ((*p++ & VSTYPE) != VSNORMAL)
6439 } else if (c == CTLENDVAR) {
6449 * Break the argument string into pieces based upon IFS and add the
6450 * strings to the argument list. The regions of the string to be
6451 * searched for IFS characters have been stored by recordregion.
6454 ifsbreakup(char *string, struct arglist *arglist)
6456 struct ifsregion *ifsp;
6461 const char *ifs, *realifs;
6466 if (ifslastp != NULL) {
6469 realifs = ifsset() ? ifsval() : defifs;
6472 p = string + ifsp->begoff;
6473 nulonly = ifsp->nulonly;
6474 ifs = nulonly ? nullstr : realifs;
6476 while (p < string + ifsp->endoff) {
6480 if (!strchr(ifs, *p)) {
6485 ifsspc = (strchr(defifs, *p) != NULL);
6486 /* Ignore IFS whitespace at start */
6487 if (q == start && ifsspc) {
6493 sp = stzalloc(sizeof(*sp));
6495 *arglist->lastp = sp;
6496 arglist->lastp = &sp->next;
6500 if (p >= string + ifsp->endoff) {
6506 if (strchr(ifs, *p) == NULL) {
6510 if (strchr(defifs, *p) == NULL) {
6525 } while (ifsp != NULL);
6534 sp = stzalloc(sizeof(*sp));
6536 *arglist->lastp = sp;
6537 arglist->lastp = &sp->next;
6543 struct ifsregion *p;
6548 struct ifsregion *ifsp;
6554 ifsfirst.next = NULL;
6559 * Add a file name to the list.
6562 addfname(const char *name)
6566 sp = stzalloc(sizeof(*sp));
6567 sp->text = ststrdup(name);
6569 exparg.lastp = &sp->next;
6572 static char *expdir;
6575 * Do metacharacter (i.e. *, ?, [...]) expansion.
6578 expmeta(char *enddir, char *name)
6593 for (p = name; *p; p++) {
6594 if (*p == '*' || *p == '?')
6596 else if (*p == '[') {
6603 if (*q == '/' || *q == '\0')
6610 } else if (*p == '\\')
6612 else if (*p == '/') {
6619 if (metaflag == 0) { /* we've reached the end of the file name */
6620 if (enddir != expdir)
6628 if (metaflag == 0 || lstat(expdir, &statb) >= 0)
6639 } while (p < start);
6641 if (enddir == expdir) {
6643 } else if (enddir == expdir + 1 && *expdir == '/') {
6652 if (enddir != expdir)
6654 if (*endname == 0) {
6666 while (!intpending && (dp = readdir(dirp)) != NULL) {
6667 if (dp->d_name[0] == '.' && !matchdot)
6669 if (pmatch(start, dp->d_name)) {
6671 strcpy(enddir, dp->d_name);
6674 for (p = enddir, cp = dp->d_name; (*p++ = *cp++) != '\0';)
6677 expmeta(p, endname);
6686 static struct strlist *
6687 msort(struct strlist *list, int len)
6689 struct strlist *p, *q = NULL;
6690 struct strlist **lpp;
6698 for (n = half; --n >= 0;) {
6702 q->next = NULL; /* terminate first half of list */
6703 q = msort(list, half); /* sort first half of list */
6704 p = msort(p, len - half); /* sort second half */
6707 #if ENABLE_LOCALE_SUPPORT
6708 if (strcoll(p->text, q->text) < 0)
6710 if (strcmp(p->text, q->text) < 0)
6734 * Sort the results of file name expansion. It calculates the number of
6735 * strings to sort and then calls msort (short for merge sort) to do the
6738 static struct strlist *
6739 expsort(struct strlist *str)
6745 for (sp = str; sp; sp = sp->next)
6747 return msort(str, len);
6751 expandmeta(struct strlist *str /*, int flag*/)
6753 static const char metachars[] ALIGN1 = {
6756 /* TODO - EXP_REDIR */
6759 struct strlist **savelastp;
6765 if (!strpbrk(str->text, metachars))
6767 savelastp = exparg.lastp;
6770 p = preglob(str->text, 0, RMESCAPE_ALLOC | RMESCAPE_HEAP);
6772 int i = strlen(str->text);
6773 expdir = ckmalloc(i < 2048 ? 2048 : i); /* XXX */
6781 if (exparg.lastp == savelastp) {
6786 *exparg.lastp = str;
6787 rmescapes(str->text);
6788 exparg.lastp = &str->next;
6790 *exparg.lastp = NULL;
6791 *savelastp = sp = expsort(*savelastp);
6792 while (sp->next != NULL)
6794 exparg.lastp = &sp->next;
6801 * Perform variable substitution and command substitution on an argument,
6802 * placing the resulting list of arguments in arglist. If EXP_FULL is true,
6803 * perform splitting and file name expansion. When arglist is NULL, perform
6804 * here document expansion.
6807 expandarg(union node *arg, struct arglist *arglist, int flag)
6812 argbackq = arg->narg.backquote;
6813 STARTSTACKSTR(expdest);
6814 ifsfirst.next = NULL;
6816 argstr(arg->narg.text, flag,
6817 /* var_str_list: */ arglist ? arglist->list : NULL);
6818 p = _STPUTC('\0', expdest);
6820 if (arglist == NULL) {
6821 return; /* here document expanded */
6823 p = grabstackstr(p);
6824 exparg.lastp = &exparg.list;
6828 if (flag & EXP_FULL) {
6829 ifsbreakup(p, &exparg);
6830 *exparg.lastp = NULL;
6831 exparg.lastp = &exparg.list;
6832 expandmeta(exparg.list /*, flag*/);
6834 if (flag & EXP_REDIR) /*XXX - for now, just remove escapes */
6836 sp = stzalloc(sizeof(*sp));
6839 exparg.lastp = &sp->next;
6843 *exparg.lastp = NULL;
6845 *arglist->lastp = exparg.list;
6846 arglist->lastp = exparg.lastp;
6851 * Expand shell variables and backquotes inside a here document.
6854 expandhere(union node *arg, int fd)
6857 expandarg(arg, (struct arglist *)NULL, 0);
6858 full_write(fd, stackblock(), expdest - (char *)stackblock());
6862 * Returns true if the pattern matches the string.
6865 patmatch(char *pattern, const char *string)
6867 return pmatch(preglob(pattern, 0, 0), string);
6871 * See if a pattern matches in a case statement.
6874 casematch(union node *pattern, char *val)
6876 struct stackmark smark;
6879 setstackmark(&smark);
6880 argbackq = pattern->narg.backquote;
6881 STARTSTACKSTR(expdest);
6883 argstr(pattern->narg.text, EXP_TILDE | EXP_CASE,
6884 /* var_str_list: */ NULL);
6885 STACKSTRNUL(expdest);
6886 result = patmatch(stackblock(), val);
6887 popstackmark(&smark);
6892 /* ============ find_command */
6896 int (*builtin)(int, char **);
6897 /* unsigned flags; */
6899 #define IS_BUILTIN_SPECIAL(b) ((b)->name[0] & 1)
6900 /* "regular" builtins always take precedence over commands,
6901 * regardless of PATH=....%builtin... position */
6902 #define IS_BUILTIN_REGULAR(b) ((b)->name[0] & 2)
6903 #define IS_BUILTIN_ASSIGN(b) ((b)->name[0] & 4)
6906 smallint cmdtype; /* CMDxxx */
6909 /* index >= 0 for commands without path (slashes) */
6910 /* (TODO: what exactly does the value mean? PATH position?) */
6911 /* index == -1 for commands with slashes */
6912 /* index == (-2 - applet_no) for NOFORK applets */
6913 const struct builtincmd *cmd;
6914 struct funcnode *func;
6917 /* values of cmdtype */
6918 #define CMDUNKNOWN -1 /* no entry in table for command */
6919 #define CMDNORMAL 0 /* command is an executable program */
6920 #define CMDFUNCTION 1 /* command is a shell function */
6921 #define CMDBUILTIN 2 /* command is a shell builtin */
6923 /* action to find_command() */
6924 #define DO_ERR 0x01 /* prints errors */
6925 #define DO_ABS 0x02 /* checks absolute paths */
6926 #define DO_NOFUNC 0x04 /* don't return shell functions, for command */
6927 #define DO_ALTPATH 0x08 /* using alternate path */
6928 #define DO_ALTBLTIN 0x20 /* %builtin in alt. path */
6930 static void find_command(char *, struct cmdentry *, int, const char *);
6933 /* ============ Hashing commands */
6936 * When commands are first encountered, they are entered in a hash table.
6937 * This ensures that a full path search will not have to be done for them
6938 * on each invocation.
6940 * We should investigate converting to a linear search, even though that
6941 * would make the command name "hash" a misnomer.
6945 struct tblentry *next; /* next entry in hash chain */
6946 union param param; /* definition of builtin function */
6947 smallint cmdtype; /* CMDxxx */
6948 char rehash; /* if set, cd done since entry created */
6949 char cmdname[1]; /* name of command */
6952 static struct tblentry **cmdtable;
6953 #define INIT_G_cmdtable() do { \
6954 cmdtable = xzalloc(CMDTABLESIZE * sizeof(cmdtable[0])); \
6957 static int builtinloc = -1; /* index in path of %builtin, or -1 */
6961 tryexec(USE_FEATURE_SH_STANDALONE(int applet_no,) char *cmd, char **argv, char **envp)
6965 #if ENABLE_FEATURE_SH_STANDALONE
6966 if (applet_no >= 0) {
6967 if (APPLET_IS_NOEXEC(applet_no))
6968 run_applet_no_and_exit(applet_no, argv);
6969 /* re-exec ourselves with the new arguments */
6970 execve(bb_busybox_exec_path, argv, envp);
6971 /* If they called chroot or otherwise made the binary no longer
6972 * executable, fall through */
6979 execve(cmd, argv, envp);
6980 } while (errno == EINTR);
6982 execve(cmd, argv, envp);
6988 if (errno == ENOEXEC) {
6992 for (ap = argv; *ap; ap++)
6994 ap = new = ckmalloc((ap - argv + 2) * sizeof(ap[0]));
6996 ap[0] = cmd = (char *)DEFAULT_SHELL;
6999 while ((*ap++ = *argv++) != NULL)
7008 * Exec a program. Never returns. If you change this routine, you may
7009 * have to change the find_command routine as well.
7011 static void shellexec(char **, const char *, int) NORETURN;
7013 shellexec(char **argv, const char *path, int idx)
7019 #if ENABLE_FEATURE_SH_STANDALONE
7023 clearredir(/*drop:*/ 1);
7024 envp = listvars(VEXPORT, VUNSET, 0);
7025 if (strchr(argv[0], '/') != NULL
7026 #if ENABLE_FEATURE_SH_STANDALONE
7027 || (applet_no = find_applet_by_name(argv[0])) >= 0
7030 tryexec(USE_FEATURE_SH_STANDALONE(applet_no,) argv[0], argv, envp);
7034 while ((cmdname = padvance(&path, argv[0])) != NULL) {
7035 if (--idx < 0 && pathopt == NULL) {
7036 tryexec(USE_FEATURE_SH_STANDALONE(-1,) cmdname, argv, envp);
7037 if (errno != ENOENT && errno != ENOTDIR)
7044 /* Map to POSIX errors */
7056 exitstatus = exerrno;
7057 TRACE(("shellexec failed for %s, errno %d, suppressint %d\n",
7058 argv[0], e, suppressint));
7059 ash_msg_and_raise(EXEXEC, "%s: %s", argv[0], errmsg(e, "not found"));
7064 printentry(struct tblentry *cmdp)
7070 idx = cmdp->param.index;
7073 name = padvance(&path, cmdp->cmdname);
7075 } while (--idx >= 0);
7076 out1fmt("%s%s\n", name, (cmdp->rehash ? "*" : nullstr));
7080 * Clear out command entries. The argument specifies the first entry in
7081 * PATH which has changed.
7084 clearcmdentry(int firstchange)
7086 struct tblentry **tblp;
7087 struct tblentry **pp;
7088 struct tblentry *cmdp;
7091 for (tblp = cmdtable; tblp < &cmdtable[CMDTABLESIZE]; tblp++) {
7093 while ((cmdp = *pp) != NULL) {
7094 if ((cmdp->cmdtype == CMDNORMAL &&
7095 cmdp->param.index >= firstchange)
7096 || (cmdp->cmdtype == CMDBUILTIN &&
7097 builtinloc >= firstchange)
7110 * Locate a command in the command hash table. If "add" is nonzero,
7111 * add the command to the table if it is not already present. The
7112 * variable "lastcmdentry" is set to point to the address of the link
7113 * pointing to the entry, so that delete_cmd_entry can delete the
7116 * Interrupts must be off if called with add != 0.
7118 static struct tblentry **lastcmdentry;
7120 static struct tblentry *
7121 cmdlookup(const char *name, int add)
7123 unsigned int hashval;
7125 struct tblentry *cmdp;
7126 struct tblentry **pp;
7129 hashval = (unsigned char)*p << 4;
7131 hashval += (unsigned char)*p++;
7133 pp = &cmdtable[hashval % CMDTABLESIZE];
7134 for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
7135 if (strcmp(cmdp->cmdname, name) == 0)
7139 if (add && cmdp == NULL) {
7140 cmdp = *pp = ckzalloc(sizeof(struct tblentry)
7142 /* + 1 - already done because
7143 * tblentry::cmdname is char[1] */);
7144 /*cmdp->next = NULL; - ckzalloc did it */
7145 cmdp->cmdtype = CMDUNKNOWN;
7146 strcpy(cmdp->cmdname, name);
7153 * Delete the command entry returned on the last lookup.
7156 delete_cmd_entry(void)
7158 struct tblentry *cmdp;
7161 cmdp = *lastcmdentry;
7162 *lastcmdentry = cmdp->next;
7163 if (cmdp->cmdtype == CMDFUNCTION)
7164 freefunc(cmdp->param.func);
7170 * Add a new command entry, replacing any existing command entry for
7171 * the same name - except special builtins.
7174 addcmdentry(char *name, struct cmdentry *entry)
7176 struct tblentry *cmdp;
7178 cmdp = cmdlookup(name, 1);
7179 if (cmdp->cmdtype == CMDFUNCTION) {
7180 freefunc(cmdp->param.func);
7182 cmdp->cmdtype = entry->cmdtype;
7183 cmdp->param = entry->u;
7188 hashcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
7190 struct tblentry **pp;
7191 struct tblentry *cmdp;
7193 struct cmdentry entry;
7196 if (nextopt("r") != '\0') {
7201 if (*argptr == NULL) {
7202 for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
7203 for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
7204 if (cmdp->cmdtype == CMDNORMAL)
7212 while ((name = *argptr) != NULL) {
7213 cmdp = cmdlookup(name, 0);
7215 && (cmdp->cmdtype == CMDNORMAL
7216 || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0))
7220 find_command(name, &entry, DO_ERR, pathval());
7221 if (entry.cmdtype == CMDUNKNOWN)
7229 * Called when a cd is done. Marks all commands so the next time they
7230 * are executed they will be rehashed.
7235 struct tblentry **pp;
7236 struct tblentry *cmdp;
7238 for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
7239 for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
7240 if (cmdp->cmdtype == CMDNORMAL
7241 || (cmdp->cmdtype == CMDBUILTIN
7242 && !IS_BUILTIN_REGULAR(cmdp->param.cmd)
7252 * Fix command hash table when PATH changed.
7253 * Called before PATH is changed. The argument is the new value of PATH;
7254 * pathval() still returns the old value at this point.
7255 * Called with interrupts off.
7258 changepath(const char *new)
7266 firstchange = 9999; /* assume no change */
7272 if ((*old == '\0' && *new == ':')
7273 || (*old == ':' && *new == '\0'))
7275 old = new; /* ignore subsequent differences */
7279 if (*new == '%' && idx_bltin < 0 && prefix(new + 1, "builtin"))
7285 if (builtinloc < 0 && idx_bltin >= 0)
7286 builtinloc = idx_bltin; /* zap builtins */
7287 if (builtinloc >= 0 && idx_bltin < 0)
7289 clearcmdentry(firstchange);
7290 builtinloc = idx_bltin;
7305 #define TENDBQUOTE 12
7322 typedef smallint token_id_t;
7324 /* first char is indicating which tokens mark the end of a list */
7325 static const char *const tokname_array[] = {
7339 #define KWDOFFSET 13
7340 /* the following are keywords */
7362 static char buf[16];
7365 //if (tok < TSEMI) return tokname_array[tok] + 1;
7366 //sprintf(buf, "\"%s\"", tokname_array[tok] + 1);
7371 sprintf(buf + (tok >= TSEMI), "%s%c",
7372 tokname_array[tok] + 1, (tok >= TSEMI ? '"' : 0));
7376 /* Wrapper around strcmp for qsort/bsearch/... */
7378 pstrcmp(const void *a, const void *b)
7380 return strcmp((char*) a, (*(char**) b) + 1);
7383 static const char *const *
7384 findkwd(const char *s)
7386 return bsearch(s, tokname_array + KWDOFFSET,
7387 ARRAY_SIZE(tokname_array) - KWDOFFSET,
7388 sizeof(tokname_array[0]), pstrcmp);
7392 * Locate and print what a word is...
7395 describe_command(char *command, int describe_command_verbose)
7397 struct cmdentry entry;
7398 struct tblentry *cmdp;
7399 #if ENABLE_ASH_ALIAS
7400 const struct alias *ap;
7402 const char *path = pathval();
7404 if (describe_command_verbose) {
7408 /* First look at the keywords */
7409 if (findkwd(command)) {
7410 out1str(describe_command_verbose ? " is a shell keyword" : command);
7414 #if ENABLE_ASH_ALIAS
7415 /* Then look at the aliases */
7416 ap = lookupalias(command, 0);
7418 if (!describe_command_verbose) {
7423 out1fmt(" is an alias for %s", ap->val);
7427 /* Then check if it is a tracked alias */
7428 cmdp = cmdlookup(command, 0);
7430 entry.cmdtype = cmdp->cmdtype;
7431 entry.u = cmdp->param;
7433 /* Finally use brute force */
7434 find_command(command, &entry, DO_ABS, path);
7437 switch (entry.cmdtype) {
7439 int j = entry.u.index;
7445 p = padvance(&path, command);
7449 if (describe_command_verbose) {
7451 (cmdp ? " a tracked alias for" : nullstr), p
7460 if (describe_command_verbose) {
7461 out1str(" is a shell function");
7468 if (describe_command_verbose) {
7469 out1fmt(" is a %sshell builtin",
7470 IS_BUILTIN_SPECIAL(entry.u.cmd) ?
7471 "special " : nullstr
7479 if (describe_command_verbose) {
7480 out1str(": not found\n");
7485 outstr("\n", stdout);
7490 typecmd(int argc UNUSED_PARAM, char **argv)
7496 /* type -p ... ? (we don't bother checking for 'p') */
7497 if (argv[1] && argv[1][0] == '-') {
7502 err |= describe_command(argv[i++], verbose);
7507 #if ENABLE_ASH_CMDCMD
7509 commandcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
7517 while ((c = nextopt("pvV")) != '\0')
7519 verify |= VERIFY_VERBOSE;
7521 verify |= VERIFY_BRIEF;
7526 /* Mimic bash: just "command -v" doesn't complain, it's a nop */
7527 if (verify && (*argptr != NULL)) {
7528 return describe_command(*argptr, verify - VERIFY_BRIEF);
7536 /* ============ eval.c */
7538 static int funcblocksize; /* size of structures in function */
7539 static int funcstringsize; /* size of strings in node */
7540 static void *funcblock; /* block to allocate function from */
7541 static char *funcstring; /* block to allocate strings from */
7543 /* flags in argument to evaltree */
7544 #define EV_EXIT 01 /* exit after evaluating tree */
7545 #define EV_TESTED 02 /* exit status is checked; ignore -e flag */
7546 #define EV_BACKCMD 04 /* command executing within back quotes */
7548 static const short nodesize[26] = {
7549 SHELL_ALIGN(sizeof(struct ncmd)),
7550 SHELL_ALIGN(sizeof(struct npipe)),
7551 SHELL_ALIGN(sizeof(struct nredir)),
7552 SHELL_ALIGN(sizeof(struct nredir)),
7553 SHELL_ALIGN(sizeof(struct nredir)),
7554 SHELL_ALIGN(sizeof(struct nbinary)),
7555 SHELL_ALIGN(sizeof(struct nbinary)),
7556 SHELL_ALIGN(sizeof(struct nbinary)),
7557 SHELL_ALIGN(sizeof(struct nif)),
7558 SHELL_ALIGN(sizeof(struct nbinary)),
7559 SHELL_ALIGN(sizeof(struct nbinary)),
7560 SHELL_ALIGN(sizeof(struct nfor)),
7561 SHELL_ALIGN(sizeof(struct ncase)),
7562 SHELL_ALIGN(sizeof(struct nclist)),
7563 SHELL_ALIGN(sizeof(struct narg)),
7564 SHELL_ALIGN(sizeof(struct narg)),
7565 SHELL_ALIGN(sizeof(struct nfile)),
7566 SHELL_ALIGN(sizeof(struct nfile)),
7567 SHELL_ALIGN(sizeof(struct nfile)),
7568 SHELL_ALIGN(sizeof(struct nfile)),
7569 SHELL_ALIGN(sizeof(struct nfile)),
7570 SHELL_ALIGN(sizeof(struct ndup)),
7571 SHELL_ALIGN(sizeof(struct ndup)),
7572 SHELL_ALIGN(sizeof(struct nhere)),
7573 SHELL_ALIGN(sizeof(struct nhere)),
7574 SHELL_ALIGN(sizeof(struct nnot)),
7577 static void calcsize(union node *n);
7580 sizenodelist(struct nodelist *lp)
7583 funcblocksize += SHELL_ALIGN(sizeof(struct nodelist));
7590 calcsize(union node *n)
7594 funcblocksize += nodesize[n->type];
7597 calcsize(n->ncmd.redirect);
7598 calcsize(n->ncmd.args);
7599 calcsize(n->ncmd.assign);
7602 sizenodelist(n->npipe.cmdlist);
7607 calcsize(n->nredir.redirect);
7608 calcsize(n->nredir.n);
7615 calcsize(n->nbinary.ch2);
7616 calcsize(n->nbinary.ch1);
7619 calcsize(n->nif.elsepart);
7620 calcsize(n->nif.ifpart);
7621 calcsize(n->nif.test);
7624 funcstringsize += strlen(n->nfor.var) + 1;
7625 calcsize(n->nfor.body);
7626 calcsize(n->nfor.args);
7629 calcsize(n->ncase.cases);
7630 calcsize(n->ncase.expr);
7633 calcsize(n->nclist.body);
7634 calcsize(n->nclist.pattern);
7635 calcsize(n->nclist.next);
7639 sizenodelist(n->narg.backquote);
7640 funcstringsize += strlen(n->narg.text) + 1;
7641 calcsize(n->narg.next);
7648 calcsize(n->nfile.fname);
7649 calcsize(n->nfile.next);
7653 calcsize(n->ndup.vname);
7654 calcsize(n->ndup.next);
7658 calcsize(n->nhere.doc);
7659 calcsize(n->nhere.next);
7662 calcsize(n->nnot.com);
7668 nodeckstrdup(char *s)
7670 char *rtn = funcstring;
7672 strcpy(funcstring, s);
7673 funcstring += strlen(s) + 1;
7677 static union node *copynode(union node *);
7679 static struct nodelist *
7680 copynodelist(struct nodelist *lp)
7682 struct nodelist *start;
7683 struct nodelist **lpp;
7688 funcblock = (char *) funcblock + SHELL_ALIGN(sizeof(struct nodelist));
7689 (*lpp)->n = copynode(lp->n);
7691 lpp = &(*lpp)->next;
7698 copynode(union node *n)
7705 funcblock = (char *) funcblock + nodesize[n->type];
7709 new->ncmd.redirect = copynode(n->ncmd.redirect);
7710 new->ncmd.args = copynode(n->ncmd.args);
7711 new->ncmd.assign = copynode(n->ncmd.assign);
7714 new->npipe.cmdlist = copynodelist(n->npipe.cmdlist);
7715 new->npipe.pipe_backgnd = n->npipe.pipe_backgnd;
7720 new->nredir.redirect = copynode(n->nredir.redirect);
7721 new->nredir.n = copynode(n->nredir.n);
7728 new->nbinary.ch2 = copynode(n->nbinary.ch2);
7729 new->nbinary.ch1 = copynode(n->nbinary.ch1);
7732 new->nif.elsepart = copynode(n->nif.elsepart);
7733 new->nif.ifpart = copynode(n->nif.ifpart);
7734 new->nif.test = copynode(n->nif.test);
7737 new->nfor.var = nodeckstrdup(n->nfor.var);
7738 new->nfor.body = copynode(n->nfor.body);
7739 new->nfor.args = copynode(n->nfor.args);
7742 new->ncase.cases = copynode(n->ncase.cases);
7743 new->ncase.expr = copynode(n->ncase.expr);
7746 new->nclist.body = copynode(n->nclist.body);
7747 new->nclist.pattern = copynode(n->nclist.pattern);
7748 new->nclist.next = copynode(n->nclist.next);
7752 new->narg.backquote = copynodelist(n->narg.backquote);
7753 new->narg.text = nodeckstrdup(n->narg.text);
7754 new->narg.next = copynode(n->narg.next);
7761 new->nfile.fname = copynode(n->nfile.fname);
7762 new->nfile.fd = n->nfile.fd;
7763 new->nfile.next = copynode(n->nfile.next);
7767 new->ndup.vname = copynode(n->ndup.vname);
7768 new->ndup.dupfd = n->ndup.dupfd;
7769 new->ndup.fd = n->ndup.fd;
7770 new->ndup.next = copynode(n->ndup.next);
7774 new->nhere.doc = copynode(n->nhere.doc);
7775 new->nhere.fd = n->nhere.fd;
7776 new->nhere.next = copynode(n->nhere.next);
7779 new->nnot.com = copynode(n->nnot.com);
7782 new->type = n->type;
7787 * Make a copy of a parse tree.
7789 static struct funcnode *
7790 copyfunc(union node *n)
7795 funcblocksize = offsetof(struct funcnode, n);
7798 blocksize = funcblocksize;
7799 f = ckmalloc(blocksize + funcstringsize);
7800 funcblock = (char *) f + offsetof(struct funcnode, n);
7801 funcstring = (char *) f + blocksize;
7808 * Define a shell function.
7811 defun(char *name, union node *func)
7813 struct cmdentry entry;
7816 entry.cmdtype = CMDFUNCTION;
7817 entry.u.func = copyfunc(func);
7818 addcmdentry(name, &entry);
7822 static int evalskip; /* set if we are skipping commands */
7823 /* reasons for skipping commands (see comment on breakcmd routine) */
7824 #define SKIPBREAK (1 << 0)
7825 #define SKIPCONT (1 << 1)
7826 #define SKIPFUNC (1 << 2)
7827 #define SKIPFILE (1 << 3)
7828 #define SKIPEVAL (1 << 4)
7829 static int skipcount; /* number of levels to skip */
7830 static int funcnest; /* depth of function calls */
7831 static int loopnest; /* current loop nesting level */
7833 /* forward decl way out to parsing code - dotrap needs it */
7834 static int evalstring(char *s, int mask);
7837 * Called to execute a trap. Perhaps we should avoid entering new trap
7838 * handlers while we are executing a trap handler.
7849 savestatus = exitstatus;
7853 for (i = 1, q = gotsig; i < NSIG; i++, q++) {
7861 skip = evalstring(p, SKIPEVAL);
7862 exitstatus = savestatus;
7870 /* forward declarations - evaluation is fairly recursive business... */
7871 static void evalloop(union node *, int);
7872 static void evalfor(union node *, int);
7873 static void evalcase(union node *, int);
7874 static void evalsubshell(union node *, int);
7875 static void expredir(union node *);
7876 static void evalpipe(union node *, int);
7877 static void evalcommand(union node *, int);
7878 static int evalbltin(const struct builtincmd *, int, char **);
7879 static void prehash(union node *);
7882 * Evaluate a parse tree. The value is left in the global variable
7886 evaltree(union node *n, int flags)
7889 struct jmploc *volatile savehandler = exception_handler;
7890 struct jmploc jmploc;
7892 void (*evalfn)(union node *, int);
7896 TRACE(("evaltree(NULL) called\n"));
7899 TRACE(("pid %d, evaltree(%p: %d, %d) called\n",
7900 getpid(), n, n->type, flags));
7902 exception_handler = &jmploc;
7904 int err = setjmp(jmploc.loc);
7906 /* if it was a signal, check for trap handlers */
7907 if (exception == EXSIG)
7909 /* continue on the way out */
7910 exception_handler = savehandler;
7911 longjmp(exception_handler->loc, err);
7918 out1fmt("Node type = %d\n", n->type);
7923 evaltree(n->nnot.com, EV_TESTED);
7924 status = !exitstatus;
7927 expredir(n->nredir.redirect);
7928 status = redirectsafe(n->nredir.redirect, REDIR_PUSH);
7930 evaltree(n->nredir.n, flags & EV_TESTED);
7931 status = exitstatus;
7933 popredir(/*drop:*/ 0, /*restore:*/ 0 /* not sure */);
7936 evalfn = evalcommand;
7938 if (eflag && !(flags & EV_TESTED))
7950 evalfn = evalsubshell;
7963 #error NAND + 1 != NOR
7965 #if NOR + 1 != NSEMI
7966 #error NOR + 1 != NSEMI
7968 unsigned is_or = n->type - NAND;
7971 (flags | ((is_or >> 1) - 1)) & EV_TESTED
7973 if (!exitstatus == is_or)
7986 evaltree(n->nif.test, EV_TESTED);
7989 if (exitstatus == 0) {
7992 } else if (n->nif.elsepart) {
7993 n = n->nif.elsepart;
7998 defun(n->narg.text, n->narg.next);
8002 exitstatus = status;
8007 exception_handler = savehandler;
8009 if (checkexit & exitstatus)
8010 evalskip |= SKIPEVAL;
8011 else if (pendingsig && dotrap())
8014 if (flags & EV_EXIT) {
8016 raise_exception(EXEXIT);
8020 #if !defined(__alpha__) || (defined(__GNUC__) && __GNUC__ >= 3)
8023 void evaltreenr(union node *, int) __attribute__ ((alias("evaltree"),__noreturn__));
8026 evalloop(union node *n, int flags)
8036 evaltree(n->nbinary.ch1, EV_TESTED);
8039 if (evalskip == SKIPCONT && --skipcount <= 0) {
8043 if (evalskip == SKIPBREAK && --skipcount <= 0)
8048 if (n->type != NWHILE)
8052 evaltree(n->nbinary.ch2, flags);
8053 status = exitstatus;
8058 exitstatus = status;
8062 evalfor(union node *n, int flags)
8064 struct arglist arglist;
8067 struct stackmark smark;
8069 setstackmark(&smark);
8070 arglist.list = NULL;
8071 arglist.lastp = &arglist.list;
8072 for (argp = n->nfor.args; argp; argp = argp->narg.next) {
8073 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE | EXP_RECORD);
8078 *arglist.lastp = NULL;
8083 for (sp = arglist.list; sp; sp = sp->next) {
8084 setvar(n->nfor.var, sp->text, 0);
8085 evaltree(n->nfor.body, flags);
8087 if (evalskip == SKIPCONT && --skipcount <= 0) {
8091 if (evalskip == SKIPBREAK && --skipcount <= 0)
8098 popstackmark(&smark);
8102 evalcase(union node *n, int flags)
8106 struct arglist arglist;
8107 struct stackmark smark;
8109 setstackmark(&smark);
8110 arglist.list = NULL;
8111 arglist.lastp = &arglist.list;
8112 expandarg(n->ncase.expr, &arglist, EXP_TILDE);
8114 for (cp = n->ncase.cases; cp && evalskip == 0; cp = cp->nclist.next) {
8115 for (patp = cp->nclist.pattern; patp; patp = patp->narg.next) {
8116 if (casematch(patp, arglist.list->text)) {
8117 if (evalskip == 0) {
8118 evaltree(cp->nclist.body, flags);
8125 popstackmark(&smark);
8129 * Kick off a subshell to evaluate a tree.
8132 evalsubshell(union node *n, int flags)
8135 int backgnd = (n->type == NBACKGND);
8138 expredir(n->nredir.redirect);
8139 if (!backgnd && flags & EV_EXIT && !trap[0])
8142 jp = makejob(/*n,*/ 1);
8143 if (forkshell(jp, n, backgnd) == 0) {
8147 flags &=~ EV_TESTED;
8149 redirect(n->nredir.redirect, 0);
8150 evaltreenr(n->nredir.n, flags);
8155 status = waitforjob(jp);
8156 exitstatus = status;
8161 * Compute the names of the files in a redirection list.
8163 static void fixredir(union node *, const char *, int);
8165 expredir(union node *n)
8169 for (redir = n; redir; redir = redir->nfile.next) {
8173 fn.lastp = &fn.list;
8174 switch (redir->type) {
8180 expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
8181 redir->nfile.expfname = fn.list->text;
8185 if (redir->ndup.vname) {
8186 expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE);
8187 if (fn.list == NULL)
8188 ash_msg_and_raise_error("redir error");
8189 fixredir(redir, fn.list->text, 1);
8197 * Evaluate a pipeline. All the processes in the pipeline are children
8198 * of the process creating the pipeline. (This differs from some versions
8199 * of the shell, which make the last process in a pipeline the parent
8203 evalpipe(union node *n, int flags)
8206 struct nodelist *lp;
8211 TRACE(("evalpipe(0x%lx) called\n", (long)n));
8213 for (lp = n->npipe.cmdlist; lp; lp = lp->next)
8217 jp = makejob(/*n,*/ pipelen);
8219 for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
8223 if (pipe(pip) < 0) {
8225 ash_msg_and_raise_error("pipe call failed");
8228 if (forkshell(jp, lp->n, n->npipe.pipe_backgnd) == 0) {
8241 evaltreenr(lp->n, flags);
8249 if (n->npipe.pipe_backgnd == 0) {
8250 exitstatus = waitforjob(jp);
8251 TRACE(("evalpipe: job done exit status %d\n", exitstatus));
8257 * Controls whether the shell is interactive or not.
8260 setinteractive(int on)
8262 static smallint is_interactive;
8264 if (++on == is_interactive)
8266 is_interactive = on;
8270 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
8271 if (is_interactive > 1) {
8272 /* Looks like they want an interactive shell */
8273 static smallint did_banner;
8278 "%s built-in shell (ash)\n"
8279 "Enter 'help' for a list of built-in commands."
8294 setinteractive(iflag);
8296 #if ENABLE_FEATURE_EDITING_VI
8298 line_input_state->flags |= VI_MODE;
8300 line_input_state->flags &= ~VI_MODE;
8302 viflag = 0; /* forcibly keep the option off */
8306 static struct localvar *localvars;
8309 * Called after a function returns.
8310 * Interrupts must be off.
8315 struct localvar *lvp;
8318 while ((lvp = localvars) != NULL) {
8319 localvars = lvp->next;
8321 TRACE(("poplocalvar %s", vp ? vp->text : "-"));
8322 if (vp == NULL) { /* $- saved */
8323 memcpy(optlist, lvp->text, sizeof(optlist));
8324 free((char*)lvp->text);
8326 } else if ((lvp->flags & (VUNSET|VSTRFIXED)) == VUNSET) {
8330 (*vp->func)(strchrnul(lvp->text, '=') + 1);
8331 if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
8332 free((char*)vp->text);
8333 vp->flags = lvp->flags;
8334 vp->text = lvp->text;
8341 evalfun(struct funcnode *func, int argc, char **argv, int flags)
8343 volatile struct shparam saveparam;
8344 struct localvar *volatile savelocalvars;
8345 struct jmploc *volatile savehandler;
8346 struct jmploc jmploc;
8349 saveparam = shellparam;
8350 savelocalvars = localvars;
8351 e = setjmp(jmploc.loc);
8356 savehandler = exception_handler;
8357 exception_handler = &jmploc;
8359 shellparam.malloced = 0;
8363 shellparam.nparam = argc - 1;
8364 shellparam.p = argv + 1;
8365 #if ENABLE_ASH_GETOPTS
8366 shellparam.optind = 1;
8367 shellparam.optoff = -1;
8369 evaltree(&func->n, flags & EV_TESTED);
8375 localvars = savelocalvars;
8376 freeparam(&shellparam);
8377 shellparam = saveparam;
8378 exception_handler = savehandler;
8380 evalskip &= ~SKIPFUNC;
8384 #if ENABLE_ASH_CMDCMD
8386 parse_command_args(char **argv, const char **path)
8399 if (c == '-' && !*cp) {
8406 *path = bb_default_path;
8409 /* run 'typecmd' for other options */
8420 * Make a variable a local variable. When a variable is made local, it's
8421 * value and flags are saved in a localvar structure. The saved values
8422 * will be restored when the shell function returns. We handle the name
8423 * "-" as a special case.
8428 struct localvar *lvp;
8433 lvp = ckzalloc(sizeof(struct localvar));
8434 if (LONE_DASH(name)) {
8436 p = ckmalloc(sizeof(optlist));
8437 lvp->text = memcpy(p, optlist, sizeof(optlist));
8442 vpp = hashvar(name);
8443 vp = *findvar(vpp, name);
8444 eq = strchr(name, '=');
8447 setvareq(name, VSTRFIXED);
8449 setvar(name, NULL, VSTRFIXED);
8450 vp = *vpp; /* the new variable */
8451 lvp->flags = VUNSET;
8453 lvp->text = vp->text;
8454 lvp->flags = vp->flags;
8455 vp->flags |= VSTRFIXED|VTEXTFIXED;
8461 lvp->next = localvars;
8467 * The "local" command.
8470 localcmd(int argc UNUSED_PARAM, char **argv)
8475 while ((name = *argv++) != NULL) {
8482 falsecmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
8488 truecmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
8494 execcmd(int argc UNUSED_PARAM, char **argv)
8497 iflag = 0; /* exit on error */
8500 shellexec(argv + 1, pathval(), 0);
8506 * The return command.
8509 returncmd(int argc UNUSED_PARAM, char **argv)
8512 * If called outside a function, do what ksh does;
8513 * skip the rest of the file.
8515 evalskip = funcnest ? SKIPFUNC : SKIPFILE;
8516 return argv[1] ? number(argv[1]) : exitstatus;
8519 /* Forward declarations for builtintab[] */
8520 static int breakcmd(int, char **);
8521 static int dotcmd(int, char **);
8522 static int evalcmd(int, char **);
8523 static int exitcmd(int, char **);
8524 static int exportcmd(int, char **);
8525 #if ENABLE_ASH_GETOPTS
8526 static int getoptscmd(int, char **);
8528 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
8529 static int helpcmd(int, char **);
8531 #if ENABLE_ASH_MATH_SUPPORT
8532 static int letcmd(int, char **);
8534 static int readcmd(int, char **);
8535 static int setcmd(int, char **);
8536 static int shiftcmd(int, char **);
8537 static int timescmd(int, char **);
8538 static int trapcmd(int, char **);
8539 static int umaskcmd(int, char **);
8540 static int unsetcmd(int, char **);
8541 static int ulimitcmd(int, char **);
8543 #define BUILTIN_NOSPEC "0"
8544 #define BUILTIN_SPECIAL "1"
8545 #define BUILTIN_REGULAR "2"
8546 #define BUILTIN_SPEC_REG "3"
8547 #define BUILTIN_ASSIGN "4"
8548 #define BUILTIN_SPEC_ASSG "5"
8549 #define BUILTIN_REG_ASSG "6"
8550 #define BUILTIN_SPEC_REG_ASSG "7"
8552 /* We do not handle [[ expr ]] bashism bash-compatibly,
8553 * we make it a synonym of [ expr ].
8554 * Basically, word splitting and pathname expansion should NOT be performed
8556 * no word splitting: a="a b"; [[ $a = "a b" ]]; echo $? should print "0"
8557 * no pathname expansion: [[ /bin/m* = "/bin/m*" ]]; echo $? should print "0"
8558 * Additional operators:
8559 * || and && should work as -o and -a
8561 * Apart from the above, [[ expr ]] should work as [ expr ]
8564 #define echocmd echo_main
8565 #define printfcmd printf_main
8566 #define testcmd test_main
8568 /* Keep these in proper order since it is searched via bsearch() */
8569 static const struct builtincmd builtintab[] = {
8570 { BUILTIN_SPEC_REG ".", dotcmd },
8571 { BUILTIN_SPEC_REG ":", truecmd },
8572 #if ENABLE_ASH_BUILTIN_TEST
8573 { BUILTIN_REGULAR "[", testcmd },
8574 #if ENABLE_ASH_BASH_COMPAT
8575 { BUILTIN_REGULAR "[[", testcmd },
8578 #if ENABLE_ASH_ALIAS
8579 { BUILTIN_REG_ASSG "alias", aliascmd },
8582 { BUILTIN_REGULAR "bg", fg_bgcmd },
8584 { BUILTIN_SPEC_REG "break", breakcmd },
8585 { BUILTIN_REGULAR "cd", cdcmd },
8586 { BUILTIN_NOSPEC "chdir", cdcmd },
8587 #if ENABLE_ASH_CMDCMD
8588 { BUILTIN_REGULAR "command", commandcmd },
8590 { BUILTIN_SPEC_REG "continue", breakcmd },
8591 #if ENABLE_ASH_BUILTIN_ECHO
8592 { BUILTIN_REGULAR "echo", echocmd },
8594 { BUILTIN_SPEC_REG "eval", evalcmd },
8595 { BUILTIN_SPEC_REG "exec", execcmd },
8596 { BUILTIN_SPEC_REG "exit", exitcmd },
8597 { BUILTIN_SPEC_REG_ASSG "export", exportcmd },
8598 { BUILTIN_REGULAR "false", falsecmd },
8600 { BUILTIN_REGULAR "fg", fg_bgcmd },
8602 #if ENABLE_ASH_GETOPTS
8603 { BUILTIN_REGULAR "getopts", getoptscmd },
8605 { BUILTIN_NOSPEC "hash", hashcmd },
8606 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
8607 { BUILTIN_NOSPEC "help", helpcmd },
8610 { BUILTIN_REGULAR "jobs", jobscmd },
8611 { BUILTIN_REGULAR "kill", killcmd },
8613 #if ENABLE_ASH_MATH_SUPPORT
8614 { BUILTIN_NOSPEC "let", letcmd },
8616 { BUILTIN_ASSIGN "local", localcmd },
8617 #if ENABLE_ASH_BUILTIN_PRINTF
8618 { BUILTIN_REGULAR "printf", printfcmd },
8620 { BUILTIN_NOSPEC "pwd", pwdcmd },
8621 { BUILTIN_REGULAR "read", readcmd },
8622 { BUILTIN_SPEC_REG_ASSG "readonly", exportcmd },
8623 { BUILTIN_SPEC_REG "return", returncmd },
8624 { BUILTIN_SPEC_REG "set", setcmd },
8625 { BUILTIN_SPEC_REG "shift", shiftcmd },
8626 { BUILTIN_SPEC_REG "source", dotcmd },
8627 #if ENABLE_ASH_BUILTIN_TEST
8628 { BUILTIN_REGULAR "test", testcmd },
8630 { BUILTIN_SPEC_REG "times", timescmd },
8631 { BUILTIN_SPEC_REG "trap", trapcmd },
8632 { BUILTIN_REGULAR "true", truecmd },
8633 { BUILTIN_NOSPEC "type", typecmd },
8634 { BUILTIN_NOSPEC "ulimit", ulimitcmd },
8635 { BUILTIN_REGULAR "umask", umaskcmd },
8636 #if ENABLE_ASH_ALIAS
8637 { BUILTIN_REGULAR "unalias", unaliascmd },
8639 { BUILTIN_SPEC_REG "unset", unsetcmd },
8640 { BUILTIN_REGULAR "wait", waitcmd },
8643 /* Should match the above table! */
8644 #define COMMANDCMD (builtintab + \
8646 1 * ENABLE_ASH_BUILTIN_TEST + \
8647 1 * ENABLE_ASH_BUILTIN_TEST * ENABLE_ASH_BASH_COMPAT + \
8648 1 * ENABLE_ASH_ALIAS + \
8649 1 * ENABLE_ASH_JOB_CONTROL + \
8651 #define EXECCMD (builtintab + \
8653 1 * ENABLE_ASH_BUILTIN_TEST + \
8654 1 * ENABLE_ASH_BUILTIN_TEST * ENABLE_ASH_BASH_COMPAT + \
8655 1 * ENABLE_ASH_ALIAS + \
8656 1 * ENABLE_ASH_JOB_CONTROL + \
8658 1 * ENABLE_ASH_CMDCMD + \
8660 ENABLE_ASH_BUILTIN_ECHO + \
8664 * Search the table of builtin commands.
8666 static struct builtincmd *
8667 find_builtin(const char *name)
8669 struct builtincmd *bp;
8672 name, builtintab, ARRAY_SIZE(builtintab), sizeof(builtintab[0]),
8679 * Execute a simple command.
8682 isassignment(const char *p)
8684 const char *q = endofname(p);
8690 bltincmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
8692 /* Preserve exitstatus of a previous possible redirection
8693 * as POSIX mandates */
8694 return back_exitstatus;
8697 evalcommand(union node *cmd, int flags)
8699 static const struct builtincmd null_bltin = {
8700 "\0\0", bltincmd /* why three NULs? */
8702 struct stackmark smark;
8704 struct arglist arglist;
8705 struct arglist varlist;
8708 const struct strlist *sp;
8709 struct cmdentry cmdentry;
8716 struct builtincmd *bcmd;
8717 smallint cmd_is_exec;
8718 smallint pseudovarflag = 0;
8720 /* First expand the arguments. */
8721 TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
8722 setstackmark(&smark);
8723 back_exitstatus = 0;
8725 cmdentry.cmdtype = CMDBUILTIN;
8726 cmdentry.u.cmd = &null_bltin;
8727 varlist.lastp = &varlist.list;
8728 *varlist.lastp = NULL;
8729 arglist.lastp = &arglist.list;
8730 *arglist.lastp = NULL;
8733 if (cmd->ncmd.args) {
8734 bcmd = find_builtin(cmd->ncmd.args->narg.text);
8735 pseudovarflag = bcmd && IS_BUILTIN_ASSIGN(bcmd);
8738 for (argp = cmd->ncmd.args; argp; argp = argp->narg.next) {
8739 struct strlist **spp;
8741 spp = arglist.lastp;
8742 if (pseudovarflag && isassignment(argp->narg.text))
8743 expandarg(argp, &arglist, EXP_VARTILDE);
8745 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
8747 for (sp = *spp; sp; sp = sp->next)
8751 argv = nargv = stalloc(sizeof(char *) * (argc + 1));
8752 for (sp = arglist.list; sp; sp = sp->next) {
8753 TRACE(("evalcommand arg: %s\n", sp->text));
8754 *nargv++ = sp->text;
8759 if (iflag && funcnest == 0 && argc > 0)
8760 lastarg = nargv[-1];
8763 expredir(cmd->ncmd.redirect);
8764 status = redirectsafe(cmd->ncmd.redirect, REDIR_PUSH | REDIR_SAVEFD2);
8767 for (argp = cmd->ncmd.assign; argp; argp = argp->narg.next) {
8768 struct strlist **spp;
8771 spp = varlist.lastp;
8772 expandarg(argp, &varlist, EXP_VARTILDE);
8775 * Modify the command lookup path, if a PATH= assignment
8779 if (varequal(p, path))
8783 /* Print the command if xflag is set. */
8786 const char *p = " %s";
8789 fdprintf(preverrout_fd, p, expandstr(ps4val()));
8792 for (n = 0; n < 2; n++) {
8794 fdprintf(preverrout_fd, p, sp->text);
8802 safe_write(preverrout_fd, "\n", 1);
8808 /* Now locate the command. */
8810 const char *oldpath;
8811 int cmd_flag = DO_ERR;
8816 find_command(argv[0], &cmdentry, cmd_flag, path);
8817 if (cmdentry.cmdtype == CMDUNKNOWN) {
8823 /* implement bltin and command here */
8824 if (cmdentry.cmdtype != CMDBUILTIN)
8827 spclbltin = IS_BUILTIN_SPECIAL(cmdentry.u.cmd);
8828 if (cmdentry.u.cmd == EXECCMD)
8830 #if ENABLE_ASH_CMDCMD
8831 if (cmdentry.u.cmd == COMMANDCMD) {
8833 nargv = parse_command_args(argv, &path);
8836 argc -= nargv - argv;
8838 cmd_flag |= DO_NOFUNC;
8846 /* We have a redirection error. */
8848 raise_exception(EXERROR);
8850 exitstatus = status;
8854 /* Execute the command. */
8855 switch (cmdentry.cmdtype) {
8857 #if ENABLE_FEATURE_SH_NOFORK
8859 /* find_command() encodes applet_no as (-2 - applet_no) */
8860 int applet_no = (- cmdentry.u.index - 2);
8861 if (applet_no >= 0 && APPLET_IS_NOFORK(applet_no)) {
8862 listsetvar(varlist.list, VEXPORT|VSTACK);
8863 /* run <applet>_main() */
8864 exitstatus = run_nofork_applet(applet_no, argv);
8870 /* Fork off a child process if necessary. */
8871 if (!(flags & EV_EXIT) || trap[0]) {
8873 jp = makejob(/*cmd,*/ 1);
8874 if (forkshell(jp, cmd, FORK_FG) != 0) {
8875 exitstatus = waitforjob(jp);
8881 listsetvar(varlist.list, VEXPORT|VSTACK);
8882 shellexec(argv, path, cmdentry.u.index);
8886 cmdenviron = varlist.list;
8888 struct strlist *list = cmdenviron;
8890 if (spclbltin > 0 || argc == 0) {
8892 if (cmd_is_exec && argc > 1)
8895 listsetvar(list, i);
8897 if (evalbltin(cmdentry.u.cmd, argc, argv)) {
8904 exit_status = 128 + SIGINT;
8906 exit_status = 128 + pendingsig;
8907 exitstatus = exit_status;
8908 if (i == EXINT || spclbltin > 0) {
8910 longjmp(exception_handler->loc, 1);
8917 listsetvar(varlist.list, 0);
8918 if (evalfun(cmdentry.u.func, argc, argv, flags))
8924 popredir(/*drop:*/ cmd_is_exec, /*restore:*/ cmd_is_exec);
8926 /* dsl: I think this is intended to be used to support
8927 * '_' in 'vi' command mode during line editing...
8928 * However I implemented that within libedit itself.
8930 setvar("_", lastarg, 0);
8932 popstackmark(&smark);
8936 evalbltin(const struct builtincmd *cmd, int argc, char **argv)
8938 char *volatile savecmdname;
8939 struct jmploc *volatile savehandler;
8940 struct jmploc jmploc;
8943 savecmdname = commandname;
8944 i = setjmp(jmploc.loc);
8947 savehandler = exception_handler;
8948 exception_handler = &jmploc;
8949 commandname = argv[0];
8951 optptr = NULL; /* initialize nextopt */
8952 exitstatus = (*cmd->builtin)(argc, argv);
8953 flush_stdout_stderr();
8955 exitstatus |= ferror(stdout);
8957 commandname = savecmdname;
8959 exception_handler = savehandler;
8965 goodname(const char *p)
8967 return !*endofname(p);
8972 * Search for a command. This is called before we fork so that the
8973 * location of the command will be available in the parent as well as
8974 * the child. The check for "goodname" is an overly conservative
8975 * check that the name will not be subject to expansion.
8978 prehash(union node *n)
8980 struct cmdentry entry;
8982 if (n->type == NCMD && n->ncmd.args && goodname(n->ncmd.args->narg.text))
8983 find_command(n->ncmd.args->narg.text, &entry, 0, pathval());
8987 /* ============ Builtin commands
8989 * Builtin commands whose functions are closely tied to evaluation
8990 * are implemented here.
8994 * Handle break and continue commands. Break, continue, and return are
8995 * all handled by setting the evalskip flag. The evaluation routines
8996 * above all check this flag, and if it is set they start skipping
8997 * commands rather than executing them. The variable skipcount is
8998 * the number of loops to break/continue, or the number of function
8999 * levels to return. (The latter is always 1.) It should probably
9000 * be an error to break out of more loops than exist, but it isn't
9001 * in the standard shell so we don't make it one here.
9004 breakcmd(int argc UNUSED_PARAM, char **argv)
9006 int n = argv[1] ? number(argv[1]) : 1;
9009 ash_msg_and_raise_error(illnum, argv[1]);
9013 evalskip = (**argv == 'c') ? SKIPCONT : SKIPBREAK;
9020 /* ============ input.c
9022 * This implements the input routines used by the parser.
9025 #define EOF_NLEFT -99 /* value of parsenleft when EOF pushed back */
9028 INPUT_PUSH_FILE = 1,
9029 INPUT_NOFILE_OK = 2,
9032 static int plinno = 1; /* input line number */
9033 /* number of characters left in input buffer */
9034 static int parsenleft; /* copy of parsefile->nleft */
9035 static int parselleft; /* copy of parsefile->lleft */
9036 /* next character in input buffer */
9037 static char *parsenextc; /* copy of parsefile->nextc */
9039 static smallint checkkwd;
9040 /* values of checkkwd variable */
9041 #define CHKALIAS 0x1
9048 struct strpush *sp = g_parsefile->strpush;
9051 #if ENABLE_ASH_ALIAS
9053 if (parsenextc[-1] == ' ' || parsenextc[-1] == '\t') {
9054 checkkwd |= CHKALIAS;
9056 if (sp->string != sp->ap->val) {
9059 sp->ap->flag &= ~ALIASINUSE;
9060 if (sp->ap->flag & ALIASDEAD) {
9061 unalias(sp->ap->name);
9065 parsenextc = sp->prevstring;
9066 parsenleft = sp->prevnleft;
9067 /*dprintf("*** calling popstring: restoring to '%s'\n", parsenextc);*/
9068 g_parsefile->strpush = sp->prev;
9069 if (sp != &(g_parsefile->basestrpush))
9078 char *buf = g_parsefile->buf;
9081 #if ENABLE_FEATURE_EDITING
9083 if (!iflag || g_parsefile->fd)
9084 nr = nonblock_safe_read(g_parsefile->fd, buf, BUFSIZ - 1);
9086 #if ENABLE_FEATURE_TAB_COMPLETION
9087 line_input_state->path_lookup = pathval();
9089 nr = read_line_input(cmdedit_prompt, buf, BUFSIZ, line_input_state);
9091 /* Ctrl+C pressed */
9100 if (nr < 0 && errno == 0) {
9101 /* Ctrl+D pressed */
9106 nr = nonblock_safe_read(g_parsefile->fd, buf, BUFSIZ - 1);
9110 /* nonblock_safe_read() handles this problem */
9112 if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
9113 int flags = fcntl(0, F_GETFL);
9114 if (flags >= 0 && (flags & O_NONBLOCK)) {
9115 flags &= ~O_NONBLOCK;
9116 if (fcntl(0, F_SETFL, flags) >= 0) {
9117 out2str("sh: turning off NDELAY mode\n");
9128 * Refill the input buffer and return the next input character:
9130 * 1) If a string was pushed back on the input, pop it;
9131 * 2) If an EOF was pushed back (parsenleft == EOF_NLEFT) or we are reading
9132 * from a string so we can't refill the buffer, return EOF.
9133 * 3) If the is more stuff in this buffer, use it else call read to fill it.
9134 * 4) Process input up to the next newline, deleting nul characters.
9143 while (g_parsefile->strpush) {
9144 #if ENABLE_ASH_ALIAS
9145 if (parsenleft == -1 && g_parsefile->strpush->ap &&
9146 parsenextc[-1] != ' ' && parsenextc[-1] != '\t') {
9151 if (--parsenleft >= 0)
9152 return signed_char2int(*parsenextc++);
9154 if (parsenleft == EOF_NLEFT || g_parsefile->buf == NULL)
9156 flush_stdout_stderr();
9163 parselleft = parsenleft = EOF_NLEFT;
9170 /* delete nul characters */
9178 memmove(q, q + 1, more);
9182 parsenleft = q - parsenextc - 1;
9188 parsenleft = q - parsenextc - 1;
9200 out2str(parsenextc);
9205 return signed_char2int(*parsenextc++);
9208 #define pgetc_as_macro() (--parsenleft >= 0? signed_char2int(*parsenextc++) : preadbuffer())
9212 return pgetc_as_macro();
9215 #if ENABLE_ASH_OPTIMIZE_FOR_SIZE
9216 #define pgetc_macro() pgetc()
9218 #define pgetc_macro() pgetc_as_macro()
9222 * Same as pgetc(), but ignores PEOA.
9224 #if ENABLE_ASH_ALIAS
9232 } while (c == PEOA);
9239 return pgetc_macro();
9244 * Read a line from the script.
9247 pfgets(char *line, int len)
9253 while (--nleft > 0) {
9269 * Undo the last call to pgetc. Only one character may be pushed back.
9270 * PEOF may be pushed back.
9280 * Push a string back onto the input at this current parsefile level.
9281 * We handle aliases this way.
9283 #if !ENABLE_ASH_ALIAS
9284 #define pushstring(s, ap) pushstring(s)
9287 pushstring(char *s, struct alias *ap)
9294 /*dprintf("*** calling pushstring: %s, %d\n", s, len);*/
9295 if (g_parsefile->strpush) {
9296 sp = ckzalloc(sizeof(struct strpush));
9297 sp->prev = g_parsefile->strpush;
9298 g_parsefile->strpush = sp;
9300 sp = g_parsefile->strpush = &(g_parsefile->basestrpush);
9301 sp->prevstring = parsenextc;
9302 sp->prevnleft = parsenleft;
9303 #if ENABLE_ASH_ALIAS
9306 ap->flag |= ALIASINUSE;
9316 * To handle the "." command, a stack of input files is used. Pushfile
9317 * adds a new entry to the stack and popfile restores the previous level.
9322 struct parsefile *pf;
9324 g_parsefile->nleft = parsenleft;
9325 g_parsefile->lleft = parselleft;
9326 g_parsefile->nextc = parsenextc;
9327 g_parsefile->linno = plinno;
9328 pf = ckzalloc(sizeof(*pf));
9329 pf->prev = g_parsefile;
9331 /*pf->strpush = NULL; - ckzalloc did it */
9332 /*pf->basestrpush.prev = NULL;*/
9339 struct parsefile *pf = g_parsefile;
9347 g_parsefile = pf->prev;
9349 parsenleft = g_parsefile->nleft;
9350 parselleft = g_parsefile->lleft;
9351 parsenextc = g_parsefile->nextc;
9352 plinno = g_parsefile->linno;
9357 * Return to top level.
9362 while (g_parsefile != &basepf)
9367 * Close the file(s) that the shell is reading commands from. Called
9368 * after a fork is done.
9374 if (g_parsefile->fd > 0) {
9375 close(g_parsefile->fd);
9376 g_parsefile->fd = 0;
9381 * Like setinputfile, but takes an open file descriptor. Call this with
9385 setinputfd(int fd, int push)
9387 close_on_exec_on(fd);
9390 g_parsefile->buf = 0;
9392 g_parsefile->fd = fd;
9393 if (g_parsefile->buf == NULL)
9394 g_parsefile->buf = ckmalloc(IBUFSIZ);
9395 parselleft = parsenleft = 0;
9400 * Set the input to take input from a file. If push is set, push the
9401 * old input onto the stack first.
9404 setinputfile(const char *fname, int flags)
9410 fd = open(fname, O_RDONLY);
9412 if (flags & INPUT_NOFILE_OK)
9414 ash_msg_and_raise_error("can't open %s", fname);
9417 fd2 = copyfd(fd, 10);
9420 ash_msg_and_raise_error("out of file descriptors");
9423 setinputfd(fd, flags & INPUT_PUSH_FILE);
9430 * Like setinputfile, but takes input from a string.
9433 setinputstring(char *string)
9437 parsenextc = string;
9438 parsenleft = strlen(string);
9439 g_parsefile->buf = NULL;
9445 /* ============ mail.c
9447 * Routines to check for mail.
9452 #define MAXMBOXES 10
9454 /* times of mailboxes */
9455 static time_t mailtime[MAXMBOXES];
9456 /* Set if MAIL or MAILPATH is changed. */
9457 static smallint mail_var_path_changed;
9460 * Print appropriate message(s) if mail has arrived.
9461 * If mail_var_path_changed is set,
9462 * then the value of MAIL has mail_var_path_changed,
9463 * so we just update the values.
9472 struct stackmark smark;
9475 setstackmark(&smark);
9476 mpath = mpathset() ? mpathval() : mailval();
9477 for (mtp = mailtime; mtp < mailtime + MAXMBOXES; mtp++) {
9478 p = padvance(&mpath, nullstr);
9483 for (q = p; *q; q++)
9489 q[-1] = '\0'; /* delete trailing '/' */
9490 if (stat(p, &statb) < 0) {
9494 if (!mail_var_path_changed && statb.st_mtime != *mtp) {
9497 pathopt ? pathopt : "you have mail"
9500 *mtp = statb.st_mtime;
9502 mail_var_path_changed = 0;
9503 popstackmark(&smark);
9507 changemail(const char *val UNUSED_PARAM)
9509 mail_var_path_changed = 1;
9512 #endif /* ASH_MAIL */
9515 /* ============ ??? */
9518 * Set the shell parameters.
9521 setparam(char **argv)
9527 for (nparam = 0; argv[nparam]; nparam++)
9529 ap = newparam = ckmalloc((nparam + 1) * sizeof(*ap));
9531 *ap++ = ckstrdup(*argv++);
9534 freeparam(&shellparam);
9535 shellparam.malloced = 1;
9536 shellparam.nparam = nparam;
9537 shellparam.p = newparam;
9538 #if ENABLE_ASH_GETOPTS
9539 shellparam.optind = 1;
9540 shellparam.optoff = -1;
9545 * Process shell options. The global variable argptr contains a pointer
9546 * to the argument list; we advance it past the options.
9548 * SUSv3 section 2.8.1 "Consequences of Shell Errors" says:
9549 * For a non-interactive shell, an error condition encountered
9550 * by a special built-in ... shall cause the shell to write a diagnostic message
9551 * to standard error and exit as shown in the following table:
9552 * Error Special Built-In
9554 * Utility syntax error (option or operand error) Shall exit
9556 * However, in bug 1142 (http://busybox.net/bugs/view.php?id=1142)
9557 * we see that bash does not do that (set "finishes" with error code 1 instead,
9558 * and shell continues), and people rely on this behavior!
9560 * set -o barfoo 2>/dev/null
9563 * Oh well. Let's mimic that.
9566 plus_minus_o(char *name, int val)
9571 for (i = 0; i < NOPTS; i++) {
9572 if (strcmp(name, optnames(i)) == 0) {
9577 ash_msg("illegal option %co %s", val ? '-' : '+', name);
9580 for (i = 0; i < NOPTS; i++) {
9582 out1fmt("%-16s%s\n", optnames(i), optlist[i] ? "on" : "off");
9584 out1fmt("set %co %s\n", optlist[i] ? '-' : '+', optnames(i));
9590 setoption(int flag, int val)
9594 for (i = 0; i < NOPTS; i++) {
9595 if (optletters(i) == flag) {
9600 ash_msg_and_raise_error("illegal option %c%c", val ? '-' : '+', flag);
9604 options(int cmdline)
9612 while ((p = *argptr) != NULL) {
9614 if (c != '-' && c != '+')
9617 val = 0; /* val = 0 if c == '+' */
9620 if (p[0] == '\0' || LONE_DASH(p)) {
9622 /* "-" means turn off -x and -v */
9625 /* "--" means reset params */
9626 else if (*argptr == NULL)
9629 break; /* "-" or "--" terminates options */
9632 /* first char was + or - */
9633 while ((c = *p++) != '\0') {
9634 /* bash 3.2 indeed handles -c CMD and +c CMD the same */
9635 if (c == 'c' && cmdline) {
9636 minusc = p; /* command is after shell args */
9637 } else if (c == 'o') {
9638 if (plus_minus_o(*argptr, val)) {
9639 /* it already printed err message */
9640 return 1; /* error */
9644 } else if (cmdline && (c == 'l')) { /* -l or +l == --login */
9646 /* bash does not accept +-login, we also won't */
9647 } else if (cmdline && val && (c == '-')) { /* long options */
9648 if (strcmp(p, "login") == 0)
9660 * The shift builtin command.
9663 shiftcmd(int argc UNUSED_PARAM, char **argv)
9670 n = number(argv[1]);
9671 if (n > shellparam.nparam)
9672 n = 0; /* bash compat, was = shellparam.nparam; */
9674 shellparam.nparam -= n;
9675 for (ap1 = shellparam.p; --n >= 0; ap1++) {
9676 if (shellparam.malloced)
9680 while ((*ap2++ = *ap1++) != NULL)
9682 #if ENABLE_ASH_GETOPTS
9683 shellparam.optind = 1;
9684 shellparam.optoff = -1;
9691 * POSIX requires that 'set' (but not export or readonly) output the
9692 * variables in lexicographic order - by the locale's collating order (sigh).
9693 * Maybe we could keep them in an ordered balanced binary tree
9694 * instead of hashed lists.
9695 * For now just roll 'em through qsort for printing...
9698 showvars(const char *sep_prefix, int on, int off)
9703 ep = listvars(on, off, &epend);
9704 qsort(ep, epend - ep, sizeof(char *), vpcmp);
9706 sep = *sep_prefix ? " " : sep_prefix;
9708 for (; ep < epend; ep++) {
9712 p = strchrnul(*ep, '=');
9715 q = single_quote(++p);
9716 out1fmt("%s%s%.*s%s\n", sep_prefix, sep, (int)(p - *ep), *ep, q);
9722 * The set command builtin.
9725 setcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9730 return showvars(nullstr, 0, VUNSET);
9733 if (!options(0)) { /* if no parse error... */
9736 if (*argptr != NULL) {
9744 #if ENABLE_ASH_RANDOM_SUPPORT
9746 change_random(const char *value)
9748 /* Galois LFSR parameter */
9749 /* Taps at 32 31 29 1: */
9750 enum { MASK = 0x8000000b };
9751 /* Another example - taps at 32 31 30 10: */
9752 /* MASK = 0x00400007 */
9754 if (value == NULL) {
9755 /* "get", generate */
9758 /* LCG has period of 2^32 and alternating lowest bit */
9759 random_LCG = 1664525 * random_LCG + 1013904223;
9760 /* Galois LFSR has period of 2^32-1 = 3 * 5 * 17 * 257 * 65537 */
9761 t = (random_galois_LFSR << 1);
9762 if (random_galois_LFSR < 0) /* if we just shifted 1 out of msb... */
9764 random_galois_LFSR = t;
9765 /* Both are weak, combining them gives better randomness
9766 * and ~2^64 period. & 0x7fff is probably bash compat
9767 * for $RANDOM range. Combining with subtraction is
9768 * just for fun. + and ^ would work equally well. */
9769 t = (t - random_LCG) & 0x7fff;
9770 /* set without recursion */
9771 setvar(vrandom.text, utoa(t), VNOFUNC);
9772 vrandom.flags &= ~VNOFUNC;
9775 random_galois_LFSR = random_LCG = strtoul(value, (char **)NULL, 10);
9780 #if ENABLE_ASH_GETOPTS
9782 getopts(char *optstr, char *optvar, char **optfirst, int *param_optind, int *optoff)
9791 if (*param_optind < 1)
9793 optnext = optfirst + *param_optind - 1;
9795 if (*param_optind <= 1 || *optoff < 0 || (int)strlen(optnext[-1]) < *optoff)
9798 p = optnext[-1] + *optoff;
9799 if (p == NULL || *p == '\0') {
9800 /* Current word is done, advance */
9802 if (p == NULL || *p != '-' || *++p == '\0') {
9809 if (LONE_DASH(p)) /* check for "--" */
9814 for (q = optstr; *q != c;) {
9816 if (optstr[0] == ':') {
9819 err |= setvarsafe("OPTARG", s, 0);
9821 fprintf(stderr, "Illegal option -%c\n", c);
9832 if (*p == '\0' && (p = *optnext) == NULL) {
9833 if (optstr[0] == ':') {
9836 err |= setvarsafe("OPTARG", s, 0);
9839 fprintf(stderr, "No arg for -%c option\n", c);
9848 err |= setvarsafe("OPTARG", p, 0);
9851 err |= setvarsafe("OPTARG", nullstr, 0);
9853 *optoff = p ? p - *(optnext - 1) : -1;
9854 *param_optind = optnext - optfirst + 1;
9855 fmtstr(s, sizeof(s), "%d", *param_optind);
9856 err |= setvarsafe("OPTIND", s, VNOFUNC);
9859 err |= setvarsafe(optvar, s, 0);
9863 flush_stdout_stderr();
9864 raise_exception(EXERROR);
9870 * The getopts builtin. Shellparam.optnext points to the next argument
9871 * to be processed. Shellparam.optptr points to the next character to
9872 * be processed in the current argument. If shellparam.optnext is NULL,
9873 * then it's the first time getopts has been called.
9876 getoptscmd(int argc, char **argv)
9881 ash_msg_and_raise_error("usage: getopts optstring var [arg]");
9883 optbase = shellparam.p;
9884 if (shellparam.optind > shellparam.nparam + 1) {
9885 shellparam.optind = 1;
9886 shellparam.optoff = -1;
9890 if (shellparam.optind > argc - 2) {
9891 shellparam.optind = 1;
9892 shellparam.optoff = -1;
9896 return getopts(argv[1], argv[2], optbase, &shellparam.optind,
9897 &shellparam.optoff);
9899 #endif /* ASH_GETOPTS */
9902 /* ============ Shell parser */
9905 struct heredoc *next; /* next here document in list */
9906 union node *here; /* redirection node */
9907 char *eofmark; /* string indicating end of input */
9908 smallint striptabs; /* if set, strip leading tabs */
9911 static smallint tokpushback; /* last token pushed back */
9912 static smallint parsebackquote; /* nonzero if we are inside backquotes */
9913 static smallint quoteflag; /* set if (part of) last token was quoted */
9914 static token_id_t lasttoken; /* last token read (integer id Txxx) */
9915 static struct heredoc *heredoclist; /* list of here documents to read */
9916 static char *wordtext; /* text of last word returned by readtoken */
9917 static struct nodelist *backquotelist;
9918 static union node *redirnode;
9919 static struct heredoc *heredoc;
9921 * NEOF is returned by parsecmd when it encounters an end of file. It
9922 * must be distinct from NULL, so we use the address of a variable that
9923 * happens to be handy.
9925 #define NEOF ((union node *)&tokpushback)
9927 static void raise_error_syntax(const char *) NORETURN;
9929 raise_error_syntax(const char *msg)
9931 ash_msg_and_raise_error("syntax error: %s", msg);
9936 * Called when an unexpected token is read during the parse. The argument
9937 * is the token that is expected, or -1 if more than one type of token can
9938 * occur at this point.
9940 static void raise_error_unexpected_syntax(int) NORETURN;
9942 raise_error_unexpected_syntax(int token)
9947 l = sprintf(msg, "%s unexpected", tokname(lasttoken));
9949 sprintf(msg + l, " (expecting %s)", tokname(token));
9950 raise_error_syntax(msg);
9954 #define EOFMARKLEN 79
9956 /* parsing is heavily cross-recursive, need these forward decls */
9957 static union node *andor(void);
9958 static union node *pipeline(void);
9959 static union node *parse_command(void);
9960 static void parseheredoc(void);
9961 static char peektoken(void);
9962 static int readtoken(void);
9967 union node *n1, *n2, *n3;
9970 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9971 if (nlflag == 2 && peektoken())
9977 if (tok == TBACKGND) {
9978 if (n2->type == NPIPE) {
9979 n2->npipe.pipe_backgnd = 1;
9981 if (n2->type != NREDIR) {
9982 n3 = stzalloc(sizeof(struct nredir));
9984 /*n3->nredir.redirect = NULL; - stzalloc did it */
9987 n2->type = NBACKGND;
9993 n3 = stzalloc(sizeof(struct nbinary));
9995 n3->nbinary.ch1 = n1;
9996 n3->nbinary.ch2 = n2;
10012 checkkwd = CHKNL | CHKKWD | CHKALIAS;
10020 pungetc(); /* push back EOF on input */
10024 raise_error_unexpected_syntax(-1);
10031 static union node *
10034 union node *n1, *n2, *n3;
10042 } else if (t == TOR) {
10048 checkkwd = CHKNL | CHKKWD | CHKALIAS;
10050 n3 = stzalloc(sizeof(struct nbinary));
10052 n3->nbinary.ch1 = n1;
10053 n3->nbinary.ch2 = n2;
10058 static union node *
10061 union node *n1, *n2, *pipenode;
10062 struct nodelist *lp, *prev;
10066 TRACE(("pipeline: entered\n"));
10067 if (readtoken() == TNOT) {
10069 checkkwd = CHKKWD | CHKALIAS;
10072 n1 = parse_command();
10073 if (readtoken() == TPIPE) {
10074 pipenode = stzalloc(sizeof(struct npipe));
10075 pipenode->type = NPIPE;
10076 /*pipenode->npipe.pipe_backgnd = 0; - stzalloc did it */
10077 lp = stzalloc(sizeof(struct nodelist));
10078 pipenode->npipe.cmdlist = lp;
10082 lp = stzalloc(sizeof(struct nodelist));
10083 checkkwd = CHKNL | CHKKWD | CHKALIAS;
10084 lp->n = parse_command();
10086 } while (readtoken() == TPIPE);
10092 n2 = stzalloc(sizeof(struct nnot));
10100 static union node *
10105 n = stzalloc(sizeof(struct narg));
10107 /*n->narg.next = NULL; - stzalloc did it */
10108 n->narg.text = wordtext;
10109 n->narg.backquote = backquotelist;
10114 fixredir(union node *n, const char *text, int err)
10118 TRACE(("Fix redir %s %d\n", text, err));
10120 n->ndup.vname = NULL;
10122 fd = bb_strtou(text, NULL, 10);
10123 if (!errno && fd >= 0)
10124 n->ndup.dupfd = fd;
10125 else if (LONE_DASH(text))
10126 n->ndup.dupfd = -1;
10129 raise_error_syntax("Bad fd number");
10130 n->ndup.vname = makename();
10135 * Returns true if the text contains nothing to expand (no dollar signs
10139 noexpand(char *text)
10145 while ((c = *p++) != '\0') {
10146 if (c == CTLQUOTEMARK)
10150 else if (SIT(c, BASESYNTAX) == CCTL)
10159 union node *n = redirnode;
10161 if (readtoken() != TWORD)
10162 raise_error_unexpected_syntax(-1);
10163 if (n->type == NHERE) {
10164 struct heredoc *here = heredoc;
10168 if (quoteflag == 0)
10170 TRACE(("Here document %d\n", n->type));
10171 if (!noexpand(wordtext) || (i = strlen(wordtext)) == 0 || i > EOFMARKLEN)
10172 raise_error_syntax("Illegal eof marker for << redirection");
10173 rmescapes(wordtext);
10174 here->eofmark = wordtext;
10176 if (heredoclist == NULL)
10177 heredoclist = here;
10179 for (p = heredoclist; p->next; p = p->next)
10183 } else if (n->type == NTOFD || n->type == NFROMFD) {
10184 fixredir(n, wordtext, 0);
10186 n->nfile.fname = makename();
10190 static union node *
10193 union node *args, **app;
10194 union node *n = NULL;
10195 union node *vars, **vpp;
10196 union node **rpp, *redir;
10198 #if ENABLE_ASH_BASH_COMPAT
10199 smallint double_brackets_flag = 0;
10209 savecheckkwd = CHKALIAS;
10212 checkkwd = savecheckkwd;
10215 #if ENABLE_ASH_BASH_COMPAT
10216 case TAND: /* "&&" */
10217 case TOR: /* "||" */
10218 if (!double_brackets_flag) {
10222 wordtext = (char *) (t == TAND ? "-a" : "-o");
10225 n = stzalloc(sizeof(struct narg));
10227 /*n->narg.next = NULL; - stzalloc did it */
10228 n->narg.text = wordtext;
10229 #if ENABLE_ASH_BASH_COMPAT
10230 if (strcmp("[[", wordtext) == 0)
10231 double_brackets_flag = 1;
10232 else if (strcmp("]]", wordtext) == 0)
10233 double_brackets_flag = 0;
10235 n->narg.backquote = backquotelist;
10236 if (savecheckkwd && isassignment(wordtext)) {
10238 vpp = &n->narg.next;
10241 app = &n->narg.next;
10246 *rpp = n = redirnode;
10247 rpp = &n->nfile.next;
10248 parsefname(); /* read name of redirection file */
10251 if (args && app == &args->narg.next
10254 struct builtincmd *bcmd;
10257 /* We have a function */
10258 if (readtoken() != TRP)
10259 raise_error_unexpected_syntax(TRP);
10260 name = n->narg.text;
10261 if (!goodname(name)
10262 || ((bcmd = find_builtin(name)) && IS_BUILTIN_SPECIAL(bcmd))
10264 raise_error_syntax("Bad function name");
10267 checkkwd = CHKNL | CHKKWD | CHKALIAS;
10268 n->narg.next = parse_command();
10281 n = stzalloc(sizeof(struct ncmd));
10283 n->ncmd.args = args;
10284 n->ncmd.assign = vars;
10285 n->ncmd.redirect = redir;
10289 static union node *
10290 parse_command(void)
10292 union node *n1, *n2;
10293 union node *ap, **app;
10294 union node *cp, **cpp;
10295 union node *redir, **rpp;
10302 switch (readtoken()) {
10304 raise_error_unexpected_syntax(-1);
10307 n1 = stzalloc(sizeof(struct nif));
10309 n1->nif.test = list(0);
10310 if (readtoken() != TTHEN)
10311 raise_error_unexpected_syntax(TTHEN);
10312 n1->nif.ifpart = list(0);
10314 while (readtoken() == TELIF) {
10315 n2->nif.elsepart = stzalloc(sizeof(struct nif));
10316 n2 = n2->nif.elsepart;
10318 n2->nif.test = list(0);
10319 if (readtoken() != TTHEN)
10320 raise_error_unexpected_syntax(TTHEN);
10321 n2->nif.ifpart = list(0);
10323 if (lasttoken == TELSE)
10324 n2->nif.elsepart = list(0);
10326 n2->nif.elsepart = NULL;
10334 n1 = stzalloc(sizeof(struct nbinary));
10335 n1->type = (lasttoken == TWHILE) ? NWHILE : NUNTIL;
10336 n1->nbinary.ch1 = list(0);
10339 TRACE(("expecting DO got %s %s\n", tokname(got),
10340 got == TWORD ? wordtext : ""));
10341 raise_error_unexpected_syntax(TDO);
10343 n1->nbinary.ch2 = list(0);
10348 if (readtoken() != TWORD || quoteflag || !goodname(wordtext))
10349 raise_error_syntax("Bad for loop variable");
10350 n1 = stzalloc(sizeof(struct nfor));
10352 n1->nfor.var = wordtext;
10353 checkkwd = CHKKWD | CHKALIAS;
10354 if (readtoken() == TIN) {
10356 while (readtoken() == TWORD) {
10357 n2 = stzalloc(sizeof(struct narg));
10359 /*n2->narg.next = NULL; - stzalloc did it */
10360 n2->narg.text = wordtext;
10361 n2->narg.backquote = backquotelist;
10363 app = &n2->narg.next;
10366 n1->nfor.args = ap;
10367 if (lasttoken != TNL && lasttoken != TSEMI)
10368 raise_error_unexpected_syntax(-1);
10370 n2 = stzalloc(sizeof(struct narg));
10372 /*n2->narg.next = NULL; - stzalloc did it */
10373 n2->narg.text = (char *)dolatstr;
10374 /*n2->narg.backquote = NULL;*/
10375 n1->nfor.args = n2;
10377 * Newline or semicolon here is optional (but note
10378 * that the original Bourne shell only allowed NL).
10380 if (lasttoken != TNL && lasttoken != TSEMI)
10383 checkkwd = CHKNL | CHKKWD | CHKALIAS;
10384 if (readtoken() != TDO)
10385 raise_error_unexpected_syntax(TDO);
10386 n1->nfor.body = list(0);
10390 n1 = stzalloc(sizeof(struct ncase));
10392 if (readtoken() != TWORD)
10393 raise_error_unexpected_syntax(TWORD);
10394 n1->ncase.expr = n2 = stzalloc(sizeof(struct narg));
10396 /*n2->narg.next = NULL; - stzalloc did it */
10397 n2->narg.text = wordtext;
10398 n2->narg.backquote = backquotelist;
10400 checkkwd = CHKKWD | CHKALIAS;
10401 } while (readtoken() == TNL);
10402 if (lasttoken != TIN)
10403 raise_error_unexpected_syntax(TIN);
10404 cpp = &n1->ncase.cases;
10406 checkkwd = CHKNL | CHKKWD;
10408 while (t != TESAC) {
10409 if (lasttoken == TLP)
10411 *cpp = cp = stzalloc(sizeof(struct nclist));
10413 app = &cp->nclist.pattern;
10415 *app = ap = stzalloc(sizeof(struct narg));
10417 /*ap->narg.next = NULL; - stzalloc did it */
10418 ap->narg.text = wordtext;
10419 ap->narg.backquote = backquotelist;
10420 if (readtoken() != TPIPE)
10422 app = &ap->narg.next;
10425 //ap->narg.next = NULL;
10426 if (lasttoken != TRP)
10427 raise_error_unexpected_syntax(TRP);
10428 cp->nclist.body = list(2);
10430 cpp = &cp->nclist.next;
10432 checkkwd = CHKNL | CHKKWD;
10436 raise_error_unexpected_syntax(TENDCASE);
10443 n1 = stzalloc(sizeof(struct nredir));
10444 n1->type = NSUBSHELL;
10445 n1->nredir.n = list(0);
10446 /*n1->nredir.redirect = NULL; - stzalloc did it */
10456 return simplecmd();
10459 if (readtoken() != t)
10460 raise_error_unexpected_syntax(t);
10463 /* Now check for redirection which may follow command */
10464 checkkwd = CHKKWD | CHKALIAS;
10466 while (readtoken() == TREDIR) {
10467 *rpp = n2 = redirnode;
10468 rpp = &n2->nfile.next;
10474 if (n1->type != NSUBSHELL) {
10475 n2 = stzalloc(sizeof(struct nredir));
10480 n1->nredir.redirect = redir;
10485 #if ENABLE_ASH_BASH_COMPAT
10486 static int decode_dollar_squote(void)
10488 static const char C_escapes[] ALIGN1 = "nrbtfav""x\\01234567";
10494 p = strchr(C_escapes, c);
10499 if ((unsigned char)(c - '0') <= 7) { /* \ooo */
10503 } while ((unsigned char)(c - '0') <= 7 && --cnt);
10505 } else if (c == 'x') { /* \xHH */
10509 } while (isxdigit(c) && --cnt);
10511 if (cnt == 3) { /* \x but next char is "bad" */
10515 } else { /* simple seq like \\ or \t */
10520 c = bb_process_escape_sequence((void*)&p);
10521 } else { /* unrecognized "\z": print both chars unless ' or " */
10522 if (c != '\'' && c != '"') {
10524 c |= 0x100; /* "please encode \, then me" */
10532 * If eofmark is NULL, read a word or a redirection symbol. If eofmark
10533 * is not NULL, read a here document. In the latter case, eofmark is the
10534 * word which marks the end of the document and striptabs is true if
10535 * leading tabs should be stripped from the document. The argument firstc
10536 * is the first character of the input token or document.
10538 * Because C does not have internal subroutines, I have simulated them
10539 * using goto's to implement the subroutine linkage. The following macros
10540 * will run code that appears at the end of readtoken1.
10542 #define CHECKEND() {goto checkend; checkend_return:;}
10543 #define PARSEREDIR() {goto parseredir; parseredir_return:;}
10544 #define PARSESUB() {goto parsesub; parsesub_return:;}
10545 #define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
10546 #define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
10547 #define PARSEARITH() {goto parsearith; parsearith_return:;}
10549 readtoken1(int firstc, int syntax, char *eofmark, int striptabs)
10551 /* NB: syntax parameter fits into smallint */
10555 char line[EOFMARKLEN + 1];
10556 struct nodelist *bqlist;
10560 smallint prevsyntax; /* syntax before arithmetic */
10561 #if ENABLE_ASH_EXPAND_PRMT
10562 smallint pssyntax; /* we are expanding a prompt string */
10564 int varnest; /* levels of variables expansion */
10565 int arinest; /* levels of arithmetic expansion */
10566 int parenlevel; /* levels of parens in arithmetic */
10567 int dqvarnest; /* levels of variables expansion within double quotes */
10569 USE_ASH_BASH_COMPAT(smallint bash_dollar_squote = 0;)
10572 /* Avoid longjmp clobbering */
10578 (void) &parenlevel;
10581 (void) &prevsyntax;
10584 startlinno = plinno;
10589 #if ENABLE_ASH_EXPAND_PRMT
10590 pssyntax = (syntax == PSSYNTAX);
10594 dblquote = (syntax == DQSYNTAX);
10600 STARTSTACKSTR(out);
10601 loop: { /* for each line, until end of word */
10602 CHECKEND(); /* set c to PEOF if at end of here document */
10603 for (;;) { /* until end of line or end of word */
10604 CHECKSTRSPACE(4, out); /* permit 4 calls to USTPUTC */
10605 switch (SIT(c, syntax)) {
10606 case CNL: /* '\n' */
10607 if (syntax == BASESYNTAX)
10608 goto endword; /* exit outer loop */
10614 goto loop; /* continue outer loop */
10619 if (eofmark == NULL || dblquote)
10620 USTPUTC(CTLESC, out);
10621 #if ENABLE_ASH_BASH_COMPAT
10622 if (c == '\\' && bash_dollar_squote) {
10623 c = decode_dollar_squote();
10625 USTPUTC('\\', out);
10626 c = (unsigned char)c;
10632 case CBACK: /* backslash */
10635 USTPUTC(CTLESC, out);
10636 USTPUTC('\\', out);
10638 } else if (c == '\n') {
10642 #if ENABLE_ASH_EXPAND_PRMT
10643 if (c == '$' && pssyntax) {
10644 USTPUTC(CTLESC, out);
10645 USTPUTC('\\', out);
10648 if (dblquote && c != '\\'
10649 && c != '`' && c != '$'
10650 && (c != '"' || eofmark != NULL)
10652 USTPUTC(CTLESC, out);
10653 USTPUTC('\\', out);
10655 if (SIT(c, SQSYNTAX) == CCTL)
10656 USTPUTC(CTLESC, out);
10664 if (eofmark == NULL) {
10665 USTPUTC(CTLQUOTEMARK, out);
10673 USE_ASH_BASH_COMPAT(bash_dollar_squote = 0;)
10674 if (eofmark != NULL && arinest == 0
10679 if (dqvarnest == 0) {
10680 syntax = BASESYNTAX;
10687 case CVAR: /* '$' */
10688 PARSESUB(); /* parse substitution */
10690 case CENDVAR: /* '}' */
10693 if (dqvarnest > 0) {
10696 USTPUTC(CTLENDVAR, out);
10701 #if ENABLE_ASH_MATH_SUPPORT
10702 case CLP: /* '(' in arithmetic */
10706 case CRP: /* ')' in arithmetic */
10707 if (parenlevel > 0) {
10711 if (pgetc() == ')') {
10712 if (--arinest == 0) {
10713 USTPUTC(CTLENDARI, out);
10714 syntax = prevsyntax;
10715 dblquote = (syntax == DQSYNTAX);
10720 * unbalanced parens
10721 * (don't 2nd guess - no error)
10729 case CBQUOTE: /* '`' */
10733 goto endword; /* exit outer loop */
10738 goto endword; /* exit outer loop */
10739 #if ENABLE_ASH_ALIAS
10749 #if ENABLE_ASH_MATH_SUPPORT
10750 if (syntax == ARISYNTAX)
10751 raise_error_syntax("Missing '))'");
10753 if (syntax != BASESYNTAX && !parsebackquote && eofmark == NULL)
10754 raise_error_syntax("Unterminated quoted string");
10755 if (varnest != 0) {
10756 startlinno = plinno;
10758 raise_error_syntax("Missing '}'");
10760 USTPUTC('\0', out);
10761 len = out - (char *)stackblock();
10762 out = stackblock();
10763 if (eofmark == NULL) {
10764 if ((c == '>' || c == '<') && quotef == 0) {
10765 int maxlen = 9 + 1; /* max 9 digit fd#: 999999999 */
10767 while (--maxlen && isdigit(*np))
10770 PARSEREDIR(); /* passed as params: out, c */
10771 lasttoken = TREDIR;
10774 /* else: non-number X seen, interpret it
10775 * as "NNNX>file" = "NNNX >file" */
10779 quoteflag = quotef;
10780 backquotelist = bqlist;
10781 grabstackblock(len);
10785 /* end of readtoken routine */
10788 * Check to see whether we are at the end of the here document. When this
10789 * is called, c is set to the first character of the next input line. If
10790 * we are at the end of the here document, this routine sets the c to PEOF.
10794 #if ENABLE_ASH_ALIAS
10800 while (c == '\t') {
10804 if (c == *eofmark) {
10805 if (pfgets(line, sizeof(line)) != NULL) {
10809 for (q = eofmark + 1; *q && *p == *q; p++, q++)
10811 if (*p == '\n' && *q == '\0') {
10814 needprompt = doprompt;
10816 pushstring(line, NULL);
10821 goto checkend_return;
10825 * Parse a redirection operator. The variable "out" points to a string
10826 * specifying the fd to be redirected. The variable "c" contains the
10827 * first character of the redirection operator.
10830 /* out is already checked to be a valid number or "" */
10831 int fd = (*out == '\0' ? -1 : atoi(out));
10834 np = stzalloc(sizeof(struct nfile));
10839 np->type = NAPPEND;
10841 np->type = NCLOBBER;
10848 } else { /* c == '<' */
10849 /*np->nfile.fd = 0; - stzalloc did it */
10853 if (sizeof(struct nfile) != sizeof(struct nhere)) {
10854 np = stzalloc(sizeof(struct nhere));
10855 /*np->nfile.fd = 0; - stzalloc did it */
10858 heredoc = stzalloc(sizeof(struct heredoc));
10859 heredoc->here = np;
10862 heredoc->striptabs = 1;
10864 /*heredoc->striptabs = 0; - stzalloc did it */
10870 np->type = NFROMFD;
10874 np->type = NFROMTO;
10886 goto parseredir_return;
10890 * Parse a substitution. At this point, we have read the dollar sign
10891 * and nothing else.
10894 /* is_special(c) evaluates to 1 for c in "!#$*-0123456789?@"; 0 otherwise
10895 * (assuming ascii char codes, as the original implementation did) */
10896 #define is_special(c) \
10897 (((unsigned)(c) - 33 < 32) \
10898 && ((0xc1ff920dU >> ((unsigned)(c) - 33)) & 1))
10904 static const char types[] ALIGN1 = "}-+?=";
10907 if (c <= PEOA_OR_PEOF
10908 || (c != '(' && c != '{' && !is_name(c) && !is_special(c))
10910 #if ENABLE_ASH_BASH_COMPAT
10912 bash_dollar_squote = 1;
10917 } else if (c == '(') { /* $(command) or $((arith)) */
10918 if (pgetc() == '(') {
10919 #if ENABLE_ASH_MATH_SUPPORT
10922 raise_error_syntax("you disabled math support for $((arith)) syntax");
10929 USTPUTC(CTLVAR, out);
10930 typeloc = out - (char *)stackblock();
10931 USTPUTC(VSNORMAL, out);
10932 subtype = VSNORMAL;
10940 subtype = VSLENGTH;
10944 if (c > PEOA_OR_PEOF && is_name(c)) {
10948 } while (c > PEOA_OR_PEOF && is_in_name(c));
10949 } else if (isdigit(c)) {
10953 } while (isdigit(c));
10954 } else if (is_special(c)) {
10958 badsub: raise_error_syntax("Bad substitution");
10962 if (subtype == 0) {
10966 #if ENABLE_ASH_BASH_COMPAT
10967 if (c == ':' || c == '$' || isdigit(c)) {
10969 subtype = VSSUBSTR;
10976 p = strchr(types, c);
10979 subtype = p - types + VSNORMAL;
10984 subtype = c == '#' ? VSTRIMLEFT : VSTRIMRIGHT;
10992 #if ENABLE_ASH_BASH_COMPAT
10994 subtype = VSREPLACE;
10997 subtype++; /* VSREPLACEALL */
11006 if (dblquote || arinest)
11008 *((char *)stackblock() + typeloc) = subtype | flags;
11009 if (subtype != VSNORMAL) {
11011 if (dblquote || arinest) {
11016 goto parsesub_return;
11020 * Called to parse command substitutions. Newstyle is set if the command
11021 * is enclosed inside $(...); nlpp is a pointer to the head of the linked
11022 * list of commands (passed by reference), and savelen is the number of
11023 * characters on the top of the stack which must be preserved.
11026 struct nodelist **nlpp;
11029 char *volatile str;
11030 struct jmploc jmploc;
11031 struct jmploc *volatile savehandler;
11033 smallint saveprompt = 0;
11036 (void) &saveprompt;
11038 savepbq = parsebackquote;
11039 if (setjmp(jmploc.loc)) {
11041 parsebackquote = 0;
11042 exception_handler = savehandler;
11043 longjmp(exception_handler->loc, 1);
11047 savelen = out - (char *)stackblock();
11049 str = ckmalloc(savelen);
11050 memcpy(str, stackblock(), savelen);
11052 savehandler = exception_handler;
11053 exception_handler = &jmploc;
11056 /* We must read until the closing backquote, giving special
11057 treatment to some slashes, and then push the string and
11058 reread it as input, interpreting it normally. */
11065 STARTSTACKSTR(pout);
11082 * If eating a newline, avoid putting
11083 * the newline into the new character
11084 * stream (via the STPUTC after the
11089 if (pc != '\\' && pc != '`' && pc != '$'
11090 && (!dblquote || pc != '"'))
11091 STPUTC('\\', pout);
11092 if (pc > PEOA_OR_PEOF) {
11098 #if ENABLE_ASH_ALIAS
11101 startlinno = plinno;
11102 raise_error_syntax("EOF in backquote substitution");
11106 needprompt = doprompt;
11115 STPUTC('\0', pout);
11116 psavelen = pout - (char *)stackblock();
11117 if (psavelen > 0) {
11118 pstr = grabstackstr(pout);
11119 setinputstring(pstr);
11124 nlpp = &(*nlpp)->next;
11125 *nlpp = stzalloc(sizeof(**nlpp));
11126 /* (*nlpp)->next = NULL; - stzalloc did it */
11127 parsebackquote = oldstyle;
11130 saveprompt = doprompt;
11137 doprompt = saveprompt;
11138 else if (readtoken() != TRP)
11139 raise_error_unexpected_syntax(TRP);
11144 * Start reading from old file again, ignoring any pushed back
11145 * tokens left from the backquote parsing
11150 while (stackblocksize() <= savelen)
11152 STARTSTACKSTR(out);
11154 memcpy(out, str, savelen);
11155 STADJUST(savelen, out);
11161 parsebackquote = savepbq;
11162 exception_handler = savehandler;
11163 if (arinest || dblquote)
11164 USTPUTC(CTLBACKQ | CTLQUOTE, out);
11166 USTPUTC(CTLBACKQ, out);
11168 goto parsebackq_oldreturn;
11169 goto parsebackq_newreturn;
11172 #if ENABLE_ASH_MATH_SUPPORT
11174 * Parse an arithmetic expansion (indicate start of one and set state)
11177 if (++arinest == 1) {
11178 prevsyntax = syntax;
11179 syntax = ARISYNTAX;
11180 USTPUTC(CTLARI, out);
11187 * we collapse embedded arithmetic expansion to
11188 * parenthesis, which should be equivalent
11192 goto parsearith_return;
11196 } /* end of readtoken */
11199 * Read the next input token.
11200 * If the token is a word, we set backquotelist to the list of cmds in
11201 * backquotes. We set quoteflag to true if any part of the word was
11203 * If the token is TREDIR, then we set redirnode to a structure containing
11205 * In all cases, the variable startlinno is set to the number of the line
11206 * on which the token starts.
11208 * [Change comment: here documents and internal procedures]
11209 * [Readtoken shouldn't have any arguments. Perhaps we should make the
11210 * word parsing code into a separate routine. In this case, readtoken
11211 * doesn't need to have any internal procedures, but parseword does.
11212 * We could also make parseoperator in essence the main routine, and
11213 * have parseword (readtoken1?) handle both words and redirection.]
11215 #define NEW_xxreadtoken
11216 #ifdef NEW_xxreadtoken
11217 /* singles must be first! */
11218 static const char xxreadtoken_chars[7] ALIGN1 = {
11219 '\n', '(', ')', '&', '|', ';', 0
11222 static const char xxreadtoken_tokens[] ALIGN1 = {
11223 TNL, TLP, TRP, /* only single occurrence allowed */
11224 TBACKGND, TPIPE, TSEMI, /* if single occurrence */
11225 TEOF, /* corresponds to trailing nul */
11226 TAND, TOR, TENDCASE /* if double occurrence */
11229 #define xxreadtoken_doubles \
11230 (sizeof(xxreadtoken_tokens) - sizeof(xxreadtoken_chars))
11231 #define xxreadtoken_singles \
11232 (sizeof(xxreadtoken_chars) - xxreadtoken_doubles - 1)
11246 startlinno = plinno;
11247 for (;;) { /* until token or start of word found */
11250 if ((c != ' ') && (c != '\t')
11251 #if ENABLE_ASH_ALIAS
11256 while ((c = pgetc()) != '\n' && c != PEOF)
11259 } else if (c == '\\') {
11260 if (pgetc() != '\n') {
11264 startlinno = ++plinno;
11269 = xxreadtoken_chars + sizeof(xxreadtoken_chars) - 1;
11274 needprompt = doprompt;
11277 p = strchr(xxreadtoken_chars, c);
11280 return readtoken1(c, BASESYNTAX, (char *) NULL, 0);
11283 if ((size_t)(p - xxreadtoken_chars) >= xxreadtoken_singles) {
11284 if (pgetc() == *p) { /* double occurrence? */
11285 p += xxreadtoken_doubles + 1;
11291 lasttoken = xxreadtoken_tokens[p - xxreadtoken_chars];
11298 #define RETURN(token) return lasttoken = token
11311 startlinno = plinno;
11312 for (;;) { /* until token or start of word found */
11315 case ' ': case '\t':
11316 #if ENABLE_ASH_ALIAS
11321 while ((c = pgetc()) != '\n' && c != PEOF)
11326 if (pgetc() == '\n') {
11327 startlinno = ++plinno;
11336 needprompt = doprompt;
11341 if (pgetc() == '&')
11346 if (pgetc() == '|')
11351 if (pgetc() == ';')
11364 return readtoken1(c, BASESYNTAX, (char *)NULL, 0);
11367 #endif /* NEW_xxreadtoken */
11374 smallint alreadyseen = tokpushback;
11377 #if ENABLE_ASH_ALIAS
11386 if (checkkwd & CHKNL) {
11393 if (t != TWORD || quoteflag) {
11398 * check for keywords
11400 if (checkkwd & CHKKWD) {
11401 const char *const *pp;
11403 pp = findkwd(wordtext);
11405 lasttoken = t = pp - tokname_array;
11406 TRACE(("keyword %s recognized\n", tokname(t)));
11411 if (checkkwd & CHKALIAS) {
11412 #if ENABLE_ASH_ALIAS
11414 ap = lookupalias(wordtext, 1);
11417 pushstring(ap->val, ap);
11427 TRACE(("token %s %s\n", tokname(t), t == TWORD ? wordtext : ""));
11429 TRACE(("reread token %s %s\n", tokname(t), t == TWORD ? wordtext : ""));
11441 return tokname_array[t][0];
11445 * Read and parse a command. Returns NEOF on end of file. (NULL is a
11446 * valid parse tree indicating a blank line.)
11448 static union node *
11449 parsecmd(int interact)
11454 doprompt = interact;
11456 setprompt(doprompt);
11468 * Input any here documents.
11473 struct heredoc *here;
11476 here = heredoclist;
11477 heredoclist = NULL;
11483 readtoken1(pgetc(), here->here->type == NHERE? SQSYNTAX : DQSYNTAX,
11484 here->eofmark, here->striptabs);
11485 n = stzalloc(sizeof(struct narg));
11486 n->narg.type = NARG;
11487 /*n->narg.next = NULL; - stzalloc did it */
11488 n->narg.text = wordtext;
11489 n->narg.backquote = backquotelist;
11490 here->here->nhere.doc = n;
11497 * called by editline -- any expansions to the prompt should be added here.
11499 #if ENABLE_ASH_EXPAND_PRMT
11500 static const char *
11501 expandstr(const char *ps)
11505 /* XXX Fix (char *) cast. */
11506 setinputstring((char *)ps);
11507 readtoken1(pgetc(), PSSYNTAX, nullstr, 0);
11510 n.narg.type = NARG;
11511 n.narg.next = NULL;
11512 n.narg.text = wordtext;
11513 n.narg.backquote = backquotelist;
11515 expandarg(&n, NULL, 0);
11516 return stackblock();
11521 * Execute a command or commands contained in a string.
11524 evalstring(char *s, int mask)
11527 struct stackmark smark;
11531 setstackmark(&smark);
11534 while ((n = parsecmd(0)) != NEOF) {
11536 popstackmark(&smark);
11549 * The eval command.
11552 evalcmd(int argc UNUSED_PARAM, char **argv)
11561 STARTSTACKSTR(concat);
11563 concat = stack_putstr(p, concat);
11567 STPUTC(' ', concat);
11569 STPUTC('\0', concat);
11570 p = grabstackstr(concat);
11572 evalstring(p, ~SKIPEVAL);
11579 * Read and execute commands. "Top" is nonzero for the top level command
11580 * loop; it turns on prompting if the shell is interactive.
11586 struct stackmark smark;
11590 TRACE(("cmdloop(%d) called\n", top));
11594 setstackmark(&smark);
11597 showjobs(stderr, SHOW_CHANGED);
11600 if (iflag && top) {
11602 #if ENABLE_ASH_MAIL
11606 n = parsecmd(inter);
11607 /* showtree(n); DEBUG */
11609 if (!top || numeof >= 50)
11611 if (!stoppedjobs()) {
11614 out2str("\nUse \"exit\" to leave shell.\n");
11617 } else if (nflag == 0) {
11618 /* job_warning can only be 2,1,0. Here 2->1, 1/0->0 */
11623 popstackmark(&smark);
11628 return skip & SKIPEVAL;
11635 * Take commands from a file. To be compatible we should do a path
11636 * search for the file, which is necessary to find sub-commands.
11639 find_dot_file(char *name)
11642 const char *path = pathval();
11645 /* don't try this for absolute or relative paths */
11646 if (strchr(name, '/'))
11649 while ((fullname = padvance(&path, name)) != NULL) {
11650 if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) {
11652 * Don't bother freeing here, since it will
11653 * be freed by the caller.
11657 stunalloc(fullname);
11660 /* not found in the PATH */
11661 ash_msg_and_raise_error("%s: not found", name);
11666 dotcmd(int argc, char **argv)
11668 struct strlist *sp;
11669 volatile struct shparam saveparam;
11672 for (sp = cmdenviron; sp; sp = sp->next)
11673 setvareq(ckstrdup(sp->text), VSTRFIXED | VTEXTFIXED);
11675 if (argv[1]) { /* That's what SVR2 does */
11676 char *fullname = find_dot_file(argv[1]);
11679 if (argc) { /* argc > 0, argv[0] != NULL */
11680 saveparam = shellparam;
11681 shellparam.malloced = 0;
11682 shellparam.nparam = argc;
11683 shellparam.p = argv;
11686 setinputfile(fullname, INPUT_PUSH_FILE);
11687 commandname = fullname;
11692 freeparam(&shellparam);
11693 shellparam = saveparam;
11695 status = exitstatus;
11701 exitcmd(int argc UNUSED_PARAM, char **argv)
11706 exitstatus = number(argv[1]);
11707 raise_exception(EXEXIT);
11712 * Read a file containing shell functions.
11715 readcmdfile(char *name)
11717 setinputfile(name, INPUT_PUSH_FILE);
11723 /* ============ find_command inplementation */
11726 * Resolve a command name. If you change this routine, you may have to
11727 * change the shellexec routine as well.
11730 find_command(char *name, struct cmdentry *entry, int act, const char *path)
11732 struct tblentry *cmdp;
11739 struct builtincmd *bcmd;
11741 /* If name contains a slash, don't use PATH or hash table */
11742 if (strchr(name, '/') != NULL) {
11743 entry->u.index = -1;
11744 if (act & DO_ABS) {
11745 while (stat(name, &statb) < 0) {
11747 if (errno == EINTR)
11750 entry->cmdtype = CMDUNKNOWN;
11754 entry->cmdtype = CMDNORMAL;
11758 /* #if ENABLE_FEATURE_SH_STANDALONE... moved after builtin check */
11760 updatetbl = (path == pathval());
11763 if (strstr(path, "%builtin") != NULL)
11764 act |= DO_ALTBLTIN;
11767 /* If name is in the table, check answer will be ok */
11768 cmdp = cmdlookup(name, 0);
11769 if (cmdp != NULL) {
11772 switch (cmdp->cmdtype) {
11790 } else if (cmdp->rehash == 0)
11791 /* if not invalidated by cd, we're done */
11795 /* If %builtin not in path, check for builtin next */
11796 bcmd = find_builtin(name);
11798 if (IS_BUILTIN_REGULAR(bcmd))
11799 goto builtin_success;
11800 if (act & DO_ALTPATH) {
11801 if (!(act & DO_ALTBLTIN))
11802 goto builtin_success;
11803 } else if (builtinloc <= 0) {
11804 goto builtin_success;
11808 #if ENABLE_FEATURE_SH_STANDALONE
11810 int applet_no = find_applet_by_name(name);
11811 if (applet_no >= 0) {
11812 entry->cmdtype = CMDNORMAL;
11813 entry->u.index = -2 - applet_no;
11819 /* We have to search path. */
11820 prev = -1; /* where to start */
11821 if (cmdp && cmdp->rehash) { /* doing a rehash */
11822 if (cmdp->cmdtype == CMDBUILTIN)
11825 prev = cmdp->param.index;
11831 while ((fullname = padvance(&path, name)) != NULL) {
11832 stunalloc(fullname);
11833 /* NB: code below will still use fullname
11834 * despite it being "unallocated" */
11837 if (prefix(pathopt, "builtin")) {
11839 goto builtin_success;
11842 if ((act & DO_NOFUNC)
11843 || !prefix(pathopt, "func")
11844 ) { /* ignore unimplemented options */
11848 /* if rehash, don't redo absolute path names */
11849 if (fullname[0] == '/' && idx <= prev) {
11852 TRACE(("searchexec \"%s\": no change\n", name));
11855 while (stat(fullname, &statb) < 0) {
11857 if (errno == EINTR)
11860 if (errno != ENOENT && errno != ENOTDIR)
11864 e = EACCES; /* if we fail, this will be the error */
11865 if (!S_ISREG(statb.st_mode))
11867 if (pathopt) { /* this is a %func directory */
11868 stalloc(strlen(fullname) + 1);
11869 /* NB: stalloc will return space pointed by fullname
11870 * (because we don't have any intervening allocations
11871 * between stunalloc above and this stalloc) */
11872 readcmdfile(fullname);
11873 cmdp = cmdlookup(name, 0);
11874 if (cmdp == NULL || cmdp->cmdtype != CMDFUNCTION)
11875 ash_msg_and_raise_error("%s not defined in %s", name, fullname);
11876 stunalloc(fullname);
11879 TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
11881 entry->cmdtype = CMDNORMAL;
11882 entry->u.index = idx;
11886 cmdp = cmdlookup(name, 1);
11887 cmdp->cmdtype = CMDNORMAL;
11888 cmdp->param.index = idx;
11893 /* We failed. If there was an entry for this command, delete it */
11894 if (cmdp && updatetbl)
11895 delete_cmd_entry();
11897 ash_msg("%s: %s", name, errmsg(e, "not found"));
11898 entry->cmdtype = CMDUNKNOWN;
11903 entry->cmdtype = CMDBUILTIN;
11904 entry->u.cmd = bcmd;
11908 cmdp = cmdlookup(name, 1);
11909 cmdp->cmdtype = CMDBUILTIN;
11910 cmdp->param.cmd = bcmd;
11914 entry->cmdtype = cmdp->cmdtype;
11915 entry->u = cmdp->param;
11919 /* ============ trap.c */
11922 * The trap builtin.
11925 trapcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
11934 for (signo = 0; signo < NSIG; signo++) {
11935 if (trap[signo] != NULL) {
11936 out1fmt("trap -- %s %s\n",
11937 single_quote(trap[signo]),
11938 get_signame(signo));
11947 signo = get_signum(*ap);
11949 ash_msg_and_raise_error("%s: bad trap", *ap);
11952 if (LONE_DASH(action))
11955 action = ckstrdup(action);
11958 trap[signo] = action;
11968 /* ============ Builtins */
11970 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
11972 * Lists available builtins
11975 helpcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
11980 out1fmt("\nBuilt-in commands:\n-------------------\n");
11981 for (col = 0, i = 0; i < ARRAY_SIZE(builtintab); i++) {
11982 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '),
11983 builtintab[i].name + 1);
11989 #if ENABLE_FEATURE_SH_STANDALONE
11991 const char *a = applet_names;
11993 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '), a);
11998 a += strlen(a) + 1;
12003 return EXIT_SUCCESS;
12005 #endif /* FEATURE_SH_EXTRA_QUIET */
12008 * The export and readonly commands.
12011 exportcmd(int argc UNUSED_PARAM, char **argv)
12017 int flag = argv[0][0] == 'r'? VREADONLY : VEXPORT;
12019 if (nextopt("p") != 'p') {
12024 p = strchr(name, '=');
12028 vp = *findvar(hashvar(name), name);
12034 setvar(name, p, flag);
12035 } while ((name = *++aptr) != NULL);
12039 showvars(argv[0], flag, 0);
12044 * Delete a function if it exists.
12047 unsetfunc(const char *name)
12049 struct tblentry *cmdp;
12051 cmdp = cmdlookup(name, 0);
12052 if (cmdp!= NULL && cmdp->cmdtype == CMDFUNCTION)
12053 delete_cmd_entry();
12057 * The unset builtin command. We unset the function before we unset the
12058 * variable to allow a function to be unset when there is a readonly variable
12059 * with the same name.
12062 unsetcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
12069 while ((i = nextopt("vf")) != '\0') {
12073 for (ap = argptr; *ap; ap++) {
12089 #include <sys/times.h>
12091 static const unsigned char timescmd_str[] ALIGN1 = {
12092 ' ', offsetof(struct tms, tms_utime),
12093 '\n', offsetof(struct tms, tms_stime),
12094 ' ', offsetof(struct tms, tms_cutime),
12095 '\n', offsetof(struct tms, tms_cstime),
12100 timescmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
12102 long clk_tck, s, t;
12103 const unsigned char *p;
12106 clk_tck = sysconf(_SC_CLK_TCK);
12111 t = *(clock_t *)(((char *) &buf) + p[1]);
12113 out1fmt("%ldm%ld.%.3lds%c",
12115 ((t - s * clk_tck) * 1000) / clk_tck,
12117 } while (*(p += 2));
12122 #if ENABLE_ASH_MATH_SUPPORT
12124 dash_arith(const char *s)
12130 result = arith(s, &errcode);
12133 ash_msg_and_raise_error("exponent less than 0");
12135 ash_msg_and_raise_error("divide by zero");
12137 ash_msg_and_raise_error("expression recursion loop detected");
12138 raise_error_syntax(s);
12146 * The let builtin. partial stolen from GNU Bash, the Bourne Again SHell.
12147 * Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
12149 * Copyright (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
12152 letcmd(int argc UNUSED_PARAM, char **argv)
12158 ash_msg_and_raise_error("expression expected");
12160 i = dash_arith(*argv);
12165 #endif /* ASH_MATH_SUPPORT */
12168 /* ============ miscbltin.c
12170 * Miscellaneous builtins.
12175 #if defined(__GLIBC__) && __GLIBC__ == 2 && __GLIBC_MINOR__ < 1
12176 typedef enum __rlimit_resource rlim_t;
12180 * The read builtin. Options:
12181 * -r Do not interpret '\' specially
12182 * -s Turn off echo (tty only)
12183 * -n NCHARS Read NCHARS max
12184 * -p PROMPT Display PROMPT on stderr (if input is from tty)
12185 * -t SECONDS Timeout after SECONDS (tty or pipe only)
12186 * -u FD Read from given FD instead of fd 0
12187 * This uses unbuffered input, which may be avoidable in some cases.
12188 * TODO: bash also has:
12189 * -a ARRAY Read into array[0],[1],etc
12190 * -d DELIM End on DELIM char, not newline
12191 * -e Use line editing (tty only)
12194 readcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
12196 static const char *const arg_REPLY[] = { "REPLY", NULL };
12209 #if ENABLE_ASH_READ_NCHARS
12210 int nchars = 0; /* if != 0, -n is in effect */
12212 struct termios tty, old_tty;
12214 #if ENABLE_ASH_READ_TIMEOUT
12215 unsigned end_ms = 0;
12216 unsigned timeout = 0;
12221 while ((i = nextopt("p:u:r"
12222 USE_ASH_READ_TIMEOUT("t:")
12223 USE_ASH_READ_NCHARS("n:s")
12227 prompt = optionarg;
12229 #if ENABLE_ASH_READ_NCHARS
12231 nchars = bb_strtou(optionarg, NULL, 10);
12232 if (nchars < 0 || errno)
12233 ash_msg_and_raise_error("invalid count");
12234 /* nchars == 0: off (bash 3.2 does this too) */
12240 #if ENABLE_ASH_READ_TIMEOUT
12242 timeout = bb_strtou(optionarg, NULL, 10);
12243 if (errno || timeout > UINT_MAX / 2048)
12244 ash_msg_and_raise_error("invalid timeout");
12246 #if 0 /* even bash have no -t N.NNN support */
12247 ts.tv_sec = bb_strtou(optionarg, &p, 10);
12249 /* EINVAL means number is ok, but not terminated by NUL */
12250 if (*p == '.' && errno == EINVAL) {
12254 ts.tv_usec = bb_strtou(p, &p2, 10);
12256 ash_msg_and_raise_error("invalid timeout");
12258 /* normalize to usec */
12260 ash_msg_and_raise_error("invalid timeout");
12261 while (scale++ < 6)
12264 } else if (ts.tv_sec < 0 || errno) {
12265 ash_msg_and_raise_error("invalid timeout");
12267 if (!(ts.tv_sec | ts.tv_usec)) { /* both are 0? */
12268 ash_msg_and_raise_error("invalid timeout");
12277 fd = bb_strtou(optionarg, NULL, 10);
12278 if (fd < 0 || errno)
12279 ash_msg_and_raise_error("invalid file descriptor");
12285 if (prompt && isatty(fd)) {
12290 ap = (char**)arg_REPLY;
12291 ifs = bltinlookup("IFS");
12294 #if ENABLE_ASH_READ_NCHARS
12295 tcgetattr(fd, &tty);
12297 if (nchars || silent) {
12299 tty.c_lflag &= ~ICANON;
12300 tty.c_cc[VMIN] = nchars < 256 ? nchars : 255;
12303 tty.c_lflag &= ~(ECHO | ECHOK | ECHONL);
12305 /* if tcgetattr failed, tcsetattr will fail too.
12306 * Ignoring, it's harmless. */
12307 tcsetattr(fd, TCSANOW, &tty);
12314 #if ENABLE_ASH_READ_TIMEOUT
12315 if (timeout) /* NB: ensuring end_ms is nonzero */
12316 end_ms = ((unsigned)(monotonic_us() / 1000) + timeout) | 1;
12320 #if ENABLE_ASH_READ_TIMEOUT
12322 struct pollfd pfd[1];
12324 pfd[0].events = POLLIN;
12325 timeout = end_ms - (unsigned)(monotonic_us() / 1000);
12326 if ((int)timeout <= 0 /* already late? */
12327 || safe_poll(pfd, 1, timeout) != 1 /* no? wait... */
12328 ) { /* timed out! */
12329 #if ENABLE_ASH_READ_NCHARS
12330 tcsetattr(fd, TCSANOW, &old_tty);
12336 if (nonblock_safe_read(fd, &c, 1) != 1) {
12348 if (!rflag && c == '\\') {
12354 if (startword && *ifs == ' ' && strchr(ifs, c)) {
12358 if (ap[1] != NULL && strchr(ifs, c) != NULL) {
12360 setvar(*ap, stackblock(), 0);
12369 /* end of do {} while: */
12370 #if ENABLE_ASH_READ_NCHARS
12376 #if ENABLE_ASH_READ_NCHARS
12377 tcsetattr(fd, TCSANOW, &old_tty);
12381 /* Remove trailing blanks */
12382 while ((char *)stackblock() <= --p && strchr(ifs, *p) != NULL)
12384 setvar(*ap, stackblock(), 0);
12385 while (*++ap != NULL)
12386 setvar(*ap, nullstr, 0);
12391 umaskcmd(int argc UNUSED_PARAM, char **argv)
12393 static const char permuser[3] ALIGN1 = "ugo";
12394 static const char permmode[3] ALIGN1 = "rwx";
12395 static const short permmask[] ALIGN2 = {
12396 S_IRUSR, S_IWUSR, S_IXUSR,
12397 S_IRGRP, S_IWGRP, S_IXGRP,
12398 S_IROTH, S_IWOTH, S_IXOTH
12404 int symbolic_mode = 0;
12406 while (nextopt("S") != '\0') {
12417 if (symbolic_mode) {
12421 for (i = 0; i < 3; i++) {
12424 *p++ = permuser[i];
12426 for (j = 0; j < 3; j++) {
12427 if ((mask & permmask[3 * i + j]) == 0) {
12428 *p++ = permmode[j];
12436 out1fmt("%.4o\n", mask);
12439 if (isdigit((unsigned char) *ap)) {
12442 if (*ap >= '8' || *ap < '0')
12443 ash_msg_and_raise_error(illnum, argv[1]);
12444 mask = (mask << 3) + (*ap - '0');
12445 } while (*++ap != '\0');
12448 mask = ~mask & 0777;
12449 if (!bb_parse_mode(ap, &mask)) {
12450 ash_msg_and_raise_error("illegal mode: %s", ap);
12452 umask(~mask & 0777);
12461 * This code, originally by Doug Gwyn, Doug Kingston, Eric Gisin, and
12462 * Michael Rendell was ripped from pdksh 5.0.8 and hacked for use with
12463 * ash by J.T. Conklin.
12469 uint8_t cmd; /* RLIMIT_xxx fit into it */
12470 uint8_t factor_shift; /* shift by to get rlim_{cur,max} values */
12474 static const struct limits limits_tbl[] = {
12476 { RLIMIT_CPU, 0, 't' },
12478 #ifdef RLIMIT_FSIZE
12479 { RLIMIT_FSIZE, 9, 'f' },
12482 { RLIMIT_DATA, 10, 'd' },
12484 #ifdef RLIMIT_STACK
12485 { RLIMIT_STACK, 10, 's' },
12488 { RLIMIT_CORE, 9, 'c' },
12491 { RLIMIT_RSS, 10, 'm' },
12493 #ifdef RLIMIT_MEMLOCK
12494 { RLIMIT_MEMLOCK, 10, 'l' },
12496 #ifdef RLIMIT_NPROC
12497 { RLIMIT_NPROC, 0, 'p' },
12499 #ifdef RLIMIT_NOFILE
12500 { RLIMIT_NOFILE, 0, 'n' },
12503 { RLIMIT_AS, 10, 'v' },
12505 #ifdef RLIMIT_LOCKS
12506 { RLIMIT_LOCKS, 0, 'w' },
12509 static const char limits_name[] =
12511 "time(seconds)" "\0"
12513 #ifdef RLIMIT_FSIZE
12514 "file(blocks)" "\0"
12519 #ifdef RLIMIT_STACK
12523 "coredump(blocks)" "\0"
12528 #ifdef RLIMIT_MEMLOCK
12529 "locked memory(kb)" "\0"
12531 #ifdef RLIMIT_NPROC
12534 #ifdef RLIMIT_NOFILE
12540 #ifdef RLIMIT_LOCKS
12545 enum limtype { SOFT = 0x1, HARD = 0x2 };
12548 printlim(enum limtype how, const struct rlimit *limit,
12549 const struct limits *l)
12553 val = limit->rlim_max;
12555 val = limit->rlim_cur;
12557 if (val == RLIM_INFINITY)
12558 out1fmt("unlimited\n");
12560 val >>= l->factor_shift;
12561 out1fmt("%lld\n", (long long) val);
12566 ulimitcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
12570 enum limtype how = SOFT | HARD;
12571 const struct limits *l;
12574 struct rlimit limit;
12577 while ((optc = nextopt("HSa"
12581 #ifdef RLIMIT_FSIZE
12587 #ifdef RLIMIT_STACK
12596 #ifdef RLIMIT_MEMLOCK
12599 #ifdef RLIMIT_NPROC
12602 #ifdef RLIMIT_NOFILE
12608 #ifdef RLIMIT_LOCKS
12626 for (l = limits_tbl; l->option != what; l++)
12629 set = *argptr ? 1 : 0;
12633 if (all || argptr[1])
12634 ash_msg_and_raise_error("too many arguments");
12635 if (strncmp(p, "unlimited\n", 9) == 0)
12636 val = RLIM_INFINITY;
12640 while ((c = *p++) >= '0' && c <= '9') {
12641 val = (val * 10) + (long)(c - '0');
12642 // val is actually 'unsigned long int' and can't get < 0
12643 if (val < (rlim_t) 0)
12647 ash_msg_and_raise_error("bad number");
12648 val <<= l->factor_shift;
12652 const char *lname = limits_name;
12653 for (l = limits_tbl; l != &limits_tbl[ARRAY_SIZE(limits_tbl)]; l++) {
12654 getrlimit(l->cmd, &limit);
12655 out1fmt("%-20s ", lname);
12656 lname += strlen(lname) + 1;
12657 printlim(how, &limit, l);
12662 getrlimit(l->cmd, &limit);
12665 limit.rlim_max = val;
12667 limit.rlim_cur = val;
12668 if (setrlimit(l->cmd, &limit) < 0)
12669 ash_msg_and_raise_error("error setting limit (%m)");
12671 printlim(how, &limit, l);
12677 /* ============ Math support */
12679 #if ENABLE_ASH_MATH_SUPPORT
12681 /* Copyright (c) 2001 Aaron Lehmann <aaronl@vitelus.com>
12683 Permission is hereby granted, free of charge, to any person obtaining
12684 a copy of this software and associated documentation files (the
12685 "Software"), to deal in the Software without restriction, including
12686 without limitation the rights to use, copy, modify, merge, publish,
12687 distribute, sublicense, and/or sell copies of the Software, and to
12688 permit persons to whom the Software is furnished to do so, subject to
12689 the following conditions:
12691 The above copyright notice and this permission notice shall be
12692 included in all copies or substantial portions of the Software.
12694 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
12695 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
12696 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
12697 IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
12698 CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
12699 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
12700 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
12703 /* This is my infix parser/evaluator. It is optimized for size, intended
12704 * as a replacement for yacc-based parsers. However, it may well be faster
12705 * than a comparable parser written in yacc. The supported operators are
12706 * listed in #defines below. Parens, order of operations, and error handling
12707 * are supported. This code is thread safe. The exact expression format should
12708 * be that which POSIX specifies for shells. */
12710 /* The code uses a simple two-stack algorithm. See
12711 * http://www.onthenet.com.au/~grahamis/int2008/week02/lect02.html
12712 * for a detailed explanation of the infix-to-postfix algorithm on which
12713 * this is based (this code differs in that it applies operators immediately
12714 * to the stack instead of adding them to a queue to end up with an
12717 /* To use the routine, call it with an expression string and error return
12721 * Aug 24, 2001 Manuel Novoa III
12723 * Reduced the generated code size by about 30% (i386) and fixed several bugs.
12725 * 1) In arith_apply():
12726 * a) Cached values of *numptr and &(numptr[-1]).
12727 * b) Removed redundant test for zero denominator.
12730 * a) Eliminated redundant code for processing operator tokens by moving
12731 * to a table-based implementation. Also folded handling of parens
12733 * b) Combined all 3 loops which called arith_apply to reduce generated
12734 * code size at the cost of speed.
12736 * 3) The following expressions were treated as valid by the original code:
12737 * 1() , 0! , 1 ( *3 ) .
12738 * These bugs have been fixed by internally enclosing the expression in
12739 * parens and then checking that all binary ops and right parens are
12740 * preceded by a valid expression (NUM_TOKEN).
12742 * Note: It may be desirable to replace Aaron's test for whitespace with
12743 * ctype's isspace() if it is used by another busybox applet or if additional
12744 * whitespace chars should be considered. Look below the "#include"s for a
12745 * precompiler test.
12749 * Aug 26, 2001 Manuel Novoa III
12751 * Return 0 for null expressions. Pointed out by Vladimir Oleynik.
12753 * Merge in Aaron's comments previously posted to the busybox list,
12754 * modified slightly to take account of my changes to the code.
12759 * (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
12761 * - allow access to variable,
12762 * used recursive find value indirection (c=2*2; a="c"; $((a+=2)) produce 6)
12763 * - realize assign syntax (VAR=expr, +=, *= etc)
12764 * - realize exponentiation (** operator)
12765 * - realize comma separated - expr, expr
12766 * - realise ++expr --expr expr++ expr--
12767 * - realise expr ? expr : expr (but, second expr calculate always)
12768 * - allow hexadecimal and octal numbers
12769 * - was restored loses XOR operator
12770 * - remove one goto label, added three ;-)
12771 * - protect $((num num)) as true zero expr (Manuel`s error)
12772 * - always use special isspace(), see comment from bash ;-)
12775 #define arith_isspace(arithval) \
12776 (arithval == ' ' || arithval == '\n' || arithval == '\t')
12778 typedef unsigned char operator;
12780 /* An operator's token id is a bit of a bitfield. The lower 5 bits are the
12781 * precedence, and 3 high bits are an ID unique across operators of that
12782 * precedence. The ID portion is so that multiple operators can have the
12783 * same precedence, ensuring that the leftmost one is evaluated first.
12784 * Consider * and /. */
12786 #define tok_decl(prec,id) (((id)<<5)|(prec))
12787 #define PREC(op) ((op) & 0x1F)
12789 #define TOK_LPAREN tok_decl(0,0)
12791 #define TOK_COMMA tok_decl(1,0)
12793 #define TOK_ASSIGN tok_decl(2,0)
12794 #define TOK_AND_ASSIGN tok_decl(2,1)
12795 #define TOK_OR_ASSIGN tok_decl(2,2)
12796 #define TOK_XOR_ASSIGN tok_decl(2,3)
12797 #define TOK_PLUS_ASSIGN tok_decl(2,4)
12798 #define TOK_MINUS_ASSIGN tok_decl(2,5)
12799 #define TOK_LSHIFT_ASSIGN tok_decl(2,6)
12800 #define TOK_RSHIFT_ASSIGN tok_decl(2,7)
12802 #define TOK_MUL_ASSIGN tok_decl(3,0)
12803 #define TOK_DIV_ASSIGN tok_decl(3,1)
12804 #define TOK_REM_ASSIGN tok_decl(3,2)
12806 /* all assign is right associativity and precedence eq, but (7+3)<<5 > 256 */
12807 #define convert_prec_is_assing(prec) do { if (prec == 3) prec = 2; } while (0)
12809 /* conditional is right associativity too */
12810 #define TOK_CONDITIONAL tok_decl(4,0)
12811 #define TOK_CONDITIONAL_SEP tok_decl(4,1)
12813 #define TOK_OR tok_decl(5,0)
12815 #define TOK_AND tok_decl(6,0)
12817 #define TOK_BOR tok_decl(7,0)
12819 #define TOK_BXOR tok_decl(8,0)
12821 #define TOK_BAND tok_decl(9,0)
12823 #define TOK_EQ tok_decl(10,0)
12824 #define TOK_NE tok_decl(10,1)
12826 #define TOK_LT tok_decl(11,0)
12827 #define TOK_GT tok_decl(11,1)
12828 #define TOK_GE tok_decl(11,2)
12829 #define TOK_LE tok_decl(11,3)
12831 #define TOK_LSHIFT tok_decl(12,0)
12832 #define TOK_RSHIFT tok_decl(12,1)
12834 #define TOK_ADD tok_decl(13,0)
12835 #define TOK_SUB tok_decl(13,1)
12837 #define TOK_MUL tok_decl(14,0)
12838 #define TOK_DIV tok_decl(14,1)
12839 #define TOK_REM tok_decl(14,2)
12841 /* exponent is right associativity */
12842 #define TOK_EXPONENT tok_decl(15,1)
12844 /* For now unary operators. */
12845 #define UNARYPREC 16
12846 #define TOK_BNOT tok_decl(UNARYPREC,0)
12847 #define TOK_NOT tok_decl(UNARYPREC,1)
12849 #define TOK_UMINUS tok_decl(UNARYPREC+1,0)
12850 #define TOK_UPLUS tok_decl(UNARYPREC+1,1)
12852 #define PREC_PRE (UNARYPREC+2)
12854 #define TOK_PRE_INC tok_decl(PREC_PRE, 0)
12855 #define TOK_PRE_DEC tok_decl(PREC_PRE, 1)
12857 #define PREC_POST (UNARYPREC+3)
12859 #define TOK_POST_INC tok_decl(PREC_POST, 0)
12860 #define TOK_POST_DEC tok_decl(PREC_POST, 1)
12862 #define SPEC_PREC (UNARYPREC+4)
12864 #define TOK_NUM tok_decl(SPEC_PREC, 0)
12865 #define TOK_RPAREN tok_decl(SPEC_PREC, 1)
12867 #define NUMPTR (*numstackptr)
12870 tok_have_assign(operator op)
12872 operator prec = PREC(op);
12874 convert_prec_is_assing(prec);
12875 return (prec == PREC(TOK_ASSIGN) ||
12876 prec == PREC_PRE || prec == PREC_POST);
12880 is_right_associativity(operator prec)
12882 return (prec == PREC(TOK_ASSIGN) || prec == PREC(TOK_EXPONENT)
12883 || prec == PREC(TOK_CONDITIONAL));
12888 arith_t contidional_second_val;
12889 char contidional_second_val_initialized;
12890 char *var; /* if NULL then is regular number,
12891 else is variable name */
12894 typedef struct chk_var_recursive_looped_t {
12896 struct chk_var_recursive_looped_t *next;
12897 } chk_var_recursive_looped_t;
12899 static chk_var_recursive_looped_t *prev_chk_var_recursive;
12902 arith_lookup_val(v_n_t *t)
12905 const char * p = lookupvar(t->var);
12910 /* recursive try as expression */
12911 chk_var_recursive_looped_t *cur;
12912 chk_var_recursive_looped_t cur_save;
12914 for (cur = prev_chk_var_recursive; cur; cur = cur->next) {
12915 if (strcmp(cur->var, t->var) == 0) {
12916 /* expression recursion loop detected */
12920 /* save current lookuped var name */
12921 cur = prev_chk_var_recursive;
12922 cur_save.var = t->var;
12923 cur_save.next = cur;
12924 prev_chk_var_recursive = &cur_save;
12926 t->val = arith (p, &errcode);
12927 /* restore previous ptr after recursiving */
12928 prev_chk_var_recursive = cur;
12931 /* allow undefined var as 0 */
12937 /* "applying" a token means performing it on the top elements on the integer
12938 * stack. For a unary operator it will only change the top element, but a
12939 * binary operator will pop two arguments and push a result */
12941 arith_apply(operator op, v_n_t *numstack, v_n_t **numstackptr)
12944 arith_t numptr_val, rez;
12945 int ret_arith_lookup_val;
12947 /* There is no operator that can work without arguments */
12948 if (NUMPTR == numstack) goto err;
12949 numptr_m1 = NUMPTR - 1;
12951 /* check operand is var with noninteger value */
12952 ret_arith_lookup_val = arith_lookup_val(numptr_m1);
12953 if (ret_arith_lookup_val)
12954 return ret_arith_lookup_val;
12956 rez = numptr_m1->val;
12957 if (op == TOK_UMINUS)
12959 else if (op == TOK_NOT)
12961 else if (op == TOK_BNOT)
12963 else if (op == TOK_POST_INC || op == TOK_PRE_INC)
12965 else if (op == TOK_POST_DEC || op == TOK_PRE_DEC)
12967 else if (op != TOK_UPLUS) {
12968 /* Binary operators */
12970 /* check and binary operators need two arguments */
12971 if (numptr_m1 == numstack) goto err;
12973 /* ... and they pop one */
12976 if (op == TOK_CONDITIONAL) {
12977 if (!numptr_m1->contidional_second_val_initialized) {
12978 /* protect $((expr1 ? expr2)) without ": expr" */
12981 rez = numptr_m1->contidional_second_val;
12982 } else if (numptr_m1->contidional_second_val_initialized) {
12983 /* protect $((expr1 : expr2)) without "expr ? " */
12986 numptr_m1 = NUMPTR - 1;
12987 if (op != TOK_ASSIGN) {
12988 /* check operand is var with noninteger value for not '=' */
12989 ret_arith_lookup_val = arith_lookup_val(numptr_m1);
12990 if (ret_arith_lookup_val)
12991 return ret_arith_lookup_val;
12993 if (op == TOK_CONDITIONAL) {
12994 numptr_m1->contidional_second_val = rez;
12996 rez = numptr_m1->val;
12997 if (op == TOK_BOR || op == TOK_OR_ASSIGN)
12999 else if (op == TOK_OR)
13000 rez = numptr_val || rez;
13001 else if (op == TOK_BAND || op == TOK_AND_ASSIGN)
13003 else if (op == TOK_BXOR || op == TOK_XOR_ASSIGN)
13005 else if (op == TOK_AND)
13006 rez = rez && numptr_val;
13007 else if (op == TOK_EQ)
13008 rez = (rez == numptr_val);
13009 else if (op == TOK_NE)
13010 rez = (rez != numptr_val);
13011 else if (op == TOK_GE)
13012 rez = (rez >= numptr_val);
13013 else if (op == TOK_RSHIFT || op == TOK_RSHIFT_ASSIGN)
13014 rez >>= numptr_val;
13015 else if (op == TOK_LSHIFT || op == TOK_LSHIFT_ASSIGN)
13016 rez <<= numptr_val;
13017 else if (op == TOK_GT)
13018 rez = (rez > numptr_val);
13019 else if (op == TOK_LT)
13020 rez = (rez < numptr_val);
13021 else if (op == TOK_LE)
13022 rez = (rez <= numptr_val);
13023 else if (op == TOK_MUL || op == TOK_MUL_ASSIGN)
13025 else if (op == TOK_ADD || op == TOK_PLUS_ASSIGN)
13027 else if (op == TOK_SUB || op == TOK_MINUS_ASSIGN)
13029 else if (op == TOK_ASSIGN || op == TOK_COMMA)
13031 else if (op == TOK_CONDITIONAL_SEP) {
13032 if (numptr_m1 == numstack) {
13033 /* protect $((expr : expr)) without "expr ? " */
13036 numptr_m1->contidional_second_val_initialized = op;
13037 numptr_m1->contidional_second_val = numptr_val;
13038 } else if (op == TOK_CONDITIONAL) {
13040 numptr_val : numptr_m1->contidional_second_val;
13041 } else if (op == TOK_EXPONENT) {
13042 if (numptr_val < 0)
13043 return -3; /* exponent less than 0 */
13048 while (numptr_val--)
13052 } else if (numptr_val==0) /* zero divisor check */
13054 else if (op == TOK_DIV || op == TOK_DIV_ASSIGN)
13056 else if (op == TOK_REM || op == TOK_REM_ASSIGN)
13059 if (tok_have_assign(op)) {
13060 char buf[sizeof(arith_t_type)*3 + 2];
13062 if (numptr_m1->var == NULL) {
13066 /* save to shell variable */
13067 #if ENABLE_ASH_MATH_SUPPORT_64
13068 snprintf(buf, sizeof(buf), "%lld", (arith_t_type) rez);
13070 snprintf(buf, sizeof(buf), "%ld", (arith_t_type) rez);
13072 setvar(numptr_m1->var, buf, 0);
13073 /* after saving, make previous value for v++ or v-- */
13074 if (op == TOK_POST_INC)
13076 else if (op == TOK_POST_DEC)
13079 numptr_m1->val = rez;
13080 /* protect geting var value, is number now */
13081 numptr_m1->var = NULL;
13087 /* longest must be first */
13088 static const char op_tokens[] ALIGN1 = {
13089 '<','<','=',0, TOK_LSHIFT_ASSIGN,
13090 '>','>','=',0, TOK_RSHIFT_ASSIGN,
13091 '<','<', 0, TOK_LSHIFT,
13092 '>','>', 0, TOK_RSHIFT,
13093 '|','|', 0, TOK_OR,
13094 '&','&', 0, TOK_AND,
13095 '!','=', 0, TOK_NE,
13096 '<','=', 0, TOK_LE,
13097 '>','=', 0, TOK_GE,
13098 '=','=', 0, TOK_EQ,
13099 '|','=', 0, TOK_OR_ASSIGN,
13100 '&','=', 0, TOK_AND_ASSIGN,
13101 '*','=', 0, TOK_MUL_ASSIGN,
13102 '/','=', 0, TOK_DIV_ASSIGN,
13103 '%','=', 0, TOK_REM_ASSIGN,
13104 '+','=', 0, TOK_PLUS_ASSIGN,
13105 '-','=', 0, TOK_MINUS_ASSIGN,
13106 '-','-', 0, TOK_POST_DEC,
13107 '^','=', 0, TOK_XOR_ASSIGN,
13108 '+','+', 0, TOK_POST_INC,
13109 '*','*', 0, TOK_EXPONENT,
13113 '=', 0, TOK_ASSIGN,
13125 '?', 0, TOK_CONDITIONAL,
13126 ':', 0, TOK_CONDITIONAL_SEP,
13127 ')', 0, TOK_RPAREN,
13128 '(', 0, TOK_LPAREN,
13132 #define endexpression (&op_tokens[sizeof(op_tokens)-7])
13135 arith(const char *expr, int *perrcode)
13137 char arithval; /* Current character under analysis */
13138 operator lasttok, op;
13140 operator *stack, *stackptr;
13141 const char *p = endexpression;
13143 v_n_t *numstack, *numstackptr;
13144 unsigned datasizes = strlen(expr) + 2;
13146 /* Stack of integers */
13147 /* The proof that there can be no more than strlen(startbuf)/2+1 integers
13148 * in any given correct or incorrect expression is left as an exercise to
13150 numstackptr = numstack = alloca((datasizes / 2) * sizeof(numstack[0]));
13151 /* Stack of operator tokens */
13152 stackptr = stack = alloca(datasizes * sizeof(stack[0]));
13154 *stackptr++ = lasttok = TOK_LPAREN; /* start off with a left paren */
13155 *perrcode = errcode = 0;
13159 if (arithval == 0) {
13160 if (p == endexpression) {
13161 /* Null expression. */
13165 /* This is only reached after all tokens have been extracted from the
13166 * input stream. If there are still tokens on the operator stack, they
13167 * are to be applied in order. At the end, there should be a final
13168 * result on the integer stack */
13170 if (expr != endexpression + 1) {
13171 /* If we haven't done so already, */
13172 /* append a closing right paren */
13173 expr = endexpression;
13174 /* and let the loop process it. */
13177 /* At this point, we're done with the expression. */
13178 if (numstackptr != numstack+1) {
13179 /* ... but if there isn't, it's bad */
13184 if (numstack->var) {
13185 /* expression is $((var)) only, lookup now */
13186 errcode = arith_lookup_val(numstack);
13189 *perrcode = errcode;
13190 return numstack->val;
13193 /* Continue processing the expression. */
13194 if (arith_isspace(arithval)) {
13195 /* Skip whitespace */
13198 p = endofname(expr);
13200 size_t var_name_size = (p-expr) + 1; /* trailing zero */
13202 numstackptr->var = alloca(var_name_size);
13203 safe_strncpy(numstackptr->var, expr, var_name_size);
13206 numstackptr->contidional_second_val_initialized = 0;
13211 if (isdigit(arithval)) {
13212 numstackptr->var = NULL;
13213 #if ENABLE_ASH_MATH_SUPPORT_64
13214 numstackptr->val = strtoll(expr, (char **) &expr, 0);
13216 numstackptr->val = strtol(expr, (char **) &expr, 0);
13220 for (p = op_tokens; ; p++) {
13224 /* strange operator not found */
13227 for (o = expr; *p && *o == *p; p++)
13234 /* skip tail uncompared token */
13237 /* skip zero delim */
13242 /* post grammar: a++ reduce to num */
13243 if (lasttok == TOK_POST_INC || lasttok == TOK_POST_DEC)
13246 /* Plus and minus are binary (not unary) _only_ if the last
13247 * token was as number, or a right paren (which pretends to be
13248 * a number, since it evaluates to one). Think about it.
13249 * It makes sense. */
13250 if (lasttok != TOK_NUM) {
13266 /* We don't want a unary operator to cause recursive descent on the
13267 * stack, because there can be many in a row and it could cause an
13268 * operator to be evaluated before its argument is pushed onto the
13269 * integer stack. */
13270 /* But for binary operators, "apply" everything on the operator
13271 * stack until we find an operator with a lesser priority than the
13272 * one we have just extracted. */
13273 /* Left paren is given the lowest priority so it will never be
13274 * "applied" in this way.
13275 * if associativity is right and priority eq, applied also skip
13278 if ((prec > 0 && prec < UNARYPREC) || prec == SPEC_PREC) {
13279 /* not left paren or unary */
13280 if (lasttok != TOK_NUM) {
13281 /* binary op must be preceded by a num */
13284 while (stackptr != stack) {
13285 if (op == TOK_RPAREN) {
13286 /* The algorithm employed here is simple: while we don't
13287 * hit an open paren nor the bottom of the stack, pop
13288 * tokens and apply them */
13289 if (stackptr[-1] == TOK_LPAREN) {
13291 /* Any operator directly after a */
13293 /* close paren should consider itself binary */
13297 operator prev_prec = PREC(stackptr[-1]);
13299 convert_prec_is_assing(prec);
13300 convert_prec_is_assing(prev_prec);
13301 if (prev_prec < prec)
13303 /* check right assoc */
13304 if (prev_prec == prec && is_right_associativity(prec))
13307 errcode = arith_apply(*--stackptr, numstack, &numstackptr);
13308 if (errcode) goto ret;
13310 if (op == TOK_RPAREN) {
13315 /* Push this operator to the stack and remember it. */
13316 *stackptr++ = lasttok = op;
13321 #endif /* ASH_MATH_SUPPORT */
13324 /* ============ main() and helpers */
13327 * Called to exit the shell.
13329 static void exitshell(void) NORETURN;
13337 status = exitstatus;
13338 TRACE(("pid %d, exitshell(%d)\n", getpid(), status));
13339 if (setjmp(loc.loc)) {
13340 if (exception == EXEXIT)
13341 /* dash bug: it just does _exit(exitstatus) here
13342 * but we have to do setjobctl(0) first!
13343 * (bug is still not fixed in dash-0.5.3 - if you run dash
13344 * under Midnight Commander, on exit from dash MC is backgrounded) */
13345 status = exitstatus;
13348 exception_handler = &loc;
13354 flush_stdout_stderr();
13364 /* from input.c: */
13365 basepf.nextc = basepf.buf = basebuf;
13368 signal(SIGCHLD, SIG_DFL);
13373 char ppid[sizeof(int)*3 + 1];
13375 struct stat st1, st2;
13378 for (envp = environ; envp && *envp; envp++) {
13379 if (strchr(*envp, '=')) {
13380 setvareq(*envp, VEXPORT|VTEXTFIXED);
13384 snprintf(ppid, sizeof(ppid), "%u", (unsigned) getppid());
13385 setvar("PPID", ppid, 0);
13387 p = lookupvar("PWD");
13389 if (*p != '/' || stat(p, &st1) || stat(".", &st2)
13390 || st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino)
13397 * Process the shell command line arguments.
13400 procargs(char **argv)
13403 const char *xminusc;
13408 /* if (xargv[0]) - mmm, this is always true! */
13410 for (i = 0; i < NOPTS; i++)
13414 /* it already printed err message */
13415 raise_exception(EXERROR);
13419 if (*xargv == NULL) {
13421 ash_msg_and_raise_error(bb_msg_requires_arg, "-c");
13424 if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
13428 for (i = 0; i < NOPTS; i++)
13429 if (optlist[i] == 2)
13434 /* POSIX 1003.2: first arg after -c cmd is $0, remainder $1... */
13439 } else if (!sflag) {
13440 setinputfile(*xargv, 0);
13443 commandname = arg0;
13446 shellparam.p = xargv;
13447 #if ENABLE_ASH_GETOPTS
13448 shellparam.optind = 1;
13449 shellparam.optoff = -1;
13451 /* assert(shellparam.malloced == 0 && shellparam.nparam == 0); */
13453 shellparam.nparam++;
13460 * Read /etc/profile or .profile.
13463 read_profile(const char *name)
13467 if (setinputfile(name, INPUT_PUSH_FILE | INPUT_NOFILE_OK) < 0)
13476 * This routine is called when an error or an interrupt occurs in an
13477 * interactive shell and control is returned to the main command loop.
13485 /* from input.c: */
13486 parselleft = parsenleft = 0; /* clear input buffer */
13488 /* from parser.c: */
13491 /* from redir.c: */
13492 clearredir(/*drop:*/ 0);
13496 static short profile_buf[16384];
13497 extern int etext();
13501 * Main routine. We initialize things, parse the arguments, execute
13502 * profiles if we're a login shell, and then call cmdloop to execute
13503 * commands. The setjmp call sets up the location to jump to when an
13504 * exception occurs. When an exception occurs the variable "state"
13505 * is used to figure out how far we had gotten.
13507 int ash_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
13508 int ash_main(int argc UNUSED_PARAM, char **argv)
13511 volatile int state;
13512 struct jmploc jmploc;
13513 struct stackmark smark;
13515 /* Initialize global data */
13519 #if ENABLE_ASH_ALIAS
13525 monitor(4, etext, profile_buf, sizeof(profile_buf), 50);
13528 #if ENABLE_FEATURE_EDITING
13529 line_input_state = new_line_input_t(FOR_SHELL | WITH_PATH_LOOKUP);
13532 if (setjmp(jmploc.loc)) {
13542 if (e == EXEXIT || s == 0 || iflag == 0 || shlvl)
13546 outcslow('\n', stderr);
13548 popstackmark(&smark);
13549 FORCE_INT_ON; /* enable interrupts */
13558 exception_handler = &jmploc;
13561 trace_puts("Shell args: ");
13562 trace_puts_args(argv);
13564 rootpid = getpid();
13566 #if ENABLE_ASH_RANDOM_SUPPORT
13567 /* Can use monotonic_ns() for better randomness but for now it is
13568 * not used anywhere else in busybox... so avoid bloat */
13569 random_galois_LFSR = random_LCG = rootpid + monotonic_us();
13572 setstackmark(&smark);
13575 #if ENABLE_FEATURE_EDITING_SAVEHISTORY
13577 const char *hp = lookupvar("HISTFILE");
13580 hp = lookupvar("HOME");
13582 char *defhp = concat_path_file(hp, ".ash_history");
13583 setvar("HISTFILE", defhp, 0);
13589 if (argv[0] && argv[0][0] == '-')
13593 read_profile("/etc/profile");
13596 read_profile(".profile");
13602 getuid() == geteuid() && getgid() == getegid() &&
13606 shinit = lookupvar("ENV");
13607 if (shinit != NULL && *shinit != '\0') {
13608 read_profile(shinit);
13614 evalstring(minusc, 0);
13616 if (sflag || minusc == NULL) {
13617 #if ENABLE_FEATURE_EDITING_SAVEHISTORY
13619 const char *hp = lookupvar("HISTFILE");
13622 line_input_state->hist_file = hp;
13625 state4: /* XXX ??? - why isn't this before the "if" statement */
13633 extern void _mcleanup(void);
13642 const char *applet_name = "debug stuff usage";
13643 int main(int argc, char **argv)
13645 return ash_main(argc, argv);
13651 * Copyright (c) 1989, 1991, 1993, 1994
13652 * The Regents of the University of California. All rights reserved.
13654 * This code is derived from software contributed to Berkeley by
13655 * Kenneth Almquist.
13657 * Redistribution and use in source and binary forms, with or without
13658 * modification, are permitted provided that the following conditions
13660 * 1. Redistributions of source code must retain the above copyright
13661 * notice, this list of conditions and the following disclaimer.
13662 * 2. Redistributions in binary form must reproduce the above copyright
13663 * notice, this list of conditions and the following disclaimer in the
13664 * documentation and/or other materials provided with the distribution.
13665 * 3. Neither the name of the University nor the names of its contributors
13666 * may be used to endorse or promote products derived from this software
13667 * without specific prior written permission.
13669 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
13670 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
13671 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
13672 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
13673 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
13674 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
13675 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
13676 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
13677 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
13678 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF