1 /* vi: set sw=4 ts=4: */
3 * ash shell port for busybox
5 * Copyright (c) 1989, 1991, 1993, 1994
6 * The Regents of the University of California. All rights reserved.
8 * Copyright (c) 1997-2005 Herbert Xu <herbert@gondor.apana.org.au>
9 * was re-ported from NetBSD and debianized.
12 * This code is derived from software contributed to Berkeley by
15 * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
17 * Original BSD copyright notice is retained at the end of this file.
21 * rewrite arith.y to micro stack based cryptic algorithm by
22 * Copyright (c) 2001 Aaron Lehmann <aaronl@vitelus.com>
24 * Modified by Paul Mundt <lethal@linux-sh.org> (c) 2004 to support
27 * Modified by Vladimir Oleynik <dzo@simtreas.ru> (c) 2001-2005 to be
28 * used in busybox and size optimizations,
29 * rewrote arith (see notes to this), added locale support,
30 * rewrote dynamic variables.
35 * The follow should be set to reflect the type of system you have:
36 * JOBS -> 1 if you have Berkeley job control, 0 otherwise.
37 * define SYSV if you are running under System V.
38 * define DEBUG=1 to compile in debugging ('set -o debug' to turn on)
39 * define DEBUG=2 to compile in and turn on debugging.
41 * When debugging is on, debugging info will be written to ./trace and
42 * a quit signal will generate a core dump.
49 #define JOBS ENABLE_ASH_JOB_CONTROL
57 #include "busybox.h" /* for applet_names */
61 #if JOBS || ENABLE_ASH_READ_NCHARS
65 #if defined(__uClinux__)
66 #error "Do not even bother, ash will not run on uClinux"
70 /* ============ Hash table sizes. Configurable. */
74 #define CMDTABLESIZE 31 /* should be prime */
77 /* ============ Misc helpers */
79 #define xbarrier() do { __asm__ __volatile__ ("": : :"memory"); } while (0)
81 /* C99 say: "char" declaration may be signed or unsigned default */
82 #define signed_char2int(sc) ((int)((signed char)sc))
85 /* ============ Shell options */
87 static const char *const optletters_optnames[] = {
108 #define optletters(n) optletters_optnames[(n)][0]
109 #define optnames(n) (&optletters_optnames[(n)][1])
111 enum { NOPTS = ARRAY_SIZE(optletters_optnames) };
114 /* ============ Misc data */
116 static const char homestr[] ALIGN1 = "HOME";
117 static const char snlfmt[] ALIGN1 = "%s\n";
118 static const char illnum[] ALIGN1 = "Illegal number: %s";
121 * We enclose jmp_buf in a structure so that we can declare pointers to
122 * jump locations. The global variable handler contains the location to
123 * jump to when an exception occurs, and the global variable exception
124 * contains a code identifying the exception. To implement nested
125 * exception handlers, the user should save the value of handler on entry
126 * to an inner scope, set handler to point to a jmploc structure for the
127 * inner scope, and restore handler on exit from the scope.
133 struct globals_misc {
134 /* pid of main shell */
136 /* shell level: 0 for the main shell, 1 for its children, and so on */
138 #define rootshell (!shlvl)
139 char *minusc; /* argument to -c option */
141 char *curdir; // = nullstr; /* current working directory */
142 char *physdir; // = nullstr; /* physical working directory */
144 char *arg0; /* value of $0 */
146 struct jmploc *exception_handler;
148 // disabled by vda: cannot understand how it was supposed to work -
149 // cannot fix bugs. That's why you have to explain your non-trivial designs!
150 // /* do we generate EXSIG events */
151 // int exsig; /* counter */
152 volatile int suppressint; /* counter */
153 volatile /*sig_atomic_t*/ smallint intpending; /* 1 = got SIGINT */
154 /* last pending signal */
155 volatile /*sig_atomic_t*/ smallint pendingsig;
156 smallint exception; /* kind of exception (0..5) */
158 #define EXINT 0 /* SIGINT received */
159 #define EXERROR 1 /* a generic error */
160 #define EXSHELLPROC 2 /* execute a shell procedure */
161 #define EXEXEC 3 /* command execution failed */
162 #define EXEXIT 4 /* exit the shell */
163 #define EXSIG 5 /* trapped signal in wait(1) */
166 char nullstr[1]; /* zero length string */
169 #define eflag optlist[0]
170 #define fflag optlist[1]
171 #define Iflag optlist[2]
172 #define iflag optlist[3]
173 #define mflag optlist[4]
174 #define nflag optlist[5]
175 #define sflag optlist[6]
176 #define xflag optlist[7]
177 #define vflag optlist[8]
178 #define Cflag optlist[9]
179 #define aflag optlist[10]
180 #define bflag optlist[11]
181 #define uflag optlist[12]
182 #define viflag optlist[13]
184 #define nolog optlist[14]
185 #define debug optlist[15]
188 /* trap handler commands */
190 * Sigmode records the current value of the signal handlers for the various
191 * modes. A value of zero means that the current handler is not known.
192 * S_HARD_IGN indicates that the signal was ignored on entry to the shell,
194 char sigmode[NSIG - 1];
195 #define S_DFL 1 /* default signal handling (SIG_DFL) */
196 #define S_CATCH 2 /* signal is caught */
197 #define S_IGN 3 /* signal is ignored (SIG_IGN) */
198 #define S_HARD_IGN 4 /* signal is ignored permenantly */
199 #define S_RESET 5 /* temporary - to reset a hard ignored sig */
201 /* indicates specified signal received */
202 char gotsig[NSIG - 1];
205 /* Rarely referenced stuff */
206 #if ENABLE_ASH_RANDOM_SUPPORT
207 /* Random number generators */
208 int32_t random_galois_LFSR; /* Galois LFSR (fast but weak). signed! */
209 uint32_t random_LCG; /* LCG (fast but weak) */
211 pid_t backgndpid; /* pid of last background process */
212 smallint job_warning; /* user was warned about stopped jobs (can be 2, 1 or 0). */
214 extern struct globals_misc *const ash_ptr_to_globals_misc;
215 #define G_misc (*ash_ptr_to_globals_misc)
216 #define rootpid (G_misc.rootpid )
217 #define shlvl (G_misc.shlvl )
218 #define minusc (G_misc.minusc )
219 #define curdir (G_misc.curdir )
220 #define physdir (G_misc.physdir )
221 #define arg0 (G_misc.arg0 )
222 #define exception_handler (G_misc.exception_handler)
223 #define exception (G_misc.exception )
224 #define suppressint (G_misc.suppressint )
225 #define intpending (G_misc.intpending )
226 //#define exsig (G_misc.exsig )
227 #define pendingsig (G_misc.pendingsig )
228 #define isloginsh (G_misc.isloginsh )
229 #define nullstr (G_misc.nullstr )
230 #define optlist (G_misc.optlist )
231 #define sigmode (G_misc.sigmode )
232 #define gotsig (G_misc.gotsig )
233 #define trap (G_misc.trap )
234 #define random_galois_LFSR (G_misc.random_galois_LFSR)
235 #define random_LCG (G_misc.random_LCG )
236 #define backgndpid (G_misc.backgndpid )
237 #define job_warning (G_misc.job_warning)
238 #define INIT_G_misc() do { \
239 (*(struct globals_misc**)&ash_ptr_to_globals_misc) = xzalloc(sizeof(G_misc)); \
246 /* ============ Interrupts / exceptions */
249 * These macros allow the user to suspend the handling of interrupt signals
250 * over a period of time. This is similar to SIGHOLD or to sigblock, but
251 * much more efficient and portable. (But hacking the kernel is so much
252 * more fun than worrying about efficiency and portability. :-))
254 #define INT_OFF do { \
260 * Called to raise an exception. Since C doesn't include exceptions, we
261 * just do a longjmp to the exception handler. The type of exception is
262 * stored in the global variable "exception".
264 static void raise_exception(int) NORETURN;
266 raise_exception(int e)
269 if (exception_handler == NULL)
274 longjmp(exception_handler->loc, 1);
278 * Called from trap.c when a SIGINT is received. (If the user specifies
279 * that SIGINT is to be trapped or ignored using the trap builtin, then
280 * this routine is not called.) Suppressint is nonzero when interrupts
281 * are held using the INT_OFF macro. (The test for iflag is just
282 * defensive programming.)
284 static void raise_interrupt(void) NORETURN;
286 raise_interrupt(void)
291 /* Signal is not automatically unmasked after it is raised,
292 * do it ourself - unmask all signals */
293 sigprocmask_allsigs(SIG_UNBLOCK);
294 /* pendingsig = 0; - now done in onsig() */
297 if (gotsig[SIGINT - 1] && !trap[SIGINT]) {
298 if (!(rootshell && iflag)) {
299 /* Kill ourself with SIGINT */
300 signal(SIGINT, SIG_DFL);
309 #if ENABLE_ASH_OPTIMIZE_FOR_SIZE
313 if (--suppressint == 0 && intpending) {
317 #define INT_ON int_on()
325 #define FORCE_INT_ON force_int_on()
327 #define INT_ON do { \
329 if (--suppressint == 0 && intpending) \
332 #define FORCE_INT_ON do { \
338 #endif /* ASH_OPTIMIZE_FOR_SIZE */
340 #define SAVE_INT(v) ((v) = suppressint)
342 #define RESTORE_INT(v) do { \
345 if (suppressint == 0 && intpending) \
350 * Ignore a signal. Only one usage site - in forkchild()
355 if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) {
356 signal(signo, SIG_IGN);
358 sigmode[signo - 1] = S_HARD_IGN;
362 * Signal handler. Only one usage site - in setsignal()
367 gotsig[signo - 1] = 1;
370 if (/* exsig || */ (signo == SIGINT && !trap[SIGINT])) {
373 raise_interrupt(); /* does not return */
380 /* ============ Stdout/stderr output */
383 outstr(const char *p, FILE *file)
391 flush_stdout_stderr(void)
408 outcslow(int c, FILE *dest)
416 static int out1fmt(const char *, ...) __attribute__((__format__(__printf__,1,2)));
418 out1fmt(const char *fmt, ...)
425 r = vprintf(fmt, ap);
431 static int fmtstr(char *, size_t, const char *, ...) __attribute__((__format__(__printf__,3,4)));
433 fmtstr(char *outbuf, size_t length, const char *fmt, ...)
440 ret = vsnprintf(outbuf, length, fmt, ap);
447 out1str(const char *p)
453 out2str(const char *p)
460 /* ============ Parser structures */
462 /* control characters in argument strings */
463 #define CTLESC '\201' /* escape next character */
464 #define CTLVAR '\202' /* variable defn */
465 #define CTLENDVAR '\203'
466 #define CTLBACKQ '\204'
467 #define CTLQUOTE 01 /* ored with CTLBACKQ code if in quotes */
468 /* CTLBACKQ | CTLQUOTE == '\205' */
469 #define CTLARI '\206' /* arithmetic expression */
470 #define CTLENDARI '\207'
471 #define CTLQUOTEMARK '\210'
473 /* variable substitution byte (follows CTLVAR) */
474 #define VSTYPE 0x0f /* type of variable substitution */
475 #define VSNUL 0x10 /* colon--treat the empty string as unset */
476 #define VSQUOTE 0x80 /* inside double quotes--suppress splitting */
478 /* values of VSTYPE field */
479 #define VSNORMAL 0x1 /* normal variable: $var or ${var} */
480 #define VSMINUS 0x2 /* ${var-text} */
481 #define VSPLUS 0x3 /* ${var+text} */
482 #define VSQUESTION 0x4 /* ${var?message} */
483 #define VSASSIGN 0x5 /* ${var=text} */
484 #define VSTRIMRIGHT 0x6 /* ${var%pattern} */
485 #define VSTRIMRIGHTMAX 0x7 /* ${var%%pattern} */
486 #define VSTRIMLEFT 0x8 /* ${var#pattern} */
487 #define VSTRIMLEFTMAX 0x9 /* ${var##pattern} */
488 #define VSLENGTH 0xa /* ${#var} */
489 #if ENABLE_ASH_BASH_COMPAT
490 #define VSSUBSTR 0xc /* ${var:position:length} */
491 #define VSREPLACE 0xd /* ${var/pattern/replacement} */
492 #define VSREPLACEALL 0xe /* ${var//pattern/replacement} */
495 static const char dolatstr[] ALIGN1 = {
496 CTLVAR, VSNORMAL|VSQUOTE, '@', '=', '\0'
529 smallint type; /* Nxxxx */
532 union node *redirect;
537 smallint pipe_backgnd;
538 struct nodelist *cmdlist;
544 union node *redirect;
557 union node *elsepart;
584 struct nodelist *backquote;
597 union node *next; /* must match nfile's layout */
598 int fd; /* must match nfile's layout */
619 struct nredir nredir;
620 struct nbinary nbinary;
624 struct nclist nclist;
633 struct nodelist *next;
646 freefunc(struct funcnode *f)
648 if (f && --f->count < 0)
653 /* ============ Debugging output */
657 static FILE *tracefile;
660 trace_printf(const char *fmt, ...)
667 vfprintf(tracefile, fmt, va);
672 trace_vprintf(const char *fmt, va_list va)
676 vfprintf(tracefile, fmt, va);
680 trace_puts(const char *s)
688 trace_puts_quoted(char *s)
695 putc('"', tracefile);
696 for (p = s; *p; p++) {
698 case '\n': c = 'n'; goto backslash;
699 case '\t': c = 't'; goto backslash;
700 case '\r': c = 'r'; goto backslash;
701 case '"': c = '"'; goto backslash;
702 case '\\': c = '\\'; goto backslash;
703 case CTLESC: c = 'e'; goto backslash;
704 case CTLVAR: c = 'v'; goto backslash;
705 case CTLVAR+CTLQUOTE: c = 'V'; goto backslash;
706 case CTLBACKQ: c = 'q'; goto backslash;
707 case CTLBACKQ+CTLQUOTE: c = 'Q'; goto backslash;
709 putc('\\', tracefile);
713 if (*p >= ' ' && *p <= '~')
716 putc('\\', tracefile);
717 putc(*p >> 6 & 03, tracefile);
718 putc(*p >> 3 & 07, tracefile);
719 putc(*p & 07, tracefile);
724 putc('"', tracefile);
728 trace_puts_args(char **ap)
735 trace_puts_quoted(*ap);
737 putc('\n', tracefile);
740 putc(' ', tracefile);
755 /* leave open because libedit might be using it */
758 strcpy(s, "./trace");
760 if (!freopen(s, "a", tracefile)) {
761 fprintf(stderr, "Can't re-open %s\n", s);
766 tracefile = fopen(s, "a");
767 if (tracefile == NULL) {
768 fprintf(stderr, "Can't open %s\n", s);
774 flags = fcntl(fileno(tracefile), F_GETFL);
776 fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND);
778 setlinebuf(tracefile);
779 fputs("\nTracing started.\n", tracefile);
783 indent(int amount, char *pfx, FILE *fp)
787 for (i = 0; i < amount; i++) {
788 if (pfx && i == amount - 1)
794 /* little circular references here... */
795 static void shtree(union node *n, int ind, char *pfx, FILE *fp);
798 sharg(union node *arg, FILE *fp)
801 struct nodelist *bqlist;
804 if (arg->type != NARG) {
805 out1fmt("<node type %d>\n", arg->type);
808 bqlist = arg->narg.backquote;
809 for (p = arg->narg.text; *p; p++) {
818 if (subtype == VSLENGTH)
827 switch (subtype & VSTYPE) {
860 out1fmt("<subtype %d>", subtype);
867 case CTLBACKQ|CTLQUOTE:
870 shtree(bqlist->n, -1, NULL, fp);
881 shcmd(union node *cmd, FILE *fp)
889 for (np = cmd->ncmd.args; np; np = np->narg.next) {
895 for (np = cmd->ncmd.redirect; np; np = np->nfile.next) {
899 switch (np->nfile.type) {
900 case NTO: s = ">>"+1; dftfd = 1; break;
901 case NCLOBBER: s = ">|"; dftfd = 1; break;
902 case NAPPEND: s = ">>"; dftfd = 1; break;
903 case NTOFD: s = ">&"; dftfd = 1; break;
904 case NFROM: s = "<"; break;
905 case NFROMFD: s = "<&"; break;
906 case NFROMTO: s = "<>"; break;
907 default: s = "*error*"; break;
909 if (np->nfile.fd != dftfd)
910 fprintf(fp, "%d", np->nfile.fd);
912 if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) {
913 fprintf(fp, "%d", np->ndup.dupfd);
915 sharg(np->nfile.fname, fp);
922 shtree(union node *n, int ind, char *pfx, FILE *fp)
930 indent(ind, pfx, fp);
941 shtree(n->nbinary.ch1, ind, NULL, fp);
944 shtree(n->nbinary.ch2, ind, NULL, fp);
952 for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
957 if (n->npipe.pipe_backgnd)
963 fprintf(fp, "<node type %d>", n->type);
971 showtree(union node *n)
973 trace_puts("showtree called\n");
974 shtree(n, 1, NULL, stdout);
977 #define TRACE(param) trace_printf param
978 #define TRACEV(param) trace_vprintf param
983 #define TRACEV(param)
988 /* ============ Parser data */
991 * ash_vmsg() needs parsefile->fd, hence parsefile definition is moved up.
994 struct strlist *next;
1001 struct strpush *prev; /* preceding string on stack */
1004 #if ENABLE_ASH_ALIAS
1005 struct alias *ap; /* if push was associated with an alias */
1007 char *string; /* remember the string since it may change */
1011 struct parsefile *prev; /* preceding file on stack */
1012 int linno; /* current line */
1013 int fd; /* file descriptor (or -1 if string) */
1014 int nleft; /* number of chars left in this line */
1015 int lleft; /* number of chars left in this buffer */
1016 char *nextc; /* next char in buffer */
1017 char *buf; /* input buffer */
1018 struct strpush *strpush; /* for pushing strings at this level */
1019 struct strpush basestrpush; /* so pushing one is fast */
1022 static struct parsefile basepf; /* top level input file */
1023 static struct parsefile *g_parsefile = &basepf; /* current input file */
1024 static int startlinno; /* line # where last token started */
1025 static char *commandname; /* currently executing command */
1026 static struct strlist *cmdenviron; /* environment for builtin command */
1027 static uint8_t exitstatus; /* exit status of last command */
1030 /* ============ Message printing */
1033 ash_vmsg(const char *msg, va_list ap)
1035 fprintf(stderr, "%s: ", arg0);
1037 if (strcmp(arg0, commandname))
1038 fprintf(stderr, "%s: ", commandname);
1039 if (!iflag || g_parsefile->fd)
1040 fprintf(stderr, "line %d: ", startlinno);
1042 vfprintf(stderr, msg, ap);
1043 outcslow('\n', stderr);
1047 * Exverror is called to raise the error exception. If the second argument
1048 * is not NULL then error prints an error message using printf style
1049 * formatting. It then raises the error exception.
1051 static void ash_vmsg_and_raise(int, const char *, va_list) NORETURN;
1053 ash_vmsg_and_raise(int cond, const char *msg, va_list ap)
1057 TRACE(("ash_vmsg_and_raise(%d, \"", cond));
1059 TRACE(("\") pid=%d\n", getpid()));
1061 TRACE(("ash_vmsg_and_raise(%d, NULL) pid=%d\n", cond, getpid()));
1066 flush_stdout_stderr();
1067 raise_exception(cond);
1071 static void ash_msg_and_raise_error(const char *, ...) NORETURN;
1073 ash_msg_and_raise_error(const char *msg, ...)
1078 ash_vmsg_and_raise(EXERROR, msg, ap);
1083 static void ash_msg_and_raise(int, const char *, ...) NORETURN;
1085 ash_msg_and_raise(int cond, const char *msg, ...)
1090 ash_vmsg_and_raise(cond, msg, ap);
1096 * error/warning routines for external builtins
1099 ash_msg(const char *fmt, ...)
1109 * Return a string describing an error. The returned string may be a
1110 * pointer to a static buffer that will be overwritten on the next call.
1111 * Action describes the operation that got the error.
1114 errmsg(int e, const char *em)
1116 if (e == ENOENT || e == ENOTDIR) {
1123 /* ============ Memory allocation */
1126 * It appears that grabstackstr() will barf with such alignments
1127 * because stalloc() will return a string allocated in a new stackblock.
1129 #define SHELL_ALIGN(nbytes) (((nbytes) + SHELL_SIZE) & ~SHELL_SIZE)
1131 /* Most machines require the value returned from malloc to be aligned
1132 * in some way. The following macro will get this right
1133 * on many machines. */
1134 SHELL_SIZE = sizeof(union {int i; char *cp; double d; }) - 1,
1135 /* Minimum size of a block */
1136 MINSIZE = SHELL_ALIGN(504),
1139 struct stack_block {
1140 struct stack_block *prev;
1141 char space[MINSIZE];
1145 struct stack_block *stackp;
1148 struct stackmark *marknext;
1152 struct globals_memstack {
1153 struct stack_block *g_stackp; // = &stackbase;
1154 struct stackmark *markp;
1155 char *g_stacknxt; // = stackbase.space;
1156 char *sstrend; // = stackbase.space + MINSIZE;
1157 size_t g_stacknleft; // = MINSIZE;
1158 int herefd; // = -1;
1159 struct stack_block stackbase;
1161 extern struct globals_memstack *const ash_ptr_to_globals_memstack;
1162 #define G_memstack (*ash_ptr_to_globals_memstack)
1163 #define g_stackp (G_memstack.g_stackp )
1164 #define markp (G_memstack.markp )
1165 #define g_stacknxt (G_memstack.g_stacknxt )
1166 #define sstrend (G_memstack.sstrend )
1167 #define g_stacknleft (G_memstack.g_stacknleft)
1168 #define herefd (G_memstack.herefd )
1169 #define stackbase (G_memstack.stackbase )
1170 #define INIT_G_memstack() do { \
1171 (*(struct globals_memstack**)&ash_ptr_to_globals_memstack) = xzalloc(sizeof(G_memstack)); \
1173 g_stackp = &stackbase; \
1174 g_stacknxt = stackbase.space; \
1175 g_stacknleft = MINSIZE; \
1176 sstrend = stackbase.space + MINSIZE; \
1180 #define stackblock() ((void *)g_stacknxt)
1181 #define stackblocksize() g_stacknleft
1185 ckrealloc(void * p, size_t nbytes)
1187 p = realloc(p, nbytes);
1189 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1194 ckmalloc(size_t nbytes)
1196 return ckrealloc(NULL, nbytes);
1200 ckzalloc(size_t nbytes)
1202 return memset(ckmalloc(nbytes), 0, nbytes);
1206 * Make a copy of a string in safe storage.
1209 ckstrdup(const char *s)
1211 char *p = strdup(s);
1213 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1218 * Parse trees for commands are allocated in lifo order, so we use a stack
1219 * to make this more efficient, and also to avoid all sorts of exception
1220 * handling code to handle interrupts in the middle of a parse.
1222 * The size 504 was chosen because the Ultrix malloc handles that size
1226 stalloc(size_t nbytes)
1231 aligned = SHELL_ALIGN(nbytes);
1232 if (aligned > g_stacknleft) {
1235 struct stack_block *sp;
1237 blocksize = aligned;
1238 if (blocksize < MINSIZE)
1239 blocksize = MINSIZE;
1240 len = sizeof(struct stack_block) - MINSIZE + blocksize;
1241 if (len < blocksize)
1242 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1245 sp->prev = g_stackp;
1246 g_stacknxt = sp->space;
1247 g_stacknleft = blocksize;
1248 sstrend = g_stacknxt + blocksize;
1253 g_stacknxt += aligned;
1254 g_stacknleft -= aligned;
1259 stzalloc(size_t nbytes)
1261 return memset(stalloc(nbytes), 0, nbytes);
1268 if (!p || (g_stacknxt < (char *)p) || ((char *)p < g_stackp->space)) {
1269 write(STDERR_FILENO, "stunalloc\n", 10);
1273 g_stacknleft += g_stacknxt - (char *)p;
1278 * Like strdup but works with the ash stack.
1281 ststrdup(const char *p)
1283 size_t len = strlen(p) + 1;
1284 return memcpy(stalloc(len), p, len);
1288 setstackmark(struct stackmark *mark)
1290 mark->stackp = g_stackp;
1291 mark->stacknxt = g_stacknxt;
1292 mark->stacknleft = g_stacknleft;
1293 mark->marknext = markp;
1298 popstackmark(struct stackmark *mark)
1300 struct stack_block *sp;
1306 markp = mark->marknext;
1307 while (g_stackp != mark->stackp) {
1309 g_stackp = sp->prev;
1312 g_stacknxt = mark->stacknxt;
1313 g_stacknleft = mark->stacknleft;
1314 sstrend = mark->stacknxt + mark->stacknleft;
1319 * When the parser reads in a string, it wants to stick the string on the
1320 * stack and only adjust the stack pointer when it knows how big the
1321 * string is. Stackblock (defined in stack.h) returns a pointer to a block
1322 * of space on top of the stack and stackblocklen returns the length of
1323 * this block. Growstackblock will grow this space by at least one byte,
1324 * possibly moving it (like realloc). Grabstackblock actually allocates the
1325 * part of the block that has been used.
1328 growstackblock(void)
1332 newlen = g_stacknleft * 2;
1333 if (newlen < g_stacknleft)
1334 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1338 if (g_stacknxt == g_stackp->space && g_stackp != &stackbase) {
1339 struct stack_block *oldstackp;
1340 struct stackmark *xmark;
1341 struct stack_block *sp;
1342 struct stack_block *prevstackp;
1346 oldstackp = g_stackp;
1348 prevstackp = sp->prev;
1349 grosslen = newlen + sizeof(struct stack_block) - MINSIZE;
1350 sp = ckrealloc(sp, grosslen);
1351 sp->prev = prevstackp;
1353 g_stacknxt = sp->space;
1354 g_stacknleft = newlen;
1355 sstrend = sp->space + newlen;
1358 * Stack marks pointing to the start of the old block
1359 * must be relocated to point to the new block
1362 while (xmark != NULL && xmark->stackp == oldstackp) {
1363 xmark->stackp = g_stackp;
1364 xmark->stacknxt = g_stacknxt;
1365 xmark->stacknleft = g_stacknleft;
1366 xmark = xmark->marknext;
1370 char *oldspace = g_stacknxt;
1371 size_t oldlen = g_stacknleft;
1372 char *p = stalloc(newlen);
1374 /* free the space we just allocated */
1375 g_stacknxt = memcpy(p, oldspace, oldlen);
1376 g_stacknleft += newlen;
1381 grabstackblock(size_t len)
1383 len = SHELL_ALIGN(len);
1385 g_stacknleft -= len;
1389 * The following routines are somewhat easier to use than the above.
1390 * The user declares a variable of type STACKSTR, which may be declared
1391 * to be a register. The macro STARTSTACKSTR initializes things. Then
1392 * the user uses the macro STPUTC to add characters to the string. In
1393 * effect, STPUTC(c, p) is the same as *p++ = c except that the stack is
1394 * grown as necessary. When the user is done, she can just leave the
1395 * string there and refer to it using stackblock(). Or she can allocate
1396 * the space for it using grabstackstr(). If it is necessary to allow
1397 * someone else to use the stack temporarily and then continue to grow
1398 * the string, the user should use grabstack to allocate the space, and
1399 * then call ungrabstr(p) to return to the previous mode of operation.
1401 * USTPUTC is like STPUTC except that it doesn't check for overflow.
1402 * CHECKSTACKSPACE can be called before USTPUTC to ensure that there
1403 * is space for at least one character.
1408 size_t len = stackblocksize();
1409 if (herefd >= 0 && len >= 1024) {
1410 full_write(herefd, stackblock(), len);
1411 return stackblock();
1414 return (char *)stackblock() + len;
1418 * Called from CHECKSTRSPACE.
1421 makestrspace(size_t newlen, char *p)
1423 size_t len = p - g_stacknxt;
1424 size_t size = stackblocksize();
1429 size = stackblocksize();
1431 if (nleft >= newlen)
1435 return (char *)stackblock() + len;
1439 stack_nputstr(const char *s, size_t n, char *p)
1441 p = makestrspace(n, p);
1442 p = (char *)memcpy(p, s, n) + n;
1447 stack_putstr(const char *s, char *p)
1449 return stack_nputstr(s, strlen(s), p);
1453 _STPUTC(int c, char *p)
1461 #define STARTSTACKSTR(p) ((p) = stackblock())
1462 #define STPUTC(c, p) ((p) = _STPUTC((c), (p)))
1463 #define CHECKSTRSPACE(n, p) do { \
1466 size_t m = sstrend - q; \
1468 (p) = makestrspace(l, q); \
1470 #define USTPUTC(c, p) (*(p)++ = (c))
1471 #define STACKSTRNUL(p) do { \
1472 if ((p) == sstrend) \
1473 (p) = growstackstr(); \
1476 #define STUNPUTC(p) (--(p))
1477 #define STTOPC(p) ((p)[-1])
1478 #define STADJUST(amount, p) ((p) += (amount))
1480 #define grabstackstr(p) stalloc((char *)(p) - (char *)stackblock())
1481 #define ungrabstackstr(s, p) stunalloc(s)
1482 #define stackstrend() ((void *)sstrend)
1485 /* ============ String helpers */
1488 * prefix -- see if pfx is a prefix of string.
1491 prefix(const char *string, const char *pfx)
1494 if (*pfx++ != *string++)
1497 return (char *) string;
1501 * Check for a valid number. This should be elsewhere.
1504 is_number(const char *p)
1509 } while (*++p != '\0');
1514 * Convert a string of digits to an integer, printing an error message on
1518 number(const char *s)
1521 ash_msg_and_raise_error(illnum, s);
1526 * Produce a possibly single quoted string suitable as input to the shell.
1527 * The return string is allocated on the stack.
1530 single_quote(const char *s)
1540 len = strchrnul(s, '\'') - s;
1542 q = p = makestrspace(len + 3, p);
1545 q = (char *)memcpy(q, s, len) + len;
1551 len = strspn(s, "'");
1555 q = p = makestrspace(len + 3, p);
1558 q = (char *)memcpy(q, s, len) + len;
1567 return stackblock();
1571 /* ============ nextopt */
1573 static char **argptr; /* argument list for builtin commands */
1574 static char *optionarg; /* set by nextopt (like getopt) */
1575 static char *optptr; /* used by nextopt */
1578 * XXX - should get rid of. Have all builtins use getopt(3).
1579 * The library getopt must have the BSD extension static variable
1580 * "optreset", otherwise it can't be used within the shell safely.
1582 * Standard option processing (a la getopt) for builtin routines.
1583 * The only argument that is passed to nextopt is the option string;
1584 * the other arguments are unnecessary. It returns the character,
1585 * or '\0' on end of input.
1588 nextopt(const char *optstring)
1595 if (p == NULL || *p == '\0') {
1596 /* We ate entire "-param", take next one */
1602 if (*++p == '\0') /* just "-" ? */
1605 if (LONE_DASH(p)) /* "--" ? */
1607 /* p => next "-param" */
1609 /* p => some option char in the middle of a "-param" */
1611 for (q = optstring; *q != c;) {
1613 ash_msg_and_raise_error("illegal option -%c", c);
1621 ash_msg_and_raise_error("no arg for -%c option", c);
1631 /* ============ Shell variables */
1634 * The parsefile structure pointed to by the global variable parsefile
1635 * contains information about the current file being read.
1638 int nparam; /* # of positional parameters (without $0) */
1639 #if ENABLE_ASH_GETOPTS
1640 int optind; /* next parameter to be processed by getopts */
1641 int optoff; /* used by getopts */
1643 unsigned char malloced; /* if parameter list dynamically allocated */
1644 char **p; /* parameter list */
1648 * Free the list of positional parameters.
1651 freeparam(volatile struct shparam *param)
1653 if (param->malloced) {
1655 ap = ap1 = param->p;
1662 #if ENABLE_ASH_GETOPTS
1663 static void getoptsreset(const char *value);
1667 struct var *next; /* next entry in hash list */
1668 int flags; /* flags are defined above */
1669 const char *text; /* name=value */
1670 void (*func)(const char *); /* function to be called when */
1671 /* the variable gets set/unset */
1675 struct localvar *next; /* next local variable in list */
1676 struct var *vp; /* the variable that was made local */
1677 int flags; /* saved flags */
1678 const char *text; /* saved text */
1682 #define VEXPORT 0x01 /* variable is exported */
1683 #define VREADONLY 0x02 /* variable cannot be modified */
1684 #define VSTRFIXED 0x04 /* variable struct is statically allocated */
1685 #define VTEXTFIXED 0x08 /* text is statically allocated */
1686 #define VSTACK 0x10 /* text is allocated on the stack */
1687 #define VUNSET 0x20 /* the variable is not set */
1688 #define VNOFUNC 0x40 /* don't call the callback function */
1689 #define VNOSET 0x80 /* do not set variable - just readonly test */
1690 #define VNOSAVE 0x100 /* when text is on the heap before setvareq */
1691 #if ENABLE_ASH_RANDOM_SUPPORT
1692 # define VDYNAMIC 0x200 /* dynamic variable */
1698 static const char defifsvar[] ALIGN1 = "IFS= \t\n";
1699 #define defifs (defifsvar + 4)
1701 static const char defifs[] ALIGN1 = " \t\n";
1705 /* Need to be before varinit_data[] */
1706 #if ENABLE_LOCALE_SUPPORT
1708 change_lc_all(const char *value)
1710 if (value && *value != '\0')
1711 setlocale(LC_ALL, value);
1714 change_lc_ctype(const char *value)
1716 if (value && *value != '\0')
1717 setlocale(LC_CTYPE, value);
1721 static void chkmail(void);
1722 static void changemail(const char *);
1724 static void changepath(const char *);
1725 #if ENABLE_ASH_RANDOM_SUPPORT
1726 static void change_random(const char *);
1729 static const struct {
1732 void (*func)(const char *);
1733 } varinit_data[] = {
1735 { VSTRFIXED|VTEXTFIXED , defifsvar , NULL },
1737 { VSTRFIXED|VTEXTFIXED|VUNSET, "IFS\0" , NULL },
1740 { VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL\0" , changemail },
1741 { VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH\0", changemail },
1743 { VSTRFIXED|VTEXTFIXED , bb_PATH_root_path, changepath },
1744 { VSTRFIXED|VTEXTFIXED , "PS1=$ " , NULL },
1745 { VSTRFIXED|VTEXTFIXED , "PS2=> " , NULL },
1746 { VSTRFIXED|VTEXTFIXED , "PS4=+ " , NULL },
1747 #if ENABLE_ASH_GETOPTS
1748 { VSTRFIXED|VTEXTFIXED , "OPTIND=1" , getoptsreset },
1750 #if ENABLE_ASH_RANDOM_SUPPORT
1751 { VSTRFIXED|VTEXTFIXED|VUNSET|VDYNAMIC, "RANDOM\0", change_random },
1753 #if ENABLE_LOCALE_SUPPORT
1754 { VSTRFIXED|VTEXTFIXED|VUNSET, "LC_ALL\0" , change_lc_all },
1755 { VSTRFIXED|VTEXTFIXED|VUNSET, "LC_CTYPE\0", change_lc_ctype },
1757 #if ENABLE_FEATURE_EDITING_SAVEHISTORY
1758 { VSTRFIXED|VTEXTFIXED|VUNSET, "HISTFILE\0", NULL },
1764 struct globals_var {
1765 struct shparam shellparam; /* $@ current positional parameters */
1766 struct redirtab *redirlist;
1768 int preverrout_fd; /* save fd2 before print debug if xflag is set. */
1769 struct var *vartab[VTABSIZE];
1770 struct var varinit[ARRAY_SIZE(varinit_data)];
1772 extern struct globals_var *const ash_ptr_to_globals_var;
1773 #define G_var (*ash_ptr_to_globals_var)
1774 #define shellparam (G_var.shellparam )
1775 //#define redirlist (G_var.redirlist )
1776 #define g_nullredirs (G_var.g_nullredirs )
1777 #define preverrout_fd (G_var.preverrout_fd)
1778 #define vartab (G_var.vartab )
1779 #define varinit (G_var.varinit )
1780 #define INIT_G_var() do { \
1782 (*(struct globals_var**)&ash_ptr_to_globals_var) = xzalloc(sizeof(G_var)); \
1784 for (i = 0; i < ARRAY_SIZE(varinit_data); i++) { \
1785 varinit[i].flags = varinit_data[i].flags; \
1786 varinit[i].text = varinit_data[i].text; \
1787 varinit[i].func = varinit_data[i].func; \
1791 #define vifs varinit[0]
1793 # define vmail (&vifs)[1]
1794 # define vmpath (&vmail)[1]
1795 # define vpath (&vmpath)[1]
1797 # define vpath (&vifs)[1]
1799 #define vps1 (&vpath)[1]
1800 #define vps2 (&vps1)[1]
1801 #define vps4 (&vps2)[1]
1802 #if ENABLE_ASH_GETOPTS
1803 # define voptind (&vps4)[1]
1804 # if ENABLE_ASH_RANDOM_SUPPORT
1805 # define vrandom (&voptind)[1]
1808 # if ENABLE_ASH_RANDOM_SUPPORT
1809 # define vrandom (&vps4)[1]
1814 * The following macros access the values of the above variables.
1815 * They have to skip over the name. They return the null string
1816 * for unset variables.
1818 #define ifsval() (vifs.text + 4)
1819 #define ifsset() ((vifs.flags & VUNSET) == 0)
1821 # define mailval() (vmail.text + 5)
1822 # define mpathval() (vmpath.text + 9)
1823 # define mpathset() ((vmpath.flags & VUNSET) == 0)
1825 #define pathval() (vpath.text + 5)
1826 #define ps1val() (vps1.text + 4)
1827 #define ps2val() (vps2.text + 4)
1828 #define ps4val() (vps4.text + 4)
1829 #if ENABLE_ASH_GETOPTS
1830 # define optindval() (voptind.text + 7)
1834 #define is_name(c) ((c) == '_' || isalpha((unsigned char)(c)))
1835 #define is_in_name(c) ((c) == '_' || isalnum((unsigned char)(c)))
1837 #if ENABLE_ASH_GETOPTS
1839 getoptsreset(const char *value)
1841 shellparam.optind = number(value);
1842 shellparam.optoff = -1;
1847 * Return of a legal variable name (a letter or underscore followed by zero or
1848 * more letters, underscores, and digits).
1851 endofname(const char *name)
1859 if (!is_in_name(*p))
1866 * Compares two strings up to the first = or '\0'. The first
1867 * string must be terminated by '='; the second may be terminated by
1868 * either '=' or '\0'.
1871 varcmp(const char *p, const char *q)
1875 while ((c = *p) == (d = *q)) {
1890 varequal(const char *a, const char *b)
1892 return !varcmp(a, b);
1896 * Find the appropriate entry in the hash table from the name.
1898 static struct var **
1899 hashvar(const char *p)
1903 hashval = ((unsigned char) *p) << 4;
1904 while (*p && *p != '=')
1905 hashval += (unsigned char) *p++;
1906 return &vartab[hashval % VTABSIZE];
1910 vpcmp(const void *a, const void *b)
1912 return varcmp(*(const char **)a, *(const char **)b);
1916 * This routine initializes the builtin variables.
1926 * PS1 depends on uid
1928 #if ENABLE_FEATURE_EDITING && ENABLE_FEATURE_EDITING_FANCY_PROMPT
1929 vps1.text = "PS1=\\w \\$ ";
1932 vps1.text = "PS1=# ";
1935 end = vp + ARRAY_SIZE(varinit);
1937 vpp = hashvar(vp->text);
1940 } while (++vp < end);
1943 static struct var **
1944 findvar(struct var **vpp, const char *name)
1946 for (; *vpp; vpp = &(*vpp)->next) {
1947 if (varequal((*vpp)->text, name)) {
1955 * Find the value of a variable. Returns NULL if not set.
1958 lookupvar(const char *name)
1962 v = *findvar(hashvar(name), name);
1964 #if ENABLE_ASH_RANDOM_SUPPORT
1966 * Dynamic variables are implemented roughly the same way they are
1967 * in bash. Namely, they're "special" so long as they aren't unset.
1968 * As soon as they're unset, they're no longer dynamic, and dynamic
1969 * lookup will no longer happen at that point. -- PFM.
1971 if ((v->flags & VDYNAMIC))
1974 if (!(v->flags & VUNSET))
1975 return strchrnul(v->text, '=') + 1;
1981 * Search the environment of a builtin command.
1984 bltinlookup(const char *name)
1988 for (sp = cmdenviron; sp; sp = sp->next) {
1989 if (varequal(sp->text, name))
1990 return strchrnul(sp->text, '=') + 1;
1992 return lookupvar(name);
1996 * Same as setvar except that the variable and value are passed in
1997 * the first argument as name=value. Since the first argument will
1998 * be actually stored in the table, it should not be a string that
2000 * Called with interrupts off.
2003 setvareq(char *s, int flags)
2005 struct var *vp, **vpp;
2008 flags |= (VEXPORT & (((unsigned) (1 - aflag)) - 1));
2009 vp = *findvar(vpp, s);
2011 if ((vp->flags & (VREADONLY|VDYNAMIC)) == VREADONLY) {
2014 if (flags & VNOSAVE)
2017 ash_msg_and_raise_error("%.*s: is read only", strchrnul(n, '=') - n, n);
2023 if (vp->func && (flags & VNOFUNC) == 0)
2024 (*vp->func)(strchrnul(s, '=') + 1);
2026 if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
2027 free((char*)vp->text);
2029 flags |= vp->flags & ~(VTEXTFIXED|VSTACK|VNOSAVE|VUNSET);
2034 vp = ckzalloc(sizeof(*vp));
2036 /*vp->func = NULL; - ckzalloc did it */
2039 if (!(flags & (VTEXTFIXED|VSTACK|VNOSAVE)))
2046 * Set the value of a variable. The flags argument is ored with the
2047 * flags of the variable. If val is NULL, the variable is unset.
2050 setvar(const char *name, const char *val, int flags)
2057 q = endofname(name);
2058 p = strchrnul(q, '=');
2060 if (!namelen || p != q)
2061 ash_msg_and_raise_error("%.*s: bad variable name", namelen, name);
2066 vallen = strlen(val);
2069 nameeq = ckmalloc(namelen + vallen + 2);
2070 p = (char *)memcpy(nameeq, name, namelen) + namelen;
2073 p = (char *)memcpy(p, val, vallen) + vallen;
2076 setvareq(nameeq, flags | VNOSAVE);
2080 #if ENABLE_ASH_GETOPTS
2082 * Safe version of setvar, returns 1 on success 0 on failure.
2085 setvarsafe(const char *name, const char *val, int flags)
2088 volatile int saveint;
2089 struct jmploc *volatile savehandler = exception_handler;
2090 struct jmploc jmploc;
2093 if (setjmp(jmploc.loc))
2096 exception_handler = &jmploc;
2097 setvar(name, val, flags);
2100 exception_handler = savehandler;
2101 RESTORE_INT(saveint);
2107 * Unset the specified variable.
2110 unsetvar(const char *s)
2116 vpp = findvar(hashvar(s), s);
2120 int flags = vp->flags;
2123 if (flags & VREADONLY)
2125 #if ENABLE_ASH_RANDOM_SUPPORT
2126 vp->flags &= ~VDYNAMIC;
2130 if ((flags & VSTRFIXED) == 0) {
2132 if ((flags & (VTEXTFIXED|VSTACK)) == 0)
2133 free((char*)vp->text);
2139 vp->flags &= ~VEXPORT;
2149 * Process a linked list of variable assignments.
2152 listsetvar(struct strlist *list_set_var, int flags)
2154 struct strlist *lp = list_set_var;
2160 setvareq(lp->text, flags);
2167 * Generate a list of variables satisfying the given conditions.
2170 listvars(int on, int off, char ***end)
2181 for (vp = *vpp; vp; vp = vp->next) {
2182 if ((vp->flags & mask) == on) {
2183 if (ep == stackstrend())
2184 ep = growstackstr();
2185 *ep++ = (char *) vp->text;
2188 } while (++vpp < vartab + VTABSIZE);
2189 if (ep == stackstrend())
2190 ep = growstackstr();
2194 return grabstackstr(ep);
2198 /* ============ Path search helper
2200 * The variable path (passed by reference) should be set to the start
2201 * of the path before the first call; padvance will update
2202 * this value as it proceeds. Successive calls to padvance will return
2203 * the possible path expansions in sequence. If an option (indicated by
2204 * a percent sign) appears in the path entry then the global variable
2205 * pathopt will be set to point to it; otherwise pathopt will be set to
2208 static const char *pathopt; /* set by padvance */
2211 padvance(const char **path, const char *name)
2221 for (p = start; *p && *p != ':' && *p != '%'; p++)
2223 len = p - start + strlen(name) + 2; /* "2" is for '/' and '\0' */
2224 while (stackblocksize() < len)
2228 memcpy(q, start, p - start);
2236 while (*p && *p != ':')
2243 return stalloc(len);
2247 /* ============ Prompt */
2249 static smallint doprompt; /* if set, prompt the user */
2250 static smallint needprompt; /* true if interactive and at start of line */
2252 #if ENABLE_FEATURE_EDITING
2253 static line_input_t *line_input_state;
2254 static const char *cmdedit_prompt;
2256 putprompt(const char *s)
2258 if (ENABLE_ASH_EXPAND_PRMT) {
2259 free((char*)cmdedit_prompt);
2260 cmdedit_prompt = ckstrdup(s);
2267 putprompt(const char *s)
2273 #if ENABLE_ASH_EXPAND_PRMT
2274 /* expandstr() needs parsing machinery, so it is far away ahead... */
2275 static const char *expandstr(const char *ps);
2277 #define expandstr(s) s
2281 setprompt(int whichprompt)
2284 #if ENABLE_ASH_EXPAND_PRMT
2285 struct stackmark smark;
2290 switch (whichprompt) {
2300 #if ENABLE_ASH_EXPAND_PRMT
2301 setstackmark(&smark);
2302 stalloc(stackblocksize());
2304 putprompt(expandstr(prompt));
2305 #if ENABLE_ASH_EXPAND_PRMT
2306 popstackmark(&smark);
2311 /* ============ The cd and pwd commands */
2313 #define CD_PHYSICAL 1
2316 static int docd(const char *, int);
2325 while ((i = nextopt("LP"))) {
2327 flags ^= CD_PHYSICAL;
2336 * Update curdir (the name of the current directory) in response to a
2340 updatepwd(const char *dir)
2347 cdcomppath = ststrdup(dir);
2350 if (curdir == nullstr)
2352 new = stack_putstr(curdir, new);
2354 new = makestrspace(strlen(dir) + 2, new);
2355 lim = (char *)stackblock() + 1;
2359 if (new > lim && *lim == '/')
2364 if (dir[1] == '/' && dir[2] != '/') {
2370 p = strtok(cdcomppath, "/");
2374 if (p[1] == '.' && p[2] == '\0') {
2386 new = stack_putstr(p, new);
2394 return stackblock();
2398 * Find out what the current directory is. If we already know the current
2399 * directory, this routine returns immediately.
2404 char *dir = getcwd(NULL, 0); /* huh, using glibc extension? */
2405 return dir ? dir : nullstr;
2409 setpwd(const char *val, int setold)
2413 oldcur = dir = curdir;
2416 setvar("OLDPWD", oldcur, VEXPORT);
2419 if (physdir != nullstr) {
2420 if (physdir != oldcur)
2424 if (oldcur == val || !val) {
2430 dir = ckstrdup(val);
2431 if (oldcur != dir && oldcur != nullstr) {
2436 setvar("PWD", dir, VEXPORT);
2439 static void hashcd(void);
2442 * Actually do the chdir. We also call hashcd to let the routines in exec.c
2443 * know that the current directory has changed.
2446 docd(const char *dest, int flags)
2448 const char *dir = 0;
2451 TRACE(("docd(\"%s\", %d) called\n", dest, flags));
2454 if (!(flags & CD_PHYSICAL)) {
2455 dir = updatepwd(dest);
2470 cdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
2482 dest = bltinlookup(homestr);
2483 else if (LONE_DASH(dest)) {
2484 dest = bltinlookup("OLDPWD");
2506 path = bltinlookup("CDPATH");
2515 p = padvance(&path, dest);
2516 if (stat(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) {
2520 if (!docd(p, flags))
2525 ash_msg_and_raise_error("can't cd to %s", dest);
2528 if (flags & CD_PRINT)
2529 out1fmt(snlfmt, curdir);
2534 pwdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
2537 const char *dir = curdir;
2541 if (physdir == nullstr)
2545 out1fmt(snlfmt, dir);
2550 /* ============ ... */
2552 #define IBUFSIZ COMMON_BUFSIZE
2553 #define basebuf bb_common_bufsiz1 /* buffer for top level input file */
2555 /* Syntax classes */
2556 #define CWORD 0 /* character is nothing special */
2557 #define CNL 1 /* newline character */
2558 #define CBACK 2 /* a backslash character */
2559 #define CSQUOTE 3 /* single quote */
2560 #define CDQUOTE 4 /* double quote */
2561 #define CENDQUOTE 5 /* a terminating quote */
2562 #define CBQUOTE 6 /* backwards single quote */
2563 #define CVAR 7 /* a dollar sign */
2564 #define CENDVAR 8 /* a '}' character */
2565 #define CLP 9 /* a left paren in arithmetic */
2566 #define CRP 10 /* a right paren in arithmetic */
2567 #define CENDFILE 11 /* end of file */
2568 #define CCTL 12 /* like CWORD, except it must be escaped */
2569 #define CSPCL 13 /* these terminate a word */
2570 #define CIGN 14 /* character should be ignored */
2572 #if ENABLE_ASH_ALIAS
2576 #define PEOA_OR_PEOF PEOA
2580 #define PEOA_OR_PEOF PEOF
2583 /* number syntax index */
2584 #define BASESYNTAX 0 /* not in quotes */
2585 #define DQSYNTAX 1 /* in double quotes */
2586 #define SQSYNTAX 2 /* in single quotes */
2587 #define ARISYNTAX 3 /* in arithmetic */
2588 #define PSSYNTAX 4 /* prompt */
2590 #if ENABLE_ASH_OPTIMIZE_FOR_SIZE
2591 #define USE_SIT_FUNCTION
2594 #if ENABLE_ASH_MATH_SUPPORT
2595 static const char S_I_T[][4] = {
2596 #if ENABLE_ASH_ALIAS
2597 { CSPCL, CIGN, CIGN, CIGN }, /* 0, PEOA */
2599 { CSPCL, CWORD, CWORD, CWORD }, /* 1, ' ' */
2600 { CNL, CNL, CNL, CNL }, /* 2, \n */
2601 { CWORD, CCTL, CCTL, CWORD }, /* 3, !*-/:=?[]~ */
2602 { CDQUOTE, CENDQUOTE, CWORD, CWORD }, /* 4, '"' */
2603 { CVAR, CVAR, CWORD, CVAR }, /* 5, $ */
2604 { CSQUOTE, CWORD, CENDQUOTE, CWORD }, /* 6, "'" */
2605 { CSPCL, CWORD, CWORD, CLP }, /* 7, ( */
2606 { CSPCL, CWORD, CWORD, CRP }, /* 8, ) */
2607 { CBACK, CBACK, CCTL, CBACK }, /* 9, \ */
2608 { CBQUOTE, CBQUOTE, CWORD, CBQUOTE }, /* 10, ` */
2609 { CENDVAR, CENDVAR, CWORD, CENDVAR }, /* 11, } */
2610 #ifndef USE_SIT_FUNCTION
2611 { CENDFILE, CENDFILE, CENDFILE, CENDFILE }, /* 12, PEOF */
2612 { CWORD, CWORD, CWORD, CWORD }, /* 13, 0-9A-Za-z */
2613 { CCTL, CCTL, CCTL, CCTL } /* 14, CTLESC ... */
2617 static const char S_I_T[][3] = {
2618 #if ENABLE_ASH_ALIAS
2619 { CSPCL, CIGN, CIGN }, /* 0, PEOA */
2621 { CSPCL, CWORD, CWORD }, /* 1, ' ' */
2622 { CNL, CNL, CNL }, /* 2, \n */
2623 { CWORD, CCTL, CCTL }, /* 3, !*-/:=?[]~ */
2624 { CDQUOTE, CENDQUOTE, CWORD }, /* 4, '"' */
2625 { CVAR, CVAR, CWORD }, /* 5, $ */
2626 { CSQUOTE, CWORD, CENDQUOTE }, /* 6, "'" */
2627 { CSPCL, CWORD, CWORD }, /* 7, ( */
2628 { CSPCL, CWORD, CWORD }, /* 8, ) */
2629 { CBACK, CBACK, CCTL }, /* 9, \ */
2630 { CBQUOTE, CBQUOTE, CWORD }, /* 10, ` */
2631 { CENDVAR, CENDVAR, CWORD }, /* 11, } */
2632 #ifndef USE_SIT_FUNCTION
2633 { CENDFILE, CENDFILE, CENDFILE }, /* 12, PEOF */
2634 { CWORD, CWORD, CWORD }, /* 13, 0-9A-Za-z */
2635 { CCTL, CCTL, CCTL } /* 14, CTLESC ... */
2638 #endif /* ASH_MATH_SUPPORT */
2640 #ifdef USE_SIT_FUNCTION
2643 SIT(int c, int syntax)
2645 static const char spec_symbls[] ALIGN1 = "\t\n !\"$&'()*-/:;<=>?[\\]`|}~";
2646 #if ENABLE_ASH_ALIAS
2647 static const char syntax_index_table[] ALIGN1 = {
2648 1, 2, 1, 3, 4, 5, 1, 6, /* "\t\n !\"$&'" */
2649 7, 8, 3, 3, 3, 3, 1, 1, /* "()*-/:;<" */
2650 3, 1, 3, 3, 9, 3, 10, 1, /* "=>?[\\]`|" */
2654 static const char syntax_index_table[] ALIGN1 = {
2655 0, 1, 0, 2, 3, 4, 0, 5, /* "\t\n !\"$&'" */
2656 6, 7, 2, 2, 2, 2, 0, 0, /* "()*-/:;<" */
2657 2, 0, 2, 2, 8, 2, 9, 0, /* "=>?[\\]`|" */
2664 if (c == PEOF) /* 2^8+2 */
2666 #if ENABLE_ASH_ALIAS
2667 if (c == PEOA) /* 2^8+1 */
2671 #define U_C(c) ((unsigned char)(c))
2673 if ((unsigned char)c >= (unsigned char)(CTLESC)
2674 && (unsigned char)c <= (unsigned char)(CTLQUOTEMARK)
2678 s = strchrnul(spec_symbls, c);
2681 indx = syntax_index_table[s - spec_symbls];
2683 return S_I_T[indx][syntax];
2686 #else /* !USE_SIT_FUNCTION */
2688 #if ENABLE_ASH_ALIAS
2689 #define CSPCL_CIGN_CIGN_CIGN 0
2690 #define CSPCL_CWORD_CWORD_CWORD 1
2691 #define CNL_CNL_CNL_CNL 2
2692 #define CWORD_CCTL_CCTL_CWORD 3
2693 #define CDQUOTE_CENDQUOTE_CWORD_CWORD 4
2694 #define CVAR_CVAR_CWORD_CVAR 5
2695 #define CSQUOTE_CWORD_CENDQUOTE_CWORD 6
2696 #define CSPCL_CWORD_CWORD_CLP 7
2697 #define CSPCL_CWORD_CWORD_CRP 8
2698 #define CBACK_CBACK_CCTL_CBACK 9
2699 #define CBQUOTE_CBQUOTE_CWORD_CBQUOTE 10
2700 #define CENDVAR_CENDVAR_CWORD_CENDVAR 11
2701 #define CENDFILE_CENDFILE_CENDFILE_CENDFILE 12
2702 #define CWORD_CWORD_CWORD_CWORD 13
2703 #define CCTL_CCTL_CCTL_CCTL 14
2705 #define CSPCL_CWORD_CWORD_CWORD 0
2706 #define CNL_CNL_CNL_CNL 1
2707 #define CWORD_CCTL_CCTL_CWORD 2
2708 #define CDQUOTE_CENDQUOTE_CWORD_CWORD 3
2709 #define CVAR_CVAR_CWORD_CVAR 4
2710 #define CSQUOTE_CWORD_CENDQUOTE_CWORD 5
2711 #define CSPCL_CWORD_CWORD_CLP 6
2712 #define CSPCL_CWORD_CWORD_CRP 7
2713 #define CBACK_CBACK_CCTL_CBACK 8
2714 #define CBQUOTE_CBQUOTE_CWORD_CBQUOTE 9
2715 #define CENDVAR_CENDVAR_CWORD_CENDVAR 10
2716 #define CENDFILE_CENDFILE_CENDFILE_CENDFILE 11
2717 #define CWORD_CWORD_CWORD_CWORD 12
2718 #define CCTL_CCTL_CCTL_CCTL 13
2721 static const char syntax_index_table[258] = {
2722 /* BASESYNTAX_DQSYNTAX_SQSYNTAX_ARISYNTAX */
2723 /* 0 PEOF */ CENDFILE_CENDFILE_CENDFILE_CENDFILE,
2724 #if ENABLE_ASH_ALIAS
2725 /* 1 PEOA */ CSPCL_CIGN_CIGN_CIGN,
2727 /* 2 -128 0x80 */ CWORD_CWORD_CWORD_CWORD,
2728 /* 3 -127 CTLESC */ CCTL_CCTL_CCTL_CCTL,
2729 /* 4 -126 CTLVAR */ CCTL_CCTL_CCTL_CCTL,
2730 /* 5 -125 CTLENDVAR */ CCTL_CCTL_CCTL_CCTL,
2731 /* 6 -124 CTLBACKQ */ CCTL_CCTL_CCTL_CCTL,
2732 /* 7 -123 CTLQUOTE */ CCTL_CCTL_CCTL_CCTL,
2733 /* 8 -122 CTLARI */ CCTL_CCTL_CCTL_CCTL,
2734 /* 9 -121 CTLENDARI */ CCTL_CCTL_CCTL_CCTL,
2735 /* 10 -120 CTLQUOTEMARK */ CCTL_CCTL_CCTL_CCTL,
2736 /* 11 -119 */ CWORD_CWORD_CWORD_CWORD,
2737 /* 12 -118 */ CWORD_CWORD_CWORD_CWORD,
2738 /* 13 -117 */ CWORD_CWORD_CWORD_CWORD,
2739 /* 14 -116 */ CWORD_CWORD_CWORD_CWORD,
2740 /* 15 -115 */ CWORD_CWORD_CWORD_CWORD,
2741 /* 16 -114 */ CWORD_CWORD_CWORD_CWORD,
2742 /* 17 -113 */ CWORD_CWORD_CWORD_CWORD,
2743 /* 18 -112 */ CWORD_CWORD_CWORD_CWORD,
2744 /* 19 -111 */ CWORD_CWORD_CWORD_CWORD,
2745 /* 20 -110 */ CWORD_CWORD_CWORD_CWORD,
2746 /* 21 -109 */ CWORD_CWORD_CWORD_CWORD,
2747 /* 22 -108 */ CWORD_CWORD_CWORD_CWORD,
2748 /* 23 -107 */ CWORD_CWORD_CWORD_CWORD,
2749 /* 24 -106 */ CWORD_CWORD_CWORD_CWORD,
2750 /* 25 -105 */ CWORD_CWORD_CWORD_CWORD,
2751 /* 26 -104 */ CWORD_CWORD_CWORD_CWORD,
2752 /* 27 -103 */ CWORD_CWORD_CWORD_CWORD,
2753 /* 28 -102 */ CWORD_CWORD_CWORD_CWORD,
2754 /* 29 -101 */ CWORD_CWORD_CWORD_CWORD,
2755 /* 30 -100 */ CWORD_CWORD_CWORD_CWORD,
2756 /* 31 -99 */ CWORD_CWORD_CWORD_CWORD,
2757 /* 32 -98 */ CWORD_CWORD_CWORD_CWORD,
2758 /* 33 -97 */ CWORD_CWORD_CWORD_CWORD,
2759 /* 34 -96 */ CWORD_CWORD_CWORD_CWORD,
2760 /* 35 -95 */ CWORD_CWORD_CWORD_CWORD,
2761 /* 36 -94 */ CWORD_CWORD_CWORD_CWORD,
2762 /* 37 -93 */ CWORD_CWORD_CWORD_CWORD,
2763 /* 38 -92 */ CWORD_CWORD_CWORD_CWORD,
2764 /* 39 -91 */ CWORD_CWORD_CWORD_CWORD,
2765 /* 40 -90 */ CWORD_CWORD_CWORD_CWORD,
2766 /* 41 -89 */ CWORD_CWORD_CWORD_CWORD,
2767 /* 42 -88 */ CWORD_CWORD_CWORD_CWORD,
2768 /* 43 -87 */ CWORD_CWORD_CWORD_CWORD,
2769 /* 44 -86 */ CWORD_CWORD_CWORD_CWORD,
2770 /* 45 -85 */ CWORD_CWORD_CWORD_CWORD,
2771 /* 46 -84 */ CWORD_CWORD_CWORD_CWORD,
2772 /* 47 -83 */ CWORD_CWORD_CWORD_CWORD,
2773 /* 48 -82 */ CWORD_CWORD_CWORD_CWORD,
2774 /* 49 -81 */ CWORD_CWORD_CWORD_CWORD,
2775 /* 50 -80 */ CWORD_CWORD_CWORD_CWORD,
2776 /* 51 -79 */ CWORD_CWORD_CWORD_CWORD,
2777 /* 52 -78 */ CWORD_CWORD_CWORD_CWORD,
2778 /* 53 -77 */ CWORD_CWORD_CWORD_CWORD,
2779 /* 54 -76 */ CWORD_CWORD_CWORD_CWORD,
2780 /* 55 -75 */ CWORD_CWORD_CWORD_CWORD,
2781 /* 56 -74 */ CWORD_CWORD_CWORD_CWORD,
2782 /* 57 -73 */ CWORD_CWORD_CWORD_CWORD,
2783 /* 58 -72 */ CWORD_CWORD_CWORD_CWORD,
2784 /* 59 -71 */ CWORD_CWORD_CWORD_CWORD,
2785 /* 60 -70 */ CWORD_CWORD_CWORD_CWORD,
2786 /* 61 -69 */ CWORD_CWORD_CWORD_CWORD,
2787 /* 62 -68 */ CWORD_CWORD_CWORD_CWORD,
2788 /* 63 -67 */ CWORD_CWORD_CWORD_CWORD,
2789 /* 64 -66 */ CWORD_CWORD_CWORD_CWORD,
2790 /* 65 -65 */ CWORD_CWORD_CWORD_CWORD,
2791 /* 66 -64 */ CWORD_CWORD_CWORD_CWORD,
2792 /* 67 -63 */ CWORD_CWORD_CWORD_CWORD,
2793 /* 68 -62 */ CWORD_CWORD_CWORD_CWORD,
2794 /* 69 -61 */ CWORD_CWORD_CWORD_CWORD,
2795 /* 70 -60 */ CWORD_CWORD_CWORD_CWORD,
2796 /* 71 -59 */ CWORD_CWORD_CWORD_CWORD,
2797 /* 72 -58 */ CWORD_CWORD_CWORD_CWORD,
2798 /* 73 -57 */ CWORD_CWORD_CWORD_CWORD,
2799 /* 74 -56 */ CWORD_CWORD_CWORD_CWORD,
2800 /* 75 -55 */ CWORD_CWORD_CWORD_CWORD,
2801 /* 76 -54 */ CWORD_CWORD_CWORD_CWORD,
2802 /* 77 -53 */ CWORD_CWORD_CWORD_CWORD,
2803 /* 78 -52 */ CWORD_CWORD_CWORD_CWORD,
2804 /* 79 -51 */ CWORD_CWORD_CWORD_CWORD,
2805 /* 80 -50 */ CWORD_CWORD_CWORD_CWORD,
2806 /* 81 -49 */ CWORD_CWORD_CWORD_CWORD,
2807 /* 82 -48 */ CWORD_CWORD_CWORD_CWORD,
2808 /* 83 -47 */ CWORD_CWORD_CWORD_CWORD,
2809 /* 84 -46 */ CWORD_CWORD_CWORD_CWORD,
2810 /* 85 -45 */ CWORD_CWORD_CWORD_CWORD,
2811 /* 86 -44 */ CWORD_CWORD_CWORD_CWORD,
2812 /* 87 -43 */ CWORD_CWORD_CWORD_CWORD,
2813 /* 88 -42 */ CWORD_CWORD_CWORD_CWORD,
2814 /* 89 -41 */ CWORD_CWORD_CWORD_CWORD,
2815 /* 90 -40 */ CWORD_CWORD_CWORD_CWORD,
2816 /* 91 -39 */ CWORD_CWORD_CWORD_CWORD,
2817 /* 92 -38 */ CWORD_CWORD_CWORD_CWORD,
2818 /* 93 -37 */ CWORD_CWORD_CWORD_CWORD,
2819 /* 94 -36 */ CWORD_CWORD_CWORD_CWORD,
2820 /* 95 -35 */ CWORD_CWORD_CWORD_CWORD,
2821 /* 96 -34 */ CWORD_CWORD_CWORD_CWORD,
2822 /* 97 -33 */ CWORD_CWORD_CWORD_CWORD,
2823 /* 98 -32 */ CWORD_CWORD_CWORD_CWORD,
2824 /* 99 -31 */ CWORD_CWORD_CWORD_CWORD,
2825 /* 100 -30 */ CWORD_CWORD_CWORD_CWORD,
2826 /* 101 -29 */ CWORD_CWORD_CWORD_CWORD,
2827 /* 102 -28 */ CWORD_CWORD_CWORD_CWORD,
2828 /* 103 -27 */ CWORD_CWORD_CWORD_CWORD,
2829 /* 104 -26 */ CWORD_CWORD_CWORD_CWORD,
2830 /* 105 -25 */ CWORD_CWORD_CWORD_CWORD,
2831 /* 106 -24 */ CWORD_CWORD_CWORD_CWORD,
2832 /* 107 -23 */ CWORD_CWORD_CWORD_CWORD,
2833 /* 108 -22 */ CWORD_CWORD_CWORD_CWORD,
2834 /* 109 -21 */ CWORD_CWORD_CWORD_CWORD,
2835 /* 110 -20 */ CWORD_CWORD_CWORD_CWORD,
2836 /* 111 -19 */ CWORD_CWORD_CWORD_CWORD,
2837 /* 112 -18 */ CWORD_CWORD_CWORD_CWORD,
2838 /* 113 -17 */ CWORD_CWORD_CWORD_CWORD,
2839 /* 114 -16 */ CWORD_CWORD_CWORD_CWORD,
2840 /* 115 -15 */ CWORD_CWORD_CWORD_CWORD,
2841 /* 116 -14 */ CWORD_CWORD_CWORD_CWORD,
2842 /* 117 -13 */ CWORD_CWORD_CWORD_CWORD,
2843 /* 118 -12 */ CWORD_CWORD_CWORD_CWORD,
2844 /* 119 -11 */ CWORD_CWORD_CWORD_CWORD,
2845 /* 120 -10 */ CWORD_CWORD_CWORD_CWORD,
2846 /* 121 -9 */ CWORD_CWORD_CWORD_CWORD,
2847 /* 122 -8 */ CWORD_CWORD_CWORD_CWORD,
2848 /* 123 -7 */ CWORD_CWORD_CWORD_CWORD,
2849 /* 124 -6 */ CWORD_CWORD_CWORD_CWORD,
2850 /* 125 -5 */ CWORD_CWORD_CWORD_CWORD,
2851 /* 126 -4 */ CWORD_CWORD_CWORD_CWORD,
2852 /* 127 -3 */ CWORD_CWORD_CWORD_CWORD,
2853 /* 128 -2 */ CWORD_CWORD_CWORD_CWORD,
2854 /* 129 -1 */ CWORD_CWORD_CWORD_CWORD,
2855 /* 130 0 */ CWORD_CWORD_CWORD_CWORD,
2856 /* 131 1 */ CWORD_CWORD_CWORD_CWORD,
2857 /* 132 2 */ CWORD_CWORD_CWORD_CWORD,
2858 /* 133 3 */ CWORD_CWORD_CWORD_CWORD,
2859 /* 134 4 */ CWORD_CWORD_CWORD_CWORD,
2860 /* 135 5 */ CWORD_CWORD_CWORD_CWORD,
2861 /* 136 6 */ CWORD_CWORD_CWORD_CWORD,
2862 /* 137 7 */ CWORD_CWORD_CWORD_CWORD,
2863 /* 138 8 */ CWORD_CWORD_CWORD_CWORD,
2864 /* 139 9 "\t" */ CSPCL_CWORD_CWORD_CWORD,
2865 /* 140 10 "\n" */ CNL_CNL_CNL_CNL,
2866 /* 141 11 */ CWORD_CWORD_CWORD_CWORD,
2867 /* 142 12 */ CWORD_CWORD_CWORD_CWORD,
2868 /* 143 13 */ CWORD_CWORD_CWORD_CWORD,
2869 /* 144 14 */ CWORD_CWORD_CWORD_CWORD,
2870 /* 145 15 */ CWORD_CWORD_CWORD_CWORD,
2871 /* 146 16 */ CWORD_CWORD_CWORD_CWORD,
2872 /* 147 17 */ CWORD_CWORD_CWORD_CWORD,
2873 /* 148 18 */ CWORD_CWORD_CWORD_CWORD,
2874 /* 149 19 */ CWORD_CWORD_CWORD_CWORD,
2875 /* 150 20 */ CWORD_CWORD_CWORD_CWORD,
2876 /* 151 21 */ CWORD_CWORD_CWORD_CWORD,
2877 /* 152 22 */ CWORD_CWORD_CWORD_CWORD,
2878 /* 153 23 */ CWORD_CWORD_CWORD_CWORD,
2879 /* 154 24 */ CWORD_CWORD_CWORD_CWORD,
2880 /* 155 25 */ CWORD_CWORD_CWORD_CWORD,
2881 /* 156 26 */ CWORD_CWORD_CWORD_CWORD,
2882 /* 157 27 */ CWORD_CWORD_CWORD_CWORD,
2883 /* 158 28 */ CWORD_CWORD_CWORD_CWORD,
2884 /* 159 29 */ CWORD_CWORD_CWORD_CWORD,
2885 /* 160 30 */ CWORD_CWORD_CWORD_CWORD,
2886 /* 161 31 */ CWORD_CWORD_CWORD_CWORD,
2887 /* 162 32 " " */ CSPCL_CWORD_CWORD_CWORD,
2888 /* 163 33 "!" */ CWORD_CCTL_CCTL_CWORD,
2889 /* 164 34 """ */ CDQUOTE_CENDQUOTE_CWORD_CWORD,
2890 /* 165 35 "#" */ CWORD_CWORD_CWORD_CWORD,
2891 /* 166 36 "$" */ CVAR_CVAR_CWORD_CVAR,
2892 /* 167 37 "%" */ CWORD_CWORD_CWORD_CWORD,
2893 /* 168 38 "&" */ CSPCL_CWORD_CWORD_CWORD,
2894 /* 169 39 "'" */ CSQUOTE_CWORD_CENDQUOTE_CWORD,
2895 /* 170 40 "(" */ CSPCL_CWORD_CWORD_CLP,
2896 /* 171 41 ")" */ CSPCL_CWORD_CWORD_CRP,
2897 /* 172 42 "*" */ CWORD_CCTL_CCTL_CWORD,
2898 /* 173 43 "+" */ CWORD_CWORD_CWORD_CWORD,
2899 /* 174 44 "," */ CWORD_CWORD_CWORD_CWORD,
2900 /* 175 45 "-" */ CWORD_CCTL_CCTL_CWORD,
2901 /* 176 46 "." */ CWORD_CWORD_CWORD_CWORD,
2902 /* 177 47 "/" */ CWORD_CCTL_CCTL_CWORD,
2903 /* 178 48 "0" */ CWORD_CWORD_CWORD_CWORD,
2904 /* 179 49 "1" */ CWORD_CWORD_CWORD_CWORD,
2905 /* 180 50 "2" */ CWORD_CWORD_CWORD_CWORD,
2906 /* 181 51 "3" */ CWORD_CWORD_CWORD_CWORD,
2907 /* 182 52 "4" */ CWORD_CWORD_CWORD_CWORD,
2908 /* 183 53 "5" */ CWORD_CWORD_CWORD_CWORD,
2909 /* 184 54 "6" */ CWORD_CWORD_CWORD_CWORD,
2910 /* 185 55 "7" */ CWORD_CWORD_CWORD_CWORD,
2911 /* 186 56 "8" */ CWORD_CWORD_CWORD_CWORD,
2912 /* 187 57 "9" */ CWORD_CWORD_CWORD_CWORD,
2913 /* 188 58 ":" */ CWORD_CCTL_CCTL_CWORD,
2914 /* 189 59 ";" */ CSPCL_CWORD_CWORD_CWORD,
2915 /* 190 60 "<" */ CSPCL_CWORD_CWORD_CWORD,
2916 /* 191 61 "=" */ CWORD_CCTL_CCTL_CWORD,
2917 /* 192 62 ">" */ CSPCL_CWORD_CWORD_CWORD,
2918 /* 193 63 "?" */ CWORD_CCTL_CCTL_CWORD,
2919 /* 194 64 "@" */ CWORD_CWORD_CWORD_CWORD,
2920 /* 195 65 "A" */ CWORD_CWORD_CWORD_CWORD,
2921 /* 196 66 "B" */ CWORD_CWORD_CWORD_CWORD,
2922 /* 197 67 "C" */ CWORD_CWORD_CWORD_CWORD,
2923 /* 198 68 "D" */ CWORD_CWORD_CWORD_CWORD,
2924 /* 199 69 "E" */ CWORD_CWORD_CWORD_CWORD,
2925 /* 200 70 "F" */ CWORD_CWORD_CWORD_CWORD,
2926 /* 201 71 "G" */ CWORD_CWORD_CWORD_CWORD,
2927 /* 202 72 "H" */ CWORD_CWORD_CWORD_CWORD,
2928 /* 203 73 "I" */ CWORD_CWORD_CWORD_CWORD,
2929 /* 204 74 "J" */ CWORD_CWORD_CWORD_CWORD,
2930 /* 205 75 "K" */ CWORD_CWORD_CWORD_CWORD,
2931 /* 206 76 "L" */ CWORD_CWORD_CWORD_CWORD,
2932 /* 207 77 "M" */ CWORD_CWORD_CWORD_CWORD,
2933 /* 208 78 "N" */ CWORD_CWORD_CWORD_CWORD,
2934 /* 209 79 "O" */ CWORD_CWORD_CWORD_CWORD,
2935 /* 210 80 "P" */ CWORD_CWORD_CWORD_CWORD,
2936 /* 211 81 "Q" */ CWORD_CWORD_CWORD_CWORD,
2937 /* 212 82 "R" */ CWORD_CWORD_CWORD_CWORD,
2938 /* 213 83 "S" */ CWORD_CWORD_CWORD_CWORD,
2939 /* 214 84 "T" */ CWORD_CWORD_CWORD_CWORD,
2940 /* 215 85 "U" */ CWORD_CWORD_CWORD_CWORD,
2941 /* 216 86 "V" */ CWORD_CWORD_CWORD_CWORD,
2942 /* 217 87 "W" */ CWORD_CWORD_CWORD_CWORD,
2943 /* 218 88 "X" */ CWORD_CWORD_CWORD_CWORD,
2944 /* 219 89 "Y" */ CWORD_CWORD_CWORD_CWORD,
2945 /* 220 90 "Z" */ CWORD_CWORD_CWORD_CWORD,
2946 /* 221 91 "[" */ CWORD_CCTL_CCTL_CWORD,
2947 /* 222 92 "\" */ CBACK_CBACK_CCTL_CBACK,
2948 /* 223 93 "]" */ CWORD_CCTL_CCTL_CWORD,
2949 /* 224 94 "^" */ CWORD_CWORD_CWORD_CWORD,
2950 /* 225 95 "_" */ CWORD_CWORD_CWORD_CWORD,
2951 /* 226 96 "`" */ CBQUOTE_CBQUOTE_CWORD_CBQUOTE,
2952 /* 227 97 "a" */ CWORD_CWORD_CWORD_CWORD,
2953 /* 228 98 "b" */ CWORD_CWORD_CWORD_CWORD,
2954 /* 229 99 "c" */ CWORD_CWORD_CWORD_CWORD,
2955 /* 230 100 "d" */ CWORD_CWORD_CWORD_CWORD,
2956 /* 231 101 "e" */ CWORD_CWORD_CWORD_CWORD,
2957 /* 232 102 "f" */ CWORD_CWORD_CWORD_CWORD,
2958 /* 233 103 "g" */ CWORD_CWORD_CWORD_CWORD,
2959 /* 234 104 "h" */ CWORD_CWORD_CWORD_CWORD,
2960 /* 235 105 "i" */ CWORD_CWORD_CWORD_CWORD,
2961 /* 236 106 "j" */ CWORD_CWORD_CWORD_CWORD,
2962 /* 237 107 "k" */ CWORD_CWORD_CWORD_CWORD,
2963 /* 238 108 "l" */ CWORD_CWORD_CWORD_CWORD,
2964 /* 239 109 "m" */ CWORD_CWORD_CWORD_CWORD,
2965 /* 240 110 "n" */ CWORD_CWORD_CWORD_CWORD,
2966 /* 241 111 "o" */ CWORD_CWORD_CWORD_CWORD,
2967 /* 242 112 "p" */ CWORD_CWORD_CWORD_CWORD,
2968 /* 243 113 "q" */ CWORD_CWORD_CWORD_CWORD,
2969 /* 244 114 "r" */ CWORD_CWORD_CWORD_CWORD,
2970 /* 245 115 "s" */ CWORD_CWORD_CWORD_CWORD,
2971 /* 246 116 "t" */ CWORD_CWORD_CWORD_CWORD,
2972 /* 247 117 "u" */ CWORD_CWORD_CWORD_CWORD,
2973 /* 248 118 "v" */ CWORD_CWORD_CWORD_CWORD,
2974 /* 249 119 "w" */ CWORD_CWORD_CWORD_CWORD,
2975 /* 250 120 "x" */ CWORD_CWORD_CWORD_CWORD,
2976 /* 251 121 "y" */ CWORD_CWORD_CWORD_CWORD,
2977 /* 252 122 "z" */ CWORD_CWORD_CWORD_CWORD,
2978 /* 253 123 "{" */ CWORD_CWORD_CWORD_CWORD,
2979 /* 254 124 "|" */ CSPCL_CWORD_CWORD_CWORD,
2980 /* 255 125 "}" */ CENDVAR_CENDVAR_CWORD_CENDVAR,
2981 /* 256 126 "~" */ CWORD_CCTL_CCTL_CWORD,
2982 /* 257 127 */ CWORD_CWORD_CWORD_CWORD,
2985 #define SIT(c, syntax) (S_I_T[(int)syntax_index_table[((int)c)+SYNBASE]][syntax])
2987 #endif /* USE_SIT_FUNCTION */
2990 /* ============ Alias handling */
2992 #if ENABLE_ASH_ALIAS
2994 #define ALIASINUSE 1
3005 static struct alias **atab; // [ATABSIZE];
3006 #define INIT_G_alias() do { \
3007 atab = xzalloc(ATABSIZE * sizeof(atab[0])); \
3011 static struct alias **
3012 __lookupalias(const char *name) {
3013 unsigned int hashval;
3020 ch = (unsigned char)*p;
3024 ch = (unsigned char)*++p;
3026 app = &atab[hashval % ATABSIZE];
3028 for (; *app; app = &(*app)->next) {
3029 if (strcmp(name, (*app)->name) == 0) {
3037 static struct alias *
3038 lookupalias(const char *name, int check)
3040 struct alias *ap = *__lookupalias(name);
3042 if (check && ap && (ap->flag & ALIASINUSE))
3047 static struct alias *
3048 freealias(struct alias *ap)
3052 if (ap->flag & ALIASINUSE) {
3053 ap->flag |= ALIASDEAD;
3065 setalias(const char *name, const char *val)
3067 struct alias *ap, **app;
3069 app = __lookupalias(name);
3073 if (!(ap->flag & ALIASINUSE)) {
3076 ap->val = ckstrdup(val);
3077 ap->flag &= ~ALIASDEAD;
3080 ap = ckzalloc(sizeof(struct alias));
3081 ap->name = ckstrdup(name);
3082 ap->val = ckstrdup(val);
3083 /*ap->flag = 0; - ckzalloc did it */
3084 /*ap->next = NULL;*/
3091 unalias(const char *name)
3095 app = __lookupalias(name);
3099 *app = freealias(*app);
3110 struct alias *ap, **app;
3114 for (i = 0; i < ATABSIZE; i++) {
3116 for (ap = *app; ap; ap = *app) {
3117 *app = freealias(*app);
3127 printalias(const struct alias *ap)
3129 out1fmt("%s=%s\n", ap->name, single_quote(ap->val));
3133 * TODO - sort output
3136 aliascmd(int argc UNUSED_PARAM, char **argv)
3145 for (i = 0; i < ATABSIZE; i++) {
3146 for (ap = atab[i]; ap; ap = ap->next) {
3152 while ((n = *++argv) != NULL) {
3153 v = strchr(n+1, '=');
3154 if (v == NULL) { /* n+1: funny ksh stuff */
3155 ap = *__lookupalias(n);
3157 fprintf(stderr, "%s: %s not found\n", "alias", n);
3171 unaliascmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
3175 while ((i = nextopt("a")) != '\0') {
3181 for (i = 0; *argptr; argptr++) {
3182 if (unalias(*argptr)) {
3183 fprintf(stderr, "%s: %s not found\n", "unalias", *argptr);
3191 #endif /* ASH_ALIAS */
3194 /* ============ jobs.c */
3196 /* Mode argument to forkshell. Don't change FORK_FG or FORK_BG. */
3199 #define FORK_NOJOB 2
3201 /* mode flags for showjob(s) */
3202 #define SHOW_PGID 0x01 /* only show pgid - for jobs -p */
3203 #define SHOW_PID 0x04 /* include process pid */
3204 #define SHOW_CHANGED 0x08 /* only jobs whose state has changed */
3207 * A job structure contains information about a job. A job is either a
3208 * single process or a set of processes contained in a pipeline. In the
3209 * latter case, pidlist will be non-NULL, and will point to a -1 terminated
3214 pid_t pid; /* process id */
3215 int status; /* last process status from wait() */
3216 char *cmd; /* text of command being run */
3220 struct procstat ps0; /* status of process */
3221 struct procstat *ps; /* status or processes when more than one */
3223 int stopstatus; /* status of a stopped job */
3226 nprocs: 16, /* number of processes */
3228 #define JOBRUNNING 0 /* at least one proc running */
3229 #define JOBSTOPPED 1 /* all procs are stopped */
3230 #define JOBDONE 2 /* all procs are completed */
3232 sigint: 1, /* job was killed by SIGINT */
3233 jobctl: 1, /* job running under job control */
3235 waited: 1, /* true if this entry has been waited for */
3236 used: 1, /* true if this entry is in used */
3237 changed: 1; /* true if status has changed */
3238 struct job *prev_job; /* previous job */
3241 static struct job *makejob(/*union node *,*/ int);
3243 #define forkshell(job, node, mode) forkshell(job, mode)
3245 static int forkshell(struct job *, union node *, int);
3246 static int waitforjob(struct job *);
3249 enum { doing_jobctl = 0 };
3250 #define setjobctl(on) do {} while (0)
3252 static smallint doing_jobctl; //references:8
3253 static void setjobctl(int);
3257 * Set the signal handler for the specified signal. The routine figures
3258 * out what it should be set to.
3261 setsignal(int signo)
3265 struct sigaction act;
3271 else if (*t != '\0')
3273 if (rootshell && action == S_DFL) {
3276 if (iflag || minusc || sflag == 0)
3299 t = &sigmode[signo - 1];
3303 * current setting unknown
3305 if (sigaction(signo, NULL, &act) == -1) {
3307 * Pretend it worked; maybe we should give a warning
3308 * here, but other shells don't. We don't alter
3309 * sigmode, so that we retry every time.
3313 tsig = S_RESET; /* force to be set */
3314 if (act.sa_handler == SIG_IGN) {
3317 && (signo == SIGTSTP || signo == SIGTTIN || signo == SIGTTOU)
3319 tsig = S_IGN; /* don't hard ignore these */
3323 if (tsig == S_HARD_IGN || tsig == action)
3325 act.sa_handler = SIG_DFL;
3328 act.sa_handler = onsig;
3331 act.sa_handler = SIG_IGN;
3336 sigfillset(&act.sa_mask);
3337 sigaction_set(signo, &act);
3340 /* mode flags for set_curjob */
3341 #define CUR_DELETE 2
3342 #define CUR_RUNNING 1
3343 #define CUR_STOPPED 0
3345 /* mode flags for dowait */
3346 #define DOWAIT_NONBLOCK WNOHANG
3347 #define DOWAIT_BLOCK 0
3350 /* pgrp of shell on invocation */
3351 static int initialpgrp; //references:2
3352 static int ttyfd = -1; //5
3355 static struct job *jobtab; //5
3357 static unsigned njobs; //4
3359 static struct job *curjob; //lots
3360 /* number of presumed living untracked jobs */
3361 static int jobless; //4
3364 set_curjob(struct job *jp, unsigned mode)
3367 struct job **jpp, **curp;
3369 /* first remove from list */
3370 jpp = curp = &curjob;
3375 jpp = &jp1->prev_job;
3377 *jpp = jp1->prev_job;
3379 /* Then re-insert in correct position */
3387 /* job being deleted */
3390 /* newly created job or backgrounded job,
3391 put after all stopped jobs. */
3395 if (!jp1 || jp1->state != JOBSTOPPED)
3398 jpp = &jp1->prev_job;
3404 /* newly stopped job - becomes curjob */
3405 jp->prev_job = *jpp;
3413 jobno(const struct job *jp)
3415 return jp - jobtab + 1;
3420 * Convert a job name to a job structure.
3423 #define getjob(name, getctl) getjob(name)
3426 getjob(const char *name, int getctl)
3430 const char *err_msg = "No such job: %s";
3434 char *(*match)(const char *, const char *);
3449 if (c == '+' || c == '%') {
3451 err_msg = "No current job";
3457 err_msg = "No previous job";
3466 // TODO: number() instead? It does error checking...
3469 jp = jobtab + num - 1;
3486 if (match(jp->ps[0].cmd, p)) {
3490 err_msg = "%s: ambiguous";
3497 err_msg = "job %s not created under job control";
3498 if (getctl && jp->jobctl == 0)
3503 ash_msg_and_raise_error(err_msg, name);
3507 * Mark a job structure as unused.
3510 freejob(struct job *jp)
3512 struct procstat *ps;
3516 for (i = jp->nprocs, ps = jp->ps; --i >= 0; ps++) {
3517 if (ps->cmd != nullstr)
3520 if (jp->ps != &jp->ps0)
3523 set_curjob(jp, CUR_DELETE);
3529 xtcsetpgrp(int fd, pid_t pgrp)
3531 if (tcsetpgrp(fd, pgrp))
3532 ash_msg_and_raise_error("can't set tty process group (%m)");
3536 * Turn job control on and off.
3538 * Note: This code assumes that the third arg to ioctl is a character
3539 * pointer, which is true on Berkeley systems but not System V. Since
3540 * System V doesn't have job control yet, this isn't a problem now.
3542 * Called with interrupts off.
3550 if (on == doing_jobctl || rootshell == 0)
3554 ofd = fd = open(_PATH_TTY, O_RDWR);
3556 /* BTW, bash will try to open(ttyname(0)) if open("/dev/tty") fails.
3557 * That sometimes helps to acquire controlling tty.
3558 * Obviously, a workaround for bugs when someone
3559 * failed to provide a controlling tty to bash! :) */
3565 fd = fcntl(fd, F_DUPFD, 10);
3570 /* fd is a tty at this point */
3571 close_on_exec_on(fd);
3572 do { /* while we are in the background */
3573 pgrp = tcgetpgrp(fd);
3576 ash_msg("can't access tty; job control turned off");
3580 if (pgrp == getpgrp())
3591 xtcsetpgrp(fd, pgrp);
3593 /* turning job control off */
3596 /* was xtcsetpgrp, but this can make exiting ash
3597 * loop forever if pty is already deleted */
3598 tcsetpgrp(fd, pgrp);
3613 killcmd(int argc, char **argv)
3616 if (argv[1] && strcmp(argv[1], "-l") != 0) {
3618 if (argv[i][0] == '%') {
3619 struct job *jp = getjob(argv[i], 0);
3620 unsigned pid = jp->ps[0].pid;
3621 /* Enough space for ' -NNN<nul>' */
3622 argv[i] = alloca(sizeof(int)*3 + 3);
3623 /* kill_main has matching code to expect
3624 * leading space. Needed to not confuse
3625 * negative pids with "kill -SIGNAL_NO" syntax */
3626 sprintf(argv[i], " -%u", pid);
3628 } while (argv[++i]);
3630 return kill_main(argc, argv);
3634 showpipe(struct job *jp, FILE *out)
3636 struct procstat *sp;
3637 struct procstat *spend;
3639 spend = jp->ps + jp->nprocs;
3640 for (sp = jp->ps + 1; sp < spend; sp++)
3641 fprintf(out, " | %s", sp->cmd);
3642 outcslow('\n', out);
3643 flush_stdout_stderr();
3648 restartjob(struct job *jp, int mode)
3650 struct procstat *ps;
3656 if (jp->state == JOBDONE)
3658 jp->state = JOBRUNNING;
3660 if (mode == FORK_FG)
3661 xtcsetpgrp(ttyfd, pgid);
3662 killpg(pgid, SIGCONT);
3666 if (WIFSTOPPED(ps->status)) {
3672 status = (mode == FORK_FG) ? waitforjob(jp) : 0;
3678 fg_bgcmd(int argc UNUSED_PARAM, char **argv)
3685 mode = (**argv == 'f') ? FORK_FG : FORK_BG;
3690 jp = getjob(*argv, 1);
3691 if (mode == FORK_BG) {
3692 set_curjob(jp, CUR_RUNNING);
3693 fprintf(out, "[%d] ", jobno(jp));
3695 outstr(jp->ps->cmd, out);
3697 retval = restartjob(jp, mode);
3698 } while (*argv && *++argv);
3704 sprint_status(char *s, int status, int sigonly)
3710 if (!WIFEXITED(status)) {
3712 if (WIFSTOPPED(status))
3713 st = WSTOPSIG(status);
3716 st = WTERMSIG(status);
3718 if (st == SIGINT || st == SIGPIPE)
3721 if (WIFSTOPPED(status))
3726 col = fmtstr(s, 32, strsignal(st));
3727 if (WCOREDUMP(status)) {
3728 col += fmtstr(s + col, 16, " (core dumped)");
3730 } else if (!sigonly) {
3731 st = WEXITSTATUS(status);
3733 col = fmtstr(s, 16, "Done(%d)", st);
3735 col = fmtstr(s, 16, "Done");
3742 * Do a wait system call. If job control is compiled in, we accept
3743 * stopped processes. If block is zero, we return a value of zero
3744 * rather than blocking.
3746 * System V doesn't have a non-blocking wait system call. It does
3747 * have a SIGCLD signal that is sent to a process when one of it's
3748 * children dies. The obvious way to use SIGCLD would be to install
3749 * a handler for SIGCLD which simply bumped a counter when a SIGCLD
3750 * was received, and have waitproc bump another counter when it got
3751 * the status of a process. Waitproc would then know that a wait
3752 * system call would not block if the two counters were different.
3753 * This approach doesn't work because if a process has children that
3754 * have not been waited for, System V will send it a SIGCLD when it
3755 * installs a signal handler for SIGCLD. What this means is that when
3756 * a child exits, the shell will be sent SIGCLD signals continuously
3757 * until is runs out of stack space, unless it does a wait call before
3758 * restoring the signal handler. The code below takes advantage of
3759 * this (mis)feature by installing a signal handler for SIGCLD and
3760 * then checking to see whether it was called. If there are any
3761 * children to be waited for, it will be.
3763 * If neither SYSV nor BSD is defined, we don't implement nonblocking
3764 * waits at all. In this case, the user will not be informed when
3765 * a background process until the next time she runs a real program
3766 * (as opposed to running a builtin command or just typing return),
3767 * and the jobs command may give out of date information.
3770 waitproc(int wait_flags, int *status)
3774 wait_flags |= WUNTRACED;
3776 /* NB: _not_ safe_waitpid, we need to detect EINTR */
3777 return waitpid(-1, status, wait_flags);
3781 * Wait for a process to terminate.
3784 dowait(int wait_flags, struct job *job)
3789 struct job *thisjob;
3792 TRACE(("dowait(%d) called\n", wait_flags));
3793 pid = waitproc(wait_flags, &status);
3794 TRACE(("wait returns pid=%d, status=%d\n", pid, status));
3796 /* If we were doing blocking wait and (probably) got EINTR,
3797 * check for pending sigs received while waiting.
3798 * (NB: can be moved into callers if needed) */
3799 if (wait_flags == DOWAIT_BLOCK && pendingsig)
3800 raise_exception(EXSIG);
3805 for (jp = curjob; jp; jp = jp->prev_job) {
3806 struct procstat *sp;
3807 struct procstat *spend;
3808 if (jp->state == JOBDONE)
3811 spend = jp->ps + jp->nprocs;
3814 if (sp->pid == pid) {
3815 TRACE(("Job %d: changing status of proc %d "
3816 "from 0x%x to 0x%x\n",
3817 jobno(jp), pid, sp->status, status));
3818 sp->status = status;
3821 if (sp->status == -1)
3824 if (state == JOBRUNNING)
3826 if (WIFSTOPPED(sp->status)) {
3827 jp->stopstatus = sp->status;
3831 } while (++sp < spend);
3836 if (!WIFSTOPPED(status))
3842 if (state != JOBRUNNING) {
3843 thisjob->changed = 1;
3845 if (thisjob->state != state) {
3846 TRACE(("Job %d: changing state from %d to %d\n",
3847 jobno(thisjob), thisjob->state, state));
3848 thisjob->state = state;
3850 if (state == JOBSTOPPED) {
3851 set_curjob(thisjob, CUR_STOPPED);
3860 if (thisjob && thisjob == job) {
3864 len = sprint_status(s, status, 1);
3876 showjob(FILE *out, struct job *jp, int mode)
3878 struct procstat *ps;
3879 struct procstat *psend;
3886 if (mode & SHOW_PGID) {
3887 /* just output process (group) id of pipeline */
3888 fprintf(out, "%d\n", ps->pid);
3892 col = fmtstr(s, 16, "[%d] ", jobno(jp));
3897 else if (curjob && jp == curjob->prev_job)
3900 if (mode & SHOW_PID)
3901 col += fmtstr(s + col, 16, "%d ", ps->pid);
3903 psend = ps + jp->nprocs;
3905 if (jp->state == JOBRUNNING) {
3906 strcpy(s + col, "Running");
3907 col += sizeof("Running") - 1;
3909 int status = psend[-1].status;
3910 if (jp->state == JOBSTOPPED)
3911 status = jp->stopstatus;
3912 col += sprint_status(s + col, status, 0);
3918 /* for each process */
3919 col = fmtstr(s, 48, " |\n%*c%d ", indent_col, ' ', ps->pid) - 3;
3921 fprintf(out, "%s%*c%s",
3922 s, 33 - col >= 0 ? 33 - col : 0, ' ', ps->cmd
3924 if (!(mode & SHOW_PID)) {
3928 if (++ps == psend) {
3929 outcslow('\n', out);
3936 if (jp->state == JOBDONE) {
3937 TRACE(("showjob: freeing job %d\n", jobno(jp)));
3943 * Print a list of jobs. If "change" is nonzero, only print jobs whose
3944 * statuses have changed since the last call to showjobs.
3947 showjobs(FILE *out, int mode)
3951 TRACE(("showjobs(%x) called\n", mode));
3953 /* If not even one job changed, there is nothing to do */
3954 while (dowait(DOWAIT_NONBLOCK, NULL) > 0)
3957 for (jp = curjob; jp; jp = jp->prev_job) {
3958 if (!(mode & SHOW_CHANGED) || jp->changed) {
3959 showjob(out, jp, mode);
3965 jobscmd(int argc UNUSED_PARAM, char **argv)
3970 while ((m = nextopt("lp"))) {
3980 showjob(stdout, getjob(*argv,0), mode);
3983 showjobs(stdout, mode);
3990 getstatus(struct job *job)
3995 status = job->ps[job->nprocs - 1].status;
3996 retval = WEXITSTATUS(status);
3997 if (!WIFEXITED(status)) {
3999 retval = WSTOPSIG(status);
4000 if (!WIFSTOPPED(status))
4003 /* XXX: limits number of signals */
4004 retval = WTERMSIG(status);
4006 if (retval == SIGINT)
4012 TRACE(("getstatus: job %d, nproc %d, status %x, retval %x\n",
4013 jobno(job), job->nprocs, status, retval));
4018 waitcmd(int argc UNUSED_PARAM, char **argv)
4027 raise_exception(EXSIG);
4034 /* wait for all jobs */
4038 if (!jp) /* no running procs */
4040 if (jp->state == JOBRUNNING)
4045 dowait(DOWAIT_BLOCK, NULL);
4051 if (**argv != '%') {
4052 pid_t pid = number(*argv);
4057 if (job->ps[job->nprocs - 1].pid == pid)
4059 job = job->prev_job;
4062 job = getjob(*argv, 0);
4063 /* loop until process terminated or stopped */
4064 while (job->state == JOBRUNNING)
4065 dowait(DOWAIT_BLOCK, NULL);
4067 retval = getstatus(job);
4081 struct job *jp, *jq;
4083 len = njobs * sizeof(*jp);
4085 jp = ckrealloc(jq, len + 4 * sizeof(*jp));
4087 offset = (char *)jp - (char *)jq;
4089 /* Relocate pointers */
4092 jq = (struct job *)((char *)jq + l);
4096 #define joff(p) ((struct job *)((char *)(p) + l))
4097 #define jmove(p) (p) = (void *)((char *)(p) + offset)
4098 if (joff(jp)->ps == &jq->ps0)
4099 jmove(joff(jp)->ps);
4100 if (joff(jp)->prev_job)
4101 jmove(joff(jp)->prev_job);
4111 jp = (struct job *)((char *)jp + len);
4115 } while (--jq >= jp);
4120 * Return a new job structure.
4121 * Called with interrupts off.
4124 makejob(/*union node *node,*/ int nprocs)
4129 for (i = njobs, jp = jobtab; ; jp++) {
4136 if (jp->state != JOBDONE || !jp->waited)
4145 memset(jp, 0, sizeof(*jp));
4147 /* jp->jobctl is a bitfield.
4148 * "jp->jobctl |= jobctl" likely to give awful code */
4152 jp->prev_job = curjob;
4157 jp->ps = ckmalloc(nprocs * sizeof(struct procstat));
4159 TRACE(("makejob(%d) returns %%%d\n", nprocs,
4166 * Return a string identifying a command (to be printed by the
4169 static char *cmdnextc;
4172 cmdputs(const char *s)
4174 static const char vstype[VSTYPE + 1][3] = {
4175 "", "}", "-", "+", "?", "=",
4176 "%", "%%", "#", "##"
4177 USE_ASH_BASH_COMPAT(, ":", "/", "//")
4180 const char *p, *str;
4181 char c, cc[2] = " ";
4186 nextc = makestrspace((strlen(s) + 1) * 8, cmdnextc);
4188 while ((c = *p++) != 0) {
4196 if ((subtype & VSTYPE) == VSLENGTH)
4200 if (!(subtype & VSQUOTE) == !(quoted & 1))
4206 str = "\"}" + !(quoted & 1);
4213 case CTLBACKQ+CTLQUOTE:
4216 #if ENABLE_ASH_MATH_SUPPORT
4231 if ((subtype & VSTYPE) != VSNORMAL)
4233 str = vstype[subtype & VSTYPE];
4234 if (subtype & VSNUL)
4243 /* These can only happen inside quotes */
4256 while ((c = *str++)) {
4261 USTPUTC('"', nextc);
4267 /* cmdtxt() and cmdlist() call each other */
4268 static void cmdtxt(union node *n);
4271 cmdlist(union node *np, int sep)
4273 for (; np; np = np->narg.next) {
4277 if (sep && np->narg.next)
4283 cmdtxt(union node *n)
4286 struct nodelist *lp;
4298 lp = n->npipe.cmdlist;
4316 cmdtxt(n->nbinary.ch1);
4332 cmdtxt(n->nif.test);
4335 if (n->nif.elsepart) {
4338 n = n->nif.elsepart;
4354 cmdtxt(n->nbinary.ch1);
4364 cmdputs(n->nfor.var);
4366 cmdlist(n->nfor.args, 1);
4371 cmdputs(n->narg.text);
4375 cmdlist(n->ncmd.args, 1);
4376 cmdlist(n->ncmd.redirect, 0);
4389 cmdputs(n->ncase.expr->narg.text);
4391 for (np = n->ncase.cases; np; np = np->nclist.next) {
4392 cmdtxt(np->nclist.pattern);
4394 cmdtxt(np->nclist.body);
4420 s[0] = n->nfile.fd + '0';
4424 if (n->type == NTOFD || n->type == NFROMFD) {
4425 s[0] = n->ndup.dupfd + '0';
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 */
4679 # define PIPESIZE 4096 /* amount of buffering in a pipe */
4681 # define PIPESIZE PIPE_BUF
4685 * Open a file in noclobber mode.
4686 * The code was copied from bash.
4689 noclobberopen(const char *fname)
4692 struct stat finfo, finfo2;
4695 * If the file exists and is a regular file, return an error
4698 r = stat(fname, &finfo);
4699 if (r == 0 && S_ISREG(finfo.st_mode)) {
4705 * If the file was not present (r != 0), make sure we open it
4706 * exclusively so that if it is created before we open it, our open
4707 * will fail. Make sure that we do not truncate an existing file.
4708 * Note that we don't turn on O_EXCL unless the stat failed -- if the
4709 * file was not a regular file, we leave O_EXCL off.
4712 return open(fname, O_WRONLY|O_CREAT|O_EXCL, 0666);
4713 fd = open(fname, O_WRONLY|O_CREAT, 0666);
4715 /* If the open failed, return the file descriptor right away. */
4720 * OK, the open succeeded, but the file may have been changed from a
4721 * non-regular file to a regular file between the stat and the open.
4722 * We are assuming that the O_EXCL open handles the case where FILENAME
4723 * did not exist and is symlinked to an existing file between the stat
4728 * If we can open it and fstat the file descriptor, and neither check
4729 * revealed that it was a regular file, and the file has not been
4730 * replaced, return the file descriptor.
4732 if (fstat(fd, &finfo2) == 0 && !S_ISREG(finfo2.st_mode)
4733 && finfo.st_dev == finfo2.st_dev && finfo.st_ino == finfo2.st_ino)
4736 /* The file has been replaced. badness. */
4743 * Handle here documents. Normally we fork off a process to write the
4744 * data to a pipe. If the document is short, we can stuff the data in
4745 * the pipe without forking.
4747 /* openhere needs this forward reference */
4748 static void expandhere(union node *arg, int fd);
4750 openhere(union node *redir)
4756 ash_msg_and_raise_error("pipe call failed");
4757 if (redir->type == NHERE) {
4758 len = strlen(redir->nhere.doc->narg.text);
4759 if (len <= PIPESIZE) {
4760 full_write(pip[1], redir->nhere.doc->narg.text, len);
4764 if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) {
4767 signal(SIGINT, SIG_IGN);
4768 signal(SIGQUIT, SIG_IGN);
4769 signal(SIGHUP, SIG_IGN);
4771 signal(SIGTSTP, SIG_IGN);
4773 signal(SIGPIPE, SIG_DFL);
4774 if (redir->type == NHERE)
4775 full_write(pip[1], redir->nhere.doc->narg.text, len);
4777 expandhere(redir->nhere.doc, pip[1]);
4778 _exit(EXIT_SUCCESS);
4786 openredirect(union node *redir)
4791 switch (redir->nfile.type) {
4793 fname = redir->nfile.expfname;
4794 f = open(fname, O_RDONLY);
4799 fname = redir->nfile.expfname;
4800 f = open(fname, O_RDWR|O_CREAT|O_TRUNC, 0666);
4805 /* Take care of noclobber mode. */
4807 fname = redir->nfile.expfname;
4808 f = noclobberopen(fname);
4815 fname = redir->nfile.expfname;
4816 f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666);
4821 fname = redir->nfile.expfname;
4822 f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666);
4830 /* Fall through to eliminate warning. */
4831 /* Our single caller does this itself */
4838 f = openhere(redir);
4844 ash_msg_and_raise_error("can't create %s: %s", fname, errmsg(errno, "nonexistent directory"));
4846 ash_msg_and_raise_error("can't open %s: %s", fname, errmsg(errno, "no such file"));
4850 * Copy a file descriptor to be >= to. Returns -1
4851 * if the source file descriptor is closed, EMPTY if there are no unused
4852 * file descriptors left.
4855 copyfd(int from, int to)
4859 newfd = fcntl(from, F_DUPFD, to);
4861 if (errno == EMFILE)
4863 ash_msg_and_raise_error("%d: %m", from);
4868 /* Struct def and variable are moved down to the first usage site */
4870 struct redirtab *next;
4874 #define redirlist (G_var.redirlist)
4877 * Process a list of redirection commands. If the REDIR_PUSH flag is set,
4878 * old file descriptors are stashed away so that the redirection can be
4879 * undone by calling popredir. If the REDIR_BACKQ flag is set, then the
4880 * standard output, and the standard error if it becomes a duplicate of
4881 * stdout, is saved in memory.
4883 /* flags passed to redirect */
4884 #define REDIR_PUSH 01 /* save previous values of file descriptors */
4885 #define REDIR_SAVEFD2 03 /* set preverrout */
4887 redirect(union node *redir, int flags)
4889 struct redirtab *sv;
4900 if (flags & REDIR_PUSH) {
4901 sv = ckmalloc(sizeof(*sv));
4902 sv->next = redirlist;
4904 sv->nullredirs = g_nullredirs - 1;
4906 for (i = 0; i < 10; i++)
4907 sv->renamed[i] = EMPTY;
4911 fd = redir->nfile.fd;
4912 if (redir->nfile.type == NTOFD || redir->nfile.type == NFROMFD) {
4913 if (redir->ndup.dupfd == fd)
4914 continue; /* redirect from/to same file descriptor */
4917 newfd = openredirect(redir); /* always >= 0 */
4919 /* Descriptor wasn't open before redirect.
4920 * Mark it for close in the future */
4921 if (sv && sv->renamed[fd] == EMPTY)
4922 sv->renamed[fd] = CLOSED;
4926 if (sv && sv->renamed[fd] == EMPTY) {
4927 /* Copy old descriptor */
4928 i = fcntl(fd, F_DUPFD, 10);
4932 /* Strange error (e.g. "too many files" EMFILE?) */
4933 /*if (newfd >= 0)*/ close(newfd);
4935 ash_msg_and_raise_error("%d: %m", fd);
4938 /* EBADF: it is not open - ok */
4940 /* fd is open, save its copy */
4941 //TODO: CLOEXEC the copy? currently these extra "saved" fds are closed
4942 // in popredir() in the child, preventing them from leaking into child.
4943 // (popredir() also cleans up the mess in case of failures)
4944 sv->renamed[fd] = i;
4950 /* At this point fd is closed */
4952 /* NTOFD/NFROMFD: copy redir->ndup.dupfd to fd */
4953 if (redir->ndup.dupfd >= 0) { /* if not ">&-" */
4954 copyfd(redir->ndup.dupfd, fd);
4956 } else { /* move newfd to fd */
4960 } while ((redir = redir->nfile.next) != NULL);
4963 if ((flags & REDIR_SAVEFD2) && sv && sv->renamed[2] >= 0)
4964 preverrout_fd = sv->renamed[2];
4968 * Undo the effects of the last redirection.
4973 struct redirtab *rp;
4976 if (--g_nullredirs >= 0)
4980 for (i = 0; i < 10; i++) {
4981 if (rp->renamed[i] == CLOSED) {
4986 if (rp->renamed[i] != EMPTY) {
4989 copyfd(rp->renamed[i], i);
4991 close(rp->renamed[i]);
4994 redirlist = rp->next;
4995 g_nullredirs = rp->nullredirs;
5001 * Undo all redirections. Called on error or interrupt.
5005 * Discard all saved file descriptors.
5008 clearredir(int drop)
5019 redirectsafe(union node *redir, int flags)
5022 volatile int saveint;
5023 struct jmploc *volatile savehandler = exception_handler;
5024 struct jmploc jmploc;
5027 err = setjmp(jmploc.loc) * 2;
5029 exception_handler = &jmploc;
5030 redirect(redir, flags);
5032 exception_handler = savehandler;
5033 if (err && exception != EXERROR)
5034 longjmp(exception_handler->loc, 1);
5035 RESTORE_INT(saveint);
5040 /* ============ Routines to expand arguments to commands
5042 * We have to deal with backquotes, shell variables, and file metacharacters.
5045 #if ENABLE_ASH_MATH_SUPPORT_64
5046 typedef int64_t arith_t;
5047 #define arith_t_type long long
5049 typedef long arith_t;
5050 #define arith_t_type long
5053 #if ENABLE_ASH_MATH_SUPPORT
5054 static arith_t dash_arith(const char *);
5055 static arith_t arith(const char *expr, int *perrcode);
5061 #define EXP_FULL 0x1 /* perform word splitting & file globbing */
5062 #define EXP_TILDE 0x2 /* do normal tilde expansion */
5063 #define EXP_VARTILDE 0x4 /* expand tildes in an assignment */
5064 #define EXP_REDIR 0x8 /* file glob for a redirection (1 match only) */
5065 #define EXP_CASE 0x10 /* keeps quotes around for CASE pattern */
5066 #define EXP_RECORD 0x20 /* need to record arguments for ifs breakup */
5067 #define EXP_VARTILDE2 0x40 /* expand tildes after colons only */
5068 #define EXP_WORD 0x80 /* expand word in parameter expansion */
5069 #define EXP_QWORD 0x100 /* expand word in quoted parameter expansion */
5073 #define RMESCAPE_ALLOC 0x1 /* Allocate a new string */
5074 #define RMESCAPE_GLOB 0x2 /* Add backslashes for glob */
5075 #define RMESCAPE_QUOTED 0x4 /* Remove CTLESC unless in quotes */
5076 #define RMESCAPE_GROW 0x8 /* Grow strings instead of stalloc */
5077 #define RMESCAPE_HEAP 0x10 /* Malloc strings instead of stalloc */
5080 * Structure specifying which parts of the string should be searched
5081 * for IFS characters.
5084 struct ifsregion *next; /* next region in list */
5085 int begoff; /* offset of start of region */
5086 int endoff; /* offset of end of region */
5087 int nulonly; /* search for nul bytes only */
5091 struct strlist *list;
5092 struct strlist **lastp;
5095 /* output of current string */
5096 static char *expdest;
5097 /* list of back quote expressions */
5098 static struct nodelist *argbackq;
5099 /* first struct in list of ifs regions */
5100 static struct ifsregion ifsfirst;
5101 /* last struct in list */
5102 static struct ifsregion *ifslastp;
5103 /* holds expanded arg list */
5104 static struct arglist exparg;
5114 expdest = makestrspace(32, expdest);
5115 #if ENABLE_ASH_MATH_SUPPORT_64
5116 len = fmtstr(expdest, 32, "%lld", (long long) num);
5118 len = fmtstr(expdest, 32, "%ld", num);
5120 STADJUST(len, expdest);
5125 esclen(const char *start, const char *p)
5129 while (p > start && *--p == CTLESC) {
5136 * Remove any CTLESC characters from a string.
5139 _rmescapes(char *str, int flag)
5141 static const char qchars[] ALIGN1 = { CTLESC, CTLQUOTEMARK, '\0' };
5148 p = strpbrk(str, qchars);
5154 if (flag & RMESCAPE_ALLOC) {
5155 size_t len = p - str;
5156 size_t fulllen = len + strlen(p) + 1;
5158 if (flag & RMESCAPE_GROW) {
5159 r = makestrspace(fulllen, expdest);
5160 } else if (flag & RMESCAPE_HEAP) {
5161 r = ckmalloc(fulllen);
5163 r = stalloc(fulllen);
5167 q = (char *)memcpy(q, str, len) + len;
5170 inquotes = (flag & RMESCAPE_QUOTED) ^ RMESCAPE_QUOTED;
5171 globbing = flag & RMESCAPE_GLOB;
5172 notescaped = globbing;
5174 if (*p == CTLQUOTEMARK) {
5175 inquotes = ~inquotes;
5177 notescaped = globbing;
5181 /* naked back slash */
5187 if (notescaped && inquotes && *p != '/') {
5191 notescaped = globbing;
5196 if (flag & RMESCAPE_GROW) {
5198 STADJUST(q - r + 1, expdest);
5202 #define rmescapes(p) _rmescapes((p), 0)
5204 #define pmatch(a, b) !fnmatch((a), (b), 0)
5207 * Prepare a pattern for a expmeta (internal glob(3)) call.
5209 * Returns an stalloced string.
5212 preglob(const char *pattern, int quoted, int flag)
5214 flag |= RMESCAPE_GLOB;
5216 flag |= RMESCAPE_QUOTED;
5218 return _rmescapes((char *)pattern, flag);
5222 * Put a string on the stack.
5225 memtodest(const char *p, size_t len, int syntax, int quotes)
5229 q = makestrspace(len * 2, q);
5232 int c = signed_char2int(*p++);
5235 if (quotes && (SIT(c, syntax) == CCTL || SIT(c, syntax) == CBACK))
5244 strtodest(const char *p, int syntax, int quotes)
5246 memtodest(p, strlen(p), syntax, quotes);
5250 * Record the fact that we have to scan this region of the
5251 * string for IFS characters.
5254 recordregion(int start, int end, int nulonly)
5256 struct ifsregion *ifsp;
5258 if (ifslastp == NULL) {
5262 ifsp = ckzalloc(sizeof(*ifsp));
5263 /*ifsp->next = NULL; - ckzalloc did it */
5264 ifslastp->next = ifsp;
5268 ifslastp->begoff = start;
5269 ifslastp->endoff = end;
5270 ifslastp->nulonly = nulonly;
5274 removerecordregions(int endoff)
5276 if (ifslastp == NULL)
5279 if (ifsfirst.endoff > endoff) {
5280 while (ifsfirst.next != NULL) {
5281 struct ifsregion *ifsp;
5283 ifsp = ifsfirst.next->next;
5284 free(ifsfirst.next);
5285 ifsfirst.next = ifsp;
5288 if (ifsfirst.begoff > endoff)
5291 ifslastp = &ifsfirst;
5292 ifsfirst.endoff = endoff;
5297 ifslastp = &ifsfirst;
5298 while (ifslastp->next && ifslastp->next->begoff < endoff)
5299 ifslastp=ifslastp->next;
5300 while (ifslastp->next != NULL) {
5301 struct ifsregion *ifsp;
5303 ifsp = ifslastp->next->next;
5304 free(ifslastp->next);
5305 ifslastp->next = ifsp;
5308 if (ifslastp->endoff > endoff)
5309 ifslastp->endoff = endoff;
5313 exptilde(char *startp, char *p, int flag)
5319 int quotes = flag & (EXP_FULL | EXP_CASE);
5324 while ((c = *++p) != '\0') {
5331 if (flag & EXP_VARTILDE)
5341 if (*name == '\0') {
5342 home = lookupvar(homestr);
5344 pw = getpwnam(name);
5349 if (!home || !*home)
5352 startloc = expdest - (char *)stackblock();
5353 strtodest(home, SQSYNTAX, quotes);
5354 recordregion(startloc, expdest - (char *)stackblock(), 0);
5362 * Execute a command inside back quotes. If it's a builtin command, we
5363 * want to save its output in a block obtained from malloc. Otherwise
5364 * we fork off a subprocess and get the output of the command via a pipe.
5365 * Should be called with interrupts off.
5367 struct backcmd { /* result of evalbackcmd */
5368 int fd; /* file descriptor to read from */
5369 int nleft; /* number of chars in buffer */
5370 char *buf; /* buffer */
5371 struct job *jp; /* job structure for command */
5374 /* These forward decls are needed to use "eval" code for backticks handling: */
5375 static uint8_t back_exitstatus; /* exit status of backquoted command */
5376 #define EV_EXIT 01 /* exit after evaluating tree */
5377 static void evaltree(union node *, int);
5380 evalbackcmd(union node *n, struct backcmd *result)
5392 saveherefd = herefd;
5400 ash_msg_and_raise_error("pipe call failed");
5401 jp = makejob(/*n,*/ 1);
5402 if (forkshell(jp, n, FORK_NOJOB) == 0) {
5411 evaltree(n, EV_EXIT); /* actually evaltreenr... */
5415 result->fd = pip[0];
5418 herefd = saveherefd;
5420 TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n",
5421 result->fd, result->buf, result->nleft, result->jp));
5425 * Expand stuff in backwards quotes.
5428 expbackq(union node *cmd, int quoted, int quotes)
5436 int syntax = quoted ? DQSYNTAX : BASESYNTAX;
5437 struct stackmark smark;
5440 setstackmark(&smark);
5442 startloc = dest - (char *)stackblock();
5444 evalbackcmd(cmd, &in);
5445 popstackmark(&smark);
5452 memtodest(p, i, syntax, quotes);
5456 i = nonblock_safe_read(in.fd, buf, sizeof(buf));
5457 TRACE(("expbackq: read returns %d\n", i));
5466 back_exitstatus = waitforjob(in.jp);
5470 /* Eat all trailing newlines */
5472 for (; dest > (char *)stackblock() && dest[-1] == '\n';)
5477 recordregion(startloc, dest - (char *)stackblock(), 0);
5478 TRACE(("evalbackq: size=%d: \"%.*s\"\n",
5479 (dest - (char *)stackblock()) - startloc,
5480 (dest - (char *)stackblock()) - startloc,
5481 stackblock() + startloc));
5484 #if ENABLE_ASH_MATH_SUPPORT
5486 * Expand arithmetic expression. Backup to start of expression,
5487 * evaluate, place result in (backed up) result, adjust string position.
5500 * This routine is slightly over-complicated for
5501 * efficiency. Next we scan backwards looking for the
5502 * start of arithmetic.
5504 start = stackblock();
5511 while (*p != CTLARI) {
5515 ash_msg_and_raise_error("missing CTLARI (shouldn't happen)");
5520 esc = esclen(start, p);
5530 removerecordregions(begoff);
5539 len = cvtnum(dash_arith(p + 2));
5542 recordregion(begoff, begoff + len, 0);
5546 /* argstr needs it */
5547 static char *evalvar(char *p, int flag, struct strlist *var_str_list);
5550 * Perform variable and command substitution. If EXP_FULL is set, output CTLESC
5551 * characters to allow for further processing. Otherwise treat
5552 * $@ like $* since no splitting will be performed.
5554 * var_str_list (can be NULL) is a list of "VAR=val" strings which take precedence
5555 * over shell varables. Needed for "A=a B=$A; echo $B" case - we use it
5556 * for correct expansion of "B=$A" word.
5559 argstr(char *p, int flag, struct strlist *var_str_list)
5561 static const char spclchars[] ALIGN1 = {
5569 CTLBACKQ | CTLQUOTE,
5570 #if ENABLE_ASH_MATH_SUPPORT
5575 const char *reject = spclchars;
5577 int quotes = flag & (EXP_FULL | EXP_CASE); /* do CTLESC */
5578 int breakall = flag & EXP_WORD;
5583 if (!(flag & EXP_VARTILDE)) {
5585 } else if (flag & EXP_VARTILDE2) {
5590 if (flag & EXP_TILDE) {
5596 if (*q == CTLESC && (flag & EXP_QWORD))
5599 p = exptilde(p, q, flag);
5602 startloc = expdest - (char *)stackblock();
5604 length += strcspn(p + length, reject);
5606 if (c && (!(c & 0x80)
5607 #if ENABLE_ASH_MATH_SUPPORT
5611 /* c == '=' || c == ':' || c == CTLENDARI */
5616 expdest = stack_nputstr(p, length, expdest);
5617 newloc = expdest - (char *)stackblock();
5618 if (breakall && !inquotes && newloc > startloc) {
5619 recordregion(startloc, newloc, 0);
5630 if (flag & EXP_VARTILDE2) {
5634 flag |= EXP_VARTILDE2;
5639 * sort of a hack - expand tildes in variable
5640 * assignments (after the first '=' and after ':'s).
5649 case CTLENDVAR: /* ??? */
5652 /* "$@" syntax adherence hack */
5655 !memcmp(p, dolatstr, 4) &&
5656 (p[4] == CTLQUOTEMARK || (
5657 p[4] == CTLENDVAR &&
5658 p[5] == CTLQUOTEMARK
5661 p = evalvar(p + 1, flag, /* var_str_list: */ NULL) + 1;
5664 inquotes = !inquotes;
5677 p = evalvar(p, flag, var_str_list);
5681 case CTLBACKQ|CTLQUOTE:
5682 expbackq(argbackq->n, c, quotes);
5683 argbackq = argbackq->next;
5685 #if ENABLE_ASH_MATH_SUPPORT
5698 scanleft(char *startp, char *rmesc, char *rmescend UNUSED_PARAM, char *str, int quotes,
5701 // This commented out code was added by James Simmons <jsimmons@infradead.org>
5702 // as part of a larger change when he added support for ${var/a/b}.
5703 // However, it broke # and % operators:
5707 //echo ${var#ab} abcdcd abcdcd
5708 //echo ${var##ab} abcdcd abcdcd
5709 //echo ${var#a*b} abcdcd ababcdcd (!)
5710 //echo ${var##a*b} cdcd cdcd
5711 //echo ${var#?} babcdcd ababcdcd (!)
5712 //echo ${var##?} babcdcd babcdcd
5713 //echo ${var#*} ababcdcd babcdcd (!)
5715 //echo ${var%cd} ababcd ababcd
5716 //echo ${var%%cd} ababcd abab (!)
5717 //echo ${var%c*d} ababcd ababcd
5718 //echo ${var%%c*d} abab ababcdcd (!)
5719 //echo ${var%?} ababcdc ababcdc
5720 //echo ${var%%?} ababcdc ababcdcd (!)
5721 //echo ${var%*} ababcdcd ababcdcd
5724 // Commenting it back out helped. Remove it completely if it really
5727 char *loc, *loc2; //, *full;
5733 int match; // = strlen(str);
5734 const char *s = loc2;
5741 match = pmatch(str, s); // this line was deleted
5743 // // chop off end if its '*'
5744 // full = strrchr(str, '*');
5745 // if (full && full != str)
5748 // // If str starts with '*' replace with s.
5749 // if ((*str == '*') && strlen(s) >= match) {
5750 // full = xstrdup(s);
5751 // strncpy(full+strlen(s)-match+1, str+1, match-1);
5753 // full = xstrndup(str, match);
5754 // match = strncmp(s, full, strlen(full));
5758 if (match) // if (!match)
5760 if (quotes && *loc == CTLESC)
5769 scanright(char *startp, char *rmesc, char *rmescend, char *str, int quotes,
5776 for (loc = str - 1, loc2 = rmescend; loc >= startp; loc2--) {
5779 const char *s = loc2;
5784 match = pmatch(str, s);
5791 esc = esclen(startp, loc);
5802 static void varunset(const char *, const char *, const char *, int) NORETURN;
5804 varunset(const char *end, const char *var, const char *umsg, int varflags)
5810 msg = "parameter not set";
5812 if (*end == CTLENDVAR) {
5813 if (varflags & VSNUL)
5818 ash_msg_and_raise_error("%.*s: %s%s", end - var - 1, var, msg, tail);
5821 #if ENABLE_ASH_BASH_COMPAT
5823 parse_sub_pattern(char *arg, int inquotes)
5825 char *idx, *repl = NULL;
5834 /* Only the first '/' seen is our separator */
5841 if (!inquotes && c == '\\' && arg[1] == '\\')
5842 arg++; /* skip both \\, not just first one */
5849 #endif /* ENABLE_ASH_BASH_COMPAT */
5852 subevalvar(char *p, char *str, int strloc, int subtype,
5853 int startloc, int varflags, int quotes, struct strlist *var_str_list)
5855 struct nodelist *saveargbackq = argbackq;
5858 char *rmesc, *rmescend;
5859 USE_ASH_BASH_COMPAT(char *repl = NULL;)
5860 USE_ASH_BASH_COMPAT(char null = '\0';)
5861 USE_ASH_BASH_COMPAT(int pos, len, orig_len;)
5862 int saveherefd = herefd;
5863 int amount, workloc, resetloc;
5865 char *(*scan)(char*, char*, char*, char*, int, int);
5868 argstr(p, (subtype != VSASSIGN && subtype != VSQUESTION) ? EXP_CASE : 0,
5870 STPUTC('\0', expdest);
5871 herefd = saveherefd;
5872 argbackq = saveargbackq;
5873 startp = (char *)stackblock() + startloc;
5877 setvar(str, startp, 0);
5878 amount = startp - expdest;
5879 STADJUST(amount, expdest);
5882 #if ENABLE_ASH_BASH_COMPAT
5884 loc = str = stackblock() + strloc;
5885 // TODO: number() instead? It does error checking...
5887 len = str - startp - 1;
5889 /* *loc != '\0', guaranteed by parser */
5893 /* We must adjust the length by the number of escapes we find. */
5894 for (ptr = startp; ptr < (str - 1); ptr++) {
5895 if(*ptr == CTLESC) {
5903 if (*loc++ == ':') {
5904 // TODO: number() instead? It does error checking...
5908 while (*loc && *loc != ':')
5911 // TODO: number() instead? It does error checking...
5914 if (pos >= orig_len) {
5918 if (len > (orig_len - pos))
5919 len = orig_len - pos;
5921 for (str = startp; pos; str++, pos--) {
5922 if (quotes && *str == CTLESC)
5925 for (loc = startp; len; len--) {
5926 if (quotes && *str == CTLESC)
5931 amount = loc - expdest;
5932 STADJUST(amount, expdest);
5937 varunset(p, str, startp, varflags);
5940 resetloc = expdest - (char *)stackblock();
5942 /* We'll comeback here if we grow the stack while handling
5943 * a VSREPLACE or VSREPLACEALL, since our pointers into the
5944 * stack will need rebasing, and we'll need to remove our work
5947 USE_ASH_BASH_COMPAT(restart:)
5949 amount = expdest - ((char *)stackblock() + resetloc);
5950 STADJUST(-amount, expdest);
5951 startp = (char *)stackblock() + startloc;
5954 rmescend = (char *)stackblock() + strloc;
5956 rmesc = _rmescapes(startp, RMESCAPE_ALLOC | RMESCAPE_GROW);
5957 if (rmesc != startp) {
5959 startp = (char *)stackblock() + startloc;
5963 str = (char *)stackblock() + strloc;
5964 preglob(str, varflags & VSQUOTE, 0);
5965 workloc = expdest - (char *)stackblock();
5967 #if ENABLE_ASH_BASH_COMPAT
5968 if (subtype == VSREPLACE || subtype == VSREPLACEALL) {
5969 char *idx, *end, *restart_detect;
5972 repl = parse_sub_pattern(str, varflags & VSQUOTE);
5977 /* If there's no pattern to match, return the expansion unmolested */
5985 loc = scanright(idx, rmesc, rmescend, str, quotes, 1);
5987 /* No match, advance */
5988 restart_detect = stackblock();
5989 STPUTC(*idx, expdest);
5990 if (quotes && *idx == CTLESC) {
5993 STPUTC(*idx, expdest);
5995 if (stackblock() != restart_detect)
6003 if (subtype == VSREPLACEALL) {
6005 if (quotes && *idx == CTLESC)
6013 for (loc = repl; *loc; loc++) {
6014 restart_detect = stackblock();
6015 STPUTC(*loc, expdest);
6016 if (stackblock() != restart_detect)
6021 if (subtype == VSREPLACE) {
6023 restart_detect = stackblock();
6024 STPUTC(*idx, expdest);
6025 if (stackblock() != restart_detect)
6034 /* We've put the replaced text into a buffer at workloc, now
6035 * move it to the right place and adjust the stack.
6037 startp = stackblock() + startloc;
6038 STPUTC('\0', expdest);
6039 memmove(startp, stackblock() + workloc, len);
6040 startp[len++] = '\0';
6041 amount = expdest - ((char *)stackblock() + startloc + len - 1);
6042 STADJUST(-amount, expdest);
6045 #endif /* ENABLE_ASH_BASH_COMPAT */
6047 subtype -= VSTRIMRIGHT;
6049 if (subtype < 0 || subtype > 7)
6052 /* zero = subtype == VSTRIMLEFT || subtype == VSTRIMLEFTMAX */
6053 zero = subtype >> 1;
6054 /* VSTRIMLEFT/VSTRIMRIGHTMAX -> scanleft */
6055 scan = (subtype & 1) ^ zero ? scanleft : scanright;
6057 loc = scan(startp, rmesc, rmescend, str, quotes, zero);
6060 memmove(startp, loc, str - loc);
6061 loc = startp + (str - loc) - 1;
6064 amount = loc - expdest;
6065 STADJUST(amount, expdest);
6071 * Add the value of a specialized variable to the stack string.
6074 varvalue(char *name, int varflags, int flags, struct strlist *var_str_list)
6084 int quoted = varflags & VSQUOTE;
6085 int subtype = varflags & VSTYPE;
6086 int quotes = flags & (EXP_FULL | EXP_CASE);
6088 if (quoted && (flags & EXP_FULL))
6089 sep = 1 << CHAR_BIT;
6091 syntax = quoted ? DQSYNTAX : BASESYNTAX;
6100 num = shellparam.nparam;
6110 p = makestrspace(NOPTS, expdest);
6111 for (i = NOPTS - 1; i >= 0; i--) {
6113 USTPUTC(optletters(i), p);
6124 sep = ifsset() ? signed_char2int(ifsval()[0]) : ' ';
6125 if (quotes && (SIT(sep, syntax) == CCTL || SIT(sep, syntax) == CBACK))
6131 while ((p = *ap++)) {
6134 partlen = strlen(p);
6137 if (!(subtype == VSPLUS || subtype == VSLENGTH))
6138 memtodest(p, partlen, syntax, quotes);
6144 if (subtype == VSPLUS || subtype == VSLENGTH) {
6165 // TODO: number() instead? It does error checking...
6167 if (num < 0 || num > shellparam.nparam)
6169 p = num ? shellparam.p[num - 1] : arg0;
6172 /* NB: name has form "VAR=..." */
6174 /* "A=a B=$A" case: var_str_list is a list of "A=a" strings
6175 * which should be considered before we check variables. */
6177 unsigned name_len = (strchrnul(name, '=') - name) + 1;
6181 str = var_str_list->text;
6182 eq = strchr(str, '=');
6183 if (!eq) /* stop at first non-assignment */
6186 if (name_len == (unsigned)(eq - str)
6187 && strncmp(str, name, name_len) == 0) {
6189 /* goto value; - WRONG! */
6190 /* think "A=1 A=2 B=$A" */
6192 var_str_list = var_str_list->next;
6193 } while (var_str_list);
6197 p = lookupvar(name);
6203 if (!(subtype == VSPLUS || subtype == VSLENGTH))
6204 memtodest(p, len, syntax, quotes);
6208 if (subtype == VSPLUS || subtype == VSLENGTH)
6209 STADJUST(-len, expdest);
6214 * Expand a variable, and return a pointer to the next character in the
6218 evalvar(char *p, int flag, struct strlist *var_str_list)
6230 subtype = varflags & VSTYPE;
6231 quoted = varflags & VSQUOTE;
6233 easy = (!quoted || (*var == '@' && shellparam.nparam));
6234 startloc = expdest - (char *)stackblock();
6235 p = strchr(p, '=') + 1;
6238 varlen = varvalue(var, varflags, flag, var_str_list);
6239 if (varflags & VSNUL)
6242 if (subtype == VSPLUS) {
6243 varlen = -1 - varlen;
6247 if (subtype == VSMINUS) {
6251 p, flag | EXP_TILDE |
6252 (quoted ? EXP_QWORD : EXP_WORD),
6262 if (subtype == VSASSIGN || subtype == VSQUESTION) {
6264 if (subevalvar(p, var, /* strloc: */ 0,
6265 subtype, startloc, varflags,
6271 * Remove any recorded regions beyond
6274 removerecordregions(startloc);
6284 if (varlen < 0 && uflag)
6285 varunset(p, var, 0, 0);
6287 if (subtype == VSLENGTH) {
6288 cvtnum(varlen > 0 ? varlen : 0);
6292 if (subtype == VSNORMAL) {
6303 case VSTRIMRIGHTMAX:
6304 #if ENABLE_ASH_BASH_COMPAT
6317 * Terminate the string and start recording the pattern
6320 STPUTC('\0', expdest);
6321 patloc = expdest - (char *)stackblock();
6322 if (0 == subevalvar(p, /* str: */ NULL, patloc, subtype,
6324 /* quotes: */ flag & (EXP_FULL | EXP_CASE),
6327 int amount = expdest - (
6328 (char *)stackblock() + patloc - 1
6330 STADJUST(-amount, expdest);
6332 /* Remove any recorded regions beyond start of variable */
6333 removerecordregions(startloc);
6335 recordregion(startloc, expdest - (char *)stackblock(), quoted);
6339 if (subtype != VSNORMAL) { /* skip to end of alternative */
6345 else if (c == CTLBACKQ || c == (CTLBACKQ|CTLQUOTE)) {
6347 argbackq = argbackq->next;
6348 } else if (c == CTLVAR) {
6349 if ((*p++ & VSTYPE) != VSNORMAL)
6351 } else if (c == CTLENDVAR) {
6361 * Break the argument string into pieces based upon IFS and add the
6362 * strings to the argument list. The regions of the string to be
6363 * searched for IFS characters have been stored by recordregion.
6366 ifsbreakup(char *string, struct arglist *arglist)
6368 struct ifsregion *ifsp;
6373 const char *ifs, *realifs;
6378 if (ifslastp != NULL) {
6381 realifs = ifsset() ? ifsval() : defifs;
6384 p = string + ifsp->begoff;
6385 nulonly = ifsp->nulonly;
6386 ifs = nulonly ? nullstr : realifs;
6388 while (p < string + ifsp->endoff) {
6392 if (!strchr(ifs, *p)) {
6397 ifsspc = (strchr(defifs, *p) != NULL);
6398 /* Ignore IFS whitespace at start */
6399 if (q == start && ifsspc) {
6405 sp = stzalloc(sizeof(*sp));
6407 *arglist->lastp = sp;
6408 arglist->lastp = &sp->next;
6412 if (p >= string + ifsp->endoff) {
6418 if (strchr(ifs, *p) == NULL) {
6422 if (strchr(defifs, *p) == NULL) {
6437 } while (ifsp != NULL);
6446 sp = stzalloc(sizeof(*sp));
6448 *arglist->lastp = sp;
6449 arglist->lastp = &sp->next;
6455 struct ifsregion *p;
6460 struct ifsregion *ifsp;
6466 ifsfirst.next = NULL;
6471 * Add a file name to the list.
6474 addfname(const char *name)
6478 sp = stzalloc(sizeof(*sp));
6479 sp->text = ststrdup(name);
6481 exparg.lastp = &sp->next;
6484 static char *expdir;
6487 * Do metacharacter (i.e. *, ?, [...]) expansion.
6490 expmeta(char *enddir, char *name)
6505 for (p = name; *p; p++) {
6506 if (*p == '*' || *p == '?')
6508 else if (*p == '[') {
6515 if (*q == '/' || *q == '\0')
6522 } else if (*p == '\\')
6524 else if (*p == '/') {
6531 if (metaflag == 0) { /* we've reached the end of the file name */
6532 if (enddir != expdir)
6540 if (metaflag == 0 || lstat(expdir, &statb) >= 0)
6551 } while (p < start);
6553 if (enddir == expdir) {
6555 } else if (enddir == expdir + 1 && *expdir == '/') {
6564 if (enddir != expdir)
6566 if (*endname == 0) {
6578 while (!intpending && (dp = readdir(dirp)) != NULL) {
6579 if (dp->d_name[0] == '.' && !matchdot)
6581 if (pmatch(start, dp->d_name)) {
6583 strcpy(enddir, dp->d_name);
6586 for (p = enddir, cp = dp->d_name; (*p++ = *cp++) != '\0';)
6589 expmeta(p, endname);
6598 static struct strlist *
6599 msort(struct strlist *list, int len)
6601 struct strlist *p, *q = NULL;
6602 struct strlist **lpp;
6610 for (n = half; --n >= 0;) {
6614 q->next = NULL; /* terminate first half of list */
6615 q = msort(list, half); /* sort first half of list */
6616 p = msort(p, len - half); /* sort second half */
6619 #if ENABLE_LOCALE_SUPPORT
6620 if (strcoll(p->text, q->text) < 0)
6622 if (strcmp(p->text, q->text) < 0)
6646 * Sort the results of file name expansion. It calculates the number of
6647 * strings to sort and then calls msort (short for merge sort) to do the
6650 static struct strlist *
6651 expsort(struct strlist *str)
6657 for (sp = str; sp; sp = sp->next)
6659 return msort(str, len);
6663 expandmeta(struct strlist *str /*, int flag*/)
6665 static const char metachars[] ALIGN1 = {
6668 /* TODO - EXP_REDIR */
6671 struct strlist **savelastp;
6677 if (!strpbrk(str->text, metachars))
6679 savelastp = exparg.lastp;
6682 p = preglob(str->text, 0, RMESCAPE_ALLOC | RMESCAPE_HEAP);
6684 int i = strlen(str->text);
6685 expdir = ckmalloc(i < 2048 ? 2048 : i); /* XXX */
6693 if (exparg.lastp == savelastp) {
6698 *exparg.lastp = str;
6699 rmescapes(str->text);
6700 exparg.lastp = &str->next;
6702 *exparg.lastp = NULL;
6703 *savelastp = sp = expsort(*savelastp);
6704 while (sp->next != NULL)
6706 exparg.lastp = &sp->next;
6713 * Perform variable substitution and command substitution on an argument,
6714 * placing the resulting list of arguments in arglist. If EXP_FULL is true,
6715 * perform splitting and file name expansion. When arglist is NULL, perform
6716 * here document expansion.
6719 expandarg(union node *arg, struct arglist *arglist, int flag)
6724 argbackq = arg->narg.backquote;
6725 STARTSTACKSTR(expdest);
6726 ifsfirst.next = NULL;
6728 argstr(arg->narg.text, flag,
6729 /* var_str_list: */ arglist ? arglist->list : NULL);
6730 p = _STPUTC('\0', expdest);
6732 if (arglist == NULL) {
6733 return; /* here document expanded */
6735 p = grabstackstr(p);
6736 exparg.lastp = &exparg.list;
6740 if (flag & EXP_FULL) {
6741 ifsbreakup(p, &exparg);
6742 *exparg.lastp = NULL;
6743 exparg.lastp = &exparg.list;
6744 expandmeta(exparg.list /*, flag*/);
6746 if (flag & EXP_REDIR) /*XXX - for now, just remove escapes */
6748 sp = stzalloc(sizeof(*sp));
6751 exparg.lastp = &sp->next;
6755 *exparg.lastp = NULL;
6757 *arglist->lastp = exparg.list;
6758 arglist->lastp = exparg.lastp;
6763 * Expand shell variables and backquotes inside a here document.
6766 expandhere(union node *arg, int fd)
6769 expandarg(arg, (struct arglist *)NULL, 0);
6770 full_write(fd, stackblock(), expdest - (char *)stackblock());
6774 * Returns true if the pattern matches the string.
6777 patmatch(char *pattern, const char *string)
6779 return pmatch(preglob(pattern, 0, 0), string);
6783 * See if a pattern matches in a case statement.
6786 casematch(union node *pattern, char *val)
6788 struct stackmark smark;
6791 setstackmark(&smark);
6792 argbackq = pattern->narg.backquote;
6793 STARTSTACKSTR(expdest);
6795 argstr(pattern->narg.text, EXP_TILDE | EXP_CASE,
6796 /* var_str_list: */ NULL);
6797 STACKSTRNUL(expdest);
6798 result = patmatch(stackblock(), val);
6799 popstackmark(&smark);
6804 /* ============ find_command */
6808 int (*builtin)(int, char **);
6809 /* unsigned flags; */
6811 #define IS_BUILTIN_SPECIAL(b) ((b)->name[0] & 1)
6812 /* "regular" builtins always take precedence over commands,
6813 * regardless of PATH=....%builtin... position */
6814 #define IS_BUILTIN_REGULAR(b) ((b)->name[0] & 2)
6815 #define IS_BUILTIN_ASSIGN(b) ((b)->name[0] & 4)
6818 smallint cmdtype; /* CMDxxx */
6821 /* index >= 0 for commands without path (slashes) */
6822 /* (TODO: what exactly does the value mean? PATH position?) */
6823 /* index == -1 for commands with slashes */
6824 /* index == (-2 - applet_no) for NOFORK applets */
6825 const struct builtincmd *cmd;
6826 struct funcnode *func;
6829 /* values of cmdtype */
6830 #define CMDUNKNOWN -1 /* no entry in table for command */
6831 #define CMDNORMAL 0 /* command is an executable program */
6832 #define CMDFUNCTION 1 /* command is a shell function */
6833 #define CMDBUILTIN 2 /* command is a shell builtin */
6835 /* action to find_command() */
6836 #define DO_ERR 0x01 /* prints errors */
6837 #define DO_ABS 0x02 /* checks absolute paths */
6838 #define DO_NOFUNC 0x04 /* don't return shell functions, for command */
6839 #define DO_ALTPATH 0x08 /* using alternate path */
6840 #define DO_ALTBLTIN 0x20 /* %builtin in alt. path */
6842 static void find_command(char *, struct cmdentry *, int, const char *);
6845 /* ============ Hashing commands */
6848 * When commands are first encountered, they are entered in a hash table.
6849 * This ensures that a full path search will not have to be done for them
6850 * on each invocation.
6852 * We should investigate converting to a linear search, even though that
6853 * would make the command name "hash" a misnomer.
6857 struct tblentry *next; /* next entry in hash chain */
6858 union param param; /* definition of builtin function */
6859 smallint cmdtype; /* CMDxxx */
6860 char rehash; /* if set, cd done since entry created */
6861 char cmdname[1]; /* name of command */
6864 static struct tblentry **cmdtable;
6865 #define INIT_G_cmdtable() do { \
6866 cmdtable = xzalloc(CMDTABLESIZE * sizeof(cmdtable[0])); \
6869 static int builtinloc = -1; /* index in path of %builtin, or -1 */
6873 tryexec(USE_FEATURE_SH_STANDALONE(int applet_no,) char *cmd, char **argv, char **envp)
6877 #if ENABLE_FEATURE_SH_STANDALONE
6878 if (applet_no >= 0) {
6879 if (APPLET_IS_NOEXEC(applet_no))
6880 run_applet_no_and_exit(applet_no, argv);
6881 /* re-exec ourselves with the new arguments */
6882 execve(bb_busybox_exec_path, argv, envp);
6883 /* If they called chroot or otherwise made the binary no longer
6884 * executable, fall through */
6891 execve(cmd, argv, envp);
6892 } while (errno == EINTR);
6894 execve(cmd, argv, envp);
6900 if (errno == ENOEXEC) {
6904 for (ap = argv; *ap; ap++)
6906 ap = new = ckmalloc((ap - argv + 2) * sizeof(ap[0]));
6908 ap[0] = cmd = (char *)DEFAULT_SHELL;
6911 while ((*ap++ = *argv++) != NULL)
6920 * Exec a program. Never returns. If you change this routine, you may
6921 * have to change the find_command routine as well.
6923 static void shellexec(char **, const char *, int) NORETURN;
6925 shellexec(char **argv, const char *path, int idx)
6931 #if ENABLE_FEATURE_SH_STANDALONE
6936 envp = listvars(VEXPORT, VUNSET, 0);
6937 if (strchr(argv[0], '/') != NULL
6938 #if ENABLE_FEATURE_SH_STANDALONE
6939 || (applet_no = find_applet_by_name(argv[0])) >= 0
6942 tryexec(USE_FEATURE_SH_STANDALONE(applet_no,) argv[0], argv, envp);
6946 while ((cmdname = padvance(&path, argv[0])) != NULL) {
6947 if (--idx < 0 && pathopt == NULL) {
6948 tryexec(USE_FEATURE_SH_STANDALONE(-1,) cmdname, argv, envp);
6949 if (errno != ENOENT && errno != ENOTDIR)
6956 /* Map to POSIX errors */
6968 exitstatus = exerrno;
6969 TRACE(("shellexec failed for %s, errno %d, suppressint %d\n",
6970 argv[0], e, suppressint));
6971 ash_msg_and_raise(EXEXEC, "%s: %s", argv[0], errmsg(e, "not found"));
6976 printentry(struct tblentry *cmdp)
6982 idx = cmdp->param.index;
6985 name = padvance(&path, cmdp->cmdname);
6987 } while (--idx >= 0);
6988 out1fmt("%s%s\n", name, (cmdp->rehash ? "*" : nullstr));
6992 * Clear out command entries. The argument specifies the first entry in
6993 * PATH which has changed.
6996 clearcmdentry(int firstchange)
6998 struct tblentry **tblp;
6999 struct tblentry **pp;
7000 struct tblentry *cmdp;
7003 for (tblp = cmdtable; tblp < &cmdtable[CMDTABLESIZE]; tblp++) {
7005 while ((cmdp = *pp) != NULL) {
7006 if ((cmdp->cmdtype == CMDNORMAL &&
7007 cmdp->param.index >= firstchange)
7008 || (cmdp->cmdtype == CMDBUILTIN &&
7009 builtinloc >= firstchange)
7022 * Locate a command in the command hash table. If "add" is nonzero,
7023 * add the command to the table if it is not already present. The
7024 * variable "lastcmdentry" is set to point to the address of the link
7025 * pointing to the entry, so that delete_cmd_entry can delete the
7028 * Interrupts must be off if called with add != 0.
7030 static struct tblentry **lastcmdentry;
7032 static struct tblentry *
7033 cmdlookup(const char *name, int add)
7035 unsigned int hashval;
7037 struct tblentry *cmdp;
7038 struct tblentry **pp;
7041 hashval = (unsigned char)*p << 4;
7043 hashval += (unsigned char)*p++;
7045 pp = &cmdtable[hashval % CMDTABLESIZE];
7046 for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
7047 if (strcmp(cmdp->cmdname, name) == 0)
7051 if (add && cmdp == NULL) {
7052 cmdp = *pp = ckzalloc(sizeof(struct tblentry)
7054 /* + 1 - already done because
7055 * tblentry::cmdname is char[1] */);
7056 /*cmdp->next = NULL; - ckzalloc did it */
7057 cmdp->cmdtype = CMDUNKNOWN;
7058 strcpy(cmdp->cmdname, name);
7065 * Delete the command entry returned on the last lookup.
7068 delete_cmd_entry(void)
7070 struct tblentry *cmdp;
7073 cmdp = *lastcmdentry;
7074 *lastcmdentry = cmdp->next;
7075 if (cmdp->cmdtype == CMDFUNCTION)
7076 freefunc(cmdp->param.func);
7082 * Add a new command entry, replacing any existing command entry for
7083 * the same name - except special builtins.
7086 addcmdentry(char *name, struct cmdentry *entry)
7088 struct tblentry *cmdp;
7090 cmdp = cmdlookup(name, 1);
7091 if (cmdp->cmdtype == CMDFUNCTION) {
7092 freefunc(cmdp->param.func);
7094 cmdp->cmdtype = entry->cmdtype;
7095 cmdp->param = entry->u;
7100 hashcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
7102 struct tblentry **pp;
7103 struct tblentry *cmdp;
7105 struct cmdentry entry;
7108 if (nextopt("r") != '\0') {
7113 if (*argptr == NULL) {
7114 for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
7115 for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
7116 if (cmdp->cmdtype == CMDNORMAL)
7124 while ((name = *argptr) != NULL) {
7125 cmdp = cmdlookup(name, 0);
7127 && (cmdp->cmdtype == CMDNORMAL
7128 || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0))
7132 find_command(name, &entry, DO_ERR, pathval());
7133 if (entry.cmdtype == CMDUNKNOWN)
7141 * Called when a cd is done. Marks all commands so the next time they
7142 * are executed they will be rehashed.
7147 struct tblentry **pp;
7148 struct tblentry *cmdp;
7150 for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
7151 for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
7152 if (cmdp->cmdtype == CMDNORMAL
7153 || (cmdp->cmdtype == CMDBUILTIN
7154 && !IS_BUILTIN_REGULAR(cmdp->param.cmd)
7164 * Fix command hash table when PATH changed.
7165 * Called before PATH is changed. The argument is the new value of PATH;
7166 * pathval() still returns the old value at this point.
7167 * Called with interrupts off.
7170 changepath(const char *new)
7178 firstchange = 9999; /* assume no change */
7184 if ((*old == '\0' && *new == ':')
7185 || (*old == ':' && *new == '\0'))
7187 old = new; /* ignore subsequent differences */
7191 if (*new == '%' && idx_bltin < 0 && prefix(new + 1, "builtin"))
7197 if (builtinloc < 0 && idx_bltin >= 0)
7198 builtinloc = idx_bltin; /* zap builtins */
7199 if (builtinloc >= 0 && idx_bltin < 0)
7201 clearcmdentry(firstchange);
7202 builtinloc = idx_bltin;
7217 #define TENDBQUOTE 12
7234 typedef smallint token_id_t;
7236 /* first char is indicating which tokens mark the end of a list */
7237 static const char *const tokname_array[] = {
7251 #define KWDOFFSET 13
7252 /* the following are keywords */
7274 static char buf[16];
7277 //if (tok < TSEMI) return tokname_array[tok] + 1;
7278 //sprintf(buf, "\"%s\"", tokname_array[tok] + 1);
7283 sprintf(buf + (tok >= TSEMI), "%s%c",
7284 tokname_array[tok] + 1, (tok >= TSEMI ? '"' : 0));
7288 /* Wrapper around strcmp for qsort/bsearch/... */
7290 pstrcmp(const void *a, const void *b)
7292 return strcmp((char*) a, (*(char**) b) + 1);
7295 static const char *const *
7296 findkwd(const char *s)
7298 return bsearch(s, tokname_array + KWDOFFSET,
7299 ARRAY_SIZE(tokname_array) - KWDOFFSET,
7300 sizeof(tokname_array[0]), pstrcmp);
7304 * Locate and print what a word is...
7307 describe_command(char *command, int describe_command_verbose)
7309 struct cmdentry entry;
7310 struct tblentry *cmdp;
7311 #if ENABLE_ASH_ALIAS
7312 const struct alias *ap;
7314 const char *path = pathval();
7316 if (describe_command_verbose) {
7320 /* First look at the keywords */
7321 if (findkwd(command)) {
7322 out1str(describe_command_verbose ? " is a shell keyword" : command);
7326 #if ENABLE_ASH_ALIAS
7327 /* Then look at the aliases */
7328 ap = lookupalias(command, 0);
7330 if (!describe_command_verbose) {
7335 out1fmt(" is an alias for %s", ap->val);
7339 /* Then check if it is a tracked alias */
7340 cmdp = cmdlookup(command, 0);
7342 entry.cmdtype = cmdp->cmdtype;
7343 entry.u = cmdp->param;
7345 /* Finally use brute force */
7346 find_command(command, &entry, DO_ABS, path);
7349 switch (entry.cmdtype) {
7351 int j = entry.u.index;
7357 p = padvance(&path, command);
7361 if (describe_command_verbose) {
7363 (cmdp ? " a tracked alias for" : nullstr), p
7372 if (describe_command_verbose) {
7373 out1str(" is a shell function");
7380 if (describe_command_verbose) {
7381 out1fmt(" is a %sshell builtin",
7382 IS_BUILTIN_SPECIAL(entry.u.cmd) ?
7383 "special " : nullstr
7391 if (describe_command_verbose) {
7392 out1str(": not found\n");
7397 outstr("\n", stdout);
7402 typecmd(int argc UNUSED_PARAM, char **argv)
7408 /* type -p ... ? (we don't bother checking for 'p') */
7409 if (argv[1] && argv[1][0] == '-') {
7414 err |= describe_command(argv[i++], verbose);
7419 #if ENABLE_ASH_CMDCMD
7421 commandcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
7429 while ((c = nextopt("pvV")) != '\0')
7431 verify |= VERIFY_VERBOSE;
7433 verify |= VERIFY_BRIEF;
7438 /* Mimic bash: just "command -v" doesn't complain, it's a nop */
7439 if (verify && (*argptr != NULL)) {
7440 return describe_command(*argptr, verify - VERIFY_BRIEF);
7448 /* ============ eval.c */
7450 static int funcblocksize; /* size of structures in function */
7451 static int funcstringsize; /* size of strings in node */
7452 static void *funcblock; /* block to allocate function from */
7453 static char *funcstring; /* block to allocate strings from */
7455 /* flags in argument to evaltree */
7456 #define EV_EXIT 01 /* exit after evaluating tree */
7457 #define EV_TESTED 02 /* exit status is checked; ignore -e flag */
7458 #define EV_BACKCMD 04 /* command executing within back quotes */
7460 static const short nodesize[26] = {
7461 SHELL_ALIGN(sizeof(struct ncmd)),
7462 SHELL_ALIGN(sizeof(struct npipe)),
7463 SHELL_ALIGN(sizeof(struct nredir)),
7464 SHELL_ALIGN(sizeof(struct nredir)),
7465 SHELL_ALIGN(sizeof(struct nredir)),
7466 SHELL_ALIGN(sizeof(struct nbinary)),
7467 SHELL_ALIGN(sizeof(struct nbinary)),
7468 SHELL_ALIGN(sizeof(struct nbinary)),
7469 SHELL_ALIGN(sizeof(struct nif)),
7470 SHELL_ALIGN(sizeof(struct nbinary)),
7471 SHELL_ALIGN(sizeof(struct nbinary)),
7472 SHELL_ALIGN(sizeof(struct nfor)),
7473 SHELL_ALIGN(sizeof(struct ncase)),
7474 SHELL_ALIGN(sizeof(struct nclist)),
7475 SHELL_ALIGN(sizeof(struct narg)),
7476 SHELL_ALIGN(sizeof(struct narg)),
7477 SHELL_ALIGN(sizeof(struct nfile)),
7478 SHELL_ALIGN(sizeof(struct nfile)),
7479 SHELL_ALIGN(sizeof(struct nfile)),
7480 SHELL_ALIGN(sizeof(struct nfile)),
7481 SHELL_ALIGN(sizeof(struct nfile)),
7482 SHELL_ALIGN(sizeof(struct ndup)),
7483 SHELL_ALIGN(sizeof(struct ndup)),
7484 SHELL_ALIGN(sizeof(struct nhere)),
7485 SHELL_ALIGN(sizeof(struct nhere)),
7486 SHELL_ALIGN(sizeof(struct nnot)),
7489 static void calcsize(union node *n);
7492 sizenodelist(struct nodelist *lp)
7495 funcblocksize += SHELL_ALIGN(sizeof(struct nodelist));
7502 calcsize(union node *n)
7506 funcblocksize += nodesize[n->type];
7509 calcsize(n->ncmd.redirect);
7510 calcsize(n->ncmd.args);
7511 calcsize(n->ncmd.assign);
7514 sizenodelist(n->npipe.cmdlist);
7519 calcsize(n->nredir.redirect);
7520 calcsize(n->nredir.n);
7527 calcsize(n->nbinary.ch2);
7528 calcsize(n->nbinary.ch1);
7531 calcsize(n->nif.elsepart);
7532 calcsize(n->nif.ifpart);
7533 calcsize(n->nif.test);
7536 funcstringsize += strlen(n->nfor.var) + 1;
7537 calcsize(n->nfor.body);
7538 calcsize(n->nfor.args);
7541 calcsize(n->ncase.cases);
7542 calcsize(n->ncase.expr);
7545 calcsize(n->nclist.body);
7546 calcsize(n->nclist.pattern);
7547 calcsize(n->nclist.next);
7551 sizenodelist(n->narg.backquote);
7552 funcstringsize += strlen(n->narg.text) + 1;
7553 calcsize(n->narg.next);
7560 calcsize(n->nfile.fname);
7561 calcsize(n->nfile.next);
7565 calcsize(n->ndup.vname);
7566 calcsize(n->ndup.next);
7570 calcsize(n->nhere.doc);
7571 calcsize(n->nhere.next);
7574 calcsize(n->nnot.com);
7580 nodeckstrdup(char *s)
7582 char *rtn = funcstring;
7584 strcpy(funcstring, s);
7585 funcstring += strlen(s) + 1;
7589 static union node *copynode(union node *);
7591 static struct nodelist *
7592 copynodelist(struct nodelist *lp)
7594 struct nodelist *start;
7595 struct nodelist **lpp;
7600 funcblock = (char *) funcblock + SHELL_ALIGN(sizeof(struct nodelist));
7601 (*lpp)->n = copynode(lp->n);
7603 lpp = &(*lpp)->next;
7610 copynode(union node *n)
7617 funcblock = (char *) funcblock + nodesize[n->type];
7621 new->ncmd.redirect = copynode(n->ncmd.redirect);
7622 new->ncmd.args = copynode(n->ncmd.args);
7623 new->ncmd.assign = copynode(n->ncmd.assign);
7626 new->npipe.cmdlist = copynodelist(n->npipe.cmdlist);
7627 new->npipe.pipe_backgnd = n->npipe.pipe_backgnd;
7632 new->nredir.redirect = copynode(n->nredir.redirect);
7633 new->nredir.n = copynode(n->nredir.n);
7640 new->nbinary.ch2 = copynode(n->nbinary.ch2);
7641 new->nbinary.ch1 = copynode(n->nbinary.ch1);
7644 new->nif.elsepart = copynode(n->nif.elsepart);
7645 new->nif.ifpart = copynode(n->nif.ifpart);
7646 new->nif.test = copynode(n->nif.test);
7649 new->nfor.var = nodeckstrdup(n->nfor.var);
7650 new->nfor.body = copynode(n->nfor.body);
7651 new->nfor.args = copynode(n->nfor.args);
7654 new->ncase.cases = copynode(n->ncase.cases);
7655 new->ncase.expr = copynode(n->ncase.expr);
7658 new->nclist.body = copynode(n->nclist.body);
7659 new->nclist.pattern = copynode(n->nclist.pattern);
7660 new->nclist.next = copynode(n->nclist.next);
7664 new->narg.backquote = copynodelist(n->narg.backquote);
7665 new->narg.text = nodeckstrdup(n->narg.text);
7666 new->narg.next = copynode(n->narg.next);
7673 new->nfile.fname = copynode(n->nfile.fname);
7674 new->nfile.fd = n->nfile.fd;
7675 new->nfile.next = copynode(n->nfile.next);
7679 new->ndup.vname = copynode(n->ndup.vname);
7680 new->ndup.dupfd = n->ndup.dupfd;
7681 new->ndup.fd = n->ndup.fd;
7682 new->ndup.next = copynode(n->ndup.next);
7686 new->nhere.doc = copynode(n->nhere.doc);
7687 new->nhere.fd = n->nhere.fd;
7688 new->nhere.next = copynode(n->nhere.next);
7691 new->nnot.com = copynode(n->nnot.com);
7694 new->type = n->type;
7699 * Make a copy of a parse tree.
7701 static struct funcnode *
7702 copyfunc(union node *n)
7707 funcblocksize = offsetof(struct funcnode, n);
7710 blocksize = funcblocksize;
7711 f = ckmalloc(blocksize + funcstringsize);
7712 funcblock = (char *) f + offsetof(struct funcnode, n);
7713 funcstring = (char *) f + blocksize;
7720 * Define a shell function.
7723 defun(char *name, union node *func)
7725 struct cmdentry entry;
7728 entry.cmdtype = CMDFUNCTION;
7729 entry.u.func = copyfunc(func);
7730 addcmdentry(name, &entry);
7734 static int evalskip; /* set if we are skipping commands */
7735 /* reasons for skipping commands (see comment on breakcmd routine) */
7736 #define SKIPBREAK (1 << 0)
7737 #define SKIPCONT (1 << 1)
7738 #define SKIPFUNC (1 << 2)
7739 #define SKIPFILE (1 << 3)
7740 #define SKIPEVAL (1 << 4)
7741 static int skipcount; /* number of levels to skip */
7742 static int funcnest; /* depth of function calls */
7743 static int loopnest; /* current loop nesting level */
7745 /* forward decl way out to parsing code - dotrap needs it */
7746 static int evalstring(char *s, int mask);
7749 * Called to execute a trap. Perhaps we should avoid entering new trap
7750 * handlers while we are executing a trap handler.
7761 savestatus = exitstatus;
7765 for (i = 0, q = gotsig; i < NSIG - 1; i++, q++) {
7773 skip = evalstring(p, SKIPEVAL);
7774 exitstatus = savestatus;
7782 /* forward declarations - evaluation is fairly recursive business... */
7783 static void evalloop(union node *, int);
7784 static void evalfor(union node *, int);
7785 static void evalcase(union node *, int);
7786 static void evalsubshell(union node *, int);
7787 static void expredir(union node *);
7788 static void evalpipe(union node *, int);
7789 static void evalcommand(union node *, int);
7790 static int evalbltin(const struct builtincmd *, int, char **);
7791 static void prehash(union node *);
7794 * Evaluate a parse tree. The value is left in the global variable
7798 evaltree(union node *n, int flags)
7801 void (*evalfn)(union node *, int);
7805 TRACE(("evaltree(NULL) called\n"));
7808 TRACE(("pid %d, evaltree(%p: %d, %d) called\n",
7809 getpid(), n, n->type, flags));
7813 out1fmt("Node type = %d\n", n->type);
7818 evaltree(n->nnot.com, EV_TESTED);
7819 status = !exitstatus;
7822 expredir(n->nredir.redirect);
7823 status = redirectsafe(n->nredir.redirect, REDIR_PUSH);
7825 evaltree(n->nredir.n, flags & EV_TESTED);
7826 status = exitstatus;
7831 evalfn = evalcommand;
7833 if (eflag && !(flags & EV_TESTED))
7845 evalfn = evalsubshell;
7857 #error NAND + 1 != NOR
7859 #if NOR + 1 != NSEMI
7860 #error NOR + 1 != NSEMI
7862 isor = n->type - NAND;
7865 (flags | ((isor >> 1) - 1)) & EV_TESTED
7867 if (!exitstatus == isor)
7879 evaltree(n->nif.test, EV_TESTED);
7882 if (exitstatus == 0) {
7885 } else if (n->nif.elsepart) {
7886 n = n->nif.elsepart;
7891 defun(n->narg.text, n->narg.next);
7895 exitstatus = status;
7899 if ((checkexit & exitstatus))
7900 evalskip |= SKIPEVAL;
7901 else if (pendingsig && dotrap())
7904 if (flags & EV_EXIT) {
7906 raise_exception(EXEXIT);
7910 #if !defined(__alpha__) || (defined(__GNUC__) && __GNUC__ >= 3)
7913 void evaltreenr(union node *, int) __attribute__ ((alias("evaltree"),__noreturn__));
7916 evalloop(union node *n, int flags)
7926 evaltree(n->nbinary.ch1, EV_TESTED);
7929 if (evalskip == SKIPCONT && --skipcount <= 0) {
7933 if (evalskip == SKIPBREAK && --skipcount <= 0)
7938 if (n->type != NWHILE)
7942 evaltree(n->nbinary.ch2, flags);
7943 status = exitstatus;
7948 exitstatus = status;
7952 evalfor(union node *n, int flags)
7954 struct arglist arglist;
7957 struct stackmark smark;
7959 setstackmark(&smark);
7960 arglist.list = NULL;
7961 arglist.lastp = &arglist.list;
7962 for (argp = n->nfor.args; argp; argp = argp->narg.next) {
7963 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE | EXP_RECORD);
7968 *arglist.lastp = NULL;
7973 for (sp = arglist.list; sp; sp = sp->next) {
7974 setvar(n->nfor.var, sp->text, 0);
7975 evaltree(n->nfor.body, flags);
7977 if (evalskip == SKIPCONT && --skipcount <= 0) {
7981 if (evalskip == SKIPBREAK && --skipcount <= 0)
7988 popstackmark(&smark);
7992 evalcase(union node *n, int flags)
7996 struct arglist arglist;
7997 struct stackmark smark;
7999 setstackmark(&smark);
8000 arglist.list = NULL;
8001 arglist.lastp = &arglist.list;
8002 expandarg(n->ncase.expr, &arglist, EXP_TILDE);
8004 for (cp = n->ncase.cases; cp && evalskip == 0; cp = cp->nclist.next) {
8005 for (patp = cp->nclist.pattern; patp; patp = patp->narg.next) {
8006 if (casematch(patp, arglist.list->text)) {
8007 if (evalskip == 0) {
8008 evaltree(cp->nclist.body, flags);
8015 popstackmark(&smark);
8019 * Kick off a subshell to evaluate a tree.
8022 evalsubshell(union node *n, int flags)
8025 int backgnd = (n->type == NBACKGND);
8028 expredir(n->nredir.redirect);
8029 if (!backgnd && flags & EV_EXIT && !trap[0])
8032 jp = makejob(/*n,*/ 1);
8033 if (forkshell(jp, n, backgnd) == 0) {
8037 flags &=~ EV_TESTED;
8039 redirect(n->nredir.redirect, 0);
8040 evaltreenr(n->nredir.n, flags);
8045 status = waitforjob(jp);
8046 exitstatus = status;
8051 * Compute the names of the files in a redirection list.
8053 static void fixredir(union node *, const char *, int);
8055 expredir(union node *n)
8059 for (redir = n; redir; redir = redir->nfile.next) {
8063 fn.lastp = &fn.list;
8064 switch (redir->type) {
8070 expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
8071 redir->nfile.expfname = fn.list->text;
8075 if (redir->ndup.vname) {
8076 expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE);
8077 if (fn.list == NULL)
8078 ash_msg_and_raise_error("redir error");
8079 fixredir(redir, fn.list->text, 1);
8087 * Evaluate a pipeline. All the processes in the pipeline are children
8088 * of the process creating the pipeline. (This differs from some versions
8089 * of the shell, which make the last process in a pipeline the parent
8093 evalpipe(union node *n, int flags)
8096 struct nodelist *lp;
8101 TRACE(("evalpipe(0x%lx) called\n", (long)n));
8103 for (lp = n->npipe.cmdlist; lp; lp = lp->next)
8107 jp = makejob(/*n,*/ pipelen);
8109 for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
8113 if (pipe(pip) < 0) {
8115 ash_msg_and_raise_error("pipe call failed");
8118 if (forkshell(jp, lp->n, n->npipe.pipe_backgnd) == 0) {
8131 evaltreenr(lp->n, flags);
8139 if (n->npipe.pipe_backgnd == 0) {
8140 exitstatus = waitforjob(jp);
8141 TRACE(("evalpipe: job done exit status %d\n", exitstatus));
8147 * Controls whether the shell is interactive or not.
8150 setinteractive(int on)
8152 static smallint is_interactive;
8154 if (++on == is_interactive)
8156 is_interactive = on;
8160 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
8161 if (is_interactive > 1) {
8162 /* Looks like they want an interactive shell */
8163 static smallint did_banner;
8168 "%s built-in shell (ash)\n"
8169 "Enter 'help' for a list of built-in commands."
8184 setinteractive(iflag);
8186 #if ENABLE_FEATURE_EDITING_VI
8188 line_input_state->flags |= VI_MODE;
8190 line_input_state->flags &= ~VI_MODE;
8192 viflag = 0; /* forcibly keep the option off */
8196 static struct localvar *localvars;
8199 * Called after a function returns.
8200 * Interrupts must be off.
8205 struct localvar *lvp;
8208 while ((lvp = localvars) != NULL) {
8209 localvars = lvp->next;
8211 TRACE(("poplocalvar %s", vp ? vp->text : "-"));
8212 if (vp == NULL) { /* $- saved */
8213 memcpy(optlist, lvp->text, sizeof(optlist));
8214 free((char*)lvp->text);
8216 } else if ((lvp->flags & (VUNSET|VSTRFIXED)) == VUNSET) {
8220 (*vp->func)(strchrnul(lvp->text, '=') + 1);
8221 if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
8222 free((char*)vp->text);
8223 vp->flags = lvp->flags;
8224 vp->text = lvp->text;
8231 evalfun(struct funcnode *func, int argc, char **argv, int flags)
8233 volatile struct shparam saveparam;
8234 struct localvar *volatile savelocalvars;
8235 struct jmploc *volatile savehandler;
8236 struct jmploc jmploc;
8239 saveparam = shellparam;
8240 savelocalvars = localvars;
8241 e = setjmp(jmploc.loc);
8246 savehandler = exception_handler;
8247 exception_handler = &jmploc;
8249 shellparam.malloced = 0;
8253 shellparam.nparam = argc - 1;
8254 shellparam.p = argv + 1;
8255 #if ENABLE_ASH_GETOPTS
8256 shellparam.optind = 1;
8257 shellparam.optoff = -1;
8259 evaltree(&func->n, flags & EV_TESTED);
8265 localvars = savelocalvars;
8266 freeparam(&shellparam);
8267 shellparam = saveparam;
8268 exception_handler = savehandler;
8270 evalskip &= ~SKIPFUNC;
8274 #if ENABLE_ASH_CMDCMD
8276 parse_command_args(char **argv, const char **path)
8289 if (c == '-' && !*cp) {
8296 *path = bb_default_path;
8299 /* run 'typecmd' for other options */
8310 * Make a variable a local variable. When a variable is made local, it's
8311 * value and flags are saved in a localvar structure. The saved values
8312 * will be restored when the shell function returns. We handle the name
8313 * "-" as a special case.
8318 struct localvar *lvp;
8323 lvp = ckzalloc(sizeof(struct localvar));
8324 if (LONE_DASH(name)) {
8326 p = ckmalloc(sizeof(optlist));
8327 lvp->text = memcpy(p, optlist, sizeof(optlist));
8332 vpp = hashvar(name);
8333 vp = *findvar(vpp, name);
8334 eq = strchr(name, '=');
8337 setvareq(name, VSTRFIXED);
8339 setvar(name, NULL, VSTRFIXED);
8340 vp = *vpp; /* the new variable */
8341 lvp->flags = VUNSET;
8343 lvp->text = vp->text;
8344 lvp->flags = vp->flags;
8345 vp->flags |= VSTRFIXED|VTEXTFIXED;
8351 lvp->next = localvars;
8357 * The "local" command.
8360 localcmd(int argc UNUSED_PARAM, char **argv)
8365 while ((name = *argv++) != NULL) {
8372 falsecmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
8378 truecmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
8384 execcmd(int argc UNUSED_PARAM, char **argv)
8387 iflag = 0; /* exit on error */
8390 shellexec(argv + 1, pathval(), 0);
8396 * The return command.
8399 returncmd(int argc UNUSED_PARAM, char **argv)
8402 * If called outside a function, do what ksh does;
8403 * skip the rest of the file.
8405 evalskip = funcnest ? SKIPFUNC : SKIPFILE;
8406 return argv[1] ? number(argv[1]) : exitstatus;
8409 /* Forward declarations for builtintab[] */
8410 static int breakcmd(int, char **);
8411 static int dotcmd(int, char **);
8412 static int evalcmd(int, char **);
8413 static int exitcmd(int, char **);
8414 static int exportcmd(int, char **);
8415 #if ENABLE_ASH_GETOPTS
8416 static int getoptscmd(int, char **);
8418 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
8419 static int helpcmd(int, char **);
8421 #if ENABLE_ASH_MATH_SUPPORT
8422 static int letcmd(int, char **);
8424 static int readcmd(int, char **);
8425 static int setcmd(int, char **);
8426 static int shiftcmd(int, char **);
8427 static int timescmd(int, char **);
8428 static int trapcmd(int, char **);
8429 static int umaskcmd(int, char **);
8430 static int unsetcmd(int, char **);
8431 static int ulimitcmd(int, char **);
8433 #define BUILTIN_NOSPEC "0"
8434 #define BUILTIN_SPECIAL "1"
8435 #define BUILTIN_REGULAR "2"
8436 #define BUILTIN_SPEC_REG "3"
8437 #define BUILTIN_ASSIGN "4"
8438 #define BUILTIN_SPEC_ASSG "5"
8439 #define BUILTIN_REG_ASSG "6"
8440 #define BUILTIN_SPEC_REG_ASSG "7"
8442 /* We do not handle [[ expr ]] bashism bash-compatibly,
8443 * we make it a synonym of [ expr ].
8444 * Basically, word splitting and pathname expansion should NOT be performed
8446 * no word splitting: a="a b"; [[ $a = "a b" ]]; echo $? should print "0"
8447 * no pathname expansion: [[ /bin/m* = "/bin/m*" ]]; echo $? should print "0"
8448 * Additional operators:
8449 * || and && should work as -o and -a
8451 * Apart from the above, [[ expr ]] should work as [ expr ]
8454 #define echocmd echo_main
8455 #define printfcmd printf_main
8456 #define testcmd test_main
8458 /* Keep these in proper order since it is searched via bsearch() */
8459 static const struct builtincmd builtintab[] = {
8460 { BUILTIN_SPEC_REG ".", dotcmd },
8461 { BUILTIN_SPEC_REG ":", truecmd },
8462 #if ENABLE_ASH_BUILTIN_TEST
8463 { BUILTIN_REGULAR "[", testcmd },
8464 #if ENABLE_ASH_BASH_COMPAT
8465 { BUILTIN_REGULAR "[[", testcmd },
8468 #if ENABLE_ASH_ALIAS
8469 { BUILTIN_REG_ASSG "alias", aliascmd },
8472 { BUILTIN_REGULAR "bg", fg_bgcmd },
8474 { BUILTIN_SPEC_REG "break", breakcmd },
8475 { BUILTIN_REGULAR "cd", cdcmd },
8476 { BUILTIN_NOSPEC "chdir", cdcmd },
8477 #if ENABLE_ASH_CMDCMD
8478 { BUILTIN_REGULAR "command", commandcmd },
8480 { BUILTIN_SPEC_REG "continue", breakcmd },
8481 #if ENABLE_ASH_BUILTIN_ECHO
8482 { BUILTIN_REGULAR "echo", echocmd },
8484 { BUILTIN_SPEC_REG "eval", evalcmd },
8485 { BUILTIN_SPEC_REG "exec", execcmd },
8486 { BUILTIN_SPEC_REG "exit", exitcmd },
8487 { BUILTIN_SPEC_REG_ASSG "export", exportcmd },
8488 { BUILTIN_REGULAR "false", falsecmd },
8490 { BUILTIN_REGULAR "fg", fg_bgcmd },
8492 #if ENABLE_ASH_GETOPTS
8493 { BUILTIN_REGULAR "getopts", getoptscmd },
8495 { BUILTIN_NOSPEC "hash", hashcmd },
8496 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
8497 { BUILTIN_NOSPEC "help", helpcmd },
8500 { BUILTIN_REGULAR "jobs", jobscmd },
8501 { BUILTIN_REGULAR "kill", killcmd },
8503 #if ENABLE_ASH_MATH_SUPPORT
8504 { BUILTIN_NOSPEC "let", letcmd },
8506 { BUILTIN_ASSIGN "local", localcmd },
8507 #if ENABLE_ASH_BUILTIN_PRINTF
8508 { BUILTIN_REGULAR "printf", printfcmd },
8510 { BUILTIN_NOSPEC "pwd", pwdcmd },
8511 { BUILTIN_REGULAR "read", readcmd },
8512 { BUILTIN_SPEC_REG_ASSG "readonly", exportcmd },
8513 { BUILTIN_SPEC_REG "return", returncmd },
8514 { BUILTIN_SPEC_REG "set", setcmd },
8515 { BUILTIN_SPEC_REG "shift", shiftcmd },
8516 { BUILTIN_SPEC_REG "source", dotcmd },
8517 #if ENABLE_ASH_BUILTIN_TEST
8518 { BUILTIN_REGULAR "test", testcmd },
8520 { BUILTIN_SPEC_REG "times", timescmd },
8521 { BUILTIN_SPEC_REG "trap", trapcmd },
8522 { BUILTIN_REGULAR "true", truecmd },
8523 { BUILTIN_NOSPEC "type", typecmd },
8524 { BUILTIN_NOSPEC "ulimit", ulimitcmd },
8525 { BUILTIN_REGULAR "umask", umaskcmd },
8526 #if ENABLE_ASH_ALIAS
8527 { BUILTIN_REGULAR "unalias", unaliascmd },
8529 { BUILTIN_SPEC_REG "unset", unsetcmd },
8530 { BUILTIN_REGULAR "wait", waitcmd },
8533 /* Should match the above table! */
8534 #define COMMANDCMD (builtintab + \
8536 1 * ENABLE_ASH_BUILTIN_TEST + \
8537 1 * ENABLE_ASH_BUILTIN_TEST * ENABLE_ASH_BASH_COMPAT + \
8538 1 * ENABLE_ASH_ALIAS + \
8539 1 * ENABLE_ASH_JOB_CONTROL + \
8541 #define EXECCMD (builtintab + \
8543 1 * ENABLE_ASH_BUILTIN_TEST + \
8544 1 * ENABLE_ASH_BUILTIN_TEST * ENABLE_ASH_BASH_COMPAT + \
8545 1 * ENABLE_ASH_ALIAS + \
8546 1 * ENABLE_ASH_JOB_CONTROL + \
8548 1 * ENABLE_ASH_CMDCMD + \
8550 ENABLE_ASH_BUILTIN_ECHO + \
8554 * Search the table of builtin commands.
8556 static struct builtincmd *
8557 find_builtin(const char *name)
8559 struct builtincmd *bp;
8562 name, builtintab, ARRAY_SIZE(builtintab), sizeof(builtintab[0]),
8569 * Execute a simple command.
8572 isassignment(const char *p)
8574 const char *q = endofname(p);
8580 bltincmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
8582 /* Preserve exitstatus of a previous possible redirection
8583 * as POSIX mandates */
8584 return back_exitstatus;
8587 evalcommand(union node *cmd, int flags)
8589 static const struct builtincmd null_bltin = {
8590 "\0\0", bltincmd /* why three NULs? */
8592 struct stackmark smark;
8594 struct arglist arglist;
8595 struct arglist varlist;
8598 const struct strlist *sp;
8599 struct cmdentry cmdentry;
8607 struct builtincmd *bcmd;
8608 int pseudovarflag = 0;
8610 /* First expand the arguments. */
8611 TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
8612 setstackmark(&smark);
8613 back_exitstatus = 0;
8615 cmdentry.cmdtype = CMDBUILTIN;
8616 cmdentry.u.cmd = &null_bltin;
8617 varlist.lastp = &varlist.list;
8618 *varlist.lastp = NULL;
8619 arglist.lastp = &arglist.list;
8620 *arglist.lastp = NULL;
8623 if (cmd->ncmd.args) {
8624 bcmd = find_builtin(cmd->ncmd.args->narg.text);
8625 pseudovarflag = bcmd && IS_BUILTIN_ASSIGN(bcmd);
8628 for (argp = cmd->ncmd.args; argp; argp = argp->narg.next) {
8629 struct strlist **spp;
8631 spp = arglist.lastp;
8632 if (pseudovarflag && isassignment(argp->narg.text))
8633 expandarg(argp, &arglist, EXP_VARTILDE);
8635 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
8637 for (sp = *spp; sp; sp = sp->next)
8641 argv = nargv = stalloc(sizeof(char *) * (argc + 1));
8642 for (sp = arglist.list; sp; sp = sp->next) {
8643 TRACE(("evalcommand arg: %s\n", sp->text));
8644 *nargv++ = sp->text;
8649 if (iflag && funcnest == 0 && argc > 0)
8650 lastarg = nargv[-1];
8653 expredir(cmd->ncmd.redirect);
8654 status = redirectsafe(cmd->ncmd.redirect, REDIR_PUSH | REDIR_SAVEFD2);
8657 for (argp = cmd->ncmd.assign; argp; argp = argp->narg.next) {
8658 struct strlist **spp;
8661 spp = varlist.lastp;
8662 expandarg(argp, &varlist, EXP_VARTILDE);
8665 * Modify the command lookup path, if a PATH= assignment
8669 if (varequal(p, path))
8673 /* Print the command if xflag is set. */
8676 const char *p = " %s";
8679 fdprintf(preverrout_fd, p, expandstr(ps4val()));
8682 for (n = 0; n < 2; n++) {
8684 fdprintf(preverrout_fd, p, sp->text);
8692 safe_write(preverrout_fd, "\n", 1);
8698 /* Now locate the command. */
8700 const char *oldpath;
8701 int cmd_flag = DO_ERR;
8706 find_command(argv[0], &cmdentry, cmd_flag, path);
8707 if (cmdentry.cmdtype == CMDUNKNOWN) {
8713 /* implement bltin and command here */
8714 if (cmdentry.cmdtype != CMDBUILTIN)
8717 spclbltin = IS_BUILTIN_SPECIAL(cmdentry.u.cmd);
8718 if (cmdentry.u.cmd == EXECCMD)
8720 #if ENABLE_ASH_CMDCMD
8721 if (cmdentry.u.cmd == COMMANDCMD) {
8723 nargv = parse_command_args(argv, &path);
8726 argc -= nargv - argv;
8728 cmd_flag |= DO_NOFUNC;
8736 /* We have a redirection error. */
8738 raise_exception(EXERROR);
8740 exitstatus = status;
8744 /* Execute the command. */
8745 switch (cmdentry.cmdtype) {
8747 #if ENABLE_FEATURE_SH_NOFORK
8749 /* find_command() encodes applet_no as (-2 - applet_no) */
8750 int applet_no = (- cmdentry.u.index - 2);
8751 if (applet_no >= 0 && APPLET_IS_NOFORK(applet_no)) {
8752 listsetvar(varlist.list, VEXPORT|VSTACK);
8753 /* run <applet>_main() */
8754 exitstatus = run_nofork_applet(applet_no, argv);
8760 /* Fork off a child process if necessary. */
8761 if (!(flags & EV_EXIT) || trap[0]) {
8763 jp = makejob(/*cmd,*/ 1);
8764 if (forkshell(jp, cmd, FORK_FG) != 0) {
8765 exitstatus = waitforjob(jp);
8771 listsetvar(varlist.list, VEXPORT|VSTACK);
8772 shellexec(argv, path, cmdentry.u.index);
8776 cmdenviron = varlist.list;
8778 struct strlist *list = cmdenviron;
8780 if (spclbltin > 0 || argc == 0) {
8782 if (cmd_is_exec && argc > 1)
8785 listsetvar(list, i);
8787 if (evalbltin(cmdentry.u.cmd, argc, argv)) {
8794 exit_status = 128 + SIGINT;
8796 exit_status = 128 + pendingsig;
8797 exitstatus = exit_status;
8798 if (i == EXINT || spclbltin > 0) {
8800 longjmp(exception_handler->loc, 1);
8807 listsetvar(varlist.list, 0);
8808 if (evalfun(cmdentry.u.func, argc, argv, flags))
8814 popredir(cmd_is_exec);
8816 /* dsl: I think this is intended to be used to support
8817 * '_' in 'vi' command mode during line editing...
8818 * However I implemented that within libedit itself.
8820 setvar("_", lastarg, 0);
8822 popstackmark(&smark);
8826 evalbltin(const struct builtincmd *cmd, int argc, char **argv)
8828 char *volatile savecmdname;
8829 struct jmploc *volatile savehandler;
8830 struct jmploc jmploc;
8833 savecmdname = commandname;
8834 i = setjmp(jmploc.loc);
8837 savehandler = exception_handler;
8838 exception_handler = &jmploc;
8839 commandname = argv[0];
8841 optptr = NULL; /* initialize nextopt */
8842 exitstatus = (*cmd->builtin)(argc, argv);
8843 flush_stdout_stderr();
8845 exitstatus |= ferror(stdout);
8847 commandname = savecmdname;
8849 exception_handler = savehandler;
8855 goodname(const char *p)
8857 return !*endofname(p);
8862 * Search for a command. This is called before we fork so that the
8863 * location of the command will be available in the parent as well as
8864 * the child. The check for "goodname" is an overly conservative
8865 * check that the name will not be subject to expansion.
8868 prehash(union node *n)
8870 struct cmdentry entry;
8872 if (n->type == NCMD && n->ncmd.args && goodname(n->ncmd.args->narg.text))
8873 find_command(n->ncmd.args->narg.text, &entry, 0, pathval());
8877 /* ============ Builtin commands
8879 * Builtin commands whose functions are closely tied to evaluation
8880 * are implemented here.
8884 * Handle break and continue commands. Break, continue, and return are
8885 * all handled by setting the evalskip flag. The evaluation routines
8886 * above all check this flag, and if it is set they start skipping
8887 * commands rather than executing them. The variable skipcount is
8888 * the number of loops to break/continue, or the number of function
8889 * levels to return. (The latter is always 1.) It should probably
8890 * be an error to break out of more loops than exist, but it isn't
8891 * in the standard shell so we don't make it one here.
8894 breakcmd(int argc UNUSED_PARAM, char **argv)
8896 int n = argv[1] ? number(argv[1]) : 1;
8899 ash_msg_and_raise_error(illnum, argv[1]);
8903 evalskip = (**argv == 'c') ? SKIPCONT : SKIPBREAK;
8910 /* ============ input.c
8912 * This implements the input routines used by the parser.
8915 #define EOF_NLEFT -99 /* value of parsenleft when EOF pushed back */
8918 INPUT_PUSH_FILE = 1,
8919 INPUT_NOFILE_OK = 2,
8922 static int plinno = 1; /* input line number */
8923 /* number of characters left in input buffer */
8924 static int parsenleft; /* copy of parsefile->nleft */
8925 static int parselleft; /* copy of parsefile->lleft */
8926 /* next character in input buffer */
8927 static char *parsenextc; /* copy of parsefile->nextc */
8929 static smallint checkkwd;
8930 /* values of checkkwd variable */
8931 #define CHKALIAS 0x1
8938 struct strpush *sp = g_parsefile->strpush;
8941 #if ENABLE_ASH_ALIAS
8943 if (parsenextc[-1] == ' ' || parsenextc[-1] == '\t') {
8944 checkkwd |= CHKALIAS;
8946 if (sp->string != sp->ap->val) {
8949 sp->ap->flag &= ~ALIASINUSE;
8950 if (sp->ap->flag & ALIASDEAD) {
8951 unalias(sp->ap->name);
8955 parsenextc = sp->prevstring;
8956 parsenleft = sp->prevnleft;
8957 /*dprintf("*** calling popstring: restoring to '%s'\n", parsenextc);*/
8958 g_parsefile->strpush = sp->prev;
8959 if (sp != &(g_parsefile->basestrpush))
8968 char *buf = g_parsefile->buf;
8971 #if ENABLE_FEATURE_EDITING
8973 if (!iflag || g_parsefile->fd)
8974 nr = nonblock_safe_read(g_parsefile->fd, buf, BUFSIZ - 1);
8976 #if ENABLE_FEATURE_TAB_COMPLETION
8977 line_input_state->path_lookup = pathval();
8979 nr = read_line_input(cmdedit_prompt, buf, BUFSIZ, line_input_state);
8981 /* Ctrl+C pressed */
8990 if (nr < 0 && errno == 0) {
8991 /* Ctrl+D pressed */
8996 nr = nonblock_safe_read(g_parsefile->fd, buf, BUFSIZ - 1);
9000 /* nonblock_safe_read() handles this problem */
9002 if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
9003 int flags = fcntl(0, F_GETFL);
9004 if (flags >= 0 && (flags & O_NONBLOCK)) {
9005 flags &= ~O_NONBLOCK;
9006 if (fcntl(0, F_SETFL, flags) >= 0) {
9007 out2str("sh: turning off NDELAY mode\n");
9018 * Refill the input buffer and return the next input character:
9020 * 1) If a string was pushed back on the input, pop it;
9021 * 2) If an EOF was pushed back (parsenleft == EOF_NLEFT) or we are reading
9022 * from a string so we can't refill the buffer, return EOF.
9023 * 3) If the is more stuff in this buffer, use it else call read to fill it.
9024 * 4) Process input up to the next newline, deleting nul characters.
9033 while (g_parsefile->strpush) {
9034 #if ENABLE_ASH_ALIAS
9035 if (parsenleft == -1 && g_parsefile->strpush->ap &&
9036 parsenextc[-1] != ' ' && parsenextc[-1] != '\t') {
9041 if (--parsenleft >= 0)
9042 return signed_char2int(*parsenextc++);
9044 if (parsenleft == EOF_NLEFT || g_parsefile->buf == NULL)
9046 flush_stdout_stderr();
9053 parselleft = parsenleft = EOF_NLEFT;
9060 /* delete nul characters */
9068 memmove(q, q + 1, more);
9072 parsenleft = q - parsenextc - 1;
9078 parsenleft = q - parsenextc - 1;
9090 out2str(parsenextc);
9095 return signed_char2int(*parsenextc++);
9098 #define pgetc_as_macro() (--parsenleft >= 0? signed_char2int(*parsenextc++) : preadbuffer())
9102 return pgetc_as_macro();
9105 #if ENABLE_ASH_OPTIMIZE_FOR_SIZE
9106 #define pgetc_macro() pgetc()
9108 #define pgetc_macro() pgetc_as_macro()
9112 * Same as pgetc(), but ignores PEOA.
9114 #if ENABLE_ASH_ALIAS
9122 } while (c == PEOA);
9129 return pgetc_macro();
9134 * Read a line from the script.
9137 pfgets(char *line, int len)
9143 while (--nleft > 0) {
9159 * Undo the last call to pgetc. Only one character may be pushed back.
9160 * PEOF may be pushed back.
9170 * Push a string back onto the input at this current parsefile level.
9171 * We handle aliases this way.
9173 #if !ENABLE_ASH_ALIAS
9174 #define pushstring(s, ap) pushstring(s)
9177 pushstring(char *s, struct alias *ap)
9184 /*dprintf("*** calling pushstring: %s, %d\n", s, len);*/
9185 if (g_parsefile->strpush) {
9186 sp = ckzalloc(sizeof(struct strpush));
9187 sp->prev = g_parsefile->strpush;
9188 g_parsefile->strpush = sp;
9190 sp = g_parsefile->strpush = &(g_parsefile->basestrpush);
9191 sp->prevstring = parsenextc;
9192 sp->prevnleft = parsenleft;
9193 #if ENABLE_ASH_ALIAS
9196 ap->flag |= ALIASINUSE;
9206 * To handle the "." command, a stack of input files is used. Pushfile
9207 * adds a new entry to the stack and popfile restores the previous level.
9212 struct parsefile *pf;
9214 g_parsefile->nleft = parsenleft;
9215 g_parsefile->lleft = parselleft;
9216 g_parsefile->nextc = parsenextc;
9217 g_parsefile->linno = plinno;
9218 pf = ckzalloc(sizeof(*pf));
9219 pf->prev = g_parsefile;
9221 /*pf->strpush = NULL; - ckzalloc did it */
9222 /*pf->basestrpush.prev = NULL;*/
9229 struct parsefile *pf = g_parsefile;
9237 g_parsefile = pf->prev;
9239 parsenleft = g_parsefile->nleft;
9240 parselleft = g_parsefile->lleft;
9241 parsenextc = g_parsefile->nextc;
9242 plinno = g_parsefile->linno;
9247 * Return to top level.
9252 while (g_parsefile != &basepf)
9257 * Close the file(s) that the shell is reading commands from. Called
9258 * after a fork is done.
9264 if (g_parsefile->fd > 0) {
9265 close(g_parsefile->fd);
9266 g_parsefile->fd = 0;
9271 * Like setinputfile, but takes an open file descriptor. Call this with
9275 setinputfd(int fd, int push)
9277 close_on_exec_on(fd);
9280 g_parsefile->buf = 0;
9282 g_parsefile->fd = fd;
9283 if (g_parsefile->buf == NULL)
9284 g_parsefile->buf = ckmalloc(IBUFSIZ);
9285 parselleft = parsenleft = 0;
9290 * Set the input to take input from a file. If push is set, push the
9291 * old input onto the stack first.
9294 setinputfile(const char *fname, int flags)
9300 fd = open(fname, O_RDONLY);
9302 if (flags & INPUT_NOFILE_OK)
9304 ash_msg_and_raise_error("can't open %s", fname);
9307 fd2 = copyfd(fd, 10);
9310 ash_msg_and_raise_error("out of file descriptors");
9313 setinputfd(fd, flags & INPUT_PUSH_FILE);
9320 * Like setinputfile, but takes input from a string.
9323 setinputstring(char *string)
9327 parsenextc = string;
9328 parsenleft = strlen(string);
9329 g_parsefile->buf = NULL;
9335 /* ============ mail.c
9337 * Routines to check for mail.
9342 #define MAXMBOXES 10
9344 /* times of mailboxes */
9345 static time_t mailtime[MAXMBOXES];
9346 /* Set if MAIL or MAILPATH is changed. */
9347 static smallint mail_var_path_changed;
9350 * Print appropriate message(s) if mail has arrived.
9351 * If mail_var_path_changed is set,
9352 * then the value of MAIL has mail_var_path_changed,
9353 * so we just update the values.
9362 struct stackmark smark;
9365 setstackmark(&smark);
9366 mpath = mpathset() ? mpathval() : mailval();
9367 for (mtp = mailtime; mtp < mailtime + MAXMBOXES; mtp++) {
9368 p = padvance(&mpath, nullstr);
9373 for (q = p; *q; q++)
9379 q[-1] = '\0'; /* delete trailing '/' */
9380 if (stat(p, &statb) < 0) {
9384 if (!mail_var_path_changed && statb.st_mtime != *mtp) {
9387 pathopt ? pathopt : "you have mail"
9390 *mtp = statb.st_mtime;
9392 mail_var_path_changed = 0;
9393 popstackmark(&smark);
9397 changemail(const char *val UNUSED_PARAM)
9399 mail_var_path_changed = 1;
9402 #endif /* ASH_MAIL */
9405 /* ============ ??? */
9408 * Set the shell parameters.
9411 setparam(char **argv)
9417 for (nparam = 0; argv[nparam]; nparam++)
9419 ap = newparam = ckmalloc((nparam + 1) * sizeof(*ap));
9421 *ap++ = ckstrdup(*argv++);
9424 freeparam(&shellparam);
9425 shellparam.malloced = 1;
9426 shellparam.nparam = nparam;
9427 shellparam.p = newparam;
9428 #if ENABLE_ASH_GETOPTS
9429 shellparam.optind = 1;
9430 shellparam.optoff = -1;
9435 * Process shell options. The global variable argptr contains a pointer
9436 * to the argument list; we advance it past the options.
9438 * SUSv3 section 2.8.1 "Consequences of Shell Errors" says:
9439 * For a non-interactive shell, an error condition encountered
9440 * by a special built-in ... shall cause the shell to write a diagnostic message
9441 * to standard error and exit as shown in the following table:
9442 * Error Special Built-In
9444 * Utility syntax error (option or operand error) Shall exit
9446 * However, in bug 1142 (http://busybox.net/bugs/view.php?id=1142)
9447 * we see that bash does not do that (set "finishes" with error code 1 instead,
9448 * and shell continues), and people rely on this behavior!
9450 * set -o barfoo 2>/dev/null
9453 * Oh well. Let's mimic that.
9456 plus_minus_o(char *name, int val)
9461 for (i = 0; i < NOPTS; i++) {
9462 if (strcmp(name, optnames(i)) == 0) {
9467 ash_msg("illegal option %co %s", val ? '-' : '+', name);
9470 for (i = 0; i < NOPTS; i++) {
9472 out1fmt("%-16s%s\n", optnames(i), optlist[i] ? "on" : "off");
9474 out1fmt("set %co %s\n", optlist[i] ? '-' : '+', optnames(i));
9480 setoption(int flag, int val)
9484 for (i = 0; i < NOPTS; i++) {
9485 if (optletters(i) == flag) {
9490 ash_msg_and_raise_error("illegal option %c%c", val ? '-' : '+', flag);
9494 options(int cmdline)
9502 while ((p = *argptr) != NULL) {
9504 if (c != '-' && c != '+')
9507 val = 0; /* val = 0 if c == '+' */
9510 if (p[0] == '\0' || LONE_DASH(p)) {
9512 /* "-" means turn off -x and -v */
9515 /* "--" means reset params */
9516 else if (*argptr == NULL)
9519 break; /* "-" or "--" terminates options */
9522 /* first char was + or - */
9523 while ((c = *p++) != '\0') {
9524 /* bash 3.2 indeed handles -c CMD and +c CMD the same */
9525 if (c == 'c' && cmdline) {
9526 minusc = p; /* command is after shell args */
9527 } else if (c == 'o') {
9528 if (plus_minus_o(*argptr, val)) {
9529 /* it already printed err message */
9530 return 1; /* error */
9534 } else if (cmdline && (c == 'l')) { /* -l or +l == --login */
9536 /* bash does not accept +-login, we also won't */
9537 } else if (cmdline && val && (c == '-')) { /* long options */
9538 if (strcmp(p, "login") == 0)
9550 * The shift builtin command.
9553 shiftcmd(int argc UNUSED_PARAM, char **argv)
9560 n = number(argv[1]);
9561 if (n > shellparam.nparam)
9562 n = shellparam.nparam;
9564 shellparam.nparam -= n;
9565 for (ap1 = shellparam.p; --n >= 0; ap1++) {
9566 if (shellparam.malloced)
9570 while ((*ap2++ = *ap1++) != NULL)
9572 #if ENABLE_ASH_GETOPTS
9573 shellparam.optind = 1;
9574 shellparam.optoff = -1;
9581 * POSIX requires that 'set' (but not export or readonly) output the
9582 * variables in lexicographic order - by the locale's collating order (sigh).
9583 * Maybe we could keep them in an ordered balanced binary tree
9584 * instead of hashed lists.
9585 * For now just roll 'em through qsort for printing...
9588 showvars(const char *sep_prefix, int on, int off)
9593 ep = listvars(on, off, &epend);
9594 qsort(ep, epend - ep, sizeof(char *), vpcmp);
9596 sep = *sep_prefix ? " " : sep_prefix;
9598 for (; ep < epend; ep++) {
9602 p = strchrnul(*ep, '=');
9605 q = single_quote(++p);
9606 out1fmt("%s%s%.*s%s\n", sep_prefix, sep, (int)(p - *ep), *ep, q);
9612 * The set command builtin.
9615 setcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9620 return showvars(nullstr, 0, VUNSET);
9623 if (!options(0)) { /* if no parse error... */
9626 if (*argptr != NULL) {
9634 #if ENABLE_ASH_RANDOM_SUPPORT
9636 change_random(const char *value)
9638 /* Galois LFSR parameter */
9639 /* Taps at 32 31 29 1: */
9640 enum { MASK = 0x8000000b };
9641 /* Another example - taps at 32 31 30 10: */
9642 /* MASK = 0x00400007 */
9644 if (value == NULL) {
9645 /* "get", generate */
9648 /* LCG has period of 2^32 and alternating lowest bit */
9649 random_LCG = 1664525 * random_LCG + 1013904223;
9650 /* Galois LFSR has period of 2^32-1 = 3 * 5 * 17 * 257 * 65537 */
9651 t = (random_galois_LFSR << 1);
9652 if (random_galois_LFSR < 0) /* if we just shifted 1 out of msb... */
9654 random_galois_LFSR = t;
9655 /* Both are weak, combining them gives better randomness
9656 * and ~2^64 period. & 0x7fff is probably bash compat
9657 * for $RANDOM range. Combining with subtraction is
9658 * just for fun. + and ^ would work equally well. */
9659 t = (t - random_LCG) & 0x7fff;
9660 /* set without recursion */
9661 setvar(vrandom.text, utoa(t), VNOFUNC);
9662 vrandom.flags &= ~VNOFUNC;
9665 random_galois_LFSR = random_LCG = strtoul(value, (char **)NULL, 10);
9670 #if ENABLE_ASH_GETOPTS
9672 getopts(char *optstr, char *optvar, char **optfirst, int *param_optind, int *optoff)
9681 if (*param_optind < 1)
9683 optnext = optfirst + *param_optind - 1;
9685 if (*param_optind <= 1 || *optoff < 0 || (int)strlen(optnext[-1]) < *optoff)
9688 p = optnext[-1] + *optoff;
9689 if (p == NULL || *p == '\0') {
9690 /* Current word is done, advance */
9692 if (p == NULL || *p != '-' || *++p == '\0') {
9699 if (LONE_DASH(p)) /* check for "--" */
9704 for (q = optstr; *q != c;) {
9706 if (optstr[0] == ':') {
9709 err |= setvarsafe("OPTARG", s, 0);
9711 fprintf(stderr, "Illegal option -%c\n", c);
9722 if (*p == '\0' && (p = *optnext) == NULL) {
9723 if (optstr[0] == ':') {
9726 err |= setvarsafe("OPTARG", s, 0);
9729 fprintf(stderr, "No arg for -%c option\n", c);
9738 err |= setvarsafe("OPTARG", p, 0);
9741 err |= setvarsafe("OPTARG", nullstr, 0);
9743 *optoff = p ? p - *(optnext - 1) : -1;
9744 *param_optind = optnext - optfirst + 1;
9745 fmtstr(s, sizeof(s), "%d", *param_optind);
9746 err |= setvarsafe("OPTIND", s, VNOFUNC);
9749 err |= setvarsafe(optvar, s, 0);
9753 flush_stdout_stderr();
9754 raise_exception(EXERROR);
9760 * The getopts builtin. Shellparam.optnext points to the next argument
9761 * to be processed. Shellparam.optptr points to the next character to
9762 * be processed in the current argument. If shellparam.optnext is NULL,
9763 * then it's the first time getopts has been called.
9766 getoptscmd(int argc, char **argv)
9771 ash_msg_and_raise_error("usage: getopts optstring var [arg]");
9773 optbase = shellparam.p;
9774 if (shellparam.optind > shellparam.nparam + 1) {
9775 shellparam.optind = 1;
9776 shellparam.optoff = -1;
9780 if (shellparam.optind > argc - 2) {
9781 shellparam.optind = 1;
9782 shellparam.optoff = -1;
9786 return getopts(argv[1], argv[2], optbase, &shellparam.optind,
9787 &shellparam.optoff);
9789 #endif /* ASH_GETOPTS */
9792 /* ============ Shell parser */
9795 struct heredoc *next; /* next here document in list */
9796 union node *here; /* redirection node */
9797 char *eofmark; /* string indicating end of input */
9798 smallint striptabs; /* if set, strip leading tabs */
9801 static smallint tokpushback; /* last token pushed back */
9802 static smallint parsebackquote; /* nonzero if we are inside backquotes */
9803 static smallint quoteflag; /* set if (part of) last token was quoted */
9804 static token_id_t lasttoken; /* last token read (integer id Txxx) */
9805 static struct heredoc *heredoclist; /* list of here documents to read */
9806 static char *wordtext; /* text of last word returned by readtoken */
9807 static struct nodelist *backquotelist;
9808 static union node *redirnode;
9809 static struct heredoc *heredoc;
9811 * NEOF is returned by parsecmd when it encounters an end of file. It
9812 * must be distinct from NULL, so we use the address of a variable that
9813 * happens to be handy.
9815 #define NEOF ((union node *)&tokpushback)
9817 static void raise_error_syntax(const char *) NORETURN;
9819 raise_error_syntax(const char *msg)
9821 ash_msg_and_raise_error("syntax error: %s", msg);
9826 * Called when an unexpected token is read during the parse. The argument
9827 * is the token that is expected, or -1 if more than one type of token can
9828 * occur at this point.
9830 static void raise_error_unexpected_syntax(int) NORETURN;
9832 raise_error_unexpected_syntax(int token)
9837 l = sprintf(msg, "%s unexpected", tokname(lasttoken));
9839 sprintf(msg + l, " (expecting %s)", tokname(token));
9840 raise_error_syntax(msg);
9844 #define EOFMARKLEN 79
9846 /* parsing is heavily cross-recursive, need these forward decls */
9847 static union node *andor(void);
9848 static union node *pipeline(void);
9849 static union node *parse_command(void);
9850 static void parseheredoc(void);
9851 static char peektoken(void);
9852 static int readtoken(void);
9857 union node *n1, *n2, *n3;
9860 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9861 if (nlflag == 2 && peektoken())
9867 if (tok == TBACKGND) {
9868 if (n2->type == NPIPE) {
9869 n2->npipe.pipe_backgnd = 1;
9871 if (n2->type != NREDIR) {
9872 n3 = stzalloc(sizeof(struct nredir));
9874 /*n3->nredir.redirect = NULL; - stzalloc did it */
9877 n2->type = NBACKGND;
9883 n3 = stzalloc(sizeof(struct nbinary));
9885 n3->nbinary.ch1 = n1;
9886 n3->nbinary.ch2 = n2;
9902 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9910 pungetc(); /* push back EOF on input */
9914 raise_error_unexpected_syntax(-1);
9924 union node *n1, *n2, *n3;
9932 } else if (t == TOR) {
9938 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9940 n3 = stzalloc(sizeof(struct nbinary));
9942 n3->nbinary.ch1 = n1;
9943 n3->nbinary.ch2 = n2;
9951 union node *n1, *n2, *pipenode;
9952 struct nodelist *lp, *prev;
9956 TRACE(("pipeline: entered\n"));
9957 if (readtoken() == TNOT) {
9959 checkkwd = CHKKWD | CHKALIAS;
9962 n1 = parse_command();
9963 if (readtoken() == TPIPE) {
9964 pipenode = stzalloc(sizeof(struct npipe));
9965 pipenode->type = NPIPE;
9966 /*pipenode->npipe.pipe_backgnd = 0; - stzalloc did it */
9967 lp = stzalloc(sizeof(struct nodelist));
9968 pipenode->npipe.cmdlist = lp;
9972 lp = stzalloc(sizeof(struct nodelist));
9973 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9974 lp->n = parse_command();
9976 } while (readtoken() == TPIPE);
9982 n2 = stzalloc(sizeof(struct nnot));
9995 n = stzalloc(sizeof(struct narg));
9997 /*n->narg.next = NULL; - stzalloc did it */
9998 n->narg.text = wordtext;
9999 n->narg.backquote = backquotelist;
10004 fixredir(union node *n, const char *text, int err)
10006 TRACE(("Fix redir %s %d\n", text, err));
10008 n->ndup.vname = NULL;
10010 if (isdigit(text[0]) && text[1] == '\0')
10011 n->ndup.dupfd = text[0] - '0';
10012 else if (LONE_DASH(text))
10013 n->ndup.dupfd = -1;
10016 raise_error_syntax("Bad fd number");
10017 n->ndup.vname = makename();
10022 * Returns true if the text contains nothing to expand (no dollar signs
10026 noexpand(char *text)
10032 while ((c = *p++) != '\0') {
10033 if (c == CTLQUOTEMARK)
10037 else if (SIT(c, BASESYNTAX) == CCTL)
10046 union node *n = redirnode;
10048 if (readtoken() != TWORD)
10049 raise_error_unexpected_syntax(-1);
10050 if (n->type == NHERE) {
10051 struct heredoc *here = heredoc;
10055 if (quoteflag == 0)
10057 TRACE(("Here document %d\n", n->type));
10058 if (!noexpand(wordtext) || (i = strlen(wordtext)) == 0 || i > EOFMARKLEN)
10059 raise_error_syntax("Illegal eof marker for << redirection");
10060 rmescapes(wordtext);
10061 here->eofmark = wordtext;
10063 if (heredoclist == NULL)
10064 heredoclist = here;
10066 for (p = heredoclist; p->next; p = p->next)
10070 } else if (n->type == NTOFD || n->type == NFROMFD) {
10071 fixredir(n, wordtext, 0);
10073 n->nfile.fname = makename();
10077 static union node *
10080 union node *args, **app;
10081 union node *n = NULL;
10082 union node *vars, **vpp;
10083 union node **rpp, *redir;
10085 #if ENABLE_ASH_BASH_COMPAT
10086 smallint double_brackets_flag = 0;
10096 savecheckkwd = CHKALIAS;
10099 checkkwd = savecheckkwd;
10102 #if ENABLE_ASH_BASH_COMPAT
10103 case TAND: /* "&&" */
10104 case TOR: /* "||" */
10105 if (!double_brackets_flag) {
10109 wordtext = (char *) (t == TAND ? "-a" : "-o");
10112 n = stzalloc(sizeof(struct narg));
10114 /*n->narg.next = NULL; - stzalloc did it */
10115 n->narg.text = wordtext;
10116 #if ENABLE_ASH_BASH_COMPAT
10117 if (strcmp("[[", wordtext) == 0)
10118 double_brackets_flag = 1;
10119 else if (strcmp("]]", wordtext) == 0)
10120 double_brackets_flag = 0;
10122 n->narg.backquote = backquotelist;
10123 if (savecheckkwd && isassignment(wordtext)) {
10125 vpp = &n->narg.next;
10128 app = &n->narg.next;
10133 *rpp = n = redirnode;
10134 rpp = &n->nfile.next;
10135 parsefname(); /* read name of redirection file */
10138 if (args && app == &args->narg.next
10141 struct builtincmd *bcmd;
10144 /* We have a function */
10145 if (readtoken() != TRP)
10146 raise_error_unexpected_syntax(TRP);
10147 name = n->narg.text;
10148 if (!goodname(name)
10149 || ((bcmd = find_builtin(name)) && IS_BUILTIN_SPECIAL(bcmd))
10151 raise_error_syntax("Bad function name");
10154 checkkwd = CHKNL | CHKKWD | CHKALIAS;
10155 n->narg.next = parse_command();
10168 n = stzalloc(sizeof(struct ncmd));
10170 n->ncmd.args = args;
10171 n->ncmd.assign = vars;
10172 n->ncmd.redirect = redir;
10176 static union node *
10177 parse_command(void)
10179 union node *n1, *n2;
10180 union node *ap, **app;
10181 union node *cp, **cpp;
10182 union node *redir, **rpp;
10189 switch (readtoken()) {
10191 raise_error_unexpected_syntax(-1);
10194 n1 = stzalloc(sizeof(struct nif));
10196 n1->nif.test = list(0);
10197 if (readtoken() != TTHEN)
10198 raise_error_unexpected_syntax(TTHEN);
10199 n1->nif.ifpart = list(0);
10201 while (readtoken() == TELIF) {
10202 n2->nif.elsepart = stzalloc(sizeof(struct nif));
10203 n2 = n2->nif.elsepart;
10205 n2->nif.test = list(0);
10206 if (readtoken() != TTHEN)
10207 raise_error_unexpected_syntax(TTHEN);
10208 n2->nif.ifpart = list(0);
10210 if (lasttoken == TELSE)
10211 n2->nif.elsepart = list(0);
10213 n2->nif.elsepart = NULL;
10221 n1 = stzalloc(sizeof(struct nbinary));
10222 n1->type = (lasttoken == TWHILE) ? NWHILE : NUNTIL;
10223 n1->nbinary.ch1 = list(0);
10226 TRACE(("expecting DO got %s %s\n", tokname(got),
10227 got == TWORD ? wordtext : ""));
10228 raise_error_unexpected_syntax(TDO);
10230 n1->nbinary.ch2 = list(0);
10235 if (readtoken() != TWORD || quoteflag || !goodname(wordtext))
10236 raise_error_syntax("Bad for loop variable");
10237 n1 = stzalloc(sizeof(struct nfor));
10239 n1->nfor.var = wordtext;
10240 checkkwd = CHKKWD | CHKALIAS;
10241 if (readtoken() == TIN) {
10243 while (readtoken() == TWORD) {
10244 n2 = stzalloc(sizeof(struct narg));
10246 /*n2->narg.next = NULL; - stzalloc did it */
10247 n2->narg.text = wordtext;
10248 n2->narg.backquote = backquotelist;
10250 app = &n2->narg.next;
10253 n1->nfor.args = ap;
10254 if (lasttoken != TNL && lasttoken != TSEMI)
10255 raise_error_unexpected_syntax(-1);
10257 n2 = stzalloc(sizeof(struct narg));
10259 /*n2->narg.next = NULL; - stzalloc did it */
10260 n2->narg.text = (char *)dolatstr;
10261 /*n2->narg.backquote = NULL;*/
10262 n1->nfor.args = n2;
10264 * Newline or semicolon here is optional (but note
10265 * that the original Bourne shell only allowed NL).
10267 if (lasttoken != TNL && lasttoken != TSEMI)
10270 checkkwd = CHKNL | CHKKWD | CHKALIAS;
10271 if (readtoken() != TDO)
10272 raise_error_unexpected_syntax(TDO);
10273 n1->nfor.body = list(0);
10277 n1 = stzalloc(sizeof(struct ncase));
10279 if (readtoken() != TWORD)
10280 raise_error_unexpected_syntax(TWORD);
10281 n1->ncase.expr = n2 = stzalloc(sizeof(struct narg));
10283 /*n2->narg.next = NULL; - stzalloc did it */
10284 n2->narg.text = wordtext;
10285 n2->narg.backquote = backquotelist;
10287 checkkwd = CHKKWD | CHKALIAS;
10288 } while (readtoken() == TNL);
10289 if (lasttoken != TIN)
10290 raise_error_unexpected_syntax(TIN);
10291 cpp = &n1->ncase.cases;
10293 checkkwd = CHKNL | CHKKWD;
10295 while (t != TESAC) {
10296 if (lasttoken == TLP)
10298 *cpp = cp = stzalloc(sizeof(struct nclist));
10300 app = &cp->nclist.pattern;
10302 *app = ap = stzalloc(sizeof(struct narg));
10304 /*ap->narg.next = NULL; - stzalloc did it */
10305 ap->narg.text = wordtext;
10306 ap->narg.backquote = backquotelist;
10307 if (readtoken() != TPIPE)
10309 app = &ap->narg.next;
10312 //ap->narg.next = NULL;
10313 if (lasttoken != TRP)
10314 raise_error_unexpected_syntax(TRP);
10315 cp->nclist.body = list(2);
10317 cpp = &cp->nclist.next;
10319 checkkwd = CHKNL | CHKKWD;
10323 raise_error_unexpected_syntax(TENDCASE);
10330 n1 = stzalloc(sizeof(struct nredir));
10331 n1->type = NSUBSHELL;
10332 n1->nredir.n = list(0);
10333 /*n1->nredir.redirect = NULL; - stzalloc did it */
10343 return simplecmd();
10346 if (readtoken() != t)
10347 raise_error_unexpected_syntax(t);
10350 /* Now check for redirection which may follow command */
10351 checkkwd = CHKKWD | CHKALIAS;
10353 while (readtoken() == TREDIR) {
10354 *rpp = n2 = redirnode;
10355 rpp = &n2->nfile.next;
10361 if (n1->type != NSUBSHELL) {
10362 n2 = stzalloc(sizeof(struct nredir));
10367 n1->nredir.redirect = redir;
10372 #if ENABLE_ASH_BASH_COMPAT
10373 static int decode_dollar_squote(void)
10375 static const char C_escapes[] ALIGN1 = "nrbtfav""x\\01234567";
10381 p = strchr(C_escapes, c);
10386 if ((unsigned char)(c - '0') <= 7) { /* \ooo */
10390 } while ((unsigned char)(c - '0') <= 7 && --cnt);
10392 } else if (c == 'x') { /* \xHH */
10396 } while (isxdigit(c) && --cnt);
10398 if (cnt == 3) { /* \x but next char is "bad" */
10402 } else { /* simple seq like \\ or \t */
10407 c = bb_process_escape_sequence((void*)&p);
10408 } else { /* unrecognized "\z": print both chars unless ' or " */
10409 if (c != '\'' && c != '"') {
10411 c |= 0x100; /* "please encode \, then me" */
10419 * If eofmark is NULL, read a word or a redirection symbol. If eofmark
10420 * is not NULL, read a here document. In the latter case, eofmark is the
10421 * word which marks the end of the document and striptabs is true if
10422 * leading tabs should be stripped from the document. The argument firstc
10423 * is the first character of the input token or document.
10425 * Because C does not have internal subroutines, I have simulated them
10426 * using goto's to implement the subroutine linkage. The following macros
10427 * will run code that appears at the end of readtoken1.
10429 #define CHECKEND() {goto checkend; checkend_return:;}
10430 #define PARSEREDIR() {goto parseredir; parseredir_return:;}
10431 #define PARSESUB() {goto parsesub; parsesub_return:;}
10432 #define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
10433 #define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
10434 #define PARSEARITH() {goto parsearith; parsearith_return:;}
10436 readtoken1(int firstc, int syntax, char *eofmark, int striptabs)
10438 /* NB: syntax parameter fits into smallint */
10442 char line[EOFMARKLEN + 1];
10443 struct nodelist *bqlist;
10447 smallint prevsyntax; /* syntax before arithmetic */
10448 #if ENABLE_ASH_EXPAND_PRMT
10449 smallint pssyntax; /* we are expanding a prompt string */
10451 int varnest; /* levels of variables expansion */
10452 int arinest; /* levels of arithmetic expansion */
10453 int parenlevel; /* levels of parens in arithmetic */
10454 int dqvarnest; /* levels of variables expansion within double quotes */
10456 USE_ASH_BASH_COMPAT(smallint bash_dollar_squote = 0;)
10459 /* Avoid longjmp clobbering */
10465 (void) &parenlevel;
10468 (void) &prevsyntax;
10471 startlinno = plinno;
10476 #if ENABLE_ASH_EXPAND_PRMT
10477 pssyntax = (syntax == PSSYNTAX);
10481 dblquote = (syntax == DQSYNTAX);
10487 STARTSTACKSTR(out);
10488 loop: { /* for each line, until end of word */
10489 CHECKEND(); /* set c to PEOF if at end of here document */
10490 for (;;) { /* until end of line or end of word */
10491 CHECKSTRSPACE(4, out); /* permit 4 calls to USTPUTC */
10492 switch (SIT(c, syntax)) {
10493 case CNL: /* '\n' */
10494 if (syntax == BASESYNTAX)
10495 goto endword; /* exit outer loop */
10501 goto loop; /* continue outer loop */
10506 if (eofmark == NULL || dblquote)
10507 USTPUTC(CTLESC, out);
10508 #if ENABLE_ASH_BASH_COMPAT
10509 if (c == '\\' && bash_dollar_squote) {
10510 c = decode_dollar_squote();
10512 USTPUTC('\\', out);
10513 c = (unsigned char)c;
10519 case CBACK: /* backslash */
10522 USTPUTC(CTLESC, out);
10523 USTPUTC('\\', out);
10525 } else if (c == '\n') {
10529 #if ENABLE_ASH_EXPAND_PRMT
10530 if (c == '$' && pssyntax) {
10531 USTPUTC(CTLESC, out);
10532 USTPUTC('\\', out);
10535 if (dblquote && c != '\\'
10536 && c != '`' && c != '$'
10537 && (c != '"' || eofmark != NULL)
10539 USTPUTC(CTLESC, out);
10540 USTPUTC('\\', out);
10542 if (SIT(c, SQSYNTAX) == CCTL)
10543 USTPUTC(CTLESC, out);
10551 if (eofmark == NULL) {
10552 USTPUTC(CTLQUOTEMARK, out);
10560 USE_ASH_BASH_COMPAT(bash_dollar_squote = 0;)
10561 if (eofmark != NULL && arinest == 0
10566 if (dqvarnest == 0) {
10567 syntax = BASESYNTAX;
10574 case CVAR: /* '$' */
10575 PARSESUB(); /* parse substitution */
10577 case CENDVAR: /* '}' */
10580 if (dqvarnest > 0) {
10583 USTPUTC(CTLENDVAR, out);
10588 #if ENABLE_ASH_MATH_SUPPORT
10589 case CLP: /* '(' in arithmetic */
10593 case CRP: /* ')' in arithmetic */
10594 if (parenlevel > 0) {
10598 if (pgetc() == ')') {
10599 if (--arinest == 0) {
10600 USTPUTC(CTLENDARI, out);
10601 syntax = prevsyntax;
10602 dblquote = (syntax == DQSYNTAX);
10607 * unbalanced parens
10608 * (don't 2nd guess - no error)
10616 case CBQUOTE: /* '`' */
10620 goto endword; /* exit outer loop */
10625 goto endword; /* exit outer loop */
10626 #if ENABLE_ASH_ALIAS
10636 #if ENABLE_ASH_MATH_SUPPORT
10637 if (syntax == ARISYNTAX)
10638 raise_error_syntax("Missing '))'");
10640 if (syntax != BASESYNTAX && !parsebackquote && eofmark == NULL)
10641 raise_error_syntax("Unterminated quoted string");
10642 if (varnest != 0) {
10643 startlinno = plinno;
10645 raise_error_syntax("Missing '}'");
10647 USTPUTC('\0', out);
10648 len = out - (char *)stackblock();
10649 out = stackblock();
10650 if (eofmark == NULL) {
10651 if ((c == '>' || c == '<')
10653 && len <= 2 // THIS LIMITS fd to 1 char: N>file, but no NN>file!
10654 && (*out == '\0' || isdigit(*out))
10657 lasttoken = TREDIR;
10662 quoteflag = quotef;
10663 backquotelist = bqlist;
10664 grabstackblock(len);
10668 /* end of readtoken routine */
10671 * Check to see whether we are at the end of the here document. When this
10672 * is called, c is set to the first character of the next input line. If
10673 * we are at the end of the here document, this routine sets the c to PEOF.
10677 #if ENABLE_ASH_ALIAS
10683 while (c == '\t') {
10687 if (c == *eofmark) {
10688 if (pfgets(line, sizeof(line)) != NULL) {
10692 for (q = eofmark + 1; *q && *p == *q; p++, q++)
10694 if (*p == '\n' && *q == '\0') {
10697 needprompt = doprompt;
10699 pushstring(line, NULL);
10704 goto checkend_return;
10708 * Parse a redirection operator. The variable "out" points to a string
10709 * specifying the fd to be redirected. The variable "c" contains the
10710 * first character of the redirection operator.
10716 np = stzalloc(sizeof(struct nfile));
10721 np->type = NAPPEND;
10723 np->type = NCLOBBER;
10730 } else { /* c == '<' */
10731 /*np->nfile.fd = 0; - stzalloc did it */
10735 if (sizeof(struct nfile) != sizeof(struct nhere)) {
10736 np = stzalloc(sizeof(struct nhere));
10737 /*np->nfile.fd = 0; - stzalloc did it */
10740 heredoc = stzalloc(sizeof(struct heredoc));
10741 heredoc->here = np;
10744 heredoc->striptabs = 1;
10746 /*heredoc->striptabs = 0; - stzalloc did it */
10752 np->type = NFROMFD;
10756 np->type = NFROMTO;
10766 np->nfile.fd = fd - '0';
10768 goto parseredir_return;
10772 * Parse a substitution. At this point, we have read the dollar sign
10773 * and nothing else.
10776 /* is_special(c) evaluates to 1 for c in "!#$*-0123456789?@"; 0 otherwise
10777 * (assuming ascii char codes, as the original implementation did) */
10778 #define is_special(c) \
10779 (((unsigned)(c) - 33 < 32) \
10780 && ((0xc1ff920dU >> ((unsigned)(c) - 33)) & 1))
10786 static const char types[] ALIGN1 = "}-+?=";
10789 if (c <= PEOA_OR_PEOF
10790 || (c != '(' && c != '{' && !is_name(c) && !is_special(c))
10792 #if ENABLE_ASH_BASH_COMPAT
10794 bash_dollar_squote = 1;
10799 } else if (c == '(') { /* $(command) or $((arith)) */
10800 if (pgetc() == '(') {
10801 #if ENABLE_ASH_MATH_SUPPORT
10804 raise_error_syntax("you disabled math support for $((arith)) syntax");
10811 USTPUTC(CTLVAR, out);
10812 typeloc = out - (char *)stackblock();
10813 USTPUTC(VSNORMAL, out);
10814 subtype = VSNORMAL;
10822 subtype = VSLENGTH;
10826 if (c > PEOA_OR_PEOF && is_name(c)) {
10830 } while (c > PEOA_OR_PEOF && is_in_name(c));
10831 } else if (isdigit(c)) {
10835 } while (isdigit(c));
10836 } else if (is_special(c)) {
10840 badsub: raise_error_syntax("Bad substitution");
10844 if (subtype == 0) {
10848 #if ENABLE_ASH_BASH_COMPAT
10849 if (c == ':' || c == '$' || isdigit(c)) {
10851 subtype = VSSUBSTR;
10858 p = strchr(types, c);
10861 subtype = p - types + VSNORMAL;
10866 subtype = c == '#' ? VSTRIMLEFT : VSTRIMRIGHT;
10874 #if ENABLE_ASH_BASH_COMPAT
10876 subtype = VSREPLACE;
10879 subtype++; /* VSREPLACEALL */
10888 if (dblquote || arinest)
10890 *((char *)stackblock() + typeloc) = subtype | flags;
10891 if (subtype != VSNORMAL) {
10893 if (dblquote || arinest) {
10898 goto parsesub_return;
10902 * Called to parse command substitutions. Newstyle is set if the command
10903 * is enclosed inside $(...); nlpp is a pointer to the head of the linked
10904 * list of commands (passed by reference), and savelen is the number of
10905 * characters on the top of the stack which must be preserved.
10908 struct nodelist **nlpp;
10911 char *volatile str;
10912 struct jmploc jmploc;
10913 struct jmploc *volatile savehandler;
10915 smallint saveprompt = 0;
10918 (void) &saveprompt;
10920 savepbq = parsebackquote;
10921 if (setjmp(jmploc.loc)) {
10923 parsebackquote = 0;
10924 exception_handler = savehandler;
10925 longjmp(exception_handler->loc, 1);
10929 savelen = out - (char *)stackblock();
10931 str = ckmalloc(savelen);
10932 memcpy(str, stackblock(), savelen);
10934 savehandler = exception_handler;
10935 exception_handler = &jmploc;
10938 /* We must read until the closing backquote, giving special
10939 treatment to some slashes, and then push the string and
10940 reread it as input, interpreting it normally. */
10947 STARTSTACKSTR(pout);
10964 * If eating a newline, avoid putting
10965 * the newline into the new character
10966 * stream (via the STPUTC after the
10971 if (pc != '\\' && pc != '`' && pc != '$'
10972 && (!dblquote || pc != '"'))
10973 STPUTC('\\', pout);
10974 if (pc > PEOA_OR_PEOF) {
10980 #if ENABLE_ASH_ALIAS
10983 startlinno = plinno;
10984 raise_error_syntax("EOF in backquote substitution");
10988 needprompt = doprompt;
10997 STPUTC('\0', pout);
10998 psavelen = pout - (char *)stackblock();
10999 if (psavelen > 0) {
11000 pstr = grabstackstr(pout);
11001 setinputstring(pstr);
11006 nlpp = &(*nlpp)->next;
11007 *nlpp = stzalloc(sizeof(**nlpp));
11008 /* (*nlpp)->next = NULL; - stzalloc did it */
11009 parsebackquote = oldstyle;
11012 saveprompt = doprompt;
11019 doprompt = saveprompt;
11020 else if (readtoken() != TRP)
11021 raise_error_unexpected_syntax(TRP);
11026 * Start reading from old file again, ignoring any pushed back
11027 * tokens left from the backquote parsing
11032 while (stackblocksize() <= savelen)
11034 STARTSTACKSTR(out);
11036 memcpy(out, str, savelen);
11037 STADJUST(savelen, out);
11043 parsebackquote = savepbq;
11044 exception_handler = savehandler;
11045 if (arinest || dblquote)
11046 USTPUTC(CTLBACKQ | CTLQUOTE, out);
11048 USTPUTC(CTLBACKQ, out);
11050 goto parsebackq_oldreturn;
11051 goto parsebackq_newreturn;
11054 #if ENABLE_ASH_MATH_SUPPORT
11056 * Parse an arithmetic expansion (indicate start of one and set state)
11059 if (++arinest == 1) {
11060 prevsyntax = syntax;
11061 syntax = ARISYNTAX;
11062 USTPUTC(CTLARI, out);
11069 * we collapse embedded arithmetic expansion to
11070 * parenthesis, which should be equivalent
11074 goto parsearith_return;
11078 } /* end of readtoken */
11081 * Read the next input token.
11082 * If the token is a word, we set backquotelist to the list of cmds in
11083 * backquotes. We set quoteflag to true if any part of the word was
11085 * If the token is TREDIR, then we set redirnode to a structure containing
11087 * In all cases, the variable startlinno is set to the number of the line
11088 * on which the token starts.
11090 * [Change comment: here documents and internal procedures]
11091 * [Readtoken shouldn't have any arguments. Perhaps we should make the
11092 * word parsing code into a separate routine. In this case, readtoken
11093 * doesn't need to have any internal procedures, but parseword does.
11094 * We could also make parseoperator in essence the main routine, and
11095 * have parseword (readtoken1?) handle both words and redirection.]
11097 #define NEW_xxreadtoken
11098 #ifdef NEW_xxreadtoken
11099 /* singles must be first! */
11100 static const char xxreadtoken_chars[7] ALIGN1 = {
11101 '\n', '(', ')', '&', '|', ';', 0
11104 static const char xxreadtoken_tokens[] ALIGN1 = {
11105 TNL, TLP, TRP, /* only single occurrence allowed */
11106 TBACKGND, TPIPE, TSEMI, /* if single occurrence */
11107 TEOF, /* corresponds to trailing nul */
11108 TAND, TOR, TENDCASE /* if double occurrence */
11111 #define xxreadtoken_doubles \
11112 (sizeof(xxreadtoken_tokens) - sizeof(xxreadtoken_chars))
11113 #define xxreadtoken_singles \
11114 (sizeof(xxreadtoken_chars) - xxreadtoken_doubles - 1)
11128 startlinno = plinno;
11129 for (;;) { /* until token or start of word found */
11132 if ((c != ' ') && (c != '\t')
11133 #if ENABLE_ASH_ALIAS
11138 while ((c = pgetc()) != '\n' && c != PEOF)
11141 } else if (c == '\\') {
11142 if (pgetc() != '\n') {
11146 startlinno = ++plinno;
11151 = xxreadtoken_chars + sizeof(xxreadtoken_chars) - 1;
11156 needprompt = doprompt;
11159 p = strchr(xxreadtoken_chars, c);
11162 return readtoken1(c, BASESYNTAX, (char *) NULL, 0);
11165 if ((size_t)(p - xxreadtoken_chars) >= xxreadtoken_singles) {
11166 if (pgetc() == *p) { /* double occurrence? */
11167 p += xxreadtoken_doubles + 1;
11173 lasttoken = xxreadtoken_tokens[p - xxreadtoken_chars];
11180 #define RETURN(token) return lasttoken = token
11193 startlinno = plinno;
11194 for (;;) { /* until token or start of word found */
11197 case ' ': case '\t':
11198 #if ENABLE_ASH_ALIAS
11203 while ((c = pgetc()) != '\n' && c != PEOF)
11208 if (pgetc() == '\n') {
11209 startlinno = ++plinno;
11218 needprompt = doprompt;
11223 if (pgetc() == '&')
11228 if (pgetc() == '|')
11233 if (pgetc() == ';')
11246 return readtoken1(c, BASESYNTAX, (char *)NULL, 0);
11249 #endif /* NEW_xxreadtoken */
11256 smallint alreadyseen = tokpushback;
11259 #if ENABLE_ASH_ALIAS
11268 if (checkkwd & CHKNL) {
11275 if (t != TWORD || quoteflag) {
11280 * check for keywords
11282 if (checkkwd & CHKKWD) {
11283 const char *const *pp;
11285 pp = findkwd(wordtext);
11287 lasttoken = t = pp - tokname_array;
11288 TRACE(("keyword %s recognized\n", tokname(t)));
11293 if (checkkwd & CHKALIAS) {
11294 #if ENABLE_ASH_ALIAS
11296 ap = lookupalias(wordtext, 1);
11299 pushstring(ap->val, ap);
11309 TRACE(("token %s %s\n", tokname(t), t == TWORD ? wordtext : ""));
11311 TRACE(("reread token %s %s\n", tokname(t), t == TWORD ? wordtext : ""));
11323 return tokname_array[t][0];
11327 * Read and parse a command. Returns NEOF on end of file. (NULL is a
11328 * valid parse tree indicating a blank line.)
11330 static union node *
11331 parsecmd(int interact)
11336 doprompt = interact;
11338 setprompt(doprompt);
11350 * Input any here documents.
11355 struct heredoc *here;
11358 here = heredoclist;
11359 heredoclist = NULL;
11365 readtoken1(pgetc(), here->here->type == NHERE? SQSYNTAX : DQSYNTAX,
11366 here->eofmark, here->striptabs);
11367 n = stzalloc(sizeof(struct narg));
11368 n->narg.type = NARG;
11369 /*n->narg.next = NULL; - stzalloc did it */
11370 n->narg.text = wordtext;
11371 n->narg.backquote = backquotelist;
11372 here->here->nhere.doc = n;
11379 * called by editline -- any expansions to the prompt should be added here.
11381 #if ENABLE_ASH_EXPAND_PRMT
11382 static const char *
11383 expandstr(const char *ps)
11387 /* XXX Fix (char *) cast. */
11388 setinputstring((char *)ps);
11389 readtoken1(pgetc(), PSSYNTAX, nullstr, 0);
11392 n.narg.type = NARG;
11393 n.narg.next = NULL;
11394 n.narg.text = wordtext;
11395 n.narg.backquote = backquotelist;
11397 expandarg(&n, NULL, 0);
11398 return stackblock();
11403 * Execute a command or commands contained in a string.
11406 evalstring(char *s, int mask)
11409 struct stackmark smark;
11413 setstackmark(&smark);
11416 while ((n = parsecmd(0)) != NEOF) {
11418 popstackmark(&smark);
11431 * The eval command.
11434 evalcmd(int argc UNUSED_PARAM, char **argv)
11443 STARTSTACKSTR(concat);
11445 concat = stack_putstr(p, concat);
11449 STPUTC(' ', concat);
11451 STPUTC('\0', concat);
11452 p = grabstackstr(concat);
11454 evalstring(p, ~SKIPEVAL);
11461 * Read and execute commands. "Top" is nonzero for the top level command
11462 * loop; it turns on prompting if the shell is interactive.
11468 struct stackmark smark;
11472 TRACE(("cmdloop(%d) called\n", top));
11476 setstackmark(&smark);
11479 showjobs(stderr, SHOW_CHANGED);
11482 if (iflag && top) {
11484 #if ENABLE_ASH_MAIL
11488 n = parsecmd(inter);
11489 /* showtree(n); DEBUG */
11491 if (!top || numeof >= 50)
11493 if (!stoppedjobs()) {
11496 out2str("\nUse \"exit\" to leave shell.\n");
11499 } else if (nflag == 0) {
11500 /* job_warning can only be 2,1,0. Here 2->1, 1/0->0 */
11505 popstackmark(&smark);
11510 return skip & SKIPEVAL;
11517 * Take commands from a file. To be compatible we should do a path
11518 * search for the file, which is necessary to find sub-commands.
11521 find_dot_file(char *name)
11524 const char *path = pathval();
11527 /* don't try this for absolute or relative paths */
11528 if (strchr(name, '/'))
11531 while ((fullname = padvance(&path, name)) != NULL) {
11532 if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) {
11534 * Don't bother freeing here, since it will
11535 * be freed by the caller.
11539 stunalloc(fullname);
11542 /* not found in the PATH */
11543 ash_msg_and_raise_error("%s: not found", name);
11548 dotcmd(int argc, char **argv)
11550 struct strlist *sp;
11551 volatile struct shparam saveparam;
11554 for (sp = cmdenviron; sp; sp = sp->next)
11555 setvareq(ckstrdup(sp->text), VSTRFIXED | VTEXTFIXED);
11557 if (argv[1]) { /* That's what SVR2 does */
11558 char *fullname = find_dot_file(argv[1]);
11561 if (argc) { /* argc > 0, argv[0] != NULL */
11562 saveparam = shellparam;
11563 shellparam.malloced = 0;
11564 shellparam.nparam = argc;
11565 shellparam.p = argv;
11568 setinputfile(fullname, INPUT_PUSH_FILE);
11569 commandname = fullname;
11574 freeparam(&shellparam);
11575 shellparam = saveparam;
11577 status = exitstatus;
11583 exitcmd(int argc UNUSED_PARAM, char **argv)
11588 exitstatus = number(argv[1]);
11589 raise_exception(EXEXIT);
11594 * Read a file containing shell functions.
11597 readcmdfile(char *name)
11599 setinputfile(name, INPUT_PUSH_FILE);
11605 /* ============ find_command inplementation */
11608 * Resolve a command name. If you change this routine, you may have to
11609 * change the shellexec routine as well.
11612 find_command(char *name, struct cmdentry *entry, int act, const char *path)
11614 struct tblentry *cmdp;
11621 struct builtincmd *bcmd;
11623 /* If name contains a slash, don't use PATH or hash table */
11624 if (strchr(name, '/') != NULL) {
11625 entry->u.index = -1;
11626 if (act & DO_ABS) {
11627 while (stat(name, &statb) < 0) {
11629 if (errno == EINTR)
11632 entry->cmdtype = CMDUNKNOWN;
11636 entry->cmdtype = CMDNORMAL;
11640 /* #if ENABLE_FEATURE_SH_STANDALONE... moved after builtin check */
11642 updatetbl = (path == pathval());
11645 if (strstr(path, "%builtin") != NULL)
11646 act |= DO_ALTBLTIN;
11649 /* If name is in the table, check answer will be ok */
11650 cmdp = cmdlookup(name, 0);
11651 if (cmdp != NULL) {
11654 switch (cmdp->cmdtype) {
11672 } else if (cmdp->rehash == 0)
11673 /* if not invalidated by cd, we're done */
11677 /* If %builtin not in path, check for builtin next */
11678 bcmd = find_builtin(name);
11680 if (IS_BUILTIN_REGULAR(bcmd))
11681 goto builtin_success;
11682 if (act & DO_ALTPATH) {
11683 if (!(act & DO_ALTBLTIN))
11684 goto builtin_success;
11685 } else if (builtinloc <= 0) {
11686 goto builtin_success;
11690 #if ENABLE_FEATURE_SH_STANDALONE
11692 int applet_no = find_applet_by_name(name);
11693 if (applet_no >= 0) {
11694 entry->cmdtype = CMDNORMAL;
11695 entry->u.index = -2 - applet_no;
11701 /* We have to search path. */
11702 prev = -1; /* where to start */
11703 if (cmdp && cmdp->rehash) { /* doing a rehash */
11704 if (cmdp->cmdtype == CMDBUILTIN)
11707 prev = cmdp->param.index;
11713 while ((fullname = padvance(&path, name)) != NULL) {
11714 stunalloc(fullname);
11715 /* NB: code below will still use fullname
11716 * despite it being "unallocated" */
11719 if (prefix(pathopt, "builtin")) {
11721 goto builtin_success;
11724 if ((act & DO_NOFUNC)
11725 || !prefix(pathopt, "func")
11726 ) { /* ignore unimplemented options */
11730 /* if rehash, don't redo absolute path names */
11731 if (fullname[0] == '/' && idx <= prev) {
11734 TRACE(("searchexec \"%s\": no change\n", name));
11737 while (stat(fullname, &statb) < 0) {
11739 if (errno == EINTR)
11742 if (errno != ENOENT && errno != ENOTDIR)
11746 e = EACCES; /* if we fail, this will be the error */
11747 if (!S_ISREG(statb.st_mode))
11749 if (pathopt) { /* this is a %func directory */
11750 stalloc(strlen(fullname) + 1);
11751 /* NB: stalloc will return space pointed by fullname
11752 * (because we don't have any intervening allocations
11753 * between stunalloc above and this stalloc) */
11754 readcmdfile(fullname);
11755 cmdp = cmdlookup(name, 0);
11756 if (cmdp == NULL || cmdp->cmdtype != CMDFUNCTION)
11757 ash_msg_and_raise_error("%s not defined in %s", name, fullname);
11758 stunalloc(fullname);
11761 TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
11763 entry->cmdtype = CMDNORMAL;
11764 entry->u.index = idx;
11768 cmdp = cmdlookup(name, 1);
11769 cmdp->cmdtype = CMDNORMAL;
11770 cmdp->param.index = idx;
11775 /* We failed. If there was an entry for this command, delete it */
11776 if (cmdp && updatetbl)
11777 delete_cmd_entry();
11779 ash_msg("%s: %s", name, errmsg(e, "not found"));
11780 entry->cmdtype = CMDUNKNOWN;
11785 entry->cmdtype = CMDBUILTIN;
11786 entry->u.cmd = bcmd;
11790 cmdp = cmdlookup(name, 1);
11791 cmdp->cmdtype = CMDBUILTIN;
11792 cmdp->param.cmd = bcmd;
11796 entry->cmdtype = cmdp->cmdtype;
11797 entry->u = cmdp->param;
11801 /* ============ trap.c */
11804 * The trap builtin.
11807 trapcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
11816 for (signo = 0; signo < NSIG; signo++) {
11817 if (trap[signo] != NULL) {
11820 sn = get_signame(signo);
11821 out1fmt("trap -- %s %s\n",
11822 single_quote(trap[signo]), sn);
11832 signo = get_signum(*ap);
11834 ash_msg_and_raise_error("%s: bad trap", *ap);
11837 if (LONE_DASH(action))
11840 action = ckstrdup(action);
11843 trap[signo] = action;
11853 /* ============ Builtins */
11855 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
11857 * Lists available builtins
11860 helpcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
11865 out1fmt("\nBuilt-in commands:\n-------------------\n");
11866 for (col = 0, i = 0; i < ARRAY_SIZE(builtintab); i++) {
11867 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '),
11868 builtintab[i].name + 1);
11874 #if ENABLE_FEATURE_SH_STANDALONE
11876 const char *a = applet_names;
11878 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '), a);
11883 a += strlen(a) + 1;
11888 return EXIT_SUCCESS;
11890 #endif /* FEATURE_SH_EXTRA_QUIET */
11893 * The export and readonly commands.
11896 exportcmd(int argc UNUSED_PARAM, char **argv)
11902 int flag = argv[0][0] == 'r'? VREADONLY : VEXPORT;
11904 if (nextopt("p") != 'p') {
11909 p = strchr(name, '=');
11913 vp = *findvar(hashvar(name), name);
11919 setvar(name, p, flag);
11920 } while ((name = *++aptr) != NULL);
11924 showvars(argv[0], flag, 0);
11929 * Delete a function if it exists.
11932 unsetfunc(const char *name)
11934 struct tblentry *cmdp;
11936 cmdp = cmdlookup(name, 0);
11937 if (cmdp!= NULL && cmdp->cmdtype == CMDFUNCTION)
11938 delete_cmd_entry();
11942 * The unset builtin command. We unset the function before we unset the
11943 * variable to allow a function to be unset when there is a readonly variable
11944 * with the same name.
11947 unsetcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
11954 while ((i = nextopt("vf")) != '\0') {
11958 for (ap = argptr; *ap; ap++) {
11974 #include <sys/times.h>
11976 static const unsigned char timescmd_str[] ALIGN1 = {
11977 ' ', offsetof(struct tms, tms_utime),
11978 '\n', offsetof(struct tms, tms_stime),
11979 ' ', offsetof(struct tms, tms_cutime),
11980 '\n', offsetof(struct tms, tms_cstime),
11985 timescmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
11987 long clk_tck, s, t;
11988 const unsigned char *p;
11991 clk_tck = sysconf(_SC_CLK_TCK);
11996 t = *(clock_t *)(((char *) &buf) + p[1]);
11998 out1fmt("%ldm%ld.%.3lds%c",
12000 ((t - s * clk_tck) * 1000) / clk_tck,
12002 } while (*(p += 2));
12007 #if ENABLE_ASH_MATH_SUPPORT
12009 dash_arith(const char *s)
12015 result = arith(s, &errcode);
12018 ash_msg_and_raise_error("exponent less than 0");
12020 ash_msg_and_raise_error("divide by zero");
12022 ash_msg_and_raise_error("expression recursion loop detected");
12023 raise_error_syntax(s);
12031 * The let builtin. partial stolen from GNU Bash, the Bourne Again SHell.
12032 * Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
12034 * Copyright (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
12037 letcmd(int argc UNUSED_PARAM, char **argv)
12043 ash_msg_and_raise_error("expression expected");
12045 i = dash_arith(*argv);
12050 #endif /* ASH_MATH_SUPPORT */
12053 /* ============ miscbltin.c
12055 * Miscellaneous builtins.
12060 #if defined(__GLIBC__) && __GLIBC__ == 2 && __GLIBC_MINOR__ < 1
12061 typedef enum __rlimit_resource rlim_t;
12065 * The read builtin. Options:
12066 * -r Do not interpret '\' specially
12067 * -s Turn off echo (tty only)
12068 * -n NCHARS Read NCHARS max
12069 * -p PROMPT Display PROMPT on stderr (if input is from tty)
12070 * -t SECONDS Timeout after SECONDS (tty or pipe only)
12071 * -u FD Read from given FD instead of fd 0
12072 * This uses unbuffered input, which may be avoidable in some cases.
12073 * TODO: bash also has:
12074 * -a ARRAY Read into array[0],[1],etc
12075 * -d DELIM End on DELIM char, not newline
12076 * -e Use line editing (tty only)
12079 readcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
12081 static const char *const arg_REPLY[] = { "REPLY", NULL };
12094 #if ENABLE_ASH_READ_NCHARS
12095 int nchars = 0; /* if != 0, -n is in effect */
12097 struct termios tty, old_tty;
12099 #if ENABLE_ASH_READ_TIMEOUT
12100 unsigned end_ms = 0;
12101 unsigned timeout = 0;
12106 while ((i = nextopt("p:u:r"
12107 USE_ASH_READ_TIMEOUT("t:")
12108 USE_ASH_READ_NCHARS("n:s")
12112 prompt = optionarg;
12114 #if ENABLE_ASH_READ_NCHARS
12116 nchars = bb_strtou(optionarg, NULL, 10);
12117 if (nchars < 0 || errno)
12118 ash_msg_and_raise_error("invalid count");
12119 /* nchars == 0: off (bash 3.2 does this too) */
12125 #if ENABLE_ASH_READ_TIMEOUT
12127 timeout = bb_strtou(optionarg, NULL, 10);
12128 if (errno || timeout > UINT_MAX / 2048)
12129 ash_msg_and_raise_error("invalid timeout");
12131 #if 0 /* even bash have no -t N.NNN support */
12132 ts.tv_sec = bb_strtou(optionarg, &p, 10);
12134 /* EINVAL means number is ok, but not terminated by NUL */
12135 if (*p == '.' && errno == EINVAL) {
12139 ts.tv_usec = bb_strtou(p, &p2, 10);
12141 ash_msg_and_raise_error("invalid timeout");
12143 /* normalize to usec */
12145 ash_msg_and_raise_error("invalid timeout");
12146 while (scale++ < 6)
12149 } else if (ts.tv_sec < 0 || errno) {
12150 ash_msg_and_raise_error("invalid timeout");
12152 if (!(ts.tv_sec | ts.tv_usec)) { /* both are 0? */
12153 ash_msg_and_raise_error("invalid timeout");
12162 fd = bb_strtou(optionarg, NULL, 10);
12163 if (fd < 0 || errno)
12164 ash_msg_and_raise_error("invalid file descriptor");
12170 if (prompt && isatty(fd)) {
12175 ap = (char**)arg_REPLY;
12176 ifs = bltinlookup("IFS");
12179 #if ENABLE_ASH_READ_NCHARS
12180 tcgetattr(fd, &tty);
12182 if (nchars || silent) {
12184 tty.c_lflag &= ~ICANON;
12185 tty.c_cc[VMIN] = nchars < 256 ? nchars : 255;
12188 tty.c_lflag &= ~(ECHO | ECHOK | ECHONL);
12190 /* if tcgetattr failed, tcsetattr will fail too.
12191 * Ignoring, it's harmless. */
12192 tcsetattr(fd, TCSANOW, &tty);
12199 #if ENABLE_ASH_READ_TIMEOUT
12200 if (timeout) /* NB: ensuring end_ms is nonzero */
12201 end_ms = ((unsigned)(monotonic_us() / 1000) + timeout) | 1;
12205 #if ENABLE_ASH_READ_TIMEOUT
12207 struct pollfd pfd[1];
12209 pfd[0].events = POLLIN;
12210 timeout = end_ms - (unsigned)(monotonic_us() / 1000);
12211 if ((int)timeout <= 0 /* already late? */
12212 || safe_poll(pfd, 1, timeout) != 1 /* no? wait... */
12213 ) { /* timed out! */
12214 #if ENABLE_ASH_READ_NCHARS
12215 tcsetattr(fd, TCSANOW, &old_tty);
12221 if (nonblock_safe_read(fd, &c, 1) != 1) {
12233 if (!rflag && c == '\\') {
12239 if (startword && *ifs == ' ' && strchr(ifs, c)) {
12243 if (ap[1] != NULL && strchr(ifs, c) != NULL) {
12245 setvar(*ap, stackblock(), 0);
12254 /* end of do {} while: */
12255 #if ENABLE_ASH_READ_NCHARS
12261 #if ENABLE_ASH_READ_NCHARS
12262 tcsetattr(fd, TCSANOW, &old_tty);
12266 /* Remove trailing blanks */
12267 while ((char *)stackblock() <= --p && strchr(ifs, *p) != NULL)
12269 setvar(*ap, stackblock(), 0);
12270 while (*++ap != NULL)
12271 setvar(*ap, nullstr, 0);
12276 umaskcmd(int argc UNUSED_PARAM, char **argv)
12278 static const char permuser[3] ALIGN1 = "ugo";
12279 static const char permmode[3] ALIGN1 = "rwx";
12280 static const short permmask[] ALIGN2 = {
12281 S_IRUSR, S_IWUSR, S_IXUSR,
12282 S_IRGRP, S_IWGRP, S_IXGRP,
12283 S_IROTH, S_IWOTH, S_IXOTH
12289 int symbolic_mode = 0;
12291 while (nextopt("S") != '\0') {
12302 if (symbolic_mode) {
12306 for (i = 0; i < 3; i++) {
12309 *p++ = permuser[i];
12311 for (j = 0; j < 3; j++) {
12312 if ((mask & permmask[3 * i + j]) == 0) {
12313 *p++ = permmode[j];
12321 out1fmt("%.4o\n", mask);
12324 if (isdigit((unsigned char) *ap)) {
12327 if (*ap >= '8' || *ap < '0')
12328 ash_msg_and_raise_error(illnum, argv[1]);
12329 mask = (mask << 3) + (*ap - '0');
12330 } while (*++ap != '\0');
12333 mask = ~mask & 0777;
12334 if (!bb_parse_mode(ap, &mask)) {
12335 ash_msg_and_raise_error("illegal mode: %s", ap);
12337 umask(~mask & 0777);
12346 * This code, originally by Doug Gwyn, Doug Kingston, Eric Gisin, and
12347 * Michael Rendell was ripped from pdksh 5.0.8 and hacked for use with
12348 * ash by J.T. Conklin.
12354 uint8_t cmd; /* RLIMIT_xxx fit into it */
12355 uint8_t factor_shift; /* shift by to get rlim_{cur,max} values */
12359 static const struct limits limits_tbl[] = {
12361 { RLIMIT_CPU, 0, 't' },
12363 #ifdef RLIMIT_FSIZE
12364 { RLIMIT_FSIZE, 9, 'f' },
12367 { RLIMIT_DATA, 10, 'd' },
12369 #ifdef RLIMIT_STACK
12370 { RLIMIT_STACK, 10, 's' },
12373 { RLIMIT_CORE, 9, 'c' },
12376 { RLIMIT_RSS, 10, 'm' },
12378 #ifdef RLIMIT_MEMLOCK
12379 { RLIMIT_MEMLOCK, 10, 'l' },
12381 #ifdef RLIMIT_NPROC
12382 { RLIMIT_NPROC, 0, 'p' },
12384 #ifdef RLIMIT_NOFILE
12385 { RLIMIT_NOFILE, 0, 'n' },
12388 { RLIMIT_AS, 10, 'v' },
12390 #ifdef RLIMIT_LOCKS
12391 { RLIMIT_LOCKS, 0, 'w' },
12394 static const char limits_name[] =
12396 "time(seconds)" "\0"
12398 #ifdef RLIMIT_FSIZE
12399 "file(blocks)" "\0"
12404 #ifdef RLIMIT_STACK
12408 "coredump(blocks)" "\0"
12413 #ifdef RLIMIT_MEMLOCK
12414 "locked memory(kb)" "\0"
12416 #ifdef RLIMIT_NPROC
12419 #ifdef RLIMIT_NOFILE
12425 #ifdef RLIMIT_LOCKS
12430 enum limtype { SOFT = 0x1, HARD = 0x2 };
12433 printlim(enum limtype how, const struct rlimit *limit,
12434 const struct limits *l)
12438 val = limit->rlim_max;
12440 val = limit->rlim_cur;
12442 if (val == RLIM_INFINITY)
12443 out1fmt("unlimited\n");
12445 val >>= l->factor_shift;
12446 out1fmt("%lld\n", (long long) val);
12451 ulimitcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
12455 enum limtype how = SOFT | HARD;
12456 const struct limits *l;
12459 struct rlimit limit;
12462 while ((optc = nextopt("HSa"
12466 #ifdef RLIMIT_FSIZE
12472 #ifdef RLIMIT_STACK
12481 #ifdef RLIMIT_MEMLOCK
12484 #ifdef RLIMIT_NPROC
12487 #ifdef RLIMIT_NOFILE
12493 #ifdef RLIMIT_LOCKS
12511 for (l = limits_tbl; l->option != what; l++)
12514 set = *argptr ? 1 : 0;
12518 if (all || argptr[1])
12519 ash_msg_and_raise_error("too many arguments");
12520 if (strncmp(p, "unlimited\n", 9) == 0)
12521 val = RLIM_INFINITY;
12525 while ((c = *p++) >= '0' && c <= '9') {
12526 val = (val * 10) + (long)(c - '0');
12527 // val is actually 'unsigned long int' and can't get < 0
12528 if (val < (rlim_t) 0)
12532 ash_msg_and_raise_error("bad number");
12533 val <<= l->factor_shift;
12537 const char *lname = limits_name;
12538 for (l = limits_tbl; l != &limits_tbl[ARRAY_SIZE(limits_tbl)]; l++) {
12539 getrlimit(l->cmd, &limit);
12540 out1fmt("%-20s ", lname);
12541 lname += strlen(lname) + 1;
12542 printlim(how, &limit, l);
12547 getrlimit(l->cmd, &limit);
12550 limit.rlim_max = val;
12552 limit.rlim_cur = val;
12553 if (setrlimit(l->cmd, &limit) < 0)
12554 ash_msg_and_raise_error("error setting limit (%m)");
12556 printlim(how, &limit, l);
12562 /* ============ Math support */
12564 #if ENABLE_ASH_MATH_SUPPORT
12566 /* Copyright (c) 2001 Aaron Lehmann <aaronl@vitelus.com>
12568 Permission is hereby granted, free of charge, to any person obtaining
12569 a copy of this software and associated documentation files (the
12570 "Software"), to deal in the Software without restriction, including
12571 without limitation the rights to use, copy, modify, merge, publish,
12572 distribute, sublicense, and/or sell copies of the Software, and to
12573 permit persons to whom the Software is furnished to do so, subject to
12574 the following conditions:
12576 The above copyright notice and this permission notice shall be
12577 included in all copies or substantial portions of the Software.
12579 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
12580 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
12581 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
12582 IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
12583 CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
12584 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
12585 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
12588 /* This is my infix parser/evaluator. It is optimized for size, intended
12589 * as a replacement for yacc-based parsers. However, it may well be faster
12590 * than a comparable parser written in yacc. The supported operators are
12591 * listed in #defines below. Parens, order of operations, and error handling
12592 * are supported. This code is thread safe. The exact expression format should
12593 * be that which POSIX specifies for shells. */
12595 /* The code uses a simple two-stack algorithm. See
12596 * http://www.onthenet.com.au/~grahamis/int2008/week02/lect02.html
12597 * for a detailed explanation of the infix-to-postfix algorithm on which
12598 * this is based (this code differs in that it applies operators immediately
12599 * to the stack instead of adding them to a queue to end up with an
12602 /* To use the routine, call it with an expression string and error return
12606 * Aug 24, 2001 Manuel Novoa III
12608 * Reduced the generated code size by about 30% (i386) and fixed several bugs.
12610 * 1) In arith_apply():
12611 * a) Cached values of *numptr and &(numptr[-1]).
12612 * b) Removed redundant test for zero denominator.
12615 * a) Eliminated redundant code for processing operator tokens by moving
12616 * to a table-based implementation. Also folded handling of parens
12618 * b) Combined all 3 loops which called arith_apply to reduce generated
12619 * code size at the cost of speed.
12621 * 3) The following expressions were treated as valid by the original code:
12622 * 1() , 0! , 1 ( *3 ) .
12623 * These bugs have been fixed by internally enclosing the expression in
12624 * parens and then checking that all binary ops and right parens are
12625 * preceded by a valid expression (NUM_TOKEN).
12627 * Note: It may be desirable to replace Aaron's test for whitespace with
12628 * ctype's isspace() if it is used by another busybox applet or if additional
12629 * whitespace chars should be considered. Look below the "#include"s for a
12630 * precompiler test.
12634 * Aug 26, 2001 Manuel Novoa III
12636 * Return 0 for null expressions. Pointed out by Vladimir Oleynik.
12638 * Merge in Aaron's comments previously posted to the busybox list,
12639 * modified slightly to take account of my changes to the code.
12644 * (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
12646 * - allow access to variable,
12647 * used recursive find value indirection (c=2*2; a="c"; $((a+=2)) produce 6)
12648 * - realize assign syntax (VAR=expr, +=, *= etc)
12649 * - realize exponentiation (** operator)
12650 * - realize comma separated - expr, expr
12651 * - realise ++expr --expr expr++ expr--
12652 * - realise expr ? expr : expr (but, second expr calculate always)
12653 * - allow hexadecimal and octal numbers
12654 * - was restored loses XOR operator
12655 * - remove one goto label, added three ;-)
12656 * - protect $((num num)) as true zero expr (Manuel`s error)
12657 * - always use special isspace(), see comment from bash ;-)
12660 #define arith_isspace(arithval) \
12661 (arithval == ' ' || arithval == '\n' || arithval == '\t')
12663 typedef unsigned char operator;
12665 /* An operator's token id is a bit of a bitfield. The lower 5 bits are the
12666 * precedence, and 3 high bits are an ID unique across operators of that
12667 * precedence. The ID portion is so that multiple operators can have the
12668 * same precedence, ensuring that the leftmost one is evaluated first.
12669 * Consider * and /. */
12671 #define tok_decl(prec,id) (((id)<<5)|(prec))
12672 #define PREC(op) ((op) & 0x1F)
12674 #define TOK_LPAREN tok_decl(0,0)
12676 #define TOK_COMMA tok_decl(1,0)
12678 #define TOK_ASSIGN tok_decl(2,0)
12679 #define TOK_AND_ASSIGN tok_decl(2,1)
12680 #define TOK_OR_ASSIGN tok_decl(2,2)
12681 #define TOK_XOR_ASSIGN tok_decl(2,3)
12682 #define TOK_PLUS_ASSIGN tok_decl(2,4)
12683 #define TOK_MINUS_ASSIGN tok_decl(2,5)
12684 #define TOK_LSHIFT_ASSIGN tok_decl(2,6)
12685 #define TOK_RSHIFT_ASSIGN tok_decl(2,7)
12687 #define TOK_MUL_ASSIGN tok_decl(3,0)
12688 #define TOK_DIV_ASSIGN tok_decl(3,1)
12689 #define TOK_REM_ASSIGN tok_decl(3,2)
12691 /* all assign is right associativity and precedence eq, but (7+3)<<5 > 256 */
12692 #define convert_prec_is_assing(prec) do { if (prec == 3) prec = 2; } while (0)
12694 /* conditional is right associativity too */
12695 #define TOK_CONDITIONAL tok_decl(4,0)
12696 #define TOK_CONDITIONAL_SEP tok_decl(4,1)
12698 #define TOK_OR tok_decl(5,0)
12700 #define TOK_AND tok_decl(6,0)
12702 #define TOK_BOR tok_decl(7,0)
12704 #define TOK_BXOR tok_decl(8,0)
12706 #define TOK_BAND tok_decl(9,0)
12708 #define TOK_EQ tok_decl(10,0)
12709 #define TOK_NE tok_decl(10,1)
12711 #define TOK_LT tok_decl(11,0)
12712 #define TOK_GT tok_decl(11,1)
12713 #define TOK_GE tok_decl(11,2)
12714 #define TOK_LE tok_decl(11,3)
12716 #define TOK_LSHIFT tok_decl(12,0)
12717 #define TOK_RSHIFT tok_decl(12,1)
12719 #define TOK_ADD tok_decl(13,0)
12720 #define TOK_SUB tok_decl(13,1)
12722 #define TOK_MUL tok_decl(14,0)
12723 #define TOK_DIV tok_decl(14,1)
12724 #define TOK_REM tok_decl(14,2)
12726 /* exponent is right associativity */
12727 #define TOK_EXPONENT tok_decl(15,1)
12729 /* For now unary operators. */
12730 #define UNARYPREC 16
12731 #define TOK_BNOT tok_decl(UNARYPREC,0)
12732 #define TOK_NOT tok_decl(UNARYPREC,1)
12734 #define TOK_UMINUS tok_decl(UNARYPREC+1,0)
12735 #define TOK_UPLUS tok_decl(UNARYPREC+1,1)
12737 #define PREC_PRE (UNARYPREC+2)
12739 #define TOK_PRE_INC tok_decl(PREC_PRE, 0)
12740 #define TOK_PRE_DEC tok_decl(PREC_PRE, 1)
12742 #define PREC_POST (UNARYPREC+3)
12744 #define TOK_POST_INC tok_decl(PREC_POST, 0)
12745 #define TOK_POST_DEC tok_decl(PREC_POST, 1)
12747 #define SPEC_PREC (UNARYPREC+4)
12749 #define TOK_NUM tok_decl(SPEC_PREC, 0)
12750 #define TOK_RPAREN tok_decl(SPEC_PREC, 1)
12752 #define NUMPTR (*numstackptr)
12755 tok_have_assign(operator op)
12757 operator prec = PREC(op);
12759 convert_prec_is_assing(prec);
12760 return (prec == PREC(TOK_ASSIGN) ||
12761 prec == PREC_PRE || prec == PREC_POST);
12765 is_right_associativity(operator prec)
12767 return (prec == PREC(TOK_ASSIGN) || prec == PREC(TOK_EXPONENT)
12768 || prec == PREC(TOK_CONDITIONAL));
12773 arith_t contidional_second_val;
12774 char contidional_second_val_initialized;
12775 char *var; /* if NULL then is regular number,
12776 else is variable name */
12779 typedef struct chk_var_recursive_looped_t {
12781 struct chk_var_recursive_looped_t *next;
12782 } chk_var_recursive_looped_t;
12784 static chk_var_recursive_looped_t *prev_chk_var_recursive;
12787 arith_lookup_val(v_n_t *t)
12790 const char * p = lookupvar(t->var);
12795 /* recursive try as expression */
12796 chk_var_recursive_looped_t *cur;
12797 chk_var_recursive_looped_t cur_save;
12799 for (cur = prev_chk_var_recursive; cur; cur = cur->next) {
12800 if (strcmp(cur->var, t->var) == 0) {
12801 /* expression recursion loop detected */
12805 /* save current lookuped var name */
12806 cur = prev_chk_var_recursive;
12807 cur_save.var = t->var;
12808 cur_save.next = cur;
12809 prev_chk_var_recursive = &cur_save;
12811 t->val = arith (p, &errcode);
12812 /* restore previous ptr after recursiving */
12813 prev_chk_var_recursive = cur;
12816 /* allow undefined var as 0 */
12822 /* "applying" a token means performing it on the top elements on the integer
12823 * stack. For a unary operator it will only change the top element, but a
12824 * binary operator will pop two arguments and push a result */
12826 arith_apply(operator op, v_n_t *numstack, v_n_t **numstackptr)
12829 arith_t numptr_val, rez;
12830 int ret_arith_lookup_val;
12832 /* There is no operator that can work without arguments */
12833 if (NUMPTR == numstack) goto err;
12834 numptr_m1 = NUMPTR - 1;
12836 /* check operand is var with noninteger value */
12837 ret_arith_lookup_val = arith_lookup_val(numptr_m1);
12838 if (ret_arith_lookup_val)
12839 return ret_arith_lookup_val;
12841 rez = numptr_m1->val;
12842 if (op == TOK_UMINUS)
12844 else if (op == TOK_NOT)
12846 else if (op == TOK_BNOT)
12848 else if (op == TOK_POST_INC || op == TOK_PRE_INC)
12850 else if (op == TOK_POST_DEC || op == TOK_PRE_DEC)
12852 else if (op != TOK_UPLUS) {
12853 /* Binary operators */
12855 /* check and binary operators need two arguments */
12856 if (numptr_m1 == numstack) goto err;
12858 /* ... and they pop one */
12861 if (op == TOK_CONDITIONAL) {
12862 if (!numptr_m1->contidional_second_val_initialized) {
12863 /* protect $((expr1 ? expr2)) without ": expr" */
12866 rez = numptr_m1->contidional_second_val;
12867 } else if (numptr_m1->contidional_second_val_initialized) {
12868 /* protect $((expr1 : expr2)) without "expr ? " */
12871 numptr_m1 = NUMPTR - 1;
12872 if (op != TOK_ASSIGN) {
12873 /* check operand is var with noninteger value for not '=' */
12874 ret_arith_lookup_val = arith_lookup_val(numptr_m1);
12875 if (ret_arith_lookup_val)
12876 return ret_arith_lookup_val;
12878 if (op == TOK_CONDITIONAL) {
12879 numptr_m1->contidional_second_val = rez;
12881 rez = numptr_m1->val;
12882 if (op == TOK_BOR || op == TOK_OR_ASSIGN)
12884 else if (op == TOK_OR)
12885 rez = numptr_val || rez;
12886 else if (op == TOK_BAND || op == TOK_AND_ASSIGN)
12888 else if (op == TOK_BXOR || op == TOK_XOR_ASSIGN)
12890 else if (op == TOK_AND)
12891 rez = rez && numptr_val;
12892 else if (op == TOK_EQ)
12893 rez = (rez == numptr_val);
12894 else if (op == TOK_NE)
12895 rez = (rez != numptr_val);
12896 else if (op == TOK_GE)
12897 rez = (rez >= numptr_val);
12898 else if (op == TOK_RSHIFT || op == TOK_RSHIFT_ASSIGN)
12899 rez >>= numptr_val;
12900 else if (op == TOK_LSHIFT || op == TOK_LSHIFT_ASSIGN)
12901 rez <<= numptr_val;
12902 else if (op == TOK_GT)
12903 rez = (rez > numptr_val);
12904 else if (op == TOK_LT)
12905 rez = (rez < numptr_val);
12906 else if (op == TOK_LE)
12907 rez = (rez <= numptr_val);
12908 else if (op == TOK_MUL || op == TOK_MUL_ASSIGN)
12910 else if (op == TOK_ADD || op == TOK_PLUS_ASSIGN)
12912 else if (op == TOK_SUB || op == TOK_MINUS_ASSIGN)
12914 else if (op == TOK_ASSIGN || op == TOK_COMMA)
12916 else if (op == TOK_CONDITIONAL_SEP) {
12917 if (numptr_m1 == numstack) {
12918 /* protect $((expr : expr)) without "expr ? " */
12921 numptr_m1->contidional_second_val_initialized = op;
12922 numptr_m1->contidional_second_val = numptr_val;
12923 } else if (op == TOK_CONDITIONAL) {
12925 numptr_val : numptr_m1->contidional_second_val;
12926 } else if (op == TOK_EXPONENT) {
12927 if (numptr_val < 0)
12928 return -3; /* exponent less than 0 */
12933 while (numptr_val--)
12937 } else if (numptr_val==0) /* zero divisor check */
12939 else if (op == TOK_DIV || op == TOK_DIV_ASSIGN)
12941 else if (op == TOK_REM || op == TOK_REM_ASSIGN)
12944 if (tok_have_assign(op)) {
12945 char buf[sizeof(arith_t_type)*3 + 2];
12947 if (numptr_m1->var == NULL) {
12951 /* save to shell variable */
12952 #if ENABLE_ASH_MATH_SUPPORT_64
12953 snprintf(buf, sizeof(buf), "%lld", (arith_t_type) rez);
12955 snprintf(buf, sizeof(buf), "%ld", (arith_t_type) rez);
12957 setvar(numptr_m1->var, buf, 0);
12958 /* after saving, make previous value for v++ or v-- */
12959 if (op == TOK_POST_INC)
12961 else if (op == TOK_POST_DEC)
12964 numptr_m1->val = rez;
12965 /* protect geting var value, is number now */
12966 numptr_m1->var = NULL;
12972 /* longest must be first */
12973 static const char op_tokens[] ALIGN1 = {
12974 '<','<','=',0, TOK_LSHIFT_ASSIGN,
12975 '>','>','=',0, TOK_RSHIFT_ASSIGN,
12976 '<','<', 0, TOK_LSHIFT,
12977 '>','>', 0, TOK_RSHIFT,
12978 '|','|', 0, TOK_OR,
12979 '&','&', 0, TOK_AND,
12980 '!','=', 0, TOK_NE,
12981 '<','=', 0, TOK_LE,
12982 '>','=', 0, TOK_GE,
12983 '=','=', 0, TOK_EQ,
12984 '|','=', 0, TOK_OR_ASSIGN,
12985 '&','=', 0, TOK_AND_ASSIGN,
12986 '*','=', 0, TOK_MUL_ASSIGN,
12987 '/','=', 0, TOK_DIV_ASSIGN,
12988 '%','=', 0, TOK_REM_ASSIGN,
12989 '+','=', 0, TOK_PLUS_ASSIGN,
12990 '-','=', 0, TOK_MINUS_ASSIGN,
12991 '-','-', 0, TOK_POST_DEC,
12992 '^','=', 0, TOK_XOR_ASSIGN,
12993 '+','+', 0, TOK_POST_INC,
12994 '*','*', 0, TOK_EXPONENT,
12998 '=', 0, TOK_ASSIGN,
13010 '?', 0, TOK_CONDITIONAL,
13011 ':', 0, TOK_CONDITIONAL_SEP,
13012 ')', 0, TOK_RPAREN,
13013 '(', 0, TOK_LPAREN,
13017 #define endexpression (&op_tokens[sizeof(op_tokens)-7])
13020 arith(const char *expr, int *perrcode)
13022 char arithval; /* Current character under analysis */
13023 operator lasttok, op;
13025 operator *stack, *stackptr;
13026 const char *p = endexpression;
13028 v_n_t *numstack, *numstackptr;
13029 unsigned datasizes = strlen(expr) + 2;
13031 /* Stack of integers */
13032 /* The proof that there can be no more than strlen(startbuf)/2+1 integers
13033 * in any given correct or incorrect expression is left as an exercise to
13035 numstackptr = numstack = alloca((datasizes / 2) * sizeof(numstack[0]));
13036 /* Stack of operator tokens */
13037 stackptr = stack = alloca(datasizes * sizeof(stack[0]));
13039 *stackptr++ = lasttok = TOK_LPAREN; /* start off with a left paren */
13040 *perrcode = errcode = 0;
13044 if (arithval == 0) {
13045 if (p == endexpression) {
13046 /* Null expression. */
13050 /* This is only reached after all tokens have been extracted from the
13051 * input stream. If there are still tokens on the operator stack, they
13052 * are to be applied in order. At the end, there should be a final
13053 * result on the integer stack */
13055 if (expr != endexpression + 1) {
13056 /* If we haven't done so already, */
13057 /* append a closing right paren */
13058 expr = endexpression;
13059 /* and let the loop process it. */
13062 /* At this point, we're done with the expression. */
13063 if (numstackptr != numstack+1) {
13064 /* ... but if there isn't, it's bad */
13069 if (numstack->var) {
13070 /* expression is $((var)) only, lookup now */
13071 errcode = arith_lookup_val(numstack);
13074 *perrcode = errcode;
13075 return numstack->val;
13078 /* Continue processing the expression. */
13079 if (arith_isspace(arithval)) {
13080 /* Skip whitespace */
13083 p = endofname(expr);
13085 size_t var_name_size = (p-expr) + 1; /* trailing zero */
13087 numstackptr->var = alloca(var_name_size);
13088 safe_strncpy(numstackptr->var, expr, var_name_size);
13091 numstackptr->contidional_second_val_initialized = 0;
13096 if (isdigit(arithval)) {
13097 numstackptr->var = NULL;
13098 #if ENABLE_ASH_MATH_SUPPORT_64
13099 numstackptr->val = strtoll(expr, (char **) &expr, 0);
13101 numstackptr->val = strtol(expr, (char **) &expr, 0);
13105 for (p = op_tokens; ; p++) {
13109 /* strange operator not found */
13112 for (o = expr; *p && *o == *p; p++)
13119 /* skip tail uncompared token */
13122 /* skip zero delim */
13127 /* post grammar: a++ reduce to num */
13128 if (lasttok == TOK_POST_INC || lasttok == TOK_POST_DEC)
13131 /* Plus and minus are binary (not unary) _only_ if the last
13132 * token was as number, or a right paren (which pretends to be
13133 * a number, since it evaluates to one). Think about it.
13134 * It makes sense. */
13135 if (lasttok != TOK_NUM) {
13151 /* We don't want a unary operator to cause recursive descent on the
13152 * stack, because there can be many in a row and it could cause an
13153 * operator to be evaluated before its argument is pushed onto the
13154 * integer stack. */
13155 /* But for binary operators, "apply" everything on the operator
13156 * stack until we find an operator with a lesser priority than the
13157 * one we have just extracted. */
13158 /* Left paren is given the lowest priority so it will never be
13159 * "applied" in this way.
13160 * if associativity is right and priority eq, applied also skip
13163 if ((prec > 0 && prec < UNARYPREC) || prec == SPEC_PREC) {
13164 /* not left paren or unary */
13165 if (lasttok != TOK_NUM) {
13166 /* binary op must be preceded by a num */
13169 while (stackptr != stack) {
13170 if (op == TOK_RPAREN) {
13171 /* The algorithm employed here is simple: while we don't
13172 * hit an open paren nor the bottom of the stack, pop
13173 * tokens and apply them */
13174 if (stackptr[-1] == TOK_LPAREN) {
13176 /* Any operator directly after a */
13178 /* close paren should consider itself binary */
13182 operator prev_prec = PREC(stackptr[-1]);
13184 convert_prec_is_assing(prec);
13185 convert_prec_is_assing(prev_prec);
13186 if (prev_prec < prec)
13188 /* check right assoc */
13189 if (prev_prec == prec && is_right_associativity(prec))
13192 errcode = arith_apply(*--stackptr, numstack, &numstackptr);
13193 if (errcode) goto ret;
13195 if (op == TOK_RPAREN) {
13200 /* Push this operator to the stack and remember it. */
13201 *stackptr++ = lasttok = op;
13206 #endif /* ASH_MATH_SUPPORT */
13209 /* ============ main() and helpers */
13212 * Called to exit the shell.
13214 static void exitshell(void) NORETURN;
13222 status = exitstatus;
13223 TRACE(("pid %d, exitshell(%d)\n", getpid(), status));
13224 if (setjmp(loc.loc)) {
13225 if (exception == EXEXIT)
13226 /* dash bug: it just does _exit(exitstatus) here
13227 * but we have to do setjobctl(0) first!
13228 * (bug is still not fixed in dash-0.5.3 - if you run dash
13229 * under Midnight Commander, on exit from dash MC is backgrounded) */
13230 status = exitstatus;
13233 exception_handler = &loc;
13239 flush_stdout_stderr();
13249 /* from input.c: */
13250 basepf.nextc = basepf.buf = basebuf;
13253 signal(SIGCHLD, SIG_DFL);
13258 char ppid[sizeof(int)*3 + 1];
13260 struct stat st1, st2;
13263 for (envp = environ; envp && *envp; envp++) {
13264 if (strchr(*envp, '=')) {
13265 setvareq(*envp, VEXPORT|VTEXTFIXED);
13269 snprintf(ppid, sizeof(ppid), "%u", (unsigned) getppid());
13270 setvar("PPID", ppid, 0);
13272 p = lookupvar("PWD");
13274 if (*p != '/' || stat(p, &st1) || stat(".", &st2)
13275 || st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino)
13282 * Process the shell command line arguments.
13285 procargs(char **argv)
13288 const char *xminusc;
13293 /* if (xargv[0]) - mmm, this is always true! */
13295 for (i = 0; i < NOPTS; i++)
13299 /* it already printed err message */
13300 raise_exception(EXERROR);
13304 if (*xargv == NULL) {
13306 ash_msg_and_raise_error(bb_msg_requires_arg, "-c");
13309 if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
13313 for (i = 0; i < NOPTS; i++)
13314 if (optlist[i] == 2)
13319 /* POSIX 1003.2: first arg after -c cmd is $0, remainder $1... */
13324 } else if (!sflag) {
13325 setinputfile(*xargv, 0);
13328 commandname = arg0;
13331 shellparam.p = xargv;
13332 #if ENABLE_ASH_GETOPTS
13333 shellparam.optind = 1;
13334 shellparam.optoff = -1;
13336 /* assert(shellparam.malloced == 0 && shellparam.nparam == 0); */
13338 shellparam.nparam++;
13345 * Read /etc/profile or .profile.
13348 read_profile(const char *name)
13352 if (setinputfile(name, INPUT_PUSH_FILE | INPUT_NOFILE_OK) < 0)
13361 * This routine is called when an error or an interrupt occurs in an
13362 * interactive shell and control is returned to the main command loop.
13370 /* from input.c: */
13371 parselleft = parsenleft = 0; /* clear input buffer */
13373 /* from parser.c: */
13376 /* from redir.c: */
13381 static short profile_buf[16384];
13382 extern int etext();
13386 * Main routine. We initialize things, parse the arguments, execute
13387 * profiles if we're a login shell, and then call cmdloop to execute
13388 * commands. The setjmp call sets up the location to jump to when an
13389 * exception occurs. When an exception occurs the variable "state"
13390 * is used to figure out how far we had gotten.
13392 int ash_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
13393 int ash_main(int argc UNUSED_PARAM, char **argv)
13396 volatile int state;
13397 struct jmploc jmploc;
13398 struct stackmark smark;
13400 /* Initialize global data */
13404 #if ENABLE_ASH_ALIAS
13410 monitor(4, etext, profile_buf, sizeof(profile_buf), 50);
13413 #if ENABLE_FEATURE_EDITING
13414 line_input_state = new_line_input_t(FOR_SHELL | WITH_PATH_LOOKUP);
13417 if (setjmp(jmploc.loc)) {
13427 if (e == EXEXIT || s == 0 || iflag == 0 || shlvl)
13431 outcslow('\n', stderr);
13433 popstackmark(&smark);
13434 FORCE_INT_ON; /* enable interrupts */
13443 exception_handler = &jmploc;
13446 trace_puts("Shell args: ");
13447 trace_puts_args(argv);
13449 rootpid = getpid();
13451 #if ENABLE_ASH_RANDOM_SUPPORT
13452 /* Can use monotonic_ns() for better randomness but for now it is
13453 * not used anywhere else in busybox... so avoid bloat */
13454 random_galois_LFSR = random_LCG = rootpid + monotonic_us();
13457 setstackmark(&smark);
13460 #if ENABLE_FEATURE_EDITING_SAVEHISTORY
13462 const char *hp = lookupvar("HISTFILE");
13465 hp = lookupvar("HOME");
13467 char *defhp = concat_path_file(hp, ".ash_history");
13468 setvar("HISTFILE", defhp, 0);
13474 if (argv[0] && argv[0][0] == '-')
13478 read_profile("/etc/profile");
13481 read_profile(".profile");
13487 getuid() == geteuid() && getgid() == getegid() &&
13491 shinit = lookupvar("ENV");
13492 if (shinit != NULL && *shinit != '\0') {
13493 read_profile(shinit);
13499 evalstring(minusc, 0);
13501 if (sflag || minusc == NULL) {
13502 #if ENABLE_FEATURE_EDITING_SAVEHISTORY
13504 const char *hp = lookupvar("HISTFILE");
13507 line_input_state->hist_file = hp;
13510 state4: /* XXX ??? - why isn't this before the "if" statement */
13518 extern void _mcleanup(void);
13527 const char *applet_name = "debug stuff usage";
13528 int main(int argc, char **argv)
13530 return ash_main(argc, argv);
13536 * Copyright (c) 1989, 1991, 1993, 1994
13537 * The Regents of the University of California. All rights reserved.
13539 * This code is derived from software contributed to Berkeley by
13540 * Kenneth Almquist.
13542 * Redistribution and use in source and binary forms, with or without
13543 * modification, are permitted provided that the following conditions
13545 * 1. Redistributions of source code must retain the above copyright
13546 * notice, this list of conditions and the following disclaimer.
13547 * 2. Redistributions in binary form must reproduce the above copyright
13548 * notice, this list of conditions and the following disclaimer in the
13549 * documentation and/or other materials provided with the distribution.
13550 * 3. Neither the name of the University nor the names of its contributors
13551 * may be used to endorse or promote products derived from this software
13552 * without specific prior written permission.
13554 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
13555 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
13556 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
13557 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
13558 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
13559 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
13560 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
13561 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
13562 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
13563 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF