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.
11 * This code is derived from software contributed to Berkeley by
14 * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
16 * Original BSD copyright notice is retained at the end of this file.
20 * rewrite arith.y to micro stack based cryptic algorithm by
21 * Copyright (c) 2001 Aaron Lehmann <aaronl@vitelus.com>
23 * Modified by Paul Mundt <lethal@linux-sh.org> (c) 2004 to support
26 * Modified by Vladimir Oleynik <dzo@simtreas.ru> (c) 2001-2005 to be
27 * used in busybox and size optimizations,
28 * rewrote arith (see notes to this), added locale support,
29 * rewrote dynamic variables.
33 * The follow should be set to reflect the type of system you have:
34 * JOBS -> 1 if you have Berkeley job control, 0 otherwise.
35 * define SYSV if you are running under System V.
36 * define DEBUG=1 to compile in debugging ('set -o debug' to turn on)
37 * define DEBUG=2 to compile in and turn on debugging.
39 * When debugging is on, debugging info will be written to ./trace and
40 * a quit signal will generate a core dump.
47 #define JOBS ENABLE_ASH_JOB_CONTROL
55 #include "busybox.h" /* for applet_names */
56 //TODO: pull in some .h and find out do we have SINGLE_APPLET_MAIN?
57 //#include "applet_tables.h" doesn't work
62 #if defined SINGLE_APPLET_MAIN
63 /* STANDALONE does not make sense, and won't compile */
64 #undef CONFIG_FEATURE_SH_STANDALONE
65 #undef ENABLE_FEATURE_SH_STANDALONE
66 #undef USE_FEATURE_SH_STANDALONE
67 #undef SKIP_FEATURE_SH_STANDALONE(...)
68 #define ENABLE_FEATURE_SH_STANDALONE 0
69 #define USE_FEATURE_SH_STANDALONE(...)
70 #define SKIP_FEATURE_SH_STANDALONE(...) __VA_ARGS__
74 #define PIPE_BUF 4096 /* amount of buffering in a pipe */
77 #if defined(__uClinux__)
78 #error "Do not even bother, ash will not run on NOMMU machine"
82 /* ============ Hash table sizes. Configurable. */
86 #define CMDTABLESIZE 31 /* should be prime */
89 /* ============ Misc helpers */
91 #define xbarrier() do { __asm__ __volatile__ ("": : :"memory"); } while (0)
93 /* C99 says: "char" declaration may be signed or unsigned by default */
94 #define signed_char2int(sc) ((int)((signed char)sc))
97 /* ============ Shell options */
99 static const char *const optletters_optnames[] = {
120 #define optletters(n) optletters_optnames[(n)][0]
121 #define optnames(n) (&optletters_optnames[(n)][1])
123 enum { NOPTS = ARRAY_SIZE(optletters_optnames) };
126 /* ============ Misc data */
128 static const char homestr[] ALIGN1 = "HOME";
129 static const char snlfmt[] ALIGN1 = "%s\n";
130 static const char illnum[] ALIGN1 = "Illegal number: %s";
133 * We enclose jmp_buf in a structure so that we can declare pointers to
134 * jump locations. The global variable handler contains the location to
135 * jump to when an exception occurs, and the global variable exception
136 * contains a code identifying the exception. To implement nested
137 * exception handlers, the user should save the value of handler on entry
138 * to an inner scope, set handler to point to a jmploc structure for the
139 * inner scope, and restore handler on exit from the scope.
145 struct globals_misc {
146 /* pid of main shell */
148 /* shell level: 0 for the main shell, 1 for its children, and so on */
150 #define rootshell (!shlvl)
151 char *minusc; /* argument to -c option */
153 char *curdir; // = nullstr; /* current working directory */
154 char *physdir; // = nullstr; /* physical working directory */
156 char *arg0; /* value of $0 */
158 struct jmploc *exception_handler;
160 // disabled by vda: cannot understand how it was supposed to work -
161 // cannot fix bugs. That's why you have to explain your non-trivial designs!
162 // /* do we generate EXSIG events */
163 // int exsig; /* counter */
164 volatile int suppressint; /* counter */
165 volatile /*sig_atomic_t*/ smallint intpending; /* 1 = got SIGINT */
166 /* last pending signal */
167 volatile /*sig_atomic_t*/ smallint pendingsig;
168 smallint exception; /* kind of exception (0..5) */
170 #define EXINT 0 /* SIGINT received */
171 #define EXERROR 1 /* a generic error */
172 #define EXSHELLPROC 2 /* execute a shell procedure */
173 #define EXEXEC 3 /* command execution failed */
174 #define EXEXIT 4 /* exit the shell */
175 #define EXSIG 5 /* trapped signal in wait(1) */
178 char nullstr[1]; /* zero length string */
181 #define eflag optlist[0]
182 #define fflag optlist[1]
183 #define Iflag optlist[2]
184 #define iflag optlist[3]
185 #define mflag optlist[4]
186 #define nflag optlist[5]
187 #define sflag optlist[6]
188 #define xflag optlist[7]
189 #define vflag optlist[8]
190 #define Cflag optlist[9]
191 #define aflag optlist[10]
192 #define bflag optlist[11]
193 #define uflag optlist[12]
194 #define viflag optlist[13]
196 #define nolog optlist[14]
197 #define debug optlist[15]
200 /* trap handler commands */
202 * Sigmode records the current value of the signal handlers for the various
203 * modes. A value of zero means that the current handler is not known.
204 * S_HARD_IGN indicates that the signal was ignored on entry to the shell.
206 char sigmode[NSIG - 1];
207 #define S_DFL 1 /* default signal handling (SIG_DFL) */
208 #define S_CATCH 2 /* signal is caught */
209 #define S_IGN 3 /* signal is ignored (SIG_IGN) */
210 #define S_HARD_IGN 4 /* signal is ignored permenantly */
212 /* indicates specified signal received */
213 char gotsig[NSIG - 1]; /* offset by 1: "signal" 0 is meaningless */
216 /* Rarely referenced stuff */
217 #if ENABLE_ASH_RANDOM_SUPPORT
218 /* Random number generators */
219 int32_t random_galois_LFSR; /* Galois LFSR (fast but weak). signed! */
220 uint32_t random_LCG; /* LCG (fast but weak) */
222 pid_t backgndpid; /* pid of last background process */
223 smallint job_warning; /* user was warned about stopped jobs (can be 2, 1 or 0). */
225 extern struct globals_misc *const ash_ptr_to_globals_misc;
226 #define G_misc (*ash_ptr_to_globals_misc)
227 #define rootpid (G_misc.rootpid )
228 #define shlvl (G_misc.shlvl )
229 #define minusc (G_misc.minusc )
230 #define curdir (G_misc.curdir )
231 #define physdir (G_misc.physdir )
232 #define arg0 (G_misc.arg0 )
233 #define exception_handler (G_misc.exception_handler)
234 #define exception (G_misc.exception )
235 #define suppressint (G_misc.suppressint )
236 #define intpending (G_misc.intpending )
237 //#define exsig (G_misc.exsig )
238 #define pendingsig (G_misc.pendingsig )
239 #define isloginsh (G_misc.isloginsh )
240 #define nullstr (G_misc.nullstr )
241 #define optlist (G_misc.optlist )
242 #define sigmode (G_misc.sigmode )
243 #define gotsig (G_misc.gotsig )
244 #define trap (G_misc.trap )
245 #define random_galois_LFSR (G_misc.random_galois_LFSR)
246 #define random_LCG (G_misc.random_LCG )
247 #define backgndpid (G_misc.backgndpid )
248 #define job_warning (G_misc.job_warning)
249 #define INIT_G_misc() do { \
250 (*(struct globals_misc**)&ash_ptr_to_globals_misc) = xzalloc(sizeof(G_misc)); \
257 /* ============ Utility functions */
258 static int isdigit_str9(const char *str)
260 int maxlen = 9 + 1; /* max 9 digits: 999999999 */
261 while (--maxlen && isdigit(*str))
263 return (*str == '\0');
267 /* ============ Interrupts / exceptions */
269 * These macros allow the user to suspend the handling of interrupt signals
270 * over a period of time. This is similar to SIGHOLD or to sigblock, but
271 * much more efficient and portable. (But hacking the kernel is so much
272 * more fun than worrying about efficiency and portability. :-))
274 #define INT_OFF do { \
280 * Called to raise an exception. Since C doesn't include exceptions, we
281 * just do a longjmp to the exception handler. The type of exception is
282 * stored in the global variable "exception".
284 static void raise_exception(int) NORETURN;
286 raise_exception(int e)
289 if (exception_handler == NULL)
294 longjmp(exception_handler->loc, 1);
298 * Called from trap.c when a SIGINT is received. (If the user specifies
299 * that SIGINT is to be trapped or ignored using the trap builtin, then
300 * this routine is not called.) Suppressint is nonzero when interrupts
301 * are held using the INT_OFF macro. (The test for iflag is just
302 * defensive programming.)
304 static void raise_interrupt(void) NORETURN;
306 raise_interrupt(void)
311 /* Signal is not automatically unmasked after it is raised,
312 * do it ourself - unmask all signals */
313 sigprocmask_allsigs(SIG_UNBLOCK);
314 /* pendingsig = 0; - now done in onsig() */
317 if (gotsig[SIGINT - 1] && !trap[SIGINT]) {
318 if (!(rootshell && iflag)) {
319 /* Kill ourself with SIGINT */
320 signal(SIGINT, SIG_DFL);
329 #if ENABLE_ASH_OPTIMIZE_FOR_SIZE
333 if (--suppressint == 0 && intpending) {
337 #define INT_ON int_on()
345 #define FORCE_INT_ON force_int_on()
347 #define INT_ON do { \
349 if (--suppressint == 0 && intpending) \
352 #define FORCE_INT_ON do { \
358 #endif /* ASH_OPTIMIZE_FOR_SIZE */
360 #define SAVE_INT(v) ((v) = suppressint)
362 #define RESTORE_INT(v) do { \
365 if (suppressint == 0 && intpending) \
370 * Ignore a signal. Avoids unnecessary system calls.
375 if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) {
376 signal(signo, SIG_IGN);
378 sigmode[signo - 1] = S_HARD_IGN;
382 * Signal handler. Only one usage site - in setsignal()
387 gotsig[signo - 1] = 1;
390 if (/* exsig || */ (signo == SIGINT && !trap[SIGINT])) {
393 raise_interrupt(); /* does not return */
400 /* ============ Stdout/stderr output */
403 outstr(const char *p, FILE *file)
411 flush_stdout_stderr(void)
428 outcslow(int c, FILE *dest)
436 static int out1fmt(const char *, ...) __attribute__((__format__(__printf__,1,2)));
438 out1fmt(const char *fmt, ...)
445 r = vprintf(fmt, ap);
451 static int fmtstr(char *, size_t, const char *, ...) __attribute__((__format__(__printf__,3,4)));
453 fmtstr(char *outbuf, size_t length, const char *fmt, ...)
460 ret = vsnprintf(outbuf, length, fmt, ap);
467 out1str(const char *p)
473 out2str(const char *p)
480 /* ============ Parser structures */
482 /* control characters in argument strings */
483 #define CTLESC '\201' /* escape next character */
484 #define CTLVAR '\202' /* variable defn */
485 #define CTLENDVAR '\203'
486 #define CTLBACKQ '\204'
487 #define CTLQUOTE 01 /* ored with CTLBACKQ code if in quotes */
488 /* CTLBACKQ | CTLQUOTE == '\205' */
489 #define CTLARI '\206' /* arithmetic expression */
490 #define CTLENDARI '\207'
491 #define CTLQUOTEMARK '\210'
493 /* variable substitution byte (follows CTLVAR) */
494 #define VSTYPE 0x0f /* type of variable substitution */
495 #define VSNUL 0x10 /* colon--treat the empty string as unset */
496 #define VSQUOTE 0x80 /* inside double quotes--suppress splitting */
498 /* values of VSTYPE field */
499 #define VSNORMAL 0x1 /* normal variable: $var or ${var} */
500 #define VSMINUS 0x2 /* ${var-text} */
501 #define VSPLUS 0x3 /* ${var+text} */
502 #define VSQUESTION 0x4 /* ${var?message} */
503 #define VSASSIGN 0x5 /* ${var=text} */
504 #define VSTRIMRIGHT 0x6 /* ${var%pattern} */
505 #define VSTRIMRIGHTMAX 0x7 /* ${var%%pattern} */
506 #define VSTRIMLEFT 0x8 /* ${var#pattern} */
507 #define VSTRIMLEFTMAX 0x9 /* ${var##pattern} */
508 #define VSLENGTH 0xa /* ${#var} */
509 #if ENABLE_ASH_BASH_COMPAT
510 #define VSSUBSTR 0xc /* ${var:position:length} */
511 #define VSREPLACE 0xd /* ${var/pattern/replacement} */
512 #define VSREPLACEALL 0xe /* ${var//pattern/replacement} */
515 static const char dolatstr[] ALIGN1 = {
516 CTLVAR, VSNORMAL|VSQUOTE, '@', '=', '\0'
536 #if ENABLE_ASH_BASH_COMPAT
553 smallint type; /* Nxxxx */
556 union node *redirect;
561 smallint pipe_backgnd;
562 struct nodelist *cmdlist;
568 union node *redirect;
581 union node *elsepart;
608 struct nodelist *backquote;
611 /* nfile and ndup layout must match!
612 * NTOFD (>&fdnum) uses ndup structure, but we may discover mid-flight
613 * that it is actually NTO2 (>&file), and change its type.
630 char *_unused_expfname;
649 struct nredir nredir;
650 struct nbinary nbinary;
654 struct nclist nclist;
663 struct nodelist *next;
676 freefunc(struct funcnode *f)
678 if (f && --f->count < 0)
683 /* ============ Debugging output */
687 static FILE *tracefile;
690 trace_printf(const char *fmt, ...)
697 vfprintf(tracefile, fmt, va);
702 trace_vprintf(const char *fmt, va_list va)
706 vfprintf(tracefile, fmt, va);
710 trace_puts(const char *s)
718 trace_puts_quoted(char *s)
725 putc('"', tracefile);
726 for (p = s; *p; p++) {
728 case '\n': c = 'n'; goto backslash;
729 case '\t': c = 't'; goto backslash;
730 case '\r': c = 'r'; goto backslash;
731 case '"': c = '"'; goto backslash;
732 case '\\': c = '\\'; goto backslash;
733 case CTLESC: c = 'e'; goto backslash;
734 case CTLVAR: c = 'v'; goto backslash;
735 case CTLVAR+CTLQUOTE: c = 'V'; goto backslash;
736 case CTLBACKQ: c = 'q'; goto backslash;
737 case CTLBACKQ+CTLQUOTE: c = 'Q'; goto backslash;
739 putc('\\', tracefile);
743 if (*p >= ' ' && *p <= '~')
746 putc('\\', tracefile);
747 putc(*p >> 6 & 03, tracefile);
748 putc(*p >> 3 & 07, tracefile);
749 putc(*p & 07, tracefile);
754 putc('"', tracefile);
758 trace_puts_args(char **ap)
765 trace_puts_quoted(*ap);
767 putc('\n', tracefile);
770 putc(' ', tracefile);
785 /* leave open because libedit might be using it */
788 strcpy(s, "./trace");
790 if (!freopen(s, "a", tracefile)) {
791 fprintf(stderr, "Can't re-open %s\n", s);
796 tracefile = fopen(s, "a");
797 if (tracefile == NULL) {
798 fprintf(stderr, "Can't open %s\n", s);
804 flags = fcntl(fileno(tracefile), F_GETFL);
806 fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND);
808 setlinebuf(tracefile);
809 fputs("\nTracing started.\n", tracefile);
813 indent(int amount, char *pfx, FILE *fp)
817 for (i = 0; i < amount; i++) {
818 if (pfx && i == amount - 1)
824 /* little circular references here... */
825 static void shtree(union node *n, int ind, char *pfx, FILE *fp);
828 sharg(union node *arg, FILE *fp)
831 struct nodelist *bqlist;
834 if (arg->type != NARG) {
835 out1fmt("<node type %d>\n", arg->type);
838 bqlist = arg->narg.backquote;
839 for (p = arg->narg.text; *p; p++) {
848 if (subtype == VSLENGTH)
857 switch (subtype & VSTYPE) {
890 out1fmt("<subtype %d>", subtype);
897 case CTLBACKQ|CTLQUOTE:
900 shtree(bqlist->n, -1, NULL, fp);
911 shcmd(union node *cmd, FILE *fp)
919 for (np = cmd->ncmd.args; np; np = np->narg.next) {
925 for (np = cmd->ncmd.redirect; np; np = np->nfile.next) {
929 switch (np->nfile.type) {
930 case NTO: s = ">>"+1; dftfd = 1; break;
931 case NCLOBBER: s = ">|"; dftfd = 1; break;
932 case NAPPEND: s = ">>"; dftfd = 1; break;
933 #if ENABLE_ASH_BASH_COMPAT
936 case NTOFD: s = ">&"; dftfd = 1; break;
937 case NFROM: s = "<"; break;
938 case NFROMFD: s = "<&"; break;
939 case NFROMTO: s = "<>"; break;
940 default: s = "*error*"; break;
942 if (np->nfile.fd != dftfd)
943 fprintf(fp, "%d", np->nfile.fd);
945 if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) {
946 fprintf(fp, "%d", np->ndup.dupfd);
948 sharg(np->nfile.fname, fp);
955 shtree(union node *n, int ind, char *pfx, FILE *fp)
963 indent(ind, pfx, fp);
974 shtree(n->nbinary.ch1, ind, NULL, fp);
977 shtree(n->nbinary.ch2, ind, NULL, fp);
985 for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
990 if (n->npipe.pipe_backgnd)
996 fprintf(fp, "<node type %d>", n->type);
1004 showtree(union node *n)
1006 trace_puts("showtree called\n");
1007 shtree(n, 1, NULL, stdout);
1010 #define TRACE(param) trace_printf param
1011 #define TRACEV(param) trace_vprintf param
1015 #define TRACE(param)
1016 #define TRACEV(param)
1021 /* ============ Parser data */
1024 * ash_vmsg() needs parsefile->fd, hence parsefile definition is moved up.
1027 struct strlist *next;
1034 struct strpush *prev; /* preceding string on stack */
1036 int prev_left_in_line;
1037 #if ENABLE_ASH_ALIAS
1038 struct alias *ap; /* if push was associated with an alias */
1040 char *string; /* remember the string since it may change */
1044 struct parsefile *prev; /* preceding file on stack */
1045 int linno; /* current line */
1046 int fd; /* file descriptor (or -1 if string) */
1047 int left_in_line; /* number of chars left in this line */
1048 int left_in_buffer; /* number of chars left in this buffer past the line */
1049 char *next_to_pgetc; /* next char in buffer */
1050 char *buf; /* input buffer */
1051 struct strpush *strpush; /* for pushing strings at this level */
1052 struct strpush basestrpush; /* so pushing one is fast */
1055 static struct parsefile basepf; /* top level input file */
1056 static struct parsefile *g_parsefile = &basepf; /* current input file */
1057 static int startlinno; /* line # where last token started */
1058 static char *commandname; /* currently executing command */
1059 static struct strlist *cmdenviron; /* environment for builtin command */
1060 static uint8_t exitstatus; /* exit status of last command */
1063 /* ============ Message printing */
1066 ash_vmsg(const char *msg, va_list ap)
1068 fprintf(stderr, "%s: ", arg0);
1070 if (strcmp(arg0, commandname))
1071 fprintf(stderr, "%s: ", commandname);
1072 if (!iflag || g_parsefile->fd)
1073 fprintf(stderr, "line %d: ", startlinno);
1075 vfprintf(stderr, msg, ap);
1076 outcslow('\n', stderr);
1080 * Exverror is called to raise the error exception. If the second argument
1081 * is not NULL then error prints an error message using printf style
1082 * formatting. It then raises the error exception.
1084 static void ash_vmsg_and_raise(int, const char *, va_list) NORETURN;
1086 ash_vmsg_and_raise(int cond, const char *msg, va_list ap)
1090 TRACE(("ash_vmsg_and_raise(%d, \"", cond));
1092 TRACE(("\") pid=%d\n", getpid()));
1094 TRACE(("ash_vmsg_and_raise(%d, NULL) pid=%d\n", cond, getpid()));
1099 flush_stdout_stderr();
1100 raise_exception(cond);
1104 static void ash_msg_and_raise_error(const char *, ...) NORETURN;
1106 ash_msg_and_raise_error(const char *msg, ...)
1111 ash_vmsg_and_raise(EXERROR, msg, ap);
1116 static void ash_msg_and_raise(int, const char *, ...) NORETURN;
1118 ash_msg_and_raise(int cond, const char *msg, ...)
1123 ash_vmsg_and_raise(cond, msg, ap);
1129 * error/warning routines for external builtins
1132 ash_msg(const char *fmt, ...)
1142 * Return a string describing an error. The returned string may be a
1143 * pointer to a static buffer that will be overwritten on the next call.
1144 * Action describes the operation that got the error.
1147 errmsg(int e, const char *em)
1149 if (e == ENOENT || e == ENOTDIR) {
1156 /* ============ Memory allocation */
1159 * It appears that grabstackstr() will barf with such alignments
1160 * because stalloc() will return a string allocated in a new stackblock.
1162 #define SHELL_ALIGN(nbytes) (((nbytes) + SHELL_SIZE) & ~SHELL_SIZE)
1164 /* Most machines require the value returned from malloc to be aligned
1165 * in some way. The following macro will get this right
1166 * on many machines. */
1167 SHELL_SIZE = sizeof(union {int i; char *cp; double d; }) - 1,
1168 /* Minimum size of a block */
1169 MINSIZE = SHELL_ALIGN(504),
1172 struct stack_block {
1173 struct stack_block *prev;
1174 char space[MINSIZE];
1178 struct stack_block *stackp;
1181 struct stackmark *marknext;
1185 struct globals_memstack {
1186 struct stack_block *g_stackp; // = &stackbase;
1187 struct stackmark *markp;
1188 char *g_stacknxt; // = stackbase.space;
1189 char *sstrend; // = stackbase.space + MINSIZE;
1190 size_t g_stacknleft; // = MINSIZE;
1191 int herefd; // = -1;
1192 struct stack_block stackbase;
1194 extern struct globals_memstack *const ash_ptr_to_globals_memstack;
1195 #define G_memstack (*ash_ptr_to_globals_memstack)
1196 #define g_stackp (G_memstack.g_stackp )
1197 #define markp (G_memstack.markp )
1198 #define g_stacknxt (G_memstack.g_stacknxt )
1199 #define sstrend (G_memstack.sstrend )
1200 #define g_stacknleft (G_memstack.g_stacknleft)
1201 #define herefd (G_memstack.herefd )
1202 #define stackbase (G_memstack.stackbase )
1203 #define INIT_G_memstack() do { \
1204 (*(struct globals_memstack**)&ash_ptr_to_globals_memstack) = xzalloc(sizeof(G_memstack)); \
1206 g_stackp = &stackbase; \
1207 g_stacknxt = stackbase.space; \
1208 g_stacknleft = MINSIZE; \
1209 sstrend = stackbase.space + MINSIZE; \
1213 #define stackblock() ((void *)g_stacknxt)
1214 #define stackblocksize() g_stacknleft
1218 ckrealloc(void * p, size_t nbytes)
1220 p = realloc(p, nbytes);
1222 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1227 ckmalloc(size_t nbytes)
1229 return ckrealloc(NULL, nbytes);
1233 ckzalloc(size_t nbytes)
1235 return memset(ckmalloc(nbytes), 0, nbytes);
1239 * Make a copy of a string in safe storage.
1242 ckstrdup(const char *s)
1244 char *p = strdup(s);
1246 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1251 * Parse trees for commands are allocated in lifo order, so we use a stack
1252 * to make this more efficient, and also to avoid all sorts of exception
1253 * handling code to handle interrupts in the middle of a parse.
1255 * The size 504 was chosen because the Ultrix malloc handles that size
1259 stalloc(size_t nbytes)
1264 aligned = SHELL_ALIGN(nbytes);
1265 if (aligned > g_stacknleft) {
1268 struct stack_block *sp;
1270 blocksize = aligned;
1271 if (blocksize < MINSIZE)
1272 blocksize = MINSIZE;
1273 len = sizeof(struct stack_block) - MINSIZE + blocksize;
1274 if (len < blocksize)
1275 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1278 sp->prev = g_stackp;
1279 g_stacknxt = sp->space;
1280 g_stacknleft = blocksize;
1281 sstrend = g_stacknxt + blocksize;
1286 g_stacknxt += aligned;
1287 g_stacknleft -= aligned;
1292 stzalloc(size_t nbytes)
1294 return memset(stalloc(nbytes), 0, nbytes);
1301 if (!p || (g_stacknxt < (char *)p) || ((char *)p < g_stackp->space)) {
1302 write(STDERR_FILENO, "stunalloc\n", 10);
1306 g_stacknleft += g_stacknxt - (char *)p;
1311 * Like strdup but works with the ash stack.
1314 ststrdup(const char *p)
1316 size_t len = strlen(p) + 1;
1317 return memcpy(stalloc(len), p, len);
1321 setstackmark(struct stackmark *mark)
1323 mark->stackp = g_stackp;
1324 mark->stacknxt = g_stacknxt;
1325 mark->stacknleft = g_stacknleft;
1326 mark->marknext = markp;
1331 popstackmark(struct stackmark *mark)
1333 struct stack_block *sp;
1339 markp = mark->marknext;
1340 while (g_stackp != mark->stackp) {
1342 g_stackp = sp->prev;
1345 g_stacknxt = mark->stacknxt;
1346 g_stacknleft = mark->stacknleft;
1347 sstrend = mark->stacknxt + mark->stacknleft;
1352 * When the parser reads in a string, it wants to stick the string on the
1353 * stack and only adjust the stack pointer when it knows how big the
1354 * string is. Stackblock (defined in stack.h) returns a pointer to a block
1355 * of space on top of the stack and stackblocklen returns the length of
1356 * this block. Growstackblock will grow this space by at least one byte,
1357 * possibly moving it (like realloc). Grabstackblock actually allocates the
1358 * part of the block that has been used.
1361 growstackblock(void)
1365 newlen = g_stacknleft * 2;
1366 if (newlen < g_stacknleft)
1367 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1371 if (g_stacknxt == g_stackp->space && g_stackp != &stackbase) {
1372 struct stack_block *oldstackp;
1373 struct stackmark *xmark;
1374 struct stack_block *sp;
1375 struct stack_block *prevstackp;
1379 oldstackp = g_stackp;
1381 prevstackp = sp->prev;
1382 grosslen = newlen + sizeof(struct stack_block) - MINSIZE;
1383 sp = ckrealloc(sp, grosslen);
1384 sp->prev = prevstackp;
1386 g_stacknxt = sp->space;
1387 g_stacknleft = newlen;
1388 sstrend = sp->space + newlen;
1391 * Stack marks pointing to the start of the old block
1392 * must be relocated to point to the new block
1395 while (xmark != NULL && xmark->stackp == oldstackp) {
1396 xmark->stackp = g_stackp;
1397 xmark->stacknxt = g_stacknxt;
1398 xmark->stacknleft = g_stacknleft;
1399 xmark = xmark->marknext;
1403 char *oldspace = g_stacknxt;
1404 size_t oldlen = g_stacknleft;
1405 char *p = stalloc(newlen);
1407 /* free the space we just allocated */
1408 g_stacknxt = memcpy(p, oldspace, oldlen);
1409 g_stacknleft += newlen;
1414 grabstackblock(size_t len)
1416 len = SHELL_ALIGN(len);
1418 g_stacknleft -= len;
1422 * The following routines are somewhat easier to use than the above.
1423 * The user declares a variable of type STACKSTR, which may be declared
1424 * to be a register. The macro STARTSTACKSTR initializes things. Then
1425 * the user uses the macro STPUTC to add characters to the string. In
1426 * effect, STPUTC(c, p) is the same as *p++ = c except that the stack is
1427 * grown as necessary. When the user is done, she can just leave the
1428 * string there and refer to it using stackblock(). Or she can allocate
1429 * the space for it using grabstackstr(). If it is necessary to allow
1430 * someone else to use the stack temporarily and then continue to grow
1431 * the string, the user should use grabstack to allocate the space, and
1432 * then call ungrabstr(p) to return to the previous mode of operation.
1434 * USTPUTC is like STPUTC except that it doesn't check for overflow.
1435 * CHECKSTACKSPACE can be called before USTPUTC to ensure that there
1436 * is space for at least one character.
1441 size_t len = stackblocksize();
1442 if (herefd >= 0 && len >= 1024) {
1443 full_write(herefd, stackblock(), len);
1444 return stackblock();
1447 return (char *)stackblock() + len;
1451 * Called from CHECKSTRSPACE.
1454 makestrspace(size_t newlen, char *p)
1456 size_t len = p - g_stacknxt;
1457 size_t size = stackblocksize();
1462 size = stackblocksize();
1464 if (nleft >= newlen)
1468 return (char *)stackblock() + len;
1472 stack_nputstr(const char *s, size_t n, char *p)
1474 p = makestrspace(n, p);
1475 p = (char *)memcpy(p, s, n) + n;
1480 stack_putstr(const char *s, char *p)
1482 return stack_nputstr(s, strlen(s), p);
1486 _STPUTC(int c, char *p)
1494 #define STARTSTACKSTR(p) ((p) = stackblock())
1495 #define STPUTC(c, p) ((p) = _STPUTC((c), (p)))
1496 #define CHECKSTRSPACE(n, p) do { \
1499 size_t m = sstrend - q; \
1501 (p) = makestrspace(l, q); \
1503 #define USTPUTC(c, p) (*(p)++ = (c))
1504 #define STACKSTRNUL(p) do { \
1505 if ((p) == sstrend) \
1506 (p) = growstackstr(); \
1509 #define STUNPUTC(p) (--(p))
1510 #define STTOPC(p) ((p)[-1])
1511 #define STADJUST(amount, p) ((p) += (amount))
1513 #define grabstackstr(p) stalloc((char *)(p) - (char *)stackblock())
1514 #define ungrabstackstr(s, p) stunalloc(s)
1515 #define stackstrend() ((void *)sstrend)
1518 /* ============ String helpers */
1521 * prefix -- see if pfx is a prefix of string.
1524 prefix(const char *string, const char *pfx)
1527 if (*pfx++ != *string++)
1530 return (char *) string;
1534 * Check for a valid number. This should be elsewhere.
1537 is_number(const char *p)
1542 } while (*++p != '\0');
1547 * Convert a string of digits to an integer, printing an error message on
1551 number(const char *s)
1554 ash_msg_and_raise_error(illnum, s);
1559 * Produce a possibly single quoted string suitable as input to the shell.
1560 * The return string is allocated on the stack.
1563 single_quote(const char *s)
1573 len = strchrnul(s, '\'') - s;
1575 q = p = makestrspace(len + 3, p);
1578 q = (char *)memcpy(q, s, len) + len;
1584 len = strspn(s, "'");
1588 q = p = makestrspace(len + 3, p);
1591 q = (char *)memcpy(q, s, len) + len;
1600 return stackblock();
1604 /* ============ nextopt */
1606 static char **argptr; /* argument list for builtin commands */
1607 static char *optionarg; /* set by nextopt (like getopt) */
1608 static char *optptr; /* used by nextopt */
1611 * XXX - should get rid of. Have all builtins use getopt(3).
1612 * The library getopt must have the BSD extension static variable
1613 * "optreset", otherwise it can't be used within the shell safely.
1615 * Standard option processing (a la getopt) for builtin routines.
1616 * The only argument that is passed to nextopt is the option string;
1617 * the other arguments are unnecessary. It returns the character,
1618 * or '\0' on end of input.
1621 nextopt(const char *optstring)
1628 if (p == NULL || *p == '\0') {
1629 /* We ate entire "-param", take next one */
1635 if (*++p == '\0') /* just "-" ? */
1638 if (LONE_DASH(p)) /* "--" ? */
1640 /* p => next "-param" */
1642 /* p => some option char in the middle of a "-param" */
1644 for (q = optstring; *q != c;) {
1646 ash_msg_and_raise_error("illegal option -%c", c);
1654 ash_msg_and_raise_error("no arg for -%c option", c);
1664 /* ============ Shell variables */
1667 * The parsefile structure pointed to by the global variable parsefile
1668 * contains information about the current file being read.
1671 int nparam; /* # of positional parameters (without $0) */
1672 #if ENABLE_ASH_GETOPTS
1673 int optind; /* next parameter to be processed by getopts */
1674 int optoff; /* used by getopts */
1676 unsigned char malloced; /* if parameter list dynamically allocated */
1677 char **p; /* parameter list */
1681 * Free the list of positional parameters.
1684 freeparam(volatile struct shparam *param)
1686 if (param->malloced) {
1688 ap = ap1 = param->p;
1695 #if ENABLE_ASH_GETOPTS
1696 static void getoptsreset(const char *value);
1700 struct var *next; /* next entry in hash list */
1701 int flags; /* flags are defined above */
1702 const char *text; /* name=value */
1703 void (*func)(const char *); /* function to be called when */
1704 /* the variable gets set/unset */
1708 struct localvar *next; /* next local variable in list */
1709 struct var *vp; /* the variable that was made local */
1710 int flags; /* saved flags */
1711 const char *text; /* saved text */
1715 #define VEXPORT 0x01 /* variable is exported */
1716 #define VREADONLY 0x02 /* variable cannot be modified */
1717 #define VSTRFIXED 0x04 /* variable struct is statically allocated */
1718 #define VTEXTFIXED 0x08 /* text is statically allocated */
1719 #define VSTACK 0x10 /* text is allocated on the stack */
1720 #define VUNSET 0x20 /* the variable is not set */
1721 #define VNOFUNC 0x40 /* don't call the callback function */
1722 #define VNOSET 0x80 /* do not set variable - just readonly test */
1723 #define VNOSAVE 0x100 /* when text is on the heap before setvareq */
1724 #if ENABLE_ASH_RANDOM_SUPPORT
1725 # define VDYNAMIC 0x200 /* dynamic variable */
1731 static const char defifsvar[] ALIGN1 = "IFS= \t\n";
1732 #define defifs (defifsvar + 4)
1734 static const char defifs[] ALIGN1 = " \t\n";
1738 /* Need to be before varinit_data[] */
1739 #if ENABLE_LOCALE_SUPPORT
1741 change_lc_all(const char *value)
1743 if (value && *value != '\0')
1744 setlocale(LC_ALL, value);
1747 change_lc_ctype(const char *value)
1749 if (value && *value != '\0')
1750 setlocale(LC_CTYPE, value);
1754 static void chkmail(void);
1755 static void changemail(const char *);
1757 static void changepath(const char *);
1758 #if ENABLE_ASH_RANDOM_SUPPORT
1759 static void change_random(const char *);
1762 static const struct {
1765 void (*func)(const char *);
1766 } varinit_data[] = {
1768 { VSTRFIXED|VTEXTFIXED , defifsvar , NULL },
1770 { VSTRFIXED|VTEXTFIXED|VUNSET, "IFS\0" , NULL },
1773 { VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL\0" , changemail },
1774 { VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH\0", changemail },
1776 { VSTRFIXED|VTEXTFIXED , bb_PATH_root_path, changepath },
1777 { VSTRFIXED|VTEXTFIXED , "PS1=$ " , NULL },
1778 { VSTRFIXED|VTEXTFIXED , "PS2=> " , NULL },
1779 { VSTRFIXED|VTEXTFIXED , "PS4=+ " , NULL },
1780 #if ENABLE_ASH_GETOPTS
1781 { VSTRFIXED|VTEXTFIXED , "OPTIND=1" , getoptsreset },
1783 #if ENABLE_ASH_RANDOM_SUPPORT
1784 { VSTRFIXED|VTEXTFIXED|VUNSET|VDYNAMIC, "RANDOM\0", change_random },
1786 #if ENABLE_LOCALE_SUPPORT
1787 { VSTRFIXED|VTEXTFIXED|VUNSET, "LC_ALL\0" , change_lc_all },
1788 { VSTRFIXED|VTEXTFIXED|VUNSET, "LC_CTYPE\0", change_lc_ctype },
1790 #if ENABLE_FEATURE_EDITING_SAVEHISTORY
1791 { VSTRFIXED|VTEXTFIXED|VUNSET, "HISTFILE\0", NULL },
1797 struct globals_var {
1798 struct shparam shellparam; /* $@ current positional parameters */
1799 struct redirtab *redirlist;
1801 int preverrout_fd; /* save fd2 before print debug if xflag is set. */
1802 struct var *vartab[VTABSIZE];
1803 struct var varinit[ARRAY_SIZE(varinit_data)];
1805 extern struct globals_var *const ash_ptr_to_globals_var;
1806 #define G_var (*ash_ptr_to_globals_var)
1807 #define shellparam (G_var.shellparam )
1808 //#define redirlist (G_var.redirlist )
1809 #define g_nullredirs (G_var.g_nullredirs )
1810 #define preverrout_fd (G_var.preverrout_fd)
1811 #define vartab (G_var.vartab )
1812 #define varinit (G_var.varinit )
1813 #define INIT_G_var() do { \
1815 (*(struct globals_var**)&ash_ptr_to_globals_var) = xzalloc(sizeof(G_var)); \
1817 for (i = 0; i < ARRAY_SIZE(varinit_data); i++) { \
1818 varinit[i].flags = varinit_data[i].flags; \
1819 varinit[i].text = varinit_data[i].text; \
1820 varinit[i].func = varinit_data[i].func; \
1824 #define vifs varinit[0]
1826 # define vmail (&vifs)[1]
1827 # define vmpath (&vmail)[1]
1828 # define vpath (&vmpath)[1]
1830 # define vpath (&vifs)[1]
1832 #define vps1 (&vpath)[1]
1833 #define vps2 (&vps1)[1]
1834 #define vps4 (&vps2)[1]
1835 #if ENABLE_ASH_GETOPTS
1836 # define voptind (&vps4)[1]
1837 # if ENABLE_ASH_RANDOM_SUPPORT
1838 # define vrandom (&voptind)[1]
1841 # if ENABLE_ASH_RANDOM_SUPPORT
1842 # define vrandom (&vps4)[1]
1847 * The following macros access the values of the above variables.
1848 * They have to skip over the name. They return the null string
1849 * for unset variables.
1851 #define ifsval() (vifs.text + 4)
1852 #define ifsset() ((vifs.flags & VUNSET) == 0)
1854 # define mailval() (vmail.text + 5)
1855 # define mpathval() (vmpath.text + 9)
1856 # define mpathset() ((vmpath.flags & VUNSET) == 0)
1858 #define pathval() (vpath.text + 5)
1859 #define ps1val() (vps1.text + 4)
1860 #define ps2val() (vps2.text + 4)
1861 #define ps4val() (vps4.text + 4)
1862 #if ENABLE_ASH_GETOPTS
1863 # define optindval() (voptind.text + 7)
1867 #define is_name(c) ((c) == '_' || isalpha((unsigned char)(c)))
1868 #define is_in_name(c) ((c) == '_' || isalnum((unsigned char)(c)))
1870 #if ENABLE_ASH_GETOPTS
1872 getoptsreset(const char *value)
1874 shellparam.optind = number(value);
1875 shellparam.optoff = -1;
1880 * Return of a legal variable name (a letter or underscore followed by zero or
1881 * more letters, underscores, and digits).
1884 endofname(const char *name)
1892 if (!is_in_name(*p))
1899 * Compares two strings up to the first = or '\0'. The first
1900 * string must be terminated by '='; the second may be terminated by
1901 * either '=' or '\0'.
1904 varcmp(const char *p, const char *q)
1908 while ((c = *p) == (d = *q)) {
1923 varequal(const char *a, const char *b)
1925 return !varcmp(a, b);
1929 * Find the appropriate entry in the hash table from the name.
1931 static struct var **
1932 hashvar(const char *p)
1936 hashval = ((unsigned char) *p) << 4;
1937 while (*p && *p != '=')
1938 hashval += (unsigned char) *p++;
1939 return &vartab[hashval % VTABSIZE];
1943 vpcmp(const void *a, const void *b)
1945 return varcmp(*(const char **)a, *(const char **)b);
1949 * This routine initializes the builtin variables.
1959 * PS1 depends on uid
1961 #if ENABLE_FEATURE_EDITING && ENABLE_FEATURE_EDITING_FANCY_PROMPT
1962 vps1.text = "PS1=\\w \\$ ";
1965 vps1.text = "PS1=# ";
1968 end = vp + ARRAY_SIZE(varinit);
1970 vpp = hashvar(vp->text);
1973 } while (++vp < end);
1976 static struct var **
1977 findvar(struct var **vpp, const char *name)
1979 for (; *vpp; vpp = &(*vpp)->next) {
1980 if (varequal((*vpp)->text, name)) {
1988 * Find the value of a variable. Returns NULL if not set.
1991 lookupvar(const char *name)
1995 v = *findvar(hashvar(name), name);
1997 #if ENABLE_ASH_RANDOM_SUPPORT
1999 * Dynamic variables are implemented roughly the same way they are
2000 * in bash. Namely, they're "special" so long as they aren't unset.
2001 * As soon as they're unset, they're no longer dynamic, and dynamic
2002 * lookup will no longer happen at that point. -- PFM.
2004 if ((v->flags & VDYNAMIC))
2007 if (!(v->flags & VUNSET))
2008 return strchrnul(v->text, '=') + 1;
2014 * Search the environment of a builtin command.
2017 bltinlookup(const char *name)
2021 for (sp = cmdenviron; sp; sp = sp->next) {
2022 if (varequal(sp->text, name))
2023 return strchrnul(sp->text, '=') + 1;
2025 return lookupvar(name);
2029 * Same as setvar except that the variable and value are passed in
2030 * the first argument as name=value. Since the first argument will
2031 * be actually stored in the table, it should not be a string that
2033 * Called with interrupts off.
2036 setvareq(char *s, int flags)
2038 struct var *vp, **vpp;
2041 flags |= (VEXPORT & (((unsigned) (1 - aflag)) - 1));
2042 vp = *findvar(vpp, s);
2044 if ((vp->flags & (VREADONLY|VDYNAMIC)) == VREADONLY) {
2047 if (flags & VNOSAVE)
2050 ash_msg_and_raise_error("%.*s: is read only", strchrnul(n, '=') - n, n);
2056 if (vp->func && (flags & VNOFUNC) == 0)
2057 (*vp->func)(strchrnul(s, '=') + 1);
2059 if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
2060 free((char*)vp->text);
2062 flags |= vp->flags & ~(VTEXTFIXED|VSTACK|VNOSAVE|VUNSET);
2067 vp = ckzalloc(sizeof(*vp));
2069 /*vp->func = NULL; - ckzalloc did it */
2072 if (!(flags & (VTEXTFIXED|VSTACK|VNOSAVE)))
2079 * Set the value of a variable. The flags argument is ored with the
2080 * flags of the variable. If val is NULL, the variable is unset.
2083 setvar(const char *name, const char *val, int flags)
2090 q = endofname(name);
2091 p = strchrnul(q, '=');
2093 if (!namelen || p != q)
2094 ash_msg_and_raise_error("%.*s: bad variable name", namelen, name);
2099 vallen = strlen(val);
2102 nameeq = ckmalloc(namelen + vallen + 2);
2103 p = (char *)memcpy(nameeq, name, namelen) + namelen;
2106 p = (char *)memcpy(p, val, vallen) + vallen;
2109 setvareq(nameeq, flags | VNOSAVE);
2113 #if ENABLE_ASH_GETOPTS
2115 * Safe version of setvar, returns 1 on success 0 on failure.
2118 setvarsafe(const char *name, const char *val, int flags)
2121 volatile int saveint;
2122 struct jmploc *volatile savehandler = exception_handler;
2123 struct jmploc jmploc;
2126 if (setjmp(jmploc.loc))
2129 exception_handler = &jmploc;
2130 setvar(name, val, flags);
2133 exception_handler = savehandler;
2134 RESTORE_INT(saveint);
2140 * Unset the specified variable.
2143 unsetvar(const char *s)
2149 vpp = findvar(hashvar(s), s);
2153 int flags = vp->flags;
2156 if (flags & VREADONLY)
2158 #if ENABLE_ASH_RANDOM_SUPPORT
2159 vp->flags &= ~VDYNAMIC;
2163 if ((flags & VSTRFIXED) == 0) {
2165 if ((flags & (VTEXTFIXED|VSTACK)) == 0)
2166 free((char*)vp->text);
2172 vp->flags &= ~VEXPORT;
2182 * Process a linked list of variable assignments.
2185 listsetvar(struct strlist *list_set_var, int flags)
2187 struct strlist *lp = list_set_var;
2193 setvareq(lp->text, flags);
2200 * Generate a list of variables satisfying the given conditions.
2203 listvars(int on, int off, char ***end)
2214 for (vp = *vpp; vp; vp = vp->next) {
2215 if ((vp->flags & mask) == on) {
2216 if (ep == stackstrend())
2217 ep = growstackstr();
2218 *ep++ = (char *) vp->text;
2221 } while (++vpp < vartab + VTABSIZE);
2222 if (ep == stackstrend())
2223 ep = growstackstr();
2227 return grabstackstr(ep);
2231 /* ============ Path search helper
2233 * The variable path (passed by reference) should be set to the start
2234 * of the path before the first call; padvance will update
2235 * this value as it proceeds. Successive calls to padvance will return
2236 * the possible path expansions in sequence. If an option (indicated by
2237 * a percent sign) appears in the path entry then the global variable
2238 * pathopt will be set to point to it; otherwise pathopt will be set to
2241 static const char *pathopt; /* set by padvance */
2244 padvance(const char **path, const char *name)
2254 for (p = start; *p && *p != ':' && *p != '%'; p++)
2256 len = p - start + strlen(name) + 2; /* "2" is for '/' and '\0' */
2257 while (stackblocksize() < len)
2261 memcpy(q, start, p - start);
2269 while (*p && *p != ':')
2276 return stalloc(len);
2280 /* ============ Prompt */
2282 static smallint doprompt; /* if set, prompt the user */
2283 static smallint needprompt; /* true if interactive and at start of line */
2285 #if ENABLE_FEATURE_EDITING
2286 static line_input_t *line_input_state;
2287 static const char *cmdedit_prompt;
2289 putprompt(const char *s)
2291 if (ENABLE_ASH_EXPAND_PRMT) {
2292 free((char*)cmdedit_prompt);
2293 cmdedit_prompt = ckstrdup(s);
2300 putprompt(const char *s)
2306 #if ENABLE_ASH_EXPAND_PRMT
2307 /* expandstr() needs parsing machinery, so it is far away ahead... */
2308 static const char *expandstr(const char *ps);
2310 #define expandstr(s) s
2314 setprompt(int whichprompt)
2317 #if ENABLE_ASH_EXPAND_PRMT
2318 struct stackmark smark;
2323 switch (whichprompt) {
2333 #if ENABLE_ASH_EXPAND_PRMT
2334 setstackmark(&smark);
2335 stalloc(stackblocksize());
2337 putprompt(expandstr(prompt));
2338 #if ENABLE_ASH_EXPAND_PRMT
2339 popstackmark(&smark);
2344 /* ============ The cd and pwd commands */
2346 #define CD_PHYSICAL 1
2349 static int docd(const char *, int);
2358 while ((i = nextopt("LP"))) {
2360 flags ^= CD_PHYSICAL;
2369 * Update curdir (the name of the current directory) in response to a
2373 updatepwd(const char *dir)
2380 cdcomppath = ststrdup(dir);
2383 if (curdir == nullstr)
2385 new = stack_putstr(curdir, new);
2387 new = makestrspace(strlen(dir) + 2, new);
2388 lim = (char *)stackblock() + 1;
2392 if (new > lim && *lim == '/')
2397 if (dir[1] == '/' && dir[2] != '/') {
2403 p = strtok(cdcomppath, "/");
2407 if (p[1] == '.' && p[2] == '\0') {
2419 new = stack_putstr(p, new);
2427 return stackblock();
2431 * Find out what the current directory is. If we already know the current
2432 * directory, this routine returns immediately.
2437 char *dir = getcwd(NULL, 0); /* huh, using glibc extension? */
2438 return dir ? dir : nullstr;
2442 setpwd(const char *val, int setold)
2446 oldcur = dir = curdir;
2449 setvar("OLDPWD", oldcur, VEXPORT);
2452 if (physdir != nullstr) {
2453 if (physdir != oldcur)
2457 if (oldcur == val || !val) {
2463 dir = ckstrdup(val);
2464 if (oldcur != dir && oldcur != nullstr) {
2469 setvar("PWD", dir, VEXPORT);
2472 static void hashcd(void);
2475 * Actually do the chdir. We also call hashcd to let the routines in exec.c
2476 * know that the current directory has changed.
2479 docd(const char *dest, int flags)
2481 const char *dir = 0;
2484 TRACE(("docd(\"%s\", %d) called\n", dest, flags));
2487 if (!(flags & CD_PHYSICAL)) {
2488 dir = updatepwd(dest);
2503 cdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
2515 dest = bltinlookup(homestr);
2516 else if (LONE_DASH(dest)) {
2517 dest = bltinlookup("OLDPWD");
2539 path = bltinlookup("CDPATH");
2548 p = padvance(&path, dest);
2549 if (stat(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) {
2553 if (!docd(p, flags))
2558 ash_msg_and_raise_error("can't cd to %s", dest);
2561 if (flags & CD_PRINT)
2562 out1fmt(snlfmt, curdir);
2567 pwdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
2570 const char *dir = curdir;
2574 if (physdir == nullstr)
2578 out1fmt(snlfmt, dir);
2583 /* ============ ... */
2586 #define IBUFSIZ COMMON_BUFSIZE
2587 /* buffer for top level input file */
2588 #define basebuf bb_common_bufsiz1
2590 /* Syntax classes */
2591 #define CWORD 0 /* character is nothing special */
2592 #define CNL 1 /* newline character */
2593 #define CBACK 2 /* a backslash character */
2594 #define CSQUOTE 3 /* single quote */
2595 #define CDQUOTE 4 /* double quote */
2596 #define CENDQUOTE 5 /* a terminating quote */
2597 #define CBQUOTE 6 /* backwards single quote */
2598 #define CVAR 7 /* a dollar sign */
2599 #define CENDVAR 8 /* a '}' character */
2600 #define CLP 9 /* a left paren in arithmetic */
2601 #define CRP 10 /* a right paren in arithmetic */
2602 #define CENDFILE 11 /* end of file */
2603 #define CCTL 12 /* like CWORD, except it must be escaped */
2604 #define CSPCL 13 /* these terminate a word */
2605 #define CIGN 14 /* character should be ignored */
2607 #if ENABLE_ASH_ALIAS
2611 #define PEOA_OR_PEOF PEOA
2615 #define PEOA_OR_PEOF PEOF
2618 /* number syntax index */
2619 #define BASESYNTAX 0 /* not in quotes */
2620 #define DQSYNTAX 1 /* in double quotes */
2621 #define SQSYNTAX 2 /* in single quotes */
2622 #define ARISYNTAX 3 /* in arithmetic */
2623 #define PSSYNTAX 4 /* prompt */
2625 #if ENABLE_ASH_OPTIMIZE_FOR_SIZE
2626 #define USE_SIT_FUNCTION
2629 #if ENABLE_ASH_MATH_SUPPORT
2630 static const char S_I_T[][4] = {
2631 #if ENABLE_ASH_ALIAS
2632 { CSPCL, CIGN, CIGN, CIGN }, /* 0, PEOA */
2634 { CSPCL, CWORD, CWORD, CWORD }, /* 1, ' ' */
2635 { CNL, CNL, CNL, CNL }, /* 2, \n */
2636 { CWORD, CCTL, CCTL, CWORD }, /* 3, !*-/:=?[]~ */
2637 { CDQUOTE, CENDQUOTE, CWORD, CWORD }, /* 4, '"' */
2638 { CVAR, CVAR, CWORD, CVAR }, /* 5, $ */
2639 { CSQUOTE, CWORD, CENDQUOTE, CWORD }, /* 6, "'" */
2640 { CSPCL, CWORD, CWORD, CLP }, /* 7, ( */
2641 { CSPCL, CWORD, CWORD, CRP }, /* 8, ) */
2642 { CBACK, CBACK, CCTL, CBACK }, /* 9, \ */
2643 { CBQUOTE, CBQUOTE, CWORD, CBQUOTE }, /* 10, ` */
2644 { CENDVAR, CENDVAR, CWORD, CENDVAR }, /* 11, } */
2645 #ifndef USE_SIT_FUNCTION
2646 { CENDFILE, CENDFILE, CENDFILE, CENDFILE }, /* 12, PEOF */
2647 { CWORD, CWORD, CWORD, CWORD }, /* 13, 0-9A-Za-z */
2648 { CCTL, CCTL, CCTL, CCTL } /* 14, CTLESC ... */
2652 static const char S_I_T[][3] = {
2653 #if ENABLE_ASH_ALIAS
2654 { CSPCL, CIGN, CIGN }, /* 0, PEOA */
2656 { CSPCL, CWORD, CWORD }, /* 1, ' ' */
2657 { CNL, CNL, CNL }, /* 2, \n */
2658 { CWORD, CCTL, CCTL }, /* 3, !*-/:=?[]~ */
2659 { CDQUOTE, CENDQUOTE, CWORD }, /* 4, '"' */
2660 { CVAR, CVAR, CWORD }, /* 5, $ */
2661 { CSQUOTE, CWORD, CENDQUOTE }, /* 6, "'" */
2662 { CSPCL, CWORD, CWORD }, /* 7, ( */
2663 { CSPCL, CWORD, CWORD }, /* 8, ) */
2664 { CBACK, CBACK, CCTL }, /* 9, \ */
2665 { CBQUOTE, CBQUOTE, CWORD }, /* 10, ` */
2666 { CENDVAR, CENDVAR, CWORD }, /* 11, } */
2667 #ifndef USE_SIT_FUNCTION
2668 { CENDFILE, CENDFILE, CENDFILE }, /* 12, PEOF */
2669 { CWORD, CWORD, CWORD }, /* 13, 0-9A-Za-z */
2670 { CCTL, CCTL, CCTL } /* 14, CTLESC ... */
2673 #endif /* ASH_MATH_SUPPORT */
2675 #ifdef USE_SIT_FUNCTION
2678 SIT(int c, int syntax)
2680 static const char spec_symbls[] ALIGN1 = "\t\n !\"$&'()*-/:;<=>?[\\]`|}~";
2681 #if ENABLE_ASH_ALIAS
2682 static const char syntax_index_table[] ALIGN1 = {
2683 1, 2, 1, 3, 4, 5, 1, 6, /* "\t\n !\"$&'" */
2684 7, 8, 3, 3, 3, 3, 1, 1, /* "()*-/:;<" */
2685 3, 1, 3, 3, 9, 3, 10, 1, /* "=>?[\\]`|" */
2689 static const char syntax_index_table[] ALIGN1 = {
2690 0, 1, 0, 2, 3, 4, 0, 5, /* "\t\n !\"$&'" */
2691 6, 7, 2, 2, 2, 2, 0, 0, /* "()*-/:;<" */
2692 2, 0, 2, 2, 8, 2, 9, 0, /* "=>?[\\]`|" */
2699 if (c == PEOF) /* 2^8+2 */
2701 #if ENABLE_ASH_ALIAS
2702 if (c == PEOA) /* 2^8+1 */
2707 if ((unsigned char)c >= (unsigned char)(CTLESC)
2708 && (unsigned char)c <= (unsigned char)(CTLQUOTEMARK)
2712 s = strchrnul(spec_symbls, c);
2715 indx = syntax_index_table[s - spec_symbls];
2717 return S_I_T[indx][syntax];
2720 #else /* !USE_SIT_FUNCTION */
2722 #if ENABLE_ASH_ALIAS
2723 #define CSPCL_CIGN_CIGN_CIGN 0
2724 #define CSPCL_CWORD_CWORD_CWORD 1
2725 #define CNL_CNL_CNL_CNL 2
2726 #define CWORD_CCTL_CCTL_CWORD 3
2727 #define CDQUOTE_CENDQUOTE_CWORD_CWORD 4
2728 #define CVAR_CVAR_CWORD_CVAR 5
2729 #define CSQUOTE_CWORD_CENDQUOTE_CWORD 6
2730 #define CSPCL_CWORD_CWORD_CLP 7
2731 #define CSPCL_CWORD_CWORD_CRP 8
2732 #define CBACK_CBACK_CCTL_CBACK 9
2733 #define CBQUOTE_CBQUOTE_CWORD_CBQUOTE 10
2734 #define CENDVAR_CENDVAR_CWORD_CENDVAR 11
2735 #define CENDFILE_CENDFILE_CENDFILE_CENDFILE 12
2736 #define CWORD_CWORD_CWORD_CWORD 13
2737 #define CCTL_CCTL_CCTL_CCTL 14
2739 #define CSPCL_CWORD_CWORD_CWORD 0
2740 #define CNL_CNL_CNL_CNL 1
2741 #define CWORD_CCTL_CCTL_CWORD 2
2742 #define CDQUOTE_CENDQUOTE_CWORD_CWORD 3
2743 #define CVAR_CVAR_CWORD_CVAR 4
2744 #define CSQUOTE_CWORD_CENDQUOTE_CWORD 5
2745 #define CSPCL_CWORD_CWORD_CLP 6
2746 #define CSPCL_CWORD_CWORD_CRP 7
2747 #define CBACK_CBACK_CCTL_CBACK 8
2748 #define CBQUOTE_CBQUOTE_CWORD_CBQUOTE 9
2749 #define CENDVAR_CENDVAR_CWORD_CENDVAR 10
2750 #define CENDFILE_CENDFILE_CENDFILE_CENDFILE 11
2751 #define CWORD_CWORD_CWORD_CWORD 12
2752 #define CCTL_CCTL_CCTL_CCTL 13
2755 static const char syntax_index_table[258] = {
2756 /* BASESYNTAX_DQSYNTAX_SQSYNTAX_ARISYNTAX */
2757 /* 0 PEOF */ CENDFILE_CENDFILE_CENDFILE_CENDFILE,
2758 #if ENABLE_ASH_ALIAS
2759 /* 1 PEOA */ CSPCL_CIGN_CIGN_CIGN,
2761 /* 2 -128 0x80 */ CWORD_CWORD_CWORD_CWORD,
2762 /* 3 -127 CTLESC */ CCTL_CCTL_CCTL_CCTL,
2763 /* 4 -126 CTLVAR */ CCTL_CCTL_CCTL_CCTL,
2764 /* 5 -125 CTLENDVAR */ CCTL_CCTL_CCTL_CCTL,
2765 /* 6 -124 CTLBACKQ */ CCTL_CCTL_CCTL_CCTL,
2766 /* 7 -123 CTLQUOTE */ CCTL_CCTL_CCTL_CCTL,
2767 /* 8 -122 CTLARI */ CCTL_CCTL_CCTL_CCTL,
2768 /* 9 -121 CTLENDARI */ CCTL_CCTL_CCTL_CCTL,
2769 /* 10 -120 CTLQUOTEMARK */ CCTL_CCTL_CCTL_CCTL,
2770 /* 11 -119 */ CWORD_CWORD_CWORD_CWORD,
2771 /* 12 -118 */ CWORD_CWORD_CWORD_CWORD,
2772 /* 13 -117 */ CWORD_CWORD_CWORD_CWORD,
2773 /* 14 -116 */ CWORD_CWORD_CWORD_CWORD,
2774 /* 15 -115 */ CWORD_CWORD_CWORD_CWORD,
2775 /* 16 -114 */ CWORD_CWORD_CWORD_CWORD,
2776 /* 17 -113 */ CWORD_CWORD_CWORD_CWORD,
2777 /* 18 -112 */ CWORD_CWORD_CWORD_CWORD,
2778 /* 19 -111 */ CWORD_CWORD_CWORD_CWORD,
2779 /* 20 -110 */ CWORD_CWORD_CWORD_CWORD,
2780 /* 21 -109 */ CWORD_CWORD_CWORD_CWORD,
2781 /* 22 -108 */ CWORD_CWORD_CWORD_CWORD,
2782 /* 23 -107 */ CWORD_CWORD_CWORD_CWORD,
2783 /* 24 -106 */ CWORD_CWORD_CWORD_CWORD,
2784 /* 25 -105 */ CWORD_CWORD_CWORD_CWORD,
2785 /* 26 -104 */ CWORD_CWORD_CWORD_CWORD,
2786 /* 27 -103 */ CWORD_CWORD_CWORD_CWORD,
2787 /* 28 -102 */ CWORD_CWORD_CWORD_CWORD,
2788 /* 29 -101 */ CWORD_CWORD_CWORD_CWORD,
2789 /* 30 -100 */ CWORD_CWORD_CWORD_CWORD,
2790 /* 31 -99 */ CWORD_CWORD_CWORD_CWORD,
2791 /* 32 -98 */ CWORD_CWORD_CWORD_CWORD,
2792 /* 33 -97 */ CWORD_CWORD_CWORD_CWORD,
2793 /* 34 -96 */ CWORD_CWORD_CWORD_CWORD,
2794 /* 35 -95 */ CWORD_CWORD_CWORD_CWORD,
2795 /* 36 -94 */ CWORD_CWORD_CWORD_CWORD,
2796 /* 37 -93 */ CWORD_CWORD_CWORD_CWORD,
2797 /* 38 -92 */ CWORD_CWORD_CWORD_CWORD,
2798 /* 39 -91 */ CWORD_CWORD_CWORD_CWORD,
2799 /* 40 -90 */ CWORD_CWORD_CWORD_CWORD,
2800 /* 41 -89 */ CWORD_CWORD_CWORD_CWORD,
2801 /* 42 -88 */ CWORD_CWORD_CWORD_CWORD,
2802 /* 43 -87 */ CWORD_CWORD_CWORD_CWORD,
2803 /* 44 -86 */ CWORD_CWORD_CWORD_CWORD,
2804 /* 45 -85 */ CWORD_CWORD_CWORD_CWORD,
2805 /* 46 -84 */ CWORD_CWORD_CWORD_CWORD,
2806 /* 47 -83 */ CWORD_CWORD_CWORD_CWORD,
2807 /* 48 -82 */ CWORD_CWORD_CWORD_CWORD,
2808 /* 49 -81 */ CWORD_CWORD_CWORD_CWORD,
2809 /* 50 -80 */ CWORD_CWORD_CWORD_CWORD,
2810 /* 51 -79 */ CWORD_CWORD_CWORD_CWORD,
2811 /* 52 -78 */ CWORD_CWORD_CWORD_CWORD,
2812 /* 53 -77 */ CWORD_CWORD_CWORD_CWORD,
2813 /* 54 -76 */ CWORD_CWORD_CWORD_CWORD,
2814 /* 55 -75 */ CWORD_CWORD_CWORD_CWORD,
2815 /* 56 -74 */ CWORD_CWORD_CWORD_CWORD,
2816 /* 57 -73 */ CWORD_CWORD_CWORD_CWORD,
2817 /* 58 -72 */ CWORD_CWORD_CWORD_CWORD,
2818 /* 59 -71 */ CWORD_CWORD_CWORD_CWORD,
2819 /* 60 -70 */ CWORD_CWORD_CWORD_CWORD,
2820 /* 61 -69 */ CWORD_CWORD_CWORD_CWORD,
2821 /* 62 -68 */ CWORD_CWORD_CWORD_CWORD,
2822 /* 63 -67 */ CWORD_CWORD_CWORD_CWORD,
2823 /* 64 -66 */ CWORD_CWORD_CWORD_CWORD,
2824 /* 65 -65 */ CWORD_CWORD_CWORD_CWORD,
2825 /* 66 -64 */ CWORD_CWORD_CWORD_CWORD,
2826 /* 67 -63 */ CWORD_CWORD_CWORD_CWORD,
2827 /* 68 -62 */ CWORD_CWORD_CWORD_CWORD,
2828 /* 69 -61 */ CWORD_CWORD_CWORD_CWORD,
2829 /* 70 -60 */ CWORD_CWORD_CWORD_CWORD,
2830 /* 71 -59 */ CWORD_CWORD_CWORD_CWORD,
2831 /* 72 -58 */ CWORD_CWORD_CWORD_CWORD,
2832 /* 73 -57 */ CWORD_CWORD_CWORD_CWORD,
2833 /* 74 -56 */ CWORD_CWORD_CWORD_CWORD,
2834 /* 75 -55 */ CWORD_CWORD_CWORD_CWORD,
2835 /* 76 -54 */ CWORD_CWORD_CWORD_CWORD,
2836 /* 77 -53 */ CWORD_CWORD_CWORD_CWORD,
2837 /* 78 -52 */ CWORD_CWORD_CWORD_CWORD,
2838 /* 79 -51 */ CWORD_CWORD_CWORD_CWORD,
2839 /* 80 -50 */ CWORD_CWORD_CWORD_CWORD,
2840 /* 81 -49 */ CWORD_CWORD_CWORD_CWORD,
2841 /* 82 -48 */ CWORD_CWORD_CWORD_CWORD,
2842 /* 83 -47 */ CWORD_CWORD_CWORD_CWORD,
2843 /* 84 -46 */ CWORD_CWORD_CWORD_CWORD,
2844 /* 85 -45 */ CWORD_CWORD_CWORD_CWORD,
2845 /* 86 -44 */ CWORD_CWORD_CWORD_CWORD,
2846 /* 87 -43 */ CWORD_CWORD_CWORD_CWORD,
2847 /* 88 -42 */ CWORD_CWORD_CWORD_CWORD,
2848 /* 89 -41 */ CWORD_CWORD_CWORD_CWORD,
2849 /* 90 -40 */ CWORD_CWORD_CWORD_CWORD,
2850 /* 91 -39 */ CWORD_CWORD_CWORD_CWORD,
2851 /* 92 -38 */ CWORD_CWORD_CWORD_CWORD,
2852 /* 93 -37 */ CWORD_CWORD_CWORD_CWORD,
2853 /* 94 -36 */ CWORD_CWORD_CWORD_CWORD,
2854 /* 95 -35 */ CWORD_CWORD_CWORD_CWORD,
2855 /* 96 -34 */ CWORD_CWORD_CWORD_CWORD,
2856 /* 97 -33 */ CWORD_CWORD_CWORD_CWORD,
2857 /* 98 -32 */ CWORD_CWORD_CWORD_CWORD,
2858 /* 99 -31 */ CWORD_CWORD_CWORD_CWORD,
2859 /* 100 -30 */ CWORD_CWORD_CWORD_CWORD,
2860 /* 101 -29 */ CWORD_CWORD_CWORD_CWORD,
2861 /* 102 -28 */ CWORD_CWORD_CWORD_CWORD,
2862 /* 103 -27 */ CWORD_CWORD_CWORD_CWORD,
2863 /* 104 -26 */ CWORD_CWORD_CWORD_CWORD,
2864 /* 105 -25 */ CWORD_CWORD_CWORD_CWORD,
2865 /* 106 -24 */ CWORD_CWORD_CWORD_CWORD,
2866 /* 107 -23 */ CWORD_CWORD_CWORD_CWORD,
2867 /* 108 -22 */ CWORD_CWORD_CWORD_CWORD,
2868 /* 109 -21 */ CWORD_CWORD_CWORD_CWORD,
2869 /* 110 -20 */ CWORD_CWORD_CWORD_CWORD,
2870 /* 111 -19 */ CWORD_CWORD_CWORD_CWORD,
2871 /* 112 -18 */ CWORD_CWORD_CWORD_CWORD,
2872 /* 113 -17 */ CWORD_CWORD_CWORD_CWORD,
2873 /* 114 -16 */ CWORD_CWORD_CWORD_CWORD,
2874 /* 115 -15 */ CWORD_CWORD_CWORD_CWORD,
2875 /* 116 -14 */ CWORD_CWORD_CWORD_CWORD,
2876 /* 117 -13 */ CWORD_CWORD_CWORD_CWORD,
2877 /* 118 -12 */ CWORD_CWORD_CWORD_CWORD,
2878 /* 119 -11 */ CWORD_CWORD_CWORD_CWORD,
2879 /* 120 -10 */ CWORD_CWORD_CWORD_CWORD,
2880 /* 121 -9 */ CWORD_CWORD_CWORD_CWORD,
2881 /* 122 -8 */ CWORD_CWORD_CWORD_CWORD,
2882 /* 123 -7 */ CWORD_CWORD_CWORD_CWORD,
2883 /* 124 -6 */ CWORD_CWORD_CWORD_CWORD,
2884 /* 125 -5 */ CWORD_CWORD_CWORD_CWORD,
2885 /* 126 -4 */ CWORD_CWORD_CWORD_CWORD,
2886 /* 127 -3 */ CWORD_CWORD_CWORD_CWORD,
2887 /* 128 -2 */ CWORD_CWORD_CWORD_CWORD,
2888 /* 129 -1 */ CWORD_CWORD_CWORD_CWORD,
2889 /* 130 0 */ CWORD_CWORD_CWORD_CWORD,
2890 /* 131 1 */ CWORD_CWORD_CWORD_CWORD,
2891 /* 132 2 */ CWORD_CWORD_CWORD_CWORD,
2892 /* 133 3 */ CWORD_CWORD_CWORD_CWORD,
2893 /* 134 4 */ CWORD_CWORD_CWORD_CWORD,
2894 /* 135 5 */ CWORD_CWORD_CWORD_CWORD,
2895 /* 136 6 */ CWORD_CWORD_CWORD_CWORD,
2896 /* 137 7 */ CWORD_CWORD_CWORD_CWORD,
2897 /* 138 8 */ CWORD_CWORD_CWORD_CWORD,
2898 /* 139 9 "\t" */ CSPCL_CWORD_CWORD_CWORD,
2899 /* 140 10 "\n" */ CNL_CNL_CNL_CNL,
2900 /* 141 11 */ CWORD_CWORD_CWORD_CWORD,
2901 /* 142 12 */ CWORD_CWORD_CWORD_CWORD,
2902 /* 143 13 */ CWORD_CWORD_CWORD_CWORD,
2903 /* 144 14 */ CWORD_CWORD_CWORD_CWORD,
2904 /* 145 15 */ CWORD_CWORD_CWORD_CWORD,
2905 /* 146 16 */ CWORD_CWORD_CWORD_CWORD,
2906 /* 147 17 */ CWORD_CWORD_CWORD_CWORD,
2907 /* 148 18 */ CWORD_CWORD_CWORD_CWORD,
2908 /* 149 19 */ CWORD_CWORD_CWORD_CWORD,
2909 /* 150 20 */ CWORD_CWORD_CWORD_CWORD,
2910 /* 151 21 */ CWORD_CWORD_CWORD_CWORD,
2911 /* 152 22 */ CWORD_CWORD_CWORD_CWORD,
2912 /* 153 23 */ CWORD_CWORD_CWORD_CWORD,
2913 /* 154 24 */ CWORD_CWORD_CWORD_CWORD,
2914 /* 155 25 */ CWORD_CWORD_CWORD_CWORD,
2915 /* 156 26 */ CWORD_CWORD_CWORD_CWORD,
2916 /* 157 27 */ CWORD_CWORD_CWORD_CWORD,
2917 /* 158 28 */ CWORD_CWORD_CWORD_CWORD,
2918 /* 159 29 */ CWORD_CWORD_CWORD_CWORD,
2919 /* 160 30 */ CWORD_CWORD_CWORD_CWORD,
2920 /* 161 31 */ CWORD_CWORD_CWORD_CWORD,
2921 /* 162 32 " " */ CSPCL_CWORD_CWORD_CWORD,
2922 /* 163 33 "!" */ CWORD_CCTL_CCTL_CWORD,
2923 /* 164 34 """ */ CDQUOTE_CENDQUOTE_CWORD_CWORD,
2924 /* 165 35 "#" */ CWORD_CWORD_CWORD_CWORD,
2925 /* 166 36 "$" */ CVAR_CVAR_CWORD_CVAR,
2926 /* 167 37 "%" */ CWORD_CWORD_CWORD_CWORD,
2927 /* 168 38 "&" */ CSPCL_CWORD_CWORD_CWORD,
2928 /* 169 39 "'" */ CSQUOTE_CWORD_CENDQUOTE_CWORD,
2929 /* 170 40 "(" */ CSPCL_CWORD_CWORD_CLP,
2930 /* 171 41 ")" */ CSPCL_CWORD_CWORD_CRP,
2931 /* 172 42 "*" */ CWORD_CCTL_CCTL_CWORD,
2932 /* 173 43 "+" */ CWORD_CWORD_CWORD_CWORD,
2933 /* 174 44 "," */ CWORD_CWORD_CWORD_CWORD,
2934 /* 175 45 "-" */ CWORD_CCTL_CCTL_CWORD,
2935 /* 176 46 "." */ CWORD_CWORD_CWORD_CWORD,
2936 /* 177 47 "/" */ CWORD_CCTL_CCTL_CWORD,
2937 /* 178 48 "0" */ CWORD_CWORD_CWORD_CWORD,
2938 /* 179 49 "1" */ CWORD_CWORD_CWORD_CWORD,
2939 /* 180 50 "2" */ CWORD_CWORD_CWORD_CWORD,
2940 /* 181 51 "3" */ CWORD_CWORD_CWORD_CWORD,
2941 /* 182 52 "4" */ CWORD_CWORD_CWORD_CWORD,
2942 /* 183 53 "5" */ CWORD_CWORD_CWORD_CWORD,
2943 /* 184 54 "6" */ CWORD_CWORD_CWORD_CWORD,
2944 /* 185 55 "7" */ CWORD_CWORD_CWORD_CWORD,
2945 /* 186 56 "8" */ CWORD_CWORD_CWORD_CWORD,
2946 /* 187 57 "9" */ CWORD_CWORD_CWORD_CWORD,
2947 /* 188 58 ":" */ CWORD_CCTL_CCTL_CWORD,
2948 /* 189 59 ";" */ CSPCL_CWORD_CWORD_CWORD,
2949 /* 190 60 "<" */ CSPCL_CWORD_CWORD_CWORD,
2950 /* 191 61 "=" */ CWORD_CCTL_CCTL_CWORD,
2951 /* 192 62 ">" */ CSPCL_CWORD_CWORD_CWORD,
2952 /* 193 63 "?" */ CWORD_CCTL_CCTL_CWORD,
2953 /* 194 64 "@" */ CWORD_CWORD_CWORD_CWORD,
2954 /* 195 65 "A" */ CWORD_CWORD_CWORD_CWORD,
2955 /* 196 66 "B" */ CWORD_CWORD_CWORD_CWORD,
2956 /* 197 67 "C" */ CWORD_CWORD_CWORD_CWORD,
2957 /* 198 68 "D" */ CWORD_CWORD_CWORD_CWORD,
2958 /* 199 69 "E" */ CWORD_CWORD_CWORD_CWORD,
2959 /* 200 70 "F" */ CWORD_CWORD_CWORD_CWORD,
2960 /* 201 71 "G" */ CWORD_CWORD_CWORD_CWORD,
2961 /* 202 72 "H" */ CWORD_CWORD_CWORD_CWORD,
2962 /* 203 73 "I" */ CWORD_CWORD_CWORD_CWORD,
2963 /* 204 74 "J" */ CWORD_CWORD_CWORD_CWORD,
2964 /* 205 75 "K" */ CWORD_CWORD_CWORD_CWORD,
2965 /* 206 76 "L" */ CWORD_CWORD_CWORD_CWORD,
2966 /* 207 77 "M" */ CWORD_CWORD_CWORD_CWORD,
2967 /* 208 78 "N" */ CWORD_CWORD_CWORD_CWORD,
2968 /* 209 79 "O" */ CWORD_CWORD_CWORD_CWORD,
2969 /* 210 80 "P" */ CWORD_CWORD_CWORD_CWORD,
2970 /* 211 81 "Q" */ CWORD_CWORD_CWORD_CWORD,
2971 /* 212 82 "R" */ CWORD_CWORD_CWORD_CWORD,
2972 /* 213 83 "S" */ CWORD_CWORD_CWORD_CWORD,
2973 /* 214 84 "T" */ CWORD_CWORD_CWORD_CWORD,
2974 /* 215 85 "U" */ CWORD_CWORD_CWORD_CWORD,
2975 /* 216 86 "V" */ CWORD_CWORD_CWORD_CWORD,
2976 /* 217 87 "W" */ CWORD_CWORD_CWORD_CWORD,
2977 /* 218 88 "X" */ CWORD_CWORD_CWORD_CWORD,
2978 /* 219 89 "Y" */ CWORD_CWORD_CWORD_CWORD,
2979 /* 220 90 "Z" */ CWORD_CWORD_CWORD_CWORD,
2980 /* 221 91 "[" */ CWORD_CCTL_CCTL_CWORD,
2981 /* 222 92 "\" */ CBACK_CBACK_CCTL_CBACK,
2982 /* 223 93 "]" */ CWORD_CCTL_CCTL_CWORD,
2983 /* 224 94 "^" */ CWORD_CWORD_CWORD_CWORD,
2984 /* 225 95 "_" */ CWORD_CWORD_CWORD_CWORD,
2985 /* 226 96 "`" */ CBQUOTE_CBQUOTE_CWORD_CBQUOTE,
2986 /* 227 97 "a" */ CWORD_CWORD_CWORD_CWORD,
2987 /* 228 98 "b" */ CWORD_CWORD_CWORD_CWORD,
2988 /* 229 99 "c" */ CWORD_CWORD_CWORD_CWORD,
2989 /* 230 100 "d" */ CWORD_CWORD_CWORD_CWORD,
2990 /* 231 101 "e" */ CWORD_CWORD_CWORD_CWORD,
2991 /* 232 102 "f" */ CWORD_CWORD_CWORD_CWORD,
2992 /* 233 103 "g" */ CWORD_CWORD_CWORD_CWORD,
2993 /* 234 104 "h" */ CWORD_CWORD_CWORD_CWORD,
2994 /* 235 105 "i" */ CWORD_CWORD_CWORD_CWORD,
2995 /* 236 106 "j" */ CWORD_CWORD_CWORD_CWORD,
2996 /* 237 107 "k" */ CWORD_CWORD_CWORD_CWORD,
2997 /* 238 108 "l" */ CWORD_CWORD_CWORD_CWORD,
2998 /* 239 109 "m" */ CWORD_CWORD_CWORD_CWORD,
2999 /* 240 110 "n" */ CWORD_CWORD_CWORD_CWORD,
3000 /* 241 111 "o" */ CWORD_CWORD_CWORD_CWORD,
3001 /* 242 112 "p" */ CWORD_CWORD_CWORD_CWORD,
3002 /* 243 113 "q" */ CWORD_CWORD_CWORD_CWORD,
3003 /* 244 114 "r" */ CWORD_CWORD_CWORD_CWORD,
3004 /* 245 115 "s" */ CWORD_CWORD_CWORD_CWORD,
3005 /* 246 116 "t" */ CWORD_CWORD_CWORD_CWORD,
3006 /* 247 117 "u" */ CWORD_CWORD_CWORD_CWORD,
3007 /* 248 118 "v" */ CWORD_CWORD_CWORD_CWORD,
3008 /* 249 119 "w" */ CWORD_CWORD_CWORD_CWORD,
3009 /* 250 120 "x" */ CWORD_CWORD_CWORD_CWORD,
3010 /* 251 121 "y" */ CWORD_CWORD_CWORD_CWORD,
3011 /* 252 122 "z" */ CWORD_CWORD_CWORD_CWORD,
3012 /* 253 123 "{" */ CWORD_CWORD_CWORD_CWORD,
3013 /* 254 124 "|" */ CSPCL_CWORD_CWORD_CWORD,
3014 /* 255 125 "}" */ CENDVAR_CENDVAR_CWORD_CENDVAR,
3015 /* 256 126 "~" */ CWORD_CCTL_CCTL_CWORD,
3016 /* 257 127 */ CWORD_CWORD_CWORD_CWORD,
3019 #define SIT(c, syntax) (S_I_T[(int)syntax_index_table[((int)c)+SYNBASE]][syntax])
3021 #endif /* USE_SIT_FUNCTION */
3024 /* ============ Alias handling */
3026 #if ENABLE_ASH_ALIAS
3028 #define ALIASINUSE 1
3039 static struct alias **atab; // [ATABSIZE];
3040 #define INIT_G_alias() do { \
3041 atab = xzalloc(ATABSIZE * sizeof(atab[0])); \
3045 static struct alias **
3046 __lookupalias(const char *name) {
3047 unsigned int hashval;
3054 ch = (unsigned char)*p;
3058 ch = (unsigned char)*++p;
3060 app = &atab[hashval % ATABSIZE];
3062 for (; *app; app = &(*app)->next) {
3063 if (strcmp(name, (*app)->name) == 0) {
3071 static struct alias *
3072 lookupalias(const char *name, int check)
3074 struct alias *ap = *__lookupalias(name);
3076 if (check && ap && (ap->flag & ALIASINUSE))
3081 static struct alias *
3082 freealias(struct alias *ap)
3086 if (ap->flag & ALIASINUSE) {
3087 ap->flag |= ALIASDEAD;
3099 setalias(const char *name, const char *val)
3101 struct alias *ap, **app;
3103 app = __lookupalias(name);
3107 if (!(ap->flag & ALIASINUSE)) {
3110 ap->val = ckstrdup(val);
3111 ap->flag &= ~ALIASDEAD;
3114 ap = ckzalloc(sizeof(struct alias));
3115 ap->name = ckstrdup(name);
3116 ap->val = ckstrdup(val);
3117 /*ap->flag = 0; - ckzalloc did it */
3118 /*ap->next = NULL;*/
3125 unalias(const char *name)
3129 app = __lookupalias(name);
3133 *app = freealias(*app);
3144 struct alias *ap, **app;
3148 for (i = 0; i < ATABSIZE; i++) {
3150 for (ap = *app; ap; ap = *app) {
3151 *app = freealias(*app);
3161 printalias(const struct alias *ap)
3163 out1fmt("%s=%s\n", ap->name, single_quote(ap->val));
3167 * TODO - sort output
3170 aliascmd(int argc UNUSED_PARAM, char **argv)
3179 for (i = 0; i < ATABSIZE; i++) {
3180 for (ap = atab[i]; ap; ap = ap->next) {
3186 while ((n = *++argv) != NULL) {
3187 v = strchr(n+1, '=');
3188 if (v == NULL) { /* n+1: funny ksh stuff */
3189 ap = *__lookupalias(n);
3191 fprintf(stderr, "%s: %s not found\n", "alias", n);
3205 unaliascmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
3209 while ((i = nextopt("a")) != '\0') {
3215 for (i = 0; *argptr; argptr++) {
3216 if (unalias(*argptr)) {
3217 fprintf(stderr, "%s: %s not found\n", "unalias", *argptr);
3225 #endif /* ASH_ALIAS */
3228 /* ============ jobs.c */
3230 /* Mode argument to forkshell. Don't change FORK_FG or FORK_BG. */
3233 #define FORK_NOJOB 2
3235 /* mode flags for showjob(s) */
3236 #define SHOW_PGID 0x01 /* only show pgid - for jobs -p */
3237 #define SHOW_PID 0x04 /* include process pid */
3238 #define SHOW_CHANGED 0x08 /* only jobs whose state has changed */
3241 * A job structure contains information about a job. A job is either a
3242 * single process or a set of processes contained in a pipeline. In the
3243 * latter case, pidlist will be non-NULL, and will point to a -1 terminated
3248 pid_t pid; /* process id */
3249 int status; /* last process status from wait() */
3250 char *cmd; /* text of command being run */
3254 struct procstat ps0; /* status of process */
3255 struct procstat *ps; /* status or processes when more than one */
3257 int stopstatus; /* status of a stopped job */
3260 nprocs: 16, /* number of processes */
3262 #define JOBRUNNING 0 /* at least one proc running */
3263 #define JOBSTOPPED 1 /* all procs are stopped */
3264 #define JOBDONE 2 /* all procs are completed */
3266 sigint: 1, /* job was killed by SIGINT */
3267 jobctl: 1, /* job running under job control */
3269 waited: 1, /* true if this entry has been waited for */
3270 used: 1, /* true if this entry is in used */
3271 changed: 1; /* true if status has changed */
3272 struct job *prev_job; /* previous job */
3275 static struct job *makejob(/*union node *,*/ int);
3277 #define forkshell(job, node, mode) forkshell(job, mode)
3279 static int forkshell(struct job *, union node *, int);
3280 static int waitforjob(struct job *);
3283 enum { doing_jobctl = 0 };
3284 #define setjobctl(on) do {} while (0)
3286 static smallint doing_jobctl; //references:8
3287 static void setjobctl(int);
3291 * Set the signal handler for the specified signal. The routine figures
3292 * out what it should be set to.
3295 setsignal(int signo)
3298 char cur_act, new_act;
3299 struct sigaction act;
3303 if (t != NULL) { /* trap for this sig is set */
3305 if (t[0] == '\0') /* trap is "": ignore this sig */
3309 if (rootshell && new_act == S_DFL) {
3312 if (iflag || minusc || sflag == 0)
3321 * "In all cases, bash ignores SIGQUIT. Non-builtin
3322 * commands run by bash have signal handlers
3323 * set to the values inherited by the shell
3324 * from its parent". */
3340 //TODO: if !rootshell, we reset SIGQUIT to DFL,
3341 //whereas we have to restore it to what shell got on entry
3342 //from the parent. See comment above
3344 t = &sigmode[signo - 1];
3347 /* current setting is not yet known */
3348 if (sigaction(signo, NULL, &act)) {
3349 /* pretend it worked; maybe we should give a warning,
3350 * but other shells don't. We don't alter sigmode,
3351 * so we retry every time.
3352 * btw, in Linux it never fails. --vda */
3355 if (act.sa_handler == SIG_IGN) {
3356 cur_act = S_HARD_IGN;
3358 && (signo == SIGTSTP || signo == SIGTTIN || signo == SIGTTOU)
3360 cur_act = S_IGN; /* don't hard ignore these */
3364 if (cur_act == S_HARD_IGN || cur_act == new_act)
3367 act.sa_handler = SIG_DFL;
3370 act.sa_handler = onsig;
3371 act.sa_flags = 0; /* matters only if !DFL and !IGN */
3372 sigfillset(&act.sa_mask); /* ditto */
3375 act.sa_handler = SIG_IGN;
3378 sigaction_set(signo, &act);
3383 /* mode flags for set_curjob */
3384 #define CUR_DELETE 2
3385 #define CUR_RUNNING 1
3386 #define CUR_STOPPED 0
3388 /* mode flags for dowait */
3389 #define DOWAIT_NONBLOCK WNOHANG
3390 #define DOWAIT_BLOCK 0
3393 /* pgrp of shell on invocation */
3394 static int initialpgrp; //references:2
3395 static int ttyfd = -1; //5
3398 static struct job *jobtab; //5
3400 static unsigned njobs; //4
3402 static struct job *curjob; //lots
3403 /* number of presumed living untracked jobs */
3404 static int jobless; //4
3407 set_curjob(struct job *jp, unsigned mode)
3410 struct job **jpp, **curp;
3412 /* first remove from list */
3413 jpp = curp = &curjob;
3418 jpp = &jp1->prev_job;
3420 *jpp = jp1->prev_job;
3422 /* Then re-insert in correct position */
3430 /* job being deleted */
3433 /* newly created job or backgrounded job,
3434 put after all stopped jobs. */
3438 if (!jp1 || jp1->state != JOBSTOPPED)
3441 jpp = &jp1->prev_job;
3447 /* newly stopped job - becomes curjob */
3448 jp->prev_job = *jpp;
3456 jobno(const struct job *jp)
3458 return jp - jobtab + 1;
3463 * Convert a job name to a job structure.
3466 #define getjob(name, getctl) getjob(name)
3469 getjob(const char *name, int getctl)
3473 const char *err_msg = "No such job: %s";
3477 char *(*match)(const char *, const char *);
3492 if (c == '+' || c == '%') {
3494 err_msg = "No current job";
3500 err_msg = "No previous job";
3509 // TODO: number() instead? It does error checking...
3512 jp = jobtab + num - 1;
3529 if (match(jp->ps[0].cmd, p)) {
3533 err_msg = "%s: ambiguous";
3540 err_msg = "job %s not created under job control";
3541 if (getctl && jp->jobctl == 0)
3546 ash_msg_and_raise_error(err_msg, name);
3550 * Mark a job structure as unused.
3553 freejob(struct job *jp)
3555 struct procstat *ps;
3559 for (i = jp->nprocs, ps = jp->ps; --i >= 0; ps++) {
3560 if (ps->cmd != nullstr)
3563 if (jp->ps != &jp->ps0)
3566 set_curjob(jp, CUR_DELETE);
3572 xtcsetpgrp(int fd, pid_t pgrp)
3574 if (tcsetpgrp(fd, pgrp))
3575 ash_msg_and_raise_error("can't set tty process group (%m)");
3579 * Turn job control on and off.
3581 * Note: This code assumes that the third arg to ioctl is a character
3582 * pointer, which is true on Berkeley systems but not System V. Since
3583 * System V doesn't have job control yet, this isn't a problem now.
3585 * Called with interrupts off.
3593 if (on == doing_jobctl || rootshell == 0)
3597 ofd = fd = open(_PATH_TTY, O_RDWR);
3599 /* BTW, bash will try to open(ttyname(0)) if open("/dev/tty") fails.
3600 * That sometimes helps to acquire controlling tty.
3601 * Obviously, a workaround for bugs when someone
3602 * failed to provide a controlling tty to bash! :) */
3608 fd = fcntl(fd, F_DUPFD, 10);
3613 /* fd is a tty at this point */
3614 close_on_exec_on(fd);
3615 do { /* while we are in the background */
3616 pgrp = tcgetpgrp(fd);
3619 ash_msg("can't access tty; job control turned off");
3623 if (pgrp == getpgrp())
3634 xtcsetpgrp(fd, pgrp);
3636 /* turning job control off */
3639 /* was xtcsetpgrp, but this can make exiting ash
3640 * loop forever if pty is already deleted */
3641 tcsetpgrp(fd, pgrp);
3656 killcmd(int argc, char **argv)
3659 if (argv[1] && strcmp(argv[1], "-l") != 0) {
3661 if (argv[i][0] == '%') {
3662 struct job *jp = getjob(argv[i], 0);
3663 unsigned pid = jp->ps[0].pid;
3664 /* Enough space for ' -NNN<nul>' */
3665 argv[i] = alloca(sizeof(int)*3 + 3);
3666 /* kill_main has matching code to expect
3667 * leading space. Needed to not confuse
3668 * negative pids with "kill -SIGNAL_NO" syntax */
3669 sprintf(argv[i], " -%u", pid);
3671 } while (argv[++i]);
3673 return kill_main(argc, argv);
3677 showpipe(struct job *jp, FILE *out)
3679 struct procstat *sp;
3680 struct procstat *spend;
3682 spend = jp->ps + jp->nprocs;
3683 for (sp = jp->ps + 1; sp < spend; sp++)
3684 fprintf(out, " | %s", sp->cmd);
3685 outcslow('\n', out);
3686 flush_stdout_stderr();
3691 restartjob(struct job *jp, int mode)
3693 struct procstat *ps;
3699 if (jp->state == JOBDONE)
3701 jp->state = JOBRUNNING;
3703 if (mode == FORK_FG)
3704 xtcsetpgrp(ttyfd, pgid);
3705 killpg(pgid, SIGCONT);
3709 if (WIFSTOPPED(ps->status)) {
3715 status = (mode == FORK_FG) ? waitforjob(jp) : 0;
3721 fg_bgcmd(int argc UNUSED_PARAM, char **argv)
3728 mode = (**argv == 'f') ? FORK_FG : FORK_BG;
3733 jp = getjob(*argv, 1);
3734 if (mode == FORK_BG) {
3735 set_curjob(jp, CUR_RUNNING);
3736 fprintf(out, "[%d] ", jobno(jp));
3738 outstr(jp->ps->cmd, out);
3740 retval = restartjob(jp, mode);
3741 } while (*argv && *++argv);
3747 sprint_status(char *s, int status, int sigonly)
3753 if (!WIFEXITED(status)) {
3755 if (WIFSTOPPED(status))
3756 st = WSTOPSIG(status);
3759 st = WTERMSIG(status);
3761 if (st == SIGINT || st == SIGPIPE)
3764 if (WIFSTOPPED(status))
3769 col = fmtstr(s, 32, strsignal(st));
3770 if (WCOREDUMP(status)) {
3771 col += fmtstr(s + col, 16, " (core dumped)");
3773 } else if (!sigonly) {
3774 st = WEXITSTATUS(status);
3776 col = fmtstr(s, 16, "Done(%d)", st);
3778 col = fmtstr(s, 16, "Done");
3785 dowait(int wait_flags, struct job *job)
3790 struct job *thisjob;
3793 TRACE(("dowait(0x%x) called\n", wait_flags));
3795 /* Do a wait system call. If job control is compiled in, we accept
3796 * stopped processes. wait_flags may have WNOHANG, preventing blocking.
3797 * NB: _not_ safe_waitpid, we need to detect EINTR */
3798 pid = waitpid(-1, &status,
3799 (doing_jobctl ? (wait_flags | WUNTRACED) : wait_flags));
3800 TRACE(("wait returns pid=%d, status=0x%x\n", pid, status));
3806 for (jp = curjob; jp; jp = jp->prev_job) {
3807 struct procstat *sp;
3808 struct procstat *spend;
3809 if (jp->state == JOBDONE)
3812 spend = jp->ps + jp->nprocs;
3815 if (sp->pid == pid) {
3816 TRACE(("Job %d: changing status of proc %d "
3817 "from 0x%x to 0x%x\n",
3818 jobno(jp), pid, sp->status, status));
3819 sp->status = status;
3822 if (sp->status == -1)
3825 if (state == JOBRUNNING)
3827 if (WIFSTOPPED(sp->status)) {
3828 jp->stopstatus = sp->status;
3832 } while (++sp < spend);
3837 if (!WIFSTOPPED(status))
3843 if (state != JOBRUNNING) {
3844 thisjob->changed = 1;
3846 if (thisjob->state != state) {
3847 TRACE(("Job %d: changing state from %d to %d\n",
3848 jobno(thisjob), thisjob->state, state));
3849 thisjob->state = state;
3851 if (state == JOBSTOPPED) {
3852 set_curjob(thisjob, CUR_STOPPED);
3861 if (thisjob && thisjob == job) {
3865 len = sprint_status(s, status, 1);
3876 blocking_wait_with_raise_on_sig(struct job *job)
3878 pid_t pid = dowait(DOWAIT_BLOCK, job);
3879 if (pid <= 0 && pendingsig)
3880 raise_exception(EXSIG);
3886 showjob(FILE *out, struct job *jp, int mode)
3888 struct procstat *ps;
3889 struct procstat *psend;
3896 if (mode & SHOW_PGID) {
3897 /* just output process (group) id of pipeline */
3898 fprintf(out, "%d\n", ps->pid);
3902 col = fmtstr(s, 16, "[%d] ", jobno(jp));
3907 else if (curjob && jp == curjob->prev_job)
3910 if (mode & SHOW_PID)
3911 col += fmtstr(s + col, 16, "%d ", ps->pid);
3913 psend = ps + jp->nprocs;
3915 if (jp->state == JOBRUNNING) {
3916 strcpy(s + col, "Running");
3917 col += sizeof("Running") - 1;
3919 int status = psend[-1].status;
3920 if (jp->state == JOBSTOPPED)
3921 status = jp->stopstatus;
3922 col += sprint_status(s + col, status, 0);
3928 /* for each process */
3929 col = fmtstr(s, 48, " |\n%*c%d ", indent_col, ' ', ps->pid) - 3;
3931 fprintf(out, "%s%*c%s",
3932 s, 33 - col >= 0 ? 33 - col : 0, ' ', ps->cmd
3934 if (!(mode & SHOW_PID)) {
3938 if (++ps == psend) {
3939 outcslow('\n', out);
3946 if (jp->state == JOBDONE) {
3947 TRACE(("showjob: freeing job %d\n", jobno(jp)));
3953 * Print a list of jobs. If "change" is nonzero, only print jobs whose
3954 * statuses have changed since the last call to showjobs.
3957 showjobs(FILE *out, int mode)
3961 TRACE(("showjobs(%x) called\n", mode));
3963 /* Handle all finished jobs */
3964 while (dowait(DOWAIT_NONBLOCK, NULL) > 0)
3967 for (jp = curjob; jp; jp = jp->prev_job) {
3968 if (!(mode & SHOW_CHANGED) || jp->changed) {
3969 showjob(out, jp, mode);
3975 jobscmd(int argc UNUSED_PARAM, char **argv)
3980 while ((m = nextopt("lp"))) {
3990 showjob(stdout, getjob(*argv,0), mode);
3993 showjobs(stdout, mode);
4000 getstatus(struct job *job)
4005 status = job->ps[job->nprocs - 1].status;
4006 retval = WEXITSTATUS(status);
4007 if (!WIFEXITED(status)) {
4009 retval = WSTOPSIG(status);
4010 if (!WIFSTOPPED(status))
4013 /* XXX: limits number of signals */
4014 retval = WTERMSIG(status);
4016 if (retval == SIGINT)
4022 TRACE(("getstatus: job %d, nproc %d, status %x, retval %x\n",
4023 jobno(job), job->nprocs, status, retval));
4028 waitcmd(int argc UNUSED_PARAM, char **argv)
4037 raise_exception(EXSIG);
4044 /* wait for all jobs */
4048 if (!jp) /* no running procs */
4050 if (jp->state == JOBRUNNING)
4056 * "When bash is waiting for an asynchronous command via
4057 * the wait builtin, the reception of a signal for which a trap
4058 * has been set will cause the wait builtin to return immediately
4059 * with an exit status greater than 128, immediately after which
4060 * the trap is executed."
4061 * Do we do it that way? */
4062 blocking_wait_with_raise_on_sig(NULL);
4068 if (**argv != '%') {
4069 pid_t pid = number(*argv);
4074 if (job->ps[job->nprocs - 1].pid == pid)
4076 job = job->prev_job;
4079 job = getjob(*argv, 0);
4080 /* loop until process terminated or stopped */
4081 while (job->state == JOBRUNNING)
4082 blocking_wait_with_raise_on_sig(NULL);
4084 retval = getstatus(job);
4097 struct job *jp, *jq;
4099 len = njobs * sizeof(*jp);
4101 jp = ckrealloc(jq, len + 4 * sizeof(*jp));
4103 offset = (char *)jp - (char *)jq;
4105 /* Relocate pointers */
4108 jq = (struct job *)((char *)jq + l);
4112 #define joff(p) ((struct job *)((char *)(p) + l))
4113 #define jmove(p) (p) = (void *)((char *)(p) + offset)
4114 if (joff(jp)->ps == &jq->ps0)
4115 jmove(joff(jp)->ps);
4116 if (joff(jp)->prev_job)
4117 jmove(joff(jp)->prev_job);
4127 jp = (struct job *)((char *)jp + len);
4131 } while (--jq >= jp);
4136 * Return a new job structure.
4137 * Called with interrupts off.
4140 makejob(/*union node *node,*/ int nprocs)
4145 for (i = njobs, jp = jobtab; ; jp++) {
4152 if (jp->state != JOBDONE || !jp->waited)
4161 memset(jp, 0, sizeof(*jp));
4163 /* jp->jobctl is a bitfield.
4164 * "jp->jobctl |= jobctl" likely to give awful code */
4168 jp->prev_job = curjob;
4173 jp->ps = ckmalloc(nprocs * sizeof(struct procstat));
4175 TRACE(("makejob(%d) returns %%%d\n", nprocs,
4182 * Return a string identifying a command (to be printed by the
4185 static char *cmdnextc;
4188 cmdputs(const char *s)
4190 static const char vstype[VSTYPE + 1][3] = {
4191 "", "}", "-", "+", "?", "=",
4192 "%", "%%", "#", "##"
4193 USE_ASH_BASH_COMPAT(, ":", "/", "//")
4196 const char *p, *str;
4197 char c, cc[2] = " ";
4202 nextc = makestrspace((strlen(s) + 1) * 8, cmdnextc);
4204 while ((c = *p++) != 0) {
4212 if ((subtype & VSTYPE) == VSLENGTH)
4216 if (!(subtype & VSQUOTE) == !(quoted & 1))
4222 str = "\"}" + !(quoted & 1);
4229 case CTLBACKQ+CTLQUOTE:
4232 #if ENABLE_ASH_MATH_SUPPORT
4247 if ((subtype & VSTYPE) != VSNORMAL)
4249 str = vstype[subtype & VSTYPE];
4250 if (subtype & VSNUL)
4259 /* These can only happen inside quotes */
4272 while ((c = *str++)) {
4277 USTPUTC('"', nextc);
4283 /* cmdtxt() and cmdlist() call each other */
4284 static void cmdtxt(union node *n);
4287 cmdlist(union node *np, int sep)
4289 for (; np; np = np->narg.next) {
4293 if (sep && np->narg.next)
4299 cmdtxt(union node *n)
4302 struct nodelist *lp;
4313 lp = n->npipe.cmdlist;
4331 cmdtxt(n->nbinary.ch1);
4347 cmdtxt(n->nif.test);
4350 if (n->nif.elsepart) {
4353 n = n->nif.elsepart;
4369 cmdtxt(n->nbinary.ch1);
4379 cmdputs(n->nfor.var);
4381 cmdlist(n->nfor.args, 1);
4386 cmdputs(n->narg.text);
4390 cmdlist(n->ncmd.args, 1);
4391 cmdlist(n->ncmd.redirect, 0);
4404 cmdputs(n->ncase.expr->narg.text);
4406 for (np = n->ncase.cases; np; np = np->nclist.next) {
4407 cmdtxt(np->nclist.pattern);
4409 cmdtxt(np->nclist.body);
4423 #if ENABLE_ASH_BASH_COMPAT
4438 cmdputs(utoa(n->nfile.fd));
4440 if (n->type == NTOFD || n->type == NFROMFD) {
4441 cmdputs(utoa(n->ndup.dupfd));
4450 commandtext(union node *n)
4454 STARTSTACKSTR(cmdnextc);
4456 name = stackblock();
4457 TRACE(("commandtext: name %p, end %p\n\t\"%s\"\n",
4458 name, cmdnextc, cmdnextc));
4459 return ckstrdup(name);
4464 * Fork off a subshell. If we are doing job control, give the subshell its
4465 * own process group. Jp is a job structure that the job is to be added to.
4466 * N is the command that will be evaluated by the child. Both jp and n may
4467 * be NULL. The mode parameter can be one of the following:
4468 * FORK_FG - Fork off a foreground process.
4469 * FORK_BG - Fork off a background process.
4470 * FORK_NOJOB - Like FORK_FG, but don't give the process its own
4471 * process group even if job control is on.
4473 * When job control is turned off, background processes have their standard
4474 * input redirected to /dev/null (except for the second and later processes
4477 * Called with interrupts off.
4480 * Clear traps on a fork.
4487 for (tp = trap; tp < &trap[NSIG]; tp++) {
4488 if (*tp && **tp) { /* trap not NULL or "" (SIG_IGN) */
4493 setsignal(tp - trap);
4499 /* Lives far away from here, needed for forkchild */
4500 static void closescript(void);
4502 /* Called after fork(), in child */
4504 forkchild(struct job *jp, /*union node *n,*/ int mode)
4508 TRACE(("Child shell %d\n", getpid()));
4512 /* man bash: "Non-builtin commands run by bash have signal handlers
4513 * set to the values inherited by the shell from its parent".
4514 * Do we do it correctly? */
4519 /* do job control only in root shell */
4521 if (mode != FORK_NOJOB && jp->jobctl && !oldlvl) {
4524 if (jp->nprocs == 0)
4527 pgrp = jp->ps[0].pid;
4528 /* this can fail because we are doing it in the parent also */
4530 if (mode == FORK_FG)
4531 xtcsetpgrp(ttyfd, pgrp);
4536 if (mode == FORK_BG) {
4537 /* man bash: "When job control is not in effect,
4538 * asynchronous commands ignore SIGINT and SIGQUIT" */
4541 if (jp->nprocs == 0) {
4543 if (open(bb_dev_null, O_RDONLY) != 0)
4544 ash_msg_and_raise_error("can't open %s", bb_dev_null);
4548 if (iflag) { /* why if iflag only? */
4553 * "In all cases, bash ignores SIGQUIT. Non-builtin
4554 * commands run by bash have signal handlers
4555 * set to the values inherited by the shell
4557 * Take care of the second rule: */
4560 for (jp = curjob; jp; jp = jp->prev_job)
4565 /* Called after fork(), in parent */
4567 #define forkparent(jp, n, mode, pid) forkparent(jp, mode, pid)
4570 forkparent(struct job *jp, union node *n, int mode, pid_t pid)
4572 TRACE(("In parent shell: child = %d\n", pid));
4574 while (jobless && dowait(DOWAIT_NONBLOCK, NULL) > 0)
4580 if (mode != FORK_NOJOB && jp->jobctl) {
4583 if (jp->nprocs == 0)
4586 pgrp = jp->ps[0].pid;
4587 /* This can fail because we are doing it in the child also */
4591 if (mode == FORK_BG) {
4592 backgndpid = pid; /* set $! */
4593 set_curjob(jp, CUR_RUNNING);
4596 struct procstat *ps = &jp->ps[jp->nprocs++];
4601 if (doing_jobctl && n)
4602 ps->cmd = commandtext(n);
4608 forkshell(struct job *jp, union node *n, int mode)
4612 TRACE(("forkshell(%%%d, %p, %d) called\n", jobno(jp), n, mode));
4615 TRACE(("Fork failed, errno=%d", errno));
4618 ash_msg_and_raise_error("can't fork");
4621 forkchild(jp, /*n,*/ mode);
4623 forkparent(jp, n, mode, pid);
4628 * Wait for job to finish.
4630 * Under job control we have the problem that while a child process
4631 * is running interrupts generated by the user are sent to the child
4632 * but not to the shell. This means that an infinite loop started by
4633 * an interactive user may be hard to kill. With job control turned off,
4634 * an interactive user may place an interactive program inside a loop.
4635 * If the interactive program catches interrupts, the user doesn't want
4636 * these interrupts to also abort the loop. The approach we take here
4637 * is to have the shell ignore interrupt signals while waiting for a
4638 * foreground process to terminate, and then send itself an interrupt
4639 * signal if the child process was terminated by an interrupt signal.
4640 * Unfortunately, some programs want to do a bit of cleanup and then
4641 * exit on interrupt; unless these processes terminate themselves by
4642 * sending a signal to themselves (instead of calling exit) they will
4643 * confuse this approach.
4645 * Called with interrupts off.
4648 waitforjob(struct job *jp)
4652 TRACE(("waitforjob(%%%d) called\n", jobno(jp)));
4655 while (jp->state == JOBRUNNING) {
4656 /* In non-interactive shells, we _can_ get
4657 * a keyboard signal here and be EINTRed,
4658 * but we just loop back, waiting for command to complete.
4661 * "If bash is waiting for a command to complete and receives
4662 * a signal for which a trap has been set, the trap
4663 * will not be executed until the command completes."
4665 * Reality is that even if trap is not set, bash
4666 * will not act on the signal until command completes.
4667 * Try this. sleep5intoff.c:
4668 * #include <signal.h>
4669 * #include <unistd.h>
4672 * sigemptyset(&set);
4673 * sigaddset(&set, SIGINT);
4674 * sigaddset(&set, SIGQUIT);
4675 * sigprocmask(SIG_BLOCK, &set, NULL);
4679 * $ bash -c './sleep5intoff; echo hi'
4680 * ^C^C^C^C <--- pressing ^C once a second
4682 * $ bash -c './sleep5intoff; echo hi'
4683 * ^\^\^\^\hi <--- pressing ^\ (SIGQUIT)
4686 dowait(DOWAIT_BLOCK, jp);
4693 xtcsetpgrp(ttyfd, rootpid);
4695 * This is truly gross.
4696 * If we're doing job control, then we did a TIOCSPGRP which
4697 * caused us (the shell) to no longer be in the controlling
4698 * session -- so we wouldn't have seen any ^C/SIGINT. So, we
4699 * intuit from the subprocess exit status whether a SIGINT
4700 * occurred, and if so interrupt ourselves. Yuck. - mycroft
4702 if (jp->sigint) /* TODO: do the same with all signals */
4703 raise(SIGINT); /* ... by raise(jp->sig) instead? */
4705 if (jp->state == JOBDONE)
4712 * return 1 if there are stopped jobs, otherwise 0
4724 if (jp && jp->state == JOBSTOPPED) {
4725 out2str("You have stopped jobs.\n");
4734 /* ============ redir.c
4736 * Code for dealing with input/output redirection.
4739 #define EMPTY -2 /* marks an unused slot in redirtab */
4740 #define CLOSED -3 /* marks a slot of previously-closed fd */
4743 * Open a file in noclobber mode.
4744 * The code was copied from bash.
4747 noclobberopen(const char *fname)
4750 struct stat finfo, finfo2;
4753 * If the file exists and is a regular file, return an error
4756 r = stat(fname, &finfo);
4757 if (r == 0 && S_ISREG(finfo.st_mode)) {
4763 * If the file was not present (r != 0), make sure we open it
4764 * exclusively so that if it is created before we open it, our open
4765 * will fail. Make sure that we do not truncate an existing file.
4766 * Note that we don't turn on O_EXCL unless the stat failed -- if the
4767 * file was not a regular file, we leave O_EXCL off.
4770 return open(fname, O_WRONLY|O_CREAT|O_EXCL, 0666);
4771 fd = open(fname, O_WRONLY|O_CREAT, 0666);
4773 /* If the open failed, return the file descriptor right away. */
4778 * OK, the open succeeded, but the file may have been changed from a
4779 * non-regular file to a regular file between the stat and the open.
4780 * We are assuming that the O_EXCL open handles the case where FILENAME
4781 * did not exist and is symlinked to an existing file between the stat
4786 * If we can open it and fstat the file descriptor, and neither check
4787 * revealed that it was a regular file, and the file has not been
4788 * replaced, return the file descriptor.
4790 if (fstat(fd, &finfo2) == 0 && !S_ISREG(finfo2.st_mode)
4791 && finfo.st_dev == finfo2.st_dev && finfo.st_ino == finfo2.st_ino)
4794 /* The file has been replaced. badness. */
4801 * Handle here documents. Normally we fork off a process to write the
4802 * data to a pipe. If the document is short, we can stuff the data in
4803 * the pipe without forking.
4805 /* openhere needs this forward reference */
4806 static void expandhere(union node *arg, int fd);
4808 openhere(union node *redir)
4814 ash_msg_and_raise_error("pipe call failed");
4815 if (redir->type == NHERE) {
4816 len = strlen(redir->nhere.doc->narg.text);
4817 if (len <= PIPE_BUF) {
4818 full_write(pip[1], redir->nhere.doc->narg.text, len);
4822 if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) {
4825 ignoresig(SIGINT); //signal(SIGINT, SIG_IGN);
4826 ignoresig(SIGQUIT); //signal(SIGQUIT, SIG_IGN);
4827 ignoresig(SIGHUP); //signal(SIGHUP, SIG_IGN);
4828 ignoresig(SIGTSTP); //signal(SIGTSTP, SIG_IGN);
4829 signal(SIGPIPE, SIG_DFL);
4830 if (redir->type == NHERE)
4831 full_write(pip[1], redir->nhere.doc->narg.text, len);
4833 expandhere(redir->nhere.doc, pip[1]);
4834 _exit(EXIT_SUCCESS);
4842 openredirect(union node *redir)
4847 switch (redir->nfile.type) {
4849 fname = redir->nfile.expfname;
4850 f = open(fname, O_RDONLY);
4855 fname = redir->nfile.expfname;
4856 f = open(fname, O_RDWR|O_CREAT|O_TRUNC, 0666);
4861 #if ENABLE_ASH_BASH_COMPAT
4864 /* Take care of noclobber mode. */
4866 fname = redir->nfile.expfname;
4867 f = noclobberopen(fname);
4874 fname = redir->nfile.expfname;
4875 f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666);
4880 fname = redir->nfile.expfname;
4881 f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666);
4889 /* Fall through to eliminate warning. */
4890 /* Our single caller does this itself */
4897 f = openhere(redir);
4903 ash_msg_and_raise_error("can't create %s: %s", fname, errmsg(errno, "nonexistent directory"));
4905 ash_msg_and_raise_error("can't open %s: %s", fname, errmsg(errno, "no such file"));
4909 * Copy a file descriptor to be >= to. Returns -1
4910 * if the source file descriptor is closed, EMPTY if there are no unused
4911 * file descriptors left.
4913 /* 0x800..00: bit to set in "to" to request dup2 instead of fcntl(F_DUPFD).
4914 * old code was doing close(to) prior to copyfd() to achieve the same */
4916 COPYFD_EXACT = (int)~(INT_MAX),
4917 COPYFD_RESTORE = (int)((unsigned)COPYFD_EXACT >> 1),
4920 copyfd(int from, int to)
4924 if (to & COPYFD_EXACT) {
4925 to &= ~COPYFD_EXACT;
4927 newfd = dup2(from, to);
4929 newfd = fcntl(from, F_DUPFD, to);
4932 if (errno == EMFILE)
4934 /* Happens when source fd is not open: try "echo >&99" */
4935 ash_msg_and_raise_error("%d: %m", from);
4940 /* Struct def and variable are moved down to the first usage site */
4945 struct redirtab *next;
4948 struct two_fd_t two_fd[0];
4950 #define redirlist (G_var.redirlist)
4952 static int need_to_remember(struct redirtab *rp, int fd)
4956 if (!rp) /* remembering was not requested */
4959 for (i = 0; i < rp->pair_count; i++) {
4960 if (rp->two_fd[i].orig == fd) {
4961 /* already remembered */
4968 /* "hidden" fd is a fd used to read scripts, or a copy of such */
4969 static int is_hidden_fd(struct redirtab *rp, int fd)
4972 struct parsefile *pf;
4985 fd |= COPYFD_RESTORE;
4986 for (i = 0; i < rp->pair_count; i++) {
4987 if (rp->two_fd[i].copy == fd) {
4995 * Process a list of redirection commands. If the REDIR_PUSH flag is set,
4996 * old file descriptors are stashed away so that the redirection can be
4997 * undone by calling popredir. If the REDIR_BACKQ flag is set, then the
4998 * standard output, and the standard error if it becomes a duplicate of
4999 * stdout, is saved in memory.
5001 /* flags passed to redirect */
5002 #define REDIR_PUSH 01 /* save previous values of file descriptors */
5003 #define REDIR_SAVEFD2 03 /* set preverrout */
5005 redirect(union node *redir, int flags)
5007 struct redirtab *sv;
5012 int copied_fd2 = -1;
5022 if (flags & REDIR_PUSH) {
5023 union node *tmp = redir;
5026 #if ENABLE_ASH_BASH_COMPAT
5027 if (redir->nfile.type == NTO2)
5030 tmp = tmp->nfile.next;
5032 sv = ckmalloc(sizeof(*sv) + sv_pos * sizeof(sv->two_fd[0]));
5033 sv->next = redirlist;
5034 sv->pair_count = sv_pos;
5036 sv->nullredirs = g_nullredirs - 1;
5038 while (sv_pos > 0) {
5040 sv->two_fd[sv_pos].orig = sv->two_fd[sv_pos].copy = EMPTY;
5045 fd = redir->nfile.fd;
5046 if (redir->nfile.type == NTOFD || redir->nfile.type == NFROMFD) {
5047 int right_fd = redir->ndup.dupfd;
5048 /* redirect from/to same file descriptor? */
5051 /* echo >&10 and 10 is a fd opened to the sh script? */
5052 if (is_hidden_fd(sv, right_fd)) {
5053 errno = EBADF; /* as if it is closed */
5054 ash_msg_and_raise_error("%d: %m", right_fd);
5058 newfd = openredirect(redir); /* always >= 0 */
5060 /* Descriptor wasn't open before redirect.
5061 * Mark it for close in the future */
5062 if (need_to_remember(sv, fd)) {
5063 goto remember_to_close;
5068 #if ENABLE_ASH_BASH_COMPAT
5071 if (need_to_remember(sv, fd)) {
5072 /* Copy old descriptor */
5073 i = fcntl(fd, F_DUPFD, 10);
5074 /* You'd expect copy to be CLOEXECed. Currently these extra "saved" fds
5075 * are closed in popredir() in the child, preventing them from leaking
5076 * into child. (popredir() also cleans up the mess in case of failures)
5081 /* Strange error (e.g. "too many files" EMFILE?) */
5085 ash_msg_and_raise_error("%d: %m", fd);
5088 /* EBADF: it is not open - good, remember to close it */
5091 } else { /* fd is open, save its copy */
5092 /* "exec fd>&-" should not close fds
5093 * which point to script file(s).
5094 * Force them to be restored afterwards */
5095 if (is_hidden_fd(sv, fd))
5096 i |= COPYFD_RESTORE;
5100 sv->two_fd[sv_pos].orig = fd;
5101 sv->two_fd[sv_pos].copy = i;
5105 /* NTOFD/NFROMFD: copy redir->ndup.dupfd to fd */
5106 if (redir->ndup.dupfd < 0) { /* "fd>&-" */
5109 copyfd(redir->ndup.dupfd, fd | COPYFD_EXACT);
5111 } else if (fd != newfd) { /* move newfd to fd */
5112 copyfd(newfd, fd | COPYFD_EXACT);
5113 #if ENABLE_ASH_BASH_COMPAT
5114 if (!(redir->nfile.type == NTO2 && fd == 2))
5118 #if ENABLE_ASH_BASH_COMPAT
5119 if (redir->nfile.type == NTO2 && fd == 1) {
5120 /* We already redirected it to fd 1, now copy it to 2 */
5126 } while ((redir = redir->nfile.next) != NULL);
5129 if ((flags & REDIR_SAVEFD2) && copied_fd2 >= 0)
5130 preverrout_fd = copied_fd2;
5134 * Undo the effects of the last redirection.
5137 popredir(int drop, int restore)
5139 struct redirtab *rp;
5142 if (--g_nullredirs >= 0)
5146 for (i = 0; i < rp->pair_count; i++) {
5147 int fd = rp->two_fd[i].orig;
5148 int copy = rp->two_fd[i].copy;
5149 if (copy == CLOSED) {
5154 if (copy != EMPTY) {
5155 if (!drop || (restore && (copy & COPYFD_RESTORE))) {
5156 copy &= ~COPYFD_RESTORE;
5158 copyfd(copy, fd | COPYFD_EXACT);
5163 redirlist = rp->next;
5164 g_nullredirs = rp->nullredirs;
5170 * Undo all redirections. Called on error or interrupt.
5174 * Discard all saved file descriptors.
5177 clearredir(int drop)
5183 popredir(drop, /*restore:*/ 0);
5188 redirectsafe(union node *redir, int flags)
5191 volatile int saveint;
5192 struct jmploc *volatile savehandler = exception_handler;
5193 struct jmploc jmploc;
5196 /* "echo 9>/dev/null; echo >&9; echo result: $?" - result should be 1, not 2! */
5197 err = setjmp(jmploc.loc); // huh?? was = setjmp(jmploc.loc) * 2;
5199 exception_handler = &jmploc;
5200 redirect(redir, flags);
5202 exception_handler = savehandler;
5203 if (err && exception != EXERROR)
5204 longjmp(exception_handler->loc, 1);
5205 RESTORE_INT(saveint);
5210 /* ============ Routines to expand arguments to commands
5212 * We have to deal with backquotes, shell variables, and file metacharacters.
5215 #if ENABLE_ASH_MATH_SUPPORT_64
5216 typedef int64_t arith_t;
5217 #define arith_t_type long long
5219 typedef long arith_t;
5220 #define arith_t_type long
5223 #if ENABLE_ASH_MATH_SUPPORT
5224 static arith_t dash_arith(const char *);
5225 static arith_t arith(const char *expr, int *perrcode);
5231 #define EXP_FULL 0x1 /* perform word splitting & file globbing */
5232 #define EXP_TILDE 0x2 /* do normal tilde expansion */
5233 #define EXP_VARTILDE 0x4 /* expand tildes in an assignment */
5234 #define EXP_REDIR 0x8 /* file glob for a redirection (1 match only) */
5235 #define EXP_CASE 0x10 /* keeps quotes around for CASE pattern */
5236 #define EXP_RECORD 0x20 /* need to record arguments for ifs breakup */
5237 #define EXP_VARTILDE2 0x40 /* expand tildes after colons only */
5238 #define EXP_WORD 0x80 /* expand word in parameter expansion */
5239 #define EXP_QWORD 0x100 /* expand word in quoted parameter expansion */
5243 #define RMESCAPE_ALLOC 0x1 /* Allocate a new string */
5244 #define RMESCAPE_GLOB 0x2 /* Add backslashes for glob */
5245 #define RMESCAPE_QUOTED 0x4 /* Remove CTLESC unless in quotes */
5246 #define RMESCAPE_GROW 0x8 /* Grow strings instead of stalloc */
5247 #define RMESCAPE_HEAP 0x10 /* Malloc strings instead of stalloc */
5250 * Structure specifying which parts of the string should be searched
5251 * for IFS characters.
5254 struct ifsregion *next; /* next region in list */
5255 int begoff; /* offset of start of region */
5256 int endoff; /* offset of end of region */
5257 int nulonly; /* search for nul bytes only */
5261 struct strlist *list;
5262 struct strlist **lastp;
5265 /* output of current string */
5266 static char *expdest;
5267 /* list of back quote expressions */
5268 static struct nodelist *argbackq;
5269 /* first struct in list of ifs regions */
5270 static struct ifsregion ifsfirst;
5271 /* last struct in list */
5272 static struct ifsregion *ifslastp;
5273 /* holds expanded arg list */
5274 static struct arglist exparg;
5284 expdest = makestrspace(32, expdest);
5285 #if ENABLE_ASH_MATH_SUPPORT_64
5286 len = fmtstr(expdest, 32, "%lld", (long long) num);
5288 len = fmtstr(expdest, 32, "%ld", num);
5290 STADJUST(len, expdest);
5295 esclen(const char *start, const char *p)
5299 while (p > start && *--p == CTLESC) {
5306 * Remove any CTLESC characters from a string.
5309 _rmescapes(char *str, int flag)
5311 static const char qchars[] ALIGN1 = { CTLESC, CTLQUOTEMARK, '\0' };
5318 p = strpbrk(str, qchars);
5324 if (flag & RMESCAPE_ALLOC) {
5325 size_t len = p - str;
5326 size_t fulllen = len + strlen(p) + 1;
5328 if (flag & RMESCAPE_GROW) {
5329 r = makestrspace(fulllen, expdest);
5330 } else if (flag & RMESCAPE_HEAP) {
5331 r = ckmalloc(fulllen);
5333 r = stalloc(fulllen);
5337 q = (char *)memcpy(q, str, len) + len;
5340 inquotes = (flag & RMESCAPE_QUOTED) ^ RMESCAPE_QUOTED;
5341 globbing = flag & RMESCAPE_GLOB;
5342 notescaped = globbing;
5344 if (*p == CTLQUOTEMARK) {
5345 inquotes = ~inquotes;
5347 notescaped = globbing;
5351 /* naked back slash */
5357 if (notescaped && inquotes && *p != '/') {
5361 notescaped = globbing;
5366 if (flag & RMESCAPE_GROW) {
5368 STADJUST(q - r + 1, expdest);
5372 #define rmescapes(p) _rmescapes((p), 0)
5374 #define pmatch(a, b) !fnmatch((a), (b), 0)
5377 * Prepare a pattern for a expmeta (internal glob(3)) call.
5379 * Returns an stalloced string.
5382 preglob(const char *pattern, int quoted, int flag)
5384 flag |= RMESCAPE_GLOB;
5386 flag |= RMESCAPE_QUOTED;
5388 return _rmescapes((char *)pattern, flag);
5392 * Put a string on the stack.
5395 memtodest(const char *p, size_t len, int syntax, int quotes)
5399 q = makestrspace(len * 2, q);
5402 int c = signed_char2int(*p++);
5405 if (quotes && (SIT(c, syntax) == CCTL || SIT(c, syntax) == CBACK))
5414 strtodest(const char *p, int syntax, int quotes)
5416 memtodest(p, strlen(p), syntax, quotes);
5420 * Record the fact that we have to scan this region of the
5421 * string for IFS characters.
5424 recordregion(int start, int end, int nulonly)
5426 struct ifsregion *ifsp;
5428 if (ifslastp == NULL) {
5432 ifsp = ckzalloc(sizeof(*ifsp));
5433 /*ifsp->next = NULL; - ckzalloc did it */
5434 ifslastp->next = ifsp;
5438 ifslastp->begoff = start;
5439 ifslastp->endoff = end;
5440 ifslastp->nulonly = nulonly;
5444 removerecordregions(int endoff)
5446 if (ifslastp == NULL)
5449 if (ifsfirst.endoff > endoff) {
5450 while (ifsfirst.next != NULL) {
5451 struct ifsregion *ifsp;
5453 ifsp = ifsfirst.next->next;
5454 free(ifsfirst.next);
5455 ifsfirst.next = ifsp;
5458 if (ifsfirst.begoff > endoff)
5461 ifslastp = &ifsfirst;
5462 ifsfirst.endoff = endoff;
5467 ifslastp = &ifsfirst;
5468 while (ifslastp->next && ifslastp->next->begoff < endoff)
5469 ifslastp=ifslastp->next;
5470 while (ifslastp->next != NULL) {
5471 struct ifsregion *ifsp;
5473 ifsp = ifslastp->next->next;
5474 free(ifslastp->next);
5475 ifslastp->next = ifsp;
5478 if (ifslastp->endoff > endoff)
5479 ifslastp->endoff = endoff;
5483 exptilde(char *startp, char *p, int flag)
5489 int quotes = flag & (EXP_FULL | EXP_CASE);
5494 while ((c = *++p) != '\0') {
5501 if (flag & EXP_VARTILDE)
5511 if (*name == '\0') {
5512 home = lookupvar(homestr);
5514 pw = getpwnam(name);
5519 if (!home || !*home)
5522 startloc = expdest - (char *)stackblock();
5523 strtodest(home, SQSYNTAX, quotes);
5524 recordregion(startloc, expdest - (char *)stackblock(), 0);
5532 * Execute a command inside back quotes. If it's a builtin command, we
5533 * want to save its output in a block obtained from malloc. Otherwise
5534 * we fork off a subprocess and get the output of the command via a pipe.
5535 * Should be called with interrupts off.
5537 struct backcmd { /* result of evalbackcmd */
5538 int fd; /* file descriptor to read from */
5539 int nleft; /* number of chars in buffer */
5540 char *buf; /* buffer */
5541 struct job *jp; /* job structure for command */
5544 /* These forward decls are needed to use "eval" code for backticks handling: */
5545 static uint8_t back_exitstatus; /* exit status of backquoted command */
5546 #define EV_EXIT 01 /* exit after evaluating tree */
5547 static void evaltree(union node *, int);
5550 evalbackcmd(union node *n, struct backcmd *result)
5561 saveherefd = herefd;
5569 ash_msg_and_raise_error("pipe call failed");
5570 jp = makejob(/*n,*/ 1);
5571 if (forkshell(jp, n, FORK_NOJOB) == 0) {
5576 copyfd(pip[1], 1 | COPYFD_EXACT);
5580 evaltree(n, EV_EXIT); /* actually evaltreenr... */
5584 result->fd = pip[0];
5587 herefd = saveherefd;
5589 TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n",
5590 result->fd, result->buf, result->nleft, result->jp));
5594 * Expand stuff in backwards quotes.
5597 expbackq(union node *cmd, int quoted, int quotes)
5605 int syntax = quoted ? DQSYNTAX : BASESYNTAX;
5606 struct stackmark smark;
5609 setstackmark(&smark);
5611 startloc = dest - (char *)stackblock();
5613 evalbackcmd(cmd, &in);
5614 popstackmark(&smark);
5621 memtodest(p, i, syntax, quotes);
5625 i = nonblock_safe_read(in.fd, buf, sizeof(buf));
5626 TRACE(("expbackq: read returns %d\n", i));
5635 back_exitstatus = waitforjob(in.jp);
5639 /* Eat all trailing newlines */
5641 for (; dest > (char *)stackblock() && dest[-1] == '\n';)
5646 recordregion(startloc, dest - (char *)stackblock(), 0);
5647 TRACE(("evalbackq: size=%d: \"%.*s\"\n",
5648 (dest - (char *)stackblock()) - startloc,
5649 (dest - (char *)stackblock()) - startloc,
5650 stackblock() + startloc));
5653 #if ENABLE_ASH_MATH_SUPPORT
5655 * Expand arithmetic expression. Backup to start of expression,
5656 * evaluate, place result in (backed up) result, adjust string position.
5669 * This routine is slightly over-complicated for
5670 * efficiency. Next we scan backwards looking for the
5671 * start of arithmetic.
5673 start = stackblock();
5680 while (*p != CTLARI) {
5684 ash_msg_and_raise_error("missing CTLARI (shouldn't happen)");
5689 esc = esclen(start, p);
5699 removerecordregions(begoff);
5708 len = cvtnum(dash_arith(p + 2));
5711 recordregion(begoff, begoff + len, 0);
5715 /* argstr needs it */
5716 static char *evalvar(char *p, int flag, struct strlist *var_str_list);
5719 * Perform variable and command substitution. If EXP_FULL is set, output CTLESC
5720 * characters to allow for further processing. Otherwise treat
5721 * $@ like $* since no splitting will be performed.
5723 * var_str_list (can be NULL) is a list of "VAR=val" strings which take precedence
5724 * over shell varables. Needed for "A=a B=$A; echo $B" case - we use it
5725 * for correct expansion of "B=$A" word.
5728 argstr(char *p, int flag, struct strlist *var_str_list)
5730 static const char spclchars[] ALIGN1 = {
5738 CTLBACKQ | CTLQUOTE,
5739 #if ENABLE_ASH_MATH_SUPPORT
5744 const char *reject = spclchars;
5746 int quotes = flag & (EXP_FULL | EXP_CASE); /* do CTLESC */
5747 int breakall = flag & EXP_WORD;
5752 if (!(flag & EXP_VARTILDE)) {
5754 } else if (flag & EXP_VARTILDE2) {
5759 if (flag & EXP_TILDE) {
5765 if (*q == CTLESC && (flag & EXP_QWORD))
5768 p = exptilde(p, q, flag);
5771 startloc = expdest - (char *)stackblock();
5773 length += strcspn(p + length, reject);
5775 if (c && (!(c & 0x80)
5776 #if ENABLE_ASH_MATH_SUPPORT
5780 /* c == '=' || c == ':' || c == CTLENDARI */
5785 expdest = stack_nputstr(p, length, expdest);
5786 newloc = expdest - (char *)stackblock();
5787 if (breakall && !inquotes && newloc > startloc) {
5788 recordregion(startloc, newloc, 0);
5799 if (flag & EXP_VARTILDE2) {
5803 flag |= EXP_VARTILDE2;
5808 * sort of a hack - expand tildes in variable
5809 * assignments (after the first '=' and after ':'s).
5818 case CTLENDVAR: /* ??? */
5821 /* "$@" syntax adherence hack */
5824 !memcmp(p, dolatstr, 4) &&
5825 (p[4] == CTLQUOTEMARK || (
5826 p[4] == CTLENDVAR &&
5827 p[5] == CTLQUOTEMARK
5830 p = evalvar(p + 1, flag, /* var_str_list: */ NULL) + 1;
5833 inquotes = !inquotes;
5846 p = evalvar(p, flag, var_str_list);
5850 case CTLBACKQ|CTLQUOTE:
5851 expbackq(argbackq->n, c, quotes);
5852 argbackq = argbackq->next;
5854 #if ENABLE_ASH_MATH_SUPPORT
5867 scanleft(char *startp, char *rmesc, char *rmescend UNUSED_PARAM, char *str, int quotes,
5870 // This commented out code was added by James Simmons <jsimmons@infradead.org>
5871 // as part of a larger change when he added support for ${var/a/b}.
5872 // However, it broke # and % operators:
5876 //echo ${var#ab} abcdcd abcdcd
5877 //echo ${var##ab} abcdcd abcdcd
5878 //echo ${var#a*b} abcdcd ababcdcd (!)
5879 //echo ${var##a*b} cdcd cdcd
5880 //echo ${var#?} babcdcd ababcdcd (!)
5881 //echo ${var##?} babcdcd babcdcd
5882 //echo ${var#*} ababcdcd babcdcd (!)
5884 //echo ${var%cd} ababcd ababcd
5885 //echo ${var%%cd} ababcd abab (!)
5886 //echo ${var%c*d} ababcd ababcd
5887 //echo ${var%%c*d} abab ababcdcd (!)
5888 //echo ${var%?} ababcdc ababcdc
5889 //echo ${var%%?} ababcdc ababcdcd (!)
5890 //echo ${var%*} ababcdcd ababcdcd
5893 // Commenting it back out helped. Remove it completely if it really
5896 char *loc, *loc2; //, *full;
5902 int match; // = strlen(str);
5903 const char *s = loc2;
5910 match = pmatch(str, s); // this line was deleted
5912 // // chop off end if its '*'
5913 // full = strrchr(str, '*');
5914 // if (full && full != str)
5917 // // If str starts with '*' replace with s.
5918 // if ((*str == '*') && strlen(s) >= match) {
5919 // full = xstrdup(s);
5920 // strncpy(full+strlen(s)-match+1, str+1, match-1);
5922 // full = xstrndup(str, match);
5923 // match = strncmp(s, full, strlen(full));
5927 if (match) // if (!match)
5929 if (quotes && *loc == CTLESC)
5938 scanright(char *startp, char *rmesc, char *rmescend, char *str, int quotes,
5945 for (loc = str - 1, loc2 = rmescend; loc >= startp; loc2--) {
5948 const char *s = loc2;
5953 match = pmatch(str, s);
5960 esc = esclen(startp, loc);
5971 static void varunset(const char *, const char *, const char *, int) NORETURN;
5973 varunset(const char *end, const char *var, const char *umsg, int varflags)
5979 msg = "parameter not set";
5981 if (*end == CTLENDVAR) {
5982 if (varflags & VSNUL)
5988 ash_msg_and_raise_error("%.*s: %s%s", end - var - 1, var, msg, tail);
5991 #if ENABLE_ASH_BASH_COMPAT
5993 parse_sub_pattern(char *arg, int inquotes)
5995 char *idx, *repl = NULL;
6004 /* Only the first '/' seen is our separator */
6011 if (!inquotes && c == '\\' && arg[1] == '\\')
6012 arg++; /* skip both \\, not just first one */
6019 #endif /* ENABLE_ASH_BASH_COMPAT */
6022 subevalvar(char *p, char *str, int strloc, int subtype,
6023 int startloc, int varflags, int quotes, struct strlist *var_str_list)
6025 struct nodelist *saveargbackq = argbackq;
6028 char *rmesc, *rmescend;
6029 USE_ASH_BASH_COMPAT(char *repl = NULL;)
6030 USE_ASH_BASH_COMPAT(char null = '\0';)
6031 USE_ASH_BASH_COMPAT(int pos, len, orig_len;)
6032 int saveherefd = herefd;
6033 int amount, workloc, resetloc;
6035 char *(*scan)(char*, char*, char*, char*, int, int);
6038 argstr(p, (subtype != VSASSIGN && subtype != VSQUESTION) ? EXP_CASE : 0,
6040 STPUTC('\0', expdest);
6041 herefd = saveherefd;
6042 argbackq = saveargbackq;
6043 startp = (char *)stackblock() + startloc;
6047 setvar(str, startp, 0);
6048 amount = startp - expdest;
6049 STADJUST(amount, expdest);
6052 #if ENABLE_ASH_BASH_COMPAT
6054 loc = str = stackblock() + strloc;
6055 // TODO: number() instead? It does error checking...
6057 len = str - startp - 1;
6059 /* *loc != '\0', guaranteed by parser */
6063 /* We must adjust the length by the number of escapes we find. */
6064 for (ptr = startp; ptr < (str - 1); ptr++) {
6065 if (*ptr == CTLESC) {
6073 if (*loc++ == ':') {
6074 // TODO: number() instead? It does error checking...
6078 while (*loc && *loc != ':')
6081 // TODO: number() instead? It does error checking...
6084 if (pos >= orig_len) {
6088 if (len > (orig_len - pos))
6089 len = orig_len - pos;
6091 for (str = startp; pos; str++, pos--) {
6092 if (quotes && *str == CTLESC)
6095 for (loc = startp; len; len--) {
6096 if (quotes && *str == CTLESC)
6101 amount = loc - expdest;
6102 STADJUST(amount, expdest);
6107 varunset(p, str, startp, varflags);
6110 resetloc = expdest - (char *)stackblock();
6112 /* We'll comeback here if we grow the stack while handling
6113 * a VSREPLACE or VSREPLACEALL, since our pointers into the
6114 * stack will need rebasing, and we'll need to remove our work
6117 USE_ASH_BASH_COMPAT(restart:)
6119 amount = expdest - ((char *)stackblock() + resetloc);
6120 STADJUST(-amount, expdest);
6121 startp = (char *)stackblock() + startloc;
6124 rmescend = (char *)stackblock() + strloc;
6126 rmesc = _rmescapes(startp, RMESCAPE_ALLOC | RMESCAPE_GROW);
6127 if (rmesc != startp) {
6129 startp = (char *)stackblock() + startloc;
6133 str = (char *)stackblock() + strloc;
6134 preglob(str, varflags & VSQUOTE, 0);
6135 workloc = expdest - (char *)stackblock();
6137 #if ENABLE_ASH_BASH_COMPAT
6138 if (subtype == VSREPLACE || subtype == VSREPLACEALL) {
6139 char *idx, *end, *restart_detect;
6142 repl = parse_sub_pattern(str, varflags & VSQUOTE);
6147 /* If there's no pattern to match, return the expansion unmolested */
6155 loc = scanright(idx, rmesc, rmescend, str, quotes, 1);
6157 /* No match, advance */
6158 restart_detect = stackblock();
6159 STPUTC(*idx, expdest);
6160 if (quotes && *idx == CTLESC) {
6163 STPUTC(*idx, expdest);
6165 if (stackblock() != restart_detect)
6173 if (subtype == VSREPLACEALL) {
6175 if (quotes && *idx == CTLESC)
6184 for (loc = repl; *loc; loc++) {
6185 restart_detect = stackblock();
6186 STPUTC(*loc, expdest);
6187 if (stackblock() != restart_detect)
6192 if (subtype == VSREPLACE) {
6194 restart_detect = stackblock();
6195 STPUTC(*idx, expdest);
6196 if (stackblock() != restart_detect)
6205 /* We've put the replaced text into a buffer at workloc, now
6206 * move it to the right place and adjust the stack.
6208 startp = stackblock() + startloc;
6209 STPUTC('\0', expdest);
6210 memmove(startp, stackblock() + workloc, len);
6211 startp[len++] = '\0';
6212 amount = expdest - ((char *)stackblock() + startloc + len - 1);
6213 STADJUST(-amount, expdest);
6216 #endif /* ENABLE_ASH_BASH_COMPAT */
6218 subtype -= VSTRIMRIGHT;
6220 if (subtype < 0 || subtype > 7)
6223 /* zero = subtype == VSTRIMLEFT || subtype == VSTRIMLEFTMAX */
6224 zero = subtype >> 1;
6225 /* VSTRIMLEFT/VSTRIMRIGHTMAX -> scanleft */
6226 scan = (subtype & 1) ^ zero ? scanleft : scanright;
6228 loc = scan(startp, rmesc, rmescend, str, quotes, zero);
6231 memmove(startp, loc, str - loc);
6232 loc = startp + (str - loc) - 1;
6235 amount = loc - expdest;
6236 STADJUST(amount, expdest);
6242 * Add the value of a specialized variable to the stack string.
6245 varvalue(char *name, int varflags, int flags, struct strlist *var_str_list)
6255 int quoted = varflags & VSQUOTE;
6256 int subtype = varflags & VSTYPE;
6257 int quotes = flags & (EXP_FULL | EXP_CASE);
6259 if (quoted && (flags & EXP_FULL))
6260 sep = 1 << CHAR_BIT;
6262 syntax = quoted ? DQSYNTAX : BASESYNTAX;
6271 num = shellparam.nparam;
6281 p = makestrspace(NOPTS, expdest);
6282 for (i = NOPTS - 1; i >= 0; i--) {
6284 USTPUTC(optletters(i), p);
6295 sep = ifsset() ? signed_char2int(ifsval()[0]) : ' ';
6296 if (quotes && (SIT(sep, syntax) == CCTL || SIT(sep, syntax) == CBACK))
6302 while ((p = *ap++)) {
6305 partlen = strlen(p);
6308 if (!(subtype == VSPLUS || subtype == VSLENGTH))
6309 memtodest(p, partlen, syntax, quotes);
6315 if (subtype == VSPLUS || subtype == VSLENGTH) {
6336 // TODO: number() instead? It does error checking...
6338 if (num < 0 || num > shellparam.nparam)
6340 p = num ? shellparam.p[num - 1] : arg0;
6343 /* NB: name has form "VAR=..." */
6345 /* "A=a B=$A" case: var_str_list is a list of "A=a" strings
6346 * which should be considered before we check variables. */
6348 unsigned name_len = (strchrnul(name, '=') - name) + 1;
6352 str = var_str_list->text;
6353 eq = strchr(str, '=');
6354 if (!eq) /* stop at first non-assignment */
6357 if (name_len == (unsigned)(eq - str)
6358 && strncmp(str, name, name_len) == 0) {
6360 /* goto value; - WRONG! */
6361 /* think "A=1 A=2 B=$A" */
6363 var_str_list = var_str_list->next;
6364 } while (var_str_list);
6368 p = lookupvar(name);
6374 if (!(subtype == VSPLUS || subtype == VSLENGTH))
6375 memtodest(p, len, syntax, quotes);
6379 if (subtype == VSPLUS || subtype == VSLENGTH)
6380 STADJUST(-len, expdest);
6385 * Expand a variable, and return a pointer to the next character in the
6389 evalvar(char *p, int flag, struct strlist *var_str_list)
6401 subtype = varflags & VSTYPE;
6402 quoted = varflags & VSQUOTE;
6404 easy = (!quoted || (*var == '@' && shellparam.nparam));
6405 startloc = expdest - (char *)stackblock();
6406 p = strchr(p, '=') + 1;
6409 varlen = varvalue(var, varflags, flag, var_str_list);
6410 if (varflags & VSNUL)
6413 if (subtype == VSPLUS) {
6414 varlen = -1 - varlen;
6418 if (subtype == VSMINUS) {
6422 p, flag | EXP_TILDE |
6423 (quoted ? EXP_QWORD : EXP_WORD),
6433 if (subtype == VSASSIGN || subtype == VSQUESTION) {
6435 if (subevalvar(p, var, /* strloc: */ 0,
6436 subtype, startloc, varflags,
6442 * Remove any recorded regions beyond
6445 removerecordregions(startloc);
6455 if (varlen < 0 && uflag)
6456 varunset(p, var, 0, 0);
6458 if (subtype == VSLENGTH) {
6459 cvtnum(varlen > 0 ? varlen : 0);
6463 if (subtype == VSNORMAL) {
6474 case VSTRIMRIGHTMAX:
6475 #if ENABLE_ASH_BASH_COMPAT
6488 * Terminate the string and start recording the pattern
6491 STPUTC('\0', expdest);
6492 patloc = expdest - (char *)stackblock();
6493 if (0 == subevalvar(p, /* str: */ NULL, patloc, subtype,
6495 /* quotes: */ flag & (EXP_FULL | EXP_CASE),
6498 int amount = expdest - (
6499 (char *)stackblock() + patloc - 1
6501 STADJUST(-amount, expdest);
6503 /* Remove any recorded regions beyond start of variable */
6504 removerecordregions(startloc);
6506 recordregion(startloc, expdest - (char *)stackblock(), quoted);
6510 if (subtype != VSNORMAL) { /* skip to end of alternative */
6516 else if (c == CTLBACKQ || c == (CTLBACKQ|CTLQUOTE)) {
6518 argbackq = argbackq->next;
6519 } else if (c == CTLVAR) {
6520 if ((*p++ & VSTYPE) != VSNORMAL)
6522 } else if (c == CTLENDVAR) {
6532 * Break the argument string into pieces based upon IFS and add the
6533 * strings to the argument list. The regions of the string to be
6534 * searched for IFS characters have been stored by recordregion.
6537 ifsbreakup(char *string, struct arglist *arglist)
6539 struct ifsregion *ifsp;
6544 const char *ifs, *realifs;
6549 if (ifslastp != NULL) {
6552 realifs = ifsset() ? ifsval() : defifs;
6555 p = string + ifsp->begoff;
6556 nulonly = ifsp->nulonly;
6557 ifs = nulonly ? nullstr : realifs;
6559 while (p < string + ifsp->endoff) {
6563 if (!strchr(ifs, *p)) {
6568 ifsspc = (strchr(defifs, *p) != NULL);
6569 /* Ignore IFS whitespace at start */
6570 if (q == start && ifsspc) {
6576 sp = stzalloc(sizeof(*sp));
6578 *arglist->lastp = sp;
6579 arglist->lastp = &sp->next;
6583 if (p >= string + ifsp->endoff) {
6589 if (strchr(ifs, *p) == NULL) {
6593 if (strchr(defifs, *p) == NULL) {
6608 } while (ifsp != NULL);
6617 sp = stzalloc(sizeof(*sp));
6619 *arglist->lastp = sp;
6620 arglist->lastp = &sp->next;
6626 struct ifsregion *p;
6631 struct ifsregion *ifsp;
6637 ifsfirst.next = NULL;
6642 * Add a file name to the list.
6645 addfname(const char *name)
6649 sp = stzalloc(sizeof(*sp));
6650 sp->text = ststrdup(name);
6652 exparg.lastp = &sp->next;
6655 static char *expdir;
6658 * Do metacharacter (i.e. *, ?, [...]) expansion.
6661 expmeta(char *enddir, char *name)
6676 for (p = name; *p; p++) {
6677 if (*p == '*' || *p == '?')
6679 else if (*p == '[') {
6686 if (*q == '/' || *q == '\0')
6693 } else if (*p == '\\')
6695 else if (*p == '/') {
6702 if (metaflag == 0) { /* we've reached the end of the file name */
6703 if (enddir != expdir)
6711 if (metaflag == 0 || lstat(expdir, &statb) >= 0)
6722 } while (p < start);
6724 if (enddir == expdir) {
6726 } else if (enddir == expdir + 1 && *expdir == '/') {
6735 if (enddir != expdir)
6737 if (*endname == 0) {
6749 while (!intpending && (dp = readdir(dirp)) != NULL) {
6750 if (dp->d_name[0] == '.' && !matchdot)
6752 if (pmatch(start, dp->d_name)) {
6754 strcpy(enddir, dp->d_name);
6757 for (p = enddir, cp = dp->d_name; (*p++ = *cp++) != '\0';)
6760 expmeta(p, endname);
6769 static struct strlist *
6770 msort(struct strlist *list, int len)
6772 struct strlist *p, *q = NULL;
6773 struct strlist **lpp;
6781 for (n = half; --n >= 0;) {
6785 q->next = NULL; /* terminate first half of list */
6786 q = msort(list, half); /* sort first half of list */
6787 p = msort(p, len - half); /* sort second half */
6790 #if ENABLE_LOCALE_SUPPORT
6791 if (strcoll(p->text, q->text) < 0)
6793 if (strcmp(p->text, q->text) < 0)
6817 * Sort the results of file name expansion. It calculates the number of
6818 * strings to sort and then calls msort (short for merge sort) to do the
6821 static struct strlist *
6822 expsort(struct strlist *str)
6828 for (sp = str; sp; sp = sp->next)
6830 return msort(str, len);
6834 expandmeta(struct strlist *str /*, int flag*/)
6836 static const char metachars[] ALIGN1 = {
6839 /* TODO - EXP_REDIR */
6842 struct strlist **savelastp;
6848 if (!strpbrk(str->text, metachars))
6850 savelastp = exparg.lastp;
6853 p = preglob(str->text, 0, RMESCAPE_ALLOC | RMESCAPE_HEAP);
6855 int i = strlen(str->text);
6856 expdir = ckmalloc(i < 2048 ? 2048 : i); /* XXX */
6864 if (exparg.lastp == savelastp) {
6869 *exparg.lastp = str;
6870 rmescapes(str->text);
6871 exparg.lastp = &str->next;
6873 *exparg.lastp = NULL;
6874 *savelastp = sp = expsort(*savelastp);
6875 while (sp->next != NULL)
6877 exparg.lastp = &sp->next;
6884 * Perform variable substitution and command substitution on an argument,
6885 * placing the resulting list of arguments in arglist. If EXP_FULL is true,
6886 * perform splitting and file name expansion. When arglist is NULL, perform
6887 * here document expansion.
6890 expandarg(union node *arg, struct arglist *arglist, int flag)
6895 argbackq = arg->narg.backquote;
6896 STARTSTACKSTR(expdest);
6897 ifsfirst.next = NULL;
6899 argstr(arg->narg.text, flag,
6900 /* var_str_list: */ arglist ? arglist->list : NULL);
6901 p = _STPUTC('\0', expdest);
6903 if (arglist == NULL) {
6904 return; /* here document expanded */
6906 p = grabstackstr(p);
6907 exparg.lastp = &exparg.list;
6911 if (flag & EXP_FULL) {
6912 ifsbreakup(p, &exparg);
6913 *exparg.lastp = NULL;
6914 exparg.lastp = &exparg.list;
6915 expandmeta(exparg.list /*, flag*/);
6917 if (flag & EXP_REDIR) /*XXX - for now, just remove escapes */
6919 sp = stzalloc(sizeof(*sp));
6922 exparg.lastp = &sp->next;
6926 *exparg.lastp = NULL;
6928 *arglist->lastp = exparg.list;
6929 arglist->lastp = exparg.lastp;
6934 * Expand shell variables and backquotes inside a here document.
6937 expandhere(union node *arg, int fd)
6940 expandarg(arg, (struct arglist *)NULL, 0);
6941 full_write(fd, stackblock(), expdest - (char *)stackblock());
6945 * Returns true if the pattern matches the string.
6948 patmatch(char *pattern, const char *string)
6950 return pmatch(preglob(pattern, 0, 0), string);
6954 * See if a pattern matches in a case statement.
6957 casematch(union node *pattern, char *val)
6959 struct stackmark smark;
6962 setstackmark(&smark);
6963 argbackq = pattern->narg.backquote;
6964 STARTSTACKSTR(expdest);
6966 argstr(pattern->narg.text, EXP_TILDE | EXP_CASE,
6967 /* var_str_list: */ NULL);
6968 STACKSTRNUL(expdest);
6969 result = patmatch(stackblock(), val);
6970 popstackmark(&smark);
6975 /* ============ find_command */
6979 int (*builtin)(int, char **);
6980 /* unsigned flags; */
6982 #define IS_BUILTIN_SPECIAL(b) ((b)->name[0] & 1)
6983 /* "regular" builtins always take precedence over commands,
6984 * regardless of PATH=....%builtin... position */
6985 #define IS_BUILTIN_REGULAR(b) ((b)->name[0] & 2)
6986 #define IS_BUILTIN_ASSIGN(b) ((b)->name[0] & 4)
6989 smallint cmdtype; /* CMDxxx */
6992 /* index >= 0 for commands without path (slashes) */
6993 /* (TODO: what exactly does the value mean? PATH position?) */
6994 /* index == -1 for commands with slashes */
6995 /* index == (-2 - applet_no) for NOFORK applets */
6996 const struct builtincmd *cmd;
6997 struct funcnode *func;
7000 /* values of cmdtype */
7001 #define CMDUNKNOWN -1 /* no entry in table for command */
7002 #define CMDNORMAL 0 /* command is an executable program */
7003 #define CMDFUNCTION 1 /* command is a shell function */
7004 #define CMDBUILTIN 2 /* command is a shell builtin */
7006 /* action to find_command() */
7007 #define DO_ERR 0x01 /* prints errors */
7008 #define DO_ABS 0x02 /* checks absolute paths */
7009 #define DO_NOFUNC 0x04 /* don't return shell functions, for command */
7010 #define DO_ALTPATH 0x08 /* using alternate path */
7011 #define DO_ALTBLTIN 0x20 /* %builtin in alt. path */
7013 static void find_command(char *, struct cmdentry *, int, const char *);
7016 /* ============ Hashing commands */
7019 * When commands are first encountered, they are entered in a hash table.
7020 * This ensures that a full path search will not have to be done for them
7021 * on each invocation.
7023 * We should investigate converting to a linear search, even though that
7024 * would make the command name "hash" a misnomer.
7028 struct tblentry *next; /* next entry in hash chain */
7029 union param param; /* definition of builtin function */
7030 smallint cmdtype; /* CMDxxx */
7031 char rehash; /* if set, cd done since entry created */
7032 char cmdname[1]; /* name of command */
7035 static struct tblentry **cmdtable;
7036 #define INIT_G_cmdtable() do { \
7037 cmdtable = xzalloc(CMDTABLESIZE * sizeof(cmdtable[0])); \
7040 static int builtinloc = -1; /* index in path of %builtin, or -1 */
7044 tryexec(USE_FEATURE_SH_STANDALONE(int applet_no,) char *cmd, char **argv, char **envp)
7048 #if ENABLE_FEATURE_SH_STANDALONE
7049 if (applet_no >= 0) {
7050 if (APPLET_IS_NOEXEC(applet_no)) {
7053 run_applet_no_and_exit(applet_no, argv);
7055 /* re-exec ourselves with the new arguments */
7056 execve(bb_busybox_exec_path, argv, envp);
7057 /* If they called chroot or otherwise made the binary no longer
7058 * executable, fall through */
7065 execve(cmd, argv, envp);
7066 } while (errno == EINTR);
7068 execve(cmd, argv, envp);
7074 if (errno == ENOEXEC) {
7078 for (ap = argv; *ap; ap++)
7080 ap = new = ckmalloc((ap - argv + 2) * sizeof(ap[0]));
7082 ap[0] = cmd = (char *)DEFAULT_SHELL;
7085 while ((*ap++ = *argv++) != NULL)
7094 * Exec a program. Never returns. If you change this routine, you may
7095 * have to change the find_command routine as well.
7097 static void shellexec(char **, const char *, int) NORETURN;
7099 shellexec(char **argv, const char *path, int idx)
7105 #if ENABLE_FEATURE_SH_STANDALONE
7109 clearredir(/*drop:*/ 1);
7110 envp = listvars(VEXPORT, VUNSET, 0);
7111 if (strchr(argv[0], '/') != NULL
7112 #if ENABLE_FEATURE_SH_STANDALONE
7113 || (applet_no = find_applet_by_name(argv[0])) >= 0
7116 tryexec(USE_FEATURE_SH_STANDALONE(applet_no,) argv[0], argv, envp);
7120 while ((cmdname = padvance(&path, argv[0])) != NULL) {
7121 if (--idx < 0 && pathopt == NULL) {
7122 tryexec(USE_FEATURE_SH_STANDALONE(-1,) cmdname, argv, envp);
7123 if (errno != ENOENT && errno != ENOTDIR)
7130 /* Map to POSIX errors */
7142 exitstatus = exerrno;
7143 TRACE(("shellexec failed for %s, errno %d, suppressint %d\n",
7144 argv[0], e, suppressint));
7145 ash_msg_and_raise(EXEXEC, "%s: %s", argv[0], errmsg(e, "not found"));
7150 printentry(struct tblentry *cmdp)
7156 idx = cmdp->param.index;
7159 name = padvance(&path, cmdp->cmdname);
7161 } while (--idx >= 0);
7162 out1fmt("%s%s\n", name, (cmdp->rehash ? "*" : nullstr));
7166 * Clear out command entries. The argument specifies the first entry in
7167 * PATH which has changed.
7170 clearcmdentry(int firstchange)
7172 struct tblentry **tblp;
7173 struct tblentry **pp;
7174 struct tblentry *cmdp;
7177 for (tblp = cmdtable; tblp < &cmdtable[CMDTABLESIZE]; tblp++) {
7179 while ((cmdp = *pp) != NULL) {
7180 if ((cmdp->cmdtype == CMDNORMAL &&
7181 cmdp->param.index >= firstchange)
7182 || (cmdp->cmdtype == CMDBUILTIN &&
7183 builtinloc >= firstchange)
7196 * Locate a command in the command hash table. If "add" is nonzero,
7197 * add the command to the table if it is not already present. The
7198 * variable "lastcmdentry" is set to point to the address of the link
7199 * pointing to the entry, so that delete_cmd_entry can delete the
7202 * Interrupts must be off if called with add != 0.
7204 static struct tblentry **lastcmdentry;
7206 static struct tblentry *
7207 cmdlookup(const char *name, int add)
7209 unsigned int hashval;
7211 struct tblentry *cmdp;
7212 struct tblentry **pp;
7215 hashval = (unsigned char)*p << 4;
7217 hashval += (unsigned char)*p++;
7219 pp = &cmdtable[hashval % CMDTABLESIZE];
7220 for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
7221 if (strcmp(cmdp->cmdname, name) == 0)
7225 if (add && cmdp == NULL) {
7226 cmdp = *pp = ckzalloc(sizeof(struct tblentry)
7228 /* + 1 - already done because
7229 * tblentry::cmdname is char[1] */);
7230 /*cmdp->next = NULL; - ckzalloc did it */
7231 cmdp->cmdtype = CMDUNKNOWN;
7232 strcpy(cmdp->cmdname, name);
7239 * Delete the command entry returned on the last lookup.
7242 delete_cmd_entry(void)
7244 struct tblentry *cmdp;
7247 cmdp = *lastcmdentry;
7248 *lastcmdentry = cmdp->next;
7249 if (cmdp->cmdtype == CMDFUNCTION)
7250 freefunc(cmdp->param.func);
7256 * Add a new command entry, replacing any existing command entry for
7257 * the same name - except special builtins.
7260 addcmdentry(char *name, struct cmdentry *entry)
7262 struct tblentry *cmdp;
7264 cmdp = cmdlookup(name, 1);
7265 if (cmdp->cmdtype == CMDFUNCTION) {
7266 freefunc(cmdp->param.func);
7268 cmdp->cmdtype = entry->cmdtype;
7269 cmdp->param = entry->u;
7274 hashcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
7276 struct tblentry **pp;
7277 struct tblentry *cmdp;
7279 struct cmdentry entry;
7282 if (nextopt("r") != '\0') {
7287 if (*argptr == NULL) {
7288 for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
7289 for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
7290 if (cmdp->cmdtype == CMDNORMAL)
7298 while ((name = *argptr) != NULL) {
7299 cmdp = cmdlookup(name, 0);
7301 && (cmdp->cmdtype == CMDNORMAL
7302 || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0))
7306 find_command(name, &entry, DO_ERR, pathval());
7307 if (entry.cmdtype == CMDUNKNOWN)
7315 * Called when a cd is done. Marks all commands so the next time they
7316 * are executed they will be rehashed.
7321 struct tblentry **pp;
7322 struct tblentry *cmdp;
7324 for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
7325 for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
7326 if (cmdp->cmdtype == CMDNORMAL
7327 || (cmdp->cmdtype == CMDBUILTIN
7328 && !IS_BUILTIN_REGULAR(cmdp->param.cmd)
7338 * Fix command hash table when PATH changed.
7339 * Called before PATH is changed. The argument is the new value of PATH;
7340 * pathval() still returns the old value at this point.
7341 * Called with interrupts off.
7344 changepath(const char *new)
7352 firstchange = 9999; /* assume no change */
7358 if ((*old == '\0' && *new == ':')
7359 || (*old == ':' && *new == '\0'))
7361 old = new; /* ignore subsequent differences */
7365 if (*new == '%' && idx_bltin < 0 && prefix(new + 1, "builtin"))
7371 if (builtinloc < 0 && idx_bltin >= 0)
7372 builtinloc = idx_bltin; /* zap builtins */
7373 if (builtinloc >= 0 && idx_bltin < 0)
7375 clearcmdentry(firstchange);
7376 builtinloc = idx_bltin;
7391 #define TENDBQUOTE 12
7408 typedef smallint token_id_t;
7410 /* first char is indicating which tokens mark the end of a list */
7411 static const char *const tokname_array[] = {
7425 #define KWDOFFSET 13
7426 /* the following are keywords */
7448 static char buf[16];
7451 //if (tok < TSEMI) return tokname_array[tok] + 1;
7452 //sprintf(buf, "\"%s\"", tokname_array[tok] + 1);
7457 sprintf(buf + (tok >= TSEMI), "%s%c",
7458 tokname_array[tok] + 1, (tok >= TSEMI ? '"' : 0));
7462 /* Wrapper around strcmp for qsort/bsearch/... */
7464 pstrcmp(const void *a, const void *b)
7466 return strcmp((char*) a, (*(char**) b) + 1);
7469 static const char *const *
7470 findkwd(const char *s)
7472 return bsearch(s, tokname_array + KWDOFFSET,
7473 ARRAY_SIZE(tokname_array) - KWDOFFSET,
7474 sizeof(tokname_array[0]), pstrcmp);
7478 * Locate and print what a word is...
7481 describe_command(char *command, int describe_command_verbose)
7483 struct cmdentry entry;
7484 struct tblentry *cmdp;
7485 #if ENABLE_ASH_ALIAS
7486 const struct alias *ap;
7488 const char *path = pathval();
7490 if (describe_command_verbose) {
7494 /* First look at the keywords */
7495 if (findkwd(command)) {
7496 out1str(describe_command_verbose ? " is a shell keyword" : command);
7500 #if ENABLE_ASH_ALIAS
7501 /* Then look at the aliases */
7502 ap = lookupalias(command, 0);
7504 if (!describe_command_verbose) {
7509 out1fmt(" is an alias for %s", ap->val);
7513 /* Then check if it is a tracked alias */
7514 cmdp = cmdlookup(command, 0);
7516 entry.cmdtype = cmdp->cmdtype;
7517 entry.u = cmdp->param;
7519 /* Finally use brute force */
7520 find_command(command, &entry, DO_ABS, path);
7523 switch (entry.cmdtype) {
7525 int j = entry.u.index;
7531 p = padvance(&path, command);
7535 if (describe_command_verbose) {
7537 (cmdp ? " a tracked alias for" : nullstr), p
7546 if (describe_command_verbose) {
7547 out1str(" is a shell function");
7554 if (describe_command_verbose) {
7555 out1fmt(" is a %sshell builtin",
7556 IS_BUILTIN_SPECIAL(entry.u.cmd) ?
7557 "special " : nullstr
7565 if (describe_command_verbose) {
7566 out1str(": not found\n");
7571 outstr("\n", stdout);
7576 typecmd(int argc UNUSED_PARAM, char **argv)
7582 /* type -p ... ? (we don't bother checking for 'p') */
7583 if (argv[1] && argv[1][0] == '-') {
7588 err |= describe_command(argv[i++], verbose);
7593 #if ENABLE_ASH_CMDCMD
7595 commandcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
7603 while ((c = nextopt("pvV")) != '\0')
7605 verify |= VERIFY_VERBOSE;
7607 verify |= VERIFY_BRIEF;
7612 /* Mimic bash: just "command -v" doesn't complain, it's a nop */
7613 if (verify && (*argptr != NULL)) {
7614 return describe_command(*argptr, verify - VERIFY_BRIEF);
7622 /* ============ eval.c */
7624 static int funcblocksize; /* size of structures in function */
7625 static int funcstringsize; /* size of strings in node */
7626 static void *funcblock; /* block to allocate function from */
7627 static char *funcstring; /* block to allocate strings from */
7629 /* flags in argument to evaltree */
7630 #define EV_EXIT 01 /* exit after evaluating tree */
7631 #define EV_TESTED 02 /* exit status is checked; ignore -e flag */
7632 #define EV_BACKCMD 04 /* command executing within back quotes */
7634 static const short nodesize[N_NUMBER] = {
7635 [NCMD ] = SHELL_ALIGN(sizeof(struct ncmd)),
7636 [NPIPE ] = SHELL_ALIGN(sizeof(struct npipe)),
7637 [NREDIR ] = SHELL_ALIGN(sizeof(struct nredir)),
7638 [NBACKGND ] = SHELL_ALIGN(sizeof(struct nredir)),
7639 [NSUBSHELL] = SHELL_ALIGN(sizeof(struct nredir)),
7640 [NAND ] = SHELL_ALIGN(sizeof(struct nbinary)),
7641 [NOR ] = SHELL_ALIGN(sizeof(struct nbinary)),
7642 [NSEMI ] = SHELL_ALIGN(sizeof(struct nbinary)),
7643 [NIF ] = SHELL_ALIGN(sizeof(struct nif)),
7644 [NWHILE ] = SHELL_ALIGN(sizeof(struct nbinary)),
7645 [NUNTIL ] = SHELL_ALIGN(sizeof(struct nbinary)),
7646 [NFOR ] = SHELL_ALIGN(sizeof(struct nfor)),
7647 [NCASE ] = SHELL_ALIGN(sizeof(struct ncase)),
7648 [NCLIST ] = SHELL_ALIGN(sizeof(struct nclist)),
7649 [NDEFUN ] = SHELL_ALIGN(sizeof(struct narg)),
7650 [NARG ] = SHELL_ALIGN(sizeof(struct narg)),
7651 [NTO ] = SHELL_ALIGN(sizeof(struct nfile)),
7652 #if ENABLE_ASH_BASH_COMPAT
7653 [NTO2 ] = SHELL_ALIGN(sizeof(struct nfile)),
7655 [NCLOBBER ] = SHELL_ALIGN(sizeof(struct nfile)),
7656 [NFROM ] = SHELL_ALIGN(sizeof(struct nfile)),
7657 [NFROMTO ] = SHELL_ALIGN(sizeof(struct nfile)),
7658 [NAPPEND ] = SHELL_ALIGN(sizeof(struct nfile)),
7659 [NTOFD ] = SHELL_ALIGN(sizeof(struct ndup)),
7660 [NFROMFD ] = SHELL_ALIGN(sizeof(struct ndup)),
7661 [NHERE ] = SHELL_ALIGN(sizeof(struct nhere)),
7662 [NXHERE ] = SHELL_ALIGN(sizeof(struct nhere)),
7663 [NNOT ] = SHELL_ALIGN(sizeof(struct nnot)),
7666 static void calcsize(union node *n);
7669 sizenodelist(struct nodelist *lp)
7672 funcblocksize += SHELL_ALIGN(sizeof(struct nodelist));
7679 calcsize(union node *n)
7683 funcblocksize += nodesize[n->type];
7686 calcsize(n->ncmd.redirect);
7687 calcsize(n->ncmd.args);
7688 calcsize(n->ncmd.assign);
7691 sizenodelist(n->npipe.cmdlist);
7696 calcsize(n->nredir.redirect);
7697 calcsize(n->nredir.n);
7704 calcsize(n->nbinary.ch2);
7705 calcsize(n->nbinary.ch1);
7708 calcsize(n->nif.elsepart);
7709 calcsize(n->nif.ifpart);
7710 calcsize(n->nif.test);
7713 funcstringsize += strlen(n->nfor.var) + 1;
7714 calcsize(n->nfor.body);
7715 calcsize(n->nfor.args);
7718 calcsize(n->ncase.cases);
7719 calcsize(n->ncase.expr);
7722 calcsize(n->nclist.body);
7723 calcsize(n->nclist.pattern);
7724 calcsize(n->nclist.next);
7728 sizenodelist(n->narg.backquote);
7729 funcstringsize += strlen(n->narg.text) + 1;
7730 calcsize(n->narg.next);
7733 #if ENABLE_ASH_BASH_COMPAT
7740 calcsize(n->nfile.fname);
7741 calcsize(n->nfile.next);
7745 calcsize(n->ndup.vname);
7746 calcsize(n->ndup.next);
7750 calcsize(n->nhere.doc);
7751 calcsize(n->nhere.next);
7754 calcsize(n->nnot.com);
7760 nodeckstrdup(char *s)
7762 char *rtn = funcstring;
7764 strcpy(funcstring, s);
7765 funcstring += strlen(s) + 1;
7769 static union node *copynode(union node *);
7771 static struct nodelist *
7772 copynodelist(struct nodelist *lp)
7774 struct nodelist *start;
7775 struct nodelist **lpp;
7780 funcblock = (char *) funcblock + SHELL_ALIGN(sizeof(struct nodelist));
7781 (*lpp)->n = copynode(lp->n);
7783 lpp = &(*lpp)->next;
7790 copynode(union node *n)
7797 funcblock = (char *) funcblock + nodesize[n->type];
7801 new->ncmd.redirect = copynode(n->ncmd.redirect);
7802 new->ncmd.args = copynode(n->ncmd.args);
7803 new->ncmd.assign = copynode(n->ncmd.assign);
7806 new->npipe.cmdlist = copynodelist(n->npipe.cmdlist);
7807 new->npipe.pipe_backgnd = n->npipe.pipe_backgnd;
7812 new->nredir.redirect = copynode(n->nredir.redirect);
7813 new->nredir.n = copynode(n->nredir.n);
7820 new->nbinary.ch2 = copynode(n->nbinary.ch2);
7821 new->nbinary.ch1 = copynode(n->nbinary.ch1);
7824 new->nif.elsepart = copynode(n->nif.elsepart);
7825 new->nif.ifpart = copynode(n->nif.ifpart);
7826 new->nif.test = copynode(n->nif.test);
7829 new->nfor.var = nodeckstrdup(n->nfor.var);
7830 new->nfor.body = copynode(n->nfor.body);
7831 new->nfor.args = copynode(n->nfor.args);
7834 new->ncase.cases = copynode(n->ncase.cases);
7835 new->ncase.expr = copynode(n->ncase.expr);
7838 new->nclist.body = copynode(n->nclist.body);
7839 new->nclist.pattern = copynode(n->nclist.pattern);
7840 new->nclist.next = copynode(n->nclist.next);
7844 new->narg.backquote = copynodelist(n->narg.backquote);
7845 new->narg.text = nodeckstrdup(n->narg.text);
7846 new->narg.next = copynode(n->narg.next);
7849 #if ENABLE_ASH_BASH_COMPAT
7856 new->nfile.fname = copynode(n->nfile.fname);
7857 new->nfile.fd = n->nfile.fd;
7858 new->nfile.next = copynode(n->nfile.next);
7862 new->ndup.vname = copynode(n->ndup.vname);
7863 new->ndup.dupfd = n->ndup.dupfd;
7864 new->ndup.fd = n->ndup.fd;
7865 new->ndup.next = copynode(n->ndup.next);
7869 new->nhere.doc = copynode(n->nhere.doc);
7870 new->nhere.fd = n->nhere.fd;
7871 new->nhere.next = copynode(n->nhere.next);
7874 new->nnot.com = copynode(n->nnot.com);
7877 new->type = n->type;
7882 * Make a copy of a parse tree.
7884 static struct funcnode *
7885 copyfunc(union node *n)
7890 funcblocksize = offsetof(struct funcnode, n);
7893 blocksize = funcblocksize;
7894 f = ckmalloc(blocksize + funcstringsize);
7895 funcblock = (char *) f + offsetof(struct funcnode, n);
7896 funcstring = (char *) f + blocksize;
7903 * Define a shell function.
7906 defun(char *name, union node *func)
7908 struct cmdentry entry;
7911 entry.cmdtype = CMDFUNCTION;
7912 entry.u.func = copyfunc(func);
7913 addcmdentry(name, &entry);
7917 static int evalskip; /* set if we are skipping commands */
7918 /* reasons for skipping commands (see comment on breakcmd routine) */
7919 #define SKIPBREAK (1 << 0)
7920 #define SKIPCONT (1 << 1)
7921 #define SKIPFUNC (1 << 2)
7922 #define SKIPFILE (1 << 3)
7923 #define SKIPEVAL (1 << 4)
7924 static int skipcount; /* number of levels to skip */
7925 static int funcnest; /* depth of function calls */
7926 static int loopnest; /* current loop nesting level */
7928 /* forward decl way out to parsing code - dotrap needs it */
7929 static int evalstring(char *s, int mask);
7932 * Called to execute a trap. Perhaps we should avoid entering new trap
7933 * handlers while we are executing a trap handler.
7944 savestatus = exitstatus;
7948 for (i = 1, q = gotsig; i < NSIG; i++, q++) {
7956 skip = evalstring(p, SKIPEVAL);
7957 exitstatus = savestatus;
7965 /* forward declarations - evaluation is fairly recursive business... */
7966 static void evalloop(union node *, int);
7967 static void evalfor(union node *, int);
7968 static void evalcase(union node *, int);
7969 static void evalsubshell(union node *, int);
7970 static void expredir(union node *);
7971 static void evalpipe(union node *, int);
7972 static void evalcommand(union node *, int);
7973 static int evalbltin(const struct builtincmd *, int, char **);
7974 static void prehash(union node *);
7977 * Evaluate a parse tree. The value is left in the global variable
7981 evaltree(union node *n, int flags)
7984 struct jmploc *volatile savehandler = exception_handler;
7985 struct jmploc jmploc;
7987 void (*evalfn)(union node *, int);
7991 TRACE(("evaltree(NULL) called\n"));
7994 TRACE(("pid %d, evaltree(%p: %d, %d) called\n",
7995 getpid(), n, n->type, flags));
7997 exception_handler = &jmploc;
7999 int err = setjmp(jmploc.loc);
8001 /* if it was a signal, check for trap handlers */
8002 if (exception == EXSIG)
8004 /* continue on the way out */
8005 exception_handler = savehandler;
8006 longjmp(exception_handler->loc, err);
8013 out1fmt("Node type = %d\n", n->type);
8018 evaltree(n->nnot.com, EV_TESTED);
8019 status = !exitstatus;
8022 expredir(n->nredir.redirect);
8023 status = redirectsafe(n->nredir.redirect, REDIR_PUSH);
8025 evaltree(n->nredir.n, flags & EV_TESTED);
8026 status = exitstatus;
8028 popredir(/*drop:*/ 0, /*restore:*/ 0 /* not sure */);
8031 evalfn = evalcommand;
8033 if (eflag && !(flags & EV_TESTED))
8045 evalfn = evalsubshell;
8058 #error NAND + 1 != NOR
8060 #if NOR + 1 != NSEMI
8061 #error NOR + 1 != NSEMI
8063 unsigned is_or = n->type - NAND;
8066 (flags | ((is_or >> 1) - 1)) & EV_TESTED
8068 if (!exitstatus == is_or)
8081 evaltree(n->nif.test, EV_TESTED);
8084 if (exitstatus == 0) {
8087 } else if (n->nif.elsepart) {
8088 n = n->nif.elsepart;
8093 defun(n->narg.text, n->narg.next);
8097 exitstatus = status;
8102 exception_handler = savehandler;
8104 if (checkexit & exitstatus)
8105 evalskip |= SKIPEVAL;
8106 else if (pendingsig && dotrap())
8109 if (flags & EV_EXIT) {
8111 raise_exception(EXEXIT);
8115 #if !defined(__alpha__) || (defined(__GNUC__) && __GNUC__ >= 3)
8118 void evaltreenr(union node *, int) __attribute__ ((alias("evaltree"),__noreturn__));
8121 evalloop(union node *n, int flags)
8131 evaltree(n->nbinary.ch1, EV_TESTED);
8134 if (evalskip == SKIPCONT && --skipcount <= 0) {
8138 if (evalskip == SKIPBREAK && --skipcount <= 0)
8143 if (n->type != NWHILE)
8147 evaltree(n->nbinary.ch2, flags);
8148 status = exitstatus;
8153 exitstatus = status;
8157 evalfor(union node *n, int flags)
8159 struct arglist arglist;
8162 struct stackmark smark;
8164 setstackmark(&smark);
8165 arglist.list = NULL;
8166 arglist.lastp = &arglist.list;
8167 for (argp = n->nfor.args; argp; argp = argp->narg.next) {
8168 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE | EXP_RECORD);
8173 *arglist.lastp = NULL;
8178 for (sp = arglist.list; sp; sp = sp->next) {
8179 setvar(n->nfor.var, sp->text, 0);
8180 evaltree(n->nfor.body, flags);
8182 if (evalskip == SKIPCONT && --skipcount <= 0) {
8186 if (evalskip == SKIPBREAK && --skipcount <= 0)
8193 popstackmark(&smark);
8197 evalcase(union node *n, int flags)
8201 struct arglist arglist;
8202 struct stackmark smark;
8204 setstackmark(&smark);
8205 arglist.list = NULL;
8206 arglist.lastp = &arglist.list;
8207 expandarg(n->ncase.expr, &arglist, EXP_TILDE);
8209 for (cp = n->ncase.cases; cp && evalskip == 0; cp = cp->nclist.next) {
8210 for (patp = cp->nclist.pattern; patp; patp = patp->narg.next) {
8211 if (casematch(patp, arglist.list->text)) {
8212 if (evalskip == 0) {
8213 evaltree(cp->nclist.body, flags);
8220 popstackmark(&smark);
8224 * Kick off a subshell to evaluate a tree.
8227 evalsubshell(union node *n, int flags)
8230 int backgnd = (n->type == NBACKGND);
8233 expredir(n->nredir.redirect);
8234 if (!backgnd && flags & EV_EXIT && !trap[0])
8237 jp = makejob(/*n,*/ 1);
8238 if (forkshell(jp, n, backgnd) == 0) {
8242 flags &=~ EV_TESTED;
8244 redirect(n->nredir.redirect, 0);
8245 evaltreenr(n->nredir.n, flags);
8250 status = waitforjob(jp);
8251 exitstatus = status;
8256 * Compute the names of the files in a redirection list.
8258 static void fixredir(union node *, const char *, int);
8260 expredir(union node *n)
8264 for (redir = n; redir; redir = redir->nfile.next) {
8268 fn.lastp = &fn.list;
8269 switch (redir->type) {
8273 #if ENABLE_ASH_BASH_COMPAT
8278 expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
8279 #if ENABLE_ASH_BASH_COMPAT
8282 redir->nfile.expfname = fn.list->text;
8285 case NTOFD: /* >& */
8286 if (redir->ndup.vname) {
8287 expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE);
8288 if (fn.list == NULL)
8289 ash_msg_and_raise_error("redir error");
8290 #if ENABLE_ASH_BASH_COMPAT
8291 //FIXME: we used expandarg with different args!
8292 if (!isdigit_str9(fn.list->text)) {
8293 /* >&file, not >&fd */
8294 if (redir->nfile.fd != 1) /* 123>&file - BAD */
8295 ash_msg_and_raise_error("redir error");
8297 goto store_expfname;
8300 fixredir(redir, fn.list->text, 1);
8308 * Evaluate a pipeline. All the processes in the pipeline are children
8309 * of the process creating the pipeline. (This differs from some versions
8310 * of the shell, which make the last process in a pipeline the parent
8314 evalpipe(union node *n, int flags)
8317 struct nodelist *lp;
8322 TRACE(("evalpipe(0x%lx) called\n", (long)n));
8324 for (lp = n->npipe.cmdlist; lp; lp = lp->next)
8328 jp = makejob(/*n,*/ pipelen);
8330 for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
8334 if (pipe(pip) < 0) {
8336 ash_msg_and_raise_error("pipe call failed");
8339 if (forkshell(jp, lp->n, n->npipe.pipe_backgnd) == 0) {
8352 evaltreenr(lp->n, flags);
8360 if (n->npipe.pipe_backgnd == 0) {
8361 exitstatus = waitforjob(jp);
8362 TRACE(("evalpipe: job done exit status %d\n", exitstatus));
8368 * Controls whether the shell is interactive or not.
8371 setinteractive(int on)
8373 static smallint is_interactive;
8375 if (++on == is_interactive)
8377 is_interactive = on;
8381 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
8382 if (is_interactive > 1) {
8383 /* Looks like they want an interactive shell */
8384 static smallint did_banner;
8389 "%s built-in shell (ash)\n"
8390 "Enter 'help' for a list of built-in commands."
8405 setinteractive(iflag);
8407 #if ENABLE_FEATURE_EDITING_VI
8409 line_input_state->flags |= VI_MODE;
8411 line_input_state->flags &= ~VI_MODE;
8413 viflag = 0; /* forcibly keep the option off */
8417 static struct localvar *localvars;
8420 * Called after a function returns.
8421 * Interrupts must be off.
8426 struct localvar *lvp;
8429 while ((lvp = localvars) != NULL) {
8430 localvars = lvp->next;
8432 TRACE(("poplocalvar %s", vp ? vp->text : "-"));
8433 if (vp == NULL) { /* $- saved */
8434 memcpy(optlist, lvp->text, sizeof(optlist));
8435 free((char*)lvp->text);
8437 } else if ((lvp->flags & (VUNSET|VSTRFIXED)) == VUNSET) {
8441 (*vp->func)(strchrnul(lvp->text, '=') + 1);
8442 if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
8443 free((char*)vp->text);
8444 vp->flags = lvp->flags;
8445 vp->text = lvp->text;
8452 evalfun(struct funcnode *func, int argc, char **argv, int flags)
8454 volatile struct shparam saveparam;
8455 struct localvar *volatile savelocalvars;
8456 struct jmploc *volatile savehandler;
8457 struct jmploc jmploc;
8460 saveparam = shellparam;
8461 savelocalvars = localvars;
8462 e = setjmp(jmploc.loc);
8467 savehandler = exception_handler;
8468 exception_handler = &jmploc;
8470 shellparam.malloced = 0;
8474 shellparam.nparam = argc - 1;
8475 shellparam.p = argv + 1;
8476 #if ENABLE_ASH_GETOPTS
8477 shellparam.optind = 1;
8478 shellparam.optoff = -1;
8480 evaltree(&func->n, flags & EV_TESTED);
8486 localvars = savelocalvars;
8487 freeparam(&shellparam);
8488 shellparam = saveparam;
8489 exception_handler = savehandler;
8491 evalskip &= ~SKIPFUNC;
8495 #if ENABLE_ASH_CMDCMD
8497 parse_command_args(char **argv, const char **path)
8510 if (c == '-' && !*cp) {
8517 *path = bb_default_path;
8520 /* run 'typecmd' for other options */
8531 * Make a variable a local variable. When a variable is made local, it's
8532 * value and flags are saved in a localvar structure. The saved values
8533 * will be restored when the shell function returns. We handle the name
8534 * "-" as a special case.
8539 struct localvar *lvp;
8544 lvp = ckzalloc(sizeof(struct localvar));
8545 if (LONE_DASH(name)) {
8547 p = ckmalloc(sizeof(optlist));
8548 lvp->text = memcpy(p, optlist, sizeof(optlist));
8553 vpp = hashvar(name);
8554 vp = *findvar(vpp, name);
8555 eq = strchr(name, '=');
8558 setvareq(name, VSTRFIXED);
8560 setvar(name, NULL, VSTRFIXED);
8561 vp = *vpp; /* the new variable */
8562 lvp->flags = VUNSET;
8564 lvp->text = vp->text;
8565 lvp->flags = vp->flags;
8566 vp->flags |= VSTRFIXED|VTEXTFIXED;
8572 lvp->next = localvars;
8578 * The "local" command.
8581 localcmd(int argc UNUSED_PARAM, char **argv)
8586 while ((name = *argv++) != NULL) {
8593 falsecmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
8599 truecmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
8605 execcmd(int argc UNUSED_PARAM, char **argv)
8608 iflag = 0; /* exit on error */
8611 shellexec(argv + 1, pathval(), 0);
8617 * The return command.
8620 returncmd(int argc UNUSED_PARAM, char **argv)
8623 * If called outside a function, do what ksh does;
8624 * skip the rest of the file.
8626 evalskip = funcnest ? SKIPFUNC : SKIPFILE;
8627 return argv[1] ? number(argv[1]) : exitstatus;
8630 /* Forward declarations for builtintab[] */
8631 static int breakcmd(int, char **);
8632 static int dotcmd(int, char **);
8633 static int evalcmd(int, char **);
8634 static int exitcmd(int, char **);
8635 static int exportcmd(int, char **);
8636 #if ENABLE_ASH_GETOPTS
8637 static int getoptscmd(int, char **);
8639 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
8640 static int helpcmd(int, char **);
8642 #if ENABLE_ASH_MATH_SUPPORT
8643 static int letcmd(int, char **);
8645 static int readcmd(int, char **);
8646 static int setcmd(int, char **);
8647 static int shiftcmd(int, char **);
8648 static int timescmd(int, char **);
8649 static int trapcmd(int, char **);
8650 static int umaskcmd(int, char **);
8651 static int unsetcmd(int, char **);
8652 static int ulimitcmd(int, char **);
8654 #define BUILTIN_NOSPEC "0"
8655 #define BUILTIN_SPECIAL "1"
8656 #define BUILTIN_REGULAR "2"
8657 #define BUILTIN_SPEC_REG "3"
8658 #define BUILTIN_ASSIGN "4"
8659 #define BUILTIN_SPEC_ASSG "5"
8660 #define BUILTIN_REG_ASSG "6"
8661 #define BUILTIN_SPEC_REG_ASSG "7"
8663 /* We do not handle [[ expr ]] bashism bash-compatibly,
8664 * we make it a synonym of [ expr ].
8665 * Basically, word splitting and pathname expansion should NOT be performed
8667 * no word splitting: a="a b"; [[ $a = "a b" ]]; echo $? should print "0"
8668 * no pathname expansion: [[ /bin/m* = "/bin/m*" ]]; echo $? should print "0"
8669 * Additional operators:
8670 * || and && should work as -o and -a
8672 * Apart from the above, [[ expr ]] should work as [ expr ]
8675 #define echocmd echo_main
8676 #define printfcmd printf_main
8677 #define testcmd test_main
8679 /* Keep these in proper order since it is searched via bsearch() */
8680 static const struct builtincmd builtintab[] = {
8681 { BUILTIN_SPEC_REG ".", dotcmd },
8682 { BUILTIN_SPEC_REG ":", truecmd },
8683 #if ENABLE_ASH_BUILTIN_TEST
8684 { BUILTIN_REGULAR "[", testcmd },
8685 #if ENABLE_ASH_BASH_COMPAT
8686 { BUILTIN_REGULAR "[[", testcmd },
8689 #if ENABLE_ASH_ALIAS
8690 { BUILTIN_REG_ASSG "alias", aliascmd },
8693 { BUILTIN_REGULAR "bg", fg_bgcmd },
8695 { BUILTIN_SPEC_REG "break", breakcmd },
8696 { BUILTIN_REGULAR "cd", cdcmd },
8697 { BUILTIN_NOSPEC "chdir", cdcmd },
8698 #if ENABLE_ASH_CMDCMD
8699 { BUILTIN_REGULAR "command", commandcmd },
8701 { BUILTIN_SPEC_REG "continue", breakcmd },
8702 #if ENABLE_ASH_BUILTIN_ECHO
8703 { BUILTIN_REGULAR "echo", echocmd },
8705 { BUILTIN_SPEC_REG "eval", evalcmd },
8706 { BUILTIN_SPEC_REG "exec", execcmd },
8707 { BUILTIN_SPEC_REG "exit", exitcmd },
8708 { BUILTIN_SPEC_REG_ASSG "export", exportcmd },
8709 { BUILTIN_REGULAR "false", falsecmd },
8711 { BUILTIN_REGULAR "fg", fg_bgcmd },
8713 #if ENABLE_ASH_GETOPTS
8714 { BUILTIN_REGULAR "getopts", getoptscmd },
8716 { BUILTIN_NOSPEC "hash", hashcmd },
8717 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
8718 { BUILTIN_NOSPEC "help", helpcmd },
8721 { BUILTIN_REGULAR "jobs", jobscmd },
8722 { BUILTIN_REGULAR "kill", killcmd },
8724 #if ENABLE_ASH_MATH_SUPPORT
8725 { BUILTIN_NOSPEC "let", letcmd },
8727 { BUILTIN_ASSIGN "local", localcmd },
8728 #if ENABLE_ASH_BUILTIN_PRINTF
8729 { BUILTIN_REGULAR "printf", printfcmd },
8731 { BUILTIN_NOSPEC "pwd", pwdcmd },
8732 { BUILTIN_REGULAR "read", readcmd },
8733 { BUILTIN_SPEC_REG_ASSG "readonly", exportcmd },
8734 { BUILTIN_SPEC_REG "return", returncmd },
8735 { BUILTIN_SPEC_REG "set", setcmd },
8736 { BUILTIN_SPEC_REG "shift", shiftcmd },
8737 { BUILTIN_SPEC_REG "source", dotcmd },
8738 #if ENABLE_ASH_BUILTIN_TEST
8739 { BUILTIN_REGULAR "test", testcmd },
8741 { BUILTIN_SPEC_REG "times", timescmd },
8742 { BUILTIN_SPEC_REG "trap", trapcmd },
8743 { BUILTIN_REGULAR "true", truecmd },
8744 { BUILTIN_NOSPEC "type", typecmd },
8745 { BUILTIN_NOSPEC "ulimit", ulimitcmd },
8746 { BUILTIN_REGULAR "umask", umaskcmd },
8747 #if ENABLE_ASH_ALIAS
8748 { BUILTIN_REGULAR "unalias", unaliascmd },
8750 { BUILTIN_SPEC_REG "unset", unsetcmd },
8751 { BUILTIN_REGULAR "wait", waitcmd },
8754 /* Should match the above table! */
8755 #define COMMANDCMD (builtintab + \
8757 1 * ENABLE_ASH_BUILTIN_TEST + \
8758 1 * ENABLE_ASH_BUILTIN_TEST * ENABLE_ASH_BASH_COMPAT + \
8759 1 * ENABLE_ASH_ALIAS + \
8760 1 * ENABLE_ASH_JOB_CONTROL + \
8762 #define EXECCMD (builtintab + \
8764 1 * ENABLE_ASH_BUILTIN_TEST + \
8765 1 * ENABLE_ASH_BUILTIN_TEST * ENABLE_ASH_BASH_COMPAT + \
8766 1 * ENABLE_ASH_ALIAS + \
8767 1 * ENABLE_ASH_JOB_CONTROL + \
8769 1 * ENABLE_ASH_CMDCMD + \
8771 ENABLE_ASH_BUILTIN_ECHO + \
8775 * Search the table of builtin commands.
8777 static struct builtincmd *
8778 find_builtin(const char *name)
8780 struct builtincmd *bp;
8783 name, builtintab, ARRAY_SIZE(builtintab), sizeof(builtintab[0]),
8790 * Execute a simple command.
8793 isassignment(const char *p)
8795 const char *q = endofname(p);
8801 bltincmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
8803 /* Preserve exitstatus of a previous possible redirection
8804 * as POSIX mandates */
8805 return back_exitstatus;
8808 evalcommand(union node *cmd, int flags)
8810 static const struct builtincmd null_bltin = {
8811 "\0\0", bltincmd /* why three NULs? */
8813 struct stackmark smark;
8815 struct arglist arglist;
8816 struct arglist varlist;
8819 const struct strlist *sp;
8820 struct cmdentry cmdentry;
8827 struct builtincmd *bcmd;
8828 smallint cmd_is_exec;
8829 smallint pseudovarflag = 0;
8831 /* First expand the arguments. */
8832 TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
8833 setstackmark(&smark);
8834 back_exitstatus = 0;
8836 cmdentry.cmdtype = CMDBUILTIN;
8837 cmdentry.u.cmd = &null_bltin;
8838 varlist.lastp = &varlist.list;
8839 *varlist.lastp = NULL;
8840 arglist.lastp = &arglist.list;
8841 *arglist.lastp = NULL;
8844 if (cmd->ncmd.args) {
8845 bcmd = find_builtin(cmd->ncmd.args->narg.text);
8846 pseudovarflag = bcmd && IS_BUILTIN_ASSIGN(bcmd);
8849 for (argp = cmd->ncmd.args; argp; argp = argp->narg.next) {
8850 struct strlist **spp;
8852 spp = arglist.lastp;
8853 if (pseudovarflag && isassignment(argp->narg.text))
8854 expandarg(argp, &arglist, EXP_VARTILDE);
8856 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
8858 for (sp = *spp; sp; sp = sp->next)
8862 argv = nargv = stalloc(sizeof(char *) * (argc + 1));
8863 for (sp = arglist.list; sp; sp = sp->next) {
8864 TRACE(("evalcommand arg: %s\n", sp->text));
8865 *nargv++ = sp->text;
8870 if (iflag && funcnest == 0 && argc > 0)
8871 lastarg = nargv[-1];
8874 expredir(cmd->ncmd.redirect);
8875 status = redirectsafe(cmd->ncmd.redirect, REDIR_PUSH | REDIR_SAVEFD2);
8878 for (argp = cmd->ncmd.assign; argp; argp = argp->narg.next) {
8879 struct strlist **spp;
8882 spp = varlist.lastp;
8883 expandarg(argp, &varlist, EXP_VARTILDE);
8886 * Modify the command lookup path, if a PATH= assignment
8890 if (varequal(p, path))
8894 /* Print the command if xflag is set. */
8897 const char *p = " %s";
8900 fdprintf(preverrout_fd, p, expandstr(ps4val()));
8903 for (n = 0; n < 2; n++) {
8905 fdprintf(preverrout_fd, p, sp->text);
8913 safe_write(preverrout_fd, "\n", 1);
8919 /* Now locate the command. */
8921 const char *oldpath;
8922 int cmd_flag = DO_ERR;
8927 find_command(argv[0], &cmdentry, cmd_flag, path);
8928 if (cmdentry.cmdtype == CMDUNKNOWN) {
8934 /* implement bltin and command here */
8935 if (cmdentry.cmdtype != CMDBUILTIN)
8938 spclbltin = IS_BUILTIN_SPECIAL(cmdentry.u.cmd);
8939 if (cmdentry.u.cmd == EXECCMD)
8941 #if ENABLE_ASH_CMDCMD
8942 if (cmdentry.u.cmd == COMMANDCMD) {
8944 nargv = parse_command_args(argv, &path);
8947 argc -= nargv - argv;
8949 cmd_flag |= DO_NOFUNC;
8957 /* We have a redirection error. */
8959 raise_exception(EXERROR);
8961 exitstatus = status;
8965 /* Execute the command. */
8966 switch (cmdentry.cmdtype) {
8969 #if ENABLE_FEATURE_SH_NOFORK
8970 /* Hmmm... shouldn't it happen somewhere in forkshell() instead?
8971 * Why "fork off a child process if necessary" doesn't apply to NOFORK? */
8973 /* find_command() encodes applet_no as (-2 - applet_no) */
8974 int applet_no = (- cmdentry.u.index - 2);
8975 if (applet_no >= 0 && APPLET_IS_NOFORK(applet_no)) {
8976 listsetvar(varlist.list, VEXPORT|VSTACK);
8977 /* run <applet>_main() */
8978 exitstatus = run_nofork_applet(applet_no, argv);
8983 /* Fork off a child process if necessary. */
8984 if (!(flags & EV_EXIT) || trap[0]) {
8986 jp = makejob(/*cmd,*/ 1);
8987 if (forkshell(jp, cmd, FORK_FG) != 0) {
8988 exitstatus = waitforjob(jp);
8994 listsetvar(varlist.list, VEXPORT|VSTACK);
8995 shellexec(argv, path, cmdentry.u.index);
8999 cmdenviron = varlist.list;
9001 struct strlist *list = cmdenviron;
9003 if (spclbltin > 0 || argc == 0) {
9005 if (cmd_is_exec && argc > 1)
9008 listsetvar(list, i);
9010 /* Tight loop with builtins only:
9011 * "while kill -0 $child; do true; done"
9012 * will never exit even if $child died, unless we do this
9013 * to reap the zombie and make kill detect that it's gone: */
9014 dowait(DOWAIT_NONBLOCK, NULL);
9016 if (evalbltin(cmdentry.u.cmd, argc, argv)) {
9023 exit_status = 128 + SIGINT;
9025 exit_status = 128 + pendingsig;
9026 exitstatus = exit_status;
9027 if (i == EXINT || spclbltin > 0) {
9029 longjmp(exception_handler->loc, 1);
9036 listsetvar(varlist.list, 0);
9037 /* See above for the rationale */
9038 dowait(DOWAIT_NONBLOCK, NULL);
9039 if (evalfun(cmdentry.u.func, argc, argv, flags))
9045 popredir(/*drop:*/ cmd_is_exec, /*restore:*/ cmd_is_exec);
9047 /* dsl: I think this is intended to be used to support
9048 * '_' in 'vi' command mode during line editing...
9049 * However I implemented that within libedit itself.
9051 setvar("_", lastarg, 0);
9053 popstackmark(&smark);
9057 evalbltin(const struct builtincmd *cmd, int argc, char **argv)
9059 char *volatile savecmdname;
9060 struct jmploc *volatile savehandler;
9061 struct jmploc jmploc;
9064 savecmdname = commandname;
9065 i = setjmp(jmploc.loc);
9068 savehandler = exception_handler;
9069 exception_handler = &jmploc;
9070 commandname = argv[0];
9072 optptr = NULL; /* initialize nextopt */
9073 exitstatus = (*cmd->builtin)(argc, argv);
9074 flush_stdout_stderr();
9076 exitstatus |= ferror(stdout);
9078 commandname = savecmdname;
9080 exception_handler = savehandler;
9086 goodname(const char *p)
9088 return !*endofname(p);
9093 * Search for a command. This is called before we fork so that the
9094 * location of the command will be available in the parent as well as
9095 * the child. The check for "goodname" is an overly conservative
9096 * check that the name will not be subject to expansion.
9099 prehash(union node *n)
9101 struct cmdentry entry;
9103 if (n->type == NCMD && n->ncmd.args && goodname(n->ncmd.args->narg.text))
9104 find_command(n->ncmd.args->narg.text, &entry, 0, pathval());
9108 /* ============ Builtin commands
9110 * Builtin commands whose functions are closely tied to evaluation
9111 * are implemented here.
9115 * Handle break and continue commands. Break, continue, and return are
9116 * all handled by setting the evalskip flag. The evaluation routines
9117 * above all check this flag, and if it is set they start skipping
9118 * commands rather than executing them. The variable skipcount is
9119 * the number of loops to break/continue, or the number of function
9120 * levels to return. (The latter is always 1.) It should probably
9121 * be an error to break out of more loops than exist, but it isn't
9122 * in the standard shell so we don't make it one here.
9125 breakcmd(int argc UNUSED_PARAM, char **argv)
9127 int n = argv[1] ? number(argv[1]) : 1;
9130 ash_msg_and_raise_error(illnum, argv[1]);
9134 evalskip = (**argv == 'c') ? SKIPCONT : SKIPBREAK;
9141 /* ============ input.c
9143 * This implements the input routines used by the parser.
9147 INPUT_PUSH_FILE = 1,
9148 INPUT_NOFILE_OK = 2,
9151 static smallint checkkwd;
9152 /* values of checkkwd variable */
9153 #define CHKALIAS 0x1
9158 * Push a string back onto the input at this current parsefile level.
9159 * We handle aliases this way.
9161 #if !ENABLE_ASH_ALIAS
9162 #define pushstring(s, ap) pushstring(s)
9165 pushstring(char *s, struct alias *ap)
9172 if (g_parsefile->strpush) {
9173 sp = ckzalloc(sizeof(*sp));
9174 sp->prev = g_parsefile->strpush;
9176 sp = &(g_parsefile->basestrpush);
9178 g_parsefile->strpush = sp;
9179 sp->prev_string = g_parsefile->next_to_pgetc;
9180 sp->prev_left_in_line = g_parsefile->left_in_line;
9181 #if ENABLE_ASH_ALIAS
9184 ap->flag |= ALIASINUSE;
9188 g_parsefile->next_to_pgetc = s;
9189 g_parsefile->left_in_line = len;
9196 struct strpush *sp = g_parsefile->strpush;
9199 #if ENABLE_ASH_ALIAS
9201 if (g_parsefile->next_to_pgetc[-1] == ' '
9202 || g_parsefile->next_to_pgetc[-1] == '\t'
9204 checkkwd |= CHKALIAS;
9206 if (sp->string != sp->ap->val) {
9209 sp->ap->flag &= ~ALIASINUSE;
9210 if (sp->ap->flag & ALIASDEAD) {
9211 unalias(sp->ap->name);
9215 g_parsefile->next_to_pgetc = sp->prev_string;
9216 g_parsefile->left_in_line = sp->prev_left_in_line;
9217 g_parsefile->strpush = sp->prev;
9218 if (sp != &(g_parsefile->basestrpush))
9223 //FIXME: BASH_COMPAT with "...&" does TWO pungetc():
9224 //it peeks whether it is &>, and then pushes back both chars.
9225 //This function needs to save last *next_to_pgetc to buf[0]
9226 //to make two pungetc() reliable. Currently,
9227 // pgetc (out of buf: does preadfd), pgetc, pungetc, pungetc won't work...
9232 char *buf = g_parsefile->buf;
9234 g_parsefile->next_to_pgetc = buf;
9235 #if ENABLE_FEATURE_EDITING
9237 if (!iflag || g_parsefile->fd != STDIN_FILENO)
9238 nr = nonblock_safe_read(g_parsefile->fd, buf, BUFSIZ - 1);
9240 #if ENABLE_FEATURE_TAB_COMPLETION
9241 line_input_state->path_lookup = pathval();
9243 nr = read_line_input(cmdedit_prompt, buf, BUFSIZ, line_input_state);
9245 /* Ctrl+C pressed */
9254 if (nr < 0 && errno == 0) {
9255 /* Ctrl+D pressed */
9260 nr = nonblock_safe_read(g_parsefile->fd, buf, BUFSIZ - 1);
9264 /* nonblock_safe_read() handles this problem */
9266 if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
9267 int flags = fcntl(0, F_GETFL);
9268 if (flags >= 0 && (flags & O_NONBLOCK)) {
9269 flags &= ~O_NONBLOCK;
9270 if (fcntl(0, F_SETFL, flags) >= 0) {
9271 out2str("sh: turning off NDELAY mode\n");
9282 * Refill the input buffer and return the next input character:
9284 * 1) If a string was pushed back on the input, pop it;
9285 * 2) If an EOF was pushed back (g_parsefile->left_in_line < -BIGNUM)
9286 * or we are reading from a string so we can't refill the buffer,
9288 * 3) If the is more stuff in this buffer, use it else call read to fill it.
9289 * 4) Process input up to the next newline, deleting nul characters.
9291 //#define pgetc_debug(...) bb_error_msg(__VA_ARGS__)
9292 #define pgetc_debug(...) ((void)0)
9299 while (g_parsefile->strpush) {
9300 #if ENABLE_ASH_ALIAS
9301 if (g_parsefile->left_in_line == -1
9302 && g_parsefile->strpush->ap
9303 && g_parsefile->next_to_pgetc[-1] != ' '
9304 && g_parsefile->next_to_pgetc[-1] != '\t'
9306 pgetc_debug("preadbuffer PEOA");
9311 /* try "pgetc" now: */
9312 pgetc_debug("preadbuffer internal pgetc at %d:%p'%s'",
9313 g_parsefile->left_in_line,
9314 g_parsefile->next_to_pgetc,
9315 g_parsefile->next_to_pgetc);
9316 if (--g_parsefile->left_in_line >= 0)
9317 return (unsigned char)(*g_parsefile->next_to_pgetc++);
9319 /* on both branches above g_parsefile->left_in_line < 0.
9320 * "pgetc" needs refilling.
9323 /* -90 is our -BIGNUM. Below we use -99 to mark "EOF on read",
9324 * pungetc() may increment it a few times.
9325 * Assuming it won't increment it to less than -90.
9327 if (g_parsefile->left_in_line < -90 || g_parsefile->buf == NULL) {
9328 pgetc_debug("preadbuffer PEOF1");
9329 /* even in failure keep left_in_line and next_to_pgetc
9330 * in lock step, for correct multi-layer pungetc.
9331 * left_in_line was decremented before preadbuffer(),
9332 * must inc next_to_pgetc: */
9333 g_parsefile->next_to_pgetc++;
9337 more = g_parsefile->left_in_buffer;
9339 flush_stdout_stderr();
9343 /* don't try reading again */
9344 g_parsefile->left_in_line = -99;
9345 pgetc_debug("preadbuffer PEOF2");
9346 g_parsefile->next_to_pgetc++;
9351 /* Find out where's the end of line.
9352 * Set g_parsefile->left_in_line
9353 * and g_parsefile->left_in_buffer acordingly.
9354 * NUL chars are deleted.
9356 q = g_parsefile->next_to_pgetc;
9364 memmove(q, q + 1, more);
9368 g_parsefile->left_in_line = q - g_parsefile->next_to_pgetc - 1;
9374 g_parsefile->left_in_line = q - g_parsefile->next_to_pgetc - 1;
9375 if (g_parsefile->left_in_line < 0)
9380 g_parsefile->left_in_buffer = more;
9385 out2str(g_parsefile->next_to_pgetc);
9389 pgetc_debug("preadbuffer at %d:%p'%s'",
9390 g_parsefile->left_in_line,
9391 g_parsefile->next_to_pgetc,
9392 g_parsefile->next_to_pgetc);
9393 return (unsigned char)(*g_parsefile->next_to_pgetc++);
9396 #define pgetc_as_macro() \
9397 (--g_parsefile->left_in_line >= 0 \
9398 ? (unsigned char)(*g_parsefile->next_to_pgetc++) \
9405 pgetc_debug("pgetc_fast at %d:%p'%s'",
9406 g_parsefile->left_in_line,
9407 g_parsefile->next_to_pgetc,
9408 g_parsefile->next_to_pgetc);
9409 return pgetc_as_macro();
9412 #if ENABLE_ASH_OPTIMIZE_FOR_SIZE
9413 #define pgetc_fast() pgetc()
9415 #define pgetc_fast() pgetc_as_macro()
9419 * Same as pgetc(), but ignores PEOA.
9421 #if ENABLE_ASH_ALIAS
9427 pgetc_debug("pgetc_fast at %d:%p'%s'",
9428 g_parsefile->left_in_line,
9429 g_parsefile->next_to_pgetc,
9430 g_parsefile->next_to_pgetc);
9432 } while (c == PEOA);
9436 #define pgetc2() pgetc()
9440 * Read a line from the script.
9443 pfgets(char *line, int len)
9449 while (--nleft > 0) {
9465 * Undo the last call to pgetc. Only one character may be pushed back.
9466 * PEOF may be pushed back.
9471 g_parsefile->left_in_line++;
9472 g_parsefile->next_to_pgetc--;
9473 pgetc_debug("pushed back to %d:%p'%s'",
9474 g_parsefile->left_in_line,
9475 g_parsefile->next_to_pgetc,
9476 g_parsefile->next_to_pgetc);
9480 * To handle the "." command, a stack of input files is used. Pushfile
9481 * adds a new entry to the stack and popfile restores the previous level.
9486 struct parsefile *pf;
9488 pf = ckzalloc(sizeof(*pf));
9489 pf->prev = g_parsefile;
9491 /*pf->strpush = NULL; - ckzalloc did it */
9492 /*pf->basestrpush.prev = NULL;*/
9499 struct parsefile *pf = g_parsefile;
9507 g_parsefile = pf->prev;
9513 * Return to top level.
9518 while (g_parsefile != &basepf)
9523 * Close the file(s) that the shell is reading commands from. Called
9524 * after a fork is done.
9530 if (g_parsefile->fd > 0) {
9531 close(g_parsefile->fd);
9532 g_parsefile->fd = 0;
9537 * Like setinputfile, but takes an open file descriptor. Call this with
9541 setinputfd(int fd, int push)
9543 close_on_exec_on(fd);
9546 g_parsefile->buf = NULL;
9548 g_parsefile->fd = fd;
9549 if (g_parsefile->buf == NULL)
9550 g_parsefile->buf = ckmalloc(IBUFSIZ);
9551 g_parsefile->left_in_buffer = 0;
9552 g_parsefile->left_in_line = 0;
9553 g_parsefile->linno = 1;
9557 * Set the input to take input from a file. If push is set, push the
9558 * old input onto the stack first.
9561 setinputfile(const char *fname, int flags)
9567 fd = open(fname, O_RDONLY);
9569 if (flags & INPUT_NOFILE_OK)
9571 ash_msg_and_raise_error("can't open %s", fname);
9574 fd2 = copyfd(fd, 10);
9577 ash_msg_and_raise_error("out of file descriptors");
9580 setinputfd(fd, flags & INPUT_PUSH_FILE);
9587 * Like setinputfile, but takes input from a string.
9590 setinputstring(char *string)
9594 g_parsefile->next_to_pgetc = string;
9595 g_parsefile->left_in_line = strlen(string);
9596 g_parsefile->buf = NULL;
9597 g_parsefile->linno = 1;
9602 /* ============ mail.c
9604 * Routines to check for mail.
9609 #define MAXMBOXES 10
9611 /* times of mailboxes */
9612 static time_t mailtime[MAXMBOXES];
9613 /* Set if MAIL or MAILPATH is changed. */
9614 static smallint mail_var_path_changed;
9617 * Print appropriate message(s) if mail has arrived.
9618 * If mail_var_path_changed is set,
9619 * then the value of MAIL has mail_var_path_changed,
9620 * so we just update the values.
9629 struct stackmark smark;
9632 setstackmark(&smark);
9633 mpath = mpathset() ? mpathval() : mailval();
9634 for (mtp = mailtime; mtp < mailtime + MAXMBOXES; mtp++) {
9635 p = padvance(&mpath, nullstr);
9640 for (q = p; *q; q++)
9646 q[-1] = '\0'; /* delete trailing '/' */
9647 if (stat(p, &statb) < 0) {
9651 if (!mail_var_path_changed && statb.st_mtime != *mtp) {
9654 pathopt ? pathopt : "you have mail"
9657 *mtp = statb.st_mtime;
9659 mail_var_path_changed = 0;
9660 popstackmark(&smark);
9664 changemail(const char *val UNUSED_PARAM)
9666 mail_var_path_changed = 1;
9669 #endif /* ASH_MAIL */
9672 /* ============ ??? */
9675 * Set the shell parameters.
9678 setparam(char **argv)
9684 for (nparam = 0; argv[nparam]; nparam++)
9686 ap = newparam = ckmalloc((nparam + 1) * sizeof(*ap));
9688 *ap++ = ckstrdup(*argv++);
9691 freeparam(&shellparam);
9692 shellparam.malloced = 1;
9693 shellparam.nparam = nparam;
9694 shellparam.p = newparam;
9695 #if ENABLE_ASH_GETOPTS
9696 shellparam.optind = 1;
9697 shellparam.optoff = -1;
9702 * Process shell options. The global variable argptr contains a pointer
9703 * to the argument list; we advance it past the options.
9705 * SUSv3 section 2.8.1 "Consequences of Shell Errors" says:
9706 * For a non-interactive shell, an error condition encountered
9707 * by a special built-in ... shall cause the shell to write a diagnostic message
9708 * to standard error and exit as shown in the following table:
9709 * Error Special Built-In
9711 * Utility syntax error (option or operand error) Shall exit
9713 * However, in bug 1142 (http://busybox.net/bugs/view.php?id=1142)
9714 * we see that bash does not do that (set "finishes" with error code 1 instead,
9715 * and shell continues), and people rely on this behavior!
9717 * set -o barfoo 2>/dev/null
9720 * Oh well. Let's mimic that.
9723 plus_minus_o(char *name, int val)
9728 for (i = 0; i < NOPTS; i++) {
9729 if (strcmp(name, optnames(i)) == 0) {
9734 ash_msg("illegal option %co %s", val ? '-' : '+', name);
9737 for (i = 0; i < NOPTS; i++) {
9739 out1fmt("%-16s%s\n", optnames(i), optlist[i] ? "on" : "off");
9741 out1fmt("set %co %s\n", optlist[i] ? '-' : '+', optnames(i));
9747 setoption(int flag, int val)
9751 for (i = 0; i < NOPTS; i++) {
9752 if (optletters(i) == flag) {
9757 ash_msg_and_raise_error("illegal option %c%c", val ? '-' : '+', flag);
9761 options(int cmdline)
9769 while ((p = *argptr) != NULL) {
9771 if (c != '-' && c != '+')
9774 val = 0; /* val = 0 if c == '+' */
9777 if (p[0] == '\0' || LONE_DASH(p)) {
9779 /* "-" means turn off -x and -v */
9782 /* "--" means reset params */
9783 else if (*argptr == NULL)
9786 break; /* "-" or "--" terminates options */
9789 /* first char was + or - */
9790 while ((c = *p++) != '\0') {
9791 /* bash 3.2 indeed handles -c CMD and +c CMD the same */
9792 if (c == 'c' && cmdline) {
9793 minusc = p; /* command is after shell args */
9794 } else if (c == 'o') {
9795 if (plus_minus_o(*argptr, val)) {
9796 /* it already printed err message */
9797 return 1; /* error */
9801 } else if (cmdline && (c == 'l')) { /* -l or +l == --login */
9803 /* bash does not accept +-login, we also won't */
9804 } else if (cmdline && val && (c == '-')) { /* long options */
9805 if (strcmp(p, "login") == 0)
9817 * The shift builtin command.
9820 shiftcmd(int argc UNUSED_PARAM, char **argv)
9827 n = number(argv[1]);
9828 if (n > shellparam.nparam)
9829 n = 0; /* bash compat, was = shellparam.nparam; */
9831 shellparam.nparam -= n;
9832 for (ap1 = shellparam.p; --n >= 0; ap1++) {
9833 if (shellparam.malloced)
9837 while ((*ap2++ = *ap1++) != NULL)
9839 #if ENABLE_ASH_GETOPTS
9840 shellparam.optind = 1;
9841 shellparam.optoff = -1;
9848 * POSIX requires that 'set' (but not export or readonly) output the
9849 * variables in lexicographic order - by the locale's collating order (sigh).
9850 * Maybe we could keep them in an ordered balanced binary tree
9851 * instead of hashed lists.
9852 * For now just roll 'em through qsort for printing...
9855 showvars(const char *sep_prefix, int on, int off)
9860 ep = listvars(on, off, &epend);
9861 qsort(ep, epend - ep, sizeof(char *), vpcmp);
9863 sep = *sep_prefix ? " " : sep_prefix;
9865 for (; ep < epend; ep++) {
9869 p = strchrnul(*ep, '=');
9872 q = single_quote(++p);
9873 out1fmt("%s%s%.*s%s\n", sep_prefix, sep, (int)(p - *ep), *ep, q);
9879 * The set command builtin.
9882 setcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9887 return showvars(nullstr, 0, VUNSET);
9890 if (!options(0)) { /* if no parse error... */
9893 if (*argptr != NULL) {
9901 #if ENABLE_ASH_RANDOM_SUPPORT
9903 change_random(const char *value)
9905 /* Galois LFSR parameter */
9906 /* Taps at 32 31 29 1: */
9907 enum { MASK = 0x8000000b };
9908 /* Another example - taps at 32 31 30 10: */
9909 /* MASK = 0x00400007 */
9911 if (value == NULL) {
9912 /* "get", generate */
9915 /* LCG has period of 2^32 and alternating lowest bit */
9916 random_LCG = 1664525 * random_LCG + 1013904223;
9917 /* Galois LFSR has period of 2^32-1 = 3 * 5 * 17 * 257 * 65537 */
9918 t = (random_galois_LFSR << 1);
9919 if (random_galois_LFSR < 0) /* if we just shifted 1 out of msb... */
9921 random_galois_LFSR = t;
9922 /* Both are weak, combining them gives better randomness
9923 * and ~2^64 period. & 0x7fff is probably bash compat
9924 * for $RANDOM range. Combining with subtraction is
9925 * just for fun. + and ^ would work equally well. */
9926 t = (t - random_LCG) & 0x7fff;
9927 /* set without recursion */
9928 setvar(vrandom.text, utoa(t), VNOFUNC);
9929 vrandom.flags &= ~VNOFUNC;
9932 random_galois_LFSR = random_LCG = strtoul(value, (char **)NULL, 10);
9937 #if ENABLE_ASH_GETOPTS
9939 getopts(char *optstr, char *optvar, char **optfirst, int *param_optind, int *optoff)
9948 if (*param_optind < 1)
9950 optnext = optfirst + *param_optind - 1;
9952 if (*param_optind <= 1 || *optoff < 0 || (int)strlen(optnext[-1]) < *optoff)
9955 p = optnext[-1] + *optoff;
9956 if (p == NULL || *p == '\0') {
9957 /* Current word is done, advance */
9959 if (p == NULL || *p != '-' || *++p == '\0') {
9966 if (LONE_DASH(p)) /* check for "--" */
9971 for (q = optstr; *q != c;) {
9973 if (optstr[0] == ':') {
9976 err |= setvarsafe("OPTARG", s, 0);
9978 fprintf(stderr, "Illegal option -%c\n", c);
9989 if (*p == '\0' && (p = *optnext) == NULL) {
9990 if (optstr[0] == ':') {
9993 err |= setvarsafe("OPTARG", s, 0);
9996 fprintf(stderr, "No arg for -%c option\n", c);
10005 err |= setvarsafe("OPTARG", p, 0);
10008 err |= setvarsafe("OPTARG", nullstr, 0);
10010 *optoff = p ? p - *(optnext - 1) : -1;
10011 *param_optind = optnext - optfirst + 1;
10012 fmtstr(s, sizeof(s), "%d", *param_optind);
10013 err |= setvarsafe("OPTIND", s, VNOFUNC);
10016 err |= setvarsafe(optvar, s, 0);
10020 flush_stdout_stderr();
10021 raise_exception(EXERROR);
10027 * The getopts builtin. Shellparam.optnext points to the next argument
10028 * to be processed. Shellparam.optptr points to the next character to
10029 * be processed in the current argument. If shellparam.optnext is NULL,
10030 * then it's the first time getopts has been called.
10033 getoptscmd(int argc, char **argv)
10038 ash_msg_and_raise_error("usage: getopts optstring var [arg]");
10040 optbase = shellparam.p;
10041 if (shellparam.optind > shellparam.nparam + 1) {
10042 shellparam.optind = 1;
10043 shellparam.optoff = -1;
10046 optbase = &argv[3];
10047 if (shellparam.optind > argc - 2) {
10048 shellparam.optind = 1;
10049 shellparam.optoff = -1;
10053 return getopts(argv[1], argv[2], optbase, &shellparam.optind,
10054 &shellparam.optoff);
10056 #endif /* ASH_GETOPTS */
10059 /* ============ Shell parser */
10062 struct heredoc *next; /* next here document in list */
10063 union node *here; /* redirection node */
10064 char *eofmark; /* string indicating end of input */
10065 smallint striptabs; /* if set, strip leading tabs */
10068 static smallint tokpushback; /* last token pushed back */
10069 static smallint parsebackquote; /* nonzero if we are inside backquotes */
10070 static smallint quoteflag; /* set if (part of) last token was quoted */
10071 static token_id_t lasttoken; /* last token read (integer id Txxx) */
10072 static struct heredoc *heredoclist; /* list of here documents to read */
10073 static char *wordtext; /* text of last word returned by readtoken */
10074 static struct nodelist *backquotelist;
10075 static union node *redirnode;
10076 static struct heredoc *heredoc;
10078 * NEOF is returned by parsecmd when it encounters an end of file. It
10079 * must be distinct from NULL, so we use the address of a variable that
10080 * happens to be handy.
10082 #define NEOF ((union node *)&tokpushback)
10084 static void raise_error_syntax(const char *) NORETURN;
10086 raise_error_syntax(const char *msg)
10088 ash_msg_and_raise_error("syntax error: %s", msg);
10093 * Called when an unexpected token is read during the parse. The argument
10094 * is the token that is expected, or -1 if more than one type of token can
10095 * occur at this point.
10097 static void raise_error_unexpected_syntax(int) NORETURN;
10099 raise_error_unexpected_syntax(int token)
10104 l = sprintf(msg, "unexpected %s", tokname(lasttoken));
10106 sprintf(msg + l, " (expecting %s)", tokname(token));
10107 raise_error_syntax(msg);
10111 #define EOFMARKLEN 79
10113 /* parsing is heavily cross-recursive, need these forward decls */
10114 static union node *andor(void);
10115 static union node *pipeline(void);
10116 static union node *parse_command(void);
10117 static void parseheredoc(void);
10118 static char peektoken(void);
10119 static int readtoken(void);
10121 static union node *
10124 union node *n1, *n2, *n3;
10127 checkkwd = CHKNL | CHKKWD | CHKALIAS;
10128 if (nlflag == 2 && peektoken())
10134 if (tok == TBACKGND) {
10135 if (n2->type == NPIPE) {
10136 n2->npipe.pipe_backgnd = 1;
10138 if (n2->type != NREDIR) {
10139 n3 = stzalloc(sizeof(struct nredir));
10141 /*n3->nredir.redirect = NULL; - stzalloc did it */
10144 n2->type = NBACKGND;
10150 n3 = stzalloc(sizeof(struct nbinary));
10152 n3->nbinary.ch1 = n1;
10153 n3->nbinary.ch2 = n2;
10169 checkkwd = CHKNL | CHKKWD | CHKALIAS;
10177 pungetc(); /* push back EOF on input */
10181 raise_error_unexpected_syntax(-1);
10188 static union node *
10191 union node *n1, *n2, *n3;
10199 } else if (t == TOR) {
10205 checkkwd = CHKNL | CHKKWD | CHKALIAS;
10207 n3 = stzalloc(sizeof(struct nbinary));
10209 n3->nbinary.ch1 = n1;
10210 n3->nbinary.ch2 = n2;
10215 static union node *
10218 union node *n1, *n2, *pipenode;
10219 struct nodelist *lp, *prev;
10223 TRACE(("pipeline: entered\n"));
10224 if (readtoken() == TNOT) {
10226 checkkwd = CHKKWD | CHKALIAS;
10229 n1 = parse_command();
10230 if (readtoken() == TPIPE) {
10231 pipenode = stzalloc(sizeof(struct npipe));
10232 pipenode->type = NPIPE;
10233 /*pipenode->npipe.pipe_backgnd = 0; - stzalloc did it */
10234 lp = stzalloc(sizeof(struct nodelist));
10235 pipenode->npipe.cmdlist = lp;
10239 lp = stzalloc(sizeof(struct nodelist));
10240 checkkwd = CHKNL | CHKKWD | CHKALIAS;
10241 lp->n = parse_command();
10243 } while (readtoken() == TPIPE);
10249 n2 = stzalloc(sizeof(struct nnot));
10257 static union node *
10262 n = stzalloc(sizeof(struct narg));
10264 /*n->narg.next = NULL; - stzalloc did it */
10265 n->narg.text = wordtext;
10266 n->narg.backquote = backquotelist;
10271 fixredir(union node *n, const char *text, int err)
10275 TRACE(("Fix redir %s %d\n", text, err));
10277 n->ndup.vname = NULL;
10279 fd = bb_strtou(text, NULL, 10);
10280 if (!errno && fd >= 0)
10281 n->ndup.dupfd = fd;
10282 else if (LONE_DASH(text))
10283 n->ndup.dupfd = -1;
10286 raise_error_syntax("bad fd number");
10287 n->ndup.vname = makename();
10292 * Returns true if the text contains nothing to expand (no dollar signs
10296 noexpand(char *text)
10302 while ((c = *p++) != '\0') {
10303 if (c == CTLQUOTEMARK)
10307 else if (SIT(c, BASESYNTAX) == CCTL)
10316 union node *n = redirnode;
10318 if (readtoken() != TWORD)
10319 raise_error_unexpected_syntax(-1);
10320 if (n->type == NHERE) {
10321 struct heredoc *here = heredoc;
10325 if (quoteflag == 0)
10327 TRACE(("Here document %d\n", n->type));
10328 if (!noexpand(wordtext) || (i = strlen(wordtext)) == 0 || i > EOFMARKLEN)
10329 raise_error_syntax("illegal eof marker for << redirection");
10330 rmescapes(wordtext);
10331 here->eofmark = wordtext;
10333 if (heredoclist == NULL)
10334 heredoclist = here;
10336 for (p = heredoclist; p->next; p = p->next)
10340 } else if (n->type == NTOFD || n->type == NFROMFD) {
10341 fixredir(n, wordtext, 0);
10343 n->nfile.fname = makename();
10347 static union node *
10350 union node *args, **app;
10351 union node *n = NULL;
10352 union node *vars, **vpp;
10353 union node **rpp, *redir;
10355 #if ENABLE_ASH_BASH_COMPAT
10356 smallint double_brackets_flag = 0;
10366 savecheckkwd = CHKALIAS;
10369 checkkwd = savecheckkwd;
10372 #if ENABLE_ASH_BASH_COMPAT
10373 case TAND: /* "&&" */
10374 case TOR: /* "||" */
10375 if (!double_brackets_flag) {
10379 wordtext = (char *) (t == TAND ? "-a" : "-o");
10382 n = stzalloc(sizeof(struct narg));
10384 /*n->narg.next = NULL; - stzalloc did it */
10385 n->narg.text = wordtext;
10386 #if ENABLE_ASH_BASH_COMPAT
10387 if (strcmp("[[", wordtext) == 0)
10388 double_brackets_flag = 1;
10389 else if (strcmp("]]", wordtext) == 0)
10390 double_brackets_flag = 0;
10392 n->narg.backquote = backquotelist;
10393 if (savecheckkwd && isassignment(wordtext)) {
10395 vpp = &n->narg.next;
10398 app = &n->narg.next;
10403 *rpp = n = redirnode;
10404 rpp = &n->nfile.next;
10405 parsefname(); /* read name of redirection file */
10408 if (args && app == &args->narg.next
10411 struct builtincmd *bcmd;
10414 /* We have a function */
10415 if (readtoken() != TRP)
10416 raise_error_unexpected_syntax(TRP);
10417 name = n->narg.text;
10418 if (!goodname(name)
10419 || ((bcmd = find_builtin(name)) && IS_BUILTIN_SPECIAL(bcmd))
10421 raise_error_syntax("bad function name");
10424 checkkwd = CHKNL | CHKKWD | CHKALIAS;
10425 n->narg.next = parse_command();
10438 n = stzalloc(sizeof(struct ncmd));
10440 n->ncmd.args = args;
10441 n->ncmd.assign = vars;
10442 n->ncmd.redirect = redir;
10446 static union node *
10447 parse_command(void)
10449 union node *n1, *n2;
10450 union node *ap, **app;
10451 union node *cp, **cpp;
10452 union node *redir, **rpp;
10459 switch (readtoken()) {
10461 raise_error_unexpected_syntax(-1);
10464 n1 = stzalloc(sizeof(struct nif));
10466 n1->nif.test = list(0);
10467 if (readtoken() != TTHEN)
10468 raise_error_unexpected_syntax(TTHEN);
10469 n1->nif.ifpart = list(0);
10471 while (readtoken() == TELIF) {
10472 n2->nif.elsepart = stzalloc(sizeof(struct nif));
10473 n2 = n2->nif.elsepart;
10475 n2->nif.test = list(0);
10476 if (readtoken() != TTHEN)
10477 raise_error_unexpected_syntax(TTHEN);
10478 n2->nif.ifpart = list(0);
10480 if (lasttoken == TELSE)
10481 n2->nif.elsepart = list(0);
10483 n2->nif.elsepart = NULL;
10491 n1 = stzalloc(sizeof(struct nbinary));
10492 n1->type = (lasttoken == TWHILE) ? NWHILE : NUNTIL;
10493 n1->nbinary.ch1 = list(0);
10496 TRACE(("expecting DO got %s %s\n", tokname(got),
10497 got == TWORD ? wordtext : ""));
10498 raise_error_unexpected_syntax(TDO);
10500 n1->nbinary.ch2 = list(0);
10505 if (readtoken() != TWORD || quoteflag || !goodname(wordtext))
10506 raise_error_syntax("bad for loop variable");
10507 n1 = stzalloc(sizeof(struct nfor));
10509 n1->nfor.var = wordtext;
10510 checkkwd = CHKKWD | CHKALIAS;
10511 if (readtoken() == TIN) {
10513 while (readtoken() == TWORD) {
10514 n2 = stzalloc(sizeof(struct narg));
10516 /*n2->narg.next = NULL; - stzalloc did it */
10517 n2->narg.text = wordtext;
10518 n2->narg.backquote = backquotelist;
10520 app = &n2->narg.next;
10523 n1->nfor.args = ap;
10524 if (lasttoken != TNL && lasttoken != TSEMI)
10525 raise_error_unexpected_syntax(-1);
10527 n2 = stzalloc(sizeof(struct narg));
10529 /*n2->narg.next = NULL; - stzalloc did it */
10530 n2->narg.text = (char *)dolatstr;
10531 /*n2->narg.backquote = NULL;*/
10532 n1->nfor.args = n2;
10534 * Newline or semicolon here is optional (but note
10535 * that the original Bourne shell only allowed NL).
10537 if (lasttoken != TNL && lasttoken != TSEMI)
10540 checkkwd = CHKNL | CHKKWD | CHKALIAS;
10541 if (readtoken() != TDO)
10542 raise_error_unexpected_syntax(TDO);
10543 n1->nfor.body = list(0);
10547 n1 = stzalloc(sizeof(struct ncase));
10549 if (readtoken() != TWORD)
10550 raise_error_unexpected_syntax(TWORD);
10551 n1->ncase.expr = n2 = stzalloc(sizeof(struct narg));
10553 /*n2->narg.next = NULL; - stzalloc did it */
10554 n2->narg.text = wordtext;
10555 n2->narg.backquote = backquotelist;
10557 checkkwd = CHKKWD | CHKALIAS;
10558 } while (readtoken() == TNL);
10559 if (lasttoken != TIN)
10560 raise_error_unexpected_syntax(TIN);
10561 cpp = &n1->ncase.cases;
10563 checkkwd = CHKNL | CHKKWD;
10565 while (t != TESAC) {
10566 if (lasttoken == TLP)
10568 *cpp = cp = stzalloc(sizeof(struct nclist));
10570 app = &cp->nclist.pattern;
10572 *app = ap = stzalloc(sizeof(struct narg));
10574 /*ap->narg.next = NULL; - stzalloc did it */
10575 ap->narg.text = wordtext;
10576 ap->narg.backquote = backquotelist;
10577 if (readtoken() != TPIPE)
10579 app = &ap->narg.next;
10582 //ap->narg.next = NULL;
10583 if (lasttoken != TRP)
10584 raise_error_unexpected_syntax(TRP);
10585 cp->nclist.body = list(2);
10587 cpp = &cp->nclist.next;
10589 checkkwd = CHKNL | CHKKWD;
10593 raise_error_unexpected_syntax(TENDCASE);
10600 n1 = stzalloc(sizeof(struct nredir));
10601 n1->type = NSUBSHELL;
10602 n1->nredir.n = list(0);
10603 /*n1->nredir.redirect = NULL; - stzalloc did it */
10613 return simplecmd();
10616 if (readtoken() != t)
10617 raise_error_unexpected_syntax(t);
10620 /* Now check for redirection which may follow command */
10621 checkkwd = CHKKWD | CHKALIAS;
10623 while (readtoken() == TREDIR) {
10624 *rpp = n2 = redirnode;
10625 rpp = &n2->nfile.next;
10631 if (n1->type != NSUBSHELL) {
10632 n2 = stzalloc(sizeof(struct nredir));
10637 n1->nredir.redirect = redir;
10642 #if ENABLE_ASH_BASH_COMPAT
10643 static int decode_dollar_squote(void)
10645 static const char C_escapes[] ALIGN1 = "nrbtfav""x\\01234567";
10651 p = strchr(C_escapes, c);
10656 if ((unsigned char)(c - '0') <= 7) { /* \ooo */
10660 } while ((unsigned char)(c - '0') <= 7 && --cnt);
10662 } else if (c == 'x') { /* \xHH */
10666 } while (isxdigit(c) && --cnt);
10668 if (cnt == 3) { /* \x but next char is "bad" */
10672 } else { /* simple seq like \\ or \t */
10677 c = bb_process_escape_sequence((void*)&p);
10678 } else { /* unrecognized "\z": print both chars unless ' or " */
10679 if (c != '\'' && c != '"') {
10681 c |= 0x100; /* "please encode \, then me" */
10689 * If eofmark is NULL, read a word or a redirection symbol. If eofmark
10690 * is not NULL, read a here document. In the latter case, eofmark is the
10691 * word which marks the end of the document and striptabs is true if
10692 * leading tabs should be stripped from the document. The argument firstc
10693 * is the first character of the input token or document.
10695 * Because C does not have internal subroutines, I have simulated them
10696 * using goto's to implement the subroutine linkage. The following macros
10697 * will run code that appears at the end of readtoken1.
10699 #define CHECKEND() {goto checkend; checkend_return:;}
10700 #define PARSEREDIR() {goto parseredir; parseredir_return:;}
10701 #define PARSESUB() {goto parsesub; parsesub_return:;}
10702 #define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
10703 #define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
10704 #define PARSEARITH() {goto parsearith; parsearith_return:;}
10706 readtoken1(int firstc, int syntax, char *eofmark, int striptabs)
10708 /* NB: syntax parameter fits into smallint */
10712 char line[EOFMARKLEN + 1];
10713 struct nodelist *bqlist;
10717 smallint prevsyntax; /* syntax before arithmetic */
10718 #if ENABLE_ASH_EXPAND_PRMT
10719 smallint pssyntax; /* we are expanding a prompt string */
10721 int varnest; /* levels of variables expansion */
10722 int arinest; /* levels of arithmetic expansion */
10723 int parenlevel; /* levels of parens in arithmetic */
10724 int dqvarnest; /* levels of variables expansion within double quotes */
10726 USE_ASH_BASH_COMPAT(smallint bash_dollar_squote = 0;)
10729 /* Avoid longjmp clobbering */
10735 (void) &parenlevel;
10738 (void) &prevsyntax;
10741 startlinno = g_parsefile->linno;
10746 #if ENABLE_ASH_EXPAND_PRMT
10747 pssyntax = (syntax == PSSYNTAX);
10751 dblquote = (syntax == DQSYNTAX);
10757 STARTSTACKSTR(out);
10759 /* For each line, until end of word */
10761 CHECKEND(); /* set c to PEOF if at end of here document */
10762 for (;;) { /* until end of line or end of word */
10763 CHECKSTRSPACE(4, out); /* permit 4 calls to USTPUTC */
10764 switch (SIT(c, syntax)) {
10765 case CNL: /* '\n' */
10766 if (syntax == BASESYNTAX)
10767 goto endword; /* exit outer loop */
10769 g_parsefile->linno++;
10773 goto loop; /* continue outer loop */
10778 if (eofmark == NULL || dblquote)
10779 USTPUTC(CTLESC, out);
10780 #if ENABLE_ASH_BASH_COMPAT
10781 if (c == '\\' && bash_dollar_squote) {
10782 c = decode_dollar_squote();
10784 USTPUTC('\\', out);
10785 c = (unsigned char)c;
10791 case CBACK: /* backslash */
10794 USTPUTC(CTLESC, out);
10795 USTPUTC('\\', out);
10797 } else if (c == '\n') {
10801 #if ENABLE_ASH_EXPAND_PRMT
10802 if (c == '$' && pssyntax) {
10803 USTPUTC(CTLESC, out);
10804 USTPUTC('\\', out);
10807 if (dblquote && c != '\\'
10808 && c != '`' && c != '$'
10809 && (c != '"' || eofmark != NULL)
10811 USTPUTC(CTLESC, out);
10812 USTPUTC('\\', out);
10814 if (SIT(c, SQSYNTAX) == CCTL)
10815 USTPUTC(CTLESC, out);
10823 if (eofmark == NULL) {
10824 USTPUTC(CTLQUOTEMARK, out);
10832 USE_ASH_BASH_COMPAT(bash_dollar_squote = 0;)
10833 if (eofmark != NULL && arinest == 0
10838 if (dqvarnest == 0) {
10839 syntax = BASESYNTAX;
10846 case CVAR: /* '$' */
10847 PARSESUB(); /* parse substitution */
10849 case CENDVAR: /* '}' */
10852 if (dqvarnest > 0) {
10855 USTPUTC(CTLENDVAR, out);
10860 #if ENABLE_ASH_MATH_SUPPORT
10861 case CLP: /* '(' in arithmetic */
10865 case CRP: /* ')' in arithmetic */
10866 if (parenlevel > 0) {
10870 if (pgetc() == ')') {
10871 if (--arinest == 0) {
10872 USTPUTC(CTLENDARI, out);
10873 syntax = prevsyntax;
10874 dblquote = (syntax == DQSYNTAX);
10879 * unbalanced parens
10880 * (don't 2nd guess - no error)
10888 case CBQUOTE: /* '`' */
10892 goto endword; /* exit outer loop */
10896 if (varnest == 0) {
10897 #if ENABLE_ASH_BASH_COMPAT
10899 if (pgetc() == '>')
10900 c = 0x100 + '>'; /* flag &> */
10904 goto endword; /* exit outer loop */
10906 #if ENABLE_ASH_ALIAS
10916 #if ENABLE_ASH_MATH_SUPPORT
10917 if (syntax == ARISYNTAX)
10918 raise_error_syntax("missing '))'");
10920 if (syntax != BASESYNTAX && !parsebackquote && eofmark == NULL)
10921 raise_error_syntax("unterminated quoted string");
10922 if (varnest != 0) {
10923 startlinno = g_parsefile->linno;
10925 raise_error_syntax("missing '}'");
10927 USTPUTC('\0', out);
10928 len = out - (char *)stackblock();
10929 out = stackblock();
10930 if (eofmark == NULL) {
10931 if ((c == '>' || c == '<' USE_ASH_BASH_COMPAT( || c == 0x100 + '>'))
10934 if (isdigit_str9(out)) {
10935 PARSEREDIR(); /* passed as params: out, c */
10936 lasttoken = TREDIR;
10939 /* else: non-number X seen, interpret it
10940 * as "NNNX>file" = "NNNX >file" */
10944 quoteflag = quotef;
10945 backquotelist = bqlist;
10946 grabstackblock(len);
10950 /* end of readtoken routine */
10953 * Check to see whether we are at the end of the here document. When this
10954 * is called, c is set to the first character of the next input line. If
10955 * we are at the end of the here document, this routine sets the c to PEOF.
10959 #if ENABLE_ASH_ALIAS
10965 while (c == '\t') {
10969 if (c == *eofmark) {
10970 if (pfgets(line, sizeof(line)) != NULL) {
10974 for (q = eofmark + 1; *q && *p == *q; p++, q++)
10976 if (*p == '\n' && *q == '\0') {
10978 g_parsefile->linno++;
10979 needprompt = doprompt;
10981 pushstring(line, NULL);
10986 goto checkend_return;
10990 * Parse a redirection operator. The variable "out" points to a string
10991 * specifying the fd to be redirected. The variable "c" contains the
10992 * first character of the redirection operator.
10995 /* out is already checked to be a valid number or "" */
10996 int fd = (*out == '\0' ? -1 : atoi(out));
10999 np = stzalloc(sizeof(struct nfile));
11004 np->type = NAPPEND;
11006 np->type = NCLOBBER;
11009 /* it also can be NTO2 (>&file), but we can't figure it out yet */
11015 #if ENABLE_ASH_BASH_COMPAT
11016 else if (c == 0x100 + '>') { /* this flags &> redirection */
11018 pgetc(); /* this is '>', no need to check */
11022 else { /* c == '<' */
11023 /*np->nfile.fd = 0; - stzalloc did it */
11027 if (sizeof(struct nfile) != sizeof(struct nhere)) {
11028 np = stzalloc(sizeof(struct nhere));
11029 /*np->nfile.fd = 0; - stzalloc did it */
11032 heredoc = stzalloc(sizeof(struct heredoc));
11033 heredoc->here = np;
11036 heredoc->striptabs = 1;
11038 /*heredoc->striptabs = 0; - stzalloc did it */
11044 np->type = NFROMFD;
11048 np->type = NFROMTO;
11060 goto parseredir_return;
11064 * Parse a substitution. At this point, we have read the dollar sign
11065 * and nothing else.
11068 /* is_special(c) evaluates to 1 for c in "!#$*-0123456789?@"; 0 otherwise
11069 * (assuming ascii char codes, as the original implementation did) */
11070 #define is_special(c) \
11071 (((unsigned)(c) - 33 < 32) \
11072 && ((0xc1ff920dU >> ((unsigned)(c) - 33)) & 1))
11078 static const char types[] ALIGN1 = "}-+?=";
11081 if (c <= PEOA_OR_PEOF
11082 || (c != '(' && c != '{' && !is_name(c) && !is_special(c))
11084 #if ENABLE_ASH_BASH_COMPAT
11086 bash_dollar_squote = 1;
11091 } else if (c == '(') { /* $(command) or $((arith)) */
11092 if (pgetc() == '(') {
11093 #if ENABLE_ASH_MATH_SUPPORT
11096 raise_error_syntax("you disabled math support for $((arith)) syntax");
11103 USTPUTC(CTLVAR, out);
11104 typeloc = out - (char *)stackblock();
11105 USTPUTC(VSNORMAL, out);
11106 subtype = VSNORMAL;
11114 subtype = VSLENGTH;
11118 if (c > PEOA_OR_PEOF && is_name(c)) {
11122 } while (c > PEOA_OR_PEOF && is_in_name(c));
11123 } else if (isdigit(c)) {
11127 } while (isdigit(c));
11128 } else if (is_special(c)) {
11133 raise_error_syntax("bad substitution");
11138 if (subtype == 0) {
11142 #if ENABLE_ASH_BASH_COMPAT
11143 if (c == ':' || c == '$' || isdigit(c)) {
11145 subtype = VSSUBSTR;
11152 p = strchr(types, c);
11155 subtype = p - types + VSNORMAL;
11160 subtype = c == '#' ? VSTRIMLEFT : VSTRIMRIGHT;
11168 #if ENABLE_ASH_BASH_COMPAT
11170 subtype = VSREPLACE;
11173 subtype++; /* VSREPLACEALL */
11182 if (dblquote || arinest)
11184 *((char *)stackblock() + typeloc) = subtype | flags;
11185 if (subtype != VSNORMAL) {
11187 if (dblquote || arinest) {
11192 goto parsesub_return;
11196 * Called to parse command substitutions. Newstyle is set if the command
11197 * is enclosed inside $(...); nlpp is a pointer to the head of the linked
11198 * list of commands (passed by reference), and savelen is the number of
11199 * characters on the top of the stack which must be preserved.
11202 struct nodelist **nlpp;
11205 char *volatile str;
11206 struct jmploc jmploc;
11207 struct jmploc *volatile savehandler;
11209 smallint saveprompt = 0;
11212 (void) &saveprompt;
11214 savepbq = parsebackquote;
11215 if (setjmp(jmploc.loc)) {
11217 parsebackquote = 0;
11218 exception_handler = savehandler;
11219 longjmp(exception_handler->loc, 1);
11223 savelen = out - (char *)stackblock();
11225 str = ckmalloc(savelen);
11226 memcpy(str, stackblock(), savelen);
11228 savehandler = exception_handler;
11229 exception_handler = &jmploc;
11232 /* We must read until the closing backquote, giving special
11233 treatment to some slashes, and then push the string and
11234 reread it as input, interpreting it normally. */
11241 STARTSTACKSTR(pout);
11254 g_parsefile->linno++;
11258 * If eating a newline, avoid putting
11259 * the newline into the new character
11260 * stream (via the STPUTC after the
11265 if (pc != '\\' && pc != '`' && pc != '$'
11266 && (!dblquote || pc != '"'))
11267 STPUTC('\\', pout);
11268 if (pc > PEOA_OR_PEOF) {
11274 #if ENABLE_ASH_ALIAS
11277 startlinno = g_parsefile->linno;
11278 raise_error_syntax("EOF in backquote substitution");
11281 g_parsefile->linno++;
11282 needprompt = doprompt;
11291 STPUTC('\0', pout);
11292 psavelen = pout - (char *)stackblock();
11293 if (psavelen > 0) {
11294 pstr = grabstackstr(pout);
11295 setinputstring(pstr);
11300 nlpp = &(*nlpp)->next;
11301 *nlpp = stzalloc(sizeof(**nlpp));
11302 /* (*nlpp)->next = NULL; - stzalloc did it */
11303 parsebackquote = oldstyle;
11306 saveprompt = doprompt;
11313 doprompt = saveprompt;
11314 else if (readtoken() != TRP)
11315 raise_error_unexpected_syntax(TRP);
11320 * Start reading from old file again, ignoring any pushed back
11321 * tokens left from the backquote parsing
11326 while (stackblocksize() <= savelen)
11328 STARTSTACKSTR(out);
11330 memcpy(out, str, savelen);
11331 STADJUST(savelen, out);
11337 parsebackquote = savepbq;
11338 exception_handler = savehandler;
11339 if (arinest || dblquote)
11340 USTPUTC(CTLBACKQ | CTLQUOTE, out);
11342 USTPUTC(CTLBACKQ, out);
11344 goto parsebackq_oldreturn;
11345 goto parsebackq_newreturn;
11348 #if ENABLE_ASH_MATH_SUPPORT
11350 * Parse an arithmetic expansion (indicate start of one and set state)
11353 if (++arinest == 1) {
11354 prevsyntax = syntax;
11355 syntax = ARISYNTAX;
11356 USTPUTC(CTLARI, out);
11363 * we collapse embedded arithmetic expansion to
11364 * parenthesis, which should be equivalent
11368 goto parsearith_return;
11372 } /* end of readtoken */
11375 * Read the next input token.
11376 * If the token is a word, we set backquotelist to the list of cmds in
11377 * backquotes. We set quoteflag to true if any part of the word was
11379 * If the token is TREDIR, then we set redirnode to a structure containing
11381 * In all cases, the variable startlinno is set to the number of the line
11382 * on which the token starts.
11384 * [Change comment: here documents and internal procedures]
11385 * [Readtoken shouldn't have any arguments. Perhaps we should make the
11386 * word parsing code into a separate routine. In this case, readtoken
11387 * doesn't need to have any internal procedures, but parseword does.
11388 * We could also make parseoperator in essence the main routine, and
11389 * have parseword (readtoken1?) handle both words and redirection.]
11391 #define NEW_xxreadtoken
11392 #ifdef NEW_xxreadtoken
11393 /* singles must be first! */
11394 static const char xxreadtoken_chars[7] ALIGN1 = {
11395 '\n', '(', ')', /* singles */
11396 '&', '|', ';', /* doubles */
11400 #define xxreadtoken_singles 3
11401 #define xxreadtoken_doubles 3
11403 static const char xxreadtoken_tokens[] ALIGN1 = {
11404 TNL, TLP, TRP, /* only single occurrence allowed */
11405 TBACKGND, TPIPE, TSEMI, /* if single occurrence */
11406 TEOF, /* corresponds to trailing nul */
11407 TAND, TOR, TENDCASE /* if double occurrence */
11422 startlinno = g_parsefile->linno;
11423 for (;;) { /* until token or start of word found */
11425 if (c == ' ' || c == '\t' USE_ASH_ALIAS( || c == PEOA))
11429 while ((c = pgetc()) != '\n' && c != PEOF)
11432 } else if (c == '\\') {
11433 if (pgetc() != '\n') {
11435 break; /* return readtoken1(...) */
11437 startlinno = ++g_parsefile->linno;
11443 p = xxreadtoken_chars + sizeof(xxreadtoken_chars) - 1;
11446 g_parsefile->linno++;
11447 needprompt = doprompt;
11450 p = strchr(xxreadtoken_chars, c);
11452 break; /* return readtoken1(...) */
11454 if ((int)(p - xxreadtoken_chars) >= xxreadtoken_singles) {
11456 if (cc == c) { /* double occurrence? */
11457 p += xxreadtoken_doubles + 1;
11460 #if ENABLE_ASH_BASH_COMPAT
11461 if (c == '&' && cc == '>') /* &> */
11462 break; /* return readtoken1(...) */
11467 lasttoken = xxreadtoken_tokens[p - xxreadtoken_chars];
11472 return readtoken1(c, BASESYNTAX, (char *) NULL, 0);
11474 #else /* old xxreadtoken */
11475 #define RETURN(token) return lasttoken = token
11488 startlinno = g_parsefile->linno;
11489 for (;;) { /* until token or start of word found */
11492 case ' ': case '\t':
11493 #if ENABLE_ASH_ALIAS
11498 while ((c = pgetc()) != '\n' && c != PEOF)
11503 if (pgetc() == '\n') {
11504 startlinno = ++g_parsefile->linno;
11512 g_parsefile->linno++;
11513 needprompt = doprompt;
11518 if (pgetc() == '&')
11523 if (pgetc() == '|')
11528 if (pgetc() == ';')
11541 return readtoken1(c, BASESYNTAX, (char *)NULL, 0);
11544 #endif /* old xxreadtoken */
11551 smallint alreadyseen = tokpushback;
11554 #if ENABLE_ASH_ALIAS
11563 if (checkkwd & CHKNL) {
11570 if (t != TWORD || quoteflag) {
11575 * check for keywords
11577 if (checkkwd & CHKKWD) {
11578 const char *const *pp;
11580 pp = findkwd(wordtext);
11582 lasttoken = t = pp - tokname_array;
11583 TRACE(("keyword %s recognized\n", tokname(t)));
11588 if (checkkwd & CHKALIAS) {
11589 #if ENABLE_ASH_ALIAS
11591 ap = lookupalias(wordtext, 1);
11594 pushstring(ap->val, ap);
11604 TRACE(("token %s %s\n", tokname(t), t == TWORD ? wordtext : ""));
11606 TRACE(("reread token %s %s\n", tokname(t), t == TWORD ? wordtext : ""));
11618 return tokname_array[t][0];
11622 * Read and parse a command. Returns NEOF on end of file. (NULL is a
11623 * valid parse tree indicating a blank line.)
11625 static union node *
11626 parsecmd(int interact)
11631 doprompt = interact;
11633 setprompt(doprompt);
11645 * Input any here documents.
11650 struct heredoc *here;
11653 here = heredoclist;
11654 heredoclist = NULL;
11660 readtoken1(pgetc(), here->here->type == NHERE? SQSYNTAX : DQSYNTAX,
11661 here->eofmark, here->striptabs);
11662 n = stzalloc(sizeof(struct narg));
11663 n->narg.type = NARG;
11664 /*n->narg.next = NULL; - stzalloc did it */
11665 n->narg.text = wordtext;
11666 n->narg.backquote = backquotelist;
11667 here->here->nhere.doc = n;
11674 * called by editline -- any expansions to the prompt should be added here.
11676 #if ENABLE_ASH_EXPAND_PRMT
11677 static const char *
11678 expandstr(const char *ps)
11682 /* XXX Fix (char *) cast. */
11683 setinputstring((char *)ps);
11684 readtoken1(pgetc(), PSSYNTAX, nullstr, 0);
11687 n.narg.type = NARG;
11688 n.narg.next = NULL;
11689 n.narg.text = wordtext;
11690 n.narg.backquote = backquotelist;
11692 expandarg(&n, NULL, 0);
11693 return stackblock();
11698 * Execute a command or commands contained in a string.
11701 evalstring(char *s, int mask)
11704 struct stackmark smark;
11708 setstackmark(&smark);
11711 while ((n = parsecmd(0)) != NEOF) {
11713 popstackmark(&smark);
11726 * The eval command.
11729 evalcmd(int argc UNUSED_PARAM, char **argv)
11738 STARTSTACKSTR(concat);
11740 concat = stack_putstr(p, concat);
11744 STPUTC(' ', concat);
11746 STPUTC('\0', concat);
11747 p = grabstackstr(concat);
11749 evalstring(p, ~SKIPEVAL);
11756 * Read and execute commands. "Top" is nonzero for the top level command
11757 * loop; it turns on prompting if the shell is interactive.
11763 struct stackmark smark;
11767 TRACE(("cmdloop(%d) called\n", top));
11771 setstackmark(&smark);
11774 showjobs(stderr, SHOW_CHANGED);
11777 if (iflag && top) {
11779 #if ENABLE_ASH_MAIL
11783 n = parsecmd(inter);
11784 /* showtree(n); DEBUG */
11786 if (!top || numeof >= 50)
11788 if (!stoppedjobs()) {
11791 out2str("\nUse \"exit\" to leave shell.\n");
11794 } else if (nflag == 0) {
11795 /* job_warning can only be 2,1,0. Here 2->1, 1/0->0 */
11800 popstackmark(&smark);
11805 return skip & SKIPEVAL;
11812 * Take commands from a file. To be compatible we should do a path
11813 * search for the file, which is necessary to find sub-commands.
11816 find_dot_file(char *name)
11819 const char *path = pathval();
11822 /* don't try this for absolute or relative paths */
11823 if (strchr(name, '/'))
11826 while ((fullname = padvance(&path, name)) != NULL) {
11827 if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) {
11829 * Don't bother freeing here, since it will
11830 * be freed by the caller.
11834 stunalloc(fullname);
11837 /* not found in the PATH */
11838 ash_msg_and_raise_error("%s: not found", name);
11843 dotcmd(int argc, char **argv)
11845 struct strlist *sp;
11846 volatile struct shparam saveparam;
11849 for (sp = cmdenviron; sp; sp = sp->next)
11850 setvareq(ckstrdup(sp->text), VSTRFIXED | VTEXTFIXED);
11852 if (argv[1]) { /* That's what SVR2 does */
11853 char *fullname = find_dot_file(argv[1]);
11856 if (argc) { /* argc > 0, argv[0] != NULL */
11857 saveparam = shellparam;
11858 shellparam.malloced = 0;
11859 shellparam.nparam = argc;
11860 shellparam.p = argv;
11863 setinputfile(fullname, INPUT_PUSH_FILE);
11864 commandname = fullname;
11869 freeparam(&shellparam);
11870 shellparam = saveparam;
11872 status = exitstatus;
11878 exitcmd(int argc UNUSED_PARAM, char **argv)
11883 exitstatus = number(argv[1]);
11884 raise_exception(EXEXIT);
11889 * Read a file containing shell functions.
11892 readcmdfile(char *name)
11894 setinputfile(name, INPUT_PUSH_FILE);
11900 /* ============ find_command inplementation */
11903 * Resolve a command name. If you change this routine, you may have to
11904 * change the shellexec routine as well.
11907 find_command(char *name, struct cmdentry *entry, int act, const char *path)
11909 struct tblentry *cmdp;
11916 struct builtincmd *bcmd;
11918 /* If name contains a slash, don't use PATH or hash table */
11919 if (strchr(name, '/') != NULL) {
11920 entry->u.index = -1;
11921 if (act & DO_ABS) {
11922 while (stat(name, &statb) < 0) {
11924 if (errno == EINTR)
11927 entry->cmdtype = CMDUNKNOWN;
11931 entry->cmdtype = CMDNORMAL;
11935 /* #if ENABLE_FEATURE_SH_STANDALONE... moved after builtin check */
11937 updatetbl = (path == pathval());
11940 if (strstr(path, "%builtin") != NULL)
11941 act |= DO_ALTBLTIN;
11944 /* If name is in the table, check answer will be ok */
11945 cmdp = cmdlookup(name, 0);
11946 if (cmdp != NULL) {
11949 switch (cmdp->cmdtype) {
11967 } else if (cmdp->rehash == 0)
11968 /* if not invalidated by cd, we're done */
11972 /* If %builtin not in path, check for builtin next */
11973 bcmd = find_builtin(name);
11975 if (IS_BUILTIN_REGULAR(bcmd))
11976 goto builtin_success;
11977 if (act & DO_ALTPATH) {
11978 if (!(act & DO_ALTBLTIN))
11979 goto builtin_success;
11980 } else if (builtinloc <= 0) {
11981 goto builtin_success;
11985 #if ENABLE_FEATURE_SH_STANDALONE
11987 int applet_no = find_applet_by_name(name);
11988 if (applet_no >= 0) {
11989 entry->cmdtype = CMDNORMAL;
11990 entry->u.index = -2 - applet_no;
11996 /* We have to search path. */
11997 prev = -1; /* where to start */
11998 if (cmdp && cmdp->rehash) { /* doing a rehash */
11999 if (cmdp->cmdtype == CMDBUILTIN)
12002 prev = cmdp->param.index;
12008 while ((fullname = padvance(&path, name)) != NULL) {
12009 stunalloc(fullname);
12010 /* NB: code below will still use fullname
12011 * despite it being "unallocated" */
12014 if (prefix(pathopt, "builtin")) {
12016 goto builtin_success;
12019 if ((act & DO_NOFUNC)
12020 || !prefix(pathopt, "func")
12021 ) { /* ignore unimplemented options */
12025 /* if rehash, don't redo absolute path names */
12026 if (fullname[0] == '/' && idx <= prev) {
12029 TRACE(("searchexec \"%s\": no change\n", name));
12032 while (stat(fullname, &statb) < 0) {
12034 if (errno == EINTR)
12037 if (errno != ENOENT && errno != ENOTDIR)
12041 e = EACCES; /* if we fail, this will be the error */
12042 if (!S_ISREG(statb.st_mode))
12044 if (pathopt) { /* this is a %func directory */
12045 stalloc(strlen(fullname) + 1);
12046 /* NB: stalloc will return space pointed by fullname
12047 * (because we don't have any intervening allocations
12048 * between stunalloc above and this stalloc) */
12049 readcmdfile(fullname);
12050 cmdp = cmdlookup(name, 0);
12051 if (cmdp == NULL || cmdp->cmdtype != CMDFUNCTION)
12052 ash_msg_and_raise_error("%s not defined in %s", name, fullname);
12053 stunalloc(fullname);
12056 TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
12058 entry->cmdtype = CMDNORMAL;
12059 entry->u.index = idx;
12063 cmdp = cmdlookup(name, 1);
12064 cmdp->cmdtype = CMDNORMAL;
12065 cmdp->param.index = idx;
12070 /* We failed. If there was an entry for this command, delete it */
12071 if (cmdp && updatetbl)
12072 delete_cmd_entry();
12074 ash_msg("%s: %s", name, errmsg(e, "not found"));
12075 entry->cmdtype = CMDUNKNOWN;
12080 entry->cmdtype = CMDBUILTIN;
12081 entry->u.cmd = bcmd;
12085 cmdp = cmdlookup(name, 1);
12086 cmdp->cmdtype = CMDBUILTIN;
12087 cmdp->param.cmd = bcmd;
12091 entry->cmdtype = cmdp->cmdtype;
12092 entry->u = cmdp->param;
12096 /* ============ trap.c */
12099 * The trap builtin.
12102 trapcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
12111 for (signo = 0; signo < NSIG; signo++) {
12112 if (trap[signo] != NULL) {
12113 out1fmt("trap -- %s %s\n",
12114 single_quote(trap[signo]),
12115 get_signame(signo));
12124 signo = get_signum(*ap);
12126 ash_msg_and_raise_error("%s: bad trap", *ap);
12129 if (LONE_DASH(action))
12132 action = ckstrdup(action);
12135 trap[signo] = action;
12145 /* ============ Builtins */
12147 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
12149 * Lists available builtins
12152 helpcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
12157 out1fmt("\nBuilt-in commands:\n-------------------\n");
12158 for (col = 0, i = 0; i < ARRAY_SIZE(builtintab); i++) {
12159 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '),
12160 builtintab[i].name + 1);
12166 #if ENABLE_FEATURE_SH_STANDALONE
12168 const char *a = applet_names;
12170 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '), a);
12175 a += strlen(a) + 1;
12180 return EXIT_SUCCESS;
12182 #endif /* FEATURE_SH_EXTRA_QUIET */
12185 * The export and readonly commands.
12188 exportcmd(int argc UNUSED_PARAM, char **argv)
12194 int flag = argv[0][0] == 'r' ? VREADONLY : VEXPORT;
12196 if (nextopt("p") != 'p') {
12201 p = strchr(name, '=');
12205 vp = *findvar(hashvar(name), name);
12211 setvar(name, p, flag);
12212 } while ((name = *++aptr) != NULL);
12216 showvars(argv[0], flag, 0);
12221 * Delete a function if it exists.
12224 unsetfunc(const char *name)
12226 struct tblentry *cmdp;
12228 cmdp = cmdlookup(name, 0);
12229 if (cmdp!= NULL && cmdp->cmdtype == CMDFUNCTION)
12230 delete_cmd_entry();
12234 * The unset builtin command. We unset the function before we unset the
12235 * variable to allow a function to be unset when there is a readonly variable
12236 * with the same name.
12239 unsetcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
12246 while ((i = nextopt("vf")) != '\0') {
12250 for (ap = argptr; *ap; ap++) {
12266 #include <sys/times.h>
12268 static const unsigned char timescmd_str[] ALIGN1 = {
12269 ' ', offsetof(struct tms, tms_utime),
12270 '\n', offsetof(struct tms, tms_stime),
12271 ' ', offsetof(struct tms, tms_cutime),
12272 '\n', offsetof(struct tms, tms_cstime),
12277 timescmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
12279 long clk_tck, s, t;
12280 const unsigned char *p;
12283 clk_tck = sysconf(_SC_CLK_TCK);
12288 t = *(clock_t *)(((char *) &buf) + p[1]);
12290 out1fmt("%ldm%ld.%.3lds%c",
12292 ((t - s * clk_tck) * 1000) / clk_tck,
12294 } while (*(p += 2));
12299 #if ENABLE_ASH_MATH_SUPPORT
12301 dash_arith(const char *s)
12307 result = arith(s, &errcode);
12310 ash_msg_and_raise_error("exponent less than 0");
12312 ash_msg_and_raise_error("divide by zero");
12314 ash_msg_and_raise_error("expression recursion loop detected");
12315 raise_error_syntax(s);
12323 * The let builtin. partial stolen from GNU Bash, the Bourne Again SHell.
12324 * Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
12326 * Copyright (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
12329 letcmd(int argc UNUSED_PARAM, char **argv)
12335 ash_msg_and_raise_error("expression expected");
12337 i = dash_arith(*argv);
12342 #endif /* ASH_MATH_SUPPORT */
12345 /* ============ miscbltin.c
12347 * Miscellaneous builtins.
12352 #if defined(__GLIBC__) && __GLIBC__ == 2 && __GLIBC_MINOR__ < 1
12353 typedef enum __rlimit_resource rlim_t;
12357 * The read builtin. Options:
12358 * -r Do not interpret '\' specially
12359 * -s Turn off echo (tty only)
12360 * -n NCHARS Read NCHARS max
12361 * -p PROMPT Display PROMPT on stderr (if input is from tty)
12362 * -t SECONDS Timeout after SECONDS (tty or pipe only)
12363 * -u FD Read from given FD instead of fd 0
12364 * This uses unbuffered input, which may be avoidable in some cases.
12365 * TODO: bash also has:
12366 * -a ARRAY Read into array[0],[1],etc
12367 * -d DELIM End on DELIM char, not newline
12368 * -e Use line editing (tty only)
12371 readcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
12373 static const char *const arg_REPLY[] = { "REPLY", NULL };
12386 #if ENABLE_ASH_READ_NCHARS
12387 int nchars = 0; /* if != 0, -n is in effect */
12389 struct termios tty, old_tty;
12391 #if ENABLE_ASH_READ_TIMEOUT
12392 unsigned end_ms = 0;
12393 unsigned timeout = 0;
12398 while ((i = nextopt("p:u:r"
12399 USE_ASH_READ_TIMEOUT("t:")
12400 USE_ASH_READ_NCHARS("n:s")
12404 prompt = optionarg;
12406 #if ENABLE_ASH_READ_NCHARS
12408 nchars = bb_strtou(optionarg, NULL, 10);
12409 if (nchars < 0 || errno)
12410 ash_msg_and_raise_error("invalid count");
12411 /* nchars == 0: off (bash 3.2 does this too) */
12417 #if ENABLE_ASH_READ_TIMEOUT
12419 timeout = bb_strtou(optionarg, NULL, 10);
12420 if (errno || timeout > UINT_MAX / 2048)
12421 ash_msg_and_raise_error("invalid timeout");
12423 #if 0 /* even bash have no -t N.NNN support */
12424 ts.tv_sec = bb_strtou(optionarg, &p, 10);
12426 /* EINVAL means number is ok, but not terminated by NUL */
12427 if (*p == '.' && errno == EINVAL) {
12431 ts.tv_usec = bb_strtou(p, &p2, 10);
12433 ash_msg_and_raise_error("invalid timeout");
12435 /* normalize to usec */
12437 ash_msg_and_raise_error("invalid timeout");
12438 while (scale++ < 6)
12441 } else if (ts.tv_sec < 0 || errno) {
12442 ash_msg_and_raise_error("invalid timeout");
12444 if (!(ts.tv_sec | ts.tv_usec)) { /* both are 0? */
12445 ash_msg_and_raise_error("invalid timeout");
12454 fd = bb_strtou(optionarg, NULL, 10);
12455 if (fd < 0 || errno)
12456 ash_msg_and_raise_error("invalid file descriptor");
12462 if (prompt && isatty(fd)) {
12467 ap = (char**)arg_REPLY;
12468 ifs = bltinlookup("IFS");
12471 #if ENABLE_ASH_READ_NCHARS
12472 tcgetattr(fd, &tty);
12474 if (nchars || silent) {
12476 tty.c_lflag &= ~ICANON;
12477 tty.c_cc[VMIN] = nchars < 256 ? nchars : 255;
12480 tty.c_lflag &= ~(ECHO | ECHOK | ECHONL);
12482 /* if tcgetattr failed, tcsetattr will fail too.
12483 * Ignoring, it's harmless. */
12484 tcsetattr(fd, TCSANOW, &tty);
12491 #if ENABLE_ASH_READ_TIMEOUT
12492 if (timeout) /* NB: ensuring end_ms is nonzero */
12493 end_ms = ((unsigned)(monotonic_us() / 1000) + timeout) | 1;
12497 #if ENABLE_ASH_READ_TIMEOUT
12499 struct pollfd pfd[1];
12501 pfd[0].events = POLLIN;
12502 timeout = end_ms - (unsigned)(monotonic_us() / 1000);
12503 if ((int)timeout <= 0 /* already late? */
12504 || safe_poll(pfd, 1, timeout) != 1 /* no? wait... */
12505 ) { /* timed out! */
12506 #if ENABLE_ASH_READ_NCHARS
12507 tcsetattr(fd, TCSANOW, &old_tty);
12513 if (nonblock_safe_read(fd, &c, 1) != 1) {
12525 if (!rflag && c == '\\') {
12531 if (startword && *ifs == ' ' && strchr(ifs, c)) {
12535 if (ap[1] != NULL && strchr(ifs, c) != NULL) {
12537 setvar(*ap, stackblock(), 0);
12546 /* end of do {} while: */
12547 #if ENABLE_ASH_READ_NCHARS
12553 #if ENABLE_ASH_READ_NCHARS
12554 tcsetattr(fd, TCSANOW, &old_tty);
12558 /* Remove trailing blanks */
12559 while ((char *)stackblock() <= --p && strchr(ifs, *p) != NULL)
12561 setvar(*ap, stackblock(), 0);
12562 while (*++ap != NULL)
12563 setvar(*ap, nullstr, 0);
12568 umaskcmd(int argc UNUSED_PARAM, char **argv)
12570 static const char permuser[3] ALIGN1 = "ugo";
12571 static const char permmode[3] ALIGN1 = "rwx";
12572 static const short permmask[] ALIGN2 = {
12573 S_IRUSR, S_IWUSR, S_IXUSR,
12574 S_IRGRP, S_IWGRP, S_IXGRP,
12575 S_IROTH, S_IWOTH, S_IXOTH
12581 int symbolic_mode = 0;
12583 while (nextopt("S") != '\0') {
12594 if (symbolic_mode) {
12598 for (i = 0; i < 3; i++) {
12601 *p++ = permuser[i];
12603 for (j = 0; j < 3; j++) {
12604 if ((mask & permmask[3 * i + j]) == 0) {
12605 *p++ = permmode[j];
12613 out1fmt("%.4o\n", mask);
12616 if (isdigit((unsigned char) *ap)) {
12619 if (*ap >= '8' || *ap < '0')
12620 ash_msg_and_raise_error(illnum, argv[1]);
12621 mask = (mask << 3) + (*ap - '0');
12622 } while (*++ap != '\0');
12625 mask = ~mask & 0777;
12626 if (!bb_parse_mode(ap, &mask)) {
12627 ash_msg_and_raise_error("illegal mode: %s", ap);
12629 umask(~mask & 0777);
12638 * This code, originally by Doug Gwyn, Doug Kingston, Eric Gisin, and
12639 * Michael Rendell was ripped from pdksh 5.0.8 and hacked for use with
12640 * ash by J.T. Conklin.
12646 uint8_t cmd; /* RLIMIT_xxx fit into it */
12647 uint8_t factor_shift; /* shift by to get rlim_{cur,max} values */
12651 static const struct limits limits_tbl[] = {
12653 { RLIMIT_CPU, 0, 't' },
12655 #ifdef RLIMIT_FSIZE
12656 { RLIMIT_FSIZE, 9, 'f' },
12659 { RLIMIT_DATA, 10, 'd' },
12661 #ifdef RLIMIT_STACK
12662 { RLIMIT_STACK, 10, 's' },
12665 { RLIMIT_CORE, 9, 'c' },
12668 { RLIMIT_RSS, 10, 'm' },
12670 #ifdef RLIMIT_MEMLOCK
12671 { RLIMIT_MEMLOCK, 10, 'l' },
12673 #ifdef RLIMIT_NPROC
12674 { RLIMIT_NPROC, 0, 'p' },
12676 #ifdef RLIMIT_NOFILE
12677 { RLIMIT_NOFILE, 0, 'n' },
12680 { RLIMIT_AS, 10, 'v' },
12682 #ifdef RLIMIT_LOCKS
12683 { RLIMIT_LOCKS, 0, 'w' },
12686 static const char limits_name[] =
12688 "time(seconds)" "\0"
12690 #ifdef RLIMIT_FSIZE
12691 "file(blocks)" "\0"
12696 #ifdef RLIMIT_STACK
12700 "coredump(blocks)" "\0"
12705 #ifdef RLIMIT_MEMLOCK
12706 "locked memory(kb)" "\0"
12708 #ifdef RLIMIT_NPROC
12711 #ifdef RLIMIT_NOFILE
12717 #ifdef RLIMIT_LOCKS
12722 enum limtype { SOFT = 0x1, HARD = 0x2 };
12725 printlim(enum limtype how, const struct rlimit *limit,
12726 const struct limits *l)
12730 val = limit->rlim_max;
12732 val = limit->rlim_cur;
12734 if (val == RLIM_INFINITY)
12735 out1fmt("unlimited\n");
12737 val >>= l->factor_shift;
12738 out1fmt("%lld\n", (long long) val);
12743 ulimitcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
12747 enum limtype how = SOFT | HARD;
12748 const struct limits *l;
12751 struct rlimit limit;
12754 while ((optc = nextopt("HSa"
12758 #ifdef RLIMIT_FSIZE
12764 #ifdef RLIMIT_STACK
12773 #ifdef RLIMIT_MEMLOCK
12776 #ifdef RLIMIT_NPROC
12779 #ifdef RLIMIT_NOFILE
12785 #ifdef RLIMIT_LOCKS
12803 for (l = limits_tbl; l->option != what; l++)
12806 set = *argptr ? 1 : 0;
12810 if (all || argptr[1])
12811 ash_msg_and_raise_error("too many arguments");
12812 if (strncmp(p, "unlimited\n", 9) == 0)
12813 val = RLIM_INFINITY;
12817 while ((c = *p++) >= '0' && c <= '9') {
12818 val = (val * 10) + (long)(c - '0');
12819 // val is actually 'unsigned long int' and can't get < 0
12820 if (val < (rlim_t) 0)
12824 ash_msg_and_raise_error("bad number");
12825 val <<= l->factor_shift;
12829 const char *lname = limits_name;
12830 for (l = limits_tbl; l != &limits_tbl[ARRAY_SIZE(limits_tbl)]; l++) {
12831 getrlimit(l->cmd, &limit);
12832 out1fmt("%-20s ", lname);
12833 lname += strlen(lname) + 1;
12834 printlim(how, &limit, l);
12839 getrlimit(l->cmd, &limit);
12842 limit.rlim_max = val;
12844 limit.rlim_cur = val;
12845 if (setrlimit(l->cmd, &limit) < 0)
12846 ash_msg_and_raise_error("error setting limit (%m)");
12848 printlim(how, &limit, l);
12854 /* ============ Math support */
12856 #if ENABLE_ASH_MATH_SUPPORT
12858 /* Copyright (c) 2001 Aaron Lehmann <aaronl@vitelus.com>
12860 Permission is hereby granted, free of charge, to any person obtaining
12861 a copy of this software and associated documentation files (the
12862 "Software"), to deal in the Software without restriction, including
12863 without limitation the rights to use, copy, modify, merge, publish,
12864 distribute, sublicense, and/or sell copies of the Software, and to
12865 permit persons to whom the Software is furnished to do so, subject to
12866 the following conditions:
12868 The above copyright notice and this permission notice shall be
12869 included in all copies or substantial portions of the Software.
12871 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
12872 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
12873 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
12874 IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
12875 CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
12876 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
12877 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
12880 /* This is my infix parser/evaluator. It is optimized for size, intended
12881 * as a replacement for yacc-based parsers. However, it may well be faster
12882 * than a comparable parser written in yacc. The supported operators are
12883 * listed in #defines below. Parens, order of operations, and error handling
12884 * are supported. This code is thread safe. The exact expression format should
12885 * be that which POSIX specifies for shells. */
12887 /* The code uses a simple two-stack algorithm. See
12888 * http://www.onthenet.com.au/~grahamis/int2008/week02/lect02.html
12889 * for a detailed explanation of the infix-to-postfix algorithm on which
12890 * this is based (this code differs in that it applies operators immediately
12891 * to the stack instead of adding them to a queue to end up with an
12894 /* To use the routine, call it with an expression string and error return
12898 * Aug 24, 2001 Manuel Novoa III
12900 * Reduced the generated code size by about 30% (i386) and fixed several bugs.
12902 * 1) In arith_apply():
12903 * a) Cached values of *numptr and &(numptr[-1]).
12904 * b) Removed redundant test for zero denominator.
12907 * a) Eliminated redundant code for processing operator tokens by moving
12908 * to a table-based implementation. Also folded handling of parens
12910 * b) Combined all 3 loops which called arith_apply to reduce generated
12911 * code size at the cost of speed.
12913 * 3) The following expressions were treated as valid by the original code:
12914 * 1() , 0! , 1 ( *3 ) .
12915 * These bugs have been fixed by internally enclosing the expression in
12916 * parens and then checking that all binary ops and right parens are
12917 * preceded by a valid expression (NUM_TOKEN).
12919 * Note: It may be desirable to replace Aaron's test for whitespace with
12920 * ctype's isspace() if it is used by another busybox applet or if additional
12921 * whitespace chars should be considered. Look below the "#include"s for a
12922 * precompiler test.
12926 * Aug 26, 2001 Manuel Novoa III
12928 * Return 0 for null expressions. Pointed out by Vladimir Oleynik.
12930 * Merge in Aaron's comments previously posted to the busybox list,
12931 * modified slightly to take account of my changes to the code.
12936 * (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
12938 * - allow access to variable,
12939 * used recursive find value indirection (c=2*2; a="c"; $((a+=2)) produce 6)
12940 * - realize assign syntax (VAR=expr, +=, *= etc)
12941 * - realize exponentiation (** operator)
12942 * - realize comma separated - expr, expr
12943 * - realise ++expr --expr expr++ expr--
12944 * - realise expr ? expr : expr (but, second expr calculate always)
12945 * - allow hexadecimal and octal numbers
12946 * - was restored loses XOR operator
12947 * - remove one goto label, added three ;-)
12948 * - protect $((num num)) as true zero expr (Manuel`s error)
12949 * - always use special isspace(), see comment from bash ;-)
12952 #define arith_isspace(arithval) \
12953 (arithval == ' ' || arithval == '\n' || arithval == '\t')
12955 typedef unsigned char operator;
12957 /* An operator's token id is a bit of a bitfield. The lower 5 bits are the
12958 * precedence, and 3 high bits are an ID unique across operators of that
12959 * precedence. The ID portion is so that multiple operators can have the
12960 * same precedence, ensuring that the leftmost one is evaluated first.
12961 * Consider * and /. */
12963 #define tok_decl(prec,id) (((id)<<5)|(prec))
12964 #define PREC(op) ((op) & 0x1F)
12966 #define TOK_LPAREN tok_decl(0,0)
12968 #define TOK_COMMA tok_decl(1,0)
12970 #define TOK_ASSIGN tok_decl(2,0)
12971 #define TOK_AND_ASSIGN tok_decl(2,1)
12972 #define TOK_OR_ASSIGN tok_decl(2,2)
12973 #define TOK_XOR_ASSIGN tok_decl(2,3)
12974 #define TOK_PLUS_ASSIGN tok_decl(2,4)
12975 #define TOK_MINUS_ASSIGN tok_decl(2,5)
12976 #define TOK_LSHIFT_ASSIGN tok_decl(2,6)
12977 #define TOK_RSHIFT_ASSIGN tok_decl(2,7)
12979 #define TOK_MUL_ASSIGN tok_decl(3,0)
12980 #define TOK_DIV_ASSIGN tok_decl(3,1)
12981 #define TOK_REM_ASSIGN tok_decl(3,2)
12983 /* all assign is right associativity and precedence eq, but (7+3)<<5 > 256 */
12984 #define convert_prec_is_assing(prec) do { if (prec == 3) prec = 2; } while (0)
12986 /* conditional is right associativity too */
12987 #define TOK_CONDITIONAL tok_decl(4,0)
12988 #define TOK_CONDITIONAL_SEP tok_decl(4,1)
12990 #define TOK_OR tok_decl(5,0)
12992 #define TOK_AND tok_decl(6,0)
12994 #define TOK_BOR tok_decl(7,0)
12996 #define TOK_BXOR tok_decl(8,0)
12998 #define TOK_BAND tok_decl(9,0)
13000 #define TOK_EQ tok_decl(10,0)
13001 #define TOK_NE tok_decl(10,1)
13003 #define TOK_LT tok_decl(11,0)
13004 #define TOK_GT tok_decl(11,1)
13005 #define TOK_GE tok_decl(11,2)
13006 #define TOK_LE tok_decl(11,3)
13008 #define TOK_LSHIFT tok_decl(12,0)
13009 #define TOK_RSHIFT tok_decl(12,1)
13011 #define TOK_ADD tok_decl(13,0)
13012 #define TOK_SUB tok_decl(13,1)
13014 #define TOK_MUL tok_decl(14,0)
13015 #define TOK_DIV tok_decl(14,1)
13016 #define TOK_REM tok_decl(14,2)
13018 /* exponent is right associativity */
13019 #define TOK_EXPONENT tok_decl(15,1)
13021 /* For now unary operators. */
13022 #define UNARYPREC 16
13023 #define TOK_BNOT tok_decl(UNARYPREC,0)
13024 #define TOK_NOT tok_decl(UNARYPREC,1)
13026 #define TOK_UMINUS tok_decl(UNARYPREC+1,0)
13027 #define TOK_UPLUS tok_decl(UNARYPREC+1,1)
13029 #define PREC_PRE (UNARYPREC+2)
13031 #define TOK_PRE_INC tok_decl(PREC_PRE, 0)
13032 #define TOK_PRE_DEC tok_decl(PREC_PRE, 1)
13034 #define PREC_POST (UNARYPREC+3)
13036 #define TOK_POST_INC tok_decl(PREC_POST, 0)
13037 #define TOK_POST_DEC tok_decl(PREC_POST, 1)
13039 #define SPEC_PREC (UNARYPREC+4)
13041 #define TOK_NUM tok_decl(SPEC_PREC, 0)
13042 #define TOK_RPAREN tok_decl(SPEC_PREC, 1)
13044 #define NUMPTR (*numstackptr)
13047 tok_have_assign(operator op)
13049 operator prec = PREC(op);
13051 convert_prec_is_assing(prec);
13052 return (prec == PREC(TOK_ASSIGN) ||
13053 prec == PREC_PRE || prec == PREC_POST);
13057 is_right_associativity(operator prec)
13059 return (prec == PREC(TOK_ASSIGN) || prec == PREC(TOK_EXPONENT)
13060 || prec == PREC(TOK_CONDITIONAL));
13065 arith_t contidional_second_val;
13066 char contidional_second_val_initialized;
13067 char *var; /* if NULL then is regular number,
13068 else is variable name */
13071 typedef struct chk_var_recursive_looped_t {
13073 struct chk_var_recursive_looped_t *next;
13074 } chk_var_recursive_looped_t;
13076 static chk_var_recursive_looped_t *prev_chk_var_recursive;
13079 arith_lookup_val(v_n_t *t)
13082 const char * p = lookupvar(t->var);
13087 /* recursive try as expression */
13088 chk_var_recursive_looped_t *cur;
13089 chk_var_recursive_looped_t cur_save;
13091 for (cur = prev_chk_var_recursive; cur; cur = cur->next) {
13092 if (strcmp(cur->var, t->var) == 0) {
13093 /* expression recursion loop detected */
13097 /* save current lookuped var name */
13098 cur = prev_chk_var_recursive;
13099 cur_save.var = t->var;
13100 cur_save.next = cur;
13101 prev_chk_var_recursive = &cur_save;
13103 t->val = arith (p, &errcode);
13104 /* restore previous ptr after recursiving */
13105 prev_chk_var_recursive = cur;
13108 /* allow undefined var as 0 */
13114 /* "applying" a token means performing it on the top elements on the integer
13115 * stack. For a unary operator it will only change the top element, but a
13116 * binary operator will pop two arguments and push a result */
13118 arith_apply(operator op, v_n_t *numstack, v_n_t **numstackptr)
13121 arith_t numptr_val, rez;
13122 int ret_arith_lookup_val;
13124 /* There is no operator that can work without arguments */
13125 if (NUMPTR == numstack) goto err;
13126 numptr_m1 = NUMPTR - 1;
13128 /* check operand is var with noninteger value */
13129 ret_arith_lookup_val = arith_lookup_val(numptr_m1);
13130 if (ret_arith_lookup_val)
13131 return ret_arith_lookup_val;
13133 rez = numptr_m1->val;
13134 if (op == TOK_UMINUS)
13136 else if (op == TOK_NOT)
13138 else if (op == TOK_BNOT)
13140 else if (op == TOK_POST_INC || op == TOK_PRE_INC)
13142 else if (op == TOK_POST_DEC || op == TOK_PRE_DEC)
13144 else if (op != TOK_UPLUS) {
13145 /* Binary operators */
13147 /* check and binary operators need two arguments */
13148 if (numptr_m1 == numstack) goto err;
13150 /* ... and they pop one */
13153 if (op == TOK_CONDITIONAL) {
13154 if (!numptr_m1->contidional_second_val_initialized) {
13155 /* protect $((expr1 ? expr2)) without ": expr" */
13158 rez = numptr_m1->contidional_second_val;
13159 } else if (numptr_m1->contidional_second_val_initialized) {
13160 /* protect $((expr1 : expr2)) without "expr ? " */
13163 numptr_m1 = NUMPTR - 1;
13164 if (op != TOK_ASSIGN) {
13165 /* check operand is var with noninteger value for not '=' */
13166 ret_arith_lookup_val = arith_lookup_val(numptr_m1);
13167 if (ret_arith_lookup_val)
13168 return ret_arith_lookup_val;
13170 if (op == TOK_CONDITIONAL) {
13171 numptr_m1->contidional_second_val = rez;
13173 rez = numptr_m1->val;
13174 if (op == TOK_BOR || op == TOK_OR_ASSIGN)
13176 else if (op == TOK_OR)
13177 rez = numptr_val || rez;
13178 else if (op == TOK_BAND || op == TOK_AND_ASSIGN)
13180 else if (op == TOK_BXOR || op == TOK_XOR_ASSIGN)
13182 else if (op == TOK_AND)
13183 rez = rez && numptr_val;
13184 else if (op == TOK_EQ)
13185 rez = (rez == numptr_val);
13186 else if (op == TOK_NE)
13187 rez = (rez != numptr_val);
13188 else if (op == TOK_GE)
13189 rez = (rez >= numptr_val);
13190 else if (op == TOK_RSHIFT || op == TOK_RSHIFT_ASSIGN)
13191 rez >>= numptr_val;
13192 else if (op == TOK_LSHIFT || op == TOK_LSHIFT_ASSIGN)
13193 rez <<= numptr_val;
13194 else if (op == TOK_GT)
13195 rez = (rez > numptr_val);
13196 else if (op == TOK_LT)
13197 rez = (rez < numptr_val);
13198 else if (op == TOK_LE)
13199 rez = (rez <= numptr_val);
13200 else if (op == TOK_MUL || op == TOK_MUL_ASSIGN)
13202 else if (op == TOK_ADD || op == TOK_PLUS_ASSIGN)
13204 else if (op == TOK_SUB || op == TOK_MINUS_ASSIGN)
13206 else if (op == TOK_ASSIGN || op == TOK_COMMA)
13208 else if (op == TOK_CONDITIONAL_SEP) {
13209 if (numptr_m1 == numstack) {
13210 /* protect $((expr : expr)) without "expr ? " */
13213 numptr_m1->contidional_second_val_initialized = op;
13214 numptr_m1->contidional_second_val = numptr_val;
13215 } else if (op == TOK_CONDITIONAL) {
13217 numptr_val : numptr_m1->contidional_second_val;
13218 } else if (op == TOK_EXPONENT) {
13219 if (numptr_val < 0)
13220 return -3; /* exponent less than 0 */
13225 while (numptr_val--)
13229 } else if (numptr_val==0) /* zero divisor check */
13231 else if (op == TOK_DIV || op == TOK_DIV_ASSIGN)
13233 else if (op == TOK_REM || op == TOK_REM_ASSIGN)
13236 if (tok_have_assign(op)) {
13237 char buf[sizeof(arith_t_type)*3 + 2];
13239 if (numptr_m1->var == NULL) {
13243 /* save to shell variable */
13244 #if ENABLE_ASH_MATH_SUPPORT_64
13245 snprintf(buf, sizeof(buf), "%lld", (arith_t_type) rez);
13247 snprintf(buf, sizeof(buf), "%ld", (arith_t_type) rez);
13249 setvar(numptr_m1->var, buf, 0);
13250 /* after saving, make previous value for v++ or v-- */
13251 if (op == TOK_POST_INC)
13253 else if (op == TOK_POST_DEC)
13256 numptr_m1->val = rez;
13257 /* protect geting var value, is number now */
13258 numptr_m1->var = NULL;
13264 /* longest must be first */
13265 static const char op_tokens[] ALIGN1 = {
13266 '<','<','=',0, TOK_LSHIFT_ASSIGN,
13267 '>','>','=',0, TOK_RSHIFT_ASSIGN,
13268 '<','<', 0, TOK_LSHIFT,
13269 '>','>', 0, TOK_RSHIFT,
13270 '|','|', 0, TOK_OR,
13271 '&','&', 0, TOK_AND,
13272 '!','=', 0, TOK_NE,
13273 '<','=', 0, TOK_LE,
13274 '>','=', 0, TOK_GE,
13275 '=','=', 0, TOK_EQ,
13276 '|','=', 0, TOK_OR_ASSIGN,
13277 '&','=', 0, TOK_AND_ASSIGN,
13278 '*','=', 0, TOK_MUL_ASSIGN,
13279 '/','=', 0, TOK_DIV_ASSIGN,
13280 '%','=', 0, TOK_REM_ASSIGN,
13281 '+','=', 0, TOK_PLUS_ASSIGN,
13282 '-','=', 0, TOK_MINUS_ASSIGN,
13283 '-','-', 0, TOK_POST_DEC,
13284 '^','=', 0, TOK_XOR_ASSIGN,
13285 '+','+', 0, TOK_POST_INC,
13286 '*','*', 0, TOK_EXPONENT,
13290 '=', 0, TOK_ASSIGN,
13302 '?', 0, TOK_CONDITIONAL,
13303 ':', 0, TOK_CONDITIONAL_SEP,
13304 ')', 0, TOK_RPAREN,
13305 '(', 0, TOK_LPAREN,
13309 #define endexpression (&op_tokens[sizeof(op_tokens)-7])
13312 arith(const char *expr, int *perrcode)
13314 char arithval; /* Current character under analysis */
13315 operator lasttok, op;
13317 operator *stack, *stackptr;
13318 const char *p = endexpression;
13320 v_n_t *numstack, *numstackptr;
13321 unsigned datasizes = strlen(expr) + 2;
13323 /* Stack of integers */
13324 /* The proof that there can be no more than strlen(startbuf)/2+1 integers
13325 * in any given correct or incorrect expression is left as an exercise to
13327 numstackptr = numstack = alloca((datasizes / 2) * sizeof(numstack[0]));
13328 /* Stack of operator tokens */
13329 stackptr = stack = alloca(datasizes * sizeof(stack[0]));
13331 *stackptr++ = lasttok = TOK_LPAREN; /* start off with a left paren */
13332 *perrcode = errcode = 0;
13336 if (arithval == 0) {
13337 if (p == endexpression) {
13338 /* Null expression. */
13342 /* This is only reached after all tokens have been extracted from the
13343 * input stream. If there are still tokens on the operator stack, they
13344 * are to be applied in order. At the end, there should be a final
13345 * result on the integer stack */
13347 if (expr != endexpression + 1) {
13348 /* If we haven't done so already, */
13349 /* append a closing right paren */
13350 expr = endexpression;
13351 /* and let the loop process it. */
13354 /* At this point, we're done with the expression. */
13355 if (numstackptr != numstack+1) {
13356 /* ... but if there isn't, it's bad */
13361 if (numstack->var) {
13362 /* expression is $((var)) only, lookup now */
13363 errcode = arith_lookup_val(numstack);
13366 *perrcode = errcode;
13367 return numstack->val;
13370 /* Continue processing the expression. */
13371 if (arith_isspace(arithval)) {
13372 /* Skip whitespace */
13375 p = endofname(expr);
13377 size_t var_name_size = (p-expr) + 1; /* trailing zero */
13379 numstackptr->var = alloca(var_name_size);
13380 safe_strncpy(numstackptr->var, expr, var_name_size);
13383 numstackptr->contidional_second_val_initialized = 0;
13388 if (isdigit(arithval)) {
13389 numstackptr->var = NULL;
13390 #if ENABLE_ASH_MATH_SUPPORT_64
13391 numstackptr->val = strtoll(expr, (char **) &expr, 0);
13393 numstackptr->val = strtol(expr, (char **) &expr, 0);
13397 for (p = op_tokens; ; p++) {
13401 /* strange operator not found */
13404 for (o = expr; *p && *o == *p; p++)
13411 /* skip tail uncompared token */
13414 /* skip zero delim */
13419 /* post grammar: a++ reduce to num */
13420 if (lasttok == TOK_POST_INC || lasttok == TOK_POST_DEC)
13423 /* Plus and minus are binary (not unary) _only_ if the last
13424 * token was as number, or a right paren (which pretends to be
13425 * a number, since it evaluates to one). Think about it.
13426 * It makes sense. */
13427 if (lasttok != TOK_NUM) {
13443 /* We don't want a unary operator to cause recursive descent on the
13444 * stack, because there can be many in a row and it could cause an
13445 * operator to be evaluated before its argument is pushed onto the
13446 * integer stack. */
13447 /* But for binary operators, "apply" everything on the operator
13448 * stack until we find an operator with a lesser priority than the
13449 * one we have just extracted. */
13450 /* Left paren is given the lowest priority so it will never be
13451 * "applied" in this way.
13452 * if associativity is right and priority eq, applied also skip
13455 if ((prec > 0 && prec < UNARYPREC) || prec == SPEC_PREC) {
13456 /* not left paren or unary */
13457 if (lasttok != TOK_NUM) {
13458 /* binary op must be preceded by a num */
13461 while (stackptr != stack) {
13462 if (op == TOK_RPAREN) {
13463 /* The algorithm employed here is simple: while we don't
13464 * hit an open paren nor the bottom of the stack, pop
13465 * tokens and apply them */
13466 if (stackptr[-1] == TOK_LPAREN) {
13468 /* Any operator directly after a */
13470 /* close paren should consider itself binary */
13474 operator prev_prec = PREC(stackptr[-1]);
13476 convert_prec_is_assing(prec);
13477 convert_prec_is_assing(prev_prec);
13478 if (prev_prec < prec)
13480 /* check right assoc */
13481 if (prev_prec == prec && is_right_associativity(prec))
13484 errcode = arith_apply(*--stackptr, numstack, &numstackptr);
13485 if (errcode) goto ret;
13487 if (op == TOK_RPAREN) {
13492 /* Push this operator to the stack and remember it. */
13493 *stackptr++ = lasttok = op;
13498 #endif /* ASH_MATH_SUPPORT */
13501 /* ============ main() and helpers */
13504 * Called to exit the shell.
13506 static void exitshell(void) NORETURN;
13514 status = exitstatus;
13515 TRACE(("pid %d, exitshell(%d)\n", getpid(), status));
13516 if (setjmp(loc.loc)) {
13517 if (exception == EXEXIT)
13518 /* dash bug: it just does _exit(exitstatus) here
13519 * but we have to do setjobctl(0) first!
13520 * (bug is still not fixed in dash-0.5.3 - if you run dash
13521 * under Midnight Commander, on exit from dash MC is backgrounded) */
13522 status = exitstatus;
13525 exception_handler = &loc;
13531 flush_stdout_stderr();
13541 /* from input.c: */
13542 basepf.next_to_pgetc = basepf.buf = basebuf;
13545 signal(SIGCHLD, SIG_DFL);
13550 char ppid[sizeof(int)*3 + 1];
13552 struct stat st1, st2;
13555 for (envp = environ; envp && *envp; envp++) {
13556 if (strchr(*envp, '=')) {
13557 setvareq(*envp, VEXPORT|VTEXTFIXED);
13561 snprintf(ppid, sizeof(ppid), "%u", (unsigned) getppid());
13562 setvar("PPID", ppid, 0);
13564 p = lookupvar("PWD");
13566 if (*p != '/' || stat(p, &st1) || stat(".", &st2)
13567 || st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino)
13574 * Process the shell command line arguments.
13577 procargs(char **argv)
13580 const char *xminusc;
13585 /* if (xargv[0]) - mmm, this is always true! */
13587 for (i = 0; i < NOPTS; i++)
13591 /* it already printed err message */
13592 raise_exception(EXERROR);
13596 if (*xargv == NULL) {
13598 ash_msg_and_raise_error(bb_msg_requires_arg, "-c");
13601 if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
13605 for (i = 0; i < NOPTS; i++)
13606 if (optlist[i] == 2)
13611 /* POSIX 1003.2: first arg after -c cmd is $0, remainder $1... */
13616 } else if (!sflag) {
13617 setinputfile(*xargv, 0);
13620 commandname = arg0;
13623 shellparam.p = xargv;
13624 #if ENABLE_ASH_GETOPTS
13625 shellparam.optind = 1;
13626 shellparam.optoff = -1;
13628 /* assert(shellparam.malloced == 0 && shellparam.nparam == 0); */
13630 shellparam.nparam++;
13637 * Read /etc/profile or .profile.
13640 read_profile(const char *name)
13644 if (setinputfile(name, INPUT_PUSH_FILE | INPUT_NOFILE_OK) < 0)
13653 * This routine is called when an error or an interrupt occurs in an
13654 * interactive shell and control is returned to the main command loop.
13662 /* from input.c: */
13663 g_parsefile->left_in_buffer = 0;
13664 g_parsefile->left_in_line = 0; /* clear input buffer */
13666 /* from parser.c: */
13669 /* from redir.c: */
13670 clearredir(/*drop:*/ 0);
13674 static short profile_buf[16384];
13675 extern int etext();
13679 * Main routine. We initialize things, parse the arguments, execute
13680 * profiles if we're a login shell, and then call cmdloop to execute
13681 * commands. The setjmp call sets up the location to jump to when an
13682 * exception occurs. When an exception occurs the variable "state"
13683 * is used to figure out how far we had gotten.
13685 int ash_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
13686 int ash_main(int argc UNUSED_PARAM, char **argv)
13689 volatile int state;
13690 struct jmploc jmploc;
13691 struct stackmark smark;
13693 /* Initialize global data */
13697 #if ENABLE_ASH_ALIAS
13703 monitor(4, etext, profile_buf, sizeof(profile_buf), 50);
13706 #if ENABLE_FEATURE_EDITING
13707 line_input_state = new_line_input_t(FOR_SHELL | WITH_PATH_LOOKUP);
13710 if (setjmp(jmploc.loc)) {
13720 if (e == EXEXIT || s == 0 || iflag == 0 || shlvl)
13724 outcslow('\n', stderr);
13726 popstackmark(&smark);
13727 FORCE_INT_ON; /* enable interrupts */
13736 exception_handler = &jmploc;
13739 trace_puts("Shell args: ");
13740 trace_puts_args(argv);
13742 rootpid = getpid();
13744 #if ENABLE_ASH_RANDOM_SUPPORT
13745 /* Can use monotonic_ns() for better randomness but for now it is
13746 * not used anywhere else in busybox... so avoid bloat */
13747 random_galois_LFSR = random_LCG = rootpid + monotonic_us();
13750 setstackmark(&smark);
13753 #if ENABLE_FEATURE_EDITING_SAVEHISTORY
13755 const char *hp = lookupvar("HISTFILE");
13758 hp = lookupvar("HOME");
13760 char *defhp = concat_path_file(hp, ".ash_history");
13761 setvar("HISTFILE", defhp, 0);
13767 if (argv[0] && argv[0][0] == '-')
13771 read_profile("/etc/profile");
13774 read_profile(".profile");
13780 getuid() == geteuid() && getgid() == getegid() &&
13784 shinit = lookupvar("ENV");
13785 if (shinit != NULL && *shinit != '\0') {
13786 read_profile(shinit);
13792 evalstring(minusc, 0);
13794 if (sflag || minusc == NULL) {
13795 #if ENABLE_FEATURE_EDITING_SAVEHISTORY
13797 const char *hp = lookupvar("HISTFILE");
13800 line_input_state->hist_file = hp;
13803 state4: /* XXX ??? - why isn't this before the "if" statement */
13811 extern void _mcleanup(void);
13820 const char *applet_name = "debug stuff usage";
13821 int main(int argc, char **argv)
13823 return ash_main(argc, argv);
13829 * Copyright (c) 1989, 1991, 1993, 1994
13830 * The Regents of the University of California. All rights reserved.
13832 * This code is derived from software contributed to Berkeley by
13833 * Kenneth Almquist.
13835 * Redistribution and use in source and binary forms, with or without
13836 * modification, are permitted provided that the following conditions
13838 * 1. Redistributions of source code must retain the above copyright
13839 * notice, this list of conditions and the following disclaimer.
13840 * 2. Redistributions in binary form must reproduce the above copyright
13841 * notice, this list of conditions and the following disclaimer in the
13842 * documentation and/or other materials provided with the distribution.
13843 * 3. Neither the name of the University nor the names of its contributors
13844 * may be used to endorse or promote products derived from this software
13845 * without specific prior written permission.
13847 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
13848 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
13849 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
13850 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
13851 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
13852 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
13853 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
13854 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
13855 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
13856 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF