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) ATTRIBUTE_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) ATTRIBUTE_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'
532 union node *redirect;
538 struct nodelist *cmdlist;
544 union node *redirect;
557 union node *elsepart;
584 struct nodelist *backquote;
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.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) ATTRIBUTE_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 *, ...) ATTRIBUTE_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 *, ...) ATTRIBUTE_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). the
1579 * library getopt must have the BSD extension static variable "optreset"
1580 * otherwise it can't be used within the shell safely.
1582 * Standard option processing (a la getopt) for builtin routines. The
1583 * only argument that is passed to nextopt is the option string; the
1584 * other arguments are unnecessary. It return the character, or '\0' on
1588 nextopt(const char *optstring)
1595 if (p == NULL || *p == '\0') {
1597 if (p == NULL || *p != '-' || *++p == '\0')
1600 if (LONE_DASH(p)) /* check for "--" */
1604 for (q = optstring; *q != c;) {
1606 ash_msg_and_raise_error("illegal option -%c", c);
1611 if (*p == '\0' && (p = *argptr++) == NULL)
1612 ash_msg_and_raise_error("no arg for -%c option", c);
1621 /* ============ Shell variables */
1624 * The parsefile structure pointed to by the global variable parsefile
1625 * contains information about the current file being read.
1628 struct redirtab *next;
1634 int nparam; /* # of positional parameters (without $0) */
1635 #if ENABLE_ASH_GETOPTS
1636 int optind; /* next parameter to be processed by getopts */
1637 int optoff; /* used by getopts */
1639 unsigned char malloced; /* if parameter list dynamically allocated */
1640 char **p; /* parameter list */
1644 * Free the list of positional parameters.
1647 freeparam(volatile struct shparam *param)
1651 if (param->malloced) {
1652 for (ap = param->p; *ap; ap++)
1658 #if ENABLE_ASH_GETOPTS
1659 static void getoptsreset(const char *value);
1663 struct var *next; /* next entry in hash list */
1664 int flags; /* flags are defined above */
1665 const char *text; /* name=value */
1666 void (*func)(const char *); /* function to be called when */
1667 /* the variable gets set/unset */
1671 struct localvar *next; /* next local variable in list */
1672 struct var *vp; /* the variable that was made local */
1673 int flags; /* saved flags */
1674 const char *text; /* saved text */
1678 #define VEXPORT 0x01 /* variable is exported */
1679 #define VREADONLY 0x02 /* variable cannot be modified */
1680 #define VSTRFIXED 0x04 /* variable struct is statically allocated */
1681 #define VTEXTFIXED 0x08 /* text is statically allocated */
1682 #define VSTACK 0x10 /* text is allocated on the stack */
1683 #define VUNSET 0x20 /* the variable is not set */
1684 #define VNOFUNC 0x40 /* don't call the callback function */
1685 #define VNOSET 0x80 /* do not set variable - just readonly test */
1686 #define VNOSAVE 0x100 /* when text is on the heap before setvareq */
1687 #if ENABLE_ASH_RANDOM_SUPPORT
1688 # define VDYNAMIC 0x200 /* dynamic variable */
1694 static const char defifsvar[] ALIGN1 = "IFS= \t\n";
1695 #define defifs (defifsvar + 4)
1697 static const char defifs[] ALIGN1 = " \t\n";
1701 /* Need to be before varinit_data[] */
1702 #if ENABLE_LOCALE_SUPPORT
1704 change_lc_all(const char *value)
1706 if (value && *value != '\0')
1707 setlocale(LC_ALL, value);
1710 change_lc_ctype(const char *value)
1712 if (value && *value != '\0')
1713 setlocale(LC_CTYPE, value);
1717 static void chkmail(void);
1718 static void changemail(const char *);
1720 static void changepath(const char *);
1721 #if ENABLE_ASH_RANDOM_SUPPORT
1722 static void change_random(const char *);
1725 static const struct {
1728 void (*func)(const char *);
1729 } varinit_data[] = {
1731 { VSTRFIXED|VTEXTFIXED , defifsvar , NULL },
1733 { VSTRFIXED|VTEXTFIXED|VUNSET, "IFS\0" , NULL },
1736 { VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL\0" , changemail },
1737 { VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH\0", changemail },
1739 { VSTRFIXED|VTEXTFIXED , bb_PATH_root_path, changepath },
1740 { VSTRFIXED|VTEXTFIXED , "PS1=$ " , NULL },
1741 { VSTRFIXED|VTEXTFIXED , "PS2=> " , NULL },
1742 { VSTRFIXED|VTEXTFIXED , "PS4=+ " , NULL },
1743 #if ENABLE_ASH_GETOPTS
1744 { VSTRFIXED|VTEXTFIXED , "OPTIND=1" , getoptsreset },
1746 #if ENABLE_ASH_RANDOM_SUPPORT
1747 { VSTRFIXED|VTEXTFIXED|VUNSET|VDYNAMIC, "RANDOM\0", change_random },
1749 #if ENABLE_LOCALE_SUPPORT
1750 { VSTRFIXED|VTEXTFIXED|VUNSET, "LC_ALL\0" , change_lc_all },
1751 { VSTRFIXED|VTEXTFIXED|VUNSET, "LC_CTYPE\0", change_lc_ctype },
1753 #if ENABLE_FEATURE_EDITING_SAVEHISTORY
1754 { VSTRFIXED|VTEXTFIXED|VUNSET, "HISTFILE\0", NULL },
1759 struct globals_var {
1760 struct shparam shellparam; /* $@ current positional parameters */
1761 struct redirtab *redirlist;
1763 int preverrout_fd; /* save fd2 before print debug if xflag is set. */
1764 struct var *vartab[VTABSIZE];
1765 struct var varinit[ARRAY_SIZE(varinit_data)];
1767 extern struct globals_var *const ash_ptr_to_globals_var;
1768 #define G_var (*ash_ptr_to_globals_var)
1769 #define shellparam (G_var.shellparam )
1770 #define redirlist (G_var.redirlist )
1771 #define g_nullredirs (G_var.g_nullredirs )
1772 #define preverrout_fd (G_var.preverrout_fd)
1773 #define vartab (G_var.vartab )
1774 #define varinit (G_var.varinit )
1775 #define INIT_G_var() do { \
1777 (*(struct globals_var**)&ash_ptr_to_globals_var) = xzalloc(sizeof(G_var)); \
1779 for (i = 0; i < ARRAY_SIZE(varinit_data); i++) { \
1780 varinit[i].flags = varinit_data[i].flags; \
1781 varinit[i].text = varinit_data[i].text; \
1782 varinit[i].func = varinit_data[i].func; \
1786 #define vifs varinit[0]
1788 # define vmail (&vifs)[1]
1789 # define vmpath (&vmail)[1]
1790 # define vpath (&vmpath)[1]
1792 # define vpath (&vifs)[1]
1794 #define vps1 (&vpath)[1]
1795 #define vps2 (&vps1)[1]
1796 #define vps4 (&vps2)[1]
1797 #if ENABLE_ASH_GETOPTS
1798 # define voptind (&vps4)[1]
1799 # if ENABLE_ASH_RANDOM_SUPPORT
1800 # define vrandom (&voptind)[1]
1803 # if ENABLE_ASH_RANDOM_SUPPORT
1804 # define vrandom (&vps4)[1]
1809 * The following macros access the values of the above variables.
1810 * They have to skip over the name. They return the null string
1811 * for unset variables.
1813 #define ifsval() (vifs.text + 4)
1814 #define ifsset() ((vifs.flags & VUNSET) == 0)
1816 # define mailval() (vmail.text + 5)
1817 # define mpathval() (vmpath.text + 9)
1818 # define mpathset() ((vmpath.flags & VUNSET) == 0)
1820 #define pathval() (vpath.text + 5)
1821 #define ps1val() (vps1.text + 4)
1822 #define ps2val() (vps2.text + 4)
1823 #define ps4val() (vps4.text + 4)
1824 #if ENABLE_ASH_GETOPTS
1825 # define optindval() (voptind.text + 7)
1829 #define is_name(c) ((c) == '_' || isalpha((unsigned char)(c)))
1830 #define is_in_name(c) ((c) == '_' || isalnum((unsigned char)(c)))
1832 #if ENABLE_ASH_GETOPTS
1834 getoptsreset(const char *value)
1836 shellparam.optind = number(value);
1837 shellparam.optoff = -1;
1842 * Return of a legal variable name (a letter or underscore followed by zero or
1843 * more letters, underscores, and digits).
1846 endofname(const char *name)
1854 if (!is_in_name(*p))
1861 * Compares two strings up to the first = or '\0'. The first
1862 * string must be terminated by '='; the second may be terminated by
1863 * either '=' or '\0'.
1866 varcmp(const char *p, const char *q)
1870 while ((c = *p) == (d = *q)) {
1885 varequal(const char *a, const char *b)
1887 return !varcmp(a, b);
1891 * Find the appropriate entry in the hash table from the name.
1893 static struct var **
1894 hashvar(const char *p)
1898 hashval = ((unsigned char) *p) << 4;
1899 while (*p && *p != '=')
1900 hashval += (unsigned char) *p++;
1901 return &vartab[hashval % VTABSIZE];
1905 vpcmp(const void *a, const void *b)
1907 return varcmp(*(const char **)a, *(const char **)b);
1911 * This routine initializes the builtin variables.
1921 * PS1 depends on uid
1923 #if ENABLE_FEATURE_EDITING && ENABLE_FEATURE_EDITING_FANCY_PROMPT
1924 vps1.text = "PS1=\\w \\$ ";
1927 vps1.text = "PS1=# ";
1930 end = vp + ARRAY_SIZE(varinit);
1932 vpp = hashvar(vp->text);
1935 } while (++vp < end);
1938 static struct var **
1939 findvar(struct var **vpp, const char *name)
1941 for (; *vpp; vpp = &(*vpp)->next) {
1942 if (varequal((*vpp)->text, name)) {
1950 * Find the value of a variable. Returns NULL if not set.
1953 lookupvar(const char *name)
1957 v = *findvar(hashvar(name), name);
1959 #if ENABLE_ASH_RANDOM_SUPPORT
1961 * Dynamic variables are implemented roughly the same way they are
1962 * in bash. Namely, they're "special" so long as they aren't unset.
1963 * As soon as they're unset, they're no longer dynamic, and dynamic
1964 * lookup will no longer happen at that point. -- PFM.
1966 if ((v->flags & VDYNAMIC))
1969 if (!(v->flags & VUNSET))
1970 return strchrnul(v->text, '=') + 1;
1976 * Search the environment of a builtin command.
1979 bltinlookup(const char *name)
1983 for (sp = cmdenviron; sp; sp = sp->next) {
1984 if (varequal(sp->text, name))
1985 return strchrnul(sp->text, '=') + 1;
1987 return lookupvar(name);
1991 * Same as setvar except that the variable and value are passed in
1992 * the first argument as name=value. Since the first argument will
1993 * be actually stored in the table, it should not be a string that
1995 * Called with interrupts off.
1998 setvareq(char *s, int flags)
2000 struct var *vp, **vpp;
2003 flags |= (VEXPORT & (((unsigned) (1 - aflag)) - 1));
2004 vp = *findvar(vpp, s);
2006 if ((vp->flags & (VREADONLY|VDYNAMIC)) == VREADONLY) {
2009 if (flags & VNOSAVE)
2012 ash_msg_and_raise_error("%.*s: is read only", strchrnul(n, '=') - n, n);
2018 if (vp->func && (flags & VNOFUNC) == 0)
2019 (*vp->func)(strchrnul(s, '=') + 1);
2021 if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
2022 free((char*)vp->text);
2024 flags |= vp->flags & ~(VTEXTFIXED|VSTACK|VNOSAVE|VUNSET);
2029 vp = ckzalloc(sizeof(*vp));
2031 /*vp->func = NULL; - ckzalloc did it */
2034 if (!(flags & (VTEXTFIXED|VSTACK|VNOSAVE)))
2041 * Set the value of a variable. The flags argument is ored with the
2042 * flags of the variable. If val is NULL, the variable is unset.
2045 setvar(const char *name, const char *val, int flags)
2052 q = endofname(name);
2053 p = strchrnul(q, '=');
2055 if (!namelen || p != q)
2056 ash_msg_and_raise_error("%.*s: bad variable name", namelen, name);
2061 vallen = strlen(val);
2064 nameeq = ckmalloc(namelen + vallen + 2);
2065 p = (char *)memcpy(nameeq, name, namelen) + namelen;
2068 p = (char *)memcpy(p, val, vallen) + vallen;
2071 setvareq(nameeq, flags | VNOSAVE);
2075 #if ENABLE_ASH_GETOPTS
2077 * Safe version of setvar, returns 1 on success 0 on failure.
2080 setvarsafe(const char *name, const char *val, int flags)
2083 volatile int saveint;
2084 struct jmploc *volatile savehandler = exception_handler;
2085 struct jmploc jmploc;
2088 if (setjmp(jmploc.loc))
2091 exception_handler = &jmploc;
2092 setvar(name, val, flags);
2095 exception_handler = savehandler;
2096 RESTORE_INT(saveint);
2102 * Unset the specified variable.
2105 unsetvar(const char *s)
2111 vpp = findvar(hashvar(s), s);
2115 int flags = vp->flags;
2118 if (flags & VREADONLY)
2120 #if ENABLE_ASH_RANDOM_SUPPORT
2121 vp->flags &= ~VDYNAMIC;
2125 if ((flags & VSTRFIXED) == 0) {
2127 if ((flags & (VTEXTFIXED|VSTACK)) == 0)
2128 free((char*)vp->text);
2134 vp->flags &= ~VEXPORT;
2144 * Process a linked list of variable assignments.
2147 listsetvar(struct strlist *list_set_var, int flags)
2149 struct strlist *lp = list_set_var;
2155 setvareq(lp->text, flags);
2162 * Generate a list of variables satisfying the given conditions.
2165 listvars(int on, int off, char ***end)
2176 for (vp = *vpp; vp; vp = vp->next) {
2177 if ((vp->flags & mask) == on) {
2178 if (ep == stackstrend())
2179 ep = growstackstr();
2180 *ep++ = (char *) vp->text;
2183 } while (++vpp < vartab + VTABSIZE);
2184 if (ep == stackstrend())
2185 ep = growstackstr();
2189 return grabstackstr(ep);
2193 /* ============ Path search helper
2195 * The variable path (passed by reference) should be set to the start
2196 * of the path before the first call; padvance will update
2197 * this value as it proceeds. Successive calls to padvance will return
2198 * the possible path expansions in sequence. If an option (indicated by
2199 * a percent sign) appears in the path entry then the global variable
2200 * pathopt will be set to point to it; otherwise pathopt will be set to
2203 static const char *pathopt; /* set by padvance */
2206 padvance(const char **path, const char *name)
2216 for (p = start; *p && *p != ':' && *p != '%'; p++)
2218 len = p - start + strlen(name) + 2; /* "2" is for '/' and '\0' */
2219 while (stackblocksize() < len)
2223 memcpy(q, start, p - start);
2231 while (*p && *p != ':')
2238 return stalloc(len);
2242 /* ============ Prompt */
2244 static smallint doprompt; /* if set, prompt the user */
2245 static smallint needprompt; /* true if interactive and at start of line */
2247 #if ENABLE_FEATURE_EDITING
2248 static line_input_t *line_input_state;
2249 static const char *cmdedit_prompt;
2251 putprompt(const char *s)
2253 if (ENABLE_ASH_EXPAND_PRMT) {
2254 free((char*)cmdedit_prompt);
2255 cmdedit_prompt = ckstrdup(s);
2262 putprompt(const char *s)
2268 #if ENABLE_ASH_EXPAND_PRMT
2269 /* expandstr() needs parsing machinery, so it is far away ahead... */
2270 static const char *expandstr(const char *ps);
2272 #define expandstr(s) s
2276 setprompt(int whichprompt)
2279 #if ENABLE_ASH_EXPAND_PRMT
2280 struct stackmark smark;
2285 switch (whichprompt) {
2295 #if ENABLE_ASH_EXPAND_PRMT
2296 setstackmark(&smark);
2297 stalloc(stackblocksize());
2299 putprompt(expandstr(prompt));
2300 #if ENABLE_ASH_EXPAND_PRMT
2301 popstackmark(&smark);
2306 /* ============ The cd and pwd commands */
2308 #define CD_PHYSICAL 1
2311 static int docd(const char *, int);
2320 while ((i = nextopt("LP"))) {
2322 flags ^= CD_PHYSICAL;
2331 * Update curdir (the name of the current directory) in response to a
2335 updatepwd(const char *dir)
2342 cdcomppath = ststrdup(dir);
2345 if (curdir == nullstr)
2347 new = stack_putstr(curdir, new);
2349 new = makestrspace(strlen(dir) + 2, new);
2350 lim = (char *)stackblock() + 1;
2354 if (new > lim && *lim == '/')
2359 if (dir[1] == '/' && dir[2] != '/') {
2365 p = strtok(cdcomppath, "/");
2369 if (p[1] == '.' && p[2] == '\0') {
2381 new = stack_putstr(p, new);
2389 return stackblock();
2393 * Find out what the current directory is. If we already know the current
2394 * directory, this routine returns immediately.
2399 char *dir = getcwd(NULL, 0); /* huh, using glibc extension? */
2400 return dir ? dir : nullstr;
2404 setpwd(const char *val, int setold)
2408 oldcur = dir = curdir;
2411 setvar("OLDPWD", oldcur, VEXPORT);
2414 if (physdir != nullstr) {
2415 if (physdir != oldcur)
2419 if (oldcur == val || !val) {
2425 dir = ckstrdup(val);
2426 if (oldcur != dir && oldcur != nullstr) {
2431 setvar("PWD", dir, VEXPORT);
2434 static void hashcd(void);
2437 * Actually do the chdir. We also call hashcd to let the routines in exec.c
2438 * know that the current directory has changed.
2441 docd(const char *dest, int flags)
2443 const char *dir = 0;
2446 TRACE(("docd(\"%s\", %d) called\n", dest, flags));
2449 if (!(flags & CD_PHYSICAL)) {
2450 dir = updatepwd(dest);
2465 cdcmd(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED)
2477 dest = bltinlookup(homestr);
2478 else if (LONE_DASH(dest)) {
2479 dest = bltinlookup("OLDPWD");
2501 path = bltinlookup("CDPATH");
2510 p = padvance(&path, dest);
2511 if (stat(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) {
2515 if (!docd(p, flags))
2520 ash_msg_and_raise_error("can't cd to %s", dest);
2523 if (flags & CD_PRINT)
2524 out1fmt(snlfmt, curdir);
2529 pwdcmd(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED)
2532 const char *dir = curdir;
2536 if (physdir == nullstr)
2540 out1fmt(snlfmt, dir);
2545 /* ============ ... */
2547 #define IBUFSIZ COMMON_BUFSIZE
2548 #define basebuf bb_common_bufsiz1 /* buffer for top level input file */
2550 /* Syntax classes */
2551 #define CWORD 0 /* character is nothing special */
2552 #define CNL 1 /* newline character */
2553 #define CBACK 2 /* a backslash character */
2554 #define CSQUOTE 3 /* single quote */
2555 #define CDQUOTE 4 /* double quote */
2556 #define CENDQUOTE 5 /* a terminating quote */
2557 #define CBQUOTE 6 /* backwards single quote */
2558 #define CVAR 7 /* a dollar sign */
2559 #define CENDVAR 8 /* a '}' character */
2560 #define CLP 9 /* a left paren in arithmetic */
2561 #define CRP 10 /* a right paren in arithmetic */
2562 #define CENDFILE 11 /* end of file */
2563 #define CCTL 12 /* like CWORD, except it must be escaped */
2564 #define CSPCL 13 /* these terminate a word */
2565 #define CIGN 14 /* character should be ignored */
2567 #if ENABLE_ASH_ALIAS
2571 #define PEOA_OR_PEOF PEOA
2575 #define PEOA_OR_PEOF PEOF
2578 /* number syntax index */
2579 #define BASESYNTAX 0 /* not in quotes */
2580 #define DQSYNTAX 1 /* in double quotes */
2581 #define SQSYNTAX 2 /* in single quotes */
2582 #define ARISYNTAX 3 /* in arithmetic */
2583 #define PSSYNTAX 4 /* prompt */
2585 #if ENABLE_ASH_OPTIMIZE_FOR_SIZE
2586 #define USE_SIT_FUNCTION
2589 #if ENABLE_ASH_MATH_SUPPORT
2590 static const char S_I_T[][4] = {
2591 #if ENABLE_ASH_ALIAS
2592 { CSPCL, CIGN, CIGN, CIGN }, /* 0, PEOA */
2594 { CSPCL, CWORD, CWORD, CWORD }, /* 1, ' ' */
2595 { CNL, CNL, CNL, CNL }, /* 2, \n */
2596 { CWORD, CCTL, CCTL, CWORD }, /* 3, !*-/:=?[]~ */
2597 { CDQUOTE, CENDQUOTE, CWORD, CWORD }, /* 4, '"' */
2598 { CVAR, CVAR, CWORD, CVAR }, /* 5, $ */
2599 { CSQUOTE, CWORD, CENDQUOTE, CWORD }, /* 6, "'" */
2600 { CSPCL, CWORD, CWORD, CLP }, /* 7, ( */
2601 { CSPCL, CWORD, CWORD, CRP }, /* 8, ) */
2602 { CBACK, CBACK, CCTL, CBACK }, /* 9, \ */
2603 { CBQUOTE, CBQUOTE, CWORD, CBQUOTE }, /* 10, ` */
2604 { CENDVAR, CENDVAR, CWORD, CENDVAR }, /* 11, } */
2605 #ifndef USE_SIT_FUNCTION
2606 { CENDFILE, CENDFILE, CENDFILE, CENDFILE }, /* 12, PEOF */
2607 { CWORD, CWORD, CWORD, CWORD }, /* 13, 0-9A-Za-z */
2608 { CCTL, CCTL, CCTL, CCTL } /* 14, CTLESC ... */
2612 static const char S_I_T[][3] = {
2613 #if ENABLE_ASH_ALIAS
2614 { CSPCL, CIGN, CIGN }, /* 0, PEOA */
2616 { CSPCL, CWORD, CWORD }, /* 1, ' ' */
2617 { CNL, CNL, CNL }, /* 2, \n */
2618 { CWORD, CCTL, CCTL }, /* 3, !*-/:=?[]~ */
2619 { CDQUOTE, CENDQUOTE, CWORD }, /* 4, '"' */
2620 { CVAR, CVAR, CWORD }, /* 5, $ */
2621 { CSQUOTE, CWORD, CENDQUOTE }, /* 6, "'" */
2622 { CSPCL, CWORD, CWORD }, /* 7, ( */
2623 { CSPCL, CWORD, CWORD }, /* 8, ) */
2624 { CBACK, CBACK, CCTL }, /* 9, \ */
2625 { CBQUOTE, CBQUOTE, CWORD }, /* 10, ` */
2626 { CENDVAR, CENDVAR, CWORD }, /* 11, } */
2627 #ifndef USE_SIT_FUNCTION
2628 { CENDFILE, CENDFILE, CENDFILE }, /* 12, PEOF */
2629 { CWORD, CWORD, CWORD }, /* 13, 0-9A-Za-z */
2630 { CCTL, CCTL, CCTL } /* 14, CTLESC ... */
2633 #endif /* ASH_MATH_SUPPORT */
2635 #ifdef USE_SIT_FUNCTION
2638 SIT(int c, int syntax)
2640 static const char spec_symbls[] ALIGN1 = "\t\n !\"$&'()*-/:;<=>?[\\]`|}~";
2641 #if ENABLE_ASH_ALIAS
2642 static const char syntax_index_table[] ALIGN1 = {
2643 1, 2, 1, 3, 4, 5, 1, 6, /* "\t\n !\"$&'" */
2644 7, 8, 3, 3, 3, 3, 1, 1, /* "()*-/:;<" */
2645 3, 1, 3, 3, 9, 3, 10, 1, /* "=>?[\\]`|" */
2649 static const char syntax_index_table[] ALIGN1 = {
2650 0, 1, 0, 2, 3, 4, 0, 5, /* "\t\n !\"$&'" */
2651 6, 7, 2, 2, 2, 2, 0, 0, /* "()*-/:;<" */
2652 2, 0, 2, 2, 8, 2, 9, 0, /* "=>?[\\]`|" */
2659 if (c == PEOF) /* 2^8+2 */
2661 #if ENABLE_ASH_ALIAS
2662 if (c == PEOA) /* 2^8+1 */
2666 #define U_C(c) ((unsigned char)(c))
2668 if ((unsigned char)c >= (unsigned char)(CTLESC)
2669 && (unsigned char)c <= (unsigned char)(CTLQUOTEMARK)
2673 s = strchrnul(spec_symbls, c);
2676 indx = syntax_index_table[s - spec_symbls];
2678 return S_I_T[indx][syntax];
2681 #else /* !USE_SIT_FUNCTION */
2683 #if ENABLE_ASH_ALIAS
2684 #define CSPCL_CIGN_CIGN_CIGN 0
2685 #define CSPCL_CWORD_CWORD_CWORD 1
2686 #define CNL_CNL_CNL_CNL 2
2687 #define CWORD_CCTL_CCTL_CWORD 3
2688 #define CDQUOTE_CENDQUOTE_CWORD_CWORD 4
2689 #define CVAR_CVAR_CWORD_CVAR 5
2690 #define CSQUOTE_CWORD_CENDQUOTE_CWORD 6
2691 #define CSPCL_CWORD_CWORD_CLP 7
2692 #define CSPCL_CWORD_CWORD_CRP 8
2693 #define CBACK_CBACK_CCTL_CBACK 9
2694 #define CBQUOTE_CBQUOTE_CWORD_CBQUOTE 10
2695 #define CENDVAR_CENDVAR_CWORD_CENDVAR 11
2696 #define CENDFILE_CENDFILE_CENDFILE_CENDFILE 12
2697 #define CWORD_CWORD_CWORD_CWORD 13
2698 #define CCTL_CCTL_CCTL_CCTL 14
2700 #define CSPCL_CWORD_CWORD_CWORD 0
2701 #define CNL_CNL_CNL_CNL 1
2702 #define CWORD_CCTL_CCTL_CWORD 2
2703 #define CDQUOTE_CENDQUOTE_CWORD_CWORD 3
2704 #define CVAR_CVAR_CWORD_CVAR 4
2705 #define CSQUOTE_CWORD_CENDQUOTE_CWORD 5
2706 #define CSPCL_CWORD_CWORD_CLP 6
2707 #define CSPCL_CWORD_CWORD_CRP 7
2708 #define CBACK_CBACK_CCTL_CBACK 8
2709 #define CBQUOTE_CBQUOTE_CWORD_CBQUOTE 9
2710 #define CENDVAR_CENDVAR_CWORD_CENDVAR 10
2711 #define CENDFILE_CENDFILE_CENDFILE_CENDFILE 11
2712 #define CWORD_CWORD_CWORD_CWORD 12
2713 #define CCTL_CCTL_CCTL_CCTL 13
2716 static const char syntax_index_table[258] = {
2717 /* BASESYNTAX_DQSYNTAX_SQSYNTAX_ARISYNTAX */
2718 /* 0 PEOF */ CENDFILE_CENDFILE_CENDFILE_CENDFILE,
2719 #if ENABLE_ASH_ALIAS
2720 /* 1 PEOA */ CSPCL_CIGN_CIGN_CIGN,
2722 /* 2 -128 0x80 */ CWORD_CWORD_CWORD_CWORD,
2723 /* 3 -127 CTLESC */ CCTL_CCTL_CCTL_CCTL,
2724 /* 4 -126 CTLVAR */ CCTL_CCTL_CCTL_CCTL,
2725 /* 5 -125 CTLENDVAR */ CCTL_CCTL_CCTL_CCTL,
2726 /* 6 -124 CTLBACKQ */ CCTL_CCTL_CCTL_CCTL,
2727 /* 7 -123 CTLQUOTE */ CCTL_CCTL_CCTL_CCTL,
2728 /* 8 -122 CTLARI */ CCTL_CCTL_CCTL_CCTL,
2729 /* 9 -121 CTLENDARI */ CCTL_CCTL_CCTL_CCTL,
2730 /* 10 -120 CTLQUOTEMARK */ CCTL_CCTL_CCTL_CCTL,
2731 /* 11 -119 */ CWORD_CWORD_CWORD_CWORD,
2732 /* 12 -118 */ CWORD_CWORD_CWORD_CWORD,
2733 /* 13 -117 */ CWORD_CWORD_CWORD_CWORD,
2734 /* 14 -116 */ CWORD_CWORD_CWORD_CWORD,
2735 /* 15 -115 */ CWORD_CWORD_CWORD_CWORD,
2736 /* 16 -114 */ CWORD_CWORD_CWORD_CWORD,
2737 /* 17 -113 */ CWORD_CWORD_CWORD_CWORD,
2738 /* 18 -112 */ CWORD_CWORD_CWORD_CWORD,
2739 /* 19 -111 */ CWORD_CWORD_CWORD_CWORD,
2740 /* 20 -110 */ CWORD_CWORD_CWORD_CWORD,
2741 /* 21 -109 */ CWORD_CWORD_CWORD_CWORD,
2742 /* 22 -108 */ CWORD_CWORD_CWORD_CWORD,
2743 /* 23 -107 */ CWORD_CWORD_CWORD_CWORD,
2744 /* 24 -106 */ CWORD_CWORD_CWORD_CWORD,
2745 /* 25 -105 */ CWORD_CWORD_CWORD_CWORD,
2746 /* 26 -104 */ CWORD_CWORD_CWORD_CWORD,
2747 /* 27 -103 */ CWORD_CWORD_CWORD_CWORD,
2748 /* 28 -102 */ CWORD_CWORD_CWORD_CWORD,
2749 /* 29 -101 */ CWORD_CWORD_CWORD_CWORD,
2750 /* 30 -100 */ CWORD_CWORD_CWORD_CWORD,
2751 /* 31 -99 */ CWORD_CWORD_CWORD_CWORD,
2752 /* 32 -98 */ CWORD_CWORD_CWORD_CWORD,
2753 /* 33 -97 */ CWORD_CWORD_CWORD_CWORD,
2754 /* 34 -96 */ CWORD_CWORD_CWORD_CWORD,
2755 /* 35 -95 */ CWORD_CWORD_CWORD_CWORD,
2756 /* 36 -94 */ CWORD_CWORD_CWORD_CWORD,
2757 /* 37 -93 */ CWORD_CWORD_CWORD_CWORD,
2758 /* 38 -92 */ CWORD_CWORD_CWORD_CWORD,
2759 /* 39 -91 */ CWORD_CWORD_CWORD_CWORD,
2760 /* 40 -90 */ CWORD_CWORD_CWORD_CWORD,
2761 /* 41 -89 */ CWORD_CWORD_CWORD_CWORD,
2762 /* 42 -88 */ CWORD_CWORD_CWORD_CWORD,
2763 /* 43 -87 */ CWORD_CWORD_CWORD_CWORD,
2764 /* 44 -86 */ CWORD_CWORD_CWORD_CWORD,
2765 /* 45 -85 */ CWORD_CWORD_CWORD_CWORD,
2766 /* 46 -84 */ CWORD_CWORD_CWORD_CWORD,
2767 /* 47 -83 */ CWORD_CWORD_CWORD_CWORD,
2768 /* 48 -82 */ CWORD_CWORD_CWORD_CWORD,
2769 /* 49 -81 */ CWORD_CWORD_CWORD_CWORD,
2770 /* 50 -80 */ CWORD_CWORD_CWORD_CWORD,
2771 /* 51 -79 */ CWORD_CWORD_CWORD_CWORD,
2772 /* 52 -78 */ CWORD_CWORD_CWORD_CWORD,
2773 /* 53 -77 */ CWORD_CWORD_CWORD_CWORD,
2774 /* 54 -76 */ CWORD_CWORD_CWORD_CWORD,
2775 /* 55 -75 */ CWORD_CWORD_CWORD_CWORD,
2776 /* 56 -74 */ CWORD_CWORD_CWORD_CWORD,
2777 /* 57 -73 */ CWORD_CWORD_CWORD_CWORD,
2778 /* 58 -72 */ CWORD_CWORD_CWORD_CWORD,
2779 /* 59 -71 */ CWORD_CWORD_CWORD_CWORD,
2780 /* 60 -70 */ CWORD_CWORD_CWORD_CWORD,
2781 /* 61 -69 */ CWORD_CWORD_CWORD_CWORD,
2782 /* 62 -68 */ CWORD_CWORD_CWORD_CWORD,
2783 /* 63 -67 */ CWORD_CWORD_CWORD_CWORD,
2784 /* 64 -66 */ CWORD_CWORD_CWORD_CWORD,
2785 /* 65 -65 */ CWORD_CWORD_CWORD_CWORD,
2786 /* 66 -64 */ CWORD_CWORD_CWORD_CWORD,
2787 /* 67 -63 */ CWORD_CWORD_CWORD_CWORD,
2788 /* 68 -62 */ CWORD_CWORD_CWORD_CWORD,
2789 /* 69 -61 */ CWORD_CWORD_CWORD_CWORD,
2790 /* 70 -60 */ CWORD_CWORD_CWORD_CWORD,
2791 /* 71 -59 */ CWORD_CWORD_CWORD_CWORD,
2792 /* 72 -58 */ CWORD_CWORD_CWORD_CWORD,
2793 /* 73 -57 */ CWORD_CWORD_CWORD_CWORD,
2794 /* 74 -56 */ CWORD_CWORD_CWORD_CWORD,
2795 /* 75 -55 */ CWORD_CWORD_CWORD_CWORD,
2796 /* 76 -54 */ CWORD_CWORD_CWORD_CWORD,
2797 /* 77 -53 */ CWORD_CWORD_CWORD_CWORD,
2798 /* 78 -52 */ CWORD_CWORD_CWORD_CWORD,
2799 /* 79 -51 */ CWORD_CWORD_CWORD_CWORD,
2800 /* 80 -50 */ CWORD_CWORD_CWORD_CWORD,
2801 /* 81 -49 */ CWORD_CWORD_CWORD_CWORD,
2802 /* 82 -48 */ CWORD_CWORD_CWORD_CWORD,
2803 /* 83 -47 */ CWORD_CWORD_CWORD_CWORD,
2804 /* 84 -46 */ CWORD_CWORD_CWORD_CWORD,
2805 /* 85 -45 */ CWORD_CWORD_CWORD_CWORD,
2806 /* 86 -44 */ CWORD_CWORD_CWORD_CWORD,
2807 /* 87 -43 */ CWORD_CWORD_CWORD_CWORD,
2808 /* 88 -42 */ CWORD_CWORD_CWORD_CWORD,
2809 /* 89 -41 */ CWORD_CWORD_CWORD_CWORD,
2810 /* 90 -40 */ CWORD_CWORD_CWORD_CWORD,
2811 /* 91 -39 */ CWORD_CWORD_CWORD_CWORD,
2812 /* 92 -38 */ CWORD_CWORD_CWORD_CWORD,
2813 /* 93 -37 */ CWORD_CWORD_CWORD_CWORD,
2814 /* 94 -36 */ CWORD_CWORD_CWORD_CWORD,
2815 /* 95 -35 */ CWORD_CWORD_CWORD_CWORD,
2816 /* 96 -34 */ CWORD_CWORD_CWORD_CWORD,
2817 /* 97 -33 */ CWORD_CWORD_CWORD_CWORD,
2818 /* 98 -32 */ CWORD_CWORD_CWORD_CWORD,
2819 /* 99 -31 */ CWORD_CWORD_CWORD_CWORD,
2820 /* 100 -30 */ CWORD_CWORD_CWORD_CWORD,
2821 /* 101 -29 */ CWORD_CWORD_CWORD_CWORD,
2822 /* 102 -28 */ CWORD_CWORD_CWORD_CWORD,
2823 /* 103 -27 */ CWORD_CWORD_CWORD_CWORD,
2824 /* 104 -26 */ CWORD_CWORD_CWORD_CWORD,
2825 /* 105 -25 */ CWORD_CWORD_CWORD_CWORD,
2826 /* 106 -24 */ CWORD_CWORD_CWORD_CWORD,
2827 /* 107 -23 */ CWORD_CWORD_CWORD_CWORD,
2828 /* 108 -22 */ CWORD_CWORD_CWORD_CWORD,
2829 /* 109 -21 */ CWORD_CWORD_CWORD_CWORD,
2830 /* 110 -20 */ CWORD_CWORD_CWORD_CWORD,
2831 /* 111 -19 */ CWORD_CWORD_CWORD_CWORD,
2832 /* 112 -18 */ CWORD_CWORD_CWORD_CWORD,
2833 /* 113 -17 */ CWORD_CWORD_CWORD_CWORD,
2834 /* 114 -16 */ CWORD_CWORD_CWORD_CWORD,
2835 /* 115 -15 */ CWORD_CWORD_CWORD_CWORD,
2836 /* 116 -14 */ CWORD_CWORD_CWORD_CWORD,
2837 /* 117 -13 */ CWORD_CWORD_CWORD_CWORD,
2838 /* 118 -12 */ CWORD_CWORD_CWORD_CWORD,
2839 /* 119 -11 */ CWORD_CWORD_CWORD_CWORD,
2840 /* 120 -10 */ CWORD_CWORD_CWORD_CWORD,
2841 /* 121 -9 */ CWORD_CWORD_CWORD_CWORD,
2842 /* 122 -8 */ CWORD_CWORD_CWORD_CWORD,
2843 /* 123 -7 */ CWORD_CWORD_CWORD_CWORD,
2844 /* 124 -6 */ CWORD_CWORD_CWORD_CWORD,
2845 /* 125 -5 */ CWORD_CWORD_CWORD_CWORD,
2846 /* 126 -4 */ CWORD_CWORD_CWORD_CWORD,
2847 /* 127 -3 */ CWORD_CWORD_CWORD_CWORD,
2848 /* 128 -2 */ CWORD_CWORD_CWORD_CWORD,
2849 /* 129 -1 */ CWORD_CWORD_CWORD_CWORD,
2850 /* 130 0 */ CWORD_CWORD_CWORD_CWORD,
2851 /* 131 1 */ CWORD_CWORD_CWORD_CWORD,
2852 /* 132 2 */ CWORD_CWORD_CWORD_CWORD,
2853 /* 133 3 */ CWORD_CWORD_CWORD_CWORD,
2854 /* 134 4 */ CWORD_CWORD_CWORD_CWORD,
2855 /* 135 5 */ CWORD_CWORD_CWORD_CWORD,
2856 /* 136 6 */ CWORD_CWORD_CWORD_CWORD,
2857 /* 137 7 */ CWORD_CWORD_CWORD_CWORD,
2858 /* 138 8 */ CWORD_CWORD_CWORD_CWORD,
2859 /* 139 9 "\t" */ CSPCL_CWORD_CWORD_CWORD,
2860 /* 140 10 "\n" */ CNL_CNL_CNL_CNL,
2861 /* 141 11 */ CWORD_CWORD_CWORD_CWORD,
2862 /* 142 12 */ CWORD_CWORD_CWORD_CWORD,
2863 /* 143 13 */ CWORD_CWORD_CWORD_CWORD,
2864 /* 144 14 */ CWORD_CWORD_CWORD_CWORD,
2865 /* 145 15 */ CWORD_CWORD_CWORD_CWORD,
2866 /* 146 16 */ CWORD_CWORD_CWORD_CWORD,
2867 /* 147 17 */ CWORD_CWORD_CWORD_CWORD,
2868 /* 148 18 */ CWORD_CWORD_CWORD_CWORD,
2869 /* 149 19 */ CWORD_CWORD_CWORD_CWORD,
2870 /* 150 20 */ CWORD_CWORD_CWORD_CWORD,
2871 /* 151 21 */ CWORD_CWORD_CWORD_CWORD,
2872 /* 152 22 */ CWORD_CWORD_CWORD_CWORD,
2873 /* 153 23 */ CWORD_CWORD_CWORD_CWORD,
2874 /* 154 24 */ CWORD_CWORD_CWORD_CWORD,
2875 /* 155 25 */ CWORD_CWORD_CWORD_CWORD,
2876 /* 156 26 */ CWORD_CWORD_CWORD_CWORD,
2877 /* 157 27 */ CWORD_CWORD_CWORD_CWORD,
2878 /* 158 28 */ CWORD_CWORD_CWORD_CWORD,
2879 /* 159 29 */ CWORD_CWORD_CWORD_CWORD,
2880 /* 160 30 */ CWORD_CWORD_CWORD_CWORD,
2881 /* 161 31 */ CWORD_CWORD_CWORD_CWORD,
2882 /* 162 32 " " */ CSPCL_CWORD_CWORD_CWORD,
2883 /* 163 33 "!" */ CWORD_CCTL_CCTL_CWORD,
2884 /* 164 34 """ */ CDQUOTE_CENDQUOTE_CWORD_CWORD,
2885 /* 165 35 "#" */ CWORD_CWORD_CWORD_CWORD,
2886 /* 166 36 "$" */ CVAR_CVAR_CWORD_CVAR,
2887 /* 167 37 "%" */ CWORD_CWORD_CWORD_CWORD,
2888 /* 168 38 "&" */ CSPCL_CWORD_CWORD_CWORD,
2889 /* 169 39 "'" */ CSQUOTE_CWORD_CENDQUOTE_CWORD,
2890 /* 170 40 "(" */ CSPCL_CWORD_CWORD_CLP,
2891 /* 171 41 ")" */ CSPCL_CWORD_CWORD_CRP,
2892 /* 172 42 "*" */ CWORD_CCTL_CCTL_CWORD,
2893 /* 173 43 "+" */ CWORD_CWORD_CWORD_CWORD,
2894 /* 174 44 "," */ CWORD_CWORD_CWORD_CWORD,
2895 /* 175 45 "-" */ CWORD_CCTL_CCTL_CWORD,
2896 /* 176 46 "." */ CWORD_CWORD_CWORD_CWORD,
2897 /* 177 47 "/" */ CWORD_CCTL_CCTL_CWORD,
2898 /* 178 48 "0" */ CWORD_CWORD_CWORD_CWORD,
2899 /* 179 49 "1" */ CWORD_CWORD_CWORD_CWORD,
2900 /* 180 50 "2" */ CWORD_CWORD_CWORD_CWORD,
2901 /* 181 51 "3" */ CWORD_CWORD_CWORD_CWORD,
2902 /* 182 52 "4" */ CWORD_CWORD_CWORD_CWORD,
2903 /* 183 53 "5" */ CWORD_CWORD_CWORD_CWORD,
2904 /* 184 54 "6" */ CWORD_CWORD_CWORD_CWORD,
2905 /* 185 55 "7" */ CWORD_CWORD_CWORD_CWORD,
2906 /* 186 56 "8" */ CWORD_CWORD_CWORD_CWORD,
2907 /* 187 57 "9" */ CWORD_CWORD_CWORD_CWORD,
2908 /* 188 58 ":" */ CWORD_CCTL_CCTL_CWORD,
2909 /* 189 59 ";" */ CSPCL_CWORD_CWORD_CWORD,
2910 /* 190 60 "<" */ CSPCL_CWORD_CWORD_CWORD,
2911 /* 191 61 "=" */ CWORD_CCTL_CCTL_CWORD,
2912 /* 192 62 ">" */ CSPCL_CWORD_CWORD_CWORD,
2913 /* 193 63 "?" */ CWORD_CCTL_CCTL_CWORD,
2914 /* 194 64 "@" */ CWORD_CWORD_CWORD_CWORD,
2915 /* 195 65 "A" */ CWORD_CWORD_CWORD_CWORD,
2916 /* 196 66 "B" */ CWORD_CWORD_CWORD_CWORD,
2917 /* 197 67 "C" */ CWORD_CWORD_CWORD_CWORD,
2918 /* 198 68 "D" */ CWORD_CWORD_CWORD_CWORD,
2919 /* 199 69 "E" */ CWORD_CWORD_CWORD_CWORD,
2920 /* 200 70 "F" */ CWORD_CWORD_CWORD_CWORD,
2921 /* 201 71 "G" */ CWORD_CWORD_CWORD_CWORD,
2922 /* 202 72 "H" */ CWORD_CWORD_CWORD_CWORD,
2923 /* 203 73 "I" */ CWORD_CWORD_CWORD_CWORD,
2924 /* 204 74 "J" */ CWORD_CWORD_CWORD_CWORD,
2925 /* 205 75 "K" */ CWORD_CWORD_CWORD_CWORD,
2926 /* 206 76 "L" */ CWORD_CWORD_CWORD_CWORD,
2927 /* 207 77 "M" */ CWORD_CWORD_CWORD_CWORD,
2928 /* 208 78 "N" */ CWORD_CWORD_CWORD_CWORD,
2929 /* 209 79 "O" */ CWORD_CWORD_CWORD_CWORD,
2930 /* 210 80 "P" */ CWORD_CWORD_CWORD_CWORD,
2931 /* 211 81 "Q" */ CWORD_CWORD_CWORD_CWORD,
2932 /* 212 82 "R" */ CWORD_CWORD_CWORD_CWORD,
2933 /* 213 83 "S" */ CWORD_CWORD_CWORD_CWORD,
2934 /* 214 84 "T" */ CWORD_CWORD_CWORD_CWORD,
2935 /* 215 85 "U" */ CWORD_CWORD_CWORD_CWORD,
2936 /* 216 86 "V" */ CWORD_CWORD_CWORD_CWORD,
2937 /* 217 87 "W" */ CWORD_CWORD_CWORD_CWORD,
2938 /* 218 88 "X" */ CWORD_CWORD_CWORD_CWORD,
2939 /* 219 89 "Y" */ CWORD_CWORD_CWORD_CWORD,
2940 /* 220 90 "Z" */ CWORD_CWORD_CWORD_CWORD,
2941 /* 221 91 "[" */ CWORD_CCTL_CCTL_CWORD,
2942 /* 222 92 "\" */ CBACK_CBACK_CCTL_CBACK,
2943 /* 223 93 "]" */ CWORD_CCTL_CCTL_CWORD,
2944 /* 224 94 "^" */ CWORD_CWORD_CWORD_CWORD,
2945 /* 225 95 "_" */ CWORD_CWORD_CWORD_CWORD,
2946 /* 226 96 "`" */ CBQUOTE_CBQUOTE_CWORD_CBQUOTE,
2947 /* 227 97 "a" */ CWORD_CWORD_CWORD_CWORD,
2948 /* 228 98 "b" */ CWORD_CWORD_CWORD_CWORD,
2949 /* 229 99 "c" */ CWORD_CWORD_CWORD_CWORD,
2950 /* 230 100 "d" */ CWORD_CWORD_CWORD_CWORD,
2951 /* 231 101 "e" */ CWORD_CWORD_CWORD_CWORD,
2952 /* 232 102 "f" */ CWORD_CWORD_CWORD_CWORD,
2953 /* 233 103 "g" */ CWORD_CWORD_CWORD_CWORD,
2954 /* 234 104 "h" */ CWORD_CWORD_CWORD_CWORD,
2955 /* 235 105 "i" */ CWORD_CWORD_CWORD_CWORD,
2956 /* 236 106 "j" */ CWORD_CWORD_CWORD_CWORD,
2957 /* 237 107 "k" */ CWORD_CWORD_CWORD_CWORD,
2958 /* 238 108 "l" */ CWORD_CWORD_CWORD_CWORD,
2959 /* 239 109 "m" */ CWORD_CWORD_CWORD_CWORD,
2960 /* 240 110 "n" */ CWORD_CWORD_CWORD_CWORD,
2961 /* 241 111 "o" */ CWORD_CWORD_CWORD_CWORD,
2962 /* 242 112 "p" */ CWORD_CWORD_CWORD_CWORD,
2963 /* 243 113 "q" */ CWORD_CWORD_CWORD_CWORD,
2964 /* 244 114 "r" */ CWORD_CWORD_CWORD_CWORD,
2965 /* 245 115 "s" */ CWORD_CWORD_CWORD_CWORD,
2966 /* 246 116 "t" */ CWORD_CWORD_CWORD_CWORD,
2967 /* 247 117 "u" */ CWORD_CWORD_CWORD_CWORD,
2968 /* 248 118 "v" */ CWORD_CWORD_CWORD_CWORD,
2969 /* 249 119 "w" */ CWORD_CWORD_CWORD_CWORD,
2970 /* 250 120 "x" */ CWORD_CWORD_CWORD_CWORD,
2971 /* 251 121 "y" */ CWORD_CWORD_CWORD_CWORD,
2972 /* 252 122 "z" */ CWORD_CWORD_CWORD_CWORD,
2973 /* 253 123 "{" */ CWORD_CWORD_CWORD_CWORD,
2974 /* 254 124 "|" */ CSPCL_CWORD_CWORD_CWORD,
2975 /* 255 125 "}" */ CENDVAR_CENDVAR_CWORD_CENDVAR,
2976 /* 256 126 "~" */ CWORD_CCTL_CCTL_CWORD,
2977 /* 257 127 */ CWORD_CWORD_CWORD_CWORD,
2980 #define SIT(c, syntax) (S_I_T[(int)syntax_index_table[((int)c)+SYNBASE]][syntax])
2982 #endif /* USE_SIT_FUNCTION */
2985 /* ============ Alias handling */
2987 #if ENABLE_ASH_ALIAS
2989 #define ALIASINUSE 1
3000 static struct alias **atab; // [ATABSIZE];
3001 #define INIT_G_alias() do { \
3002 atab = xzalloc(ATABSIZE * sizeof(atab[0])); \
3006 static struct alias **
3007 __lookupalias(const char *name) {
3008 unsigned int hashval;
3015 ch = (unsigned char)*p;
3019 ch = (unsigned char)*++p;
3021 app = &atab[hashval % ATABSIZE];
3023 for (; *app; app = &(*app)->next) {
3024 if (strcmp(name, (*app)->name) == 0) {
3032 static struct alias *
3033 lookupalias(const char *name, int check)
3035 struct alias *ap = *__lookupalias(name);
3037 if (check && ap && (ap->flag & ALIASINUSE))
3042 static struct alias *
3043 freealias(struct alias *ap)
3047 if (ap->flag & ALIASINUSE) {
3048 ap->flag |= ALIASDEAD;
3060 setalias(const char *name, const char *val)
3062 struct alias *ap, **app;
3064 app = __lookupalias(name);
3068 if (!(ap->flag & ALIASINUSE)) {
3071 ap->val = ckstrdup(val);
3072 ap->flag &= ~ALIASDEAD;
3075 ap = ckzalloc(sizeof(struct alias));
3076 ap->name = ckstrdup(name);
3077 ap->val = ckstrdup(val);
3078 /*ap->flag = 0; - ckzalloc did it */
3079 /*ap->next = NULL;*/
3086 unalias(const char *name)
3090 app = __lookupalias(name);
3094 *app = freealias(*app);
3105 struct alias *ap, **app;
3109 for (i = 0; i < ATABSIZE; i++) {
3111 for (ap = *app; ap; ap = *app) {
3112 *app = freealias(*app);
3122 printalias(const struct alias *ap)
3124 out1fmt("%s=%s\n", ap->name, single_quote(ap->val));
3128 * TODO - sort output
3131 aliascmd(int argc ATTRIBUTE_UNUSED, char **argv)
3140 for (i = 0; i < ATABSIZE; i++) {
3141 for (ap = atab[i]; ap; ap = ap->next) {
3147 while ((n = *++argv) != NULL) {
3148 v = strchr(n+1, '=');
3149 if (v == NULL) { /* n+1: funny ksh stuff */
3150 ap = *__lookupalias(n);
3152 fprintf(stderr, "%s: %s not found\n", "alias", n);
3166 unaliascmd(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED)
3170 while ((i = nextopt("a")) != '\0') {
3176 for (i = 0; *argptr; argptr++) {
3177 if (unalias(*argptr)) {
3178 fprintf(stderr, "%s: %s not found\n", "unalias", *argptr);
3186 #endif /* ASH_ALIAS */
3189 /* ============ jobs.c */
3191 /* Mode argument to forkshell. Don't change FORK_FG or FORK_BG. */
3194 #define FORK_NOJOB 2
3196 /* mode flags for showjob(s) */
3197 #define SHOW_PGID 0x01 /* only show pgid - for jobs -p */
3198 #define SHOW_PID 0x04 /* include process pid */
3199 #define SHOW_CHANGED 0x08 /* only jobs whose state has changed */
3202 * A job structure contains information about a job. A job is either a
3203 * single process or a set of processes contained in a pipeline. In the
3204 * latter case, pidlist will be non-NULL, and will point to a -1 terminated
3209 pid_t pid; /* process id */
3210 int status; /* last process status from wait() */
3211 char *cmd; /* text of command being run */
3215 struct procstat ps0; /* status of process */
3216 struct procstat *ps; /* status or processes when more than one */
3218 int stopstatus; /* status of a stopped job */
3221 nprocs: 16, /* number of processes */
3223 #define JOBRUNNING 0 /* at least one proc running */
3224 #define JOBSTOPPED 1 /* all procs are stopped */
3225 #define JOBDONE 2 /* all procs are completed */
3227 sigint: 1, /* job was killed by SIGINT */
3228 jobctl: 1, /* job running under job control */
3230 waited: 1, /* true if this entry has been waited for */
3231 used: 1, /* true if this entry is in used */
3232 changed: 1; /* true if status has changed */
3233 struct job *prev_job; /* previous job */
3236 static struct job *makejob(/*union node *,*/ int);
3238 #define forkshell(job, node, mode) forkshell(job, mode)
3240 static int forkshell(struct job *, union node *, int);
3241 static int waitforjob(struct job *);
3244 enum { doing_jobctl = 0 };
3245 #define setjobctl(on) do {} while (0)
3247 static smallint doing_jobctl; //references:8
3248 static void setjobctl(int);
3252 * Set the signal handler for the specified signal. The routine figures
3253 * out what it should be set to.
3256 setsignal(int signo)
3260 struct sigaction act;
3266 else if (*t != '\0')
3268 if (rootshell && action == S_DFL) {
3271 if (iflag || minusc || sflag == 0)
3294 t = &sigmode[signo - 1];
3298 * current setting unknown
3300 if (sigaction(signo, NULL, &act) == -1) {
3302 * Pretend it worked; maybe we should give a warning
3303 * here, but other shells don't. We don't alter
3304 * sigmode, so that we retry every time.
3308 tsig = S_RESET; /* force to be set */
3309 if (act.sa_handler == SIG_IGN) {
3312 && (signo == SIGTSTP || signo == SIGTTIN || signo == SIGTTOU)
3314 tsig = S_IGN; /* don't hard ignore these */
3318 if (tsig == S_HARD_IGN || tsig == action)
3320 act.sa_handler = SIG_DFL;
3323 act.sa_handler = onsig;
3326 act.sa_handler = SIG_IGN;
3331 sigfillset(&act.sa_mask);
3332 sigaction_set(signo, &act);
3335 /* mode flags for set_curjob */
3336 #define CUR_DELETE 2
3337 #define CUR_RUNNING 1
3338 #define CUR_STOPPED 0
3340 /* mode flags for dowait */
3341 #define DOWAIT_NONBLOCK WNOHANG
3342 #define DOWAIT_BLOCK 0
3345 /* pgrp of shell on invocation */
3346 static int initialpgrp; //references:2
3347 static int ttyfd = -1; //5
3350 static struct job *jobtab; //5
3352 static unsigned njobs; //4
3354 static struct job *curjob; //lots
3355 /* number of presumed living untracked jobs */
3356 static int jobless; //4
3359 set_curjob(struct job *jp, unsigned mode)
3362 struct job **jpp, **curp;
3364 /* first remove from list */
3365 jpp = curp = &curjob;
3370 jpp = &jp1->prev_job;
3372 *jpp = jp1->prev_job;
3374 /* Then re-insert in correct position */
3382 /* job being deleted */
3385 /* newly created job or backgrounded job,
3386 put after all stopped jobs. */
3390 if (!jp1 || jp1->state != JOBSTOPPED)
3393 jpp = &jp1->prev_job;
3399 /* newly stopped job - becomes curjob */
3400 jp->prev_job = *jpp;
3408 jobno(const struct job *jp)
3410 return jp - jobtab + 1;
3415 * Convert a job name to a job structure.
3418 #define getjob(name, getctl) getjob(name)
3421 getjob(const char *name, int getctl)
3425 const char *err_msg = "No such job: %s";
3429 char *(*match)(const char *, const char *);
3444 if (c == '+' || c == '%') {
3446 err_msg = "No current job";
3452 err_msg = "No previous job";
3461 // TODO: number() instead? It does error checking...
3464 jp = jobtab + num - 1;
3481 if (match(jp->ps[0].cmd, p)) {
3485 err_msg = "%s: ambiguous";
3492 err_msg = "job %s not created under job control";
3493 if (getctl && jp->jobctl == 0)
3498 ash_msg_and_raise_error(err_msg, name);
3502 * Mark a job structure as unused.
3505 freejob(struct job *jp)
3507 struct procstat *ps;
3511 for (i = jp->nprocs, ps = jp->ps; --i >= 0; ps++) {
3512 if (ps->cmd != nullstr)
3515 if (jp->ps != &jp->ps0)
3518 set_curjob(jp, CUR_DELETE);
3524 xtcsetpgrp(int fd, pid_t pgrp)
3526 if (tcsetpgrp(fd, pgrp))
3527 ash_msg_and_raise_error("cannot set tty process group (%m)");
3531 * Turn job control on and off.
3533 * Note: This code assumes that the third arg to ioctl is a character
3534 * pointer, which is true on Berkeley systems but not System V. Since
3535 * System V doesn't have job control yet, this isn't a problem now.
3537 * Called with interrupts off.
3545 if (on == doing_jobctl || rootshell == 0)
3549 ofd = fd = open(_PATH_TTY, O_RDWR);
3551 /* BTW, bash will try to open(ttyname(0)) if open("/dev/tty") fails.
3552 * That sometimes helps to acquire controlling tty.
3553 * Obviously, a workaround for bugs when someone
3554 * failed to provide a controlling tty to bash! :) */
3560 fd = fcntl(fd, F_DUPFD, 10);
3565 /* fd is a tty at this point */
3566 close_on_exec_on(fd);
3567 do { /* while we are in the background */
3568 pgrp = tcgetpgrp(fd);
3571 ash_msg("can't access tty; job control turned off");
3575 if (pgrp == getpgrp())
3586 xtcsetpgrp(fd, pgrp);
3588 /* turning job control off */
3591 /* was xtcsetpgrp, but this can make exiting ash
3592 * loop forever if pty is already deleted */
3593 tcsetpgrp(fd, pgrp);
3608 killcmd(int argc, char **argv)
3611 if (argv[1] && strcmp(argv[1], "-l") != 0) {
3613 if (argv[i][0] == '%') {
3614 struct job *jp = getjob(argv[i], 0);
3615 unsigned pid = jp->ps[0].pid;
3616 /* Enough space for ' -NNN<nul>' */
3617 argv[i] = alloca(sizeof(int)*3 + 3);
3618 /* kill_main has matching code to expect
3619 * leading space. Needed to not confuse
3620 * negative pids with "kill -SIGNAL_NO" syntax */
3621 sprintf(argv[i], " -%u", pid);
3623 } while (argv[++i]);
3625 return kill_main(argc, argv);
3629 showpipe(struct job *jp, FILE *out)
3631 struct procstat *sp;
3632 struct procstat *spend;
3634 spend = jp->ps + jp->nprocs;
3635 for (sp = jp->ps + 1; sp < spend; sp++)
3636 fprintf(out, " | %s", sp->cmd);
3637 outcslow('\n', out);
3638 flush_stdout_stderr();
3643 restartjob(struct job *jp, int mode)
3645 struct procstat *ps;
3651 if (jp->state == JOBDONE)
3653 jp->state = JOBRUNNING;
3655 if (mode == FORK_FG)
3656 xtcsetpgrp(ttyfd, pgid);
3657 killpg(pgid, SIGCONT);
3661 if (WIFSTOPPED(ps->status)) {
3667 status = (mode == FORK_FG) ? waitforjob(jp) : 0;
3673 fg_bgcmd(int argc ATTRIBUTE_UNUSED, char **argv)
3680 mode = (**argv == 'f') ? FORK_FG : FORK_BG;
3685 jp = getjob(*argv, 1);
3686 if (mode == FORK_BG) {
3687 set_curjob(jp, CUR_RUNNING);
3688 fprintf(out, "[%d] ", jobno(jp));
3690 outstr(jp->ps->cmd, out);
3692 retval = restartjob(jp, mode);
3693 } while (*argv && *++argv);
3699 sprint_status(char *s, int status, int sigonly)
3705 if (!WIFEXITED(status)) {
3707 if (WIFSTOPPED(status))
3708 st = WSTOPSIG(status);
3711 st = WTERMSIG(status);
3713 if (st == SIGINT || st == SIGPIPE)
3716 if (WIFSTOPPED(status))
3721 col = fmtstr(s, 32, strsignal(st));
3722 if (WCOREDUMP(status)) {
3723 col += fmtstr(s + col, 16, " (core dumped)");
3725 } else if (!sigonly) {
3726 st = WEXITSTATUS(status);
3728 col = fmtstr(s, 16, "Done(%d)", st);
3730 col = fmtstr(s, 16, "Done");
3737 * Do a wait system call. If job control is compiled in, we accept
3738 * stopped processes. If block is zero, we return a value of zero
3739 * rather than blocking.
3741 * System V doesn't have a non-blocking wait system call. It does
3742 * have a SIGCLD signal that is sent to a process when one of it's
3743 * children dies. The obvious way to use SIGCLD would be to install
3744 * a handler for SIGCLD which simply bumped a counter when a SIGCLD
3745 * was received, and have waitproc bump another counter when it got
3746 * the status of a process. Waitproc would then know that a wait
3747 * system call would not block if the two counters were different.
3748 * This approach doesn't work because if a process has children that
3749 * have not been waited for, System V will send it a SIGCLD when it
3750 * installs a signal handler for SIGCLD. What this means is that when
3751 * a child exits, the shell will be sent SIGCLD signals continuously
3752 * until is runs out of stack space, unless it does a wait call before
3753 * restoring the signal handler. The code below takes advantage of
3754 * this (mis)feature by installing a signal handler for SIGCLD and
3755 * then checking to see whether it was called. If there are any
3756 * children to be waited for, it will be.
3758 * If neither SYSV nor BSD is defined, we don't implement nonblocking
3759 * waits at all. In this case, the user will not be informed when
3760 * a background process until the next time she runs a real program
3761 * (as opposed to running a builtin command or just typing return),
3762 * and the jobs command may give out of date information.
3765 waitproc(int wait_flags, int *status)
3769 wait_flags |= WUNTRACED;
3771 /* NB: _not_ safe_waitpid, we need to detect EINTR */
3772 return waitpid(-1, status, wait_flags);
3776 * Wait for a process to terminate.
3779 dowait(int wait_flags, struct job *job)
3784 struct job *thisjob;
3787 TRACE(("dowait(%d) called\n", wait_flags));
3788 pid = waitproc(wait_flags, &status);
3789 TRACE(("wait returns pid=%d, status=%d\n", pid, status));
3791 /* If we were doing blocking wait and (probably) got EINTR,
3792 * check for pending sigs received while waiting.
3793 * (NB: can be moved into callers if needed) */
3794 if (wait_flags == DOWAIT_BLOCK && pendingsig)
3795 raise_exception(EXSIG);
3800 for (jp = curjob; jp; jp = jp->prev_job) {
3801 struct procstat *sp;
3802 struct procstat *spend;
3803 if (jp->state == JOBDONE)
3806 spend = jp->ps + jp->nprocs;
3809 if (sp->pid == pid) {
3810 TRACE(("Job %d: changing status of proc %d "
3811 "from 0x%x to 0x%x\n",
3812 jobno(jp), pid, sp->status, status));
3813 sp->status = status;
3816 if (sp->status == -1)
3819 if (state == JOBRUNNING)
3821 if (WIFSTOPPED(sp->status)) {
3822 jp->stopstatus = sp->status;
3826 } while (++sp < spend);
3831 if (!WIFSTOPPED(status))
3837 if (state != JOBRUNNING) {
3838 thisjob->changed = 1;
3840 if (thisjob->state != state) {
3841 TRACE(("Job %d: changing state from %d to %d\n",
3842 jobno(thisjob), thisjob->state, state));
3843 thisjob->state = state;
3845 if (state == JOBSTOPPED) {
3846 set_curjob(thisjob, CUR_STOPPED);
3855 if (thisjob && thisjob == job) {
3859 len = sprint_status(s, status, 1);
3871 showjob(FILE *out, struct job *jp, int mode)
3873 struct procstat *ps;
3874 struct procstat *psend;
3881 if (mode & SHOW_PGID) {
3882 /* just output process (group) id of pipeline */
3883 fprintf(out, "%d\n", ps->pid);
3887 col = fmtstr(s, 16, "[%d] ", jobno(jp));
3892 else if (curjob && jp == curjob->prev_job)
3895 if (mode & SHOW_PID)
3896 col += fmtstr(s + col, 16, "%d ", ps->pid);
3898 psend = ps + jp->nprocs;
3900 if (jp->state == JOBRUNNING) {
3901 strcpy(s + col, "Running");
3902 col += sizeof("Running") - 1;
3904 int status = psend[-1].status;
3905 if (jp->state == JOBSTOPPED)
3906 status = jp->stopstatus;
3907 col += sprint_status(s + col, status, 0);
3913 /* for each process */
3914 col = fmtstr(s, 48, " |\n%*c%d ", indent_col, ' ', ps->pid) - 3;
3916 fprintf(out, "%s%*c%s",
3917 s, 33 - col >= 0 ? 33 - col : 0, ' ', ps->cmd
3919 if (!(mode & SHOW_PID)) {
3923 if (++ps == psend) {
3924 outcslow('\n', out);
3931 if (jp->state == JOBDONE) {
3932 TRACE(("showjob: freeing job %d\n", jobno(jp)));
3938 * Print a list of jobs. If "change" is nonzero, only print jobs whose
3939 * statuses have changed since the last call to showjobs.
3942 showjobs(FILE *out, int mode)
3946 TRACE(("showjobs(%x) called\n", mode));
3948 /* If not even one job changed, there is nothing to do */
3949 while (dowait(DOWAIT_NONBLOCK, NULL) > 0)
3952 for (jp = curjob; jp; jp = jp->prev_job) {
3953 if (!(mode & SHOW_CHANGED) || jp->changed) {
3954 showjob(out, jp, mode);
3960 jobscmd(int argc ATTRIBUTE_UNUSED, char **argv)
3965 while ((m = nextopt("lp"))) {
3975 showjob(stdout, getjob(*argv,0), mode);
3978 showjobs(stdout, mode);
3985 getstatus(struct job *job)
3990 status = job->ps[job->nprocs - 1].status;
3991 retval = WEXITSTATUS(status);
3992 if (!WIFEXITED(status)) {
3994 retval = WSTOPSIG(status);
3995 if (!WIFSTOPPED(status))
3998 /* XXX: limits number of signals */
3999 retval = WTERMSIG(status);
4001 if (retval == SIGINT)
4007 TRACE(("getstatus: job %d, nproc %d, status %x, retval %x\n",
4008 jobno(job), job->nprocs, status, retval));
4013 waitcmd(int argc ATTRIBUTE_UNUSED, char **argv)
4022 raise_exception(EXSIG);
4029 /* wait for all jobs */
4033 if (!jp) /* no running procs */
4035 if (jp->state == JOBRUNNING)
4040 dowait(DOWAIT_BLOCK, NULL);
4046 if (**argv != '%') {
4047 pid_t pid = number(*argv);
4052 if (job->ps[job->nprocs - 1].pid == pid)
4054 job = job->prev_job;
4057 job = getjob(*argv, 0);
4058 /* loop until process terminated or stopped */
4059 while (job->state == JOBRUNNING)
4060 dowait(DOWAIT_BLOCK, NULL);
4062 retval = getstatus(job);
4076 struct job *jp, *jq;
4078 len = njobs * sizeof(*jp);
4080 jp = ckrealloc(jq, len + 4 * sizeof(*jp));
4082 offset = (char *)jp - (char *)jq;
4084 /* Relocate pointers */
4087 jq = (struct job *)((char *)jq + l);
4091 #define joff(p) ((struct job *)((char *)(p) + l))
4092 #define jmove(p) (p) = (void *)((char *)(p) + offset)
4093 if (joff(jp)->ps == &jq->ps0)
4094 jmove(joff(jp)->ps);
4095 if (joff(jp)->prev_job)
4096 jmove(joff(jp)->prev_job);
4106 jp = (struct job *)((char *)jp + len);
4110 } while (--jq >= jp);
4115 * Return a new job structure.
4116 * Called with interrupts off.
4119 makejob(/*union node *node,*/ int nprocs)
4124 for (i = njobs, jp = jobtab; ; jp++) {
4131 if (jp->state != JOBDONE || !jp->waited)
4140 memset(jp, 0, sizeof(*jp));
4142 /* jp->jobctl is a bitfield.
4143 * "jp->jobctl |= jobctl" likely to give awful code */
4147 jp->prev_job = curjob;
4152 jp->ps = ckmalloc(nprocs * sizeof(struct procstat));
4154 TRACE(("makejob(%d) returns %%%d\n", nprocs,
4161 * Return a string identifying a command (to be printed by the
4164 static char *cmdnextc;
4167 cmdputs(const char *s)
4169 static const char vstype[VSTYPE + 1][3] = {
4170 "", "}", "-", "+", "?", "=",
4171 "%", "%%", "#", "##"
4172 USE_ASH_BASH_COMPAT(, ":", "/", "//")
4175 const char *p, *str;
4176 char c, cc[2] = " ";
4181 nextc = makestrspace((strlen(s) + 1) * 8, cmdnextc);
4183 while ((c = *p++) != 0) {
4191 if ((subtype & VSTYPE) == VSLENGTH)
4195 if (!(subtype & VSQUOTE) == !(quoted & 1))
4201 str = "\"}" + !(quoted & 1);
4208 case CTLBACKQ+CTLQUOTE:
4211 #if ENABLE_ASH_MATH_SUPPORT
4226 if ((subtype & VSTYPE) != VSNORMAL)
4228 str = vstype[subtype & VSTYPE];
4229 if (subtype & VSNUL)
4238 /* These can only happen inside quotes */
4251 while ((c = *str++)) {
4256 USTPUTC('"', nextc);
4262 /* cmdtxt() and cmdlist() call each other */
4263 static void cmdtxt(union node *n);
4266 cmdlist(union node *np, int sep)
4268 for (; np; np = np->narg.next) {
4272 if (sep && np->narg.next)
4278 cmdtxt(union node *n)
4281 struct nodelist *lp;
4293 lp = n->npipe.cmdlist;
4311 cmdtxt(n->nbinary.ch1);
4327 cmdtxt(n->nif.test);
4330 if (n->nif.elsepart) {
4333 n = n->nif.elsepart;
4349 cmdtxt(n->nbinary.ch1);
4359 cmdputs(n->nfor.var);
4361 cmdlist(n->nfor.args, 1);
4366 cmdputs(n->narg.text);
4370 cmdlist(n->ncmd.args, 1);
4371 cmdlist(n->ncmd.redirect, 0);
4384 cmdputs(n->ncase.expr->narg.text);
4386 for (np = n->ncase.cases; np; np = np->nclist.next) {
4387 cmdtxt(np->nclist.pattern);
4389 cmdtxt(np->nclist.body);
4415 s[0] = n->nfile.fd + '0';
4419 if (n->type == NTOFD || n->type == NFROMFD) {
4420 s[0] = n->ndup.dupfd + '0';
4430 commandtext(union node *n)
4434 STARTSTACKSTR(cmdnextc);
4436 name = stackblock();
4437 TRACE(("commandtext: name %p, end %p\n\t\"%s\"\n",
4438 name, cmdnextc, cmdnextc));
4439 return ckstrdup(name);
4444 * Fork off a subshell. If we are doing job control, give the subshell its
4445 * own process group. Jp is a job structure that the job is to be added to.
4446 * N is the command that will be evaluated by the child. Both jp and n may
4447 * be NULL. The mode parameter can be one of the following:
4448 * FORK_FG - Fork off a foreground process.
4449 * FORK_BG - Fork off a background process.
4450 * FORK_NOJOB - Like FORK_FG, but don't give the process its own
4451 * process group even if job control is on.
4453 * When job control is turned off, background processes have their standard
4454 * input redirected to /dev/null (except for the second and later processes
4457 * Called with interrupts off.
4460 * Clear traps on a fork.
4467 for (tp = trap; tp < &trap[NSIG]; tp++) {
4468 if (*tp && **tp) { /* trap not NULL or "" (SIG_IGN) */
4473 setsignal(tp - trap);
4479 /* Lives far away from here, needed for forkchild */
4480 static void closescript(void);
4482 /* Called after fork(), in child */
4484 forkchild(struct job *jp, /*union node *n,*/ int mode)
4488 TRACE(("Child shell %d\n", getpid()));
4495 /* do job control only in root shell */
4497 if (mode != FORK_NOJOB && jp->jobctl && !oldlvl) {
4500 if (jp->nprocs == 0)
4503 pgrp = jp->ps[0].pid;
4504 /* This can fail because we are doing it in the parent also */
4505 (void)setpgid(0, pgrp);
4506 if (mode == FORK_FG)
4507 xtcsetpgrp(ttyfd, pgrp);
4512 if (mode == FORK_BG) {
4515 if (jp->nprocs == 0) {
4517 if (open(bb_dev_null, O_RDONLY) != 0)
4518 ash_msg_and_raise_error("can't open %s", bb_dev_null);
4521 if (!oldlvl && iflag) {
4526 for (jp = curjob; jp; jp = jp->prev_job)
4531 /* Called after fork(), in parent */
4533 #define forkparent(jp, n, mode, pid) forkparent(jp, mode, pid)
4536 forkparent(struct job *jp, union node *n, int mode, pid_t pid)
4538 TRACE(("In parent shell: child = %d\n", pid));
4540 while (jobless && dowait(DOWAIT_NONBLOCK, NULL) > 0)
4546 if (mode != FORK_NOJOB && jp->jobctl) {
4549 if (jp->nprocs == 0)
4552 pgrp = jp->ps[0].pid;
4553 /* This can fail because we are doing it in the child also */
4557 if (mode == FORK_BG) {
4558 backgndpid = pid; /* set $! */
4559 set_curjob(jp, CUR_RUNNING);
4562 struct procstat *ps = &jp->ps[jp->nprocs++];
4567 if (doing_jobctl && n)
4568 ps->cmd = commandtext(n);
4574 forkshell(struct job *jp, union node *n, int mode)
4578 TRACE(("forkshell(%%%d, %p, %d) called\n", jobno(jp), n, mode));
4581 TRACE(("Fork failed, errno=%d", errno));
4584 ash_msg_and_raise_error("can't fork");
4587 forkchild(jp, /*n,*/ mode);
4589 forkparent(jp, n, mode, pid);
4594 * Wait for job to finish.
4596 * Under job control we have the problem that while a child process is
4597 * running interrupts generated by the user are sent to the child but not
4598 * to the shell. This means that an infinite loop started by an inter-
4599 * active user may be hard to kill. With job control turned off, an
4600 * interactive user may place an interactive program inside a loop. If
4601 * the interactive program catches interrupts, the user doesn't want
4602 * these interrupts to also abort the loop. The approach we take here
4603 * is to have the shell ignore interrupt signals while waiting for a
4604 * foreground process to terminate, and then send itself an interrupt
4605 * signal if the child process was terminated by an interrupt signal.
4606 * Unfortunately, some programs want to do a bit of cleanup and then
4607 * exit on interrupt; unless these processes terminate themselves by
4608 * sending a signal to themselves (instead of calling exit) they will
4609 * confuse this approach.
4611 * Called with interrupts off.
4614 waitforjob(struct job *jp)
4618 TRACE(("waitforjob(%%%d) called\n", jobno(jp)));
4619 while (jp->state == JOBRUNNING) {
4620 dowait(DOWAIT_BLOCK, jp);
4625 xtcsetpgrp(ttyfd, rootpid);
4627 * This is truly gross.
4628 * If we're doing job control, then we did a TIOCSPGRP which
4629 * caused us (the shell) to no longer be in the controlling
4630 * session -- so we wouldn't have seen any ^C/SIGINT. So, we
4631 * intuit from the subprocess exit status whether a SIGINT
4632 * occurred, and if so interrupt ourselves. Yuck. - mycroft
4634 if (jp->sigint) /* TODO: do the same with all signals */
4635 raise(SIGINT); /* ... by raise(jp->sig) instead? */
4637 if (jp->state == JOBDONE)
4644 * return 1 if there are stopped jobs, otherwise 0
4656 if (jp && jp->state == JOBSTOPPED) {
4657 out2str("You have stopped jobs.\n");
4666 /* ============ redir.c
4668 * Code for dealing with input/output redirection.
4671 #define EMPTY -2 /* marks an unused slot in redirtab */
4672 #define CLOSED -3 /* marks a slot of previously-closed fd */
4674 # define PIPESIZE 4096 /* amount of buffering in a pipe */
4676 # define PIPESIZE PIPE_BUF
4680 * Open a file in noclobber mode.
4681 * The code was copied from bash.
4684 noclobberopen(const char *fname)
4687 struct stat finfo, finfo2;
4690 * If the file exists and is a regular file, return an error
4693 r = stat(fname, &finfo);
4694 if (r == 0 && S_ISREG(finfo.st_mode)) {
4700 * If the file was not present (r != 0), make sure we open it
4701 * exclusively so that if it is created before we open it, our open
4702 * will fail. Make sure that we do not truncate an existing file.
4703 * Note that we don't turn on O_EXCL unless the stat failed -- if the
4704 * file was not a regular file, we leave O_EXCL off.
4707 return open(fname, O_WRONLY|O_CREAT|O_EXCL, 0666);
4708 fd = open(fname, O_WRONLY|O_CREAT, 0666);
4710 /* If the open failed, return the file descriptor right away. */
4715 * OK, the open succeeded, but the file may have been changed from a
4716 * non-regular file to a regular file between the stat and the open.
4717 * We are assuming that the O_EXCL open handles the case where FILENAME
4718 * did not exist and is symlinked to an existing file between the stat
4723 * If we can open it and fstat the file descriptor, and neither check
4724 * revealed that it was a regular file, and the file has not been
4725 * replaced, return the file descriptor.
4727 if (fstat(fd, &finfo2) == 0 && !S_ISREG(finfo2.st_mode)
4728 && finfo.st_dev == finfo2.st_dev && finfo.st_ino == finfo2.st_ino)
4731 /* The file has been replaced. badness. */
4738 * Handle here documents. Normally we fork off a process to write the
4739 * data to a pipe. If the document is short, we can stuff the data in
4740 * the pipe without forking.
4742 /* openhere needs this forward reference */
4743 static void expandhere(union node *arg, int fd);
4745 openhere(union node *redir)
4751 ash_msg_and_raise_error("pipe call failed");
4752 if (redir->type == NHERE) {
4753 len = strlen(redir->nhere.doc->narg.text);
4754 if (len <= PIPESIZE) {
4755 full_write(pip[1], redir->nhere.doc->narg.text, len);
4759 if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) {
4761 signal(SIGINT, SIG_IGN);
4762 signal(SIGQUIT, SIG_IGN);
4763 signal(SIGHUP, SIG_IGN);
4765 signal(SIGTSTP, SIG_IGN);
4767 signal(SIGPIPE, SIG_DFL);
4768 if (redir->type == NHERE)
4769 full_write(pip[1], redir->nhere.doc->narg.text, len);
4771 expandhere(redir->nhere.doc, pip[1]);
4772 _exit(EXIT_SUCCESS);
4780 openredirect(union node *redir)
4785 switch (redir->nfile.type) {
4787 fname = redir->nfile.expfname;
4788 f = open(fname, O_RDONLY);
4793 fname = redir->nfile.expfname;
4794 f = open(fname, O_RDWR|O_CREAT|O_TRUNC, 0666);
4799 /* Take care of noclobber mode. */
4801 fname = redir->nfile.expfname;
4802 f = noclobberopen(fname);
4809 fname = redir->nfile.expfname;
4810 f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666);
4815 fname = redir->nfile.expfname;
4816 f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666);
4824 /* Fall through to eliminate warning. */
4831 f = openhere(redir);
4837 ash_msg_and_raise_error("cannot create %s: %s", fname, errmsg(errno, "nonexistent directory"));
4839 ash_msg_and_raise_error("cannot open %s: %s", fname, errmsg(errno, "no such file"));
4843 * Copy a file descriptor to be >= to. Returns -1
4844 * if the source file descriptor is closed, EMPTY if there are no unused
4845 * file descriptors left.
4848 copyfd(int from, int to)
4852 newfd = fcntl(from, F_DUPFD, to);
4854 if (errno == EMFILE)
4856 ash_msg_and_raise_error("%d: %m", from);
4862 dupredirect(union node *redir, int f)
4864 int fd = redir->nfile.fd;
4866 if (redir->nfile.type == NTOFD || redir->nfile.type == NFROMFD) {
4867 if (redir->ndup.dupfd >= 0) { /* if not ">&-" */
4868 copyfd(redir->ndup.dupfd, fd);
4880 * Process a list of redirection commands. If the REDIR_PUSH flag is set,
4881 * old file descriptors are stashed away so that the redirection can be
4882 * undone by calling popredir. If the REDIR_BACKQ flag is set, then the
4883 * standard output, and the standard error if it becomes a duplicate of
4884 * stdout, is saved in memory.
4886 /* flags passed to redirect */
4887 #define REDIR_PUSH 01 /* save previous values of file descriptors */
4888 #define REDIR_SAVEFD2 03 /* set preverrout */
4890 redirect(union node *redir, int flags)
4893 struct redirtab *sv;
4904 if (flags & REDIR_PUSH) {
4905 sv = ckmalloc(sizeof(*sv));
4906 sv->next = redirlist;
4908 sv->nullredirs = g_nullredirs - 1;
4909 for (i = 0; i < 10; i++)
4910 sv->renamed[i] = EMPTY;
4916 if ((n->nfile.type == NTOFD || n->nfile.type == NFROMFD)
4917 && n->ndup.dupfd == fd)
4918 continue; /* redirect from/to same file descriptor */
4920 newfd = openredirect(n);
4922 /* Descriptor wasn't open before redirect.
4923 * Mark it for close in the future */
4924 if (sv && sv->renamed[fd] == EMPTY)
4925 sv->renamed[fd] = CLOSED;
4928 if (sv && sv->renamed[fd] == EMPTY) {
4929 i = fcntl(fd, F_DUPFD, 10);
4936 ash_msg_and_raise_error("%d: %m", fd);
4940 sv->renamed[fd] = i;
4946 dupredirect(n, newfd);
4947 } while ((n = n->nfile.next));
4949 if ((flags & REDIR_SAVEFD2) && sv && sv->renamed[2] >= 0)
4950 preverrout_fd = sv->renamed[2];
4954 * Undo the effects of the last redirection.
4959 struct redirtab *rp;
4962 if (--g_nullredirs >= 0)
4966 for (i = 0; i < 10; i++) {
4967 if (rp->renamed[i] == CLOSED) {
4972 if (rp->renamed[i] != EMPTY) {
4975 copyfd(rp->renamed[i], i);
4977 close(rp->renamed[i]);
4980 redirlist = rp->next;
4981 g_nullredirs = rp->nullredirs;
4987 * Undo all redirections. Called on error or interrupt.
4991 * Discard all saved file descriptors.
4994 clearredir(int drop)
5005 redirectsafe(union node *redir, int flags)
5008 volatile int saveint;
5009 struct jmploc *volatile savehandler = exception_handler;
5010 struct jmploc jmploc;
5013 err = setjmp(jmploc.loc) * 2;
5015 exception_handler = &jmploc;
5016 redirect(redir, flags);
5018 exception_handler = savehandler;
5019 if (err && exception != EXERROR)
5020 longjmp(exception_handler->loc, 1);
5021 RESTORE_INT(saveint);
5026 /* ============ Routines to expand arguments to commands
5028 * We have to deal with backquotes, shell variables, and file metacharacters.
5031 #if ENABLE_ASH_MATH_SUPPORT_64
5032 typedef int64_t arith_t;
5033 #define arith_t_type long long
5035 typedef long arith_t;
5036 #define arith_t_type long
5039 #if ENABLE_ASH_MATH_SUPPORT
5040 static arith_t dash_arith(const char *);
5041 static arith_t arith(const char *expr, int *perrcode);
5047 #define EXP_FULL 0x1 /* perform word splitting & file globbing */
5048 #define EXP_TILDE 0x2 /* do normal tilde expansion */
5049 #define EXP_VARTILDE 0x4 /* expand tildes in an assignment */
5050 #define EXP_REDIR 0x8 /* file glob for a redirection (1 match only) */
5051 #define EXP_CASE 0x10 /* keeps quotes around for CASE pattern */
5052 #define EXP_RECORD 0x20 /* need to record arguments for ifs breakup */
5053 #define EXP_VARTILDE2 0x40 /* expand tildes after colons only */
5054 #define EXP_WORD 0x80 /* expand word in parameter expansion */
5055 #define EXP_QWORD 0x100 /* expand word in quoted parameter expansion */
5059 #define RMESCAPE_ALLOC 0x1 /* Allocate a new string */
5060 #define RMESCAPE_GLOB 0x2 /* Add backslashes for glob */
5061 #define RMESCAPE_QUOTED 0x4 /* Remove CTLESC unless in quotes */
5062 #define RMESCAPE_GROW 0x8 /* Grow strings instead of stalloc */
5063 #define RMESCAPE_HEAP 0x10 /* Malloc strings instead of stalloc */
5066 * Structure specifying which parts of the string should be searched
5067 * for IFS characters.
5070 struct ifsregion *next; /* next region in list */
5071 int begoff; /* offset of start of region */
5072 int endoff; /* offset of end of region */
5073 int nulonly; /* search for nul bytes only */
5077 struct strlist *list;
5078 struct strlist **lastp;
5081 /* output of current string */
5082 static char *expdest;
5083 /* list of back quote expressions */
5084 static struct nodelist *argbackq;
5085 /* first struct in list of ifs regions */
5086 static struct ifsregion ifsfirst;
5087 /* last struct in list */
5088 static struct ifsregion *ifslastp;
5089 /* holds expanded arg list */
5090 static struct arglist exparg;
5100 expdest = makestrspace(32, expdest);
5101 #if ENABLE_ASH_MATH_SUPPORT_64
5102 len = fmtstr(expdest, 32, "%lld", (long long) num);
5104 len = fmtstr(expdest, 32, "%ld", num);
5106 STADJUST(len, expdest);
5111 esclen(const char *start, const char *p)
5115 while (p > start && *--p == CTLESC) {
5122 * Remove any CTLESC characters from a string.
5125 _rmescapes(char *str, int flag)
5127 static const char qchars[] ALIGN1 = { CTLESC, CTLQUOTEMARK, '\0' };
5134 p = strpbrk(str, qchars);
5140 if (flag & RMESCAPE_ALLOC) {
5141 size_t len = p - str;
5142 size_t fulllen = len + strlen(p) + 1;
5144 if (flag & RMESCAPE_GROW) {
5145 r = makestrspace(fulllen, expdest);
5146 } else if (flag & RMESCAPE_HEAP) {
5147 r = ckmalloc(fulllen);
5149 r = stalloc(fulllen);
5153 q = (char *)memcpy(q, str, len) + len;
5156 inquotes = (flag & RMESCAPE_QUOTED) ^ RMESCAPE_QUOTED;
5157 globbing = flag & RMESCAPE_GLOB;
5158 notescaped = globbing;
5160 if (*p == CTLQUOTEMARK) {
5161 inquotes = ~inquotes;
5163 notescaped = globbing;
5167 /* naked back slash */
5173 if (notescaped && inquotes && *p != '/') {
5177 notescaped = globbing;
5182 if (flag & RMESCAPE_GROW) {
5184 STADJUST(q - r + 1, expdest);
5188 #define rmescapes(p) _rmescapes((p), 0)
5190 #define pmatch(a, b) !fnmatch((a), (b), 0)
5193 * Prepare a pattern for a expmeta (internal glob(3)) call.
5195 * Returns an stalloced string.
5198 preglob(const char *pattern, int quoted, int flag)
5200 flag |= RMESCAPE_GLOB;
5202 flag |= RMESCAPE_QUOTED;
5204 return _rmescapes((char *)pattern, flag);
5208 * Put a string on the stack.
5211 memtodest(const char *p, size_t len, int syntax, int quotes)
5215 q = makestrspace(len * 2, q);
5218 int c = signed_char2int(*p++);
5221 if (quotes && (SIT(c, syntax) == CCTL || SIT(c, syntax) == CBACK))
5230 strtodest(const char *p, int syntax, int quotes)
5232 memtodest(p, strlen(p), syntax, quotes);
5236 * Record the fact that we have to scan this region of the
5237 * string for IFS characters.
5240 recordregion(int start, int end, int nulonly)
5242 struct ifsregion *ifsp;
5244 if (ifslastp == NULL) {
5248 ifsp = ckzalloc(sizeof(*ifsp));
5249 /*ifsp->next = NULL; - ckzalloc did it */
5250 ifslastp->next = ifsp;
5254 ifslastp->begoff = start;
5255 ifslastp->endoff = end;
5256 ifslastp->nulonly = nulonly;
5260 removerecordregions(int endoff)
5262 if (ifslastp == NULL)
5265 if (ifsfirst.endoff > endoff) {
5266 while (ifsfirst.next != NULL) {
5267 struct ifsregion *ifsp;
5269 ifsp = ifsfirst.next->next;
5270 free(ifsfirst.next);
5271 ifsfirst.next = ifsp;
5274 if (ifsfirst.begoff > endoff)
5277 ifslastp = &ifsfirst;
5278 ifsfirst.endoff = endoff;
5283 ifslastp = &ifsfirst;
5284 while (ifslastp->next && ifslastp->next->begoff < endoff)
5285 ifslastp=ifslastp->next;
5286 while (ifslastp->next != NULL) {
5287 struct ifsregion *ifsp;
5289 ifsp = ifslastp->next->next;
5290 free(ifslastp->next);
5291 ifslastp->next = ifsp;
5294 if (ifslastp->endoff > endoff)
5295 ifslastp->endoff = endoff;
5299 exptilde(char *startp, char *p, int flag)
5305 int quotes = flag & (EXP_FULL | EXP_CASE);
5310 while ((c = *++p) != '\0') {
5317 if (flag & EXP_VARTILDE)
5327 if (*name == '\0') {
5328 home = lookupvar(homestr);
5330 pw = getpwnam(name);
5335 if (!home || !*home)
5338 startloc = expdest - (char *)stackblock();
5339 strtodest(home, SQSYNTAX, quotes);
5340 recordregion(startloc, expdest - (char *)stackblock(), 0);
5348 * Execute a command inside back quotes. If it's a builtin command, we
5349 * want to save its output in a block obtained from malloc. Otherwise
5350 * we fork off a subprocess and get the output of the command via a pipe.
5351 * Should be called with interrupts off.
5353 struct backcmd { /* result of evalbackcmd */
5354 int fd; /* file descriptor to read from */
5355 int nleft; /* number of chars in buffer */
5356 char *buf; /* buffer */
5357 struct job *jp; /* job structure for command */
5360 /* These forward decls are needed to use "eval" code for backticks handling: */
5361 static uint8_t back_exitstatus; /* exit status of backquoted command */
5362 #define EV_EXIT 01 /* exit after evaluating tree */
5363 static void evaltree(union node *, int);
5366 evalbackcmd(union node *n, struct backcmd *result)
5378 saveherefd = herefd;
5386 ash_msg_and_raise_error("pipe call failed");
5387 jp = makejob(/*n,*/ 1);
5388 if (forkshell(jp, n, FORK_NOJOB) == 0) {
5397 evaltree(n, EV_EXIT); /* actually evaltreenr... */
5401 result->fd = pip[0];
5404 herefd = saveherefd;
5406 TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n",
5407 result->fd, result->buf, result->nleft, result->jp));
5411 * Expand stuff in backwards quotes.
5414 expbackq(union node *cmd, int quoted, int quotes)
5422 int syntax = quoted ? DQSYNTAX : BASESYNTAX;
5423 struct stackmark smark;
5426 setstackmark(&smark);
5428 startloc = dest - (char *)stackblock();
5430 evalbackcmd(cmd, &in);
5431 popstackmark(&smark);
5438 memtodest(p, i, syntax, quotes);
5442 i = nonblock_safe_read(in.fd, buf, sizeof(buf));
5443 TRACE(("expbackq: read returns %d\n", i));
5452 back_exitstatus = waitforjob(in.jp);
5456 /* Eat all trailing newlines */
5458 for (; dest > (char *)stackblock() && dest[-1] == '\n';)
5463 recordregion(startloc, dest - (char *)stackblock(), 0);
5464 TRACE(("evalbackq: size=%d: \"%.*s\"\n",
5465 (dest - (char *)stackblock()) - startloc,
5466 (dest - (char *)stackblock()) - startloc,
5467 stackblock() + startloc));
5470 #if ENABLE_ASH_MATH_SUPPORT
5472 * Expand arithmetic expression. Backup to start of expression,
5473 * evaluate, place result in (backed up) result, adjust string position.
5486 * This routine is slightly over-complicated for
5487 * efficiency. Next we scan backwards looking for the
5488 * start of arithmetic.
5490 start = stackblock();
5497 while (*p != CTLARI) {
5501 ash_msg_and_raise_error("missing CTLARI (shouldn't happen)");
5506 esc = esclen(start, p);
5516 removerecordregions(begoff);
5525 len = cvtnum(dash_arith(p + 2));
5528 recordregion(begoff, begoff + len, 0);
5532 /* argstr needs it */
5533 static char *evalvar(char *p, int flag, struct strlist *var_str_list);
5536 * Perform variable and command substitution. If EXP_FULL is set, output CTLESC
5537 * characters to allow for further processing. Otherwise treat
5538 * $@ like $* since no splitting will be performed.
5540 * var_str_list (can be NULL) is a list of "VAR=val" strings which take precedence
5541 * over shell varables. Needed for "A=a B=$A; echo $B" case - we use it
5542 * for correct expansion of "B=$A" word.
5545 argstr(char *p, int flag, struct strlist *var_str_list)
5547 static const char spclchars[] ALIGN1 = {
5555 CTLBACKQ | CTLQUOTE,
5556 #if ENABLE_ASH_MATH_SUPPORT
5561 const char *reject = spclchars;
5563 int quotes = flag & (EXP_FULL | EXP_CASE); /* do CTLESC */
5564 int breakall = flag & EXP_WORD;
5569 if (!(flag & EXP_VARTILDE)) {
5571 } else if (flag & EXP_VARTILDE2) {
5576 if (flag & EXP_TILDE) {
5582 if (*q == CTLESC && (flag & EXP_QWORD))
5585 p = exptilde(p, q, flag);
5588 startloc = expdest - (char *)stackblock();
5590 length += strcspn(p + length, reject);
5592 if (c && (!(c & 0x80)
5593 #if ENABLE_ASH_MATH_SUPPORT
5597 /* c == '=' || c == ':' || c == CTLENDARI */
5602 expdest = stack_nputstr(p, length, expdest);
5603 newloc = expdest - (char *)stackblock();
5604 if (breakall && !inquotes && newloc > startloc) {
5605 recordregion(startloc, newloc, 0);
5616 if (flag & EXP_VARTILDE2) {
5620 flag |= EXP_VARTILDE2;
5625 * sort of a hack - expand tildes in variable
5626 * assignments (after the first '=' and after ':'s).
5635 case CTLENDVAR: /* ??? */
5638 /* "$@" syntax adherence hack */
5641 !memcmp(p, dolatstr, 4) &&
5642 (p[4] == CTLQUOTEMARK || (
5643 p[4] == CTLENDVAR &&
5644 p[5] == CTLQUOTEMARK
5647 p = evalvar(p + 1, flag, /* var_str_list: */ NULL) + 1;
5650 inquotes = !inquotes;
5663 p = evalvar(p, flag, var_str_list);
5667 case CTLBACKQ|CTLQUOTE:
5668 expbackq(argbackq->n, c, quotes);
5669 argbackq = argbackq->next;
5671 #if ENABLE_ASH_MATH_SUPPORT
5684 scanleft(char *startp, char *rmesc, char *rmescend ATTRIBUTE_UNUSED, char *str, int quotes,
5687 // This commented out code was added by James Simmons <jsimmons@infradead.org>
5688 // as part of a larger change when he added support for ${var/a/b}.
5689 // However, it broke # and % operators:
5693 //echo ${var#ab} abcdcd abcdcd
5694 //echo ${var##ab} abcdcd abcdcd
5695 //echo ${var#a*b} abcdcd ababcdcd (!)
5696 //echo ${var##a*b} cdcd cdcd
5697 //echo ${var#?} babcdcd ababcdcd (!)
5698 //echo ${var##?} babcdcd babcdcd
5699 //echo ${var#*} ababcdcd babcdcd (!)
5701 //echo ${var%cd} ababcd ababcd
5702 //echo ${var%%cd} ababcd abab (!)
5703 //echo ${var%c*d} ababcd ababcd
5704 //echo ${var%%c*d} abab ababcdcd (!)
5705 //echo ${var%?} ababcdc ababcdc
5706 //echo ${var%%?} ababcdc ababcdcd (!)
5707 //echo ${var%*} ababcdcd ababcdcd
5710 // Commenting it back out helped. Remove it completely if it really
5713 char *loc, *loc2; //, *full;
5719 int match; // = strlen(str);
5720 const char *s = loc2;
5727 match = pmatch(str, s); // this line was deleted
5729 // // chop off end if its '*'
5730 // full = strrchr(str, '*');
5731 // if (full && full != str)
5734 // // If str starts with '*' replace with s.
5735 // if ((*str == '*') && strlen(s) >= match) {
5736 // full = xstrdup(s);
5737 // strncpy(full+strlen(s)-match+1, str+1, match-1);
5739 // full = xstrndup(str, match);
5740 // match = strncmp(s, full, strlen(full));
5744 if (match) // if (!match)
5746 if (quotes && *loc == CTLESC)
5755 scanright(char *startp, char *rmesc, char *rmescend, char *str, int quotes,
5762 for (loc = str - 1, loc2 = rmescend; loc >= startp; loc2--) {
5765 const char *s = loc2;
5770 match = pmatch(str, s);
5777 esc = esclen(startp, loc);
5788 static void varunset(const char *, const char *, const char *, int) ATTRIBUTE_NORETURN;
5790 varunset(const char *end, const char *var, const char *umsg, int varflags)
5796 msg = "parameter not set";
5798 if (*end == CTLENDVAR) {
5799 if (varflags & VSNUL)
5804 ash_msg_and_raise_error("%.*s: %s%s", end - var - 1, var, msg, tail);
5807 #if ENABLE_ASH_BASH_COMPAT
5809 parse_sub_pattern(char *arg, int inquotes)
5811 char *idx, *repl = NULL;
5820 /* Only the first '/' seen is our separator */
5827 if (!inquotes && c == '\\' && arg[1] == '\\')
5828 arg++; /* skip both \\, not just first one */
5835 #endif /* ENABLE_ASH_BASH_COMPAT */
5838 subevalvar(char *p, char *str, int strloc, int subtype,
5839 int startloc, int varflags, int quotes, struct strlist *var_str_list)
5841 struct nodelist *saveargbackq = argbackq;
5844 char *rmesc, *rmescend;
5845 USE_ASH_BASH_COMPAT(char *repl = NULL;)
5846 USE_ASH_BASH_COMPAT(char null = '\0';)
5847 USE_ASH_BASH_COMPAT(int pos, len, orig_len;)
5848 int saveherefd = herefd;
5849 int amount, workloc, resetloc;
5851 char *(*scan)(char*, char*, char*, char*, int, int);
5854 argstr(p, (subtype != VSASSIGN && subtype != VSQUESTION) ? EXP_CASE : 0,
5856 STPUTC('\0', expdest);
5857 herefd = saveherefd;
5858 argbackq = saveargbackq;
5859 startp = (char *)stackblock() + startloc;
5863 setvar(str, startp, 0);
5864 amount = startp - expdest;
5865 STADJUST(amount, expdest);
5868 #if ENABLE_ASH_BASH_COMPAT
5870 loc = str = stackblock() + strloc;
5871 // TODO: number() instead? It does error checking...
5873 len = str - startp - 1;
5875 /* *loc != '\0', guaranteed by parser */
5879 /* We must adjust the length by the number of escapes we find. */
5880 for (ptr = startp; ptr < (str - 1); ptr++) {
5881 if(*ptr == CTLESC) {
5889 if (*loc++ == ':') {
5890 // TODO: number() instead? It does error checking...
5894 while (*loc && *loc != ':')
5897 // TODO: number() instead? It does error checking...
5900 if (pos >= orig_len) {
5904 if (len > (orig_len - pos))
5905 len = orig_len - pos;
5907 for (str = startp; pos; str++, pos--) {
5908 if (quotes && *str == CTLESC)
5911 for (loc = startp; len; len--) {
5912 if (quotes && *str == CTLESC)
5917 amount = loc - expdest;
5918 STADJUST(amount, expdest);
5923 varunset(p, str, startp, varflags);
5926 resetloc = expdest - (char *)stackblock();
5928 /* We'll comeback here if we grow the stack while handling
5929 * a VSREPLACE or VSREPLACEALL, since our pointers into the
5930 * stack will need rebasing, and we'll need to remove our work
5933 USE_ASH_BASH_COMPAT(restart:)
5935 amount = expdest - ((char *)stackblock() + resetloc);
5936 STADJUST(-amount, expdest);
5937 startp = (char *)stackblock() + startloc;
5940 rmescend = (char *)stackblock() + strloc;
5942 rmesc = _rmescapes(startp, RMESCAPE_ALLOC | RMESCAPE_GROW);
5943 if (rmesc != startp) {
5945 startp = (char *)stackblock() + startloc;
5949 str = (char *)stackblock() + strloc;
5950 preglob(str, varflags & VSQUOTE, 0);
5951 workloc = expdest - (char *)stackblock();
5953 #if ENABLE_ASH_BASH_COMPAT
5954 if (subtype == VSREPLACE || subtype == VSREPLACEALL) {
5955 char *idx, *end, *restart_detect;
5958 repl = parse_sub_pattern(str, varflags & VSQUOTE);
5963 /* If there's no pattern to match, return the expansion unmolested */
5971 loc = scanright(idx, rmesc, rmescend, str, quotes, 1);
5973 /* No match, advance */
5974 restart_detect = stackblock();
5975 STPUTC(*idx, expdest);
5976 if (quotes && *idx == CTLESC) {
5979 STPUTC(*idx, expdest);
5981 if (stackblock() != restart_detect)
5989 if (subtype == VSREPLACEALL) {
5991 if (quotes && *idx == CTLESC)
5999 for (loc = repl; *loc; loc++) {
6000 restart_detect = stackblock();
6001 STPUTC(*loc, expdest);
6002 if (stackblock() != restart_detect)
6007 if (subtype == VSREPLACE) {
6009 restart_detect = stackblock();
6010 STPUTC(*idx, expdest);
6011 if (stackblock() != restart_detect)
6020 /* We've put the replaced text into a buffer at workloc, now
6021 * move it to the right place and adjust the stack.
6023 startp = stackblock() + startloc;
6024 STPUTC('\0', expdest);
6025 memmove(startp, stackblock() + workloc, len);
6026 startp[len++] = '\0';
6027 amount = expdest - ((char *)stackblock() + startloc + len - 1);
6028 STADJUST(-amount, expdest);
6031 #endif /* ENABLE_ASH_BASH_COMPAT */
6033 subtype -= VSTRIMRIGHT;
6035 if (subtype < 0 || subtype > 7)
6038 /* zero = subtype == VSTRIMLEFT || subtype == VSTRIMLEFTMAX */
6039 zero = subtype >> 1;
6040 /* VSTRIMLEFT/VSTRIMRIGHTMAX -> scanleft */
6041 scan = (subtype & 1) ^ zero ? scanleft : scanright;
6043 loc = scan(startp, rmesc, rmescend, str, quotes, zero);
6046 memmove(startp, loc, str - loc);
6047 loc = startp + (str - loc) - 1;
6050 amount = loc - expdest;
6051 STADJUST(amount, expdest);
6057 * Add the value of a specialized variable to the stack string.
6060 varvalue(char *name, int varflags, int flags, struct strlist *var_str_list)
6070 int quoted = varflags & VSQUOTE;
6071 int subtype = varflags & VSTYPE;
6072 int quotes = flags & (EXP_FULL | EXP_CASE);
6074 if (quoted && (flags & EXP_FULL))
6075 sep = 1 << CHAR_BIT;
6077 syntax = quoted ? DQSYNTAX : BASESYNTAX;
6086 num = shellparam.nparam;
6096 p = makestrspace(NOPTS, expdest);
6097 for (i = NOPTS - 1; i >= 0; i--) {
6099 USTPUTC(optletters(i), p);
6110 sep = ifsset() ? signed_char2int(ifsval()[0]) : ' ';
6111 if (quotes && (SIT(sep, syntax) == CCTL || SIT(sep, syntax) == CBACK))
6117 while ((p = *ap++)) {
6120 partlen = strlen(p);
6123 if (!(subtype == VSPLUS || subtype == VSLENGTH))
6124 memtodest(p, partlen, syntax, quotes);
6130 if (subtype == VSPLUS || subtype == VSLENGTH) {
6151 // TODO: number() instead? It does error checking...
6153 if (num < 0 || num > shellparam.nparam)
6155 p = num ? shellparam.p[num - 1] : arg0;
6158 /* NB: name has form "VAR=..." */
6160 /* "A=a B=$A" case: var_str_list is a list of "A=a" strings
6161 * which should be considered before we check variables. */
6163 unsigned name_len = (strchrnul(name, '=') - name) + 1;
6167 str = var_str_list->text;
6168 eq = strchr(str, '=');
6169 if (!eq) /* stop at first non-assignment */
6172 if (name_len == (unsigned)(eq - str)
6173 && strncmp(str, name, name_len) == 0) {
6175 /* goto value; - WRONG! */
6176 /* think "A=1 A=2 B=$A" */
6178 var_str_list = var_str_list->next;
6179 } while (var_str_list);
6183 p = lookupvar(name);
6189 if (!(subtype == VSPLUS || subtype == VSLENGTH))
6190 memtodest(p, len, syntax, quotes);
6194 if (subtype == VSPLUS || subtype == VSLENGTH)
6195 STADJUST(-len, expdest);
6200 * Expand a variable, and return a pointer to the next character in the
6204 evalvar(char *p, int flag, struct strlist *var_str_list)
6216 subtype = varflags & VSTYPE;
6217 quoted = varflags & VSQUOTE;
6219 easy = (!quoted || (*var == '@' && shellparam.nparam));
6220 startloc = expdest - (char *)stackblock();
6221 p = strchr(p, '=') + 1;
6224 varlen = varvalue(var, varflags, flag, var_str_list);
6225 if (varflags & VSNUL)
6228 if (subtype == VSPLUS) {
6229 varlen = -1 - varlen;
6233 if (subtype == VSMINUS) {
6237 p, flag | EXP_TILDE |
6238 (quoted ? EXP_QWORD : EXP_WORD),
6248 if (subtype == VSASSIGN || subtype == VSQUESTION) {
6250 if (subevalvar(p, var, /* strloc: */ 0,
6251 subtype, startloc, varflags,
6257 * Remove any recorded regions beyond
6260 removerecordregions(startloc);
6270 if (varlen < 0 && uflag)
6271 varunset(p, var, 0, 0);
6273 if (subtype == VSLENGTH) {
6274 cvtnum(varlen > 0 ? varlen : 0);
6278 if (subtype == VSNORMAL) {
6289 case VSTRIMRIGHTMAX:
6290 #if ENABLE_ASH_BASH_COMPAT
6303 * Terminate the string and start recording the pattern
6306 STPUTC('\0', expdest);
6307 patloc = expdest - (char *)stackblock();
6308 if (0 == subevalvar(p, /* str: */ NULL, patloc, subtype,
6310 /* quotes: */ flag & (EXP_FULL | EXP_CASE),
6313 int amount = expdest - (
6314 (char *)stackblock() + patloc - 1
6316 STADJUST(-amount, expdest);
6318 /* Remove any recorded regions beyond start of variable */
6319 removerecordregions(startloc);
6321 recordregion(startloc, expdest - (char *)stackblock(), quoted);
6325 if (subtype != VSNORMAL) { /* skip to end of alternative */
6331 else if (c == CTLBACKQ || c == (CTLBACKQ|CTLQUOTE)) {
6333 argbackq = argbackq->next;
6334 } else if (c == CTLVAR) {
6335 if ((*p++ & VSTYPE) != VSNORMAL)
6337 } else if (c == CTLENDVAR) {
6347 * Break the argument string into pieces based upon IFS and add the
6348 * strings to the argument list. The regions of the string to be
6349 * searched for IFS characters have been stored by recordregion.
6352 ifsbreakup(char *string, struct arglist *arglist)
6354 struct ifsregion *ifsp;
6359 const char *ifs, *realifs;
6364 if (ifslastp != NULL) {
6367 realifs = ifsset() ? ifsval() : defifs;
6370 p = string + ifsp->begoff;
6371 nulonly = ifsp->nulonly;
6372 ifs = nulonly ? nullstr : realifs;
6374 while (p < string + ifsp->endoff) {
6378 if (!strchr(ifs, *p)) {
6383 ifsspc = (strchr(defifs, *p) != NULL);
6384 /* Ignore IFS whitespace at start */
6385 if (q == start && ifsspc) {
6391 sp = stzalloc(sizeof(*sp));
6393 *arglist->lastp = sp;
6394 arglist->lastp = &sp->next;
6398 if (p >= string + ifsp->endoff) {
6404 if (strchr(ifs, *p) == NULL) {
6408 if (strchr(defifs, *p) == NULL) {
6423 } while (ifsp != NULL);
6432 sp = stzalloc(sizeof(*sp));
6434 *arglist->lastp = sp;
6435 arglist->lastp = &sp->next;
6441 struct ifsregion *p;
6446 struct ifsregion *ifsp;
6452 ifsfirst.next = NULL;
6457 * Add a file name to the list.
6460 addfname(const char *name)
6464 sp = stzalloc(sizeof(*sp));
6465 sp->text = ststrdup(name);
6467 exparg.lastp = &sp->next;
6470 static char *expdir;
6473 * Do metacharacter (i.e. *, ?, [...]) expansion.
6476 expmeta(char *enddir, char *name)
6491 for (p = name; *p; p++) {
6492 if (*p == '*' || *p == '?')
6494 else if (*p == '[') {
6501 if (*q == '/' || *q == '\0')
6508 } else if (*p == '\\')
6510 else if (*p == '/') {
6517 if (metaflag == 0) { /* we've reached the end of the file name */
6518 if (enddir != expdir)
6526 if (metaflag == 0 || lstat(expdir, &statb) >= 0)
6537 } while (p < start);
6539 if (enddir == expdir) {
6541 } else if (enddir == expdir + 1 && *expdir == '/') {
6550 if (enddir != expdir)
6552 if (*endname == 0) {
6564 while (!intpending && (dp = readdir(dirp)) != NULL) {
6565 if (dp->d_name[0] == '.' && ! matchdot)
6567 if (pmatch(start, dp->d_name)) {
6569 strcpy(enddir, dp->d_name);
6572 for (p = enddir, cp = dp->d_name; (*p++ = *cp++) != '\0';)
6575 expmeta(p, endname);
6584 static struct strlist *
6585 msort(struct strlist *list, int len)
6587 struct strlist *p, *q = NULL;
6588 struct strlist **lpp;
6596 for (n = half; --n >= 0;) {
6600 q->next = NULL; /* terminate first half of list */
6601 q = msort(list, half); /* sort first half of list */
6602 p = msort(p, len - half); /* sort second half */
6605 #if ENABLE_LOCALE_SUPPORT
6606 if (strcoll(p->text, q->text) < 0)
6608 if (strcmp(p->text, q->text) < 0)
6632 * Sort the results of file name expansion. It calculates the number of
6633 * strings to sort and then calls msort (short for merge sort) to do the
6636 static struct strlist *
6637 expsort(struct strlist *str)
6643 for (sp = str; sp; sp = sp->next)
6645 return msort(str, len);
6649 expandmeta(struct strlist *str /*, int flag*/)
6651 static const char metachars[] ALIGN1 = {
6654 /* TODO - EXP_REDIR */
6657 struct strlist **savelastp;
6663 if (!strpbrk(str->text, metachars))
6665 savelastp = exparg.lastp;
6668 p = preglob(str->text, 0, RMESCAPE_ALLOC | RMESCAPE_HEAP);
6670 int i = strlen(str->text);
6671 expdir = ckmalloc(i < 2048 ? 2048 : i); /* XXX */
6679 if (exparg.lastp == savelastp) {
6684 *exparg.lastp = str;
6685 rmescapes(str->text);
6686 exparg.lastp = &str->next;
6688 *exparg.lastp = NULL;
6689 *savelastp = sp = expsort(*savelastp);
6690 while (sp->next != NULL)
6692 exparg.lastp = &sp->next;
6699 * Perform variable substitution and command substitution on an argument,
6700 * placing the resulting list of arguments in arglist. If EXP_FULL is true,
6701 * perform splitting and file name expansion. When arglist is NULL, perform
6702 * here document expansion.
6705 expandarg(union node *arg, struct arglist *arglist, int flag)
6710 argbackq = arg->narg.backquote;
6711 STARTSTACKSTR(expdest);
6712 ifsfirst.next = NULL;
6714 argstr(arg->narg.text, flag,
6715 /* var_str_list: */ arglist ? arglist->list : NULL);
6716 p = _STPUTC('\0', expdest);
6718 if (arglist == NULL) {
6719 return; /* here document expanded */
6721 p = grabstackstr(p);
6722 exparg.lastp = &exparg.list;
6726 if (flag & EXP_FULL) {
6727 ifsbreakup(p, &exparg);
6728 *exparg.lastp = NULL;
6729 exparg.lastp = &exparg.list;
6730 expandmeta(exparg.list /*, flag*/);
6732 if (flag & EXP_REDIR) /*XXX - for now, just remove escapes */
6734 sp = stzalloc(sizeof(*sp));
6737 exparg.lastp = &sp->next;
6741 *exparg.lastp = NULL;
6743 *arglist->lastp = exparg.list;
6744 arglist->lastp = exparg.lastp;
6749 * Expand shell variables and backquotes inside a here document.
6752 expandhere(union node *arg, int fd)
6755 expandarg(arg, (struct arglist *)NULL, 0);
6756 full_write(fd, stackblock(), expdest - (char *)stackblock());
6760 * Returns true if the pattern matches the string.
6763 patmatch(char *pattern, const char *string)
6765 return pmatch(preglob(pattern, 0, 0), string);
6769 * See if a pattern matches in a case statement.
6772 casematch(union node *pattern, char *val)
6774 struct stackmark smark;
6777 setstackmark(&smark);
6778 argbackq = pattern->narg.backquote;
6779 STARTSTACKSTR(expdest);
6781 argstr(pattern->narg.text, EXP_TILDE | EXP_CASE,
6782 /* var_str_list: */ NULL);
6783 STACKSTRNUL(expdest);
6784 result = patmatch(stackblock(), val);
6785 popstackmark(&smark);
6790 /* ============ find_command */
6794 int (*builtin)(int, char **);
6795 /* unsigned flags; */
6797 #define IS_BUILTIN_SPECIAL(b) ((b)->name[0] & 1)
6798 /* "regular" builtins always take precedence over commands,
6799 * regardless of PATH=....%builtin... position */
6800 #define IS_BUILTIN_REGULAR(b) ((b)->name[0] & 2)
6801 #define IS_BUILTIN_ASSIGN(b) ((b)->name[0] & 4)
6804 smallint cmdtype; /* CMDxxx */
6807 /* index >= 0 for commands without path (slashes) */
6808 /* (TODO: what exactly does the value mean? PATH position?) */
6809 /* index == -1 for commands with slashes */
6810 /* index == (-2 - applet_no) for NOFORK applets */
6811 const struct builtincmd *cmd;
6812 struct funcnode *func;
6815 /* values of cmdtype */
6816 #define CMDUNKNOWN -1 /* no entry in table for command */
6817 #define CMDNORMAL 0 /* command is an executable program */
6818 #define CMDFUNCTION 1 /* command is a shell function */
6819 #define CMDBUILTIN 2 /* command is a shell builtin */
6821 /* action to find_command() */
6822 #define DO_ERR 0x01 /* prints errors */
6823 #define DO_ABS 0x02 /* checks absolute paths */
6824 #define DO_NOFUNC 0x04 /* don't return shell functions, for command */
6825 #define DO_ALTPATH 0x08 /* using alternate path */
6826 #define DO_ALTBLTIN 0x20 /* %builtin in alt. path */
6828 static void find_command(char *, struct cmdentry *, int, const char *);
6831 /* ============ Hashing commands */
6834 * When commands are first encountered, they are entered in a hash table.
6835 * This ensures that a full path search will not have to be done for them
6836 * on each invocation.
6838 * We should investigate converting to a linear search, even though that
6839 * would make the command name "hash" a misnomer.
6843 struct tblentry *next; /* next entry in hash chain */
6844 union param param; /* definition of builtin function */
6845 smallint cmdtype; /* CMDxxx */
6846 char rehash; /* if set, cd done since entry created */
6847 char cmdname[1]; /* name of command */
6850 static struct tblentry **cmdtable;
6851 #define INIT_G_cmdtable() do { \
6852 cmdtable = xzalloc(CMDTABLESIZE * sizeof(cmdtable[0])); \
6855 static int builtinloc = -1; /* index in path of %builtin, or -1 */
6859 tryexec(USE_FEATURE_SH_STANDALONE(int applet_no,) char *cmd, char **argv, char **envp)
6863 #if ENABLE_FEATURE_SH_STANDALONE
6864 if (applet_no >= 0) {
6865 if (APPLET_IS_NOEXEC(applet_no))
6866 run_applet_no_and_exit(applet_no, argv);
6867 /* re-exec ourselves with the new arguments */
6868 execve(bb_busybox_exec_path, argv, envp);
6869 /* If they called chroot or otherwise made the binary no longer
6870 * executable, fall through */
6877 execve(cmd, argv, envp);
6878 } while (errno == EINTR);
6880 execve(cmd, argv, envp);
6886 if (errno == ENOEXEC) {
6890 for (ap = argv; *ap; ap++)
6892 ap = new = ckmalloc((ap - argv + 2) * sizeof(ap[0]));
6894 ap[0] = cmd = (char *)DEFAULT_SHELL;
6897 while ((*ap++ = *argv++) != NULL)
6906 * Exec a program. Never returns. If you change this routine, you may
6907 * have to change the find_command routine as well.
6909 static void shellexec(char **, const char *, int) ATTRIBUTE_NORETURN;
6911 shellexec(char **argv, const char *path, int idx)
6917 #if ENABLE_FEATURE_SH_STANDALONE
6922 envp = listvars(VEXPORT, VUNSET, 0);
6923 if (strchr(argv[0], '/') != NULL
6924 #if ENABLE_FEATURE_SH_STANDALONE
6925 || (applet_no = find_applet_by_name(argv[0])) >= 0
6928 tryexec(USE_FEATURE_SH_STANDALONE(applet_no,) argv[0], argv, envp);
6932 while ((cmdname = padvance(&path, argv[0])) != NULL) {
6933 if (--idx < 0 && pathopt == NULL) {
6934 tryexec(USE_FEATURE_SH_STANDALONE(-1,) cmdname, argv, envp);
6935 if (errno != ENOENT && errno != ENOTDIR)
6942 /* Map to POSIX errors */
6954 exitstatus = exerrno;
6955 TRACE(("shellexec failed for %s, errno %d, suppressint %d\n",
6956 argv[0], e, suppressint));
6957 ash_msg_and_raise(EXEXEC, "%s: %s", argv[0], errmsg(e, "not found"));
6962 printentry(struct tblentry *cmdp)
6968 idx = cmdp->param.index;
6971 name = padvance(&path, cmdp->cmdname);
6973 } while (--idx >= 0);
6974 out1fmt("%s%s\n", name, (cmdp->rehash ? "*" : nullstr));
6978 * Clear out command entries. The argument specifies the first entry in
6979 * PATH which has changed.
6982 clearcmdentry(int firstchange)
6984 struct tblentry **tblp;
6985 struct tblentry **pp;
6986 struct tblentry *cmdp;
6989 for (tblp = cmdtable; tblp < &cmdtable[CMDTABLESIZE]; tblp++) {
6991 while ((cmdp = *pp) != NULL) {
6992 if ((cmdp->cmdtype == CMDNORMAL &&
6993 cmdp->param.index >= firstchange)
6994 || (cmdp->cmdtype == CMDBUILTIN &&
6995 builtinloc >= firstchange)
7008 * Locate a command in the command hash table. If "add" is nonzero,
7009 * add the command to the table if it is not already present. The
7010 * variable "lastcmdentry" is set to point to the address of the link
7011 * pointing to the entry, so that delete_cmd_entry can delete the
7014 * Interrupts must be off if called with add != 0.
7016 static struct tblentry **lastcmdentry;
7018 static struct tblentry *
7019 cmdlookup(const char *name, int add)
7021 unsigned int hashval;
7023 struct tblentry *cmdp;
7024 struct tblentry **pp;
7027 hashval = (unsigned char)*p << 4;
7029 hashval += (unsigned char)*p++;
7031 pp = &cmdtable[hashval % CMDTABLESIZE];
7032 for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
7033 if (strcmp(cmdp->cmdname, name) == 0)
7037 if (add && cmdp == NULL) {
7038 cmdp = *pp = ckzalloc(sizeof(struct tblentry)
7040 /* + 1 - already done because
7041 * tblentry::cmdname is char[1] */);
7042 /*cmdp->next = NULL; - ckzalloc did it */
7043 cmdp->cmdtype = CMDUNKNOWN;
7044 strcpy(cmdp->cmdname, name);
7051 * Delete the command entry returned on the last lookup.
7054 delete_cmd_entry(void)
7056 struct tblentry *cmdp;
7059 cmdp = *lastcmdentry;
7060 *lastcmdentry = cmdp->next;
7061 if (cmdp->cmdtype == CMDFUNCTION)
7062 freefunc(cmdp->param.func);
7068 * Add a new command entry, replacing any existing command entry for
7069 * the same name - except special builtins.
7072 addcmdentry(char *name, struct cmdentry *entry)
7074 struct tblentry *cmdp;
7076 cmdp = cmdlookup(name, 1);
7077 if (cmdp->cmdtype == CMDFUNCTION) {
7078 freefunc(cmdp->param.func);
7080 cmdp->cmdtype = entry->cmdtype;
7081 cmdp->param = entry->u;
7086 hashcmd(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED)
7088 struct tblentry **pp;
7089 struct tblentry *cmdp;
7091 struct cmdentry entry;
7094 if (nextopt("r") != '\0') {
7099 if (*argptr == NULL) {
7100 for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
7101 for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
7102 if (cmdp->cmdtype == CMDNORMAL)
7110 while ((name = *argptr) != NULL) {
7111 cmdp = cmdlookup(name, 0);
7113 && (cmdp->cmdtype == CMDNORMAL
7114 || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0))
7118 find_command(name, &entry, DO_ERR, pathval());
7119 if (entry.cmdtype == CMDUNKNOWN)
7127 * Called when a cd is done. Marks all commands so the next time they
7128 * are executed they will be rehashed.
7133 struct tblentry **pp;
7134 struct tblentry *cmdp;
7136 for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
7137 for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
7138 if (cmdp->cmdtype == CMDNORMAL
7139 || (cmdp->cmdtype == CMDBUILTIN
7140 && !IS_BUILTIN_REGULAR(cmdp->param.cmd)
7150 * Fix command hash table when PATH changed.
7151 * Called before PATH is changed. The argument is the new value of PATH;
7152 * pathval() still returns the old value at this point.
7153 * Called with interrupts off.
7156 changepath(const char *new)
7164 firstchange = 9999; /* assume no change */
7170 if ((*old == '\0' && *new == ':')
7171 || (*old == ':' && *new == '\0'))
7173 old = new; /* ignore subsequent differences */
7177 if (*new == '%' && idx_bltin < 0 && prefix(new + 1, "builtin"))
7183 if (builtinloc < 0 && idx_bltin >= 0)
7184 builtinloc = idx_bltin; /* zap builtins */
7185 if (builtinloc >= 0 && idx_bltin < 0)
7187 clearcmdentry(firstchange);
7188 builtinloc = idx_bltin;
7203 #define TENDBQUOTE 12
7220 typedef smallint token_id_t;
7222 /* first char is indicating which tokens mark the end of a list */
7223 static const char *const tokname_array[] = {
7237 #define KWDOFFSET 13
7238 /* the following are keywords */
7260 static char buf[16];
7263 //if (tok < TSEMI) return tokname_array[tok] + 1;
7264 //sprintf(buf, "\"%s\"", tokname_array[tok] + 1);
7269 sprintf(buf + (tok >= TSEMI), "%s%c",
7270 tokname_array[tok] + 1, (tok >= TSEMI ? '"' : 0));
7274 /* Wrapper around strcmp for qsort/bsearch/... */
7276 pstrcmp(const void *a, const void *b)
7278 return strcmp((char*) a, (*(char**) b) + 1);
7281 static const char *const *
7282 findkwd(const char *s)
7284 return bsearch(s, tokname_array + KWDOFFSET,
7285 ARRAY_SIZE(tokname_array) - KWDOFFSET,
7286 sizeof(tokname_array[0]), pstrcmp);
7290 * Locate and print what a word is...
7293 describe_command(char *command, int describe_command_verbose)
7295 struct cmdentry entry;
7296 struct tblentry *cmdp;
7297 #if ENABLE_ASH_ALIAS
7298 const struct alias *ap;
7300 const char *path = pathval();
7302 if (describe_command_verbose) {
7306 /* First look at the keywords */
7307 if (findkwd(command)) {
7308 out1str(describe_command_verbose ? " is a shell keyword" : command);
7312 #if ENABLE_ASH_ALIAS
7313 /* Then look at the aliases */
7314 ap = lookupalias(command, 0);
7316 if (!describe_command_verbose) {
7321 out1fmt(" is an alias for %s", ap->val);
7325 /* Then check if it is a tracked alias */
7326 cmdp = cmdlookup(command, 0);
7328 entry.cmdtype = cmdp->cmdtype;
7329 entry.u = cmdp->param;
7331 /* Finally use brute force */
7332 find_command(command, &entry, DO_ABS, path);
7335 switch (entry.cmdtype) {
7337 int j = entry.u.index;
7343 p = padvance(&path, command);
7347 if (describe_command_verbose) {
7349 (cmdp ? " a tracked alias for" : nullstr), p
7358 if (describe_command_verbose) {
7359 out1str(" is a shell function");
7366 if (describe_command_verbose) {
7367 out1fmt(" is a %sshell builtin",
7368 IS_BUILTIN_SPECIAL(entry.u.cmd) ?
7369 "special " : nullstr
7377 if (describe_command_verbose) {
7378 out1str(": not found\n");
7383 outstr("\n", stdout);
7388 typecmd(int argc ATTRIBUTE_UNUSED, char **argv)
7394 /* type -p ... ? (we don't bother checking for 'p') */
7395 if (argv[1] && argv[1][0] == '-') {
7400 err |= describe_command(argv[i++], verbose);
7405 #if ENABLE_ASH_CMDCMD
7407 commandcmd(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED)
7415 while ((c = nextopt("pvV")) != '\0')
7417 verify |= VERIFY_VERBOSE;
7419 verify |= VERIFY_BRIEF;
7425 return describe_command(*argptr, verify - VERIFY_BRIEF);
7432 /* ============ eval.c */
7434 static int funcblocksize; /* size of structures in function */
7435 static int funcstringsize; /* size of strings in node */
7436 static void *funcblock; /* block to allocate function from */
7437 static char *funcstring; /* block to allocate strings from */
7439 /* flags in argument to evaltree */
7440 #define EV_EXIT 01 /* exit after evaluating tree */
7441 #define EV_TESTED 02 /* exit status is checked; ignore -e flag */
7442 #define EV_BACKCMD 04 /* command executing within back quotes */
7444 static const short nodesize[26] = {
7445 SHELL_ALIGN(sizeof(struct ncmd)),
7446 SHELL_ALIGN(sizeof(struct npipe)),
7447 SHELL_ALIGN(sizeof(struct nredir)),
7448 SHELL_ALIGN(sizeof(struct nredir)),
7449 SHELL_ALIGN(sizeof(struct nredir)),
7450 SHELL_ALIGN(sizeof(struct nbinary)),
7451 SHELL_ALIGN(sizeof(struct nbinary)),
7452 SHELL_ALIGN(sizeof(struct nbinary)),
7453 SHELL_ALIGN(sizeof(struct nif)),
7454 SHELL_ALIGN(sizeof(struct nbinary)),
7455 SHELL_ALIGN(sizeof(struct nbinary)),
7456 SHELL_ALIGN(sizeof(struct nfor)),
7457 SHELL_ALIGN(sizeof(struct ncase)),
7458 SHELL_ALIGN(sizeof(struct nclist)),
7459 SHELL_ALIGN(sizeof(struct narg)),
7460 SHELL_ALIGN(sizeof(struct narg)),
7461 SHELL_ALIGN(sizeof(struct nfile)),
7462 SHELL_ALIGN(sizeof(struct nfile)),
7463 SHELL_ALIGN(sizeof(struct nfile)),
7464 SHELL_ALIGN(sizeof(struct nfile)),
7465 SHELL_ALIGN(sizeof(struct nfile)),
7466 SHELL_ALIGN(sizeof(struct ndup)),
7467 SHELL_ALIGN(sizeof(struct ndup)),
7468 SHELL_ALIGN(sizeof(struct nhere)),
7469 SHELL_ALIGN(sizeof(struct nhere)),
7470 SHELL_ALIGN(sizeof(struct nnot)),
7473 static void calcsize(union node *n);
7476 sizenodelist(struct nodelist *lp)
7479 funcblocksize += SHELL_ALIGN(sizeof(struct nodelist));
7486 calcsize(union node *n)
7490 funcblocksize += nodesize[n->type];
7493 calcsize(n->ncmd.redirect);
7494 calcsize(n->ncmd.args);
7495 calcsize(n->ncmd.assign);
7498 sizenodelist(n->npipe.cmdlist);
7503 calcsize(n->nredir.redirect);
7504 calcsize(n->nredir.n);
7511 calcsize(n->nbinary.ch2);
7512 calcsize(n->nbinary.ch1);
7515 calcsize(n->nif.elsepart);
7516 calcsize(n->nif.ifpart);
7517 calcsize(n->nif.test);
7520 funcstringsize += strlen(n->nfor.var) + 1;
7521 calcsize(n->nfor.body);
7522 calcsize(n->nfor.args);
7525 calcsize(n->ncase.cases);
7526 calcsize(n->ncase.expr);
7529 calcsize(n->nclist.body);
7530 calcsize(n->nclist.pattern);
7531 calcsize(n->nclist.next);
7535 sizenodelist(n->narg.backquote);
7536 funcstringsize += strlen(n->narg.text) + 1;
7537 calcsize(n->narg.next);
7544 calcsize(n->nfile.fname);
7545 calcsize(n->nfile.next);
7549 calcsize(n->ndup.vname);
7550 calcsize(n->ndup.next);
7554 calcsize(n->nhere.doc);
7555 calcsize(n->nhere.next);
7558 calcsize(n->nnot.com);
7564 nodeckstrdup(char *s)
7566 char *rtn = funcstring;
7568 strcpy(funcstring, s);
7569 funcstring += strlen(s) + 1;
7573 static union node *copynode(union node *);
7575 static struct nodelist *
7576 copynodelist(struct nodelist *lp)
7578 struct nodelist *start;
7579 struct nodelist **lpp;
7584 funcblock = (char *) funcblock + SHELL_ALIGN(sizeof(struct nodelist));
7585 (*lpp)->n = copynode(lp->n);
7587 lpp = &(*lpp)->next;
7594 copynode(union node *n)
7601 funcblock = (char *) funcblock + nodesize[n->type];
7605 new->ncmd.redirect = copynode(n->ncmd.redirect);
7606 new->ncmd.args = copynode(n->ncmd.args);
7607 new->ncmd.assign = copynode(n->ncmd.assign);
7610 new->npipe.cmdlist = copynodelist(n->npipe.cmdlist);
7611 new->npipe.backgnd = n->npipe.backgnd;
7616 new->nredir.redirect = copynode(n->nredir.redirect);
7617 new->nredir.n = copynode(n->nredir.n);
7624 new->nbinary.ch2 = copynode(n->nbinary.ch2);
7625 new->nbinary.ch1 = copynode(n->nbinary.ch1);
7628 new->nif.elsepart = copynode(n->nif.elsepart);
7629 new->nif.ifpart = copynode(n->nif.ifpart);
7630 new->nif.test = copynode(n->nif.test);
7633 new->nfor.var = nodeckstrdup(n->nfor.var);
7634 new->nfor.body = copynode(n->nfor.body);
7635 new->nfor.args = copynode(n->nfor.args);
7638 new->ncase.cases = copynode(n->ncase.cases);
7639 new->ncase.expr = copynode(n->ncase.expr);
7642 new->nclist.body = copynode(n->nclist.body);
7643 new->nclist.pattern = copynode(n->nclist.pattern);
7644 new->nclist.next = copynode(n->nclist.next);
7648 new->narg.backquote = copynodelist(n->narg.backquote);
7649 new->narg.text = nodeckstrdup(n->narg.text);
7650 new->narg.next = copynode(n->narg.next);
7657 new->nfile.fname = copynode(n->nfile.fname);
7658 new->nfile.fd = n->nfile.fd;
7659 new->nfile.next = copynode(n->nfile.next);
7663 new->ndup.vname = copynode(n->ndup.vname);
7664 new->ndup.dupfd = n->ndup.dupfd;
7665 new->ndup.fd = n->ndup.fd;
7666 new->ndup.next = copynode(n->ndup.next);
7670 new->nhere.doc = copynode(n->nhere.doc);
7671 new->nhere.fd = n->nhere.fd;
7672 new->nhere.next = copynode(n->nhere.next);
7675 new->nnot.com = copynode(n->nnot.com);
7678 new->type = n->type;
7683 * Make a copy of a parse tree.
7685 static struct funcnode *
7686 copyfunc(union node *n)
7691 funcblocksize = offsetof(struct funcnode, n);
7694 blocksize = funcblocksize;
7695 f = ckmalloc(blocksize + funcstringsize);
7696 funcblock = (char *) f + offsetof(struct funcnode, n);
7697 funcstring = (char *) f + blocksize;
7704 * Define a shell function.
7707 defun(char *name, union node *func)
7709 struct cmdentry entry;
7712 entry.cmdtype = CMDFUNCTION;
7713 entry.u.func = copyfunc(func);
7714 addcmdentry(name, &entry);
7718 static int evalskip; /* set if we are skipping commands */
7719 /* reasons for skipping commands (see comment on breakcmd routine) */
7720 #define SKIPBREAK (1 << 0)
7721 #define SKIPCONT (1 << 1)
7722 #define SKIPFUNC (1 << 2)
7723 #define SKIPFILE (1 << 3)
7724 #define SKIPEVAL (1 << 4)
7725 static int skipcount; /* number of levels to skip */
7726 static int funcnest; /* depth of function calls */
7727 static int loopnest; /* current loop nesting level */
7729 /* forward decl way out to parsing code - dotrap needs it */
7730 static int evalstring(char *s, int mask);
7733 * Called to execute a trap. Perhaps we should avoid entering new trap
7734 * handlers while we are executing a trap handler.
7745 savestatus = exitstatus;
7749 for (i = 0, q = gotsig; i < NSIG - 1; i++, q++) {
7757 skip = evalstring(p, SKIPEVAL);
7758 exitstatus = savestatus;
7766 /* forward declarations - evaluation is fairly recursive business... */
7767 static void evalloop(union node *, int);
7768 static void evalfor(union node *, int);
7769 static void evalcase(union node *, int);
7770 static void evalsubshell(union node *, int);
7771 static void expredir(union node *);
7772 static void evalpipe(union node *, int);
7773 static void evalcommand(union node *, int);
7774 static int evalbltin(const struct builtincmd *, int, char **);
7775 static void prehash(union node *);
7778 * Evaluate a parse tree. The value is left in the global variable
7782 evaltree(union node *n, int flags)
7785 void (*evalfn)(union node *, int);
7789 TRACE(("evaltree(NULL) called\n"));
7792 TRACE(("pid %d, evaltree(%p: %d, %d) called\n",
7793 getpid(), n, n->type, flags));
7797 out1fmt("Node type = %d\n", n->type);
7802 evaltree(n->nnot.com, EV_TESTED);
7803 status = !exitstatus;
7806 expredir(n->nredir.redirect);
7807 status = redirectsafe(n->nredir.redirect, REDIR_PUSH);
7809 evaltree(n->nredir.n, flags & EV_TESTED);
7810 status = exitstatus;
7815 evalfn = evalcommand;
7817 if (eflag && !(flags & EV_TESTED))
7829 evalfn = evalsubshell;
7841 #error NAND + 1 != NOR
7843 #if NOR + 1 != NSEMI
7844 #error NOR + 1 != NSEMI
7846 isor = n->type - NAND;
7849 (flags | ((isor >> 1) - 1)) & EV_TESTED
7851 if (!exitstatus == isor)
7863 evaltree(n->nif.test, EV_TESTED);
7866 if (exitstatus == 0) {
7869 } else if (n->nif.elsepart) {
7870 n = n->nif.elsepart;
7875 defun(n->narg.text, n->narg.next);
7879 exitstatus = status;
7883 if ((checkexit & exitstatus))
7884 evalskip |= SKIPEVAL;
7885 else if (pendingsig && dotrap())
7888 if (flags & EV_EXIT) {
7890 raise_exception(EXEXIT);
7894 #if !defined(__alpha__) || (defined(__GNUC__) && __GNUC__ >= 3)
7897 void evaltreenr(union node *, int) __attribute__ ((alias("evaltree"),__noreturn__));
7900 evalloop(union node *n, int flags)
7910 evaltree(n->nbinary.ch1, EV_TESTED);
7913 if (evalskip == SKIPCONT && --skipcount <= 0) {
7917 if (evalskip == SKIPBREAK && --skipcount <= 0)
7922 if (n->type != NWHILE)
7926 evaltree(n->nbinary.ch2, flags);
7927 status = exitstatus;
7932 exitstatus = status;
7936 evalfor(union node *n, int flags)
7938 struct arglist arglist;
7941 struct stackmark smark;
7943 setstackmark(&smark);
7944 arglist.list = NULL;
7945 arglist.lastp = &arglist.list;
7946 for (argp = n->nfor.args; argp; argp = argp->narg.next) {
7947 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE | EXP_RECORD);
7952 *arglist.lastp = NULL;
7957 for (sp = arglist.list; sp; sp = sp->next) {
7958 setvar(n->nfor.var, sp->text, 0);
7959 evaltree(n->nfor.body, flags);
7961 if (evalskip == SKIPCONT && --skipcount <= 0) {
7965 if (evalskip == SKIPBREAK && --skipcount <= 0)
7972 popstackmark(&smark);
7976 evalcase(union node *n, int flags)
7980 struct arglist arglist;
7981 struct stackmark smark;
7983 setstackmark(&smark);
7984 arglist.list = NULL;
7985 arglist.lastp = &arglist.list;
7986 expandarg(n->ncase.expr, &arglist, EXP_TILDE);
7988 for (cp = n->ncase.cases; cp && evalskip == 0; cp = cp->nclist.next) {
7989 for (patp = cp->nclist.pattern; patp; patp = patp->narg.next) {
7990 if (casematch(patp, arglist.list->text)) {
7991 if (evalskip == 0) {
7992 evaltree(cp->nclist.body, flags);
7999 popstackmark(&smark);
8003 * Kick off a subshell to evaluate a tree.
8006 evalsubshell(union node *n, int flags)
8009 int backgnd = (n->type == NBACKGND);
8012 expredir(n->nredir.redirect);
8013 if (!backgnd && flags & EV_EXIT && !trap[0])
8016 jp = makejob(/*n,*/ 1);
8017 if (forkshell(jp, n, backgnd) == 0) {
8021 flags &=~ EV_TESTED;
8023 redirect(n->nredir.redirect, 0);
8024 evaltreenr(n->nredir.n, flags);
8029 status = waitforjob(jp);
8030 exitstatus = status;
8035 * Compute the names of the files in a redirection list.
8037 static void fixredir(union node *, const char *, int);
8039 expredir(union node *n)
8043 for (redir = n; redir; redir = redir->nfile.next) {
8047 fn.lastp = &fn.list;
8048 switch (redir->type) {
8054 expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
8055 redir->nfile.expfname = fn.list->text;
8059 if (redir->ndup.vname) {
8060 expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE);
8061 if (fn.list == NULL)
8062 ash_msg_and_raise_error("redir error");
8063 fixredir(redir, fn.list->text, 1);
8071 * Evaluate a pipeline. All the processes in the pipeline are children
8072 * of the process creating the pipeline. (This differs from some versions
8073 * of the shell, which make the last process in a pipeline the parent
8077 evalpipe(union node *n, int flags)
8080 struct nodelist *lp;
8085 TRACE(("evalpipe(0x%lx) called\n", (long)n));
8087 for (lp = n->npipe.cmdlist; lp; lp = lp->next)
8091 jp = makejob(/*n,*/ pipelen);
8093 for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
8097 if (pipe(pip) < 0) {
8099 ash_msg_and_raise_error("pipe call failed");
8102 if (forkshell(jp, lp->n, n->npipe.backgnd) == 0) {
8115 evaltreenr(lp->n, flags);
8123 if (n->npipe.backgnd == 0) {
8124 exitstatus = waitforjob(jp);
8125 TRACE(("evalpipe: job done exit status %d\n", exitstatus));
8131 * Controls whether the shell is interactive or not.
8134 setinteractive(int on)
8136 static smallint is_interactive;
8138 if (++on == is_interactive)
8140 is_interactive = on;
8144 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
8145 if (is_interactive > 1) {
8146 /* Looks like they want an interactive shell */
8147 static smallint did_banner;
8152 "%s built-in shell (ash)\n"
8153 "Enter 'help' for a list of built-in commands."
8168 setinteractive(iflag);
8170 #if ENABLE_FEATURE_EDITING_VI
8172 line_input_state->flags |= VI_MODE;
8174 line_input_state->flags &= ~VI_MODE;
8176 viflag = 0; /* forcibly keep the option off */
8180 static struct localvar *localvars;
8183 * Called after a function returns.
8184 * Interrupts must be off.
8189 struct localvar *lvp;
8192 while ((lvp = localvars) != NULL) {
8193 localvars = lvp->next;
8195 TRACE(("poplocalvar %s", vp ? vp->text : "-"));
8196 if (vp == NULL) { /* $- saved */
8197 memcpy(optlist, lvp->text, sizeof(optlist));
8198 free((char*)lvp->text);
8200 } else if ((lvp->flags & (VUNSET|VSTRFIXED)) == VUNSET) {
8204 (*vp->func)(strchrnul(lvp->text, '=') + 1);
8205 if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
8206 free((char*)vp->text);
8207 vp->flags = lvp->flags;
8208 vp->text = lvp->text;
8215 evalfun(struct funcnode *func, int argc, char **argv, int flags)
8217 volatile struct shparam saveparam;
8218 struct localvar *volatile savelocalvars;
8219 struct jmploc *volatile savehandler;
8220 struct jmploc jmploc;
8223 saveparam = shellparam;
8224 savelocalvars = localvars;
8225 e = setjmp(jmploc.loc);
8230 savehandler = exception_handler;
8231 exception_handler = &jmploc;
8233 shellparam.malloced = 0;
8237 shellparam.nparam = argc - 1;
8238 shellparam.p = argv + 1;
8239 #if ENABLE_ASH_GETOPTS
8240 shellparam.optind = 1;
8241 shellparam.optoff = -1;
8243 evaltree(&func->n, flags & EV_TESTED);
8249 localvars = savelocalvars;
8250 freeparam(&shellparam);
8251 shellparam = saveparam;
8252 exception_handler = savehandler;
8254 evalskip &= ~SKIPFUNC;
8258 #if ENABLE_ASH_CMDCMD
8260 parse_command_args(char **argv, const char **path)
8273 if (c == '-' && !*cp) {
8280 *path = bb_default_path;
8283 /* run 'typecmd' for other options */
8294 * Make a variable a local variable. When a variable is made local, it's
8295 * value and flags are saved in a localvar structure. The saved values
8296 * will be restored when the shell function returns. We handle the name
8297 * "-" as a special case.
8302 struct localvar *lvp;
8307 lvp = ckzalloc(sizeof(struct localvar));
8308 if (LONE_DASH(name)) {
8310 p = ckmalloc(sizeof(optlist));
8311 lvp->text = memcpy(p, optlist, sizeof(optlist));
8316 vpp = hashvar(name);
8317 vp = *findvar(vpp, name);
8318 eq = strchr(name, '=');
8321 setvareq(name, VSTRFIXED);
8323 setvar(name, NULL, VSTRFIXED);
8324 vp = *vpp; /* the new variable */
8325 lvp->flags = VUNSET;
8327 lvp->text = vp->text;
8328 lvp->flags = vp->flags;
8329 vp->flags |= VSTRFIXED|VTEXTFIXED;
8335 lvp->next = localvars;
8341 * The "local" command.
8344 localcmd(int argc ATTRIBUTE_UNUSED, char **argv)
8349 while ((name = *argv++) != NULL) {
8356 falsecmd(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED)
8362 truecmd(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED)
8368 execcmd(int argc ATTRIBUTE_UNUSED, char **argv)
8371 iflag = 0; /* exit on error */
8374 shellexec(argv + 1, pathval(), 0);
8380 * The return command.
8383 returncmd(int argc ATTRIBUTE_UNUSED, char **argv)
8386 * If called outside a function, do what ksh does;
8387 * skip the rest of the file.
8389 evalskip = funcnest ? SKIPFUNC : SKIPFILE;
8390 return argv[1] ? number(argv[1]) : exitstatus;
8393 /* Forward declarations for builtintab[] */
8394 static int breakcmd(int, char **);
8395 static int dotcmd(int, char **);
8396 static int evalcmd(int, char **);
8397 static int exitcmd(int, char **);
8398 static int exportcmd(int, char **);
8399 #if ENABLE_ASH_GETOPTS
8400 static int getoptscmd(int, char **);
8402 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
8403 static int helpcmd(int, char **);
8405 #if ENABLE_ASH_MATH_SUPPORT
8406 static int letcmd(int, char **);
8408 static int readcmd(int, char **);
8409 static int setcmd(int, char **);
8410 static int shiftcmd(int, char **);
8411 static int timescmd(int, char **);
8412 static int trapcmd(int, char **);
8413 static int umaskcmd(int, char **);
8414 static int unsetcmd(int, char **);
8415 static int ulimitcmd(int, char **);
8417 #define BUILTIN_NOSPEC "0"
8418 #define BUILTIN_SPECIAL "1"
8419 #define BUILTIN_REGULAR "2"
8420 #define BUILTIN_SPEC_REG "3"
8421 #define BUILTIN_ASSIGN "4"
8422 #define BUILTIN_SPEC_ASSG "5"
8423 #define BUILTIN_REG_ASSG "6"
8424 #define BUILTIN_SPEC_REG_ASSG "7"
8426 /* We do not handle [[ expr ]] bashism bash-compatibly,
8427 * we make it a synonym of [ expr ].
8428 * Basically, word splitting and pathname expansion should NOT be performed
8430 * no word splitting: a="a b"; [[ $a = "a b" ]]; echo $? should print "0"
8431 * no pathname expansion: [[ /bin/m* = "/bin/m*" ]]; echo $? should print "0"
8432 * Additional operators:
8433 * || and && should work as -o and -a
8435 * Apart from the above, [[ expr ]] should work as [ expr ]
8438 #define echocmd echo_main
8439 #define printfcmd printf_main
8440 #define testcmd test_main
8442 /* Keep these in proper order since it is searched via bsearch() */
8443 static const struct builtincmd builtintab[] = {
8444 { BUILTIN_SPEC_REG ".", dotcmd },
8445 { BUILTIN_SPEC_REG ":", truecmd },
8446 #if ENABLE_ASH_BUILTIN_TEST
8447 { BUILTIN_REGULAR "[", testcmd },
8448 #if ENABLE_ASH_BASH_COMPAT
8449 { BUILTIN_REGULAR "[[", testcmd },
8452 #if ENABLE_ASH_ALIAS
8453 { BUILTIN_REG_ASSG "alias", aliascmd },
8456 { BUILTIN_REGULAR "bg", fg_bgcmd },
8458 { BUILTIN_SPEC_REG "break", breakcmd },
8459 { BUILTIN_REGULAR "cd", cdcmd },
8460 { BUILTIN_NOSPEC "chdir", cdcmd },
8461 #if ENABLE_ASH_CMDCMD
8462 { BUILTIN_REGULAR "command", commandcmd },
8464 { BUILTIN_SPEC_REG "continue", breakcmd },
8465 #if ENABLE_ASH_BUILTIN_ECHO
8466 { BUILTIN_REGULAR "echo", echocmd },
8468 { BUILTIN_SPEC_REG "eval", evalcmd },
8469 { BUILTIN_SPEC_REG "exec", execcmd },
8470 { BUILTIN_SPEC_REG "exit", exitcmd },
8471 { BUILTIN_SPEC_REG_ASSG "export", exportcmd },
8472 { BUILTIN_REGULAR "false", falsecmd },
8474 { BUILTIN_REGULAR "fg", fg_bgcmd },
8476 #if ENABLE_ASH_GETOPTS
8477 { BUILTIN_REGULAR "getopts", getoptscmd },
8479 { BUILTIN_NOSPEC "hash", hashcmd },
8480 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
8481 { BUILTIN_NOSPEC "help", helpcmd },
8484 { BUILTIN_REGULAR "jobs", jobscmd },
8485 { BUILTIN_REGULAR "kill", killcmd },
8487 #if ENABLE_ASH_MATH_SUPPORT
8488 { BUILTIN_NOSPEC "let", letcmd },
8490 { BUILTIN_ASSIGN "local", localcmd },
8491 #if ENABLE_ASH_BUILTIN_PRINTF
8492 { BUILTIN_REGULAR "printf", printfcmd },
8494 { BUILTIN_NOSPEC "pwd", pwdcmd },
8495 { BUILTIN_REGULAR "read", readcmd },
8496 { BUILTIN_SPEC_REG_ASSG "readonly", exportcmd },
8497 { BUILTIN_SPEC_REG "return", returncmd },
8498 { BUILTIN_SPEC_REG "set", setcmd },
8499 { BUILTIN_SPEC_REG "shift", shiftcmd },
8500 { BUILTIN_SPEC_REG "source", dotcmd },
8501 #if ENABLE_ASH_BUILTIN_TEST
8502 { BUILTIN_REGULAR "test", testcmd },
8504 { BUILTIN_SPEC_REG "times", timescmd },
8505 { BUILTIN_SPEC_REG "trap", trapcmd },
8506 { BUILTIN_REGULAR "true", truecmd },
8507 { BUILTIN_NOSPEC "type", typecmd },
8508 { BUILTIN_NOSPEC "ulimit", ulimitcmd },
8509 { BUILTIN_REGULAR "umask", umaskcmd },
8510 #if ENABLE_ASH_ALIAS
8511 { BUILTIN_REGULAR "unalias", unaliascmd },
8513 { BUILTIN_SPEC_REG "unset", unsetcmd },
8514 { BUILTIN_REGULAR "wait", waitcmd },
8517 /* Should match the above table! */
8518 #define COMMANDCMD (builtintab + \
8520 1 * ENABLE_ASH_BUILTIN_TEST + \
8521 1 * ENABLE_ASH_BUILTIN_TEST * ENABLE_ASH_BASH_COMPAT + \
8522 1 * ENABLE_ASH_ALIAS + \
8523 1 * ENABLE_ASH_JOB_CONTROL + \
8525 #define EXECCMD (builtintab + \
8527 1 * ENABLE_ASH_BUILTIN_TEST + \
8528 1 * ENABLE_ASH_BUILTIN_TEST * ENABLE_ASH_BASH_COMPAT + \
8529 1 * ENABLE_ASH_ALIAS + \
8530 1 * ENABLE_ASH_JOB_CONTROL + \
8532 1 * ENABLE_ASH_CMDCMD + \
8534 ENABLE_ASH_BUILTIN_ECHO + \
8538 * Search the table of builtin commands.
8540 static struct builtincmd *
8541 find_builtin(const char *name)
8543 struct builtincmd *bp;
8546 name, builtintab, ARRAY_SIZE(builtintab), sizeof(builtintab[0]),
8553 * Execute a simple command.
8556 isassignment(const char *p)
8558 const char *q = endofname(p);
8564 bltincmd(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED)
8566 /* Preserve exitstatus of a previous possible redirection
8567 * as POSIX mandates */
8568 return back_exitstatus;
8571 evalcommand(union node *cmd, int flags)
8573 static const struct builtincmd null_bltin = {
8574 "\0\0", bltincmd /* why three NULs? */
8576 struct stackmark smark;
8578 struct arglist arglist;
8579 struct arglist varlist;
8582 const struct strlist *sp;
8583 struct cmdentry cmdentry;
8591 struct builtincmd *bcmd;
8592 int pseudovarflag = 0;
8594 /* First expand the arguments. */
8595 TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
8596 setstackmark(&smark);
8597 back_exitstatus = 0;
8599 cmdentry.cmdtype = CMDBUILTIN;
8600 cmdentry.u.cmd = &null_bltin;
8601 varlist.lastp = &varlist.list;
8602 *varlist.lastp = NULL;
8603 arglist.lastp = &arglist.list;
8604 *arglist.lastp = NULL;
8607 if (cmd->ncmd.args) {
8608 bcmd = find_builtin(cmd->ncmd.args->narg.text);
8609 pseudovarflag = bcmd && IS_BUILTIN_ASSIGN(bcmd);
8612 for (argp = cmd->ncmd.args; argp; argp = argp->narg.next) {
8613 struct strlist **spp;
8615 spp = arglist.lastp;
8616 if (pseudovarflag && isassignment(argp->narg.text))
8617 expandarg(argp, &arglist, EXP_VARTILDE);
8619 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
8621 for (sp = *spp; sp; sp = sp->next)
8625 argv = nargv = stalloc(sizeof(char *) * (argc + 1));
8626 for (sp = arglist.list; sp; sp = sp->next) {
8627 TRACE(("evalcommand arg: %s\n", sp->text));
8628 *nargv++ = sp->text;
8633 if (iflag && funcnest == 0 && argc > 0)
8634 lastarg = nargv[-1];
8637 expredir(cmd->ncmd.redirect);
8638 status = redirectsafe(cmd->ncmd.redirect, REDIR_PUSH | REDIR_SAVEFD2);
8641 for (argp = cmd->ncmd.assign; argp; argp = argp->narg.next) {
8642 struct strlist **spp;
8645 spp = varlist.lastp;
8646 expandarg(argp, &varlist, EXP_VARTILDE);
8649 * Modify the command lookup path, if a PATH= assignment
8653 if (varequal(p, path))
8657 /* Print the command if xflag is set. */
8660 const char *p = " %s";
8663 fdprintf(preverrout_fd, p, expandstr(ps4val()));
8666 for (n = 0; n < 2; n++) {
8668 fdprintf(preverrout_fd, p, sp->text);
8676 safe_write(preverrout_fd, "\n", 1);
8682 /* Now locate the command. */
8684 const char *oldpath;
8685 int cmd_flag = DO_ERR;
8690 find_command(argv[0], &cmdentry, cmd_flag, path);
8691 if (cmdentry.cmdtype == CMDUNKNOWN) {
8697 /* implement bltin and command here */
8698 if (cmdentry.cmdtype != CMDBUILTIN)
8701 spclbltin = IS_BUILTIN_SPECIAL(cmdentry.u.cmd);
8702 if (cmdentry.u.cmd == EXECCMD)
8704 #if ENABLE_ASH_CMDCMD
8705 if (cmdentry.u.cmd == COMMANDCMD) {
8707 nargv = parse_command_args(argv, &path);
8710 argc -= nargv - argv;
8712 cmd_flag |= DO_NOFUNC;
8720 /* We have a redirection error. */
8722 raise_exception(EXERROR);
8724 exitstatus = status;
8728 /* Execute the command. */
8729 switch (cmdentry.cmdtype) {
8731 #if ENABLE_FEATURE_SH_NOFORK
8733 /* find_command() encodes applet_no as (-2 - applet_no) */
8734 int applet_no = (- cmdentry.u.index - 2);
8735 if (applet_no >= 0 && APPLET_IS_NOFORK(applet_no)) {
8736 listsetvar(varlist.list, VEXPORT|VSTACK);
8737 /* run <applet>_main() */
8738 exitstatus = run_nofork_applet(applet_no, argv);
8744 /* Fork off a child process if necessary. */
8745 if (!(flags & EV_EXIT) || trap[0]) {
8747 jp = makejob(/*cmd,*/ 1);
8748 if (forkshell(jp, cmd, FORK_FG) != 0) {
8749 exitstatus = waitforjob(jp);
8755 listsetvar(varlist.list, VEXPORT|VSTACK);
8756 shellexec(argv, path, cmdentry.u.index);
8760 cmdenviron = varlist.list;
8762 struct strlist *list = cmdenviron;
8764 if (spclbltin > 0 || argc == 0) {
8766 if (cmd_is_exec && argc > 1)
8769 listsetvar(list, i);
8771 if (evalbltin(cmdentry.u.cmd, argc, argv)) {
8778 exit_status = 128 + SIGINT;
8780 exit_status = 128 + pendingsig;
8781 exitstatus = exit_status;
8782 if (i == EXINT || spclbltin > 0) {
8784 longjmp(exception_handler->loc, 1);
8791 listsetvar(varlist.list, 0);
8792 if (evalfun(cmdentry.u.func, argc, argv, flags))
8798 popredir(cmd_is_exec);
8800 /* dsl: I think this is intended to be used to support
8801 * '_' in 'vi' command mode during line editing...
8802 * However I implemented that within libedit itself.
8804 setvar("_", lastarg, 0);
8805 popstackmark(&smark);
8809 evalbltin(const struct builtincmd *cmd, int argc, char **argv)
8811 char *volatile savecmdname;
8812 struct jmploc *volatile savehandler;
8813 struct jmploc jmploc;
8816 savecmdname = commandname;
8817 i = setjmp(jmploc.loc);
8820 savehandler = exception_handler;
8821 exception_handler = &jmploc;
8822 commandname = argv[0];
8824 optptr = NULL; /* initialize nextopt */
8825 exitstatus = (*cmd->builtin)(argc, argv);
8826 flush_stdout_stderr();
8828 exitstatus |= ferror(stdout);
8830 commandname = savecmdname;
8832 exception_handler = savehandler;
8838 goodname(const char *p)
8840 return !*endofname(p);
8845 * Search for a command. This is called before we fork so that the
8846 * location of the command will be available in the parent as well as
8847 * the child. The check for "goodname" is an overly conservative
8848 * check that the name will not be subject to expansion.
8851 prehash(union node *n)
8853 struct cmdentry entry;
8855 if (n->type == NCMD && n->ncmd.args && goodname(n->ncmd.args->narg.text))
8856 find_command(n->ncmd.args->narg.text, &entry, 0, pathval());
8860 /* ============ Builtin commands
8862 * Builtin commands whose functions are closely tied to evaluation
8863 * are implemented here.
8867 * Handle break and continue commands. Break, continue, and return are
8868 * all handled by setting the evalskip flag. The evaluation routines
8869 * above all check this flag, and if it is set they start skipping
8870 * commands rather than executing them. The variable skipcount is
8871 * the number of loops to break/continue, or the number of function
8872 * levels to return. (The latter is always 1.) It should probably
8873 * be an error to break out of more loops than exist, but it isn't
8874 * in the standard shell so we don't make it one here.
8877 breakcmd(int argc ATTRIBUTE_UNUSED, char **argv)
8879 int n = argv[1] ? number(argv[1]) : 1;
8882 ash_msg_and_raise_error(illnum, argv[1]);
8886 evalskip = (**argv == 'c') ? SKIPCONT : SKIPBREAK;
8893 /* ============ input.c
8895 * This implements the input routines used by the parser.
8898 #define EOF_NLEFT -99 /* value of parsenleft when EOF pushed back */
8901 INPUT_PUSH_FILE = 1,
8902 INPUT_NOFILE_OK = 2,
8905 static int plinno = 1; /* input line number */
8906 /* number of characters left in input buffer */
8907 static int parsenleft; /* copy of parsefile->nleft */
8908 static int parselleft; /* copy of parsefile->lleft */
8909 /* next character in input buffer */
8910 static char *parsenextc; /* copy of parsefile->nextc */
8912 static smallint checkkwd;
8913 /* values of checkkwd variable */
8914 #define CHKALIAS 0x1
8921 struct strpush *sp = g_parsefile->strpush;
8924 #if ENABLE_ASH_ALIAS
8926 if (parsenextc[-1] == ' ' || parsenextc[-1] == '\t') {
8927 checkkwd |= CHKALIAS;
8929 if (sp->string != sp->ap->val) {
8932 sp->ap->flag &= ~ALIASINUSE;
8933 if (sp->ap->flag & ALIASDEAD) {
8934 unalias(sp->ap->name);
8938 parsenextc = sp->prevstring;
8939 parsenleft = sp->prevnleft;
8940 /*dprintf("*** calling popstring: restoring to '%s'\n", parsenextc);*/
8941 g_parsefile->strpush = sp->prev;
8942 if (sp != &(g_parsefile->basestrpush))
8951 char *buf = g_parsefile->buf;
8954 #if ENABLE_FEATURE_EDITING
8956 if (!iflag || g_parsefile->fd)
8957 nr = nonblock_safe_read(g_parsefile->fd, buf, BUFSIZ - 1);
8959 #if ENABLE_FEATURE_TAB_COMPLETION
8960 line_input_state->path_lookup = pathval();
8962 nr = read_line_input(cmdedit_prompt, buf, BUFSIZ, line_input_state);
8964 /* Ctrl+C pressed */
8973 if (nr < 0 && errno == 0) {
8974 /* Ctrl+D pressed */
8979 nr = nonblock_safe_read(g_parsefile->fd, buf, BUFSIZ - 1);
8983 /* nonblock_safe_read() handles this problem */
8985 if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
8986 int flags = fcntl(0, F_GETFL);
8987 if (flags >= 0 && (flags & O_NONBLOCK)) {
8988 flags &= ~O_NONBLOCK;
8989 if (fcntl(0, F_SETFL, flags) >= 0) {
8990 out2str("sh: turning off NDELAY mode\n");
9001 * Refill the input buffer and return the next input character:
9003 * 1) If a string was pushed back on the input, pop it;
9004 * 2) If an EOF was pushed back (parsenleft == EOF_NLEFT) or we are reading
9005 * from a string so we can't refill the buffer, return EOF.
9006 * 3) If the is more stuff in this buffer, use it else call read to fill it.
9007 * 4) Process input up to the next newline, deleting nul characters.
9016 while (g_parsefile->strpush) {
9017 #if ENABLE_ASH_ALIAS
9018 if (parsenleft == -1 && g_parsefile->strpush->ap &&
9019 parsenextc[-1] != ' ' && parsenextc[-1] != '\t') {
9024 if (--parsenleft >= 0)
9025 return signed_char2int(*parsenextc++);
9027 if (parsenleft == EOF_NLEFT || g_parsefile->buf == NULL)
9029 flush_stdout_stderr();
9036 parselleft = parsenleft = EOF_NLEFT;
9043 /* delete nul characters */
9051 memmove(q, q + 1, more);
9055 parsenleft = q - parsenextc - 1;
9061 parsenleft = q - parsenextc - 1;
9073 out2str(parsenextc);
9078 return signed_char2int(*parsenextc++);
9081 #define pgetc_as_macro() (--parsenleft >= 0? signed_char2int(*parsenextc++) : preadbuffer())
9085 return pgetc_as_macro();
9088 #if ENABLE_ASH_OPTIMIZE_FOR_SIZE
9089 #define pgetc_macro() pgetc()
9091 #define pgetc_macro() pgetc_as_macro()
9095 * Same as pgetc(), but ignores PEOA.
9097 #if ENABLE_ASH_ALIAS
9105 } while (c == PEOA);
9112 return pgetc_macro();
9117 * Read a line from the script.
9120 pfgets(char *line, int len)
9126 while (--nleft > 0) {
9142 * Undo the last call to pgetc. Only one character may be pushed back.
9143 * PEOF may be pushed back.
9153 * Push a string back onto the input at this current parsefile level.
9154 * We handle aliases this way.
9156 #if !ENABLE_ASH_ALIAS
9157 #define pushstring(s, ap) pushstring(s)
9160 pushstring(char *s, struct alias *ap)
9167 /*dprintf("*** calling pushstring: %s, %d\n", s, len);*/
9168 if (g_parsefile->strpush) {
9169 sp = ckzalloc(sizeof(struct strpush));
9170 sp->prev = g_parsefile->strpush;
9171 g_parsefile->strpush = sp;
9173 sp = g_parsefile->strpush = &(g_parsefile->basestrpush);
9174 sp->prevstring = parsenextc;
9175 sp->prevnleft = parsenleft;
9176 #if ENABLE_ASH_ALIAS
9179 ap->flag |= ALIASINUSE;
9189 * To handle the "." command, a stack of input files is used. Pushfile
9190 * adds a new entry to the stack and popfile restores the previous level.
9195 struct parsefile *pf;
9197 g_parsefile->nleft = parsenleft;
9198 g_parsefile->lleft = parselleft;
9199 g_parsefile->nextc = parsenextc;
9200 g_parsefile->linno = plinno;
9201 pf = ckzalloc(sizeof(*pf));
9202 pf->prev = g_parsefile;
9204 /*pf->strpush = NULL; - ckzalloc did it */
9205 /*pf->basestrpush.prev = NULL;*/
9212 struct parsefile *pf = g_parsefile;
9220 g_parsefile = pf->prev;
9222 parsenleft = g_parsefile->nleft;
9223 parselleft = g_parsefile->lleft;
9224 parsenextc = g_parsefile->nextc;
9225 plinno = g_parsefile->linno;
9230 * Return to top level.
9235 while (g_parsefile != &basepf)
9240 * Close the file(s) that the shell is reading commands from. Called
9241 * after a fork is done.
9247 if (g_parsefile->fd > 0) {
9248 close(g_parsefile->fd);
9249 g_parsefile->fd = 0;
9254 * Like setinputfile, but takes an open file descriptor. Call this with
9258 setinputfd(int fd, int push)
9260 close_on_exec_on(fd);
9263 g_parsefile->buf = 0;
9265 g_parsefile->fd = fd;
9266 if (g_parsefile->buf == NULL)
9267 g_parsefile->buf = ckmalloc(IBUFSIZ);
9268 parselleft = parsenleft = 0;
9273 * Set the input to take input from a file. If push is set, push the
9274 * old input onto the stack first.
9277 setinputfile(const char *fname, int flags)
9283 fd = open(fname, O_RDONLY);
9285 if (flags & INPUT_NOFILE_OK)
9287 ash_msg_and_raise_error("can't open %s", fname);
9290 fd2 = copyfd(fd, 10);
9293 ash_msg_and_raise_error("out of file descriptors");
9296 setinputfd(fd, flags & INPUT_PUSH_FILE);
9303 * Like setinputfile, but takes input from a string.
9306 setinputstring(char *string)
9310 parsenextc = string;
9311 parsenleft = strlen(string);
9312 g_parsefile->buf = NULL;
9318 /* ============ mail.c
9320 * Routines to check for mail.
9325 #define MAXMBOXES 10
9327 /* times of mailboxes */
9328 static time_t mailtime[MAXMBOXES];
9329 /* Set if MAIL or MAILPATH is changed. */
9330 static smallint mail_var_path_changed;
9333 * Print appropriate message(s) if mail has arrived.
9334 * If mail_var_path_changed is set,
9335 * then the value of MAIL has mail_var_path_changed,
9336 * so we just update the values.
9345 struct stackmark smark;
9348 setstackmark(&smark);
9349 mpath = mpathset() ? mpathval() : mailval();
9350 for (mtp = mailtime; mtp < mailtime + MAXMBOXES; mtp++) {
9351 p = padvance(&mpath, nullstr);
9356 for (q = p; *q; q++)
9362 q[-1] = '\0'; /* delete trailing '/' */
9363 if (stat(p, &statb) < 0) {
9367 if (!mail_var_path_changed && statb.st_mtime != *mtp) {
9370 pathopt ? pathopt : "you have mail"
9373 *mtp = statb.st_mtime;
9375 mail_var_path_changed = 0;
9376 popstackmark(&smark);
9380 changemail(const char *val ATTRIBUTE_UNUSED)
9382 mail_var_path_changed = 1;
9385 #endif /* ASH_MAIL */
9388 /* ============ ??? */
9391 * Set the shell parameters.
9394 setparam(char **argv)
9400 for (nparam = 0; argv[nparam]; nparam++)
9402 ap = newparam = ckmalloc((nparam + 1) * sizeof(*ap));
9404 *ap++ = ckstrdup(*argv++);
9407 freeparam(&shellparam);
9408 shellparam.malloced = 1;
9409 shellparam.nparam = nparam;
9410 shellparam.p = newparam;
9411 #if ENABLE_ASH_GETOPTS
9412 shellparam.optind = 1;
9413 shellparam.optoff = -1;
9418 * Process shell options. The global variable argptr contains a pointer
9419 * to the argument list; we advance it past the options.
9421 * SUSv3 section 2.8.1 "Consequences of Shell Errors" says:
9422 * For a non-interactive shell, an error condition encountered
9423 * by a special built-in ... shall cause the shell to write a diagnostic message
9424 * to standard error and exit as shown in the following table:
9425 * Error Special Built-In
9427 * Utility syntax error (option or operand error) Shall exit
9429 * However, in bug 1142 (http://busybox.net/bugs/view.php?id=1142)
9430 * we see that bash does not do that (set "finishes" with error code 1 instead,
9431 * and shell continues), and people rely on this behavior!
9433 * set -o barfoo 2>/dev/null
9436 * Oh well. Let's mimic that.
9439 plus_minus_o(char *name, int val)
9444 for (i = 0; i < NOPTS; i++) {
9445 if (strcmp(name, optnames(i)) == 0) {
9450 ash_msg("illegal option %co %s", val ? '-' : '+', name);
9453 for (i = 0; i < NOPTS; i++) {
9455 out1fmt("%-16s%s\n", optnames(i), optlist[i] ? "on" : "off");
9457 out1fmt("set %co %s\n", optlist[i] ? '-' : '+', optnames(i));
9463 setoption(int flag, int val)
9467 for (i = 0; i < NOPTS; i++) {
9468 if (optletters(i) == flag) {
9473 ash_msg_and_raise_error("illegal option %c%c", val ? '-' : '+', flag);
9477 options(int cmdline)
9485 while ((p = *argptr) != NULL) {
9487 if (c != '-' && c != '+')
9490 val = 0; /* val = 0 if c == '+' */
9493 if (p[0] == '\0' || LONE_DASH(p)) {
9495 /* "-" means turn off -x and -v */
9498 /* "--" means reset params */
9499 else if (*argptr == NULL)
9502 break; /* "-" or "--" terminates options */
9505 /* first char was + or - */
9506 while ((c = *p++) != '\0') {
9507 /* bash 3.2 indeed handles -c CMD and +c CMD the same */
9508 if (c == 'c' && cmdline) {
9509 minusc = p; /* command is after shell args */
9510 } else if (c == 'o') {
9511 if (plus_minus_o(*argptr, val)) {
9512 /* it already printed err message */
9513 return 1; /* error */
9517 } else if (cmdline && (c == 'l')) { /* -l or +l == --login */
9519 /* bash does not accept +-login, we also won't */
9520 } else if (cmdline && val && (c == '-')) { /* long options */
9521 if (strcmp(p, "login") == 0)
9533 * The shift builtin command.
9536 shiftcmd(int argc ATTRIBUTE_UNUSED, char **argv)
9543 n = number(argv[1]);
9544 if (n > shellparam.nparam)
9545 n = shellparam.nparam;
9547 shellparam.nparam -= n;
9548 for (ap1 = shellparam.p; --n >= 0; ap1++) {
9549 if (shellparam.malloced)
9553 while ((*ap2++ = *ap1++) != NULL)
9555 #if ENABLE_ASH_GETOPTS
9556 shellparam.optind = 1;
9557 shellparam.optoff = -1;
9564 * POSIX requires that 'set' (but not export or readonly) output the
9565 * variables in lexicographic order - by the locale's collating order (sigh).
9566 * Maybe we could keep them in an ordered balanced binary tree
9567 * instead of hashed lists.
9568 * For now just roll 'em through qsort for printing...
9571 showvars(const char *sep_prefix, int on, int off)
9576 ep = listvars(on, off, &epend);
9577 qsort(ep, epend - ep, sizeof(char *), vpcmp);
9579 sep = *sep_prefix ? " " : sep_prefix;
9581 for (; ep < epend; ep++) {
9585 p = strchrnul(*ep, '=');
9588 q = single_quote(++p);
9589 out1fmt("%s%s%.*s%s\n", sep_prefix, sep, (int)(p - *ep), *ep, q);
9595 * The set command builtin.
9598 setcmd(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED)
9603 return showvars(nullstr, 0, VUNSET);
9606 if (!options(0)) { /* if no parse error... */
9609 if (*argptr != NULL) {
9617 #if ENABLE_ASH_RANDOM_SUPPORT
9619 change_random(const char *value)
9621 /* Galois LFSR parameter */
9622 /* Taps at 32 31 29 1: */
9623 enum { MASK = 0x8000000b };
9624 /* Another example - taps at 32 31 30 10: */
9625 /* MASK = 0x00400007 */
9627 if (value == NULL) {
9628 /* "get", generate */
9631 /* LCG has period of 2^32 and alternating lowest bit */
9632 random_LCG = 1664525 * random_LCG + 1013904223;
9633 /* Galois LFSR has period of 2^32-1 = 3 * 5 * 17 * 257 * 65537 */
9634 t = (random_galois_LFSR << 1);
9635 if (random_galois_LFSR < 0) /* if we just shifted 1 out of msb... */
9637 random_galois_LFSR = t;
9638 /* Both are weak, combining them gives better randomness
9639 * and ~2^64 period. & 0x7fff is probably bash compat
9640 * for $RANDOM range. Combining with subtraction is
9641 * just for fun. + and ^ would work equally well. */
9642 t = (t - random_LCG) & 0x7fff;
9643 /* set without recursion */
9644 setvar(vrandom.text, utoa(t), VNOFUNC);
9645 vrandom.flags &= ~VNOFUNC;
9648 random_galois_LFSR = random_LCG = strtoul(value, (char **)NULL, 10);
9653 #if ENABLE_ASH_GETOPTS
9655 getopts(char *optstr, char *optvar, char **optfirst, int *param_optind, int *optoff)
9664 if (*param_optind < 1)
9666 optnext = optfirst + *param_optind - 1;
9668 if (*param_optind <= 1 || *optoff < 0 || (int)strlen(optnext[-1]) < *optoff)
9671 p = optnext[-1] + *optoff;
9672 if (p == NULL || *p == '\0') {
9673 /* Current word is done, advance */
9675 if (p == NULL || *p != '-' || *++p == '\0') {
9682 if (LONE_DASH(p)) /* check for "--" */
9687 for (q = optstr; *q != c;) {
9689 if (optstr[0] == ':') {
9692 err |= setvarsafe("OPTARG", s, 0);
9694 fprintf(stderr, "Illegal option -%c\n", c);
9705 if (*p == '\0' && (p = *optnext) == NULL) {
9706 if (optstr[0] == ':') {
9709 err |= setvarsafe("OPTARG", s, 0);
9712 fprintf(stderr, "No arg for -%c option\n", c);
9721 err |= setvarsafe("OPTARG", p, 0);
9724 err |= setvarsafe("OPTARG", nullstr, 0);
9726 *optoff = p ? p - *(optnext - 1) : -1;
9727 *param_optind = optnext - optfirst + 1;
9728 fmtstr(s, sizeof(s), "%d", *param_optind);
9729 err |= setvarsafe("OPTIND", s, VNOFUNC);
9732 err |= setvarsafe(optvar, s, 0);
9736 flush_stdout_stderr();
9737 raise_exception(EXERROR);
9743 * The getopts builtin. Shellparam.optnext points to the next argument
9744 * to be processed. Shellparam.optptr points to the next character to
9745 * be processed in the current argument. If shellparam.optnext is NULL,
9746 * then it's the first time getopts has been called.
9749 getoptscmd(int argc, char **argv)
9754 ash_msg_and_raise_error("usage: getopts optstring var [arg]");
9756 optbase = shellparam.p;
9757 if (shellparam.optind > shellparam.nparam + 1) {
9758 shellparam.optind = 1;
9759 shellparam.optoff = -1;
9763 if (shellparam.optind > argc - 2) {
9764 shellparam.optind = 1;
9765 shellparam.optoff = -1;
9769 return getopts(argv[1], argv[2], optbase, &shellparam.optind,
9770 &shellparam.optoff);
9772 #endif /* ASH_GETOPTS */
9775 /* ============ Shell parser */
9778 struct heredoc *next; /* next here document in list */
9779 union node *here; /* redirection node */
9780 char *eofmark; /* string indicating end of input */
9781 smallint striptabs; /* if set, strip leading tabs */
9784 static smallint tokpushback; /* last token pushed back */
9785 static smallint parsebackquote; /* nonzero if we are inside backquotes */
9786 static smallint quoteflag; /* set if (part of) last token was quoted */
9787 static token_id_t lasttoken; /* last token read (integer id Txxx) */
9788 static struct heredoc *heredoclist; /* list of here documents to read */
9789 static char *wordtext; /* text of last word returned by readtoken */
9790 static struct nodelist *backquotelist;
9791 static union node *redirnode;
9792 static struct heredoc *heredoc;
9794 * NEOF is returned by parsecmd when it encounters an end of file. It
9795 * must be distinct from NULL, so we use the address of a variable that
9796 * happens to be handy.
9798 #define NEOF ((union node *)&tokpushback)
9800 static void raise_error_syntax(const char *) ATTRIBUTE_NORETURN;
9802 raise_error_syntax(const char *msg)
9804 ash_msg_and_raise_error("syntax error: %s", msg);
9809 * Called when an unexpected token is read during the parse. The argument
9810 * is the token that is expected, or -1 if more than one type of token can
9811 * occur at this point.
9813 static void raise_error_unexpected_syntax(int) ATTRIBUTE_NORETURN;
9815 raise_error_unexpected_syntax(int token)
9820 l = sprintf(msg, "%s unexpected", tokname(lasttoken));
9822 sprintf(msg + l, " (expecting %s)", tokname(token));
9823 raise_error_syntax(msg);
9827 #define EOFMARKLEN 79
9829 /* parsing is heavily cross-recursive, need these forward decls */
9830 static union node *andor(void);
9831 static union node *pipeline(void);
9832 static union node *parse_command(void);
9833 static void parseheredoc(void);
9834 static char peektoken(void);
9835 static int readtoken(void);
9840 union node *n1, *n2, *n3;
9843 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9844 if (nlflag == 2 && peektoken())
9850 if (tok == TBACKGND) {
9851 if (n2->type == NPIPE) {
9852 n2->npipe.backgnd = 1;
9854 if (n2->type != NREDIR) {
9855 n3 = stzalloc(sizeof(struct nredir));
9857 /*n3->nredir.redirect = NULL; - stzalloc did it */
9860 n2->type = NBACKGND;
9866 n3 = stzalloc(sizeof(struct nbinary));
9868 n3->nbinary.ch1 = n1;
9869 n3->nbinary.ch2 = n2;
9885 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9893 pungetc(); /* push back EOF on input */
9897 raise_error_unexpected_syntax(-1);
9907 union node *n1, *n2, *n3;
9915 } else if (t == TOR) {
9921 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9923 n3 = stzalloc(sizeof(struct nbinary));
9925 n3->nbinary.ch1 = n1;
9926 n3->nbinary.ch2 = n2;
9934 union node *n1, *n2, *pipenode;
9935 struct nodelist *lp, *prev;
9939 TRACE(("pipeline: entered\n"));
9940 if (readtoken() == TNOT) {
9942 checkkwd = CHKKWD | CHKALIAS;
9945 n1 = parse_command();
9946 if (readtoken() == TPIPE) {
9947 pipenode = stzalloc(sizeof(struct npipe));
9948 pipenode->type = NPIPE;
9949 /*pipenode->npipe.backgnd = 0; - stzalloc did it */
9950 lp = stzalloc(sizeof(struct nodelist));
9951 pipenode->npipe.cmdlist = lp;
9955 lp = stzalloc(sizeof(struct nodelist));
9956 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9957 lp->n = parse_command();
9959 } while (readtoken() == TPIPE);
9965 n2 = stzalloc(sizeof(struct nnot));
9978 n = stzalloc(sizeof(struct narg));
9980 /*n->narg.next = NULL; - stzalloc did it */
9981 n->narg.text = wordtext;
9982 n->narg.backquote = backquotelist;
9987 fixredir(union node *n, const char *text, int err)
9989 TRACE(("Fix redir %s %d\n", text, err));
9991 n->ndup.vname = NULL;
9993 if (isdigit(text[0]) && text[1] == '\0')
9994 n->ndup.dupfd = text[0] - '0';
9995 else if (LONE_DASH(text))
9999 raise_error_syntax("Bad fd number");
10000 n->ndup.vname = makename();
10005 * Returns true if the text contains nothing to expand (no dollar signs
10009 noexpand(char *text)
10015 while ((c = *p++) != '\0') {
10016 if (c == CTLQUOTEMARK)
10020 else if (SIT(c, BASESYNTAX) == CCTL)
10029 union node *n = redirnode;
10031 if (readtoken() != TWORD)
10032 raise_error_unexpected_syntax(-1);
10033 if (n->type == NHERE) {
10034 struct heredoc *here = heredoc;
10038 if (quoteflag == 0)
10040 TRACE(("Here document %d\n", n->type));
10041 if (!noexpand(wordtext) || (i = strlen(wordtext)) == 0 || i > EOFMARKLEN)
10042 raise_error_syntax("Illegal eof marker for << redirection");
10043 rmescapes(wordtext);
10044 here->eofmark = wordtext;
10046 if (heredoclist == NULL)
10047 heredoclist = here;
10049 for (p = heredoclist; p->next; p = p->next)
10053 } else if (n->type == NTOFD || n->type == NFROMFD) {
10054 fixredir(n, wordtext, 0);
10056 n->nfile.fname = makename();
10060 static union node *
10063 union node *args, **app;
10064 union node *n = NULL;
10065 union node *vars, **vpp;
10066 union node **rpp, *redir;
10068 #if ENABLE_ASH_BASH_COMPAT
10069 smallint double_brackets_flag = 0;
10079 savecheckkwd = CHKALIAS;
10082 checkkwd = savecheckkwd;
10085 #if ENABLE_ASH_BASH_COMPAT
10086 case TAND: /* "&&" */
10087 case TOR: /* "||" */
10088 if (!double_brackets_flag) {
10092 wordtext = (char *) (t == TAND ? "-a" : "-o");
10095 n = stzalloc(sizeof(struct narg));
10097 /*n->narg.next = NULL; - stzalloc did it */
10098 n->narg.text = wordtext;
10099 #if ENABLE_ASH_BASH_COMPAT
10100 if (strcmp("[[", wordtext) == 0)
10101 double_brackets_flag = 1;
10102 else if (strcmp("]]", wordtext) == 0)
10103 double_brackets_flag = 0;
10105 n->narg.backquote = backquotelist;
10106 if (savecheckkwd && isassignment(wordtext)) {
10108 vpp = &n->narg.next;
10111 app = &n->narg.next;
10116 *rpp = n = redirnode;
10117 rpp = &n->nfile.next;
10118 parsefname(); /* read name of redirection file */
10121 if (args && app == &args->narg.next
10124 struct builtincmd *bcmd;
10127 /* We have a function */
10128 if (readtoken() != TRP)
10129 raise_error_unexpected_syntax(TRP);
10130 name = n->narg.text;
10131 if (!goodname(name)
10132 || ((bcmd = find_builtin(name)) && IS_BUILTIN_SPECIAL(bcmd))
10134 raise_error_syntax("Bad function name");
10137 checkkwd = CHKNL | CHKKWD | CHKALIAS;
10138 n->narg.next = parse_command();
10151 n = stzalloc(sizeof(struct ncmd));
10153 n->ncmd.args = args;
10154 n->ncmd.assign = vars;
10155 n->ncmd.redirect = redir;
10159 static union node *
10160 parse_command(void)
10162 union node *n1, *n2;
10163 union node *ap, **app;
10164 union node *cp, **cpp;
10165 union node *redir, **rpp;
10172 switch (readtoken()) {
10174 raise_error_unexpected_syntax(-1);
10177 n1 = stzalloc(sizeof(struct nif));
10179 n1->nif.test = list(0);
10180 if (readtoken() != TTHEN)
10181 raise_error_unexpected_syntax(TTHEN);
10182 n1->nif.ifpart = list(0);
10184 while (readtoken() == TELIF) {
10185 n2->nif.elsepart = stzalloc(sizeof(struct nif));
10186 n2 = n2->nif.elsepart;
10188 n2->nif.test = list(0);
10189 if (readtoken() != TTHEN)
10190 raise_error_unexpected_syntax(TTHEN);
10191 n2->nif.ifpart = list(0);
10193 if (lasttoken == TELSE)
10194 n2->nif.elsepart = list(0);
10196 n2->nif.elsepart = NULL;
10204 n1 = stzalloc(sizeof(struct nbinary));
10205 n1->type = (lasttoken == TWHILE) ? NWHILE : NUNTIL;
10206 n1->nbinary.ch1 = list(0);
10209 TRACE(("expecting DO got %s %s\n", tokname(got),
10210 got == TWORD ? wordtext : ""));
10211 raise_error_unexpected_syntax(TDO);
10213 n1->nbinary.ch2 = list(0);
10218 if (readtoken() != TWORD || quoteflag || ! goodname(wordtext))
10219 raise_error_syntax("Bad for loop variable");
10220 n1 = stzalloc(sizeof(struct nfor));
10222 n1->nfor.var = wordtext;
10223 checkkwd = CHKKWD | CHKALIAS;
10224 if (readtoken() == TIN) {
10226 while (readtoken() == TWORD) {
10227 n2 = stzalloc(sizeof(struct narg));
10229 /*n2->narg.next = NULL; - stzalloc did it */
10230 n2->narg.text = wordtext;
10231 n2->narg.backquote = backquotelist;
10233 app = &n2->narg.next;
10236 n1->nfor.args = ap;
10237 if (lasttoken != TNL && lasttoken != TSEMI)
10238 raise_error_unexpected_syntax(-1);
10240 n2 = stzalloc(sizeof(struct narg));
10242 /*n2->narg.next = NULL; - stzalloc did it */
10243 n2->narg.text = (char *)dolatstr;
10244 /*n2->narg.backquote = NULL;*/
10245 n1->nfor.args = n2;
10247 * Newline or semicolon here is optional (but note
10248 * that the original Bourne shell only allowed NL).
10250 if (lasttoken != TNL && lasttoken != TSEMI)
10253 checkkwd = CHKNL | CHKKWD | CHKALIAS;
10254 if (readtoken() != TDO)
10255 raise_error_unexpected_syntax(TDO);
10256 n1->nfor.body = list(0);
10260 n1 = stzalloc(sizeof(struct ncase));
10262 if (readtoken() != TWORD)
10263 raise_error_unexpected_syntax(TWORD);
10264 n1->ncase.expr = n2 = stzalloc(sizeof(struct narg));
10266 /*n2->narg.next = NULL; - stzalloc did it */
10267 n2->narg.text = wordtext;
10268 n2->narg.backquote = backquotelist;
10270 checkkwd = CHKKWD | CHKALIAS;
10271 } while (readtoken() == TNL);
10272 if (lasttoken != TIN)
10273 raise_error_unexpected_syntax(TIN);
10274 cpp = &n1->ncase.cases;
10276 checkkwd = CHKNL | CHKKWD;
10278 while (t != TESAC) {
10279 if (lasttoken == TLP)
10281 *cpp = cp = stzalloc(sizeof(struct nclist));
10283 app = &cp->nclist.pattern;
10285 *app = ap = stzalloc(sizeof(struct narg));
10287 /*ap->narg.next = NULL; - stzalloc did it */
10288 ap->narg.text = wordtext;
10289 ap->narg.backquote = backquotelist;
10290 if (readtoken() != TPIPE)
10292 app = &ap->narg.next;
10295 //ap->narg.next = NULL;
10296 if (lasttoken != TRP)
10297 raise_error_unexpected_syntax(TRP);
10298 cp->nclist.body = list(2);
10300 cpp = &cp->nclist.next;
10302 checkkwd = CHKNL | CHKKWD;
10306 raise_error_unexpected_syntax(TENDCASE);
10313 n1 = stzalloc(sizeof(struct nredir));
10314 n1->type = NSUBSHELL;
10315 n1->nredir.n = list(0);
10316 /*n1->nredir.redirect = NULL; - stzalloc did it */
10326 return simplecmd();
10329 if (readtoken() != t)
10330 raise_error_unexpected_syntax(t);
10333 /* Now check for redirection which may follow command */
10334 checkkwd = CHKKWD | CHKALIAS;
10336 while (readtoken() == TREDIR) {
10337 *rpp = n2 = redirnode;
10338 rpp = &n2->nfile.next;
10344 if (n1->type != NSUBSHELL) {
10345 n2 = stzalloc(sizeof(struct nredir));
10350 n1->nredir.redirect = redir;
10355 #if ENABLE_ASH_BASH_COMPAT
10356 static int decode_dollar_squote(void)
10358 static const char C_escapes[] ALIGN1 = "nrbtfav""x\\01234567";
10364 p = strchr(C_escapes, c);
10369 if ((unsigned char)(c - '0') <= 7) { /* \ooo */
10373 } while ((unsigned char)(c - '0') <= 7 && --cnt);
10375 } else if (c == 'x') { /* \xHH */
10379 } while (isxdigit(c) && --cnt);
10381 if (cnt == 3) { /* \x but next char is "bad" */
10385 } else { /* simple seq like \\ or \t */
10390 c = bb_process_escape_sequence((void*)&p);
10391 } else { /* unrecognized "\z": print both chars unless ' or " */
10392 if (c != '\'' && c != '"') {
10394 c |= 0x100; /* "please encode \, then me" */
10402 * If eofmark is NULL, read a word or a redirection symbol. If eofmark
10403 * is not NULL, read a here document. In the latter case, eofmark is the
10404 * word which marks the end of the document and striptabs is true if
10405 * leading tabs should be stripped from the document. The argument firstc
10406 * is the first character of the input token or document.
10408 * Because C does not have internal subroutines, I have simulated them
10409 * using goto's to implement the subroutine linkage. The following macros
10410 * will run code that appears at the end of readtoken1.
10412 #define CHECKEND() {goto checkend; checkend_return:;}
10413 #define PARSEREDIR() {goto parseredir; parseredir_return:;}
10414 #define PARSESUB() {goto parsesub; parsesub_return:;}
10415 #define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
10416 #define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
10417 #define PARSEARITH() {goto parsearith; parsearith_return:;}
10419 readtoken1(int firstc, int syntax, char *eofmark, int striptabs)
10421 /* NB: syntax parameter fits into smallint */
10425 char line[EOFMARKLEN + 1];
10426 struct nodelist *bqlist;
10430 smallint prevsyntax; /* syntax before arithmetic */
10431 #if ENABLE_ASH_EXPAND_PRMT
10432 smallint pssyntax; /* we are expanding a prompt string */
10434 int varnest; /* levels of variables expansion */
10435 int arinest; /* levels of arithmetic expansion */
10436 int parenlevel; /* levels of parens in arithmetic */
10437 int dqvarnest; /* levels of variables expansion within double quotes */
10439 USE_ASH_BASH_COMPAT(smallint bash_dollar_squote = 0;)
10442 /* Avoid longjmp clobbering */
10448 (void) &parenlevel;
10451 (void) &prevsyntax;
10454 startlinno = plinno;
10459 #if ENABLE_ASH_EXPAND_PRMT
10460 pssyntax = (syntax == PSSYNTAX);
10464 dblquote = (syntax == DQSYNTAX);
10470 STARTSTACKSTR(out);
10471 loop: { /* for each line, until end of word */
10472 CHECKEND(); /* set c to PEOF if at end of here document */
10473 for (;;) { /* until end of line or end of word */
10474 CHECKSTRSPACE(4, out); /* permit 4 calls to USTPUTC */
10475 switch (SIT(c, syntax)) {
10476 case CNL: /* '\n' */
10477 if (syntax == BASESYNTAX)
10478 goto endword; /* exit outer loop */
10484 goto loop; /* continue outer loop */
10489 if (eofmark == NULL || dblquote)
10490 USTPUTC(CTLESC, out);
10491 #if ENABLE_ASH_BASH_COMPAT
10492 if (c == '\\' && bash_dollar_squote) {
10493 c = decode_dollar_squote();
10495 USTPUTC('\\', out);
10496 c = (unsigned char)c;
10502 case CBACK: /* backslash */
10505 USTPUTC(CTLESC, out);
10506 USTPUTC('\\', out);
10508 } else if (c == '\n') {
10512 #if ENABLE_ASH_EXPAND_PRMT
10513 if (c == '$' && pssyntax) {
10514 USTPUTC(CTLESC, out);
10515 USTPUTC('\\', out);
10518 if (dblquote && c != '\\'
10519 && c != '`' && c != '$'
10520 && (c != '"' || eofmark != NULL)
10522 USTPUTC(CTLESC, out);
10523 USTPUTC('\\', out);
10525 if (SIT(c, SQSYNTAX) == CCTL)
10526 USTPUTC(CTLESC, out);
10534 if (eofmark == NULL) {
10535 USTPUTC(CTLQUOTEMARK, out);
10543 USE_ASH_BASH_COMPAT(bash_dollar_squote = 0;)
10544 if (eofmark != NULL && arinest == 0
10549 if (dqvarnest == 0) {
10550 syntax = BASESYNTAX;
10557 case CVAR: /* '$' */
10558 PARSESUB(); /* parse substitution */
10560 case CENDVAR: /* '}' */
10563 if (dqvarnest > 0) {
10566 USTPUTC(CTLENDVAR, out);
10571 #if ENABLE_ASH_MATH_SUPPORT
10572 case CLP: /* '(' in arithmetic */
10576 case CRP: /* ')' in arithmetic */
10577 if (parenlevel > 0) {
10581 if (pgetc() == ')') {
10582 if (--arinest == 0) {
10583 USTPUTC(CTLENDARI, out);
10584 syntax = prevsyntax;
10585 dblquote = (syntax == DQSYNTAX);
10590 * unbalanced parens
10591 * (don't 2nd guess - no error)
10599 case CBQUOTE: /* '`' */
10603 goto endword; /* exit outer loop */
10608 goto endword; /* exit outer loop */
10609 #if ENABLE_ASH_ALIAS
10619 #if ENABLE_ASH_MATH_SUPPORT
10620 if (syntax == ARISYNTAX)
10621 raise_error_syntax("Missing '))'");
10623 if (syntax != BASESYNTAX && !parsebackquote && eofmark == NULL)
10624 raise_error_syntax("Unterminated quoted string");
10625 if (varnest != 0) {
10626 startlinno = plinno;
10628 raise_error_syntax("Missing '}'");
10630 USTPUTC('\0', out);
10631 len = out - (char *)stackblock();
10632 out = stackblock();
10633 if (eofmark == NULL) {
10634 if ((c == '>' || c == '<')
10637 && (*out == '\0' || isdigit(*out))
10640 lasttoken = TREDIR;
10645 quoteflag = quotef;
10646 backquotelist = bqlist;
10647 grabstackblock(len);
10651 /* end of readtoken routine */
10654 * Check to see whether we are at the end of the here document. When this
10655 * is called, c is set to the first character of the next input line. If
10656 * we are at the end of the here document, this routine sets the c to PEOF.
10660 #if ENABLE_ASH_ALIAS
10666 while (c == '\t') {
10670 if (c == *eofmark) {
10671 if (pfgets(line, sizeof(line)) != NULL) {
10675 for (q = eofmark + 1; *q && *p == *q; p++, q++)
10677 if (*p == '\n' && *q == '\0') {
10680 needprompt = doprompt;
10682 pushstring(line, NULL);
10687 goto checkend_return;
10691 * Parse a redirection operator. The variable "out" points to a string
10692 * specifying the fd to be redirected. The variable "c" contains the
10693 * first character of the redirection operator.
10699 np = stzalloc(sizeof(struct nfile));
10704 np->type = NAPPEND;
10706 np->type = NCLOBBER;
10713 } else { /* c == '<' */
10714 /*np->nfile.fd = 0; - stzalloc did it */
10718 if (sizeof(struct nfile) != sizeof(struct nhere)) {
10719 np = stzalloc(sizeof(struct nhere));
10720 /*np->nfile.fd = 0; - stzalloc did it */
10723 heredoc = stzalloc(sizeof(struct heredoc));
10724 heredoc->here = np;
10727 heredoc->striptabs = 1;
10729 /*heredoc->striptabs = 0; - stzalloc did it */
10735 np->type = NFROMFD;
10739 np->type = NFROMTO;
10749 np->nfile.fd = fd - '0';
10751 goto parseredir_return;
10755 * Parse a substitution. At this point, we have read the dollar sign
10756 * and nothing else.
10759 /* is_special(c) evaluates to 1 for c in "!#$*-0123456789?@"; 0 otherwise
10760 * (assuming ascii char codes, as the original implementation did) */
10761 #define is_special(c) \
10762 (((unsigned)(c) - 33 < 32) \
10763 && ((0xc1ff920dU >> ((unsigned)(c) - 33)) & 1))
10769 static const char types[] ALIGN1 = "}-+?=";
10772 if (c <= PEOA_OR_PEOF
10773 || (c != '(' && c != '{' && !is_name(c) && !is_special(c))
10775 #if ENABLE_ASH_BASH_COMPAT
10777 bash_dollar_squote = 1;
10782 } else if (c == '(') { /* $(command) or $((arith)) */
10783 if (pgetc() == '(') {
10784 #if ENABLE_ASH_MATH_SUPPORT
10787 raise_error_syntax("you disabled math support for $((arith)) syntax");
10794 USTPUTC(CTLVAR, out);
10795 typeloc = out - (char *)stackblock();
10796 USTPUTC(VSNORMAL, out);
10797 subtype = VSNORMAL;
10805 subtype = VSLENGTH;
10809 if (c > PEOA_OR_PEOF && is_name(c)) {
10813 } while (c > PEOA_OR_PEOF && is_in_name(c));
10814 } else if (isdigit(c)) {
10818 } while (isdigit(c));
10819 } else if (is_special(c)) {
10823 badsub: raise_error_syntax("Bad substitution");
10827 if (subtype == 0) {
10831 #if ENABLE_ASH_BASH_COMPAT
10832 if (c == ':' || c == '$' || isdigit(c)) {
10834 subtype = VSSUBSTR;
10841 p = strchr(types, c);
10844 subtype = p - types + VSNORMAL;
10849 subtype = c == '#' ? VSTRIMLEFT : VSTRIMRIGHT;
10857 #if ENABLE_ASH_BASH_COMPAT
10859 subtype = VSREPLACE;
10862 subtype++; /* VSREPLACEALL */
10871 if (dblquote || arinest)
10873 *((char *)stackblock() + typeloc) = subtype | flags;
10874 if (subtype != VSNORMAL) {
10876 if (dblquote || arinest) {
10881 goto parsesub_return;
10885 * Called to parse command substitutions. Newstyle is set if the command
10886 * is enclosed inside $(...); nlpp is a pointer to the head of the linked
10887 * list of commands (passed by reference), and savelen is the number of
10888 * characters on the top of the stack which must be preserved.
10891 struct nodelist **nlpp;
10894 char *volatile str;
10895 struct jmploc jmploc;
10896 struct jmploc *volatile savehandler;
10898 smallint saveprompt = 0;
10901 (void) &saveprompt;
10903 savepbq = parsebackquote;
10904 if (setjmp(jmploc.loc)) {
10906 parsebackquote = 0;
10907 exception_handler = savehandler;
10908 longjmp(exception_handler->loc, 1);
10912 savelen = out - (char *)stackblock();
10914 str = ckmalloc(savelen);
10915 memcpy(str, stackblock(), savelen);
10917 savehandler = exception_handler;
10918 exception_handler = &jmploc;
10921 /* We must read until the closing backquote, giving special
10922 treatment to some slashes, and then push the string and
10923 reread it as input, interpreting it normally. */
10930 STARTSTACKSTR(pout);
10947 * If eating a newline, avoid putting
10948 * the newline into the new character
10949 * stream (via the STPUTC after the
10954 if (pc != '\\' && pc != '`' && pc != '$'
10955 && (!dblquote || pc != '"'))
10956 STPUTC('\\', pout);
10957 if (pc > PEOA_OR_PEOF) {
10963 #if ENABLE_ASH_ALIAS
10966 startlinno = plinno;
10967 raise_error_syntax("EOF in backquote substitution");
10971 needprompt = doprompt;
10980 STPUTC('\0', pout);
10981 psavelen = pout - (char *)stackblock();
10982 if (psavelen > 0) {
10983 pstr = grabstackstr(pout);
10984 setinputstring(pstr);
10989 nlpp = &(*nlpp)->next;
10990 *nlpp = stzalloc(sizeof(**nlpp));
10991 /* (*nlpp)->next = NULL; - stzalloc did it */
10992 parsebackquote = oldstyle;
10995 saveprompt = doprompt;
11002 doprompt = saveprompt;
11003 else if (readtoken() != TRP)
11004 raise_error_unexpected_syntax(TRP);
11009 * Start reading from old file again, ignoring any pushed back
11010 * tokens left from the backquote parsing
11015 while (stackblocksize() <= savelen)
11017 STARTSTACKSTR(out);
11019 memcpy(out, str, savelen);
11020 STADJUST(savelen, out);
11026 parsebackquote = savepbq;
11027 exception_handler = savehandler;
11028 if (arinest || dblquote)
11029 USTPUTC(CTLBACKQ | CTLQUOTE, out);
11031 USTPUTC(CTLBACKQ, out);
11033 goto parsebackq_oldreturn;
11034 goto parsebackq_newreturn;
11037 #if ENABLE_ASH_MATH_SUPPORT
11039 * Parse an arithmetic expansion (indicate start of one and set state)
11042 if (++arinest == 1) {
11043 prevsyntax = syntax;
11044 syntax = ARISYNTAX;
11045 USTPUTC(CTLARI, out);
11052 * we collapse embedded arithmetic expansion to
11053 * parenthesis, which should be equivalent
11057 goto parsearith_return;
11061 } /* end of readtoken */
11064 * Read the next input token.
11065 * If the token is a word, we set backquotelist to the list of cmds in
11066 * backquotes. We set quoteflag to true if any part of the word was
11068 * If the token is TREDIR, then we set redirnode to a structure containing
11070 * In all cases, the variable startlinno is set to the number of the line
11071 * on which the token starts.
11073 * [Change comment: here documents and internal procedures]
11074 * [Readtoken shouldn't have any arguments. Perhaps we should make the
11075 * word parsing code into a separate routine. In this case, readtoken
11076 * doesn't need to have any internal procedures, but parseword does.
11077 * We could also make parseoperator in essence the main routine, and
11078 * have parseword (readtoken1?) handle both words and redirection.]
11080 #define NEW_xxreadtoken
11081 #ifdef NEW_xxreadtoken
11082 /* singles must be first! */
11083 static const char xxreadtoken_chars[7] ALIGN1 = {
11084 '\n', '(', ')', '&', '|', ';', 0
11087 static const char xxreadtoken_tokens[] ALIGN1 = {
11088 TNL, TLP, TRP, /* only single occurrence allowed */
11089 TBACKGND, TPIPE, TSEMI, /* if single occurrence */
11090 TEOF, /* corresponds to trailing nul */
11091 TAND, TOR, TENDCASE /* if double occurrence */
11094 #define xxreadtoken_doubles \
11095 (sizeof(xxreadtoken_tokens) - sizeof(xxreadtoken_chars))
11096 #define xxreadtoken_singles \
11097 (sizeof(xxreadtoken_chars) - xxreadtoken_doubles - 1)
11111 startlinno = plinno;
11112 for (;;) { /* until token or start of word found */
11115 if ((c != ' ') && (c != '\t')
11116 #if ENABLE_ASH_ALIAS
11121 while ((c = pgetc()) != '\n' && c != PEOF)
11124 } else if (c == '\\') {
11125 if (pgetc() != '\n') {
11129 startlinno = ++plinno;
11134 = xxreadtoken_chars + sizeof(xxreadtoken_chars) - 1;
11139 needprompt = doprompt;
11142 p = strchr(xxreadtoken_chars, c);
11145 return readtoken1(c, BASESYNTAX, (char *) NULL, 0);
11148 if ((size_t)(p - xxreadtoken_chars) >= xxreadtoken_singles) {
11149 if (pgetc() == *p) { /* double occurrence? */
11150 p += xxreadtoken_doubles + 1;
11156 lasttoken = xxreadtoken_tokens[p - xxreadtoken_chars];
11163 #define RETURN(token) return lasttoken = token
11176 startlinno = plinno;
11177 for (;;) { /* until token or start of word found */
11180 case ' ': case '\t':
11181 #if ENABLE_ASH_ALIAS
11186 while ((c = pgetc()) != '\n' && c != PEOF)
11191 if (pgetc() == '\n') {
11192 startlinno = ++plinno;
11201 needprompt = doprompt;
11206 if (pgetc() == '&')
11211 if (pgetc() == '|')
11216 if (pgetc() == ';')
11229 return readtoken1(c, BASESYNTAX, (char *)NULL, 0);
11232 #endif /* NEW_xxreadtoken */
11239 smallint alreadyseen = tokpushback;
11242 #if ENABLE_ASH_ALIAS
11251 if (checkkwd & CHKNL) {
11258 if (t != TWORD || quoteflag) {
11263 * check for keywords
11265 if (checkkwd & CHKKWD) {
11266 const char *const *pp;
11268 pp = findkwd(wordtext);
11270 lasttoken = t = pp - tokname_array;
11271 TRACE(("keyword %s recognized\n", tokname(t)));
11276 if (checkkwd & CHKALIAS) {
11277 #if ENABLE_ASH_ALIAS
11279 ap = lookupalias(wordtext, 1);
11282 pushstring(ap->val, ap);
11292 TRACE(("token %s %s\n", tokname(t), t == TWORD ? wordtext : ""));
11294 TRACE(("reread token %s %s\n", tokname(t), t == TWORD ? wordtext : ""));
11306 return tokname_array[t][0];
11310 * Read and parse a command. Returns NEOF on end of file. (NULL is a
11311 * valid parse tree indicating a blank line.)
11313 static union node *
11314 parsecmd(int interact)
11319 doprompt = interact;
11321 setprompt(doprompt);
11333 * Input any here documents.
11338 struct heredoc *here;
11341 here = heredoclist;
11342 heredoclist = NULL;
11348 readtoken1(pgetc(), here->here->type == NHERE? SQSYNTAX : DQSYNTAX,
11349 here->eofmark, here->striptabs);
11350 n = stzalloc(sizeof(struct narg));
11351 n->narg.type = NARG;
11352 /*n->narg.next = NULL; - stzalloc did it */
11353 n->narg.text = wordtext;
11354 n->narg.backquote = backquotelist;
11355 here->here->nhere.doc = n;
11362 * called by editline -- any expansions to the prompt should be added here.
11364 #if ENABLE_ASH_EXPAND_PRMT
11365 static const char *
11366 expandstr(const char *ps)
11370 /* XXX Fix (char *) cast. */
11371 setinputstring((char *)ps);
11372 readtoken1(pgetc(), PSSYNTAX, nullstr, 0);
11375 n.narg.type = NARG;
11376 n.narg.next = NULL;
11377 n.narg.text = wordtext;
11378 n.narg.backquote = backquotelist;
11380 expandarg(&n, NULL, 0);
11381 return stackblock();
11386 * Execute a command or commands contained in a string.
11389 evalstring(char *s, int mask)
11392 struct stackmark smark;
11396 setstackmark(&smark);
11399 while ((n = parsecmd(0)) != NEOF) {
11401 popstackmark(&smark);
11414 * The eval command.
11417 evalcmd(int argc ATTRIBUTE_UNUSED, char **argv)
11426 STARTSTACKSTR(concat);
11428 concat = stack_putstr(p, concat);
11432 STPUTC(' ', concat);
11434 STPUTC('\0', concat);
11435 p = grabstackstr(concat);
11437 evalstring(p, ~SKIPEVAL);
11444 * Read and execute commands. "Top" is nonzero for the top level command
11445 * loop; it turns on prompting if the shell is interactive.
11451 struct stackmark smark;
11455 TRACE(("cmdloop(%d) called\n", top));
11459 setstackmark(&smark);
11462 showjobs(stderr, SHOW_CHANGED);
11465 if (iflag && top) {
11467 #if ENABLE_ASH_MAIL
11471 n = parsecmd(inter);
11472 /* showtree(n); DEBUG */
11474 if (!top || numeof >= 50)
11476 if (!stoppedjobs()) {
11479 out2str("\nUse \"exit\" to leave shell.\n");
11482 } else if (nflag == 0) {
11483 /* job_warning can only be 2,1,0. Here 2->1, 1/0->0 */
11488 popstackmark(&smark);
11493 return skip & SKIPEVAL;
11500 * Take commands from a file. To be compatible we should do a path
11501 * search for the file, which is necessary to find sub-commands.
11504 find_dot_file(char *name)
11507 const char *path = pathval();
11510 /* don't try this for absolute or relative paths */
11511 if (strchr(name, '/'))
11514 while ((fullname = padvance(&path, name)) != NULL) {
11515 if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) {
11517 * Don't bother freeing here, since it will
11518 * be freed by the caller.
11522 stunalloc(fullname);
11525 /* not found in the PATH */
11526 ash_msg_and_raise_error("%s: not found", name);
11531 dotcmd(int argc, char **argv)
11533 struct strlist *sp;
11534 volatile struct shparam saveparam;
11537 for (sp = cmdenviron; sp; sp = sp->next)
11538 setvareq(ckstrdup(sp->text), VSTRFIXED | VTEXTFIXED);
11540 if (argv[1]) { /* That's what SVR2 does */
11541 char *fullname = find_dot_file(argv[1]);
11544 if (argc) { /* argc > 0, argv[0] != NULL */
11545 saveparam = shellparam;
11546 shellparam.malloced = 0;
11547 shellparam.nparam = argc;
11548 shellparam.p = argv;
11551 setinputfile(fullname, INPUT_PUSH_FILE);
11552 commandname = fullname;
11557 freeparam(&shellparam);
11558 shellparam = saveparam;
11560 status = exitstatus;
11566 exitcmd(int argc ATTRIBUTE_UNUSED, char **argv)
11571 exitstatus = number(argv[1]);
11572 raise_exception(EXEXIT);
11577 * Read a file containing shell functions.
11580 readcmdfile(char *name)
11582 setinputfile(name, INPUT_PUSH_FILE);
11588 /* ============ find_command inplementation */
11591 * Resolve a command name. If you change this routine, you may have to
11592 * change the shellexec routine as well.
11595 find_command(char *name, struct cmdentry *entry, int act, const char *path)
11597 struct tblentry *cmdp;
11604 struct builtincmd *bcmd;
11606 /* If name contains a slash, don't use PATH or hash table */
11607 if (strchr(name, '/') != NULL) {
11608 entry->u.index = -1;
11609 if (act & DO_ABS) {
11610 while (stat(name, &statb) < 0) {
11612 if (errno == EINTR)
11615 entry->cmdtype = CMDUNKNOWN;
11619 entry->cmdtype = CMDNORMAL;
11623 /* #if ENABLE_FEATURE_SH_STANDALONE... moved after builtin check */
11625 updatetbl = (path == pathval());
11628 if (strstr(path, "%builtin") != NULL)
11629 act |= DO_ALTBLTIN;
11632 /* If name is in the table, check answer will be ok */
11633 cmdp = cmdlookup(name, 0);
11634 if (cmdp != NULL) {
11637 switch (cmdp->cmdtype) {
11655 } else if (cmdp->rehash == 0)
11656 /* if not invalidated by cd, we're done */
11660 /* If %builtin not in path, check for builtin next */
11661 bcmd = find_builtin(name);
11663 if (IS_BUILTIN_REGULAR(bcmd))
11664 goto builtin_success;
11665 if (act & DO_ALTPATH) {
11666 if (!(act & DO_ALTBLTIN))
11667 goto builtin_success;
11668 } else if (builtinloc <= 0) {
11669 goto builtin_success;
11673 #if ENABLE_FEATURE_SH_STANDALONE
11675 int applet_no = find_applet_by_name(name);
11676 if (applet_no >= 0) {
11677 entry->cmdtype = CMDNORMAL;
11678 entry->u.index = -2 - applet_no;
11684 /* We have to search path. */
11685 prev = -1; /* where to start */
11686 if (cmdp && cmdp->rehash) { /* doing a rehash */
11687 if (cmdp->cmdtype == CMDBUILTIN)
11690 prev = cmdp->param.index;
11696 while ((fullname = padvance(&path, name)) != NULL) {
11697 stunalloc(fullname);
11698 /* NB: code below will still use fullname
11699 * despite it being "unallocated" */
11702 if (prefix(pathopt, "builtin")) {
11704 goto builtin_success;
11707 if ((act & DO_NOFUNC)
11708 || !prefix(pathopt, "func")
11709 ) { /* ignore unimplemented options */
11713 /* if rehash, don't redo absolute path names */
11714 if (fullname[0] == '/' && idx <= prev) {
11717 TRACE(("searchexec \"%s\": no change\n", name));
11720 while (stat(fullname, &statb) < 0) {
11722 if (errno == EINTR)
11725 if (errno != ENOENT && errno != ENOTDIR)
11729 e = EACCES; /* if we fail, this will be the error */
11730 if (!S_ISREG(statb.st_mode))
11732 if (pathopt) { /* this is a %func directory */
11733 stalloc(strlen(fullname) + 1);
11734 /* NB: stalloc will return space pointed by fullname
11735 * (because we don't have any intervening allocations
11736 * between stunalloc above and this stalloc) */
11737 readcmdfile(fullname);
11738 cmdp = cmdlookup(name, 0);
11739 if (cmdp == NULL || cmdp->cmdtype != CMDFUNCTION)
11740 ash_msg_and_raise_error("%s not defined in %s", name, fullname);
11741 stunalloc(fullname);
11744 TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
11746 entry->cmdtype = CMDNORMAL;
11747 entry->u.index = idx;
11751 cmdp = cmdlookup(name, 1);
11752 cmdp->cmdtype = CMDNORMAL;
11753 cmdp->param.index = idx;
11758 /* We failed. If there was an entry for this command, delete it */
11759 if (cmdp && updatetbl)
11760 delete_cmd_entry();
11762 ash_msg("%s: %s", name, errmsg(e, "not found"));
11763 entry->cmdtype = CMDUNKNOWN;
11768 entry->cmdtype = CMDBUILTIN;
11769 entry->u.cmd = bcmd;
11773 cmdp = cmdlookup(name, 1);
11774 cmdp->cmdtype = CMDBUILTIN;
11775 cmdp->param.cmd = bcmd;
11779 entry->cmdtype = cmdp->cmdtype;
11780 entry->u = cmdp->param;
11784 /* ============ trap.c */
11787 * The trap builtin.
11790 trapcmd(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED)
11799 for (signo = 0; signo < NSIG; signo++) {
11800 if (trap[signo] != NULL) {
11803 sn = get_signame(signo);
11804 out1fmt("trap -- %s %s\n",
11805 single_quote(trap[signo]), sn);
11815 signo = get_signum(*ap);
11817 ash_msg_and_raise_error("%s: bad trap", *ap);
11820 if (LONE_DASH(action))
11823 action = ckstrdup(action);
11826 trap[signo] = action;
11836 /* ============ Builtins */
11838 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
11840 * Lists available builtins
11843 helpcmd(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED)
11848 out1fmt("\nBuilt-in commands:\n-------------------\n");
11849 for (col = 0, i = 0; i < ARRAY_SIZE(builtintab); i++) {
11850 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '),
11851 builtintab[i].name + 1);
11857 #if ENABLE_FEATURE_SH_STANDALONE
11859 const char *a = applet_names;
11861 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '), a);
11866 a += strlen(a) + 1;
11871 return EXIT_SUCCESS;
11873 #endif /* FEATURE_SH_EXTRA_QUIET */
11876 * The export and readonly commands.
11879 exportcmd(int argc ATTRIBUTE_UNUSED, char **argv)
11885 int flag = argv[0][0] == 'r'? VREADONLY : VEXPORT;
11887 if (nextopt("p") != 'p') {
11892 p = strchr(name, '=');
11896 vp = *findvar(hashvar(name), name);
11902 setvar(name, p, flag);
11903 } while ((name = *++aptr) != NULL);
11907 showvars(argv[0], flag, 0);
11912 * Delete a function if it exists.
11915 unsetfunc(const char *name)
11917 struct tblentry *cmdp;
11919 cmdp = cmdlookup(name, 0);
11920 if (cmdp!= NULL && cmdp->cmdtype == CMDFUNCTION)
11921 delete_cmd_entry();
11925 * The unset builtin command. We unset the function before we unset the
11926 * variable to allow a function to be unset when there is a readonly variable
11927 * with the same name.
11930 unsetcmd(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED)
11937 while ((i = nextopt("vf")) != '\0') {
11941 for (ap = argptr; *ap; ap++) {
11957 #include <sys/times.h>
11959 static const unsigned char timescmd_str[] ALIGN1 = {
11960 ' ', offsetof(struct tms, tms_utime),
11961 '\n', offsetof(struct tms, tms_stime),
11962 ' ', offsetof(struct tms, tms_cutime),
11963 '\n', offsetof(struct tms, tms_cstime),
11968 timescmd(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED)
11970 long clk_tck, s, t;
11971 const unsigned char *p;
11974 clk_tck = sysconf(_SC_CLK_TCK);
11979 t = *(clock_t *)(((char *) &buf) + p[1]);
11981 out1fmt("%ldm%ld.%.3lds%c",
11983 ((t - s * clk_tck) * 1000) / clk_tck,
11985 } while (*(p += 2));
11990 #if ENABLE_ASH_MATH_SUPPORT
11992 dash_arith(const char *s)
11998 result = arith(s, &errcode);
12001 ash_msg_and_raise_error("exponent less than 0");
12003 ash_msg_and_raise_error("divide by zero");
12005 ash_msg_and_raise_error("expression recursion loop detected");
12006 raise_error_syntax(s);
12014 * The let builtin. partial stolen from GNU Bash, the Bourne Again SHell.
12015 * Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
12017 * Copyright (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
12020 letcmd(int argc ATTRIBUTE_UNUSED, char **argv)
12026 ash_msg_and_raise_error("expression expected");
12028 i = dash_arith(*argv);
12033 #endif /* ASH_MATH_SUPPORT */
12036 /* ============ miscbltin.c
12038 * Miscellaneous builtins.
12043 #if defined(__GLIBC__) && __GLIBC__ == 2 && __GLIBC_MINOR__ < 1
12044 typedef enum __rlimit_resource rlim_t;
12048 * The read builtin. Options:
12049 * -r Do not interpret '\' specially
12050 * -s Turn off echo (tty only)
12051 * -n NCHARS Read NCHARS max
12052 * -p PROMPT Display PROMPT on stderr (if input is from tty)
12053 * -t SECONDS Timeout after SECONDS (tty or pipe only)
12054 * -u FD Read from given FD instead of fd 0
12055 * This uses unbuffered input, which may be avoidable in some cases.
12056 * TODO: bash also has:
12057 * -a ARRAY Read into array[0],[1],etc
12058 * -d DELIM End on DELIM char, not newline
12059 * -e Use line editing (tty only)
12062 readcmd(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED)
12064 static const char *const arg_REPLY[] = { "REPLY", NULL };
12077 #if ENABLE_ASH_READ_NCHARS
12078 int nchars = 0; /* if != 0, -n is in effect */
12080 struct termios tty, old_tty;
12082 #if ENABLE_ASH_READ_TIMEOUT
12083 unsigned end_ms = 0;
12084 unsigned timeout = 0;
12089 while ((i = nextopt("p:u:r"
12090 USE_ASH_READ_TIMEOUT("t:")
12091 USE_ASH_READ_NCHARS("n:s")
12095 prompt = optionarg;
12097 #if ENABLE_ASH_READ_NCHARS
12099 nchars = bb_strtou(optionarg, NULL, 10);
12100 if (nchars < 0 || errno)
12101 ash_msg_and_raise_error("invalid count");
12102 /* nchars == 0: off (bash 3.2 does this too) */
12108 #if ENABLE_ASH_READ_TIMEOUT
12110 timeout = bb_strtou(optionarg, NULL, 10);
12111 if (errno || timeout > UINT_MAX / 2048)
12112 ash_msg_and_raise_error("invalid timeout");
12114 #if 0 /* even bash have no -t N.NNN support */
12115 ts.tv_sec = bb_strtou(optionarg, &p, 10);
12117 /* EINVAL means number is ok, but not terminated by NUL */
12118 if (*p == '.' && errno == EINVAL) {
12122 ts.tv_usec = bb_strtou(p, &p2, 10);
12124 ash_msg_and_raise_error("invalid timeout");
12126 /* normalize to usec */
12128 ash_msg_and_raise_error("invalid timeout");
12129 while (scale++ < 6)
12132 } else if (ts.tv_sec < 0 || errno) {
12133 ash_msg_and_raise_error("invalid timeout");
12135 if (!(ts.tv_sec | ts.tv_usec)) { /* both are 0? */
12136 ash_msg_and_raise_error("invalid timeout");
12145 fd = bb_strtou(optionarg, NULL, 10);
12146 if (fd < 0 || errno)
12147 ash_msg_and_raise_error("invalid file descriptor");
12153 if (prompt && isatty(fd)) {
12158 ap = (char**)arg_REPLY;
12159 ifs = bltinlookup("IFS");
12162 #if ENABLE_ASH_READ_NCHARS
12163 tcgetattr(fd, &tty);
12165 if (nchars || silent) {
12167 tty.c_lflag &= ~ICANON;
12168 tty.c_cc[VMIN] = nchars < 256 ? nchars : 255;
12171 tty.c_lflag &= ~(ECHO | ECHOK | ECHONL);
12173 /* if tcgetattr failed, tcsetattr will fail too.
12174 * Ignoring, it's harmless. */
12175 tcsetattr(fd, TCSANOW, &tty);
12182 #if ENABLE_ASH_READ_TIMEOUT
12183 if (timeout) /* NB: ensuring end_ms is nonzero */
12184 end_ms = ((unsigned)(monotonic_us() / 1000) + timeout) | 1;
12188 #if ENABLE_ASH_READ_TIMEOUT
12190 struct pollfd pfd[1];
12192 pfd[0].events = POLLIN;
12193 timeout = end_ms - (unsigned)(monotonic_us() / 1000);
12194 if ((int)timeout <= 0 /* already late? */
12195 || safe_poll(pfd, 1, timeout) != 1 /* no? wait... */
12196 ) { /* timed out! */
12197 #if ENABLE_ASH_READ_NCHARS
12198 tcsetattr(fd, TCSANOW, &old_tty);
12204 if (nonblock_safe_read(fd, &c, 1) != 1) {
12216 if (!rflag && c == '\\') {
12222 if (startword && *ifs == ' ' && strchr(ifs, c)) {
12226 if (ap[1] != NULL && strchr(ifs, c) != NULL) {
12228 setvar(*ap, stackblock(), 0);
12237 /* end of do {} while: */
12238 #if ENABLE_ASH_READ_NCHARS
12244 #if ENABLE_ASH_READ_NCHARS
12245 tcsetattr(fd, TCSANOW, &old_tty);
12249 /* Remove trailing blanks */
12250 while ((char *)stackblock() <= --p && strchr(ifs, *p) != NULL)
12252 setvar(*ap, stackblock(), 0);
12253 while (*++ap != NULL)
12254 setvar(*ap, nullstr, 0);
12259 umaskcmd(int argc ATTRIBUTE_UNUSED, char **argv)
12261 static const char permuser[3] ALIGN1 = "ugo";
12262 static const char permmode[3] ALIGN1 = "rwx";
12263 static const short permmask[] ALIGN2 = {
12264 S_IRUSR, S_IWUSR, S_IXUSR,
12265 S_IRGRP, S_IWGRP, S_IXGRP,
12266 S_IROTH, S_IWOTH, S_IXOTH
12272 int symbolic_mode = 0;
12274 while (nextopt("S") != '\0') {
12285 if (symbolic_mode) {
12289 for (i = 0; i < 3; i++) {
12292 *p++ = permuser[i];
12294 for (j = 0; j < 3; j++) {
12295 if ((mask & permmask[3 * i + j]) == 0) {
12296 *p++ = permmode[j];
12304 out1fmt("%.4o\n", mask);
12307 if (isdigit((unsigned char) *ap)) {
12310 if (*ap >= '8' || *ap < '0')
12311 ash_msg_and_raise_error(illnum, argv[1]);
12312 mask = (mask << 3) + (*ap - '0');
12313 } while (*++ap != '\0');
12316 mask = ~mask & 0777;
12317 if (!bb_parse_mode(ap, &mask)) {
12318 ash_msg_and_raise_error("illegal mode: %s", ap);
12320 umask(~mask & 0777);
12329 * This code, originally by Doug Gwyn, Doug Kingston, Eric Gisin, and
12330 * Michael Rendell was ripped from pdksh 5.0.8 and hacked for use with
12331 * ash by J.T. Conklin.
12337 uint8_t cmd; /* RLIMIT_xxx fit into it */
12338 uint8_t factor_shift; /* shift by to get rlim_{cur,max} values */
12342 static const struct limits limits_tbl[] = {
12344 { RLIMIT_CPU, 0, 't' },
12346 #ifdef RLIMIT_FSIZE
12347 { RLIMIT_FSIZE, 9, 'f' },
12350 { RLIMIT_DATA, 10, 'd' },
12352 #ifdef RLIMIT_STACK
12353 { RLIMIT_STACK, 10, 's' },
12356 { RLIMIT_CORE, 9, 'c' },
12359 { RLIMIT_RSS, 10, 'm' },
12361 #ifdef RLIMIT_MEMLOCK
12362 { RLIMIT_MEMLOCK, 10, 'l' },
12364 #ifdef RLIMIT_NPROC
12365 { RLIMIT_NPROC, 0, 'p' },
12367 #ifdef RLIMIT_NOFILE
12368 { RLIMIT_NOFILE, 0, 'n' },
12371 { RLIMIT_AS, 10, 'v' },
12373 #ifdef RLIMIT_LOCKS
12374 { RLIMIT_LOCKS, 0, 'w' },
12377 static const char limits_name[] =
12379 "time(seconds)" "\0"
12381 #ifdef RLIMIT_FSIZE
12382 "file(blocks)" "\0"
12387 #ifdef RLIMIT_STACK
12391 "coredump(blocks)" "\0"
12396 #ifdef RLIMIT_MEMLOCK
12397 "locked memory(kb)" "\0"
12399 #ifdef RLIMIT_NPROC
12402 #ifdef RLIMIT_NOFILE
12408 #ifdef RLIMIT_LOCKS
12413 enum limtype { SOFT = 0x1, HARD = 0x2 };
12416 printlim(enum limtype how, const struct rlimit *limit,
12417 const struct limits *l)
12421 val = limit->rlim_max;
12423 val = limit->rlim_cur;
12425 if (val == RLIM_INFINITY)
12426 out1fmt("unlimited\n");
12428 val >>= l->factor_shift;
12429 out1fmt("%lld\n", (long long) val);
12434 ulimitcmd(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED)
12438 enum limtype how = SOFT | HARD;
12439 const struct limits *l;
12442 struct rlimit limit;
12445 while ((optc = nextopt("HSa"
12449 #ifdef RLIMIT_FSIZE
12455 #ifdef RLIMIT_STACK
12464 #ifdef RLIMIT_MEMLOCK
12467 #ifdef RLIMIT_NPROC
12470 #ifdef RLIMIT_NOFILE
12476 #ifdef RLIMIT_LOCKS
12494 for (l = limits_tbl; l->option != what; l++)
12497 set = *argptr ? 1 : 0;
12501 if (all || argptr[1])
12502 ash_msg_and_raise_error("too many arguments");
12503 if (strncmp(p, "unlimited\n", 9) == 0)
12504 val = RLIM_INFINITY;
12508 while ((c = *p++) >= '0' && c <= '9') {
12509 val = (val * 10) + (long)(c - '0');
12510 // val is actually 'unsigned long int' and can't get < 0
12511 if (val < (rlim_t) 0)
12515 ash_msg_and_raise_error("bad number");
12516 val <<= l->factor_shift;
12520 const char *lname = limits_name;
12521 for (l = limits_tbl; l != &limits_tbl[ARRAY_SIZE(limits_tbl)]; l++) {
12522 getrlimit(l->cmd, &limit);
12523 out1fmt("%-20s ", lname);
12524 lname += strlen(lname) + 1;
12525 printlim(how, &limit, l);
12530 getrlimit(l->cmd, &limit);
12533 limit.rlim_max = val;
12535 limit.rlim_cur = val;
12536 if (setrlimit(l->cmd, &limit) < 0)
12537 ash_msg_and_raise_error("error setting limit (%m)");
12539 printlim(how, &limit, l);
12545 /* ============ Math support */
12547 #if ENABLE_ASH_MATH_SUPPORT
12549 /* Copyright (c) 2001 Aaron Lehmann <aaronl@vitelus.com>
12551 Permission is hereby granted, free of charge, to any person obtaining
12552 a copy of this software and associated documentation files (the
12553 "Software"), to deal in the Software without restriction, including
12554 without limitation the rights to use, copy, modify, merge, publish,
12555 distribute, sublicense, and/or sell copies of the Software, and to
12556 permit persons to whom the Software is furnished to do so, subject to
12557 the following conditions:
12559 The above copyright notice and this permission notice shall be
12560 included in all copies or substantial portions of the Software.
12562 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
12563 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
12564 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
12565 IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
12566 CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
12567 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
12568 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
12571 /* This is my infix parser/evaluator. It is optimized for size, intended
12572 * as a replacement for yacc-based parsers. However, it may well be faster
12573 * than a comparable parser written in yacc. The supported operators are
12574 * listed in #defines below. Parens, order of operations, and error handling
12575 * are supported. This code is thread safe. The exact expression format should
12576 * be that which POSIX specifies for shells. */
12578 /* The code uses a simple two-stack algorithm. See
12579 * http://www.onthenet.com.au/~grahamis/int2008/week02/lect02.html
12580 * for a detailed explanation of the infix-to-postfix algorithm on which
12581 * this is based (this code differs in that it applies operators immediately
12582 * to the stack instead of adding them to a queue to end up with an
12585 /* To use the routine, call it with an expression string and error return
12589 * Aug 24, 2001 Manuel Novoa III
12591 * Reduced the generated code size by about 30% (i386) and fixed several bugs.
12593 * 1) In arith_apply():
12594 * a) Cached values of *numptr and &(numptr[-1]).
12595 * b) Removed redundant test for zero denominator.
12598 * a) Eliminated redundant code for processing operator tokens by moving
12599 * to a table-based implementation. Also folded handling of parens
12601 * b) Combined all 3 loops which called arith_apply to reduce generated
12602 * code size at the cost of speed.
12604 * 3) The following expressions were treated as valid by the original code:
12605 * 1() , 0! , 1 ( *3 ) .
12606 * These bugs have been fixed by internally enclosing the expression in
12607 * parens and then checking that all binary ops and right parens are
12608 * preceded by a valid expression (NUM_TOKEN).
12610 * Note: It may be desirable to replace Aaron's test for whitespace with
12611 * ctype's isspace() if it is used by another busybox applet or if additional
12612 * whitespace chars should be considered. Look below the "#include"s for a
12613 * precompiler test.
12617 * Aug 26, 2001 Manuel Novoa III
12619 * Return 0 for null expressions. Pointed out by Vladimir Oleynik.
12621 * Merge in Aaron's comments previously posted to the busybox list,
12622 * modified slightly to take account of my changes to the code.
12627 * (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
12629 * - allow access to variable,
12630 * used recursive find value indirection (c=2*2; a="c"; $((a+=2)) produce 6)
12631 * - realize assign syntax (VAR=expr, +=, *= etc)
12632 * - realize exponentiation (** operator)
12633 * - realize comma separated - expr, expr
12634 * - realise ++expr --expr expr++ expr--
12635 * - realise expr ? expr : expr (but, second expr calculate always)
12636 * - allow hexadecimal and octal numbers
12637 * - was restored loses XOR operator
12638 * - remove one goto label, added three ;-)
12639 * - protect $((num num)) as true zero expr (Manuel`s error)
12640 * - always use special isspace(), see comment from bash ;-)
12643 #define arith_isspace(arithval) \
12644 (arithval == ' ' || arithval == '\n' || arithval == '\t')
12646 typedef unsigned char operator;
12648 /* An operator's token id is a bit of a bitfield. The lower 5 bits are the
12649 * precedence, and 3 high bits are an ID unique across operators of that
12650 * precedence. The ID portion is so that multiple operators can have the
12651 * same precedence, ensuring that the leftmost one is evaluated first.
12652 * Consider * and /. */
12654 #define tok_decl(prec,id) (((id)<<5)|(prec))
12655 #define PREC(op) ((op) & 0x1F)
12657 #define TOK_LPAREN tok_decl(0,0)
12659 #define TOK_COMMA tok_decl(1,0)
12661 #define TOK_ASSIGN tok_decl(2,0)
12662 #define TOK_AND_ASSIGN tok_decl(2,1)
12663 #define TOK_OR_ASSIGN tok_decl(2,2)
12664 #define TOK_XOR_ASSIGN tok_decl(2,3)
12665 #define TOK_PLUS_ASSIGN tok_decl(2,4)
12666 #define TOK_MINUS_ASSIGN tok_decl(2,5)
12667 #define TOK_LSHIFT_ASSIGN tok_decl(2,6)
12668 #define TOK_RSHIFT_ASSIGN tok_decl(2,7)
12670 #define TOK_MUL_ASSIGN tok_decl(3,0)
12671 #define TOK_DIV_ASSIGN tok_decl(3,1)
12672 #define TOK_REM_ASSIGN tok_decl(3,2)
12674 /* all assign is right associativity and precedence eq, but (7+3)<<5 > 256 */
12675 #define convert_prec_is_assing(prec) do { if (prec == 3) prec = 2; } while (0)
12677 /* conditional is right associativity too */
12678 #define TOK_CONDITIONAL tok_decl(4,0)
12679 #define TOK_CONDITIONAL_SEP tok_decl(4,1)
12681 #define TOK_OR tok_decl(5,0)
12683 #define TOK_AND tok_decl(6,0)
12685 #define TOK_BOR tok_decl(7,0)
12687 #define TOK_BXOR tok_decl(8,0)
12689 #define TOK_BAND tok_decl(9,0)
12691 #define TOK_EQ tok_decl(10,0)
12692 #define TOK_NE tok_decl(10,1)
12694 #define TOK_LT tok_decl(11,0)
12695 #define TOK_GT tok_decl(11,1)
12696 #define TOK_GE tok_decl(11,2)
12697 #define TOK_LE tok_decl(11,3)
12699 #define TOK_LSHIFT tok_decl(12,0)
12700 #define TOK_RSHIFT tok_decl(12,1)
12702 #define TOK_ADD tok_decl(13,0)
12703 #define TOK_SUB tok_decl(13,1)
12705 #define TOK_MUL tok_decl(14,0)
12706 #define TOK_DIV tok_decl(14,1)
12707 #define TOK_REM tok_decl(14,2)
12709 /* exponent is right associativity */
12710 #define TOK_EXPONENT tok_decl(15,1)
12712 /* For now unary operators. */
12713 #define UNARYPREC 16
12714 #define TOK_BNOT tok_decl(UNARYPREC,0)
12715 #define TOK_NOT tok_decl(UNARYPREC,1)
12717 #define TOK_UMINUS tok_decl(UNARYPREC+1,0)
12718 #define TOK_UPLUS tok_decl(UNARYPREC+1,1)
12720 #define PREC_PRE (UNARYPREC+2)
12722 #define TOK_PRE_INC tok_decl(PREC_PRE, 0)
12723 #define TOK_PRE_DEC tok_decl(PREC_PRE, 1)
12725 #define PREC_POST (UNARYPREC+3)
12727 #define TOK_POST_INC tok_decl(PREC_POST, 0)
12728 #define TOK_POST_DEC tok_decl(PREC_POST, 1)
12730 #define SPEC_PREC (UNARYPREC+4)
12732 #define TOK_NUM tok_decl(SPEC_PREC, 0)
12733 #define TOK_RPAREN tok_decl(SPEC_PREC, 1)
12735 #define NUMPTR (*numstackptr)
12738 tok_have_assign(operator op)
12740 operator prec = PREC(op);
12742 convert_prec_is_assing(prec);
12743 return (prec == PREC(TOK_ASSIGN) ||
12744 prec == PREC_PRE || prec == PREC_POST);
12748 is_right_associativity(operator prec)
12750 return (prec == PREC(TOK_ASSIGN) || prec == PREC(TOK_EXPONENT)
12751 || prec == PREC(TOK_CONDITIONAL));
12756 arith_t contidional_second_val;
12757 char contidional_second_val_initialized;
12758 char *var; /* if NULL then is regular number,
12759 else is variable name */
12762 typedef struct chk_var_recursive_looped_t {
12764 struct chk_var_recursive_looped_t *next;
12765 } chk_var_recursive_looped_t;
12767 static chk_var_recursive_looped_t *prev_chk_var_recursive;
12770 arith_lookup_val(v_n_t *t)
12773 const char * p = lookupvar(t->var);
12778 /* recursive try as expression */
12779 chk_var_recursive_looped_t *cur;
12780 chk_var_recursive_looped_t cur_save;
12782 for (cur = prev_chk_var_recursive; cur; cur = cur->next) {
12783 if (strcmp(cur->var, t->var) == 0) {
12784 /* expression recursion loop detected */
12788 /* save current lookuped var name */
12789 cur = prev_chk_var_recursive;
12790 cur_save.var = t->var;
12791 cur_save.next = cur;
12792 prev_chk_var_recursive = &cur_save;
12794 t->val = arith (p, &errcode);
12795 /* restore previous ptr after recursiving */
12796 prev_chk_var_recursive = cur;
12799 /* allow undefined var as 0 */
12805 /* "applying" a token means performing it on the top elements on the integer
12806 * stack. For a unary operator it will only change the top element, but a
12807 * binary operator will pop two arguments and push a result */
12809 arith_apply(operator op, v_n_t *numstack, v_n_t **numstackptr)
12812 arith_t numptr_val, rez;
12813 int ret_arith_lookup_val;
12815 /* There is no operator that can work without arguments */
12816 if (NUMPTR == numstack) goto err;
12817 numptr_m1 = NUMPTR - 1;
12819 /* check operand is var with noninteger value */
12820 ret_arith_lookup_val = arith_lookup_val(numptr_m1);
12821 if (ret_arith_lookup_val)
12822 return ret_arith_lookup_val;
12824 rez = numptr_m1->val;
12825 if (op == TOK_UMINUS)
12827 else if (op == TOK_NOT)
12829 else if (op == TOK_BNOT)
12831 else if (op == TOK_POST_INC || op == TOK_PRE_INC)
12833 else if (op == TOK_POST_DEC || op == TOK_PRE_DEC)
12835 else if (op != TOK_UPLUS) {
12836 /* Binary operators */
12838 /* check and binary operators need two arguments */
12839 if (numptr_m1 == numstack) goto err;
12841 /* ... and they pop one */
12844 if (op == TOK_CONDITIONAL) {
12845 if (! numptr_m1->contidional_second_val_initialized) {
12846 /* protect $((expr1 ? expr2)) without ": expr" */
12849 rez = numptr_m1->contidional_second_val;
12850 } else if (numptr_m1->contidional_second_val_initialized) {
12851 /* protect $((expr1 : expr2)) without "expr ? " */
12854 numptr_m1 = NUMPTR - 1;
12855 if (op != TOK_ASSIGN) {
12856 /* check operand is var with noninteger value for not '=' */
12857 ret_arith_lookup_val = arith_lookup_val(numptr_m1);
12858 if (ret_arith_lookup_val)
12859 return ret_arith_lookup_val;
12861 if (op == TOK_CONDITIONAL) {
12862 numptr_m1->contidional_second_val = rez;
12864 rez = numptr_m1->val;
12865 if (op == TOK_BOR || op == TOK_OR_ASSIGN)
12867 else if (op == TOK_OR)
12868 rez = numptr_val || rez;
12869 else if (op == TOK_BAND || op == TOK_AND_ASSIGN)
12871 else if (op == TOK_BXOR || op == TOK_XOR_ASSIGN)
12873 else if (op == TOK_AND)
12874 rez = rez && numptr_val;
12875 else if (op == TOK_EQ)
12876 rez = (rez == numptr_val);
12877 else if (op == TOK_NE)
12878 rez = (rez != numptr_val);
12879 else if (op == TOK_GE)
12880 rez = (rez >= numptr_val);
12881 else if (op == TOK_RSHIFT || op == TOK_RSHIFT_ASSIGN)
12882 rez >>= numptr_val;
12883 else if (op == TOK_LSHIFT || op == TOK_LSHIFT_ASSIGN)
12884 rez <<= numptr_val;
12885 else if (op == TOK_GT)
12886 rez = (rez > numptr_val);
12887 else if (op == TOK_LT)
12888 rez = (rez < numptr_val);
12889 else if (op == TOK_LE)
12890 rez = (rez <= numptr_val);
12891 else if (op == TOK_MUL || op == TOK_MUL_ASSIGN)
12893 else if (op == TOK_ADD || op == TOK_PLUS_ASSIGN)
12895 else if (op == TOK_SUB || op == TOK_MINUS_ASSIGN)
12897 else if (op == TOK_ASSIGN || op == TOK_COMMA)
12899 else if (op == TOK_CONDITIONAL_SEP) {
12900 if (numptr_m1 == numstack) {
12901 /* protect $((expr : expr)) without "expr ? " */
12904 numptr_m1->contidional_second_val_initialized = op;
12905 numptr_m1->contidional_second_val = numptr_val;
12906 } else if (op == TOK_CONDITIONAL) {
12908 numptr_val : numptr_m1->contidional_second_val;
12909 } else if (op == TOK_EXPONENT) {
12910 if (numptr_val < 0)
12911 return -3; /* exponent less than 0 */
12916 while (numptr_val--)
12920 } else if (numptr_val==0) /* zero divisor check */
12922 else if (op == TOK_DIV || op == TOK_DIV_ASSIGN)
12924 else if (op == TOK_REM || op == TOK_REM_ASSIGN)
12927 if (tok_have_assign(op)) {
12928 char buf[sizeof(arith_t_type)*3 + 2];
12930 if (numptr_m1->var == NULL) {
12934 /* save to shell variable */
12935 #if ENABLE_ASH_MATH_SUPPORT_64
12936 snprintf(buf, sizeof(buf), "%lld", (arith_t_type) rez);
12938 snprintf(buf, sizeof(buf), "%ld", (arith_t_type) rez);
12940 setvar(numptr_m1->var, buf, 0);
12941 /* after saving, make previous value for v++ or v-- */
12942 if (op == TOK_POST_INC)
12944 else if (op == TOK_POST_DEC)
12947 numptr_m1->val = rez;
12948 /* protect geting var value, is number now */
12949 numptr_m1->var = NULL;
12955 /* longest must be first */
12956 static const char op_tokens[] ALIGN1 = {
12957 '<','<','=',0, TOK_LSHIFT_ASSIGN,
12958 '>','>','=',0, TOK_RSHIFT_ASSIGN,
12959 '<','<', 0, TOK_LSHIFT,
12960 '>','>', 0, TOK_RSHIFT,
12961 '|','|', 0, TOK_OR,
12962 '&','&', 0, TOK_AND,
12963 '!','=', 0, TOK_NE,
12964 '<','=', 0, TOK_LE,
12965 '>','=', 0, TOK_GE,
12966 '=','=', 0, TOK_EQ,
12967 '|','=', 0, TOK_OR_ASSIGN,
12968 '&','=', 0, TOK_AND_ASSIGN,
12969 '*','=', 0, TOK_MUL_ASSIGN,
12970 '/','=', 0, TOK_DIV_ASSIGN,
12971 '%','=', 0, TOK_REM_ASSIGN,
12972 '+','=', 0, TOK_PLUS_ASSIGN,
12973 '-','=', 0, TOK_MINUS_ASSIGN,
12974 '-','-', 0, TOK_POST_DEC,
12975 '^','=', 0, TOK_XOR_ASSIGN,
12976 '+','+', 0, TOK_POST_INC,
12977 '*','*', 0, TOK_EXPONENT,
12981 '=', 0, TOK_ASSIGN,
12993 '?', 0, TOK_CONDITIONAL,
12994 ':', 0, TOK_CONDITIONAL_SEP,
12995 ')', 0, TOK_RPAREN,
12996 '(', 0, TOK_LPAREN,
13000 #define endexpression (&op_tokens[sizeof(op_tokens)-7])
13003 arith(const char *expr, int *perrcode)
13005 char arithval; /* Current character under analysis */
13006 operator lasttok, op;
13008 operator *stack, *stackptr;
13009 const char *p = endexpression;
13011 v_n_t *numstack, *numstackptr;
13012 unsigned datasizes = strlen(expr) + 2;
13014 /* Stack of integers */
13015 /* The proof that there can be no more than strlen(startbuf)/2+1 integers
13016 * in any given correct or incorrect expression is left as an exercise to
13018 numstackptr = numstack = alloca((datasizes / 2) * sizeof(numstack[0]));
13019 /* Stack of operator tokens */
13020 stackptr = stack = alloca(datasizes * sizeof(stack[0]));
13022 *stackptr++ = lasttok = TOK_LPAREN; /* start off with a left paren */
13023 *perrcode = errcode = 0;
13027 if (arithval == 0) {
13028 if (p == endexpression) {
13029 /* Null expression. */
13033 /* This is only reached after all tokens have been extracted from the
13034 * input stream. If there are still tokens on the operator stack, they
13035 * are to be applied in order. At the end, there should be a final
13036 * result on the integer stack */
13038 if (expr != endexpression + 1) {
13039 /* If we haven't done so already, */
13040 /* append a closing right paren */
13041 expr = endexpression;
13042 /* and let the loop process it. */
13045 /* At this point, we're done with the expression. */
13046 if (numstackptr != numstack+1) {
13047 /* ... but if there isn't, it's bad */
13052 if (numstack->var) {
13053 /* expression is $((var)) only, lookup now */
13054 errcode = arith_lookup_val(numstack);
13057 *perrcode = errcode;
13058 return numstack->val;
13061 /* Continue processing the expression. */
13062 if (arith_isspace(arithval)) {
13063 /* Skip whitespace */
13066 p = endofname(expr);
13068 size_t var_name_size = (p-expr) + 1; /* trailing zero */
13070 numstackptr->var = alloca(var_name_size);
13071 safe_strncpy(numstackptr->var, expr, var_name_size);
13074 numstackptr->contidional_second_val_initialized = 0;
13079 if (isdigit(arithval)) {
13080 numstackptr->var = NULL;
13081 #if ENABLE_ASH_MATH_SUPPORT_64
13082 numstackptr->val = strtoll(expr, (char **) &expr, 0);
13084 numstackptr->val = strtol(expr, (char **) &expr, 0);
13088 for (p = op_tokens; ; p++) {
13092 /* strange operator not found */
13095 for (o = expr; *p && *o == *p; p++)
13102 /* skip tail uncompared token */
13105 /* skip zero delim */
13110 /* post grammar: a++ reduce to num */
13111 if (lasttok == TOK_POST_INC || lasttok == TOK_POST_DEC)
13114 /* Plus and minus are binary (not unary) _only_ if the last
13115 * token was as number, or a right paren (which pretends to be
13116 * a number, since it evaluates to one). Think about it.
13117 * It makes sense. */
13118 if (lasttok != TOK_NUM) {
13134 /* We don't want a unary operator to cause recursive descent on the
13135 * stack, because there can be many in a row and it could cause an
13136 * operator to be evaluated before its argument is pushed onto the
13137 * integer stack. */
13138 /* But for binary operators, "apply" everything on the operator
13139 * stack until we find an operator with a lesser priority than the
13140 * one we have just extracted. */
13141 /* Left paren is given the lowest priority so it will never be
13142 * "applied" in this way.
13143 * if associativity is right and priority eq, applied also skip
13146 if ((prec > 0 && prec < UNARYPREC) || prec == SPEC_PREC) {
13147 /* not left paren or unary */
13148 if (lasttok != TOK_NUM) {
13149 /* binary op must be preceded by a num */
13152 while (stackptr != stack) {
13153 if (op == TOK_RPAREN) {
13154 /* The algorithm employed here is simple: while we don't
13155 * hit an open paren nor the bottom of the stack, pop
13156 * tokens and apply them */
13157 if (stackptr[-1] == TOK_LPAREN) {
13159 /* Any operator directly after a */
13161 /* close paren should consider itself binary */
13165 operator prev_prec = PREC(stackptr[-1]);
13167 convert_prec_is_assing(prec);
13168 convert_prec_is_assing(prev_prec);
13169 if (prev_prec < prec)
13171 /* check right assoc */
13172 if (prev_prec == prec && is_right_associativity(prec))
13175 errcode = arith_apply(*--stackptr, numstack, &numstackptr);
13176 if (errcode) goto ret;
13178 if (op == TOK_RPAREN) {
13183 /* Push this operator to the stack and remember it. */
13184 *stackptr++ = lasttok = op;
13189 #endif /* ASH_MATH_SUPPORT */
13192 /* ============ main() and helpers */
13195 * Called to exit the shell.
13197 static void exitshell(void) ATTRIBUTE_NORETURN;
13205 status = exitstatus;
13206 TRACE(("pid %d, exitshell(%d)\n", getpid(), status));
13207 if (setjmp(loc.loc)) {
13208 if (exception == EXEXIT)
13209 /* dash bug: it just does _exit(exitstatus) here
13210 * but we have to do setjobctl(0) first!
13211 * (bug is still not fixed in dash-0.5.3 - if you run dash
13212 * under Midnight Commander, on exit from dash MC is backgrounded) */
13213 status = exitstatus;
13216 exception_handler = &loc;
13222 flush_stdout_stderr();
13232 /* from input.c: */
13233 basepf.nextc = basepf.buf = basebuf;
13236 signal(SIGCHLD, SIG_DFL);
13241 char ppid[sizeof(int)*3 + 1];
13243 struct stat st1, st2;
13246 for (envp = environ; envp && *envp; envp++) {
13247 if (strchr(*envp, '=')) {
13248 setvareq(*envp, VEXPORT|VTEXTFIXED);
13252 snprintf(ppid, sizeof(ppid), "%u", (unsigned) getppid());
13253 setvar("PPID", ppid, 0);
13255 p = lookupvar("PWD");
13257 if (*p != '/' || stat(p, &st1) || stat(".", &st2)
13258 || st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino)
13265 * Process the shell command line arguments.
13268 procargs(char **argv)
13271 const char *xminusc;
13276 /* if (xargv[0]) - mmm, this is always true! */
13278 for (i = 0; i < NOPTS; i++)
13282 /* it already printed err message */
13283 raise_exception(EXERROR);
13287 if (*xargv == NULL) {
13289 ash_msg_and_raise_error(bb_msg_requires_arg, "-c");
13292 if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
13296 for (i = 0; i < NOPTS; i++)
13297 if (optlist[i] == 2)
13302 /* POSIX 1003.2: first arg after -c cmd is $0, remainder $1... */
13307 } else if (!sflag) {
13308 setinputfile(*xargv, 0);
13311 commandname = arg0;
13314 shellparam.p = xargv;
13315 #if ENABLE_ASH_GETOPTS
13316 shellparam.optind = 1;
13317 shellparam.optoff = -1;
13319 /* assert(shellparam.malloced == 0 && shellparam.nparam == 0); */
13321 shellparam.nparam++;
13328 * Read /etc/profile or .profile.
13331 read_profile(const char *name)
13335 if (setinputfile(name, INPUT_PUSH_FILE | INPUT_NOFILE_OK) < 0)
13344 * This routine is called when an error or an interrupt occurs in an
13345 * interactive shell and control is returned to the main command loop.
13353 /* from input.c: */
13354 parselleft = parsenleft = 0; /* clear input buffer */
13356 /* from parser.c: */
13359 /* from redir.c: */
13364 static short profile_buf[16384];
13365 extern int etext();
13369 * Main routine. We initialize things, parse the arguments, execute
13370 * profiles if we're a login shell, and then call cmdloop to execute
13371 * commands. The setjmp call sets up the location to jump to when an
13372 * exception occurs. When an exception occurs the variable "state"
13373 * is used to figure out how far we had gotten.
13375 int ash_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
13376 int ash_main(int argc ATTRIBUTE_UNUSED, char **argv)
13379 volatile int state;
13380 struct jmploc jmploc;
13381 struct stackmark smark;
13383 /* Initialize global data */
13387 #if ENABLE_ASH_ALIAS
13393 monitor(4, etext, profile_buf, sizeof(profile_buf), 50);
13396 #if ENABLE_FEATURE_EDITING
13397 line_input_state = new_line_input_t(FOR_SHELL | WITH_PATH_LOOKUP);
13400 if (setjmp(jmploc.loc)) {
13410 if (e == EXEXIT || s == 0 || iflag == 0 || shlvl)
13414 outcslow('\n', stderr);
13416 popstackmark(&smark);
13417 FORCE_INT_ON; /* enable interrupts */
13426 exception_handler = &jmploc;
13429 trace_puts("Shell args: ");
13430 trace_puts_args(argv);
13432 rootpid = getpid();
13434 #if ENABLE_ASH_RANDOM_SUPPORT
13435 /* Can use monotonic_ns() for better randomness but for now it is
13436 * not used anywhere else in busybox... so avoid bloat */
13437 random_galois_LFSR = random_LCG = rootpid + monotonic_us();
13440 setstackmark(&smark);
13443 #if ENABLE_FEATURE_EDITING_SAVEHISTORY
13445 const char *hp = lookupvar("HISTFILE");
13448 hp = lookupvar("HOME");
13450 char *defhp = concat_path_file(hp, ".ash_history");
13451 setvar("HISTFILE", defhp, 0);
13457 if (argv[0] && argv[0][0] == '-')
13461 read_profile("/etc/profile");
13464 read_profile(".profile");
13470 getuid() == geteuid() && getgid() == getegid() &&
13474 shinit = lookupvar("ENV");
13475 if (shinit != NULL && *shinit != '\0') {
13476 read_profile(shinit);
13482 evalstring(minusc, 0);
13484 if (sflag || minusc == NULL) {
13485 #if ENABLE_FEATURE_EDITING_SAVEHISTORY
13487 const char *hp = lookupvar("HISTFILE");
13490 line_input_state->hist_file = hp;
13493 state4: /* XXX ??? - why isn't this before the "if" statement */
13501 extern void _mcleanup(void);
13510 const char *applet_name = "debug stuff usage";
13511 int main(int argc, char **argv)
13513 return ash_main(argc, argv);
13519 * Copyright (c) 1989, 1991, 1993, 1994
13520 * The Regents of the University of California. All rights reserved.
13522 * This code is derived from software contributed to Berkeley by
13523 * Kenneth Almquist.
13525 * Redistribution and use in source and binary forms, with or without
13526 * modification, are permitted provided that the following conditions
13528 * 1. Redistributions of source code must retain the above copyright
13529 * notice, this list of conditions and the following disclaimer.
13530 * 2. Redistributions in binary form must reproduce the above copyright
13531 * notice, this list of conditions and the following disclaimer in the
13532 * documentation and/or other materials provided with the distribution.
13533 * 3. Neither the name of the University nor the names of its contributors
13534 * may be used to endorse or promote products derived from this software
13535 * without specific prior written permission.
13537 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
13538 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
13539 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
13540 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
13541 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
13542 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
13543 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
13544 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
13545 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
13546 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF