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];
2716 return S_I_T[indx][syntax];
2719 #else /* !USE_SIT_FUNCTION */
2721 #if ENABLE_ASH_ALIAS
2722 #define CSPCL_CIGN_CIGN_CIGN 0
2723 #define CSPCL_CWORD_CWORD_CWORD 1
2724 #define CNL_CNL_CNL_CNL 2
2725 #define CWORD_CCTL_CCTL_CWORD 3
2726 #define CDQUOTE_CENDQUOTE_CWORD_CWORD 4
2727 #define CVAR_CVAR_CWORD_CVAR 5
2728 #define CSQUOTE_CWORD_CENDQUOTE_CWORD 6
2729 #define CSPCL_CWORD_CWORD_CLP 7
2730 #define CSPCL_CWORD_CWORD_CRP 8
2731 #define CBACK_CBACK_CCTL_CBACK 9
2732 #define CBQUOTE_CBQUOTE_CWORD_CBQUOTE 10
2733 #define CENDVAR_CENDVAR_CWORD_CENDVAR 11
2734 #define CENDFILE_CENDFILE_CENDFILE_CENDFILE 12
2735 #define CWORD_CWORD_CWORD_CWORD 13
2736 #define CCTL_CCTL_CCTL_CCTL 14
2738 #define CSPCL_CWORD_CWORD_CWORD 0
2739 #define CNL_CNL_CNL_CNL 1
2740 #define CWORD_CCTL_CCTL_CWORD 2
2741 #define CDQUOTE_CENDQUOTE_CWORD_CWORD 3
2742 #define CVAR_CVAR_CWORD_CVAR 4
2743 #define CSQUOTE_CWORD_CENDQUOTE_CWORD 5
2744 #define CSPCL_CWORD_CWORD_CLP 6
2745 #define CSPCL_CWORD_CWORD_CRP 7
2746 #define CBACK_CBACK_CCTL_CBACK 8
2747 #define CBQUOTE_CBQUOTE_CWORD_CBQUOTE 9
2748 #define CENDVAR_CENDVAR_CWORD_CENDVAR 10
2749 #define CENDFILE_CENDFILE_CENDFILE_CENDFILE 11
2750 #define CWORD_CWORD_CWORD_CWORD 12
2751 #define CCTL_CCTL_CCTL_CCTL 13
2754 static const char syntax_index_table[258] = {
2755 /* BASESYNTAX_DQSYNTAX_SQSYNTAX_ARISYNTAX */
2756 /* 0 PEOF */ CENDFILE_CENDFILE_CENDFILE_CENDFILE,
2757 #if ENABLE_ASH_ALIAS
2758 /* 1 PEOA */ CSPCL_CIGN_CIGN_CIGN,
2760 /* 2 -128 0x80 */ CWORD_CWORD_CWORD_CWORD,
2761 /* 3 -127 CTLESC */ CCTL_CCTL_CCTL_CCTL,
2762 /* 4 -126 CTLVAR */ CCTL_CCTL_CCTL_CCTL,
2763 /* 5 -125 CTLENDVAR */ CCTL_CCTL_CCTL_CCTL,
2764 /* 6 -124 CTLBACKQ */ CCTL_CCTL_CCTL_CCTL,
2765 /* 7 -123 CTLQUOTE */ CCTL_CCTL_CCTL_CCTL,
2766 /* 8 -122 CTLARI */ CCTL_CCTL_CCTL_CCTL,
2767 /* 9 -121 CTLENDARI */ CCTL_CCTL_CCTL_CCTL,
2768 /* 10 -120 CTLQUOTEMARK */ CCTL_CCTL_CCTL_CCTL,
2769 /* 11 -119 */ CWORD_CWORD_CWORD_CWORD,
2770 /* 12 -118 */ CWORD_CWORD_CWORD_CWORD,
2771 /* 13 -117 */ CWORD_CWORD_CWORD_CWORD,
2772 /* 14 -116 */ CWORD_CWORD_CWORD_CWORD,
2773 /* 15 -115 */ CWORD_CWORD_CWORD_CWORD,
2774 /* 16 -114 */ CWORD_CWORD_CWORD_CWORD,
2775 /* 17 -113 */ CWORD_CWORD_CWORD_CWORD,
2776 /* 18 -112 */ CWORD_CWORD_CWORD_CWORD,
2777 /* 19 -111 */ CWORD_CWORD_CWORD_CWORD,
2778 /* 20 -110 */ CWORD_CWORD_CWORD_CWORD,
2779 /* 21 -109 */ CWORD_CWORD_CWORD_CWORD,
2780 /* 22 -108 */ CWORD_CWORD_CWORD_CWORD,
2781 /* 23 -107 */ CWORD_CWORD_CWORD_CWORD,
2782 /* 24 -106 */ CWORD_CWORD_CWORD_CWORD,
2783 /* 25 -105 */ CWORD_CWORD_CWORD_CWORD,
2784 /* 26 -104 */ CWORD_CWORD_CWORD_CWORD,
2785 /* 27 -103 */ CWORD_CWORD_CWORD_CWORD,
2786 /* 28 -102 */ CWORD_CWORD_CWORD_CWORD,
2787 /* 29 -101 */ CWORD_CWORD_CWORD_CWORD,
2788 /* 30 -100 */ CWORD_CWORD_CWORD_CWORD,
2789 /* 31 -99 */ CWORD_CWORD_CWORD_CWORD,
2790 /* 32 -98 */ CWORD_CWORD_CWORD_CWORD,
2791 /* 33 -97 */ CWORD_CWORD_CWORD_CWORD,
2792 /* 34 -96 */ CWORD_CWORD_CWORD_CWORD,
2793 /* 35 -95 */ CWORD_CWORD_CWORD_CWORD,
2794 /* 36 -94 */ CWORD_CWORD_CWORD_CWORD,
2795 /* 37 -93 */ CWORD_CWORD_CWORD_CWORD,
2796 /* 38 -92 */ CWORD_CWORD_CWORD_CWORD,
2797 /* 39 -91 */ CWORD_CWORD_CWORD_CWORD,
2798 /* 40 -90 */ CWORD_CWORD_CWORD_CWORD,
2799 /* 41 -89 */ CWORD_CWORD_CWORD_CWORD,
2800 /* 42 -88 */ CWORD_CWORD_CWORD_CWORD,
2801 /* 43 -87 */ CWORD_CWORD_CWORD_CWORD,
2802 /* 44 -86 */ CWORD_CWORD_CWORD_CWORD,
2803 /* 45 -85 */ CWORD_CWORD_CWORD_CWORD,
2804 /* 46 -84 */ CWORD_CWORD_CWORD_CWORD,
2805 /* 47 -83 */ CWORD_CWORD_CWORD_CWORD,
2806 /* 48 -82 */ CWORD_CWORD_CWORD_CWORD,
2807 /* 49 -81 */ CWORD_CWORD_CWORD_CWORD,
2808 /* 50 -80 */ CWORD_CWORD_CWORD_CWORD,
2809 /* 51 -79 */ CWORD_CWORD_CWORD_CWORD,
2810 /* 52 -78 */ CWORD_CWORD_CWORD_CWORD,
2811 /* 53 -77 */ CWORD_CWORD_CWORD_CWORD,
2812 /* 54 -76 */ CWORD_CWORD_CWORD_CWORD,
2813 /* 55 -75 */ CWORD_CWORD_CWORD_CWORD,
2814 /* 56 -74 */ CWORD_CWORD_CWORD_CWORD,
2815 /* 57 -73 */ CWORD_CWORD_CWORD_CWORD,
2816 /* 58 -72 */ CWORD_CWORD_CWORD_CWORD,
2817 /* 59 -71 */ CWORD_CWORD_CWORD_CWORD,
2818 /* 60 -70 */ CWORD_CWORD_CWORD_CWORD,
2819 /* 61 -69 */ CWORD_CWORD_CWORD_CWORD,
2820 /* 62 -68 */ CWORD_CWORD_CWORD_CWORD,
2821 /* 63 -67 */ CWORD_CWORD_CWORD_CWORD,
2822 /* 64 -66 */ CWORD_CWORD_CWORD_CWORD,
2823 /* 65 -65 */ CWORD_CWORD_CWORD_CWORD,
2824 /* 66 -64 */ CWORD_CWORD_CWORD_CWORD,
2825 /* 67 -63 */ CWORD_CWORD_CWORD_CWORD,
2826 /* 68 -62 */ CWORD_CWORD_CWORD_CWORD,
2827 /* 69 -61 */ CWORD_CWORD_CWORD_CWORD,
2828 /* 70 -60 */ CWORD_CWORD_CWORD_CWORD,
2829 /* 71 -59 */ CWORD_CWORD_CWORD_CWORD,
2830 /* 72 -58 */ CWORD_CWORD_CWORD_CWORD,
2831 /* 73 -57 */ CWORD_CWORD_CWORD_CWORD,
2832 /* 74 -56 */ CWORD_CWORD_CWORD_CWORD,
2833 /* 75 -55 */ CWORD_CWORD_CWORD_CWORD,
2834 /* 76 -54 */ CWORD_CWORD_CWORD_CWORD,
2835 /* 77 -53 */ CWORD_CWORD_CWORD_CWORD,
2836 /* 78 -52 */ CWORD_CWORD_CWORD_CWORD,
2837 /* 79 -51 */ CWORD_CWORD_CWORD_CWORD,
2838 /* 80 -50 */ CWORD_CWORD_CWORD_CWORD,
2839 /* 81 -49 */ CWORD_CWORD_CWORD_CWORD,
2840 /* 82 -48 */ CWORD_CWORD_CWORD_CWORD,
2841 /* 83 -47 */ CWORD_CWORD_CWORD_CWORD,
2842 /* 84 -46 */ CWORD_CWORD_CWORD_CWORD,
2843 /* 85 -45 */ CWORD_CWORD_CWORD_CWORD,
2844 /* 86 -44 */ CWORD_CWORD_CWORD_CWORD,
2845 /* 87 -43 */ CWORD_CWORD_CWORD_CWORD,
2846 /* 88 -42 */ CWORD_CWORD_CWORD_CWORD,
2847 /* 89 -41 */ CWORD_CWORD_CWORD_CWORD,
2848 /* 90 -40 */ CWORD_CWORD_CWORD_CWORD,
2849 /* 91 -39 */ CWORD_CWORD_CWORD_CWORD,
2850 /* 92 -38 */ CWORD_CWORD_CWORD_CWORD,
2851 /* 93 -37 */ CWORD_CWORD_CWORD_CWORD,
2852 /* 94 -36 */ CWORD_CWORD_CWORD_CWORD,
2853 /* 95 -35 */ CWORD_CWORD_CWORD_CWORD,
2854 /* 96 -34 */ CWORD_CWORD_CWORD_CWORD,
2855 /* 97 -33 */ CWORD_CWORD_CWORD_CWORD,
2856 /* 98 -32 */ CWORD_CWORD_CWORD_CWORD,
2857 /* 99 -31 */ CWORD_CWORD_CWORD_CWORD,
2858 /* 100 -30 */ CWORD_CWORD_CWORD_CWORD,
2859 /* 101 -29 */ CWORD_CWORD_CWORD_CWORD,
2860 /* 102 -28 */ CWORD_CWORD_CWORD_CWORD,
2861 /* 103 -27 */ CWORD_CWORD_CWORD_CWORD,
2862 /* 104 -26 */ CWORD_CWORD_CWORD_CWORD,
2863 /* 105 -25 */ CWORD_CWORD_CWORD_CWORD,
2864 /* 106 -24 */ CWORD_CWORD_CWORD_CWORD,
2865 /* 107 -23 */ CWORD_CWORD_CWORD_CWORD,
2866 /* 108 -22 */ CWORD_CWORD_CWORD_CWORD,
2867 /* 109 -21 */ CWORD_CWORD_CWORD_CWORD,
2868 /* 110 -20 */ CWORD_CWORD_CWORD_CWORD,
2869 /* 111 -19 */ CWORD_CWORD_CWORD_CWORD,
2870 /* 112 -18 */ CWORD_CWORD_CWORD_CWORD,
2871 /* 113 -17 */ CWORD_CWORD_CWORD_CWORD,
2872 /* 114 -16 */ CWORD_CWORD_CWORD_CWORD,
2873 /* 115 -15 */ CWORD_CWORD_CWORD_CWORD,
2874 /* 116 -14 */ CWORD_CWORD_CWORD_CWORD,
2875 /* 117 -13 */ CWORD_CWORD_CWORD_CWORD,
2876 /* 118 -12 */ CWORD_CWORD_CWORD_CWORD,
2877 /* 119 -11 */ CWORD_CWORD_CWORD_CWORD,
2878 /* 120 -10 */ CWORD_CWORD_CWORD_CWORD,
2879 /* 121 -9 */ CWORD_CWORD_CWORD_CWORD,
2880 /* 122 -8 */ CWORD_CWORD_CWORD_CWORD,
2881 /* 123 -7 */ CWORD_CWORD_CWORD_CWORD,
2882 /* 124 -6 */ CWORD_CWORD_CWORD_CWORD,
2883 /* 125 -5 */ CWORD_CWORD_CWORD_CWORD,
2884 /* 126 -4 */ CWORD_CWORD_CWORD_CWORD,
2885 /* 127 -3 */ CWORD_CWORD_CWORD_CWORD,
2886 /* 128 -2 */ CWORD_CWORD_CWORD_CWORD,
2887 /* 129 -1 */ CWORD_CWORD_CWORD_CWORD,
2888 /* 130 0 */ CWORD_CWORD_CWORD_CWORD,
2889 /* 131 1 */ CWORD_CWORD_CWORD_CWORD,
2890 /* 132 2 */ CWORD_CWORD_CWORD_CWORD,
2891 /* 133 3 */ CWORD_CWORD_CWORD_CWORD,
2892 /* 134 4 */ CWORD_CWORD_CWORD_CWORD,
2893 /* 135 5 */ CWORD_CWORD_CWORD_CWORD,
2894 /* 136 6 */ CWORD_CWORD_CWORD_CWORD,
2895 /* 137 7 */ CWORD_CWORD_CWORD_CWORD,
2896 /* 138 8 */ CWORD_CWORD_CWORD_CWORD,
2897 /* 139 9 "\t" */ CSPCL_CWORD_CWORD_CWORD,
2898 /* 140 10 "\n" */ CNL_CNL_CNL_CNL,
2899 /* 141 11 */ CWORD_CWORD_CWORD_CWORD,
2900 /* 142 12 */ CWORD_CWORD_CWORD_CWORD,
2901 /* 143 13 */ CWORD_CWORD_CWORD_CWORD,
2902 /* 144 14 */ CWORD_CWORD_CWORD_CWORD,
2903 /* 145 15 */ CWORD_CWORD_CWORD_CWORD,
2904 /* 146 16 */ CWORD_CWORD_CWORD_CWORD,
2905 /* 147 17 */ CWORD_CWORD_CWORD_CWORD,
2906 /* 148 18 */ CWORD_CWORD_CWORD_CWORD,
2907 /* 149 19 */ CWORD_CWORD_CWORD_CWORD,
2908 /* 150 20 */ CWORD_CWORD_CWORD_CWORD,
2909 /* 151 21 */ CWORD_CWORD_CWORD_CWORD,
2910 /* 152 22 */ CWORD_CWORD_CWORD_CWORD,
2911 /* 153 23 */ CWORD_CWORD_CWORD_CWORD,
2912 /* 154 24 */ CWORD_CWORD_CWORD_CWORD,
2913 /* 155 25 */ CWORD_CWORD_CWORD_CWORD,
2914 /* 156 26 */ CWORD_CWORD_CWORD_CWORD,
2915 /* 157 27 */ CWORD_CWORD_CWORD_CWORD,
2916 /* 158 28 */ CWORD_CWORD_CWORD_CWORD,
2917 /* 159 29 */ CWORD_CWORD_CWORD_CWORD,
2918 /* 160 30 */ CWORD_CWORD_CWORD_CWORD,
2919 /* 161 31 */ CWORD_CWORD_CWORD_CWORD,
2920 /* 162 32 " " */ CSPCL_CWORD_CWORD_CWORD,
2921 /* 163 33 "!" */ CWORD_CCTL_CCTL_CWORD,
2922 /* 164 34 """ */ CDQUOTE_CENDQUOTE_CWORD_CWORD,
2923 /* 165 35 "#" */ CWORD_CWORD_CWORD_CWORD,
2924 /* 166 36 "$" */ CVAR_CVAR_CWORD_CVAR,
2925 /* 167 37 "%" */ CWORD_CWORD_CWORD_CWORD,
2926 /* 168 38 "&" */ CSPCL_CWORD_CWORD_CWORD,
2927 /* 169 39 "'" */ CSQUOTE_CWORD_CENDQUOTE_CWORD,
2928 /* 170 40 "(" */ CSPCL_CWORD_CWORD_CLP,
2929 /* 171 41 ")" */ CSPCL_CWORD_CWORD_CRP,
2930 /* 172 42 "*" */ CWORD_CCTL_CCTL_CWORD,
2931 /* 173 43 "+" */ CWORD_CWORD_CWORD_CWORD,
2932 /* 174 44 "," */ CWORD_CWORD_CWORD_CWORD,
2933 /* 175 45 "-" */ CWORD_CCTL_CCTL_CWORD,
2934 /* 176 46 "." */ CWORD_CWORD_CWORD_CWORD,
2935 /* 177 47 "/" */ CWORD_CCTL_CCTL_CWORD,
2936 /* 178 48 "0" */ CWORD_CWORD_CWORD_CWORD,
2937 /* 179 49 "1" */ CWORD_CWORD_CWORD_CWORD,
2938 /* 180 50 "2" */ CWORD_CWORD_CWORD_CWORD,
2939 /* 181 51 "3" */ CWORD_CWORD_CWORD_CWORD,
2940 /* 182 52 "4" */ CWORD_CWORD_CWORD_CWORD,
2941 /* 183 53 "5" */ CWORD_CWORD_CWORD_CWORD,
2942 /* 184 54 "6" */ CWORD_CWORD_CWORD_CWORD,
2943 /* 185 55 "7" */ CWORD_CWORD_CWORD_CWORD,
2944 /* 186 56 "8" */ CWORD_CWORD_CWORD_CWORD,
2945 /* 187 57 "9" */ CWORD_CWORD_CWORD_CWORD,
2946 /* 188 58 ":" */ CWORD_CCTL_CCTL_CWORD,
2947 /* 189 59 ";" */ CSPCL_CWORD_CWORD_CWORD,
2948 /* 190 60 "<" */ CSPCL_CWORD_CWORD_CWORD,
2949 /* 191 61 "=" */ CWORD_CCTL_CCTL_CWORD,
2950 /* 192 62 ">" */ CSPCL_CWORD_CWORD_CWORD,
2951 /* 193 63 "?" */ CWORD_CCTL_CCTL_CWORD,
2952 /* 194 64 "@" */ CWORD_CWORD_CWORD_CWORD,
2953 /* 195 65 "A" */ CWORD_CWORD_CWORD_CWORD,
2954 /* 196 66 "B" */ CWORD_CWORD_CWORD_CWORD,
2955 /* 197 67 "C" */ CWORD_CWORD_CWORD_CWORD,
2956 /* 198 68 "D" */ CWORD_CWORD_CWORD_CWORD,
2957 /* 199 69 "E" */ CWORD_CWORD_CWORD_CWORD,
2958 /* 200 70 "F" */ CWORD_CWORD_CWORD_CWORD,
2959 /* 201 71 "G" */ CWORD_CWORD_CWORD_CWORD,
2960 /* 202 72 "H" */ CWORD_CWORD_CWORD_CWORD,
2961 /* 203 73 "I" */ CWORD_CWORD_CWORD_CWORD,
2962 /* 204 74 "J" */ CWORD_CWORD_CWORD_CWORD,
2963 /* 205 75 "K" */ CWORD_CWORD_CWORD_CWORD,
2964 /* 206 76 "L" */ CWORD_CWORD_CWORD_CWORD,
2965 /* 207 77 "M" */ CWORD_CWORD_CWORD_CWORD,
2966 /* 208 78 "N" */ CWORD_CWORD_CWORD_CWORD,
2967 /* 209 79 "O" */ CWORD_CWORD_CWORD_CWORD,
2968 /* 210 80 "P" */ CWORD_CWORD_CWORD_CWORD,
2969 /* 211 81 "Q" */ CWORD_CWORD_CWORD_CWORD,
2970 /* 212 82 "R" */ CWORD_CWORD_CWORD_CWORD,
2971 /* 213 83 "S" */ CWORD_CWORD_CWORD_CWORD,
2972 /* 214 84 "T" */ CWORD_CWORD_CWORD_CWORD,
2973 /* 215 85 "U" */ CWORD_CWORD_CWORD_CWORD,
2974 /* 216 86 "V" */ CWORD_CWORD_CWORD_CWORD,
2975 /* 217 87 "W" */ CWORD_CWORD_CWORD_CWORD,
2976 /* 218 88 "X" */ CWORD_CWORD_CWORD_CWORD,
2977 /* 219 89 "Y" */ CWORD_CWORD_CWORD_CWORD,
2978 /* 220 90 "Z" */ CWORD_CWORD_CWORD_CWORD,
2979 /* 221 91 "[" */ CWORD_CCTL_CCTL_CWORD,
2980 /* 222 92 "\" */ CBACK_CBACK_CCTL_CBACK,
2981 /* 223 93 "]" */ CWORD_CCTL_CCTL_CWORD,
2982 /* 224 94 "^" */ CWORD_CWORD_CWORD_CWORD,
2983 /* 225 95 "_" */ CWORD_CWORD_CWORD_CWORD,
2984 /* 226 96 "`" */ CBQUOTE_CBQUOTE_CWORD_CBQUOTE,
2985 /* 227 97 "a" */ CWORD_CWORD_CWORD_CWORD,
2986 /* 228 98 "b" */ CWORD_CWORD_CWORD_CWORD,
2987 /* 229 99 "c" */ CWORD_CWORD_CWORD_CWORD,
2988 /* 230 100 "d" */ CWORD_CWORD_CWORD_CWORD,
2989 /* 231 101 "e" */ CWORD_CWORD_CWORD_CWORD,
2990 /* 232 102 "f" */ CWORD_CWORD_CWORD_CWORD,
2991 /* 233 103 "g" */ CWORD_CWORD_CWORD_CWORD,
2992 /* 234 104 "h" */ CWORD_CWORD_CWORD_CWORD,
2993 /* 235 105 "i" */ CWORD_CWORD_CWORD_CWORD,
2994 /* 236 106 "j" */ CWORD_CWORD_CWORD_CWORD,
2995 /* 237 107 "k" */ CWORD_CWORD_CWORD_CWORD,
2996 /* 238 108 "l" */ CWORD_CWORD_CWORD_CWORD,
2997 /* 239 109 "m" */ CWORD_CWORD_CWORD_CWORD,
2998 /* 240 110 "n" */ CWORD_CWORD_CWORD_CWORD,
2999 /* 241 111 "o" */ CWORD_CWORD_CWORD_CWORD,
3000 /* 242 112 "p" */ CWORD_CWORD_CWORD_CWORD,
3001 /* 243 113 "q" */ CWORD_CWORD_CWORD_CWORD,
3002 /* 244 114 "r" */ CWORD_CWORD_CWORD_CWORD,
3003 /* 245 115 "s" */ CWORD_CWORD_CWORD_CWORD,
3004 /* 246 116 "t" */ CWORD_CWORD_CWORD_CWORD,
3005 /* 247 117 "u" */ CWORD_CWORD_CWORD_CWORD,
3006 /* 248 118 "v" */ CWORD_CWORD_CWORD_CWORD,
3007 /* 249 119 "w" */ CWORD_CWORD_CWORD_CWORD,
3008 /* 250 120 "x" */ CWORD_CWORD_CWORD_CWORD,
3009 /* 251 121 "y" */ CWORD_CWORD_CWORD_CWORD,
3010 /* 252 122 "z" */ CWORD_CWORD_CWORD_CWORD,
3011 /* 253 123 "{" */ CWORD_CWORD_CWORD_CWORD,
3012 /* 254 124 "|" */ CSPCL_CWORD_CWORD_CWORD,
3013 /* 255 125 "}" */ CENDVAR_CENDVAR_CWORD_CENDVAR,
3014 /* 256 126 "~" */ CWORD_CCTL_CCTL_CWORD,
3015 /* 257 127 */ CWORD_CWORD_CWORD_CWORD,
3018 #define SIT(c, syntax) (S_I_T[(int)syntax_index_table[((int)c)+SYNBASE]][syntax])
3020 #endif /* USE_SIT_FUNCTION */
3023 /* ============ Alias handling */
3025 #if ENABLE_ASH_ALIAS
3027 #define ALIASINUSE 1
3038 static struct alias **atab; // [ATABSIZE];
3039 #define INIT_G_alias() do { \
3040 atab = xzalloc(ATABSIZE * sizeof(atab[0])); \
3044 static struct alias **
3045 __lookupalias(const char *name) {
3046 unsigned int hashval;
3053 ch = (unsigned char)*p;
3057 ch = (unsigned char)*++p;
3059 app = &atab[hashval % ATABSIZE];
3061 for (; *app; app = &(*app)->next) {
3062 if (strcmp(name, (*app)->name) == 0) {
3070 static struct alias *
3071 lookupalias(const char *name, int check)
3073 struct alias *ap = *__lookupalias(name);
3075 if (check && ap && (ap->flag & ALIASINUSE))
3080 static struct alias *
3081 freealias(struct alias *ap)
3085 if (ap->flag & ALIASINUSE) {
3086 ap->flag |= ALIASDEAD;
3098 setalias(const char *name, const char *val)
3100 struct alias *ap, **app;
3102 app = __lookupalias(name);
3106 if (!(ap->flag & ALIASINUSE)) {
3109 ap->val = ckstrdup(val);
3110 ap->flag &= ~ALIASDEAD;
3113 ap = ckzalloc(sizeof(struct alias));
3114 ap->name = ckstrdup(name);
3115 ap->val = ckstrdup(val);
3116 /*ap->flag = 0; - ckzalloc did it */
3117 /*ap->next = NULL;*/
3124 unalias(const char *name)
3128 app = __lookupalias(name);
3132 *app = freealias(*app);
3143 struct alias *ap, **app;
3147 for (i = 0; i < ATABSIZE; i++) {
3149 for (ap = *app; ap; ap = *app) {
3150 *app = freealias(*app);
3160 printalias(const struct alias *ap)
3162 out1fmt("%s=%s\n", ap->name, single_quote(ap->val));
3166 * TODO - sort output
3169 aliascmd(int argc UNUSED_PARAM, char **argv)
3178 for (i = 0; i < ATABSIZE; i++) {
3179 for (ap = atab[i]; ap; ap = ap->next) {
3185 while ((n = *++argv) != NULL) {
3186 v = strchr(n+1, '=');
3187 if (v == NULL) { /* n+1: funny ksh stuff */
3188 ap = *__lookupalias(n);
3190 fprintf(stderr, "%s: %s not found\n", "alias", n);
3204 unaliascmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
3208 while ((i = nextopt("a")) != '\0') {
3214 for (i = 0; *argptr; argptr++) {
3215 if (unalias(*argptr)) {
3216 fprintf(stderr, "%s: %s not found\n", "unalias", *argptr);
3224 #endif /* ASH_ALIAS */
3227 /* ============ jobs.c */
3229 /* Mode argument to forkshell. Don't change FORK_FG or FORK_BG. */
3232 #define FORK_NOJOB 2
3234 /* mode flags for showjob(s) */
3235 #define SHOW_PGID 0x01 /* only show pgid - for jobs -p */
3236 #define SHOW_PID 0x04 /* include process pid */
3237 #define SHOW_CHANGED 0x08 /* only jobs whose state has changed */
3240 * A job structure contains information about a job. A job is either a
3241 * single process or a set of processes contained in a pipeline. In the
3242 * latter case, pidlist will be non-NULL, and will point to a -1 terminated
3247 pid_t pid; /* process id */
3248 int status; /* last process status from wait() */
3249 char *cmd; /* text of command being run */
3253 struct procstat ps0; /* status of process */
3254 struct procstat *ps; /* status or processes when more than one */
3256 int stopstatus; /* status of a stopped job */
3259 nprocs: 16, /* number of processes */
3261 #define JOBRUNNING 0 /* at least one proc running */
3262 #define JOBSTOPPED 1 /* all procs are stopped */
3263 #define JOBDONE 2 /* all procs are completed */
3265 sigint: 1, /* job was killed by SIGINT */
3266 jobctl: 1, /* job running under job control */
3268 waited: 1, /* true if this entry has been waited for */
3269 used: 1, /* true if this entry is in used */
3270 changed: 1; /* true if status has changed */
3271 struct job *prev_job; /* previous job */
3274 static struct job *makejob(/*union node *,*/ int);
3276 #define forkshell(job, node, mode) forkshell(job, mode)
3278 static int forkshell(struct job *, union node *, int);
3279 static int waitforjob(struct job *);
3282 enum { doing_jobctl = 0 };
3283 #define setjobctl(on) do {} while (0)
3285 static smallint doing_jobctl; //references:8
3286 static void setjobctl(int);
3290 * Set the signal handler for the specified signal. The routine figures
3291 * out what it should be set to.
3294 setsignal(int signo)
3297 char cur_act, new_act;
3298 struct sigaction act;
3302 if (t != NULL) { /* trap for this sig is set */
3304 if (t[0] == '\0') /* trap is "": ignore this sig */
3308 if (rootshell && new_act == S_DFL) {
3311 if (iflag || minusc || sflag == 0)
3320 * "In all cases, bash ignores SIGQUIT. Non-builtin
3321 * commands run by bash have signal handlers
3322 * set to the values inherited by the shell
3323 * from its parent". */
3339 //TODO: if !rootshell, we reset SIGQUIT to DFL,
3340 //whereas we have to restore it to what shell got on entry
3341 //from the parent. See comment above
3343 t = &sigmode[signo - 1];
3346 /* current setting is not yet known */
3347 if (sigaction(signo, NULL, &act)) {
3348 /* pretend it worked; maybe we should give a warning,
3349 * but other shells don't. We don't alter sigmode,
3350 * so we retry every time.
3351 * btw, in Linux it never fails. --vda */
3354 if (act.sa_handler == SIG_IGN) {
3355 cur_act = S_HARD_IGN;
3357 && (signo == SIGTSTP || signo == SIGTTIN || signo == SIGTTOU)
3359 cur_act = S_IGN; /* don't hard ignore these */
3363 if (cur_act == S_HARD_IGN || cur_act == new_act)
3366 act.sa_handler = SIG_DFL;
3369 act.sa_handler = onsig;
3370 act.sa_flags = 0; /* matters only if !DFL and !IGN */
3371 sigfillset(&act.sa_mask); /* ditto */
3374 act.sa_handler = SIG_IGN;
3377 sigaction_set(signo, &act);
3382 /* mode flags for set_curjob */
3383 #define CUR_DELETE 2
3384 #define CUR_RUNNING 1
3385 #define CUR_STOPPED 0
3387 /* mode flags for dowait */
3388 #define DOWAIT_NONBLOCK WNOHANG
3389 #define DOWAIT_BLOCK 0
3392 /* pgrp of shell on invocation */
3393 static int initialpgrp; //references:2
3394 static int ttyfd = -1; //5
3397 static struct job *jobtab; //5
3399 static unsigned njobs; //4
3401 static struct job *curjob; //lots
3402 /* number of presumed living untracked jobs */
3403 static int jobless; //4
3406 set_curjob(struct job *jp, unsigned mode)
3409 struct job **jpp, **curp;
3411 /* first remove from list */
3412 jpp = curp = &curjob;
3417 jpp = &jp1->prev_job;
3419 *jpp = jp1->prev_job;
3421 /* Then re-insert in correct position */
3429 /* job being deleted */
3432 /* newly created job or backgrounded job,
3433 put after all stopped jobs. */
3437 if (!jp1 || jp1->state != JOBSTOPPED)
3440 jpp = &jp1->prev_job;
3446 /* newly stopped job - becomes curjob */
3447 jp->prev_job = *jpp;
3455 jobno(const struct job *jp)
3457 return jp - jobtab + 1;
3462 * Convert a job name to a job structure.
3465 #define getjob(name, getctl) getjob(name)
3468 getjob(const char *name, int getctl)
3472 const char *err_msg = "No such job: %s";
3476 char *(*match)(const char *, const char *);
3491 if (c == '+' || c == '%') {
3493 err_msg = "No current job";
3499 err_msg = "No previous job";
3508 // TODO: number() instead? It does error checking...
3511 jp = jobtab + num - 1;
3528 if (match(jp->ps[0].cmd, p)) {
3532 err_msg = "%s: ambiguous";
3539 err_msg = "job %s not created under job control";
3540 if (getctl && jp->jobctl == 0)
3545 ash_msg_and_raise_error(err_msg, name);
3549 * Mark a job structure as unused.
3552 freejob(struct job *jp)
3554 struct procstat *ps;
3558 for (i = jp->nprocs, ps = jp->ps; --i >= 0; ps++) {
3559 if (ps->cmd != nullstr)
3562 if (jp->ps != &jp->ps0)
3565 set_curjob(jp, CUR_DELETE);
3571 xtcsetpgrp(int fd, pid_t pgrp)
3573 if (tcsetpgrp(fd, pgrp))
3574 ash_msg_and_raise_error("can't set tty process group (%m)");
3578 * Turn job control on and off.
3580 * Note: This code assumes that the third arg to ioctl is a character
3581 * pointer, which is true on Berkeley systems but not System V. Since
3582 * System V doesn't have job control yet, this isn't a problem now.
3584 * Called with interrupts off.
3592 if (on == doing_jobctl || rootshell == 0)
3596 ofd = fd = open(_PATH_TTY, O_RDWR);
3598 /* BTW, bash will try to open(ttyname(0)) if open("/dev/tty") fails.
3599 * That sometimes helps to acquire controlling tty.
3600 * Obviously, a workaround for bugs when someone
3601 * failed to provide a controlling tty to bash! :) */
3607 fd = fcntl(fd, F_DUPFD, 10);
3612 /* fd is a tty at this point */
3613 close_on_exec_on(fd);
3614 do { /* while we are in the background */
3615 pgrp = tcgetpgrp(fd);
3618 ash_msg("can't access tty; job control turned off");
3622 if (pgrp == getpgrp())
3633 xtcsetpgrp(fd, pgrp);
3635 /* turning job control off */
3638 /* was xtcsetpgrp, but this can make exiting ash
3639 * loop forever if pty is already deleted */
3640 tcsetpgrp(fd, pgrp);
3655 killcmd(int argc, char **argv)
3658 if (argv[1] && strcmp(argv[1], "-l") != 0) {
3660 if (argv[i][0] == '%') {
3661 struct job *jp = getjob(argv[i], 0);
3662 unsigned pid = jp->ps[0].pid;
3663 /* Enough space for ' -NNN<nul>' */
3664 argv[i] = alloca(sizeof(int)*3 + 3);
3665 /* kill_main has matching code to expect
3666 * leading space. Needed to not confuse
3667 * negative pids with "kill -SIGNAL_NO" syntax */
3668 sprintf(argv[i], " -%u", pid);
3670 } while (argv[++i]);
3672 return kill_main(argc, argv);
3676 showpipe(struct job *jp, FILE *out)
3678 struct procstat *sp;
3679 struct procstat *spend;
3681 spend = jp->ps + jp->nprocs;
3682 for (sp = jp->ps + 1; sp < spend; sp++)
3683 fprintf(out, " | %s", sp->cmd);
3684 outcslow('\n', out);
3685 flush_stdout_stderr();
3690 restartjob(struct job *jp, int mode)
3692 struct procstat *ps;
3698 if (jp->state == JOBDONE)
3700 jp->state = JOBRUNNING;
3702 if (mode == FORK_FG)
3703 xtcsetpgrp(ttyfd, pgid);
3704 killpg(pgid, SIGCONT);
3708 if (WIFSTOPPED(ps->status)) {
3714 status = (mode == FORK_FG) ? waitforjob(jp) : 0;
3720 fg_bgcmd(int argc UNUSED_PARAM, char **argv)
3727 mode = (**argv == 'f') ? FORK_FG : FORK_BG;
3732 jp = getjob(*argv, 1);
3733 if (mode == FORK_BG) {
3734 set_curjob(jp, CUR_RUNNING);
3735 fprintf(out, "[%d] ", jobno(jp));
3737 outstr(jp->ps->cmd, out);
3739 retval = restartjob(jp, mode);
3740 } while (*argv && *++argv);
3746 sprint_status(char *s, int status, int sigonly)
3752 if (!WIFEXITED(status)) {
3754 if (WIFSTOPPED(status))
3755 st = WSTOPSIG(status);
3758 st = WTERMSIG(status);
3760 if (st == SIGINT || st == SIGPIPE)
3763 if (WIFSTOPPED(status))
3768 col = fmtstr(s, 32, strsignal(st));
3769 if (WCOREDUMP(status)) {
3770 col += fmtstr(s + col, 16, " (core dumped)");
3772 } else if (!sigonly) {
3773 st = WEXITSTATUS(status);
3775 col = fmtstr(s, 16, "Done(%d)", st);
3777 col = fmtstr(s, 16, "Done");
3784 dowait(int wait_flags, struct job *job)
3789 struct job *thisjob;
3792 TRACE(("dowait(0x%x) called\n", wait_flags));
3794 /* Do a wait system call. If job control is compiled in, we accept
3795 * stopped processes. wait_flags may have WNOHANG, preventing blocking.
3796 * NB: _not_ safe_waitpid, we need to detect EINTR */
3797 pid = waitpid(-1, &status,
3798 (doing_jobctl ? (wait_flags | WUNTRACED) : wait_flags));
3799 TRACE(("wait returns pid=%d, status=0x%x\n", pid, status));
3805 for (jp = curjob; jp; jp = jp->prev_job) {
3806 struct procstat *sp;
3807 struct procstat *spend;
3808 if (jp->state == JOBDONE)
3811 spend = jp->ps + jp->nprocs;
3814 if (sp->pid == pid) {
3815 TRACE(("Job %d: changing status of proc %d "
3816 "from 0x%x to 0x%x\n",
3817 jobno(jp), pid, sp->status, status));
3818 sp->status = status;
3821 if (sp->status == -1)
3824 if (state == JOBRUNNING)
3826 if (WIFSTOPPED(sp->status)) {
3827 jp->stopstatus = sp->status;
3831 } while (++sp < spend);
3836 if (!WIFSTOPPED(status))
3842 if (state != JOBRUNNING) {
3843 thisjob->changed = 1;
3845 if (thisjob->state != state) {
3846 TRACE(("Job %d: changing state from %d to %d\n",
3847 jobno(thisjob), thisjob->state, state));
3848 thisjob->state = state;
3850 if (state == JOBSTOPPED) {
3851 set_curjob(thisjob, CUR_STOPPED);
3860 if (thisjob && thisjob == job) {
3864 len = sprint_status(s, status, 1);
3875 blocking_wait_with_raise_on_sig(struct job *job)
3877 pid_t pid = dowait(DOWAIT_BLOCK, job);
3878 if (pid <= 0 && pendingsig)
3879 raise_exception(EXSIG);
3885 showjob(FILE *out, struct job *jp, int mode)
3887 struct procstat *ps;
3888 struct procstat *psend;
3895 if (mode & SHOW_PGID) {
3896 /* just output process (group) id of pipeline */
3897 fprintf(out, "%d\n", ps->pid);
3901 col = fmtstr(s, 16, "[%d] ", jobno(jp));
3906 else if (curjob && jp == curjob->prev_job)
3909 if (mode & SHOW_PID)
3910 col += fmtstr(s + col, 16, "%d ", ps->pid);
3912 psend = ps + jp->nprocs;
3914 if (jp->state == JOBRUNNING) {
3915 strcpy(s + col, "Running");
3916 col += sizeof("Running") - 1;
3918 int status = psend[-1].status;
3919 if (jp->state == JOBSTOPPED)
3920 status = jp->stopstatus;
3921 col += sprint_status(s + col, status, 0);
3927 /* for each process */
3928 col = fmtstr(s, 48, " |\n%*c%d ", indent_col, ' ', ps->pid) - 3;
3930 fprintf(out, "%s%*c%s",
3931 s, 33 - col >= 0 ? 33 - col : 0, ' ', ps->cmd
3933 if (!(mode & SHOW_PID)) {
3937 if (++ps == psend) {
3938 outcslow('\n', out);
3945 if (jp->state == JOBDONE) {
3946 TRACE(("showjob: freeing job %d\n", jobno(jp)));
3952 * Print a list of jobs. If "change" is nonzero, only print jobs whose
3953 * statuses have changed since the last call to showjobs.
3956 showjobs(FILE *out, int mode)
3960 TRACE(("showjobs(%x) called\n", mode));
3962 /* Handle all finished jobs */
3963 while (dowait(DOWAIT_NONBLOCK, NULL) > 0)
3966 for (jp = curjob; jp; jp = jp->prev_job) {
3967 if (!(mode & SHOW_CHANGED) || jp->changed) {
3968 showjob(out, jp, mode);
3974 jobscmd(int argc UNUSED_PARAM, char **argv)
3979 while ((m = nextopt("lp"))) {
3989 showjob(stdout, getjob(*argv,0), mode);
3992 showjobs(stdout, mode);
3999 getstatus(struct job *job)
4004 status = job->ps[job->nprocs - 1].status;
4005 retval = WEXITSTATUS(status);
4006 if (!WIFEXITED(status)) {
4008 retval = WSTOPSIG(status);
4009 if (!WIFSTOPPED(status))
4012 /* XXX: limits number of signals */
4013 retval = WTERMSIG(status);
4015 if (retval == SIGINT)
4021 TRACE(("getstatus: job %d, nproc %d, status %x, retval %x\n",
4022 jobno(job), job->nprocs, status, retval));
4027 waitcmd(int argc UNUSED_PARAM, char **argv)
4036 raise_exception(EXSIG);
4043 /* wait for all jobs */
4047 if (!jp) /* no running procs */
4049 if (jp->state == JOBRUNNING)
4055 * "When bash is waiting for an asynchronous command via
4056 * the wait builtin, the reception of a signal for which a trap
4057 * has been set will cause the wait builtin to return immediately
4058 * with an exit status greater than 128, immediately after which
4059 * the trap is executed."
4060 * Do we do it that way? */
4061 blocking_wait_with_raise_on_sig(NULL);
4067 if (**argv != '%') {
4068 pid_t pid = number(*argv);
4073 if (job->ps[job->nprocs - 1].pid == pid)
4075 job = job->prev_job;
4078 job = getjob(*argv, 0);
4079 /* loop until process terminated or stopped */
4080 while (job->state == JOBRUNNING)
4081 blocking_wait_with_raise_on_sig(NULL);
4083 retval = getstatus(job);
4096 struct job *jp, *jq;
4098 len = njobs * sizeof(*jp);
4100 jp = ckrealloc(jq, len + 4 * sizeof(*jp));
4102 offset = (char *)jp - (char *)jq;
4104 /* Relocate pointers */
4107 jq = (struct job *)((char *)jq + l);
4111 #define joff(p) ((struct job *)((char *)(p) + l))
4112 #define jmove(p) (p) = (void *)((char *)(p) + offset)
4113 if (joff(jp)->ps == &jq->ps0)
4114 jmove(joff(jp)->ps);
4115 if (joff(jp)->prev_job)
4116 jmove(joff(jp)->prev_job);
4126 jp = (struct job *)((char *)jp + len);
4130 } while (--jq >= jp);
4135 * Return a new job structure.
4136 * Called with interrupts off.
4139 makejob(/*union node *node,*/ int nprocs)
4144 for (i = njobs, jp = jobtab; ; jp++) {
4151 if (jp->state != JOBDONE || !jp->waited)
4160 memset(jp, 0, sizeof(*jp));
4162 /* jp->jobctl is a bitfield.
4163 * "jp->jobctl |= jobctl" likely to give awful code */
4167 jp->prev_job = curjob;
4172 jp->ps = ckmalloc(nprocs * sizeof(struct procstat));
4174 TRACE(("makejob(%d) returns %%%d\n", nprocs,
4181 * Return a string identifying a command (to be printed by the
4184 static char *cmdnextc;
4187 cmdputs(const char *s)
4189 static const char vstype[VSTYPE + 1][3] = {
4190 "", "}", "-", "+", "?", "=",
4191 "%", "%%", "#", "##"
4192 USE_ASH_BASH_COMPAT(, ":", "/", "//")
4195 const char *p, *str;
4196 char c, cc[2] = " ";
4201 nextc = makestrspace((strlen(s) + 1) * 8, cmdnextc);
4203 while ((c = *p++) != 0) {
4211 if ((subtype & VSTYPE) == VSLENGTH)
4215 if (!(subtype & VSQUOTE) == !(quoted & 1))
4221 str = "\"}" + !(quoted & 1);
4228 case CTLBACKQ+CTLQUOTE:
4231 #if ENABLE_ASH_MATH_SUPPORT
4246 if ((subtype & VSTYPE) != VSNORMAL)
4248 str = vstype[subtype & VSTYPE];
4249 if (subtype & VSNUL)
4258 /* These can only happen inside quotes */
4271 while ((c = *str++)) {
4276 USTPUTC('"', nextc);
4282 /* cmdtxt() and cmdlist() call each other */
4283 static void cmdtxt(union node *n);
4286 cmdlist(union node *np, int sep)
4288 for (; np; np = np->narg.next) {
4292 if (sep && np->narg.next)
4298 cmdtxt(union node *n)
4301 struct nodelist *lp;
4312 lp = n->npipe.cmdlist;
4330 cmdtxt(n->nbinary.ch1);
4346 cmdtxt(n->nif.test);
4349 if (n->nif.elsepart) {
4352 n = n->nif.elsepart;
4368 cmdtxt(n->nbinary.ch1);
4378 cmdputs(n->nfor.var);
4380 cmdlist(n->nfor.args, 1);
4385 cmdputs(n->narg.text);
4389 cmdlist(n->ncmd.args, 1);
4390 cmdlist(n->ncmd.redirect, 0);
4403 cmdputs(n->ncase.expr->narg.text);
4405 for (np = n->ncase.cases; np; np = np->nclist.next) {
4406 cmdtxt(np->nclist.pattern);
4408 cmdtxt(np->nclist.body);
4422 #if ENABLE_ASH_BASH_COMPAT
4437 cmdputs(utoa(n->nfile.fd));
4439 if (n->type == NTOFD || n->type == NFROMFD) {
4440 cmdputs(utoa(n->ndup.dupfd));
4449 commandtext(union node *n)
4453 STARTSTACKSTR(cmdnextc);
4455 name = stackblock();
4456 TRACE(("commandtext: name %p, end %p\n\t\"%s\"\n",
4457 name, cmdnextc, cmdnextc));
4458 return ckstrdup(name);
4463 * Fork off a subshell. If we are doing job control, give the subshell its
4464 * own process group. Jp is a job structure that the job is to be added to.
4465 * N is the command that will be evaluated by the child. Both jp and n may
4466 * be NULL. The mode parameter can be one of the following:
4467 * FORK_FG - Fork off a foreground process.
4468 * FORK_BG - Fork off a background process.
4469 * FORK_NOJOB - Like FORK_FG, but don't give the process its own
4470 * process group even if job control is on.
4472 * When job control is turned off, background processes have their standard
4473 * input redirected to /dev/null (except for the second and later processes
4476 * Called with interrupts off.
4479 * Clear traps on a fork.
4486 for (tp = trap; tp < &trap[NSIG]; tp++) {
4487 if (*tp && **tp) { /* trap not NULL or "" (SIG_IGN) */
4492 setsignal(tp - trap);
4498 /* Lives far away from here, needed for forkchild */
4499 static void closescript(void);
4501 /* Called after fork(), in child */
4503 forkchild(struct job *jp, /*union node *n,*/ int mode)
4507 TRACE(("Child shell %d\n", getpid()));
4511 /* man bash: "Non-builtin commands run by bash have signal handlers
4512 * set to the values inherited by the shell from its parent".
4513 * Do we do it correctly? */
4518 /* do job control only in root shell */
4520 if (mode != FORK_NOJOB && jp->jobctl && !oldlvl) {
4523 if (jp->nprocs == 0)
4526 pgrp = jp->ps[0].pid;
4527 /* this can fail because we are doing it in the parent also */
4529 if (mode == FORK_FG)
4530 xtcsetpgrp(ttyfd, pgrp);
4535 if (mode == FORK_BG) {
4536 /* man bash: "When job control is not in effect,
4537 * asynchronous commands ignore SIGINT and SIGQUIT" */
4540 if (jp->nprocs == 0) {
4542 if (open(bb_dev_null, O_RDONLY) != 0)
4543 ash_msg_and_raise_error("can't open %s", bb_dev_null);
4547 if (iflag) { /* why if iflag only? */
4552 * "In all cases, bash ignores SIGQUIT. Non-builtin
4553 * commands run by bash have signal handlers
4554 * set to the values inherited by the shell
4556 * Take care of the second rule: */
4559 for (jp = curjob; jp; jp = jp->prev_job)
4564 /* Called after fork(), in parent */
4566 #define forkparent(jp, n, mode, pid) forkparent(jp, mode, pid)
4569 forkparent(struct job *jp, union node *n, int mode, pid_t pid)
4571 TRACE(("In parent shell: child = %d\n", pid));
4573 while (jobless && dowait(DOWAIT_NONBLOCK, NULL) > 0)
4579 if (mode != FORK_NOJOB && jp->jobctl) {
4582 if (jp->nprocs == 0)
4585 pgrp = jp->ps[0].pid;
4586 /* This can fail because we are doing it in the child also */
4590 if (mode == FORK_BG) {
4591 backgndpid = pid; /* set $! */
4592 set_curjob(jp, CUR_RUNNING);
4595 struct procstat *ps = &jp->ps[jp->nprocs++];
4600 if (doing_jobctl && n)
4601 ps->cmd = commandtext(n);
4607 forkshell(struct job *jp, union node *n, int mode)
4611 TRACE(("forkshell(%%%d, %p, %d) called\n", jobno(jp), n, mode));
4614 TRACE(("Fork failed, errno=%d", errno));
4617 ash_msg_and_raise_error("can't fork");
4620 forkchild(jp, /*n,*/ mode);
4622 forkparent(jp, n, mode, pid);
4627 * Wait for job to finish.
4629 * Under job control we have the problem that while a child process
4630 * is running interrupts generated by the user are sent to the child
4631 * but not to the shell. This means that an infinite loop started by
4632 * an interactive user may be hard to kill. With job control turned off,
4633 * an interactive user may place an interactive program inside a loop.
4634 * If the interactive program catches interrupts, the user doesn't want
4635 * these interrupts to also abort the loop. The approach we take here
4636 * is to have the shell ignore interrupt signals while waiting for a
4637 * foreground process to terminate, and then send itself an interrupt
4638 * signal if the child process was terminated by an interrupt signal.
4639 * Unfortunately, some programs want to do a bit of cleanup and then
4640 * exit on interrupt; unless these processes terminate themselves by
4641 * sending a signal to themselves (instead of calling exit) they will
4642 * confuse this approach.
4644 * Called with interrupts off.
4647 waitforjob(struct job *jp)
4651 TRACE(("waitforjob(%%%d) called\n", jobno(jp)));
4654 while (jp->state == JOBRUNNING) {
4655 /* In non-interactive shells, we _can_ get
4656 * a keyboard signal here and be EINTRed,
4657 * but we just loop back, waiting for command to complete.
4660 * "If bash is waiting for a command to complete and receives
4661 * a signal for which a trap has been set, the trap
4662 * will not be executed until the command completes."
4664 * Reality is that even if trap is not set, bash
4665 * will not act on the signal until command completes.
4666 * Try this. sleep5intoff.c:
4667 * #include <signal.h>
4668 * #include <unistd.h>
4671 * sigemptyset(&set);
4672 * sigaddset(&set, SIGINT);
4673 * sigaddset(&set, SIGQUIT);
4674 * sigprocmask(SIG_BLOCK, &set, NULL);
4678 * $ bash -c './sleep5intoff; echo hi'
4679 * ^C^C^C^C <--- pressing ^C once a second
4681 * $ bash -c './sleep5intoff; echo hi'
4682 * ^\^\^\^\hi <--- pressing ^\ (SIGQUIT)
4685 dowait(DOWAIT_BLOCK, jp);
4692 xtcsetpgrp(ttyfd, rootpid);
4694 * This is truly gross.
4695 * If we're doing job control, then we did a TIOCSPGRP which
4696 * caused us (the shell) to no longer be in the controlling
4697 * session -- so we wouldn't have seen any ^C/SIGINT. So, we
4698 * intuit from the subprocess exit status whether a SIGINT
4699 * occurred, and if so interrupt ourselves. Yuck. - mycroft
4701 if (jp->sigint) /* TODO: do the same with all signals */
4702 raise(SIGINT); /* ... by raise(jp->sig) instead? */
4704 if (jp->state == JOBDONE)
4711 * return 1 if there are stopped jobs, otherwise 0
4723 if (jp && jp->state == JOBSTOPPED) {
4724 out2str("You have stopped jobs.\n");
4733 /* ============ redir.c
4735 * Code for dealing with input/output redirection.
4738 #define EMPTY -2 /* marks an unused slot in redirtab */
4739 #define CLOSED -3 /* marks a slot of previously-closed fd */
4742 * Open a file in noclobber mode.
4743 * The code was copied from bash.
4746 noclobberopen(const char *fname)
4749 struct stat finfo, finfo2;
4752 * If the file exists and is a regular file, return an error
4755 r = stat(fname, &finfo);
4756 if (r == 0 && S_ISREG(finfo.st_mode)) {
4762 * If the file was not present (r != 0), make sure we open it
4763 * exclusively so that if it is created before we open it, our open
4764 * will fail. Make sure that we do not truncate an existing file.
4765 * Note that we don't turn on O_EXCL unless the stat failed -- if the
4766 * file was not a regular file, we leave O_EXCL off.
4769 return open(fname, O_WRONLY|O_CREAT|O_EXCL, 0666);
4770 fd = open(fname, O_WRONLY|O_CREAT, 0666);
4772 /* If the open failed, return the file descriptor right away. */
4777 * OK, the open succeeded, but the file may have been changed from a
4778 * non-regular file to a regular file between the stat and the open.
4779 * We are assuming that the O_EXCL open handles the case where FILENAME
4780 * did not exist and is symlinked to an existing file between the stat
4785 * If we can open it and fstat the file descriptor, and neither check
4786 * revealed that it was a regular file, and the file has not been
4787 * replaced, return the file descriptor.
4789 if (fstat(fd, &finfo2) == 0 && !S_ISREG(finfo2.st_mode)
4790 && finfo.st_dev == finfo2.st_dev && finfo.st_ino == finfo2.st_ino)
4793 /* The file has been replaced. badness. */
4800 * Handle here documents. Normally we fork off a process to write the
4801 * data to a pipe. If the document is short, we can stuff the data in
4802 * the pipe without forking.
4804 /* openhere needs this forward reference */
4805 static void expandhere(union node *arg, int fd);
4807 openhere(union node *redir)
4813 ash_msg_and_raise_error("pipe call failed");
4814 if (redir->type == NHERE) {
4815 len = strlen(redir->nhere.doc->narg.text);
4816 if (len <= PIPE_BUF) {
4817 full_write(pip[1], redir->nhere.doc->narg.text, len);
4821 if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) {
4824 ignoresig(SIGINT); //signal(SIGINT, SIG_IGN);
4825 ignoresig(SIGQUIT); //signal(SIGQUIT, SIG_IGN);
4826 ignoresig(SIGHUP); //signal(SIGHUP, SIG_IGN);
4827 ignoresig(SIGTSTP); //signal(SIGTSTP, SIG_IGN);
4828 signal(SIGPIPE, SIG_DFL);
4829 if (redir->type == NHERE)
4830 full_write(pip[1], redir->nhere.doc->narg.text, len);
4832 expandhere(redir->nhere.doc, pip[1]);
4833 _exit(EXIT_SUCCESS);
4841 openredirect(union node *redir)
4846 switch (redir->nfile.type) {
4848 fname = redir->nfile.expfname;
4849 f = open(fname, O_RDONLY);
4854 fname = redir->nfile.expfname;
4855 f = open(fname, O_RDWR|O_CREAT|O_TRUNC, 0666);
4860 #if ENABLE_ASH_BASH_COMPAT
4863 /* Take care of noclobber mode. */
4865 fname = redir->nfile.expfname;
4866 f = noclobberopen(fname);
4873 fname = redir->nfile.expfname;
4874 f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666);
4879 fname = redir->nfile.expfname;
4880 f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666);
4888 /* Fall through to eliminate warning. */
4889 /* Our single caller does this itself */
4896 f = openhere(redir);
4902 ash_msg_and_raise_error("can't create %s: %s", fname, errmsg(errno, "nonexistent directory"));
4904 ash_msg_and_raise_error("can't open %s: %s", fname, errmsg(errno, "no such file"));
4908 * Copy a file descriptor to be >= to. Returns -1
4909 * if the source file descriptor is closed, EMPTY if there are no unused
4910 * file descriptors left.
4912 /* 0x800..00: bit to set in "to" to request dup2 instead of fcntl(F_DUPFD).
4913 * old code was doing close(to) prior to copyfd() to achieve the same */
4915 COPYFD_EXACT = (int)~(INT_MAX),
4916 COPYFD_RESTORE = (int)((unsigned)COPYFD_EXACT >> 1),
4919 copyfd(int from, int to)
4923 if (to & COPYFD_EXACT) {
4924 to &= ~COPYFD_EXACT;
4926 newfd = dup2(from, to);
4928 newfd = fcntl(from, F_DUPFD, to);
4931 if (errno == EMFILE)
4933 /* Happens when source fd is not open: try "echo >&99" */
4934 ash_msg_and_raise_error("%d: %m", from);
4939 /* Struct def and variable are moved down to the first usage site */
4944 struct redirtab *next;
4947 struct two_fd_t two_fd[0];
4949 #define redirlist (G_var.redirlist)
4951 static int need_to_remember(struct redirtab *rp, int fd)
4955 if (!rp) /* remembering was not requested */
4958 for (i = 0; i < rp->pair_count; i++) {
4959 if (rp->two_fd[i].orig == fd) {
4960 /* already remembered */
4967 /* "hidden" fd is a fd used to read scripts, or a copy of such */
4968 static int is_hidden_fd(struct redirtab *rp, int fd)
4971 struct parsefile *pf;
4984 fd |= COPYFD_RESTORE;
4985 for (i = 0; i < rp->pair_count; i++) {
4986 if (rp->two_fd[i].copy == fd) {
4994 * Process a list of redirection commands. If the REDIR_PUSH flag is set,
4995 * old file descriptors are stashed away so that the redirection can be
4996 * undone by calling popredir. If the REDIR_BACKQ flag is set, then the
4997 * standard output, and the standard error if it becomes a duplicate of
4998 * stdout, is saved in memory.
5000 /* flags passed to redirect */
5001 #define REDIR_PUSH 01 /* save previous values of file descriptors */
5002 #define REDIR_SAVEFD2 03 /* set preverrout */
5004 redirect(union node *redir, int flags)
5006 struct redirtab *sv;
5011 int copied_fd2 = -1;
5021 if (flags & REDIR_PUSH) {
5022 union node *tmp = redir;
5025 #if ENABLE_ASH_BASH_COMPAT
5026 if (redir->nfile.type == NTO2)
5029 tmp = tmp->nfile.next;
5031 sv = ckmalloc(sizeof(*sv) + sv_pos * sizeof(sv->two_fd[0]));
5032 sv->next = redirlist;
5033 sv->pair_count = sv_pos;
5035 sv->nullredirs = g_nullredirs - 1;
5037 while (sv_pos > 0) {
5039 sv->two_fd[sv_pos].orig = sv->two_fd[sv_pos].copy = EMPTY;
5044 fd = redir->nfile.fd;
5045 if (redir->nfile.type == NTOFD || redir->nfile.type == NFROMFD) {
5046 int right_fd = redir->ndup.dupfd;
5047 /* redirect from/to same file descriptor? */
5050 /* echo >&10 and 10 is a fd opened to the sh script? */
5051 if (is_hidden_fd(sv, right_fd)) {
5052 errno = EBADF; /* as if it is closed */
5053 ash_msg_and_raise_error("%d: %m", right_fd);
5057 newfd = openredirect(redir); /* always >= 0 */
5059 /* Descriptor wasn't open before redirect.
5060 * Mark it for close in the future */
5061 if (need_to_remember(sv, fd)) {
5062 goto remember_to_close;
5067 #if ENABLE_ASH_BASH_COMPAT
5070 if (need_to_remember(sv, fd)) {
5071 /* Copy old descriptor */
5072 i = fcntl(fd, F_DUPFD, 10);
5073 /* You'd expect copy to be CLOEXECed. Currently these extra "saved" fds
5074 * are closed in popredir() in the child, preventing them from leaking
5075 * into child. (popredir() also cleans up the mess in case of failures)
5080 /* Strange error (e.g. "too many files" EMFILE?) */
5084 ash_msg_and_raise_error("%d: %m", fd);
5087 /* EBADF: it is not open - good, remember to close it */
5090 } else { /* fd is open, save its copy */
5091 /* "exec fd>&-" should not close fds
5092 * which point to script file(s).
5093 * Force them to be restored afterwards */
5094 if (is_hidden_fd(sv, fd))
5095 i |= COPYFD_RESTORE;
5099 sv->two_fd[sv_pos].orig = fd;
5100 sv->two_fd[sv_pos].copy = i;
5104 /* NTOFD/NFROMFD: copy redir->ndup.dupfd to fd */
5105 if (redir->ndup.dupfd < 0) { /* "fd>&-" */
5108 copyfd(redir->ndup.dupfd, fd | COPYFD_EXACT);
5110 } else if (fd != newfd) { /* move newfd to fd */
5111 copyfd(newfd, fd | COPYFD_EXACT);
5112 #if ENABLE_ASH_BASH_COMPAT
5113 if (!(redir->nfile.type == NTO2 && fd == 2))
5117 #if ENABLE_ASH_BASH_COMPAT
5118 if (redir->nfile.type == NTO2 && fd == 1) {
5119 /* We already redirected it to fd 1, now copy it to 2 */
5125 } while ((redir = redir->nfile.next) != NULL);
5128 if ((flags & REDIR_SAVEFD2) && copied_fd2 >= 0)
5129 preverrout_fd = copied_fd2;
5133 * Undo the effects of the last redirection.
5136 popredir(int drop, int restore)
5138 struct redirtab *rp;
5141 if (--g_nullredirs >= 0)
5145 for (i = 0; i < rp->pair_count; i++) {
5146 int fd = rp->two_fd[i].orig;
5147 int copy = rp->two_fd[i].copy;
5148 if (copy == CLOSED) {
5153 if (copy != EMPTY) {
5154 if (!drop || (restore && (copy & COPYFD_RESTORE))) {
5155 copy &= ~COPYFD_RESTORE;
5157 copyfd(copy, fd | COPYFD_EXACT);
5162 redirlist = rp->next;
5163 g_nullredirs = rp->nullredirs;
5169 * Undo all redirections. Called on error or interrupt.
5173 * Discard all saved file descriptors.
5176 clearredir(int drop)
5182 popredir(drop, /*restore:*/ 0);
5187 redirectsafe(union node *redir, int flags)
5190 volatile int saveint;
5191 struct jmploc *volatile savehandler = exception_handler;
5192 struct jmploc jmploc;
5195 /* "echo 9>/dev/null; echo >&9; echo result: $?" - result should be 1, not 2! */
5196 err = setjmp(jmploc.loc); // huh?? was = setjmp(jmploc.loc) * 2;
5198 exception_handler = &jmploc;
5199 redirect(redir, flags);
5201 exception_handler = savehandler;
5202 if (err && exception != EXERROR)
5203 longjmp(exception_handler->loc, 1);
5204 RESTORE_INT(saveint);
5209 /* ============ Routines to expand arguments to commands
5211 * We have to deal with backquotes, shell variables, and file metacharacters.
5214 #if ENABLE_ASH_MATH_SUPPORT_64
5215 typedef int64_t arith_t;
5216 #define arith_t_type long long
5218 typedef long arith_t;
5219 #define arith_t_type long
5222 #if ENABLE_ASH_MATH_SUPPORT
5223 static arith_t dash_arith(const char *);
5224 static arith_t arith(const char *expr, int *perrcode);
5230 #define EXP_FULL 0x1 /* perform word splitting & file globbing */
5231 #define EXP_TILDE 0x2 /* do normal tilde expansion */
5232 #define EXP_VARTILDE 0x4 /* expand tildes in an assignment */
5233 #define EXP_REDIR 0x8 /* file glob for a redirection (1 match only) */
5234 #define EXP_CASE 0x10 /* keeps quotes around for CASE pattern */
5235 #define EXP_RECORD 0x20 /* need to record arguments for ifs breakup */
5236 #define EXP_VARTILDE2 0x40 /* expand tildes after colons only */
5237 #define EXP_WORD 0x80 /* expand word in parameter expansion */
5238 #define EXP_QWORD 0x100 /* expand word in quoted parameter expansion */
5242 #define RMESCAPE_ALLOC 0x1 /* Allocate a new string */
5243 #define RMESCAPE_GLOB 0x2 /* Add backslashes for glob */
5244 #define RMESCAPE_QUOTED 0x4 /* Remove CTLESC unless in quotes */
5245 #define RMESCAPE_GROW 0x8 /* Grow strings instead of stalloc */
5246 #define RMESCAPE_HEAP 0x10 /* Malloc strings instead of stalloc */
5249 * Structure specifying which parts of the string should be searched
5250 * for IFS characters.
5253 struct ifsregion *next; /* next region in list */
5254 int begoff; /* offset of start of region */
5255 int endoff; /* offset of end of region */
5256 int nulonly; /* search for nul bytes only */
5260 struct strlist *list;
5261 struct strlist **lastp;
5264 /* output of current string */
5265 static char *expdest;
5266 /* list of back quote expressions */
5267 static struct nodelist *argbackq;
5268 /* first struct in list of ifs regions */
5269 static struct ifsregion ifsfirst;
5270 /* last struct in list */
5271 static struct ifsregion *ifslastp;
5272 /* holds expanded arg list */
5273 static struct arglist exparg;
5283 expdest = makestrspace(32, expdest);
5284 #if ENABLE_ASH_MATH_SUPPORT_64
5285 len = fmtstr(expdest, 32, "%lld", (long long) num);
5287 len = fmtstr(expdest, 32, "%ld", num);
5289 STADJUST(len, expdest);
5294 esclen(const char *start, const char *p)
5298 while (p > start && *--p == CTLESC) {
5305 * Remove any CTLESC characters from a string.
5308 _rmescapes(char *str, int flag)
5310 static const char qchars[] ALIGN1 = { CTLESC, CTLQUOTEMARK, '\0' };
5317 p = strpbrk(str, qchars);
5323 if (flag & RMESCAPE_ALLOC) {
5324 size_t len = p - str;
5325 size_t fulllen = len + strlen(p) + 1;
5327 if (flag & RMESCAPE_GROW) {
5328 r = makestrspace(fulllen, expdest);
5329 } else if (flag & RMESCAPE_HEAP) {
5330 r = ckmalloc(fulllen);
5332 r = stalloc(fulllen);
5336 q = (char *)memcpy(q, str, len) + len;
5339 inquotes = (flag & RMESCAPE_QUOTED) ^ RMESCAPE_QUOTED;
5340 globbing = flag & RMESCAPE_GLOB;
5341 notescaped = globbing;
5343 if (*p == CTLQUOTEMARK) {
5344 inquotes = ~inquotes;
5346 notescaped = globbing;
5350 /* naked back slash */
5356 if (notescaped && inquotes && *p != '/') {
5360 notescaped = globbing;
5365 if (flag & RMESCAPE_GROW) {
5367 STADJUST(q - r + 1, expdest);
5371 #define rmescapes(p) _rmescapes((p), 0)
5373 #define pmatch(a, b) !fnmatch((a), (b), 0)
5376 * Prepare a pattern for a expmeta (internal glob(3)) call.
5378 * Returns an stalloced string.
5381 preglob(const char *pattern, int quoted, int flag)
5383 flag |= RMESCAPE_GLOB;
5385 flag |= RMESCAPE_QUOTED;
5387 return _rmescapes((char *)pattern, flag);
5391 * Put a string on the stack.
5394 memtodest(const char *p, size_t len, int syntax, int quotes)
5398 q = makestrspace(len * 2, q);
5401 int c = signed_char2int(*p++);
5404 if (quotes && (SIT(c, syntax) == CCTL || SIT(c, syntax) == CBACK))
5413 strtodest(const char *p, int syntax, int quotes)
5415 memtodest(p, strlen(p), syntax, quotes);
5419 * Record the fact that we have to scan this region of the
5420 * string for IFS characters.
5423 recordregion(int start, int end, int nulonly)
5425 struct ifsregion *ifsp;
5427 if (ifslastp == NULL) {
5431 ifsp = ckzalloc(sizeof(*ifsp));
5432 /*ifsp->next = NULL; - ckzalloc did it */
5433 ifslastp->next = ifsp;
5437 ifslastp->begoff = start;
5438 ifslastp->endoff = end;
5439 ifslastp->nulonly = nulonly;
5443 removerecordregions(int endoff)
5445 if (ifslastp == NULL)
5448 if (ifsfirst.endoff > endoff) {
5449 while (ifsfirst.next != NULL) {
5450 struct ifsregion *ifsp;
5452 ifsp = ifsfirst.next->next;
5453 free(ifsfirst.next);
5454 ifsfirst.next = ifsp;
5457 if (ifsfirst.begoff > endoff)
5460 ifslastp = &ifsfirst;
5461 ifsfirst.endoff = endoff;
5466 ifslastp = &ifsfirst;
5467 while (ifslastp->next && ifslastp->next->begoff < endoff)
5468 ifslastp=ifslastp->next;
5469 while (ifslastp->next != NULL) {
5470 struct ifsregion *ifsp;
5472 ifsp = ifslastp->next->next;
5473 free(ifslastp->next);
5474 ifslastp->next = ifsp;
5477 if (ifslastp->endoff > endoff)
5478 ifslastp->endoff = endoff;
5482 exptilde(char *startp, char *p, int flag)
5488 int quotes = flag & (EXP_FULL | EXP_CASE);
5493 while ((c = *++p) != '\0') {
5500 if (flag & EXP_VARTILDE)
5510 if (*name == '\0') {
5511 home = lookupvar(homestr);
5513 pw = getpwnam(name);
5518 if (!home || !*home)
5521 startloc = expdest - (char *)stackblock();
5522 strtodest(home, SQSYNTAX, quotes);
5523 recordregion(startloc, expdest - (char *)stackblock(), 0);
5531 * Execute a command inside back quotes. If it's a builtin command, we
5532 * want to save its output in a block obtained from malloc. Otherwise
5533 * we fork off a subprocess and get the output of the command via a pipe.
5534 * Should be called with interrupts off.
5536 struct backcmd { /* result of evalbackcmd */
5537 int fd; /* file descriptor to read from */
5538 int nleft; /* number of chars in buffer */
5539 char *buf; /* buffer */
5540 struct job *jp; /* job structure for command */
5543 /* These forward decls are needed to use "eval" code for backticks handling: */
5544 static uint8_t back_exitstatus; /* exit status of backquoted command */
5545 #define EV_EXIT 01 /* exit after evaluating tree */
5546 static void evaltree(union node *, int);
5549 evalbackcmd(union node *n, struct backcmd *result)
5560 saveherefd = herefd;
5568 ash_msg_and_raise_error("pipe call failed");
5569 jp = makejob(/*n,*/ 1);
5570 if (forkshell(jp, n, FORK_NOJOB) == 0) {
5575 copyfd(pip[1], 1 | COPYFD_EXACT);
5579 evaltree(n, EV_EXIT); /* actually evaltreenr... */
5583 result->fd = pip[0];
5586 herefd = saveherefd;
5588 TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n",
5589 result->fd, result->buf, result->nleft, result->jp));
5593 * Expand stuff in backwards quotes.
5596 expbackq(union node *cmd, int quoted, int quotes)
5604 int syntax = quoted ? DQSYNTAX : BASESYNTAX;
5605 struct stackmark smark;
5608 setstackmark(&smark);
5610 startloc = dest - (char *)stackblock();
5612 evalbackcmd(cmd, &in);
5613 popstackmark(&smark);
5620 memtodest(p, i, syntax, quotes);
5624 i = nonblock_safe_read(in.fd, buf, sizeof(buf));
5625 TRACE(("expbackq: read returns %d\n", i));
5634 back_exitstatus = waitforjob(in.jp);
5638 /* Eat all trailing newlines */
5640 for (; dest > (char *)stackblock() && dest[-1] == '\n';)
5645 recordregion(startloc, dest - (char *)stackblock(), 0);
5646 TRACE(("evalbackq: size=%d: \"%.*s\"\n",
5647 (dest - (char *)stackblock()) - startloc,
5648 (dest - (char *)stackblock()) - startloc,
5649 stackblock() + startloc));
5652 #if ENABLE_ASH_MATH_SUPPORT
5654 * Expand arithmetic expression. Backup to start of expression,
5655 * evaluate, place result in (backed up) result, adjust string position.
5668 * This routine is slightly over-complicated for
5669 * efficiency. Next we scan backwards looking for the
5670 * start of arithmetic.
5672 start = stackblock();
5679 while (*p != CTLARI) {
5683 ash_msg_and_raise_error("missing CTLARI (shouldn't happen)");
5688 esc = esclen(start, p);
5698 removerecordregions(begoff);
5707 len = cvtnum(dash_arith(p + 2));
5710 recordregion(begoff, begoff + len, 0);
5714 /* argstr needs it */
5715 static char *evalvar(char *p, int flag, struct strlist *var_str_list);
5718 * Perform variable and command substitution. If EXP_FULL is set, output CTLESC
5719 * characters to allow for further processing. Otherwise treat
5720 * $@ like $* since no splitting will be performed.
5722 * var_str_list (can be NULL) is a list of "VAR=val" strings which take precedence
5723 * over shell varables. Needed for "A=a B=$A; echo $B" case - we use it
5724 * for correct expansion of "B=$A" word.
5727 argstr(char *p, int flag, struct strlist *var_str_list)
5729 static const char spclchars[] ALIGN1 = {
5737 CTLBACKQ | CTLQUOTE,
5738 #if ENABLE_ASH_MATH_SUPPORT
5743 const char *reject = spclchars;
5745 int quotes = flag & (EXP_FULL | EXP_CASE); /* do CTLESC */
5746 int breakall = flag & EXP_WORD;
5751 if (!(flag & EXP_VARTILDE)) {
5753 } else if (flag & EXP_VARTILDE2) {
5758 if (flag & EXP_TILDE) {
5764 if (*q == CTLESC && (flag & EXP_QWORD))
5767 p = exptilde(p, q, flag);
5770 startloc = expdest - (char *)stackblock();
5772 length += strcspn(p + length, reject);
5774 if (c && (!(c & 0x80)
5775 #if ENABLE_ASH_MATH_SUPPORT
5779 /* c == '=' || c == ':' || c == CTLENDARI */
5784 expdest = stack_nputstr(p, length, expdest);
5785 newloc = expdest - (char *)stackblock();
5786 if (breakall && !inquotes && newloc > startloc) {
5787 recordregion(startloc, newloc, 0);
5798 if (flag & EXP_VARTILDE2) {
5802 flag |= EXP_VARTILDE2;
5807 * sort of a hack - expand tildes in variable
5808 * assignments (after the first '=' and after ':'s).
5817 case CTLENDVAR: /* ??? */
5820 /* "$@" syntax adherence hack */
5823 !memcmp(p, dolatstr, 4) &&
5824 (p[4] == CTLQUOTEMARK || (
5825 p[4] == CTLENDVAR &&
5826 p[5] == CTLQUOTEMARK
5829 p = evalvar(p + 1, flag, /* var_str_list: */ NULL) + 1;
5832 inquotes = !inquotes;
5845 p = evalvar(p, flag, var_str_list);
5849 case CTLBACKQ|CTLQUOTE:
5850 expbackq(argbackq->n, c, quotes);
5851 argbackq = argbackq->next;
5853 #if ENABLE_ASH_MATH_SUPPORT
5866 scanleft(char *startp, char *rmesc, char *rmescend UNUSED_PARAM, char *str, int quotes,
5869 // This commented out code was added by James Simmons <jsimmons@infradead.org>
5870 // as part of a larger change when he added support for ${var/a/b}.
5871 // However, it broke # and % operators:
5875 //echo ${var#ab} abcdcd abcdcd
5876 //echo ${var##ab} abcdcd abcdcd
5877 //echo ${var#a*b} abcdcd ababcdcd (!)
5878 //echo ${var##a*b} cdcd cdcd
5879 //echo ${var#?} babcdcd ababcdcd (!)
5880 //echo ${var##?} babcdcd babcdcd
5881 //echo ${var#*} ababcdcd babcdcd (!)
5883 //echo ${var%cd} ababcd ababcd
5884 //echo ${var%%cd} ababcd abab (!)
5885 //echo ${var%c*d} ababcd ababcd
5886 //echo ${var%%c*d} abab ababcdcd (!)
5887 //echo ${var%?} ababcdc ababcdc
5888 //echo ${var%%?} ababcdc ababcdcd (!)
5889 //echo ${var%*} ababcdcd ababcdcd
5892 // Commenting it back out helped. Remove it completely if it really
5895 char *loc, *loc2; //, *full;
5901 int match; // = strlen(str);
5902 const char *s = loc2;
5909 match = pmatch(str, s); // this line was deleted
5911 // // chop off end if its '*'
5912 // full = strrchr(str, '*');
5913 // if (full && full != str)
5916 // // If str starts with '*' replace with s.
5917 // if ((*str == '*') && strlen(s) >= match) {
5918 // full = xstrdup(s);
5919 // strncpy(full+strlen(s)-match+1, str+1, match-1);
5921 // full = xstrndup(str, match);
5922 // match = strncmp(s, full, strlen(full));
5926 if (match) // if (!match)
5928 if (quotes && *loc == CTLESC)
5937 scanright(char *startp, char *rmesc, char *rmescend, char *str, int quotes,
5944 for (loc = str - 1, loc2 = rmescend; loc >= startp; loc2--) {
5947 const char *s = loc2;
5952 match = pmatch(str, s);
5959 esc = esclen(startp, loc);
5970 static void varunset(const char *, const char *, const char *, int) NORETURN;
5972 varunset(const char *end, const char *var, const char *umsg, int varflags)
5978 msg = "parameter not set";
5980 if (*end == CTLENDVAR) {
5981 if (varflags & VSNUL)
5987 ash_msg_and_raise_error("%.*s: %s%s", end - var - 1, var, msg, tail);
5990 #if ENABLE_ASH_BASH_COMPAT
5992 parse_sub_pattern(char *arg, int inquotes)
5994 char *idx, *repl = NULL;
6003 /* Only the first '/' seen is our separator */
6010 if (!inquotes && c == '\\' && arg[1] == '\\')
6011 arg++; /* skip both \\, not just first one */
6018 #endif /* ENABLE_ASH_BASH_COMPAT */
6021 subevalvar(char *p, char *str, int strloc, int subtype,
6022 int startloc, int varflags, int quotes, struct strlist *var_str_list)
6024 struct nodelist *saveargbackq = argbackq;
6027 char *rmesc, *rmescend;
6028 USE_ASH_BASH_COMPAT(char *repl = NULL;)
6029 USE_ASH_BASH_COMPAT(char null = '\0';)
6030 USE_ASH_BASH_COMPAT(int pos, len, orig_len;)
6031 int saveherefd = herefd;
6032 int amount, workloc, resetloc;
6034 char *(*scan)(char*, char*, char*, char*, int, int);
6037 argstr(p, (subtype != VSASSIGN && subtype != VSQUESTION) ? EXP_CASE : 0,
6039 STPUTC('\0', expdest);
6040 herefd = saveherefd;
6041 argbackq = saveargbackq;
6042 startp = (char *)stackblock() + startloc;
6046 setvar(str, startp, 0);
6047 amount = startp - expdest;
6048 STADJUST(amount, expdest);
6051 #if ENABLE_ASH_BASH_COMPAT
6053 loc = str = stackblock() + strloc;
6054 // TODO: number() instead? It does error checking...
6056 len = str - startp - 1;
6058 /* *loc != '\0', guaranteed by parser */
6062 /* We must adjust the length by the number of escapes we find. */
6063 for (ptr = startp; ptr < (str - 1); ptr++) {
6064 if (*ptr == CTLESC) {
6072 if (*loc++ == ':') {
6073 // TODO: number() instead? It does error checking...
6077 while (*loc && *loc != ':')
6080 // TODO: number() instead? It does error checking...
6083 if (pos >= orig_len) {
6087 if (len > (orig_len - pos))
6088 len = orig_len - pos;
6090 for (str = startp; pos; str++, pos--) {
6091 if (quotes && *str == CTLESC)
6094 for (loc = startp; len; len--) {
6095 if (quotes && *str == CTLESC)
6100 amount = loc - expdest;
6101 STADJUST(amount, expdest);
6106 varunset(p, str, startp, varflags);
6109 resetloc = expdest - (char *)stackblock();
6111 /* We'll comeback here if we grow the stack while handling
6112 * a VSREPLACE or VSREPLACEALL, since our pointers into the
6113 * stack will need rebasing, and we'll need to remove our work
6116 USE_ASH_BASH_COMPAT(restart:)
6118 amount = expdest - ((char *)stackblock() + resetloc);
6119 STADJUST(-amount, expdest);
6120 startp = (char *)stackblock() + startloc;
6123 rmescend = (char *)stackblock() + strloc;
6125 rmesc = _rmescapes(startp, RMESCAPE_ALLOC | RMESCAPE_GROW);
6126 if (rmesc != startp) {
6128 startp = (char *)stackblock() + startloc;
6132 str = (char *)stackblock() + strloc;
6133 preglob(str, varflags & VSQUOTE, 0);
6134 workloc = expdest - (char *)stackblock();
6136 #if ENABLE_ASH_BASH_COMPAT
6137 if (subtype == VSREPLACE || subtype == VSREPLACEALL) {
6138 char *idx, *end, *restart_detect;
6141 repl = parse_sub_pattern(str, varflags & VSQUOTE);
6146 /* If there's no pattern to match, return the expansion unmolested */
6154 loc = scanright(idx, rmesc, rmescend, str, quotes, 1);
6156 /* No match, advance */
6157 restart_detect = stackblock();
6158 STPUTC(*idx, expdest);
6159 if (quotes && *idx == CTLESC) {
6162 STPUTC(*idx, expdest);
6164 if (stackblock() != restart_detect)
6172 if (subtype == VSREPLACEALL) {
6174 if (quotes && *idx == CTLESC)
6183 for (loc = repl; *loc; loc++) {
6184 restart_detect = stackblock();
6185 STPUTC(*loc, expdest);
6186 if (stackblock() != restart_detect)
6191 if (subtype == VSREPLACE) {
6193 restart_detect = stackblock();
6194 STPUTC(*idx, expdest);
6195 if (stackblock() != restart_detect)
6204 /* We've put the replaced text into a buffer at workloc, now
6205 * move it to the right place and adjust the stack.
6207 startp = stackblock() + startloc;
6208 STPUTC('\0', expdest);
6209 memmove(startp, stackblock() + workloc, len);
6210 startp[len++] = '\0';
6211 amount = expdest - ((char *)stackblock() + startloc + len - 1);
6212 STADJUST(-amount, expdest);
6215 #endif /* ENABLE_ASH_BASH_COMPAT */
6217 subtype -= VSTRIMRIGHT;
6219 if (subtype < 0 || subtype > 7)
6222 /* zero = subtype == VSTRIMLEFT || subtype == VSTRIMLEFTMAX */
6223 zero = subtype >> 1;
6224 /* VSTRIMLEFT/VSTRIMRIGHTMAX -> scanleft */
6225 scan = (subtype & 1) ^ zero ? scanleft : scanright;
6227 loc = scan(startp, rmesc, rmescend, str, quotes, zero);
6230 memmove(startp, loc, str - loc);
6231 loc = startp + (str - loc) - 1;
6234 amount = loc - expdest;
6235 STADJUST(amount, expdest);
6241 * Add the value of a specialized variable to the stack string.
6244 varvalue(char *name, int varflags, int flags, struct strlist *var_str_list)
6254 int quoted = varflags & VSQUOTE;
6255 int subtype = varflags & VSTYPE;
6256 int quotes = flags & (EXP_FULL | EXP_CASE);
6258 if (quoted && (flags & EXP_FULL))
6259 sep = 1 << CHAR_BIT;
6261 syntax = quoted ? DQSYNTAX : BASESYNTAX;
6270 num = shellparam.nparam;
6280 p = makestrspace(NOPTS, expdest);
6281 for (i = NOPTS - 1; i >= 0; i--) {
6283 USTPUTC(optletters(i), p);
6294 sep = ifsset() ? signed_char2int(ifsval()[0]) : ' ';
6295 if (quotes && (SIT(sep, syntax) == CCTL || SIT(sep, syntax) == CBACK))
6301 while ((p = *ap++)) {
6304 partlen = strlen(p);
6307 if (!(subtype == VSPLUS || subtype == VSLENGTH))
6308 memtodest(p, partlen, syntax, quotes);
6314 if (subtype == VSPLUS || subtype == VSLENGTH) {
6335 // TODO: number() instead? It does error checking...
6337 if (num < 0 || num > shellparam.nparam)
6339 p = num ? shellparam.p[num - 1] : arg0;
6342 /* NB: name has form "VAR=..." */
6344 /* "A=a B=$A" case: var_str_list is a list of "A=a" strings
6345 * which should be considered before we check variables. */
6347 unsigned name_len = (strchrnul(name, '=') - name) + 1;
6351 str = var_str_list->text;
6352 eq = strchr(str, '=');
6353 if (!eq) /* stop at first non-assignment */
6356 if (name_len == (unsigned)(eq - str)
6357 && strncmp(str, name, name_len) == 0) {
6359 /* goto value; - WRONG! */
6360 /* think "A=1 A=2 B=$A" */
6362 var_str_list = var_str_list->next;
6363 } while (var_str_list);
6367 p = lookupvar(name);
6373 if (!(subtype == VSPLUS || subtype == VSLENGTH))
6374 memtodest(p, len, syntax, quotes);
6378 if (subtype == VSPLUS || subtype == VSLENGTH)
6379 STADJUST(-len, expdest);
6384 * Expand a variable, and return a pointer to the next character in the
6388 evalvar(char *p, int flag, struct strlist *var_str_list)
6400 subtype = varflags & VSTYPE;
6401 quoted = varflags & VSQUOTE;
6403 easy = (!quoted || (*var == '@' && shellparam.nparam));
6404 startloc = expdest - (char *)stackblock();
6405 p = strchr(p, '=') + 1;
6408 varlen = varvalue(var, varflags, flag, var_str_list);
6409 if (varflags & VSNUL)
6412 if (subtype == VSPLUS) {
6413 varlen = -1 - varlen;
6417 if (subtype == VSMINUS) {
6421 p, flag | EXP_TILDE |
6422 (quoted ? EXP_QWORD : EXP_WORD),
6432 if (subtype == VSASSIGN || subtype == VSQUESTION) {
6434 if (subevalvar(p, var, /* strloc: */ 0,
6435 subtype, startloc, varflags,
6441 * Remove any recorded regions beyond
6444 removerecordregions(startloc);
6454 if (varlen < 0 && uflag)
6455 varunset(p, var, 0, 0);
6457 if (subtype == VSLENGTH) {
6458 cvtnum(varlen > 0 ? varlen : 0);
6462 if (subtype == VSNORMAL) {
6473 case VSTRIMRIGHTMAX:
6474 #if ENABLE_ASH_BASH_COMPAT
6487 * Terminate the string and start recording the pattern
6490 STPUTC('\0', expdest);
6491 patloc = expdest - (char *)stackblock();
6492 if (0 == subevalvar(p, /* str: */ NULL, patloc, subtype,
6494 /* quotes: */ flag & (EXP_FULL | EXP_CASE),
6497 int amount = expdest - (
6498 (char *)stackblock() + patloc - 1
6500 STADJUST(-amount, expdest);
6502 /* Remove any recorded regions beyond start of variable */
6503 removerecordregions(startloc);
6505 recordregion(startloc, expdest - (char *)stackblock(), quoted);
6509 if (subtype != VSNORMAL) { /* skip to end of alternative */
6515 else if (c == CTLBACKQ || c == (CTLBACKQ|CTLQUOTE)) {
6517 argbackq = argbackq->next;
6518 } else if (c == CTLVAR) {
6519 if ((*p++ & VSTYPE) != VSNORMAL)
6521 } else if (c == CTLENDVAR) {
6531 * Break the argument string into pieces based upon IFS and add the
6532 * strings to the argument list. The regions of the string to be
6533 * searched for IFS characters have been stored by recordregion.
6536 ifsbreakup(char *string, struct arglist *arglist)
6538 struct ifsregion *ifsp;
6543 const char *ifs, *realifs;
6548 if (ifslastp != NULL) {
6551 realifs = ifsset() ? ifsval() : defifs;
6554 p = string + ifsp->begoff;
6555 nulonly = ifsp->nulonly;
6556 ifs = nulonly ? nullstr : realifs;
6558 while (p < string + ifsp->endoff) {
6562 if (!strchr(ifs, *p)) {
6567 ifsspc = (strchr(defifs, *p) != NULL);
6568 /* Ignore IFS whitespace at start */
6569 if (q == start && ifsspc) {
6575 sp = stzalloc(sizeof(*sp));
6577 *arglist->lastp = sp;
6578 arglist->lastp = &sp->next;
6582 if (p >= string + ifsp->endoff) {
6588 if (strchr(ifs, *p) == NULL) {
6592 if (strchr(defifs, *p) == NULL) {
6607 } while (ifsp != NULL);
6616 sp = stzalloc(sizeof(*sp));
6618 *arglist->lastp = sp;
6619 arglist->lastp = &sp->next;
6625 struct ifsregion *p;
6630 struct ifsregion *ifsp;
6636 ifsfirst.next = NULL;
6641 * Add a file name to the list.
6644 addfname(const char *name)
6648 sp = stzalloc(sizeof(*sp));
6649 sp->text = ststrdup(name);
6651 exparg.lastp = &sp->next;
6654 static char *expdir;
6657 * Do metacharacter (i.e. *, ?, [...]) expansion.
6660 expmeta(char *enddir, char *name)
6675 for (p = name; *p; p++) {
6676 if (*p == '*' || *p == '?')
6678 else if (*p == '[') {
6685 if (*q == '/' || *q == '\0')
6692 } else if (*p == '\\')
6694 else if (*p == '/') {
6701 if (metaflag == 0) { /* we've reached the end of the file name */
6702 if (enddir != expdir)
6710 if (metaflag == 0 || lstat(expdir, &statb) >= 0)
6721 } while (p < start);
6723 if (enddir == expdir) {
6725 } else if (enddir == expdir + 1 && *expdir == '/') {
6734 if (enddir != expdir)
6736 if (*endname == 0) {
6748 while (!intpending && (dp = readdir(dirp)) != NULL) {
6749 if (dp->d_name[0] == '.' && !matchdot)
6751 if (pmatch(start, dp->d_name)) {
6753 strcpy(enddir, dp->d_name);
6756 for (p = enddir, cp = dp->d_name; (*p++ = *cp++) != '\0';)
6759 expmeta(p, endname);
6768 static struct strlist *
6769 msort(struct strlist *list, int len)
6771 struct strlist *p, *q = NULL;
6772 struct strlist **lpp;
6780 for (n = half; --n >= 0;) {
6784 q->next = NULL; /* terminate first half of list */
6785 q = msort(list, half); /* sort first half of list */
6786 p = msort(p, len - half); /* sort second half */
6789 #if ENABLE_LOCALE_SUPPORT
6790 if (strcoll(p->text, q->text) < 0)
6792 if (strcmp(p->text, q->text) < 0)
6816 * Sort the results of file name expansion. It calculates the number of
6817 * strings to sort and then calls msort (short for merge sort) to do the
6820 static struct strlist *
6821 expsort(struct strlist *str)
6827 for (sp = str; sp; sp = sp->next)
6829 return msort(str, len);
6833 expandmeta(struct strlist *str /*, int flag*/)
6835 static const char metachars[] ALIGN1 = {
6838 /* TODO - EXP_REDIR */
6841 struct strlist **savelastp;
6847 if (!strpbrk(str->text, metachars))
6849 savelastp = exparg.lastp;
6852 p = preglob(str->text, 0, RMESCAPE_ALLOC | RMESCAPE_HEAP);
6854 int i = strlen(str->text);
6855 expdir = ckmalloc(i < 2048 ? 2048 : i); /* XXX */
6863 if (exparg.lastp == savelastp) {
6868 *exparg.lastp = str;
6869 rmescapes(str->text);
6870 exparg.lastp = &str->next;
6872 *exparg.lastp = NULL;
6873 *savelastp = sp = expsort(*savelastp);
6874 while (sp->next != NULL)
6876 exparg.lastp = &sp->next;
6883 * Perform variable substitution and command substitution on an argument,
6884 * placing the resulting list of arguments in arglist. If EXP_FULL is true,
6885 * perform splitting and file name expansion. When arglist is NULL, perform
6886 * here document expansion.
6889 expandarg(union node *arg, struct arglist *arglist, int flag)
6894 argbackq = arg->narg.backquote;
6895 STARTSTACKSTR(expdest);
6896 ifsfirst.next = NULL;
6898 argstr(arg->narg.text, flag,
6899 /* var_str_list: */ arglist ? arglist->list : NULL);
6900 p = _STPUTC('\0', expdest);
6902 if (arglist == NULL) {
6903 return; /* here document expanded */
6905 p = grabstackstr(p);
6906 exparg.lastp = &exparg.list;
6910 if (flag & EXP_FULL) {
6911 ifsbreakup(p, &exparg);
6912 *exparg.lastp = NULL;
6913 exparg.lastp = &exparg.list;
6914 expandmeta(exparg.list /*, flag*/);
6916 if (flag & EXP_REDIR) /*XXX - for now, just remove escapes */
6918 sp = stzalloc(sizeof(*sp));
6921 exparg.lastp = &sp->next;
6925 *exparg.lastp = NULL;
6927 *arglist->lastp = exparg.list;
6928 arglist->lastp = exparg.lastp;
6933 * Expand shell variables and backquotes inside a here document.
6936 expandhere(union node *arg, int fd)
6939 expandarg(arg, (struct arglist *)NULL, 0);
6940 full_write(fd, stackblock(), expdest - (char *)stackblock());
6944 * Returns true if the pattern matches the string.
6947 patmatch(char *pattern, const char *string)
6949 return pmatch(preglob(pattern, 0, 0), string);
6953 * See if a pattern matches in a case statement.
6956 casematch(union node *pattern, char *val)
6958 struct stackmark smark;
6961 setstackmark(&smark);
6962 argbackq = pattern->narg.backquote;
6963 STARTSTACKSTR(expdest);
6965 argstr(pattern->narg.text, EXP_TILDE | EXP_CASE,
6966 /* var_str_list: */ NULL);
6967 STACKSTRNUL(expdest);
6968 result = patmatch(stackblock(), val);
6969 popstackmark(&smark);
6974 /* ============ find_command */
6978 int (*builtin)(int, char **);
6979 /* unsigned flags; */
6981 #define IS_BUILTIN_SPECIAL(b) ((b)->name[0] & 1)
6982 /* "regular" builtins always take precedence over commands,
6983 * regardless of PATH=....%builtin... position */
6984 #define IS_BUILTIN_REGULAR(b) ((b)->name[0] & 2)
6985 #define IS_BUILTIN_ASSIGN(b) ((b)->name[0] & 4)
6988 smallint cmdtype; /* CMDxxx */
6991 /* index >= 0 for commands without path (slashes) */
6992 /* (TODO: what exactly does the value mean? PATH position?) */
6993 /* index == -1 for commands with slashes */
6994 /* index == (-2 - applet_no) for NOFORK applets */
6995 const struct builtincmd *cmd;
6996 struct funcnode *func;
6999 /* values of cmdtype */
7000 #define CMDUNKNOWN -1 /* no entry in table for command */
7001 #define CMDNORMAL 0 /* command is an executable program */
7002 #define CMDFUNCTION 1 /* command is a shell function */
7003 #define CMDBUILTIN 2 /* command is a shell builtin */
7005 /* action to find_command() */
7006 #define DO_ERR 0x01 /* prints errors */
7007 #define DO_ABS 0x02 /* checks absolute paths */
7008 #define DO_NOFUNC 0x04 /* don't return shell functions, for command */
7009 #define DO_ALTPATH 0x08 /* using alternate path */
7010 #define DO_ALTBLTIN 0x20 /* %builtin in alt. path */
7012 static void find_command(char *, struct cmdentry *, int, const char *);
7015 /* ============ Hashing commands */
7018 * When commands are first encountered, they are entered in a hash table.
7019 * This ensures that a full path search will not have to be done for them
7020 * on each invocation.
7022 * We should investigate converting to a linear search, even though that
7023 * would make the command name "hash" a misnomer.
7027 struct tblentry *next; /* next entry in hash chain */
7028 union param param; /* definition of builtin function */
7029 smallint cmdtype; /* CMDxxx */
7030 char rehash; /* if set, cd done since entry created */
7031 char cmdname[1]; /* name of command */
7034 static struct tblentry **cmdtable;
7035 #define INIT_G_cmdtable() do { \
7036 cmdtable = xzalloc(CMDTABLESIZE * sizeof(cmdtable[0])); \
7039 static int builtinloc = -1; /* index in path of %builtin, or -1 */
7043 tryexec(USE_FEATURE_SH_STANDALONE(int applet_no,) char *cmd, char **argv, char **envp)
7047 #if ENABLE_FEATURE_SH_STANDALONE
7048 if (applet_no >= 0) {
7049 if (APPLET_IS_NOEXEC(applet_no)) {
7052 run_applet_no_and_exit(applet_no, argv);
7054 /* re-exec ourselves with the new arguments */
7055 execve(bb_busybox_exec_path, argv, envp);
7056 /* If they called chroot or otherwise made the binary no longer
7057 * executable, fall through */
7064 execve(cmd, argv, envp);
7065 } while (errno == EINTR);
7067 execve(cmd, argv, envp);
7073 if (errno == ENOEXEC) {
7077 for (ap = argv; *ap; ap++)
7079 ap = new = ckmalloc((ap - argv + 2) * sizeof(ap[0]));
7081 ap[0] = cmd = (char *)DEFAULT_SHELL;
7084 while ((*ap++ = *argv++) != NULL)
7093 * Exec a program. Never returns. If you change this routine, you may
7094 * have to change the find_command routine as well.
7096 static void shellexec(char **, const char *, int) NORETURN;
7098 shellexec(char **argv, const char *path, int idx)
7104 #if ENABLE_FEATURE_SH_STANDALONE
7108 clearredir(/*drop:*/ 1);
7109 envp = listvars(VEXPORT, VUNSET, 0);
7110 if (strchr(argv[0], '/') != NULL
7111 #if ENABLE_FEATURE_SH_STANDALONE
7112 || (applet_no = find_applet_by_name(argv[0])) >= 0
7115 tryexec(USE_FEATURE_SH_STANDALONE(applet_no,) argv[0], argv, envp);
7119 while ((cmdname = padvance(&path, argv[0])) != NULL) {
7120 if (--idx < 0 && pathopt == NULL) {
7121 tryexec(USE_FEATURE_SH_STANDALONE(-1,) cmdname, argv, envp);
7122 if (errno != ENOENT && errno != ENOTDIR)
7129 /* Map to POSIX errors */
7141 exitstatus = exerrno;
7142 TRACE(("shellexec failed for %s, errno %d, suppressint %d\n",
7143 argv[0], e, suppressint));
7144 ash_msg_and_raise(EXEXEC, "%s: %s", argv[0], errmsg(e, "not found"));
7149 printentry(struct tblentry *cmdp)
7155 idx = cmdp->param.index;
7158 name = padvance(&path, cmdp->cmdname);
7160 } while (--idx >= 0);
7161 out1fmt("%s%s\n", name, (cmdp->rehash ? "*" : nullstr));
7165 * Clear out command entries. The argument specifies the first entry in
7166 * PATH which has changed.
7169 clearcmdentry(int firstchange)
7171 struct tblentry **tblp;
7172 struct tblentry **pp;
7173 struct tblentry *cmdp;
7176 for (tblp = cmdtable; tblp < &cmdtable[CMDTABLESIZE]; tblp++) {
7178 while ((cmdp = *pp) != NULL) {
7179 if ((cmdp->cmdtype == CMDNORMAL &&
7180 cmdp->param.index >= firstchange)
7181 || (cmdp->cmdtype == CMDBUILTIN &&
7182 builtinloc >= firstchange)
7195 * Locate a command in the command hash table. If "add" is nonzero,
7196 * add the command to the table if it is not already present. The
7197 * variable "lastcmdentry" is set to point to the address of the link
7198 * pointing to the entry, so that delete_cmd_entry can delete the
7201 * Interrupts must be off if called with add != 0.
7203 static struct tblentry **lastcmdentry;
7205 static struct tblentry *
7206 cmdlookup(const char *name, int add)
7208 unsigned int hashval;
7210 struct tblentry *cmdp;
7211 struct tblentry **pp;
7214 hashval = (unsigned char)*p << 4;
7216 hashval += (unsigned char)*p++;
7218 pp = &cmdtable[hashval % CMDTABLESIZE];
7219 for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
7220 if (strcmp(cmdp->cmdname, name) == 0)
7224 if (add && cmdp == NULL) {
7225 cmdp = *pp = ckzalloc(sizeof(struct tblentry)
7227 /* + 1 - already done because
7228 * tblentry::cmdname is char[1] */);
7229 /*cmdp->next = NULL; - ckzalloc did it */
7230 cmdp->cmdtype = CMDUNKNOWN;
7231 strcpy(cmdp->cmdname, name);
7238 * Delete the command entry returned on the last lookup.
7241 delete_cmd_entry(void)
7243 struct tblentry *cmdp;
7246 cmdp = *lastcmdentry;
7247 *lastcmdentry = cmdp->next;
7248 if (cmdp->cmdtype == CMDFUNCTION)
7249 freefunc(cmdp->param.func);
7255 * Add a new command entry, replacing any existing command entry for
7256 * the same name - except special builtins.
7259 addcmdentry(char *name, struct cmdentry *entry)
7261 struct tblentry *cmdp;
7263 cmdp = cmdlookup(name, 1);
7264 if (cmdp->cmdtype == CMDFUNCTION) {
7265 freefunc(cmdp->param.func);
7267 cmdp->cmdtype = entry->cmdtype;
7268 cmdp->param = entry->u;
7273 hashcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
7275 struct tblentry **pp;
7276 struct tblentry *cmdp;
7278 struct cmdentry entry;
7281 if (nextopt("r") != '\0') {
7286 if (*argptr == NULL) {
7287 for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
7288 for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
7289 if (cmdp->cmdtype == CMDNORMAL)
7297 while ((name = *argptr) != NULL) {
7298 cmdp = cmdlookup(name, 0);
7300 && (cmdp->cmdtype == CMDNORMAL
7301 || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0))
7305 find_command(name, &entry, DO_ERR, pathval());
7306 if (entry.cmdtype == CMDUNKNOWN)
7314 * Called when a cd is done. Marks all commands so the next time they
7315 * are executed they will be rehashed.
7320 struct tblentry **pp;
7321 struct tblentry *cmdp;
7323 for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
7324 for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
7325 if (cmdp->cmdtype == CMDNORMAL
7326 || (cmdp->cmdtype == CMDBUILTIN
7327 && !IS_BUILTIN_REGULAR(cmdp->param.cmd)
7337 * Fix command hash table when PATH changed.
7338 * Called before PATH is changed. The argument is the new value of PATH;
7339 * pathval() still returns the old value at this point.
7340 * Called with interrupts off.
7343 changepath(const char *new)
7351 firstchange = 9999; /* assume no change */
7357 if ((*old == '\0' && *new == ':')
7358 || (*old == ':' && *new == '\0'))
7360 old = new; /* ignore subsequent differences */
7364 if (*new == '%' && idx_bltin < 0 && prefix(new + 1, "builtin"))
7370 if (builtinloc < 0 && idx_bltin >= 0)
7371 builtinloc = idx_bltin; /* zap builtins */
7372 if (builtinloc >= 0 && idx_bltin < 0)
7374 clearcmdentry(firstchange);
7375 builtinloc = idx_bltin;
7390 #define TENDBQUOTE 12
7407 typedef smallint token_id_t;
7409 /* first char is indicating which tokens mark the end of a list */
7410 static const char *const tokname_array[] = {
7424 #define KWDOFFSET 13
7425 /* the following are keywords */
7447 static char buf[16];
7450 //if (tok < TSEMI) return tokname_array[tok] + 1;
7451 //sprintf(buf, "\"%s\"", tokname_array[tok] + 1);
7456 sprintf(buf + (tok >= TSEMI), "%s%c",
7457 tokname_array[tok] + 1, (tok >= TSEMI ? '"' : 0));
7461 /* Wrapper around strcmp for qsort/bsearch/... */
7463 pstrcmp(const void *a, const void *b)
7465 return strcmp((char*) a, (*(char**) b) + 1);
7468 static const char *const *
7469 findkwd(const char *s)
7471 return bsearch(s, tokname_array + KWDOFFSET,
7472 ARRAY_SIZE(tokname_array) - KWDOFFSET,
7473 sizeof(tokname_array[0]), pstrcmp);
7477 * Locate and print what a word is...
7480 describe_command(char *command, int describe_command_verbose)
7482 struct cmdentry entry;
7483 struct tblentry *cmdp;
7484 #if ENABLE_ASH_ALIAS
7485 const struct alias *ap;
7487 const char *path = pathval();
7489 if (describe_command_verbose) {
7493 /* First look at the keywords */
7494 if (findkwd(command)) {
7495 out1str(describe_command_verbose ? " is a shell keyword" : command);
7499 #if ENABLE_ASH_ALIAS
7500 /* Then look at the aliases */
7501 ap = lookupalias(command, 0);
7503 if (!describe_command_verbose) {
7508 out1fmt(" is an alias for %s", ap->val);
7512 /* Then check if it is a tracked alias */
7513 cmdp = cmdlookup(command, 0);
7515 entry.cmdtype = cmdp->cmdtype;
7516 entry.u = cmdp->param;
7518 /* Finally use brute force */
7519 find_command(command, &entry, DO_ABS, path);
7522 switch (entry.cmdtype) {
7524 int j = entry.u.index;
7530 p = padvance(&path, command);
7534 if (describe_command_verbose) {
7536 (cmdp ? " a tracked alias for" : nullstr), p
7545 if (describe_command_verbose) {
7546 out1str(" is a shell function");
7553 if (describe_command_verbose) {
7554 out1fmt(" is a %sshell builtin",
7555 IS_BUILTIN_SPECIAL(entry.u.cmd) ?
7556 "special " : nullstr
7564 if (describe_command_verbose) {
7565 out1str(": not found\n");
7570 outstr("\n", stdout);
7575 typecmd(int argc UNUSED_PARAM, char **argv)
7581 /* type -p ... ? (we don't bother checking for 'p') */
7582 if (argv[1] && argv[1][0] == '-') {
7587 err |= describe_command(argv[i++], verbose);
7592 #if ENABLE_ASH_CMDCMD
7594 commandcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
7602 while ((c = nextopt("pvV")) != '\0')
7604 verify |= VERIFY_VERBOSE;
7606 verify |= VERIFY_BRIEF;
7611 /* Mimic bash: just "command -v" doesn't complain, it's a nop */
7612 if (verify && (*argptr != NULL)) {
7613 return describe_command(*argptr, verify - VERIFY_BRIEF);
7621 /* ============ eval.c */
7623 static int funcblocksize; /* size of structures in function */
7624 static int funcstringsize; /* size of strings in node */
7625 static void *funcblock; /* block to allocate function from */
7626 static char *funcstring; /* block to allocate strings from */
7628 /* flags in argument to evaltree */
7629 #define EV_EXIT 01 /* exit after evaluating tree */
7630 #define EV_TESTED 02 /* exit status is checked; ignore -e flag */
7631 #define EV_BACKCMD 04 /* command executing within back quotes */
7633 static const short nodesize[N_NUMBER] = {
7634 [NCMD ] = SHELL_ALIGN(sizeof(struct ncmd)),
7635 [NPIPE ] = SHELL_ALIGN(sizeof(struct npipe)),
7636 [NREDIR ] = SHELL_ALIGN(sizeof(struct nredir)),
7637 [NBACKGND ] = SHELL_ALIGN(sizeof(struct nredir)),
7638 [NSUBSHELL] = SHELL_ALIGN(sizeof(struct nredir)),
7639 [NAND ] = SHELL_ALIGN(sizeof(struct nbinary)),
7640 [NOR ] = SHELL_ALIGN(sizeof(struct nbinary)),
7641 [NSEMI ] = SHELL_ALIGN(sizeof(struct nbinary)),
7642 [NIF ] = SHELL_ALIGN(sizeof(struct nif)),
7643 [NWHILE ] = SHELL_ALIGN(sizeof(struct nbinary)),
7644 [NUNTIL ] = SHELL_ALIGN(sizeof(struct nbinary)),
7645 [NFOR ] = SHELL_ALIGN(sizeof(struct nfor)),
7646 [NCASE ] = SHELL_ALIGN(sizeof(struct ncase)),
7647 [NCLIST ] = SHELL_ALIGN(sizeof(struct nclist)),
7648 [NDEFUN ] = SHELL_ALIGN(sizeof(struct narg)),
7649 [NARG ] = SHELL_ALIGN(sizeof(struct narg)),
7650 [NTO ] = SHELL_ALIGN(sizeof(struct nfile)),
7651 #if ENABLE_ASH_BASH_COMPAT
7652 [NTO2 ] = SHELL_ALIGN(sizeof(struct nfile)),
7654 [NCLOBBER ] = SHELL_ALIGN(sizeof(struct nfile)),
7655 [NFROM ] = SHELL_ALIGN(sizeof(struct nfile)),
7656 [NFROMTO ] = SHELL_ALIGN(sizeof(struct nfile)),
7657 [NAPPEND ] = SHELL_ALIGN(sizeof(struct nfile)),
7658 [NTOFD ] = SHELL_ALIGN(sizeof(struct ndup)),
7659 [NFROMFD ] = SHELL_ALIGN(sizeof(struct ndup)),
7660 [NHERE ] = SHELL_ALIGN(sizeof(struct nhere)),
7661 [NXHERE ] = SHELL_ALIGN(sizeof(struct nhere)),
7662 [NNOT ] = SHELL_ALIGN(sizeof(struct nnot)),
7665 static void calcsize(union node *n);
7668 sizenodelist(struct nodelist *lp)
7671 funcblocksize += SHELL_ALIGN(sizeof(struct nodelist));
7678 calcsize(union node *n)
7682 funcblocksize += nodesize[n->type];
7685 calcsize(n->ncmd.redirect);
7686 calcsize(n->ncmd.args);
7687 calcsize(n->ncmd.assign);
7690 sizenodelist(n->npipe.cmdlist);
7695 calcsize(n->nredir.redirect);
7696 calcsize(n->nredir.n);
7703 calcsize(n->nbinary.ch2);
7704 calcsize(n->nbinary.ch1);
7707 calcsize(n->nif.elsepart);
7708 calcsize(n->nif.ifpart);
7709 calcsize(n->nif.test);
7712 funcstringsize += strlen(n->nfor.var) + 1;
7713 calcsize(n->nfor.body);
7714 calcsize(n->nfor.args);
7717 calcsize(n->ncase.cases);
7718 calcsize(n->ncase.expr);
7721 calcsize(n->nclist.body);
7722 calcsize(n->nclist.pattern);
7723 calcsize(n->nclist.next);
7727 sizenodelist(n->narg.backquote);
7728 funcstringsize += strlen(n->narg.text) + 1;
7729 calcsize(n->narg.next);
7732 #if ENABLE_ASH_BASH_COMPAT
7739 calcsize(n->nfile.fname);
7740 calcsize(n->nfile.next);
7744 calcsize(n->ndup.vname);
7745 calcsize(n->ndup.next);
7749 calcsize(n->nhere.doc);
7750 calcsize(n->nhere.next);
7753 calcsize(n->nnot.com);
7759 nodeckstrdup(char *s)
7761 char *rtn = funcstring;
7763 strcpy(funcstring, s);
7764 funcstring += strlen(s) + 1;
7768 static union node *copynode(union node *);
7770 static struct nodelist *
7771 copynodelist(struct nodelist *lp)
7773 struct nodelist *start;
7774 struct nodelist **lpp;
7779 funcblock = (char *) funcblock + SHELL_ALIGN(sizeof(struct nodelist));
7780 (*lpp)->n = copynode(lp->n);
7782 lpp = &(*lpp)->next;
7789 copynode(union node *n)
7796 funcblock = (char *) funcblock + nodesize[n->type];
7800 new->ncmd.redirect = copynode(n->ncmd.redirect);
7801 new->ncmd.args = copynode(n->ncmd.args);
7802 new->ncmd.assign = copynode(n->ncmd.assign);
7805 new->npipe.cmdlist = copynodelist(n->npipe.cmdlist);
7806 new->npipe.pipe_backgnd = n->npipe.pipe_backgnd;
7811 new->nredir.redirect = copynode(n->nredir.redirect);
7812 new->nredir.n = copynode(n->nredir.n);
7819 new->nbinary.ch2 = copynode(n->nbinary.ch2);
7820 new->nbinary.ch1 = copynode(n->nbinary.ch1);
7823 new->nif.elsepart = copynode(n->nif.elsepart);
7824 new->nif.ifpart = copynode(n->nif.ifpart);
7825 new->nif.test = copynode(n->nif.test);
7828 new->nfor.var = nodeckstrdup(n->nfor.var);
7829 new->nfor.body = copynode(n->nfor.body);
7830 new->nfor.args = copynode(n->nfor.args);
7833 new->ncase.cases = copynode(n->ncase.cases);
7834 new->ncase.expr = copynode(n->ncase.expr);
7837 new->nclist.body = copynode(n->nclist.body);
7838 new->nclist.pattern = copynode(n->nclist.pattern);
7839 new->nclist.next = copynode(n->nclist.next);
7843 new->narg.backquote = copynodelist(n->narg.backquote);
7844 new->narg.text = nodeckstrdup(n->narg.text);
7845 new->narg.next = copynode(n->narg.next);
7848 #if ENABLE_ASH_BASH_COMPAT
7855 new->nfile.fname = copynode(n->nfile.fname);
7856 new->nfile.fd = n->nfile.fd;
7857 new->nfile.next = copynode(n->nfile.next);
7861 new->ndup.vname = copynode(n->ndup.vname);
7862 new->ndup.dupfd = n->ndup.dupfd;
7863 new->ndup.fd = n->ndup.fd;
7864 new->ndup.next = copynode(n->ndup.next);
7868 new->nhere.doc = copynode(n->nhere.doc);
7869 new->nhere.fd = n->nhere.fd;
7870 new->nhere.next = copynode(n->nhere.next);
7873 new->nnot.com = copynode(n->nnot.com);
7876 new->type = n->type;
7881 * Make a copy of a parse tree.
7883 static struct funcnode *
7884 copyfunc(union node *n)
7889 funcblocksize = offsetof(struct funcnode, n);
7892 blocksize = funcblocksize;
7893 f = ckmalloc(blocksize + funcstringsize);
7894 funcblock = (char *) f + offsetof(struct funcnode, n);
7895 funcstring = (char *) f + blocksize;
7902 * Define a shell function.
7905 defun(char *name, union node *func)
7907 struct cmdentry entry;
7910 entry.cmdtype = CMDFUNCTION;
7911 entry.u.func = copyfunc(func);
7912 addcmdentry(name, &entry);
7916 static int evalskip; /* set if we are skipping commands */
7917 /* reasons for skipping commands (see comment on breakcmd routine) */
7918 #define SKIPBREAK (1 << 0)
7919 #define SKIPCONT (1 << 1)
7920 #define SKIPFUNC (1 << 2)
7921 #define SKIPFILE (1 << 3)
7922 #define SKIPEVAL (1 << 4)
7923 static int skipcount; /* number of levels to skip */
7924 static int funcnest; /* depth of function calls */
7925 static int loopnest; /* current loop nesting level */
7927 /* forward decl way out to parsing code - dotrap needs it */
7928 static int evalstring(char *s, int mask);
7931 * Called to execute a trap. Perhaps we should avoid entering new trap
7932 * handlers while we are executing a trap handler.
7943 savestatus = exitstatus;
7947 for (i = 1, q = gotsig; i < NSIG; i++, q++) {
7955 skip = evalstring(p, SKIPEVAL);
7956 exitstatus = savestatus;
7964 /* forward declarations - evaluation is fairly recursive business... */
7965 static void evalloop(union node *, int);
7966 static void evalfor(union node *, int);
7967 static void evalcase(union node *, int);
7968 static void evalsubshell(union node *, int);
7969 static void expredir(union node *);
7970 static void evalpipe(union node *, int);
7971 static void evalcommand(union node *, int);
7972 static int evalbltin(const struct builtincmd *, int, char **);
7973 static void prehash(union node *);
7976 * Evaluate a parse tree. The value is left in the global variable
7980 evaltree(union node *n, int flags)
7983 struct jmploc *volatile savehandler = exception_handler;
7984 struct jmploc jmploc;
7986 void (*evalfn)(union node *, int);
7990 TRACE(("evaltree(NULL) called\n"));
7993 TRACE(("pid %d, evaltree(%p: %d, %d) called\n",
7994 getpid(), n, n->type, flags));
7996 exception_handler = &jmploc;
7998 int err = setjmp(jmploc.loc);
8000 /* if it was a signal, check for trap handlers */
8001 if (exception == EXSIG)
8003 /* continue on the way out */
8004 exception_handler = savehandler;
8005 longjmp(exception_handler->loc, err);
8012 out1fmt("Node type = %d\n", n->type);
8017 evaltree(n->nnot.com, EV_TESTED);
8018 status = !exitstatus;
8021 expredir(n->nredir.redirect);
8022 status = redirectsafe(n->nredir.redirect, REDIR_PUSH);
8024 evaltree(n->nredir.n, flags & EV_TESTED);
8025 status = exitstatus;
8027 popredir(/*drop:*/ 0, /*restore:*/ 0 /* not sure */);
8030 evalfn = evalcommand;
8032 if (eflag && !(flags & EV_TESTED))
8044 evalfn = evalsubshell;
8057 #error NAND + 1 != NOR
8059 #if NOR + 1 != NSEMI
8060 #error NOR + 1 != NSEMI
8062 unsigned is_or = n->type - NAND;
8065 (flags | ((is_or >> 1) - 1)) & EV_TESTED
8067 if (!exitstatus == is_or)
8080 evaltree(n->nif.test, EV_TESTED);
8083 if (exitstatus == 0) {
8086 } else if (n->nif.elsepart) {
8087 n = n->nif.elsepart;
8092 defun(n->narg.text, n->narg.next);
8096 exitstatus = status;
8101 exception_handler = savehandler;
8103 if (checkexit & exitstatus)
8104 evalskip |= SKIPEVAL;
8105 else if (pendingsig && dotrap())
8108 if (flags & EV_EXIT) {
8110 raise_exception(EXEXIT);
8114 #if !defined(__alpha__) || (defined(__GNUC__) && __GNUC__ >= 3)
8117 void evaltreenr(union node *, int) __attribute__ ((alias("evaltree"),__noreturn__));
8120 evalloop(union node *n, int flags)
8130 evaltree(n->nbinary.ch1, EV_TESTED);
8133 if (evalskip == SKIPCONT && --skipcount <= 0) {
8137 if (evalskip == SKIPBREAK && --skipcount <= 0)
8142 if (n->type != NWHILE)
8146 evaltree(n->nbinary.ch2, flags);
8147 status = exitstatus;
8152 exitstatus = status;
8156 evalfor(union node *n, int flags)
8158 struct arglist arglist;
8161 struct stackmark smark;
8163 setstackmark(&smark);
8164 arglist.list = NULL;
8165 arglist.lastp = &arglist.list;
8166 for (argp = n->nfor.args; argp; argp = argp->narg.next) {
8167 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE | EXP_RECORD);
8172 *arglist.lastp = NULL;
8177 for (sp = arglist.list; sp; sp = sp->next) {
8178 setvar(n->nfor.var, sp->text, 0);
8179 evaltree(n->nfor.body, flags);
8181 if (evalskip == SKIPCONT && --skipcount <= 0) {
8185 if (evalskip == SKIPBREAK && --skipcount <= 0)
8192 popstackmark(&smark);
8196 evalcase(union node *n, int flags)
8200 struct arglist arglist;
8201 struct stackmark smark;
8203 setstackmark(&smark);
8204 arglist.list = NULL;
8205 arglist.lastp = &arglist.list;
8206 expandarg(n->ncase.expr, &arglist, EXP_TILDE);
8208 for (cp = n->ncase.cases; cp && evalskip == 0; cp = cp->nclist.next) {
8209 for (patp = cp->nclist.pattern; patp; patp = patp->narg.next) {
8210 if (casematch(patp, arglist.list->text)) {
8211 if (evalskip == 0) {
8212 evaltree(cp->nclist.body, flags);
8219 popstackmark(&smark);
8223 * Kick off a subshell to evaluate a tree.
8226 evalsubshell(union node *n, int flags)
8229 int backgnd = (n->type == NBACKGND);
8232 expredir(n->nredir.redirect);
8233 if (!backgnd && flags & EV_EXIT && !trap[0])
8236 jp = makejob(/*n,*/ 1);
8237 if (forkshell(jp, n, backgnd) == 0) {
8241 flags &=~ EV_TESTED;
8243 redirect(n->nredir.redirect, 0);
8244 evaltreenr(n->nredir.n, flags);
8249 status = waitforjob(jp);
8250 exitstatus = status;
8255 * Compute the names of the files in a redirection list.
8257 static void fixredir(union node *, const char *, int);
8259 expredir(union node *n)
8263 for (redir = n; redir; redir = redir->nfile.next) {
8267 fn.lastp = &fn.list;
8268 switch (redir->type) {
8272 #if ENABLE_ASH_BASH_COMPAT
8277 expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
8278 #if ENABLE_ASH_BASH_COMPAT
8281 redir->nfile.expfname = fn.list->text;
8284 case NTOFD: /* >& */
8285 if (redir->ndup.vname) {
8286 expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE);
8287 if (fn.list == NULL)
8288 ash_msg_and_raise_error("redir error");
8289 #if ENABLE_ASH_BASH_COMPAT
8290 //FIXME: we used expandarg with different args!
8291 if (!isdigit_str9(fn.list->text)) {
8292 /* >&file, not >&fd */
8293 if (redir->nfile.fd != 1) /* 123>&file - BAD */
8294 ash_msg_and_raise_error("redir error");
8296 goto store_expfname;
8299 fixredir(redir, fn.list->text, 1);
8307 * Evaluate a pipeline. All the processes in the pipeline are children
8308 * of the process creating the pipeline. (This differs from some versions
8309 * of the shell, which make the last process in a pipeline the parent
8313 evalpipe(union node *n, int flags)
8316 struct nodelist *lp;
8321 TRACE(("evalpipe(0x%lx) called\n", (long)n));
8323 for (lp = n->npipe.cmdlist; lp; lp = lp->next)
8327 jp = makejob(/*n,*/ pipelen);
8329 for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
8333 if (pipe(pip) < 0) {
8335 ash_msg_and_raise_error("pipe call failed");
8338 if (forkshell(jp, lp->n, n->npipe.pipe_backgnd) == 0) {
8351 evaltreenr(lp->n, flags);
8359 if (n->npipe.pipe_backgnd == 0) {
8360 exitstatus = waitforjob(jp);
8361 TRACE(("evalpipe: job done exit status %d\n", exitstatus));
8367 * Controls whether the shell is interactive or not.
8370 setinteractive(int on)
8372 static smallint is_interactive;
8374 if (++on == is_interactive)
8376 is_interactive = on;
8380 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
8381 if (is_interactive > 1) {
8382 /* Looks like they want an interactive shell */
8383 static smallint did_banner;
8388 "%s built-in shell (ash)\n"
8389 "Enter 'help' for a list of built-in commands."
8404 setinteractive(iflag);
8406 #if ENABLE_FEATURE_EDITING_VI
8408 line_input_state->flags |= VI_MODE;
8410 line_input_state->flags &= ~VI_MODE;
8412 viflag = 0; /* forcibly keep the option off */
8416 static struct localvar *localvars;
8419 * Called after a function returns.
8420 * Interrupts must be off.
8425 struct localvar *lvp;
8428 while ((lvp = localvars) != NULL) {
8429 localvars = lvp->next;
8431 TRACE(("poplocalvar %s", vp ? vp->text : "-"));
8432 if (vp == NULL) { /* $- saved */
8433 memcpy(optlist, lvp->text, sizeof(optlist));
8434 free((char*)lvp->text);
8436 } else if ((lvp->flags & (VUNSET|VSTRFIXED)) == VUNSET) {
8440 (*vp->func)(strchrnul(lvp->text, '=') + 1);
8441 if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
8442 free((char*)vp->text);
8443 vp->flags = lvp->flags;
8444 vp->text = lvp->text;
8451 evalfun(struct funcnode *func, int argc, char **argv, int flags)
8453 volatile struct shparam saveparam;
8454 struct localvar *volatile savelocalvars;
8455 struct jmploc *volatile savehandler;
8456 struct jmploc jmploc;
8459 saveparam = shellparam;
8460 savelocalvars = localvars;
8461 e = setjmp(jmploc.loc);
8466 savehandler = exception_handler;
8467 exception_handler = &jmploc;
8469 shellparam.malloced = 0;
8473 shellparam.nparam = argc - 1;
8474 shellparam.p = argv + 1;
8475 #if ENABLE_ASH_GETOPTS
8476 shellparam.optind = 1;
8477 shellparam.optoff = -1;
8479 evaltree(&func->n, flags & EV_TESTED);
8485 localvars = savelocalvars;
8486 freeparam(&shellparam);
8487 shellparam = saveparam;
8488 exception_handler = savehandler;
8490 evalskip &= ~SKIPFUNC;
8494 #if ENABLE_ASH_CMDCMD
8496 parse_command_args(char **argv, const char **path)
8509 if (c == '-' && !*cp) {
8516 *path = bb_default_path;
8519 /* run 'typecmd' for other options */
8530 * Make a variable a local variable. When a variable is made local, it's
8531 * value and flags are saved in a localvar structure. The saved values
8532 * will be restored when the shell function returns. We handle the name
8533 * "-" as a special case.
8538 struct localvar *lvp;
8543 lvp = ckzalloc(sizeof(struct localvar));
8544 if (LONE_DASH(name)) {
8546 p = ckmalloc(sizeof(optlist));
8547 lvp->text = memcpy(p, optlist, sizeof(optlist));
8552 vpp = hashvar(name);
8553 vp = *findvar(vpp, name);
8554 eq = strchr(name, '=');
8557 setvareq(name, VSTRFIXED);
8559 setvar(name, NULL, VSTRFIXED);
8560 vp = *vpp; /* the new variable */
8561 lvp->flags = VUNSET;
8563 lvp->text = vp->text;
8564 lvp->flags = vp->flags;
8565 vp->flags |= VSTRFIXED|VTEXTFIXED;
8571 lvp->next = localvars;
8577 * The "local" command.
8580 localcmd(int argc UNUSED_PARAM, char **argv)
8585 while ((name = *argv++) != NULL) {
8592 falsecmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
8598 truecmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
8604 execcmd(int argc UNUSED_PARAM, char **argv)
8607 iflag = 0; /* exit on error */
8610 shellexec(argv + 1, pathval(), 0);
8616 * The return command.
8619 returncmd(int argc UNUSED_PARAM, char **argv)
8622 * If called outside a function, do what ksh does;
8623 * skip the rest of the file.
8625 evalskip = funcnest ? SKIPFUNC : SKIPFILE;
8626 return argv[1] ? number(argv[1]) : exitstatus;
8629 /* Forward declarations for builtintab[] */
8630 static int breakcmd(int, char **);
8631 static int dotcmd(int, char **);
8632 static int evalcmd(int, char **);
8633 static int exitcmd(int, char **);
8634 static int exportcmd(int, char **);
8635 #if ENABLE_ASH_GETOPTS
8636 static int getoptscmd(int, char **);
8638 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
8639 static int helpcmd(int, char **);
8641 #if ENABLE_ASH_MATH_SUPPORT
8642 static int letcmd(int, char **);
8644 static int readcmd(int, char **);
8645 static int setcmd(int, char **);
8646 static int shiftcmd(int, char **);
8647 static int timescmd(int, char **);
8648 static int trapcmd(int, char **);
8649 static int umaskcmd(int, char **);
8650 static int unsetcmd(int, char **);
8651 static int ulimitcmd(int, char **);
8653 #define BUILTIN_NOSPEC "0"
8654 #define BUILTIN_SPECIAL "1"
8655 #define BUILTIN_REGULAR "2"
8656 #define BUILTIN_SPEC_REG "3"
8657 #define BUILTIN_ASSIGN "4"
8658 #define BUILTIN_SPEC_ASSG "5"
8659 #define BUILTIN_REG_ASSG "6"
8660 #define BUILTIN_SPEC_REG_ASSG "7"
8662 /* We do not handle [[ expr ]] bashism bash-compatibly,
8663 * we make it a synonym of [ expr ].
8664 * Basically, word splitting and pathname expansion should NOT be performed
8666 * no word splitting: a="a b"; [[ $a = "a b" ]]; echo $? should print "0"
8667 * no pathname expansion: [[ /bin/m* = "/bin/m*" ]]; echo $? should print "0"
8668 * Additional operators:
8669 * || and && should work as -o and -a
8671 * Apart from the above, [[ expr ]] should work as [ expr ]
8674 #define echocmd echo_main
8675 #define printfcmd printf_main
8676 #define testcmd test_main
8678 /* Keep these in proper order since it is searched via bsearch() */
8679 static const struct builtincmd builtintab[] = {
8680 { BUILTIN_SPEC_REG ".", dotcmd },
8681 { BUILTIN_SPEC_REG ":", truecmd },
8682 #if ENABLE_ASH_BUILTIN_TEST
8683 { BUILTIN_REGULAR "[", testcmd },
8684 #if ENABLE_ASH_BASH_COMPAT
8685 { BUILTIN_REGULAR "[[", testcmd },
8688 #if ENABLE_ASH_ALIAS
8689 { BUILTIN_REG_ASSG "alias", aliascmd },
8692 { BUILTIN_REGULAR "bg", fg_bgcmd },
8694 { BUILTIN_SPEC_REG "break", breakcmd },
8695 { BUILTIN_REGULAR "cd", cdcmd },
8696 { BUILTIN_NOSPEC "chdir", cdcmd },
8697 #if ENABLE_ASH_CMDCMD
8698 { BUILTIN_REGULAR "command", commandcmd },
8700 { BUILTIN_SPEC_REG "continue", breakcmd },
8701 #if ENABLE_ASH_BUILTIN_ECHO
8702 { BUILTIN_REGULAR "echo", echocmd },
8704 { BUILTIN_SPEC_REG "eval", evalcmd },
8705 { BUILTIN_SPEC_REG "exec", execcmd },
8706 { BUILTIN_SPEC_REG "exit", exitcmd },
8707 { BUILTIN_SPEC_REG_ASSG "export", exportcmd },
8708 { BUILTIN_REGULAR "false", falsecmd },
8710 { BUILTIN_REGULAR "fg", fg_bgcmd },
8712 #if ENABLE_ASH_GETOPTS
8713 { BUILTIN_REGULAR "getopts", getoptscmd },
8715 { BUILTIN_NOSPEC "hash", hashcmd },
8716 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
8717 { BUILTIN_NOSPEC "help", helpcmd },
8720 { BUILTIN_REGULAR "jobs", jobscmd },
8721 { BUILTIN_REGULAR "kill", killcmd },
8723 #if ENABLE_ASH_MATH_SUPPORT
8724 { BUILTIN_NOSPEC "let", letcmd },
8726 { BUILTIN_ASSIGN "local", localcmd },
8727 #if ENABLE_ASH_BUILTIN_PRINTF
8728 { BUILTIN_REGULAR "printf", printfcmd },
8730 { BUILTIN_NOSPEC "pwd", pwdcmd },
8731 { BUILTIN_REGULAR "read", readcmd },
8732 { BUILTIN_SPEC_REG_ASSG "readonly", exportcmd },
8733 { BUILTIN_SPEC_REG "return", returncmd },
8734 { BUILTIN_SPEC_REG "set", setcmd },
8735 { BUILTIN_SPEC_REG "shift", shiftcmd },
8736 { BUILTIN_SPEC_REG "source", dotcmd },
8737 #if ENABLE_ASH_BUILTIN_TEST
8738 { BUILTIN_REGULAR "test", testcmd },
8740 { BUILTIN_SPEC_REG "times", timescmd },
8741 { BUILTIN_SPEC_REG "trap", trapcmd },
8742 { BUILTIN_REGULAR "true", truecmd },
8743 { BUILTIN_NOSPEC "type", typecmd },
8744 { BUILTIN_NOSPEC "ulimit", ulimitcmd },
8745 { BUILTIN_REGULAR "umask", umaskcmd },
8746 #if ENABLE_ASH_ALIAS
8747 { BUILTIN_REGULAR "unalias", unaliascmd },
8749 { BUILTIN_SPEC_REG "unset", unsetcmd },
8750 { BUILTIN_REGULAR "wait", waitcmd },
8753 /* Should match the above table! */
8754 #define COMMANDCMD (builtintab + \
8756 1 * ENABLE_ASH_BUILTIN_TEST + \
8757 1 * ENABLE_ASH_BUILTIN_TEST * ENABLE_ASH_BASH_COMPAT + \
8758 1 * ENABLE_ASH_ALIAS + \
8759 1 * ENABLE_ASH_JOB_CONTROL + \
8761 #define EXECCMD (builtintab + \
8763 1 * ENABLE_ASH_BUILTIN_TEST + \
8764 1 * ENABLE_ASH_BUILTIN_TEST * ENABLE_ASH_BASH_COMPAT + \
8765 1 * ENABLE_ASH_ALIAS + \
8766 1 * ENABLE_ASH_JOB_CONTROL + \
8768 1 * ENABLE_ASH_CMDCMD + \
8770 ENABLE_ASH_BUILTIN_ECHO + \
8774 * Search the table of builtin commands.
8776 static struct builtincmd *
8777 find_builtin(const char *name)
8779 struct builtincmd *bp;
8782 name, builtintab, ARRAY_SIZE(builtintab), sizeof(builtintab[0]),
8789 * Execute a simple command.
8792 isassignment(const char *p)
8794 const char *q = endofname(p);
8800 bltincmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
8802 /* Preserve exitstatus of a previous possible redirection
8803 * as POSIX mandates */
8804 return back_exitstatus;
8807 evalcommand(union node *cmd, int flags)
8809 static const struct builtincmd null_bltin = {
8810 "\0\0", bltincmd /* why three NULs? */
8812 struct stackmark smark;
8814 struct arglist arglist;
8815 struct arglist varlist;
8818 const struct strlist *sp;
8819 struct cmdentry cmdentry;
8826 struct builtincmd *bcmd;
8827 smallint cmd_is_exec;
8828 smallint pseudovarflag = 0;
8830 /* First expand the arguments. */
8831 TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
8832 setstackmark(&smark);
8833 back_exitstatus = 0;
8835 cmdentry.cmdtype = CMDBUILTIN;
8836 cmdentry.u.cmd = &null_bltin;
8837 varlist.lastp = &varlist.list;
8838 *varlist.lastp = NULL;
8839 arglist.lastp = &arglist.list;
8840 *arglist.lastp = NULL;
8843 if (cmd->ncmd.args) {
8844 bcmd = find_builtin(cmd->ncmd.args->narg.text);
8845 pseudovarflag = bcmd && IS_BUILTIN_ASSIGN(bcmd);
8848 for (argp = cmd->ncmd.args; argp; argp = argp->narg.next) {
8849 struct strlist **spp;
8851 spp = arglist.lastp;
8852 if (pseudovarflag && isassignment(argp->narg.text))
8853 expandarg(argp, &arglist, EXP_VARTILDE);
8855 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
8857 for (sp = *spp; sp; sp = sp->next)
8861 argv = nargv = stalloc(sizeof(char *) * (argc + 1));
8862 for (sp = arglist.list; sp; sp = sp->next) {
8863 TRACE(("evalcommand arg: %s\n", sp->text));
8864 *nargv++ = sp->text;
8869 if (iflag && funcnest == 0 && argc > 0)
8870 lastarg = nargv[-1];
8873 expredir(cmd->ncmd.redirect);
8874 status = redirectsafe(cmd->ncmd.redirect, REDIR_PUSH | REDIR_SAVEFD2);
8877 for (argp = cmd->ncmd.assign; argp; argp = argp->narg.next) {
8878 struct strlist **spp;
8881 spp = varlist.lastp;
8882 expandarg(argp, &varlist, EXP_VARTILDE);
8885 * Modify the command lookup path, if a PATH= assignment
8889 if (varequal(p, path))
8893 /* Print the command if xflag is set. */
8896 const char *p = " %s";
8899 fdprintf(preverrout_fd, p, expandstr(ps4val()));
8902 for (n = 0; n < 2; n++) {
8904 fdprintf(preverrout_fd, p, sp->text);
8912 safe_write(preverrout_fd, "\n", 1);
8918 /* Now locate the command. */
8920 const char *oldpath;
8921 int cmd_flag = DO_ERR;
8926 find_command(argv[0], &cmdentry, cmd_flag, path);
8927 if (cmdentry.cmdtype == CMDUNKNOWN) {
8933 /* implement bltin and command here */
8934 if (cmdentry.cmdtype != CMDBUILTIN)
8937 spclbltin = IS_BUILTIN_SPECIAL(cmdentry.u.cmd);
8938 if (cmdentry.u.cmd == EXECCMD)
8940 #if ENABLE_ASH_CMDCMD
8941 if (cmdentry.u.cmd == COMMANDCMD) {
8943 nargv = parse_command_args(argv, &path);
8946 argc -= nargv - argv;
8948 cmd_flag |= DO_NOFUNC;
8956 /* We have a redirection error. */
8958 raise_exception(EXERROR);
8960 exitstatus = status;
8964 /* Execute the command. */
8965 switch (cmdentry.cmdtype) {
8968 #if ENABLE_FEATURE_SH_NOFORK
8969 /* Hmmm... shouldn't it happen somewhere in forkshell() instead?
8970 * Why "fork off a child process if necessary" doesn't apply to NOFORK? */
8972 /* find_command() encodes applet_no as (-2 - applet_no) */
8973 int applet_no = (- cmdentry.u.index - 2);
8974 if (applet_no >= 0 && APPLET_IS_NOFORK(applet_no)) {
8975 listsetvar(varlist.list, VEXPORT|VSTACK);
8976 /* run <applet>_main() */
8977 exitstatus = run_nofork_applet(applet_no, argv);
8982 /* Fork off a child process if necessary. */
8983 if (!(flags & EV_EXIT) || trap[0]) {
8985 jp = makejob(/*cmd,*/ 1);
8986 if (forkshell(jp, cmd, FORK_FG) != 0) {
8987 exitstatus = waitforjob(jp);
8993 listsetvar(varlist.list, VEXPORT|VSTACK);
8994 shellexec(argv, path, cmdentry.u.index);
8998 cmdenviron = varlist.list;
9000 struct strlist *list = cmdenviron;
9002 if (spclbltin > 0 || argc == 0) {
9004 if (cmd_is_exec && argc > 1)
9007 listsetvar(list, i);
9009 /* Tight loop with builtins only:
9010 * "while kill -0 $child; do true; done"
9011 * will never exit even if $child died, unless we do this
9012 * to reap the zombie and make kill detect that it's gone: */
9013 dowait(DOWAIT_NONBLOCK, NULL);
9015 if (evalbltin(cmdentry.u.cmd, argc, argv)) {
9022 exit_status = 128 + SIGINT;
9024 exit_status = 128 + pendingsig;
9025 exitstatus = exit_status;
9026 if (i == EXINT || spclbltin > 0) {
9028 longjmp(exception_handler->loc, 1);
9035 listsetvar(varlist.list, 0);
9036 /* See above for the rationale */
9037 dowait(DOWAIT_NONBLOCK, NULL);
9038 if (evalfun(cmdentry.u.func, argc, argv, flags))
9044 popredir(/*drop:*/ cmd_is_exec, /*restore:*/ cmd_is_exec);
9046 /* dsl: I think this is intended to be used to support
9047 * '_' in 'vi' command mode during line editing...
9048 * However I implemented that within libedit itself.
9050 setvar("_", lastarg, 0);
9052 popstackmark(&smark);
9056 evalbltin(const struct builtincmd *cmd, int argc, char **argv)
9058 char *volatile savecmdname;
9059 struct jmploc *volatile savehandler;
9060 struct jmploc jmploc;
9063 savecmdname = commandname;
9064 i = setjmp(jmploc.loc);
9067 savehandler = exception_handler;
9068 exception_handler = &jmploc;
9069 commandname = argv[0];
9071 optptr = NULL; /* initialize nextopt */
9072 exitstatus = (*cmd->builtin)(argc, argv);
9073 flush_stdout_stderr();
9075 exitstatus |= ferror(stdout);
9077 commandname = savecmdname;
9079 exception_handler = savehandler;
9085 goodname(const char *p)
9087 return !*endofname(p);
9092 * Search for a command. This is called before we fork so that the
9093 * location of the command will be available in the parent as well as
9094 * the child. The check for "goodname" is an overly conservative
9095 * check that the name will not be subject to expansion.
9098 prehash(union node *n)
9100 struct cmdentry entry;
9102 if (n->type == NCMD && n->ncmd.args && goodname(n->ncmd.args->narg.text))
9103 find_command(n->ncmd.args->narg.text, &entry, 0, pathval());
9107 /* ============ Builtin commands
9109 * Builtin commands whose functions are closely tied to evaluation
9110 * are implemented here.
9114 * Handle break and continue commands. Break, continue, and return are
9115 * all handled by setting the evalskip flag. The evaluation routines
9116 * above all check this flag, and if it is set they start skipping
9117 * commands rather than executing them. The variable skipcount is
9118 * the number of loops to break/continue, or the number of function
9119 * levels to return. (The latter is always 1.) It should probably
9120 * be an error to break out of more loops than exist, but it isn't
9121 * in the standard shell so we don't make it one here.
9124 breakcmd(int argc UNUSED_PARAM, char **argv)
9126 int n = argv[1] ? number(argv[1]) : 1;
9129 ash_msg_and_raise_error(illnum, argv[1]);
9133 evalskip = (**argv == 'c') ? SKIPCONT : SKIPBREAK;
9140 /* ============ input.c
9142 * This implements the input routines used by the parser.
9146 INPUT_PUSH_FILE = 1,
9147 INPUT_NOFILE_OK = 2,
9150 static smallint checkkwd;
9151 /* values of checkkwd variable */
9152 #define CHKALIAS 0x1
9157 * Push a string back onto the input at this current parsefile level.
9158 * We handle aliases this way.
9160 #if !ENABLE_ASH_ALIAS
9161 #define pushstring(s, ap) pushstring(s)
9164 pushstring(char *s, struct alias *ap)
9171 if (g_parsefile->strpush) {
9172 sp = ckzalloc(sizeof(*sp));
9173 sp->prev = g_parsefile->strpush;
9175 sp = &(g_parsefile->basestrpush);
9177 g_parsefile->strpush = sp;
9178 sp->prev_string = g_parsefile->next_to_pgetc;
9179 sp->prev_left_in_line = g_parsefile->left_in_line;
9180 #if ENABLE_ASH_ALIAS
9183 ap->flag |= ALIASINUSE;
9187 g_parsefile->next_to_pgetc = s;
9188 g_parsefile->left_in_line = len;
9195 struct strpush *sp = g_parsefile->strpush;
9198 #if ENABLE_ASH_ALIAS
9200 if (g_parsefile->next_to_pgetc[-1] == ' '
9201 || g_parsefile->next_to_pgetc[-1] == '\t'
9203 checkkwd |= CHKALIAS;
9205 if (sp->string != sp->ap->val) {
9208 sp->ap->flag &= ~ALIASINUSE;
9209 if (sp->ap->flag & ALIASDEAD) {
9210 unalias(sp->ap->name);
9214 g_parsefile->next_to_pgetc = sp->prev_string;
9215 g_parsefile->left_in_line = sp->prev_left_in_line;
9216 g_parsefile->strpush = sp->prev;
9217 if (sp != &(g_parsefile->basestrpush))
9222 //FIXME: BASH_COMPAT with "...&" does TWO pungetc():
9223 //it peeks whether it is &>, and then pushes back both chars.
9224 //This function needs to save last *next_to_pgetc to buf[0]
9225 //to make two pungetc() reliable. Currently,
9226 // pgetc (out of buf: does preadfd), pgetc, pungetc, pungetc won't work...
9231 char *buf = g_parsefile->buf;
9233 g_parsefile->next_to_pgetc = buf;
9234 #if ENABLE_FEATURE_EDITING
9236 if (!iflag || g_parsefile->fd != STDIN_FILENO)
9237 nr = nonblock_safe_read(g_parsefile->fd, buf, BUFSIZ - 1);
9239 #if ENABLE_FEATURE_TAB_COMPLETION
9240 line_input_state->path_lookup = pathval();
9242 nr = read_line_input(cmdedit_prompt, buf, BUFSIZ, line_input_state);
9244 /* Ctrl+C pressed */
9253 if (nr < 0 && errno == 0) {
9254 /* Ctrl+D pressed */
9259 nr = nonblock_safe_read(g_parsefile->fd, buf, BUFSIZ - 1);
9263 /* nonblock_safe_read() handles this problem */
9265 if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
9266 int flags = fcntl(0, F_GETFL);
9267 if (flags >= 0 && (flags & O_NONBLOCK)) {
9268 flags &= ~O_NONBLOCK;
9269 if (fcntl(0, F_SETFL, flags) >= 0) {
9270 out2str("sh: turning off NDELAY mode\n");
9281 * Refill the input buffer and return the next input character:
9283 * 1) If a string was pushed back on the input, pop it;
9284 * 2) If an EOF was pushed back (g_parsefile->left_in_line < -BIGNUM)
9285 * or we are reading from a string so we can't refill the buffer,
9287 * 3) If the is more stuff in this buffer, use it else call read to fill it.
9288 * 4) Process input up to the next newline, deleting nul characters.
9290 //#define pgetc_debug(...) bb_error_msg(__VA_ARGS__)
9291 #define pgetc_debug(...) ((void)0)
9293 * NB: due to SIT(c) internals (syntax_index_table[] vector),
9294 * pgetc() and related functions must return chars SIGN-EXTENDED into ints,
9295 * not zero-extended. Seems fragile to me. Affects only !USE_SIT_FUNCTION case,
9296 * so we can fix it by ditching !USE_SIT_FUNCTION if Unicode requires that.
9304 while (g_parsefile->strpush) {
9305 #if ENABLE_ASH_ALIAS
9306 if (g_parsefile->left_in_line == -1
9307 && g_parsefile->strpush->ap
9308 && g_parsefile->next_to_pgetc[-1] != ' '
9309 && g_parsefile->next_to_pgetc[-1] != '\t'
9311 pgetc_debug("preadbuffer PEOA");
9316 /* try "pgetc" now: */
9317 pgetc_debug("preadbuffer internal pgetc at %d:%p'%s'",
9318 g_parsefile->left_in_line,
9319 g_parsefile->next_to_pgetc,
9320 g_parsefile->next_to_pgetc);
9321 if (--g_parsefile->left_in_line >= 0)
9322 return (unsigned char)(*g_parsefile->next_to_pgetc++);
9324 /* on both branches above g_parsefile->left_in_line < 0.
9325 * "pgetc" needs refilling.
9328 /* -90 is our -BIGNUM. Below we use -99 to mark "EOF on read",
9329 * pungetc() may increment it a few times.
9330 * Assuming it won't increment it to less than -90.
9332 if (g_parsefile->left_in_line < -90 || g_parsefile->buf == NULL) {
9333 pgetc_debug("preadbuffer PEOF1");
9334 /* even in failure keep left_in_line and next_to_pgetc
9335 * in lock step, for correct multi-layer pungetc.
9336 * left_in_line was decremented before preadbuffer(),
9337 * must inc next_to_pgetc: */
9338 g_parsefile->next_to_pgetc++;
9342 more = g_parsefile->left_in_buffer;
9344 flush_stdout_stderr();
9348 /* don't try reading again */
9349 g_parsefile->left_in_line = -99;
9350 pgetc_debug("preadbuffer PEOF2");
9351 g_parsefile->next_to_pgetc++;
9356 /* Find out where's the end of line.
9357 * Set g_parsefile->left_in_line
9358 * and g_parsefile->left_in_buffer acordingly.
9359 * NUL chars are deleted.
9361 q = g_parsefile->next_to_pgetc;
9369 memmove(q, q + 1, more);
9373 g_parsefile->left_in_line = q - g_parsefile->next_to_pgetc - 1;
9379 g_parsefile->left_in_line = q - g_parsefile->next_to_pgetc - 1;
9380 if (g_parsefile->left_in_line < 0)
9385 g_parsefile->left_in_buffer = more;
9390 out2str(g_parsefile->next_to_pgetc);
9394 pgetc_debug("preadbuffer at %d:%p'%s'",
9395 g_parsefile->left_in_line,
9396 g_parsefile->next_to_pgetc,
9397 g_parsefile->next_to_pgetc);
9398 return signed_char2int(*g_parsefile->next_to_pgetc++);
9401 #define pgetc_as_macro() \
9402 (--g_parsefile->left_in_line >= 0 \
9403 ? signed_char2int(*g_parsefile->next_to_pgetc++) \
9410 pgetc_debug("pgetc_fast at %d:%p'%s'",
9411 g_parsefile->left_in_line,
9412 g_parsefile->next_to_pgetc,
9413 g_parsefile->next_to_pgetc);
9414 return pgetc_as_macro();
9417 #if ENABLE_ASH_OPTIMIZE_FOR_SIZE
9418 #define pgetc_fast() pgetc()
9420 #define pgetc_fast() pgetc_as_macro()
9424 * Same as pgetc(), but ignores PEOA.
9426 #if ENABLE_ASH_ALIAS
9432 pgetc_debug("pgetc_fast at %d:%p'%s'",
9433 g_parsefile->left_in_line,
9434 g_parsefile->next_to_pgetc,
9435 g_parsefile->next_to_pgetc);
9437 } while (c == PEOA);
9441 #define pgetc2() pgetc()
9445 * Read a line from the script.
9448 pfgets(char *line, int len)
9454 while (--nleft > 0) {
9470 * Undo the last call to pgetc. Only one character may be pushed back.
9471 * PEOF may be pushed back.
9476 g_parsefile->left_in_line++;
9477 g_parsefile->next_to_pgetc--;
9478 pgetc_debug("pushed back to %d:%p'%s'",
9479 g_parsefile->left_in_line,
9480 g_parsefile->next_to_pgetc,
9481 g_parsefile->next_to_pgetc);
9485 * To handle the "." command, a stack of input files is used. Pushfile
9486 * adds a new entry to the stack and popfile restores the previous level.
9491 struct parsefile *pf;
9493 pf = ckzalloc(sizeof(*pf));
9494 pf->prev = g_parsefile;
9496 /*pf->strpush = NULL; - ckzalloc did it */
9497 /*pf->basestrpush.prev = NULL;*/
9504 struct parsefile *pf = g_parsefile;
9512 g_parsefile = pf->prev;
9518 * Return to top level.
9523 while (g_parsefile != &basepf)
9528 * Close the file(s) that the shell is reading commands from. Called
9529 * after a fork is done.
9535 if (g_parsefile->fd > 0) {
9536 close(g_parsefile->fd);
9537 g_parsefile->fd = 0;
9542 * Like setinputfile, but takes an open file descriptor. Call this with
9546 setinputfd(int fd, int push)
9548 close_on_exec_on(fd);
9551 g_parsefile->buf = NULL;
9553 g_parsefile->fd = fd;
9554 if (g_parsefile->buf == NULL)
9555 g_parsefile->buf = ckmalloc(IBUFSIZ);
9556 g_parsefile->left_in_buffer = 0;
9557 g_parsefile->left_in_line = 0;
9558 g_parsefile->linno = 1;
9562 * Set the input to take input from a file. If push is set, push the
9563 * old input onto the stack first.
9566 setinputfile(const char *fname, int flags)
9572 fd = open(fname, O_RDONLY);
9574 if (flags & INPUT_NOFILE_OK)
9576 ash_msg_and_raise_error("can't open %s", fname);
9579 fd2 = copyfd(fd, 10);
9582 ash_msg_and_raise_error("out of file descriptors");
9585 setinputfd(fd, flags & INPUT_PUSH_FILE);
9592 * Like setinputfile, but takes input from a string.
9595 setinputstring(char *string)
9599 g_parsefile->next_to_pgetc = string;
9600 g_parsefile->left_in_line = strlen(string);
9601 g_parsefile->buf = NULL;
9602 g_parsefile->linno = 1;
9607 /* ============ mail.c
9609 * Routines to check for mail.
9614 #define MAXMBOXES 10
9616 /* times of mailboxes */
9617 static time_t mailtime[MAXMBOXES];
9618 /* Set if MAIL or MAILPATH is changed. */
9619 static smallint mail_var_path_changed;
9622 * Print appropriate message(s) if mail has arrived.
9623 * If mail_var_path_changed is set,
9624 * then the value of MAIL has mail_var_path_changed,
9625 * so we just update the values.
9634 struct stackmark smark;
9637 setstackmark(&smark);
9638 mpath = mpathset() ? mpathval() : mailval();
9639 for (mtp = mailtime; mtp < mailtime + MAXMBOXES; mtp++) {
9640 p = padvance(&mpath, nullstr);
9645 for (q = p; *q; q++)
9651 q[-1] = '\0'; /* delete trailing '/' */
9652 if (stat(p, &statb) < 0) {
9656 if (!mail_var_path_changed && statb.st_mtime != *mtp) {
9659 pathopt ? pathopt : "you have mail"
9662 *mtp = statb.st_mtime;
9664 mail_var_path_changed = 0;
9665 popstackmark(&smark);
9669 changemail(const char *val UNUSED_PARAM)
9671 mail_var_path_changed = 1;
9674 #endif /* ASH_MAIL */
9677 /* ============ ??? */
9680 * Set the shell parameters.
9683 setparam(char **argv)
9689 for (nparam = 0; argv[nparam]; nparam++)
9691 ap = newparam = ckmalloc((nparam + 1) * sizeof(*ap));
9693 *ap++ = ckstrdup(*argv++);
9696 freeparam(&shellparam);
9697 shellparam.malloced = 1;
9698 shellparam.nparam = nparam;
9699 shellparam.p = newparam;
9700 #if ENABLE_ASH_GETOPTS
9701 shellparam.optind = 1;
9702 shellparam.optoff = -1;
9707 * Process shell options. The global variable argptr contains a pointer
9708 * to the argument list; we advance it past the options.
9710 * SUSv3 section 2.8.1 "Consequences of Shell Errors" says:
9711 * For a non-interactive shell, an error condition encountered
9712 * by a special built-in ... shall cause the shell to write a diagnostic message
9713 * to standard error and exit as shown in the following table:
9714 * Error Special Built-In
9716 * Utility syntax error (option or operand error) Shall exit
9718 * However, in bug 1142 (http://busybox.net/bugs/view.php?id=1142)
9719 * we see that bash does not do that (set "finishes" with error code 1 instead,
9720 * and shell continues), and people rely on this behavior!
9722 * set -o barfoo 2>/dev/null
9725 * Oh well. Let's mimic that.
9728 plus_minus_o(char *name, int val)
9733 for (i = 0; i < NOPTS; i++) {
9734 if (strcmp(name, optnames(i)) == 0) {
9739 ash_msg("illegal option %co %s", val ? '-' : '+', name);
9742 for (i = 0; i < NOPTS; i++) {
9744 out1fmt("%-16s%s\n", optnames(i), optlist[i] ? "on" : "off");
9746 out1fmt("set %co %s\n", optlist[i] ? '-' : '+', optnames(i));
9752 setoption(int flag, int val)
9756 for (i = 0; i < NOPTS; i++) {
9757 if (optletters(i) == flag) {
9762 ash_msg_and_raise_error("illegal option %c%c", val ? '-' : '+', flag);
9766 options(int cmdline)
9774 while ((p = *argptr) != NULL) {
9776 if (c != '-' && c != '+')
9779 val = 0; /* val = 0 if c == '+' */
9782 if (p[0] == '\0' || LONE_DASH(p)) {
9784 /* "-" means turn off -x and -v */
9787 /* "--" means reset params */
9788 else if (*argptr == NULL)
9791 break; /* "-" or "--" terminates options */
9794 /* first char was + or - */
9795 while ((c = *p++) != '\0') {
9796 /* bash 3.2 indeed handles -c CMD and +c CMD the same */
9797 if (c == 'c' && cmdline) {
9798 minusc = p; /* command is after shell args */
9799 } else if (c == 'o') {
9800 if (plus_minus_o(*argptr, val)) {
9801 /* it already printed err message */
9802 return 1; /* error */
9806 } else if (cmdline && (c == 'l')) { /* -l or +l == --login */
9808 /* bash does not accept +-login, we also won't */
9809 } else if (cmdline && val && (c == '-')) { /* long options */
9810 if (strcmp(p, "login") == 0)
9822 * The shift builtin command.
9825 shiftcmd(int argc UNUSED_PARAM, char **argv)
9832 n = number(argv[1]);
9833 if (n > shellparam.nparam)
9834 n = 0; /* bash compat, was = shellparam.nparam; */
9836 shellparam.nparam -= n;
9837 for (ap1 = shellparam.p; --n >= 0; ap1++) {
9838 if (shellparam.malloced)
9842 while ((*ap2++ = *ap1++) != NULL)
9844 #if ENABLE_ASH_GETOPTS
9845 shellparam.optind = 1;
9846 shellparam.optoff = -1;
9853 * POSIX requires that 'set' (but not export or readonly) output the
9854 * variables in lexicographic order - by the locale's collating order (sigh).
9855 * Maybe we could keep them in an ordered balanced binary tree
9856 * instead of hashed lists.
9857 * For now just roll 'em through qsort for printing...
9860 showvars(const char *sep_prefix, int on, int off)
9865 ep = listvars(on, off, &epend);
9866 qsort(ep, epend - ep, sizeof(char *), vpcmp);
9868 sep = *sep_prefix ? " " : sep_prefix;
9870 for (; ep < epend; ep++) {
9874 p = strchrnul(*ep, '=');
9877 q = single_quote(++p);
9878 out1fmt("%s%s%.*s%s\n", sep_prefix, sep, (int)(p - *ep), *ep, q);
9884 * The set command builtin.
9887 setcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9892 return showvars(nullstr, 0, VUNSET);
9895 if (!options(0)) { /* if no parse error... */
9898 if (*argptr != NULL) {
9906 #if ENABLE_ASH_RANDOM_SUPPORT
9908 change_random(const char *value)
9910 /* Galois LFSR parameter */
9911 /* Taps at 32 31 29 1: */
9912 enum { MASK = 0x8000000b };
9913 /* Another example - taps at 32 31 30 10: */
9914 /* MASK = 0x00400007 */
9916 if (value == NULL) {
9917 /* "get", generate */
9920 /* LCG has period of 2^32 and alternating lowest bit */
9921 random_LCG = 1664525 * random_LCG + 1013904223;
9922 /* Galois LFSR has period of 2^32-1 = 3 * 5 * 17 * 257 * 65537 */
9923 t = (random_galois_LFSR << 1);
9924 if (random_galois_LFSR < 0) /* if we just shifted 1 out of msb... */
9926 random_galois_LFSR = t;
9927 /* Both are weak, combining them gives better randomness
9928 * and ~2^64 period. & 0x7fff is probably bash compat
9929 * for $RANDOM range. Combining with subtraction is
9930 * just for fun. + and ^ would work equally well. */
9931 t = (t - random_LCG) & 0x7fff;
9932 /* set without recursion */
9933 setvar(vrandom.text, utoa(t), VNOFUNC);
9934 vrandom.flags &= ~VNOFUNC;
9937 random_galois_LFSR = random_LCG = strtoul(value, (char **)NULL, 10);
9942 #if ENABLE_ASH_GETOPTS
9944 getopts(char *optstr, char *optvar, char **optfirst, int *param_optind, int *optoff)
9953 if (*param_optind < 1)
9955 optnext = optfirst + *param_optind - 1;
9957 if (*param_optind <= 1 || *optoff < 0 || (int)strlen(optnext[-1]) < *optoff)
9960 p = optnext[-1] + *optoff;
9961 if (p == NULL || *p == '\0') {
9962 /* Current word is done, advance */
9964 if (p == NULL || *p != '-' || *++p == '\0') {
9971 if (LONE_DASH(p)) /* check for "--" */
9976 for (q = optstr; *q != c;) {
9978 if (optstr[0] == ':') {
9981 err |= setvarsafe("OPTARG", s, 0);
9983 fprintf(stderr, "Illegal option -%c\n", c);
9994 if (*p == '\0' && (p = *optnext) == NULL) {
9995 if (optstr[0] == ':') {
9998 err |= setvarsafe("OPTARG", s, 0);
10001 fprintf(stderr, "No arg for -%c option\n", c);
10002 unsetvar("OPTARG");
10010 err |= setvarsafe("OPTARG", p, 0);
10013 err |= setvarsafe("OPTARG", nullstr, 0);
10015 *optoff = p ? p - *(optnext - 1) : -1;
10016 *param_optind = optnext - optfirst + 1;
10017 fmtstr(s, sizeof(s), "%d", *param_optind);
10018 err |= setvarsafe("OPTIND", s, VNOFUNC);
10021 err |= setvarsafe(optvar, s, 0);
10025 flush_stdout_stderr();
10026 raise_exception(EXERROR);
10032 * The getopts builtin. Shellparam.optnext points to the next argument
10033 * to be processed. Shellparam.optptr points to the next character to
10034 * be processed in the current argument. If shellparam.optnext is NULL,
10035 * then it's the first time getopts has been called.
10038 getoptscmd(int argc, char **argv)
10043 ash_msg_and_raise_error("usage: getopts optstring var [arg]");
10045 optbase = shellparam.p;
10046 if (shellparam.optind > shellparam.nparam + 1) {
10047 shellparam.optind = 1;
10048 shellparam.optoff = -1;
10051 optbase = &argv[3];
10052 if (shellparam.optind > argc - 2) {
10053 shellparam.optind = 1;
10054 shellparam.optoff = -1;
10058 return getopts(argv[1], argv[2], optbase, &shellparam.optind,
10059 &shellparam.optoff);
10061 #endif /* ASH_GETOPTS */
10064 /* ============ Shell parser */
10067 struct heredoc *next; /* next here document in list */
10068 union node *here; /* redirection node */
10069 char *eofmark; /* string indicating end of input */
10070 smallint striptabs; /* if set, strip leading tabs */
10073 static smallint tokpushback; /* last token pushed back */
10074 static smallint parsebackquote; /* nonzero if we are inside backquotes */
10075 static smallint quoteflag; /* set if (part of) last token was quoted */
10076 static token_id_t lasttoken; /* last token read (integer id Txxx) */
10077 static struct heredoc *heredoclist; /* list of here documents to read */
10078 static char *wordtext; /* text of last word returned by readtoken */
10079 static struct nodelist *backquotelist;
10080 static union node *redirnode;
10081 static struct heredoc *heredoc;
10083 * NEOF is returned by parsecmd when it encounters an end of file. It
10084 * must be distinct from NULL, so we use the address of a variable that
10085 * happens to be handy.
10087 #define NEOF ((union node *)&tokpushback)
10089 static void raise_error_syntax(const char *) NORETURN;
10091 raise_error_syntax(const char *msg)
10093 ash_msg_and_raise_error("syntax error: %s", msg);
10098 * Called when an unexpected token is read during the parse. The argument
10099 * is the token that is expected, or -1 if more than one type of token can
10100 * occur at this point.
10102 static void raise_error_unexpected_syntax(int) NORETURN;
10104 raise_error_unexpected_syntax(int token)
10109 l = sprintf(msg, "unexpected %s", tokname(lasttoken));
10111 sprintf(msg + l, " (expecting %s)", tokname(token));
10112 raise_error_syntax(msg);
10116 #define EOFMARKLEN 79
10118 /* parsing is heavily cross-recursive, need these forward decls */
10119 static union node *andor(void);
10120 static union node *pipeline(void);
10121 static union node *parse_command(void);
10122 static void parseheredoc(void);
10123 static char peektoken(void);
10124 static int readtoken(void);
10126 static union node *
10129 union node *n1, *n2, *n3;
10132 checkkwd = CHKNL | CHKKWD | CHKALIAS;
10133 if (nlflag == 2 && peektoken())
10139 if (tok == TBACKGND) {
10140 if (n2->type == NPIPE) {
10141 n2->npipe.pipe_backgnd = 1;
10143 if (n2->type != NREDIR) {
10144 n3 = stzalloc(sizeof(struct nredir));
10146 /*n3->nredir.redirect = NULL; - stzalloc did it */
10149 n2->type = NBACKGND;
10155 n3 = stzalloc(sizeof(struct nbinary));
10157 n3->nbinary.ch1 = n1;
10158 n3->nbinary.ch2 = n2;
10174 checkkwd = CHKNL | CHKKWD | CHKALIAS;
10182 pungetc(); /* push back EOF on input */
10186 raise_error_unexpected_syntax(-1);
10193 static union node *
10196 union node *n1, *n2, *n3;
10204 } else if (t == TOR) {
10210 checkkwd = CHKNL | CHKKWD | CHKALIAS;
10212 n3 = stzalloc(sizeof(struct nbinary));
10214 n3->nbinary.ch1 = n1;
10215 n3->nbinary.ch2 = n2;
10220 static union node *
10223 union node *n1, *n2, *pipenode;
10224 struct nodelist *lp, *prev;
10228 TRACE(("pipeline: entered\n"));
10229 if (readtoken() == TNOT) {
10231 checkkwd = CHKKWD | CHKALIAS;
10234 n1 = parse_command();
10235 if (readtoken() == TPIPE) {
10236 pipenode = stzalloc(sizeof(struct npipe));
10237 pipenode->type = NPIPE;
10238 /*pipenode->npipe.pipe_backgnd = 0; - stzalloc did it */
10239 lp = stzalloc(sizeof(struct nodelist));
10240 pipenode->npipe.cmdlist = lp;
10244 lp = stzalloc(sizeof(struct nodelist));
10245 checkkwd = CHKNL | CHKKWD | CHKALIAS;
10246 lp->n = parse_command();
10248 } while (readtoken() == TPIPE);
10254 n2 = stzalloc(sizeof(struct nnot));
10262 static union node *
10267 n = stzalloc(sizeof(struct narg));
10269 /*n->narg.next = NULL; - stzalloc did it */
10270 n->narg.text = wordtext;
10271 n->narg.backquote = backquotelist;
10276 fixredir(union node *n, const char *text, int err)
10280 TRACE(("Fix redir %s %d\n", text, err));
10282 n->ndup.vname = NULL;
10284 fd = bb_strtou(text, NULL, 10);
10285 if (!errno && fd >= 0)
10286 n->ndup.dupfd = fd;
10287 else if (LONE_DASH(text))
10288 n->ndup.dupfd = -1;
10291 raise_error_syntax("bad fd number");
10292 n->ndup.vname = makename();
10297 * Returns true if the text contains nothing to expand (no dollar signs
10301 noexpand(const char *text)
10307 while ((c = *p++) != '\0') {
10308 if (c == CTLQUOTEMARK)
10312 else if (SIT((signed char)c, BASESYNTAX) == CCTL)
10321 union node *n = redirnode;
10323 if (readtoken() != TWORD)
10324 raise_error_unexpected_syntax(-1);
10325 if (n->type == NHERE) {
10326 struct heredoc *here = heredoc;
10330 if (quoteflag == 0)
10332 TRACE(("Here document %d\n", n->type));
10333 if (!noexpand(wordtext) || (i = strlen(wordtext)) == 0 || i > EOFMARKLEN)
10334 raise_error_syntax("illegal eof marker for << redirection");
10335 rmescapes(wordtext);
10336 here->eofmark = wordtext;
10338 if (heredoclist == NULL)
10339 heredoclist = here;
10341 for (p = heredoclist; p->next; p = p->next)
10345 } else if (n->type == NTOFD || n->type == NFROMFD) {
10346 fixredir(n, wordtext, 0);
10348 n->nfile.fname = makename();
10352 static union node *
10355 union node *args, **app;
10356 union node *n = NULL;
10357 union node *vars, **vpp;
10358 union node **rpp, *redir;
10360 #if ENABLE_ASH_BASH_COMPAT
10361 smallint double_brackets_flag = 0;
10371 savecheckkwd = CHKALIAS;
10374 checkkwd = savecheckkwd;
10377 #if ENABLE_ASH_BASH_COMPAT
10378 case TAND: /* "&&" */
10379 case TOR: /* "||" */
10380 if (!double_brackets_flag) {
10384 wordtext = (char *) (t == TAND ? "-a" : "-o");
10387 n = stzalloc(sizeof(struct narg));
10389 /*n->narg.next = NULL; - stzalloc did it */
10390 n->narg.text = wordtext;
10391 #if ENABLE_ASH_BASH_COMPAT
10392 if (strcmp("[[", wordtext) == 0)
10393 double_brackets_flag = 1;
10394 else if (strcmp("]]", wordtext) == 0)
10395 double_brackets_flag = 0;
10397 n->narg.backquote = backquotelist;
10398 if (savecheckkwd && isassignment(wordtext)) {
10400 vpp = &n->narg.next;
10403 app = &n->narg.next;
10408 *rpp = n = redirnode;
10409 rpp = &n->nfile.next;
10410 parsefname(); /* read name of redirection file */
10413 if (args && app == &args->narg.next
10416 struct builtincmd *bcmd;
10419 /* We have a function */
10420 if (readtoken() != TRP)
10421 raise_error_unexpected_syntax(TRP);
10422 name = n->narg.text;
10423 if (!goodname(name)
10424 || ((bcmd = find_builtin(name)) && IS_BUILTIN_SPECIAL(bcmd))
10426 raise_error_syntax("bad function name");
10429 checkkwd = CHKNL | CHKKWD | CHKALIAS;
10430 n->narg.next = parse_command();
10443 n = stzalloc(sizeof(struct ncmd));
10445 n->ncmd.args = args;
10446 n->ncmd.assign = vars;
10447 n->ncmd.redirect = redir;
10451 static union node *
10452 parse_command(void)
10454 union node *n1, *n2;
10455 union node *ap, **app;
10456 union node *cp, **cpp;
10457 union node *redir, **rpp;
10464 switch (readtoken()) {
10466 raise_error_unexpected_syntax(-1);
10469 n1 = stzalloc(sizeof(struct nif));
10471 n1->nif.test = list(0);
10472 if (readtoken() != TTHEN)
10473 raise_error_unexpected_syntax(TTHEN);
10474 n1->nif.ifpart = list(0);
10476 while (readtoken() == TELIF) {
10477 n2->nif.elsepart = stzalloc(sizeof(struct nif));
10478 n2 = n2->nif.elsepart;
10480 n2->nif.test = list(0);
10481 if (readtoken() != TTHEN)
10482 raise_error_unexpected_syntax(TTHEN);
10483 n2->nif.ifpart = list(0);
10485 if (lasttoken == TELSE)
10486 n2->nif.elsepart = list(0);
10488 n2->nif.elsepart = NULL;
10496 n1 = stzalloc(sizeof(struct nbinary));
10497 n1->type = (lasttoken == TWHILE) ? NWHILE : NUNTIL;
10498 n1->nbinary.ch1 = list(0);
10501 TRACE(("expecting DO got %s %s\n", tokname(got),
10502 got == TWORD ? wordtext : ""));
10503 raise_error_unexpected_syntax(TDO);
10505 n1->nbinary.ch2 = list(0);
10510 if (readtoken() != TWORD || quoteflag || !goodname(wordtext))
10511 raise_error_syntax("bad for loop variable");
10512 n1 = stzalloc(sizeof(struct nfor));
10514 n1->nfor.var = wordtext;
10515 checkkwd = CHKKWD | CHKALIAS;
10516 if (readtoken() == TIN) {
10518 while (readtoken() == TWORD) {
10519 n2 = stzalloc(sizeof(struct narg));
10521 /*n2->narg.next = NULL; - stzalloc did it */
10522 n2->narg.text = wordtext;
10523 n2->narg.backquote = backquotelist;
10525 app = &n2->narg.next;
10528 n1->nfor.args = ap;
10529 if (lasttoken != TNL && lasttoken != TSEMI)
10530 raise_error_unexpected_syntax(-1);
10532 n2 = stzalloc(sizeof(struct narg));
10534 /*n2->narg.next = NULL; - stzalloc did it */
10535 n2->narg.text = (char *)dolatstr;
10536 /*n2->narg.backquote = NULL;*/
10537 n1->nfor.args = n2;
10539 * Newline or semicolon here is optional (but note
10540 * that the original Bourne shell only allowed NL).
10542 if (lasttoken != TNL && lasttoken != TSEMI)
10545 checkkwd = CHKNL | CHKKWD | CHKALIAS;
10546 if (readtoken() != TDO)
10547 raise_error_unexpected_syntax(TDO);
10548 n1->nfor.body = list(0);
10552 n1 = stzalloc(sizeof(struct ncase));
10554 if (readtoken() != TWORD)
10555 raise_error_unexpected_syntax(TWORD);
10556 n1->ncase.expr = n2 = stzalloc(sizeof(struct narg));
10558 /*n2->narg.next = NULL; - stzalloc did it */
10559 n2->narg.text = wordtext;
10560 n2->narg.backquote = backquotelist;
10562 checkkwd = CHKKWD | CHKALIAS;
10563 } while (readtoken() == TNL);
10564 if (lasttoken != TIN)
10565 raise_error_unexpected_syntax(TIN);
10566 cpp = &n1->ncase.cases;
10568 checkkwd = CHKNL | CHKKWD;
10570 while (t != TESAC) {
10571 if (lasttoken == TLP)
10573 *cpp = cp = stzalloc(sizeof(struct nclist));
10575 app = &cp->nclist.pattern;
10577 *app = ap = stzalloc(sizeof(struct narg));
10579 /*ap->narg.next = NULL; - stzalloc did it */
10580 ap->narg.text = wordtext;
10581 ap->narg.backquote = backquotelist;
10582 if (readtoken() != TPIPE)
10584 app = &ap->narg.next;
10587 //ap->narg.next = NULL;
10588 if (lasttoken != TRP)
10589 raise_error_unexpected_syntax(TRP);
10590 cp->nclist.body = list(2);
10592 cpp = &cp->nclist.next;
10594 checkkwd = CHKNL | CHKKWD;
10598 raise_error_unexpected_syntax(TENDCASE);
10605 n1 = stzalloc(sizeof(struct nredir));
10606 n1->type = NSUBSHELL;
10607 n1->nredir.n = list(0);
10608 /*n1->nredir.redirect = NULL; - stzalloc did it */
10618 return simplecmd();
10621 if (readtoken() != t)
10622 raise_error_unexpected_syntax(t);
10625 /* Now check for redirection which may follow command */
10626 checkkwd = CHKKWD | CHKALIAS;
10628 while (readtoken() == TREDIR) {
10629 *rpp = n2 = redirnode;
10630 rpp = &n2->nfile.next;
10636 if (n1->type != NSUBSHELL) {
10637 n2 = stzalloc(sizeof(struct nredir));
10642 n1->nredir.redirect = redir;
10647 #if ENABLE_ASH_BASH_COMPAT
10648 static int decode_dollar_squote(void)
10650 static const char C_escapes[] ALIGN1 = "nrbtfav""x\\01234567";
10656 p = strchr(C_escapes, c);
10661 if ((unsigned char)(c - '0') <= 7) { /* \ooo */
10665 } while ((unsigned char)(c - '0') <= 7 && --cnt);
10667 } else if (c == 'x') { /* \xHH */
10671 } while (isxdigit(c) && --cnt);
10673 if (cnt == 3) { /* \x but next char is "bad" */
10677 } else { /* simple seq like \\ or \t */
10682 c = bb_process_escape_sequence((void*)&p);
10683 } else { /* unrecognized "\z": print both chars unless ' or " */
10684 if (c != '\'' && c != '"') {
10686 c |= 0x100; /* "please encode \, then me" */
10694 * If eofmark is NULL, read a word or a redirection symbol. If eofmark
10695 * is not NULL, read a here document. In the latter case, eofmark is the
10696 * word which marks the end of the document and striptabs is true if
10697 * leading tabs should be stripped from the document. The argument firstc
10698 * is the first character of the input token or document.
10700 * Because C does not have internal subroutines, I have simulated them
10701 * using goto's to implement the subroutine linkage. The following macros
10702 * will run code that appears at the end of readtoken1.
10704 #define CHECKEND() {goto checkend; checkend_return:;}
10705 #define PARSEREDIR() {goto parseredir; parseredir_return:;}
10706 #define PARSESUB() {goto parsesub; parsesub_return:;}
10707 #define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
10708 #define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
10709 #define PARSEARITH() {goto parsearith; parsearith_return:;}
10711 readtoken1(int firstc, int syntax, char *eofmark, int striptabs)
10713 /* NB: syntax parameter fits into smallint */
10717 char line[EOFMARKLEN + 1];
10718 struct nodelist *bqlist;
10722 smallint prevsyntax; /* syntax before arithmetic */
10723 #if ENABLE_ASH_EXPAND_PRMT
10724 smallint pssyntax; /* we are expanding a prompt string */
10726 int varnest; /* levels of variables expansion */
10727 int arinest; /* levels of arithmetic expansion */
10728 int parenlevel; /* levels of parens in arithmetic */
10729 int dqvarnest; /* levels of variables expansion within double quotes */
10731 USE_ASH_BASH_COMPAT(smallint bash_dollar_squote = 0;)
10734 /* Avoid longjmp clobbering */
10740 (void) &parenlevel;
10743 (void) &prevsyntax;
10746 startlinno = g_parsefile->linno;
10751 #if ENABLE_ASH_EXPAND_PRMT
10752 pssyntax = (syntax == PSSYNTAX);
10756 dblquote = (syntax == DQSYNTAX);
10762 STARTSTACKSTR(out);
10764 /* For each line, until end of word */
10766 CHECKEND(); /* set c to PEOF if at end of here document */
10767 for (;;) { /* until end of line or end of word */
10768 CHECKSTRSPACE(4, out); /* permit 4 calls to USTPUTC */
10769 switch (SIT(c, syntax)) {
10770 case CNL: /* '\n' */
10771 if (syntax == BASESYNTAX)
10772 goto endword; /* exit outer loop */
10774 g_parsefile->linno++;
10778 goto loop; /* continue outer loop */
10783 if (eofmark == NULL || dblquote)
10784 USTPUTC(CTLESC, out);
10785 #if ENABLE_ASH_BASH_COMPAT
10786 if (c == '\\' && bash_dollar_squote) {
10787 c = decode_dollar_squote();
10789 USTPUTC('\\', out);
10790 c = (unsigned char)c;
10796 case CBACK: /* backslash */
10799 USTPUTC(CTLESC, out);
10800 USTPUTC('\\', out);
10802 } else if (c == '\n') {
10806 #if ENABLE_ASH_EXPAND_PRMT
10807 if (c == '$' && pssyntax) {
10808 USTPUTC(CTLESC, out);
10809 USTPUTC('\\', out);
10812 if (dblquote && c != '\\'
10813 && c != '`' && c != '$'
10814 && (c != '"' || eofmark != NULL)
10816 USTPUTC(CTLESC, out);
10817 USTPUTC('\\', out);
10819 if (SIT(c, SQSYNTAX) == CCTL)
10820 USTPUTC(CTLESC, out);
10828 if (eofmark == NULL) {
10829 USTPUTC(CTLQUOTEMARK, out);
10837 USE_ASH_BASH_COMPAT(bash_dollar_squote = 0;)
10838 if (eofmark != NULL && arinest == 0
10843 if (dqvarnest == 0) {
10844 syntax = BASESYNTAX;
10851 case CVAR: /* '$' */
10852 PARSESUB(); /* parse substitution */
10854 case CENDVAR: /* '}' */
10857 if (dqvarnest > 0) {
10860 USTPUTC(CTLENDVAR, out);
10865 #if ENABLE_ASH_MATH_SUPPORT
10866 case CLP: /* '(' in arithmetic */
10870 case CRP: /* ')' in arithmetic */
10871 if (parenlevel > 0) {
10875 if (pgetc() == ')') {
10876 if (--arinest == 0) {
10877 USTPUTC(CTLENDARI, out);
10878 syntax = prevsyntax;
10879 dblquote = (syntax == DQSYNTAX);
10884 * unbalanced parens
10885 * (don't 2nd guess - no error)
10893 case CBQUOTE: /* '`' */
10897 goto endword; /* exit outer loop */
10901 if (varnest == 0) {
10902 #if ENABLE_ASH_BASH_COMPAT
10904 if (pgetc() == '>')
10905 c = 0x100 + '>'; /* flag &> */
10909 goto endword; /* exit outer loop */
10911 #if ENABLE_ASH_ALIAS
10921 #if ENABLE_ASH_MATH_SUPPORT
10922 if (syntax == ARISYNTAX)
10923 raise_error_syntax("missing '))'");
10925 if (syntax != BASESYNTAX && !parsebackquote && eofmark == NULL)
10926 raise_error_syntax("unterminated quoted string");
10927 if (varnest != 0) {
10928 startlinno = g_parsefile->linno;
10930 raise_error_syntax("missing '}'");
10932 USTPUTC('\0', out);
10933 len = out - (char *)stackblock();
10934 out = stackblock();
10935 if (eofmark == NULL) {
10936 if ((c == '>' || c == '<' USE_ASH_BASH_COMPAT( || c == 0x100 + '>'))
10939 if (isdigit_str9(out)) {
10940 PARSEREDIR(); /* passed as params: out, c */
10941 lasttoken = TREDIR;
10944 /* else: non-number X seen, interpret it
10945 * as "NNNX>file" = "NNNX >file" */
10949 quoteflag = quotef;
10950 backquotelist = bqlist;
10951 grabstackblock(len);
10955 /* end of readtoken routine */
10958 * Check to see whether we are at the end of the here document. When this
10959 * is called, c is set to the first character of the next input line. If
10960 * we are at the end of the here document, this routine sets the c to PEOF.
10964 #if ENABLE_ASH_ALIAS
10970 while (c == '\t') {
10974 if (c == *eofmark) {
10975 if (pfgets(line, sizeof(line)) != NULL) {
10979 for (q = eofmark + 1; *q && *p == *q; p++, q++)
10981 if (*p == '\n' && *q == '\0') {
10983 g_parsefile->linno++;
10984 needprompt = doprompt;
10986 pushstring(line, NULL);
10991 goto checkend_return;
10995 * Parse a redirection operator. The variable "out" points to a string
10996 * specifying the fd to be redirected. The variable "c" contains the
10997 * first character of the redirection operator.
11000 /* out is already checked to be a valid number or "" */
11001 int fd = (*out == '\0' ? -1 : atoi(out));
11004 np = stzalloc(sizeof(struct nfile));
11009 np->type = NAPPEND;
11011 np->type = NCLOBBER;
11014 /* it also can be NTO2 (>&file), but we can't figure it out yet */
11020 #if ENABLE_ASH_BASH_COMPAT
11021 else if (c == 0x100 + '>') { /* this flags &> redirection */
11023 pgetc(); /* this is '>', no need to check */
11027 else { /* c == '<' */
11028 /*np->nfile.fd = 0; - stzalloc did it */
11032 if (sizeof(struct nfile) != sizeof(struct nhere)) {
11033 np = stzalloc(sizeof(struct nhere));
11034 /*np->nfile.fd = 0; - stzalloc did it */
11037 heredoc = stzalloc(sizeof(struct heredoc));
11038 heredoc->here = np;
11041 heredoc->striptabs = 1;
11043 /*heredoc->striptabs = 0; - stzalloc did it */
11049 np->type = NFROMFD;
11053 np->type = NFROMTO;
11065 goto parseredir_return;
11069 * Parse a substitution. At this point, we have read the dollar sign
11070 * and nothing else.
11073 /* is_special(c) evaluates to 1 for c in "!#$*-0123456789?@"; 0 otherwise
11074 * (assuming ascii char codes, as the original implementation did) */
11075 #define is_special(c) \
11076 (((unsigned)(c) - 33 < 32) \
11077 && ((0xc1ff920dU >> ((unsigned)(c) - 33)) & 1))
11083 static const char types[] ALIGN1 = "}-+?=";
11086 if (c <= PEOA_OR_PEOF
11087 || (c != '(' && c != '{' && !is_name(c) && !is_special(c))
11089 #if ENABLE_ASH_BASH_COMPAT
11091 bash_dollar_squote = 1;
11096 } else if (c == '(') { /* $(command) or $((arith)) */
11097 if (pgetc() == '(') {
11098 #if ENABLE_ASH_MATH_SUPPORT
11101 raise_error_syntax("you disabled math support for $((arith)) syntax");
11108 USTPUTC(CTLVAR, out);
11109 typeloc = out - (char *)stackblock();
11110 USTPUTC(VSNORMAL, out);
11111 subtype = VSNORMAL;
11119 subtype = VSLENGTH;
11123 if (c > PEOA_OR_PEOF && is_name(c)) {
11127 } while (c > PEOA_OR_PEOF && is_in_name(c));
11128 } else if (isdigit(c)) {
11132 } while (isdigit(c));
11133 } else if (is_special(c)) {
11138 raise_error_syntax("bad substitution");
11143 if (subtype == 0) {
11147 #if ENABLE_ASH_BASH_COMPAT
11148 if (c == ':' || c == '$' || isdigit(c)) {
11150 subtype = VSSUBSTR;
11157 p = strchr(types, c);
11160 subtype = p - types + VSNORMAL;
11165 subtype = c == '#' ? VSTRIMLEFT : VSTRIMRIGHT;
11173 #if ENABLE_ASH_BASH_COMPAT
11175 subtype = VSREPLACE;
11178 subtype++; /* VSREPLACEALL */
11187 if (dblquote || arinest)
11189 *((char *)stackblock() + typeloc) = subtype | flags;
11190 if (subtype != VSNORMAL) {
11192 if (dblquote || arinest) {
11197 goto parsesub_return;
11201 * Called to parse command substitutions. Newstyle is set if the command
11202 * is enclosed inside $(...); nlpp is a pointer to the head of the linked
11203 * list of commands (passed by reference), and savelen is the number of
11204 * characters on the top of the stack which must be preserved.
11207 struct nodelist **nlpp;
11210 char *volatile str;
11211 struct jmploc jmploc;
11212 struct jmploc *volatile savehandler;
11214 smallint saveprompt = 0;
11217 (void) &saveprompt;
11219 savepbq = parsebackquote;
11220 if (setjmp(jmploc.loc)) {
11222 parsebackquote = 0;
11223 exception_handler = savehandler;
11224 longjmp(exception_handler->loc, 1);
11228 savelen = out - (char *)stackblock();
11230 str = ckmalloc(savelen);
11231 memcpy(str, stackblock(), savelen);
11233 savehandler = exception_handler;
11234 exception_handler = &jmploc;
11237 /* We must read until the closing backquote, giving special
11238 treatment to some slashes, and then push the string and
11239 reread it as input, interpreting it normally. */
11246 STARTSTACKSTR(pout);
11259 g_parsefile->linno++;
11263 * If eating a newline, avoid putting
11264 * the newline into the new character
11265 * stream (via the STPUTC after the
11270 if (pc != '\\' && pc != '`' && pc != '$'
11271 && (!dblquote || pc != '"'))
11272 STPUTC('\\', pout);
11273 if (pc > PEOA_OR_PEOF) {
11279 #if ENABLE_ASH_ALIAS
11282 startlinno = g_parsefile->linno;
11283 raise_error_syntax("EOF in backquote substitution");
11286 g_parsefile->linno++;
11287 needprompt = doprompt;
11296 STPUTC('\0', pout);
11297 psavelen = pout - (char *)stackblock();
11298 if (psavelen > 0) {
11299 pstr = grabstackstr(pout);
11300 setinputstring(pstr);
11305 nlpp = &(*nlpp)->next;
11306 *nlpp = stzalloc(sizeof(**nlpp));
11307 /* (*nlpp)->next = NULL; - stzalloc did it */
11308 parsebackquote = oldstyle;
11311 saveprompt = doprompt;
11318 doprompt = saveprompt;
11319 else if (readtoken() != TRP)
11320 raise_error_unexpected_syntax(TRP);
11325 * Start reading from old file again, ignoring any pushed back
11326 * tokens left from the backquote parsing
11331 while (stackblocksize() <= savelen)
11333 STARTSTACKSTR(out);
11335 memcpy(out, str, savelen);
11336 STADJUST(savelen, out);
11342 parsebackquote = savepbq;
11343 exception_handler = savehandler;
11344 if (arinest || dblquote)
11345 USTPUTC(CTLBACKQ | CTLQUOTE, out);
11347 USTPUTC(CTLBACKQ, out);
11349 goto parsebackq_oldreturn;
11350 goto parsebackq_newreturn;
11353 #if ENABLE_ASH_MATH_SUPPORT
11355 * Parse an arithmetic expansion (indicate start of one and set state)
11358 if (++arinest == 1) {
11359 prevsyntax = syntax;
11360 syntax = ARISYNTAX;
11361 USTPUTC(CTLARI, out);
11368 * we collapse embedded arithmetic expansion to
11369 * parenthesis, which should be equivalent
11373 goto parsearith_return;
11377 } /* end of readtoken */
11380 * Read the next input token.
11381 * If the token is a word, we set backquotelist to the list of cmds in
11382 * backquotes. We set quoteflag to true if any part of the word was
11384 * If the token is TREDIR, then we set redirnode to a structure containing
11386 * In all cases, the variable startlinno is set to the number of the line
11387 * on which the token starts.
11389 * [Change comment: here documents and internal procedures]
11390 * [Readtoken shouldn't have any arguments. Perhaps we should make the
11391 * word parsing code into a separate routine. In this case, readtoken
11392 * doesn't need to have any internal procedures, but parseword does.
11393 * We could also make parseoperator in essence the main routine, and
11394 * have parseword (readtoken1?) handle both words and redirection.]
11396 #define NEW_xxreadtoken
11397 #ifdef NEW_xxreadtoken
11398 /* singles must be first! */
11399 static const char xxreadtoken_chars[7] ALIGN1 = {
11400 '\n', '(', ')', /* singles */
11401 '&', '|', ';', /* doubles */
11405 #define xxreadtoken_singles 3
11406 #define xxreadtoken_doubles 3
11408 static const char xxreadtoken_tokens[] ALIGN1 = {
11409 TNL, TLP, TRP, /* only single occurrence allowed */
11410 TBACKGND, TPIPE, TSEMI, /* if single occurrence */
11411 TEOF, /* corresponds to trailing nul */
11412 TAND, TOR, TENDCASE /* if double occurrence */
11427 startlinno = g_parsefile->linno;
11428 for (;;) { /* until token or start of word found */
11430 if (c == ' ' || c == '\t' USE_ASH_ALIAS( || c == PEOA))
11434 while ((c = pgetc()) != '\n' && c != PEOF)
11437 } else if (c == '\\') {
11438 if (pgetc() != '\n') {
11440 break; /* return readtoken1(...) */
11442 startlinno = ++g_parsefile->linno;
11448 p = xxreadtoken_chars + sizeof(xxreadtoken_chars) - 1;
11451 g_parsefile->linno++;
11452 needprompt = doprompt;
11455 p = strchr(xxreadtoken_chars, c);
11457 break; /* return readtoken1(...) */
11459 if ((int)(p - xxreadtoken_chars) >= xxreadtoken_singles) {
11461 if (cc == c) { /* double occurrence? */
11462 p += xxreadtoken_doubles + 1;
11465 #if ENABLE_ASH_BASH_COMPAT
11466 if (c == '&' && cc == '>') /* &> */
11467 break; /* return readtoken1(...) */
11472 lasttoken = xxreadtoken_tokens[p - xxreadtoken_chars];
11477 return readtoken1(c, BASESYNTAX, (char *) NULL, 0);
11479 #else /* old xxreadtoken */
11480 #define RETURN(token) return lasttoken = token
11493 startlinno = g_parsefile->linno;
11494 for (;;) { /* until token or start of word found */
11497 case ' ': case '\t':
11498 #if ENABLE_ASH_ALIAS
11503 while ((c = pgetc()) != '\n' && c != PEOF)
11508 if (pgetc() == '\n') {
11509 startlinno = ++g_parsefile->linno;
11517 g_parsefile->linno++;
11518 needprompt = doprompt;
11523 if (pgetc() == '&')
11528 if (pgetc() == '|')
11533 if (pgetc() == ';')
11546 return readtoken1(c, BASESYNTAX, (char *)NULL, 0);
11549 #endif /* old xxreadtoken */
11556 smallint alreadyseen = tokpushback;
11559 #if ENABLE_ASH_ALIAS
11568 if (checkkwd & CHKNL) {
11575 if (t != TWORD || quoteflag) {
11580 * check for keywords
11582 if (checkkwd & CHKKWD) {
11583 const char *const *pp;
11585 pp = findkwd(wordtext);
11587 lasttoken = t = pp - tokname_array;
11588 TRACE(("keyword %s recognized\n", tokname(t)));
11593 if (checkkwd & CHKALIAS) {
11594 #if ENABLE_ASH_ALIAS
11596 ap = lookupalias(wordtext, 1);
11599 pushstring(ap->val, ap);
11609 TRACE(("token %s %s\n", tokname(t), t == TWORD ? wordtext : ""));
11611 TRACE(("reread token %s %s\n", tokname(t), t == TWORD ? wordtext : ""));
11623 return tokname_array[t][0];
11627 * Read and parse a command. Returns NEOF on end of file. (NULL is a
11628 * valid parse tree indicating a blank line.)
11630 static union node *
11631 parsecmd(int interact)
11636 doprompt = interact;
11638 setprompt(doprompt);
11650 * Input any here documents.
11655 struct heredoc *here;
11658 here = heredoclist;
11659 heredoclist = NULL;
11665 readtoken1(pgetc(), here->here->type == NHERE? SQSYNTAX : DQSYNTAX,
11666 here->eofmark, here->striptabs);
11667 n = stzalloc(sizeof(struct narg));
11668 n->narg.type = NARG;
11669 /*n->narg.next = NULL; - stzalloc did it */
11670 n->narg.text = wordtext;
11671 n->narg.backquote = backquotelist;
11672 here->here->nhere.doc = n;
11679 * called by editline -- any expansions to the prompt should be added here.
11681 #if ENABLE_ASH_EXPAND_PRMT
11682 static const char *
11683 expandstr(const char *ps)
11687 /* XXX Fix (char *) cast. */
11688 setinputstring((char *)ps);
11689 readtoken1(pgetc(), PSSYNTAX, nullstr, 0);
11692 n.narg.type = NARG;
11693 n.narg.next = NULL;
11694 n.narg.text = wordtext;
11695 n.narg.backquote = backquotelist;
11697 expandarg(&n, NULL, 0);
11698 return stackblock();
11703 * Execute a command or commands contained in a string.
11706 evalstring(char *s, int mask)
11709 struct stackmark smark;
11713 setstackmark(&smark);
11716 while ((n = parsecmd(0)) != NEOF) {
11718 popstackmark(&smark);
11731 * The eval command.
11734 evalcmd(int argc UNUSED_PARAM, char **argv)
11743 STARTSTACKSTR(concat);
11745 concat = stack_putstr(p, concat);
11749 STPUTC(' ', concat);
11751 STPUTC('\0', concat);
11752 p = grabstackstr(concat);
11754 evalstring(p, ~SKIPEVAL);
11761 * Read and execute commands. "Top" is nonzero for the top level command
11762 * loop; it turns on prompting if the shell is interactive.
11768 struct stackmark smark;
11772 TRACE(("cmdloop(%d) called\n", top));
11776 setstackmark(&smark);
11779 showjobs(stderr, SHOW_CHANGED);
11782 if (iflag && top) {
11784 #if ENABLE_ASH_MAIL
11788 n = parsecmd(inter);
11789 /* showtree(n); DEBUG */
11791 if (!top || numeof >= 50)
11793 if (!stoppedjobs()) {
11796 out2str("\nUse \"exit\" to leave shell.\n");
11799 } else if (nflag == 0) {
11800 /* job_warning can only be 2,1,0. Here 2->1, 1/0->0 */
11805 popstackmark(&smark);
11810 return skip & SKIPEVAL;
11817 * Take commands from a file. To be compatible we should do a path
11818 * search for the file, which is necessary to find sub-commands.
11821 find_dot_file(char *name)
11824 const char *path = pathval();
11827 /* don't try this for absolute or relative paths */
11828 if (strchr(name, '/'))
11831 /* IIRC standards do not say whether . is to be searched.
11832 * And it is even smaller this way, making it unconditional for now:
11834 if (1) { /* ENABLE_ASH_BASH_COMPAT */
11839 while ((fullname = padvance(&path, name)) != NULL) {
11841 if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) {
11843 * Don't bother freeing here, since it will
11844 * be freed by the caller.
11848 stunalloc(fullname);
11851 /* not found in the PATH */
11852 ash_msg_and_raise_error("%s: not found", name);
11857 dotcmd(int argc, char **argv)
11859 struct strlist *sp;
11860 volatile struct shparam saveparam;
11863 for (sp = cmdenviron; sp; sp = sp->next)
11864 setvareq(ckstrdup(sp->text), VSTRFIXED | VTEXTFIXED);
11866 if (argv[1]) { /* That's what SVR2 does */
11867 char *fullname = find_dot_file(argv[1]);
11870 if (argc) { /* argc > 0, argv[0] != NULL */
11871 saveparam = shellparam;
11872 shellparam.malloced = 0;
11873 shellparam.nparam = argc;
11874 shellparam.p = argv;
11877 setinputfile(fullname, INPUT_PUSH_FILE);
11878 commandname = fullname;
11883 freeparam(&shellparam);
11884 shellparam = saveparam;
11886 status = exitstatus;
11892 exitcmd(int argc UNUSED_PARAM, char **argv)
11897 exitstatus = number(argv[1]);
11898 raise_exception(EXEXIT);
11903 * Read a file containing shell functions.
11906 readcmdfile(char *name)
11908 setinputfile(name, INPUT_PUSH_FILE);
11914 /* ============ find_command inplementation */
11917 * Resolve a command name. If you change this routine, you may have to
11918 * change the shellexec routine as well.
11921 find_command(char *name, struct cmdentry *entry, int act, const char *path)
11923 struct tblentry *cmdp;
11930 struct builtincmd *bcmd;
11932 /* If name contains a slash, don't use PATH or hash table */
11933 if (strchr(name, '/') != NULL) {
11934 entry->u.index = -1;
11935 if (act & DO_ABS) {
11936 while (stat(name, &statb) < 0) {
11938 if (errno == EINTR)
11941 entry->cmdtype = CMDUNKNOWN;
11945 entry->cmdtype = CMDNORMAL;
11949 /* #if ENABLE_FEATURE_SH_STANDALONE... moved after builtin check */
11951 updatetbl = (path == pathval());
11954 if (strstr(path, "%builtin") != NULL)
11955 act |= DO_ALTBLTIN;
11958 /* If name is in the table, check answer will be ok */
11959 cmdp = cmdlookup(name, 0);
11960 if (cmdp != NULL) {
11963 switch (cmdp->cmdtype) {
11981 } else if (cmdp->rehash == 0)
11982 /* if not invalidated by cd, we're done */
11986 /* If %builtin not in path, check for builtin next */
11987 bcmd = find_builtin(name);
11989 if (IS_BUILTIN_REGULAR(bcmd))
11990 goto builtin_success;
11991 if (act & DO_ALTPATH) {
11992 if (!(act & DO_ALTBLTIN))
11993 goto builtin_success;
11994 } else if (builtinloc <= 0) {
11995 goto builtin_success;
11999 #if ENABLE_FEATURE_SH_STANDALONE
12001 int applet_no = find_applet_by_name(name);
12002 if (applet_no >= 0) {
12003 entry->cmdtype = CMDNORMAL;
12004 entry->u.index = -2 - applet_no;
12010 /* We have to search path. */
12011 prev = -1; /* where to start */
12012 if (cmdp && cmdp->rehash) { /* doing a rehash */
12013 if (cmdp->cmdtype == CMDBUILTIN)
12016 prev = cmdp->param.index;
12022 while ((fullname = padvance(&path, name)) != NULL) {
12023 stunalloc(fullname);
12024 /* NB: code below will still use fullname
12025 * despite it being "unallocated" */
12028 if (prefix(pathopt, "builtin")) {
12030 goto builtin_success;
12033 if ((act & DO_NOFUNC)
12034 || !prefix(pathopt, "func")
12035 ) { /* ignore unimplemented options */
12039 /* if rehash, don't redo absolute path names */
12040 if (fullname[0] == '/' && idx <= prev) {
12043 TRACE(("searchexec \"%s\": no change\n", name));
12046 while (stat(fullname, &statb) < 0) {
12048 if (errno == EINTR)
12051 if (errno != ENOENT && errno != ENOTDIR)
12055 e = EACCES; /* if we fail, this will be the error */
12056 if (!S_ISREG(statb.st_mode))
12058 if (pathopt) { /* this is a %func directory */
12059 stalloc(strlen(fullname) + 1);
12060 /* NB: stalloc will return space pointed by fullname
12061 * (because we don't have any intervening allocations
12062 * between stunalloc above and this stalloc) */
12063 readcmdfile(fullname);
12064 cmdp = cmdlookup(name, 0);
12065 if (cmdp == NULL || cmdp->cmdtype != CMDFUNCTION)
12066 ash_msg_and_raise_error("%s not defined in %s", name, fullname);
12067 stunalloc(fullname);
12070 TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
12072 entry->cmdtype = CMDNORMAL;
12073 entry->u.index = idx;
12077 cmdp = cmdlookup(name, 1);
12078 cmdp->cmdtype = CMDNORMAL;
12079 cmdp->param.index = idx;
12084 /* We failed. If there was an entry for this command, delete it */
12085 if (cmdp && updatetbl)
12086 delete_cmd_entry();
12088 ash_msg("%s: %s", name, errmsg(e, "not found"));
12089 entry->cmdtype = CMDUNKNOWN;
12094 entry->cmdtype = CMDBUILTIN;
12095 entry->u.cmd = bcmd;
12099 cmdp = cmdlookup(name, 1);
12100 cmdp->cmdtype = CMDBUILTIN;
12101 cmdp->param.cmd = bcmd;
12105 entry->cmdtype = cmdp->cmdtype;
12106 entry->u = cmdp->param;
12110 /* ============ trap.c */
12113 * The trap builtin.
12116 trapcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
12125 for (signo = 0; signo < NSIG; signo++) {
12126 if (trap[signo] != NULL) {
12127 out1fmt("trap -- %s %s\n",
12128 single_quote(trap[signo]),
12129 get_signame(signo));
12138 signo = get_signum(*ap);
12140 ash_msg_and_raise_error("%s: bad trap", *ap);
12143 if (LONE_DASH(action))
12146 action = ckstrdup(action);
12149 trap[signo] = action;
12159 /* ============ Builtins */
12161 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
12163 * Lists available builtins
12166 helpcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
12171 out1fmt("\nBuilt-in commands:\n-------------------\n");
12172 for (col = 0, i = 0; i < ARRAY_SIZE(builtintab); i++) {
12173 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '),
12174 builtintab[i].name + 1);
12180 #if ENABLE_FEATURE_SH_STANDALONE
12182 const char *a = applet_names;
12184 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '), a);
12189 a += strlen(a) + 1;
12194 return EXIT_SUCCESS;
12196 #endif /* FEATURE_SH_EXTRA_QUIET */
12199 * The export and readonly commands.
12202 exportcmd(int argc UNUSED_PARAM, char **argv)
12208 int flag = argv[0][0] == 'r' ? VREADONLY : VEXPORT;
12210 if (nextopt("p") != 'p') {
12215 p = strchr(name, '=');
12219 vp = *findvar(hashvar(name), name);
12225 setvar(name, p, flag);
12226 } while ((name = *++aptr) != NULL);
12230 showvars(argv[0], flag, 0);
12235 * Delete a function if it exists.
12238 unsetfunc(const char *name)
12240 struct tblentry *cmdp;
12242 cmdp = cmdlookup(name, 0);
12243 if (cmdp!= NULL && cmdp->cmdtype == CMDFUNCTION)
12244 delete_cmd_entry();
12248 * The unset builtin command. We unset the function before we unset the
12249 * variable to allow a function to be unset when there is a readonly variable
12250 * with the same name.
12253 unsetcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
12260 while ((i = nextopt("vf")) != '\0') {
12264 for (ap = argptr; *ap; ap++) {
12280 #include <sys/times.h>
12282 static const unsigned char timescmd_str[] ALIGN1 = {
12283 ' ', offsetof(struct tms, tms_utime),
12284 '\n', offsetof(struct tms, tms_stime),
12285 ' ', offsetof(struct tms, tms_cutime),
12286 '\n', offsetof(struct tms, tms_cstime),
12291 timescmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
12293 long clk_tck, s, t;
12294 const unsigned char *p;
12297 clk_tck = sysconf(_SC_CLK_TCK);
12302 t = *(clock_t *)(((char *) &buf) + p[1]);
12304 out1fmt("%ldm%ld.%.3lds%c",
12306 ((t - s * clk_tck) * 1000) / clk_tck,
12308 } while (*(p += 2));
12313 #if ENABLE_ASH_MATH_SUPPORT
12315 dash_arith(const char *s)
12321 result = arith(s, &errcode);
12324 ash_msg_and_raise_error("exponent less than 0");
12326 ash_msg_and_raise_error("divide by zero");
12328 ash_msg_and_raise_error("expression recursion loop detected");
12329 raise_error_syntax(s);
12337 * The let builtin. partial stolen from GNU Bash, the Bourne Again SHell.
12338 * Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
12340 * Copyright (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
12343 letcmd(int argc UNUSED_PARAM, char **argv)
12349 ash_msg_and_raise_error("expression expected");
12351 i = dash_arith(*argv);
12356 #endif /* ASH_MATH_SUPPORT */
12359 /* ============ miscbltin.c
12361 * Miscellaneous builtins.
12366 #if defined(__GLIBC__) && __GLIBC__ == 2 && __GLIBC_MINOR__ < 1
12367 typedef enum __rlimit_resource rlim_t;
12371 * The read builtin. Options:
12372 * -r Do not interpret '\' specially
12373 * -s Turn off echo (tty only)
12374 * -n NCHARS Read NCHARS max
12375 * -p PROMPT Display PROMPT on stderr (if input is from tty)
12376 * -t SECONDS Timeout after SECONDS (tty or pipe only)
12377 * -u FD Read from given FD instead of fd 0
12378 * This uses unbuffered input, which may be avoidable in some cases.
12379 * TODO: bash also has:
12380 * -a ARRAY Read into array[0],[1],etc
12381 * -d DELIM End on DELIM char, not newline
12382 * -e Use line editing (tty only)
12385 readcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
12387 static const char *const arg_REPLY[] = { "REPLY", NULL };
12400 #if ENABLE_ASH_READ_NCHARS
12401 int nchars = 0; /* if != 0, -n is in effect */
12403 struct termios tty, old_tty;
12405 #if ENABLE_ASH_READ_TIMEOUT
12406 unsigned end_ms = 0;
12407 unsigned timeout = 0;
12412 while ((i = nextopt("p:u:r"
12413 USE_ASH_READ_TIMEOUT("t:")
12414 USE_ASH_READ_NCHARS("n:s")
12418 prompt = optionarg;
12420 #if ENABLE_ASH_READ_NCHARS
12422 nchars = bb_strtou(optionarg, NULL, 10);
12423 if (nchars < 0 || errno)
12424 ash_msg_and_raise_error("invalid count");
12425 /* nchars == 0: off (bash 3.2 does this too) */
12431 #if ENABLE_ASH_READ_TIMEOUT
12433 timeout = bb_strtou(optionarg, NULL, 10);
12434 if (errno || timeout > UINT_MAX / 2048)
12435 ash_msg_and_raise_error("invalid timeout");
12437 #if 0 /* even bash have no -t N.NNN support */
12438 ts.tv_sec = bb_strtou(optionarg, &p, 10);
12440 /* EINVAL means number is ok, but not terminated by NUL */
12441 if (*p == '.' && errno == EINVAL) {
12445 ts.tv_usec = bb_strtou(p, &p2, 10);
12447 ash_msg_and_raise_error("invalid timeout");
12449 /* normalize to usec */
12451 ash_msg_and_raise_error("invalid timeout");
12452 while (scale++ < 6)
12455 } else if (ts.tv_sec < 0 || errno) {
12456 ash_msg_and_raise_error("invalid timeout");
12458 if (!(ts.tv_sec | ts.tv_usec)) { /* both are 0? */
12459 ash_msg_and_raise_error("invalid timeout");
12468 fd = bb_strtou(optionarg, NULL, 10);
12469 if (fd < 0 || errno)
12470 ash_msg_and_raise_error("invalid file descriptor");
12476 if (prompt && isatty(fd)) {
12481 ap = (char**)arg_REPLY;
12482 ifs = bltinlookup("IFS");
12485 #if ENABLE_ASH_READ_NCHARS
12486 tcgetattr(fd, &tty);
12488 if (nchars || silent) {
12490 tty.c_lflag &= ~ICANON;
12491 tty.c_cc[VMIN] = nchars < 256 ? nchars : 255;
12494 tty.c_lflag &= ~(ECHO | ECHOK | ECHONL);
12496 /* if tcgetattr failed, tcsetattr will fail too.
12497 * Ignoring, it's harmless. */
12498 tcsetattr(fd, TCSANOW, &tty);
12505 #if ENABLE_ASH_READ_TIMEOUT
12506 if (timeout) /* NB: ensuring end_ms is nonzero */
12507 end_ms = ((unsigned)(monotonic_us() / 1000) + timeout) | 1;
12511 #if ENABLE_ASH_READ_TIMEOUT
12513 struct pollfd pfd[1];
12515 pfd[0].events = POLLIN;
12516 timeout = end_ms - (unsigned)(monotonic_us() / 1000);
12517 if ((int)timeout <= 0 /* already late? */
12518 || safe_poll(pfd, 1, timeout) != 1 /* no? wait... */
12519 ) { /* timed out! */
12520 #if ENABLE_ASH_READ_NCHARS
12521 tcsetattr(fd, TCSANOW, &old_tty);
12527 if (nonblock_safe_read(fd, &c, 1) != 1) {
12539 if (!rflag && c == '\\') {
12545 if (startword && *ifs == ' ' && strchr(ifs, c)) {
12549 if (ap[1] != NULL && strchr(ifs, c) != NULL) {
12551 setvar(*ap, stackblock(), 0);
12560 /* end of do {} while: */
12561 #if ENABLE_ASH_READ_NCHARS
12567 #if ENABLE_ASH_READ_NCHARS
12568 tcsetattr(fd, TCSANOW, &old_tty);
12572 /* Remove trailing blanks */
12573 while ((char *)stackblock() <= --p && strchr(ifs, *p) != NULL)
12575 setvar(*ap, stackblock(), 0);
12576 while (*++ap != NULL)
12577 setvar(*ap, nullstr, 0);
12582 umaskcmd(int argc UNUSED_PARAM, char **argv)
12584 static const char permuser[3] ALIGN1 = "ugo";
12585 static const char permmode[3] ALIGN1 = "rwx";
12586 static const short permmask[] ALIGN2 = {
12587 S_IRUSR, S_IWUSR, S_IXUSR,
12588 S_IRGRP, S_IWGRP, S_IXGRP,
12589 S_IROTH, S_IWOTH, S_IXOTH
12595 int symbolic_mode = 0;
12597 while (nextopt("S") != '\0') {
12608 if (symbolic_mode) {
12612 for (i = 0; i < 3; i++) {
12615 *p++ = permuser[i];
12617 for (j = 0; j < 3; j++) {
12618 if ((mask & permmask[3 * i + j]) == 0) {
12619 *p++ = permmode[j];
12627 out1fmt("%.4o\n", mask);
12630 if (isdigit((unsigned char) *ap)) {
12633 if (*ap >= '8' || *ap < '0')
12634 ash_msg_and_raise_error(illnum, argv[1]);
12635 mask = (mask << 3) + (*ap - '0');
12636 } while (*++ap != '\0');
12639 mask = ~mask & 0777;
12640 if (!bb_parse_mode(ap, &mask)) {
12641 ash_msg_and_raise_error("illegal mode: %s", ap);
12643 umask(~mask & 0777);
12652 * This code, originally by Doug Gwyn, Doug Kingston, Eric Gisin, and
12653 * Michael Rendell was ripped from pdksh 5.0.8 and hacked for use with
12654 * ash by J.T. Conklin.
12660 uint8_t cmd; /* RLIMIT_xxx fit into it */
12661 uint8_t factor_shift; /* shift by to get rlim_{cur,max} values */
12665 static const struct limits limits_tbl[] = {
12667 { RLIMIT_CPU, 0, 't' },
12669 #ifdef RLIMIT_FSIZE
12670 { RLIMIT_FSIZE, 9, 'f' },
12673 { RLIMIT_DATA, 10, 'd' },
12675 #ifdef RLIMIT_STACK
12676 { RLIMIT_STACK, 10, 's' },
12679 { RLIMIT_CORE, 9, 'c' },
12682 { RLIMIT_RSS, 10, 'm' },
12684 #ifdef RLIMIT_MEMLOCK
12685 { RLIMIT_MEMLOCK, 10, 'l' },
12687 #ifdef RLIMIT_NPROC
12688 { RLIMIT_NPROC, 0, 'p' },
12690 #ifdef RLIMIT_NOFILE
12691 { RLIMIT_NOFILE, 0, 'n' },
12694 { RLIMIT_AS, 10, 'v' },
12696 #ifdef RLIMIT_LOCKS
12697 { RLIMIT_LOCKS, 0, 'w' },
12700 static const char limits_name[] =
12702 "time(seconds)" "\0"
12704 #ifdef RLIMIT_FSIZE
12705 "file(blocks)" "\0"
12710 #ifdef RLIMIT_STACK
12714 "coredump(blocks)" "\0"
12719 #ifdef RLIMIT_MEMLOCK
12720 "locked memory(kb)" "\0"
12722 #ifdef RLIMIT_NPROC
12725 #ifdef RLIMIT_NOFILE
12731 #ifdef RLIMIT_LOCKS
12736 enum limtype { SOFT = 0x1, HARD = 0x2 };
12739 printlim(enum limtype how, const struct rlimit *limit,
12740 const struct limits *l)
12744 val = limit->rlim_max;
12746 val = limit->rlim_cur;
12748 if (val == RLIM_INFINITY)
12749 out1fmt("unlimited\n");
12751 val >>= l->factor_shift;
12752 out1fmt("%lld\n", (long long) val);
12757 ulimitcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
12761 enum limtype how = SOFT | HARD;
12762 const struct limits *l;
12765 struct rlimit limit;
12768 while ((optc = nextopt("HSa"
12772 #ifdef RLIMIT_FSIZE
12778 #ifdef RLIMIT_STACK
12787 #ifdef RLIMIT_MEMLOCK
12790 #ifdef RLIMIT_NPROC
12793 #ifdef RLIMIT_NOFILE
12799 #ifdef RLIMIT_LOCKS
12817 for (l = limits_tbl; l->option != what; l++)
12820 set = *argptr ? 1 : 0;
12824 if (all || argptr[1])
12825 ash_msg_and_raise_error("too many arguments");
12826 if (strncmp(p, "unlimited\n", 9) == 0)
12827 val = RLIM_INFINITY;
12831 while ((c = *p++) >= '0' && c <= '9') {
12832 val = (val * 10) + (long)(c - '0');
12833 // val is actually 'unsigned long int' and can't get < 0
12834 if (val < (rlim_t) 0)
12838 ash_msg_and_raise_error("bad number");
12839 val <<= l->factor_shift;
12843 const char *lname = limits_name;
12844 for (l = limits_tbl; l != &limits_tbl[ARRAY_SIZE(limits_tbl)]; l++) {
12845 getrlimit(l->cmd, &limit);
12846 out1fmt("%-20s ", lname);
12847 lname += strlen(lname) + 1;
12848 printlim(how, &limit, l);
12853 getrlimit(l->cmd, &limit);
12856 limit.rlim_max = val;
12858 limit.rlim_cur = val;
12859 if (setrlimit(l->cmd, &limit) < 0)
12860 ash_msg_and_raise_error("error setting limit (%m)");
12862 printlim(how, &limit, l);
12868 /* ============ Math support */
12870 #if ENABLE_ASH_MATH_SUPPORT
12872 /* Copyright (c) 2001 Aaron Lehmann <aaronl@vitelus.com>
12874 Permission is hereby granted, free of charge, to any person obtaining
12875 a copy of this software and associated documentation files (the
12876 "Software"), to deal in the Software without restriction, including
12877 without limitation the rights to use, copy, modify, merge, publish,
12878 distribute, sublicense, and/or sell copies of the Software, and to
12879 permit persons to whom the Software is furnished to do so, subject to
12880 the following conditions:
12882 The above copyright notice and this permission notice shall be
12883 included in all copies or substantial portions of the Software.
12885 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
12886 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
12887 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
12888 IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
12889 CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
12890 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
12891 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
12894 /* This is my infix parser/evaluator. It is optimized for size, intended
12895 * as a replacement for yacc-based parsers. However, it may well be faster
12896 * than a comparable parser written in yacc. The supported operators are
12897 * listed in #defines below. Parens, order of operations, and error handling
12898 * are supported. This code is thread safe. The exact expression format should
12899 * be that which POSIX specifies for shells. */
12901 /* The code uses a simple two-stack algorithm. See
12902 * http://www.onthenet.com.au/~grahamis/int2008/week02/lect02.html
12903 * for a detailed explanation of the infix-to-postfix algorithm on which
12904 * this is based (this code differs in that it applies operators immediately
12905 * to the stack instead of adding them to a queue to end up with an
12908 /* To use the routine, call it with an expression string and error return
12912 * Aug 24, 2001 Manuel Novoa III
12914 * Reduced the generated code size by about 30% (i386) and fixed several bugs.
12916 * 1) In arith_apply():
12917 * a) Cached values of *numptr and &(numptr[-1]).
12918 * b) Removed redundant test for zero denominator.
12921 * a) Eliminated redundant code for processing operator tokens by moving
12922 * to a table-based implementation. Also folded handling of parens
12924 * b) Combined all 3 loops which called arith_apply to reduce generated
12925 * code size at the cost of speed.
12927 * 3) The following expressions were treated as valid by the original code:
12928 * 1() , 0! , 1 ( *3 ) .
12929 * These bugs have been fixed by internally enclosing the expression in
12930 * parens and then checking that all binary ops and right parens are
12931 * preceded by a valid expression (NUM_TOKEN).
12933 * Note: It may be desirable to replace Aaron's test for whitespace with
12934 * ctype's isspace() if it is used by another busybox applet or if additional
12935 * whitespace chars should be considered. Look below the "#include"s for a
12936 * precompiler test.
12940 * Aug 26, 2001 Manuel Novoa III
12942 * Return 0 for null expressions. Pointed out by Vladimir Oleynik.
12944 * Merge in Aaron's comments previously posted to the busybox list,
12945 * modified slightly to take account of my changes to the code.
12950 * (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
12952 * - allow access to variable,
12953 * used recursive find value indirection (c=2*2; a="c"; $((a+=2)) produce 6)
12954 * - realize assign syntax (VAR=expr, +=, *= etc)
12955 * - realize exponentiation (** operator)
12956 * - realize comma separated - expr, expr
12957 * - realise ++expr --expr expr++ expr--
12958 * - realise expr ? expr : expr (but, second expr calculate always)
12959 * - allow hexadecimal and octal numbers
12960 * - was restored loses XOR operator
12961 * - remove one goto label, added three ;-)
12962 * - protect $((num num)) as true zero expr (Manuel`s error)
12963 * - always use special isspace(), see comment from bash ;-)
12966 #define arith_isspace(arithval) \
12967 (arithval == ' ' || arithval == '\n' || arithval == '\t')
12969 typedef unsigned char operator;
12971 /* An operator's token id is a bit of a bitfield. The lower 5 bits are the
12972 * precedence, and 3 high bits are an ID unique across operators of that
12973 * precedence. The ID portion is so that multiple operators can have the
12974 * same precedence, ensuring that the leftmost one is evaluated first.
12975 * Consider * and /. */
12977 #define tok_decl(prec,id) (((id)<<5)|(prec))
12978 #define PREC(op) ((op) & 0x1F)
12980 #define TOK_LPAREN tok_decl(0,0)
12982 #define TOK_COMMA tok_decl(1,0)
12984 #define TOK_ASSIGN tok_decl(2,0)
12985 #define TOK_AND_ASSIGN tok_decl(2,1)
12986 #define TOK_OR_ASSIGN tok_decl(2,2)
12987 #define TOK_XOR_ASSIGN tok_decl(2,3)
12988 #define TOK_PLUS_ASSIGN tok_decl(2,4)
12989 #define TOK_MINUS_ASSIGN tok_decl(2,5)
12990 #define TOK_LSHIFT_ASSIGN tok_decl(2,6)
12991 #define TOK_RSHIFT_ASSIGN tok_decl(2,7)
12993 #define TOK_MUL_ASSIGN tok_decl(3,0)
12994 #define TOK_DIV_ASSIGN tok_decl(3,1)
12995 #define TOK_REM_ASSIGN tok_decl(3,2)
12997 /* all assign is right associativity and precedence eq, but (7+3)<<5 > 256 */
12998 #define convert_prec_is_assing(prec) do { if (prec == 3) prec = 2; } while (0)
13000 /* conditional is right associativity too */
13001 #define TOK_CONDITIONAL tok_decl(4,0)
13002 #define TOK_CONDITIONAL_SEP tok_decl(4,1)
13004 #define TOK_OR tok_decl(5,0)
13006 #define TOK_AND tok_decl(6,0)
13008 #define TOK_BOR tok_decl(7,0)
13010 #define TOK_BXOR tok_decl(8,0)
13012 #define TOK_BAND tok_decl(9,0)
13014 #define TOK_EQ tok_decl(10,0)
13015 #define TOK_NE tok_decl(10,1)
13017 #define TOK_LT tok_decl(11,0)
13018 #define TOK_GT tok_decl(11,1)
13019 #define TOK_GE tok_decl(11,2)
13020 #define TOK_LE tok_decl(11,3)
13022 #define TOK_LSHIFT tok_decl(12,0)
13023 #define TOK_RSHIFT tok_decl(12,1)
13025 #define TOK_ADD tok_decl(13,0)
13026 #define TOK_SUB tok_decl(13,1)
13028 #define TOK_MUL tok_decl(14,0)
13029 #define TOK_DIV tok_decl(14,1)
13030 #define TOK_REM tok_decl(14,2)
13032 /* exponent is right associativity */
13033 #define TOK_EXPONENT tok_decl(15,1)
13035 /* For now unary operators. */
13036 #define UNARYPREC 16
13037 #define TOK_BNOT tok_decl(UNARYPREC,0)
13038 #define TOK_NOT tok_decl(UNARYPREC,1)
13040 #define TOK_UMINUS tok_decl(UNARYPREC+1,0)
13041 #define TOK_UPLUS tok_decl(UNARYPREC+1,1)
13043 #define PREC_PRE (UNARYPREC+2)
13045 #define TOK_PRE_INC tok_decl(PREC_PRE, 0)
13046 #define TOK_PRE_DEC tok_decl(PREC_PRE, 1)
13048 #define PREC_POST (UNARYPREC+3)
13050 #define TOK_POST_INC tok_decl(PREC_POST, 0)
13051 #define TOK_POST_DEC tok_decl(PREC_POST, 1)
13053 #define SPEC_PREC (UNARYPREC+4)
13055 #define TOK_NUM tok_decl(SPEC_PREC, 0)
13056 #define TOK_RPAREN tok_decl(SPEC_PREC, 1)
13058 #define NUMPTR (*numstackptr)
13061 tok_have_assign(operator op)
13063 operator prec = PREC(op);
13065 convert_prec_is_assing(prec);
13066 return (prec == PREC(TOK_ASSIGN) ||
13067 prec == PREC_PRE || prec == PREC_POST);
13071 is_right_associativity(operator prec)
13073 return (prec == PREC(TOK_ASSIGN) || prec == PREC(TOK_EXPONENT)
13074 || prec == PREC(TOK_CONDITIONAL));
13079 arith_t contidional_second_val;
13080 char contidional_second_val_initialized;
13081 char *var; /* if NULL then is regular number,
13082 else is variable name */
13085 typedef struct chk_var_recursive_looped_t {
13087 struct chk_var_recursive_looped_t *next;
13088 } chk_var_recursive_looped_t;
13090 static chk_var_recursive_looped_t *prev_chk_var_recursive;
13093 arith_lookup_val(v_n_t *t)
13096 const char * p = lookupvar(t->var);
13101 /* recursive try as expression */
13102 chk_var_recursive_looped_t *cur;
13103 chk_var_recursive_looped_t cur_save;
13105 for (cur = prev_chk_var_recursive; cur; cur = cur->next) {
13106 if (strcmp(cur->var, t->var) == 0) {
13107 /* expression recursion loop detected */
13111 /* save current lookuped var name */
13112 cur = prev_chk_var_recursive;
13113 cur_save.var = t->var;
13114 cur_save.next = cur;
13115 prev_chk_var_recursive = &cur_save;
13117 t->val = arith (p, &errcode);
13118 /* restore previous ptr after recursiving */
13119 prev_chk_var_recursive = cur;
13122 /* allow undefined var as 0 */
13128 /* "applying" a token means performing it on the top elements on the integer
13129 * stack. For a unary operator it will only change the top element, but a
13130 * binary operator will pop two arguments and push a result */
13132 arith_apply(operator op, v_n_t *numstack, v_n_t **numstackptr)
13135 arith_t numptr_val, rez;
13136 int ret_arith_lookup_val;
13138 /* There is no operator that can work without arguments */
13139 if (NUMPTR == numstack) goto err;
13140 numptr_m1 = NUMPTR - 1;
13142 /* check operand is var with noninteger value */
13143 ret_arith_lookup_val = arith_lookup_val(numptr_m1);
13144 if (ret_arith_lookup_val)
13145 return ret_arith_lookup_val;
13147 rez = numptr_m1->val;
13148 if (op == TOK_UMINUS)
13150 else if (op == TOK_NOT)
13152 else if (op == TOK_BNOT)
13154 else if (op == TOK_POST_INC || op == TOK_PRE_INC)
13156 else if (op == TOK_POST_DEC || op == TOK_PRE_DEC)
13158 else if (op != TOK_UPLUS) {
13159 /* Binary operators */
13161 /* check and binary operators need two arguments */
13162 if (numptr_m1 == numstack) goto err;
13164 /* ... and they pop one */
13167 if (op == TOK_CONDITIONAL) {
13168 if (!numptr_m1->contidional_second_val_initialized) {
13169 /* protect $((expr1 ? expr2)) without ": expr" */
13172 rez = numptr_m1->contidional_second_val;
13173 } else if (numptr_m1->contidional_second_val_initialized) {
13174 /* protect $((expr1 : expr2)) without "expr ? " */
13177 numptr_m1 = NUMPTR - 1;
13178 if (op != TOK_ASSIGN) {
13179 /* check operand is var with noninteger value for not '=' */
13180 ret_arith_lookup_val = arith_lookup_val(numptr_m1);
13181 if (ret_arith_lookup_val)
13182 return ret_arith_lookup_val;
13184 if (op == TOK_CONDITIONAL) {
13185 numptr_m1->contidional_second_val = rez;
13187 rez = numptr_m1->val;
13188 if (op == TOK_BOR || op == TOK_OR_ASSIGN)
13190 else if (op == TOK_OR)
13191 rez = numptr_val || rez;
13192 else if (op == TOK_BAND || op == TOK_AND_ASSIGN)
13194 else if (op == TOK_BXOR || op == TOK_XOR_ASSIGN)
13196 else if (op == TOK_AND)
13197 rez = rez && numptr_val;
13198 else if (op == TOK_EQ)
13199 rez = (rez == numptr_val);
13200 else if (op == TOK_NE)
13201 rez = (rez != numptr_val);
13202 else if (op == TOK_GE)
13203 rez = (rez >= numptr_val);
13204 else if (op == TOK_RSHIFT || op == TOK_RSHIFT_ASSIGN)
13205 rez >>= numptr_val;
13206 else if (op == TOK_LSHIFT || op == TOK_LSHIFT_ASSIGN)
13207 rez <<= numptr_val;
13208 else if (op == TOK_GT)
13209 rez = (rez > numptr_val);
13210 else if (op == TOK_LT)
13211 rez = (rez < numptr_val);
13212 else if (op == TOK_LE)
13213 rez = (rez <= numptr_val);
13214 else if (op == TOK_MUL || op == TOK_MUL_ASSIGN)
13216 else if (op == TOK_ADD || op == TOK_PLUS_ASSIGN)
13218 else if (op == TOK_SUB || op == TOK_MINUS_ASSIGN)
13220 else if (op == TOK_ASSIGN || op == TOK_COMMA)
13222 else if (op == TOK_CONDITIONAL_SEP) {
13223 if (numptr_m1 == numstack) {
13224 /* protect $((expr : expr)) without "expr ? " */
13227 numptr_m1->contidional_second_val_initialized = op;
13228 numptr_m1->contidional_second_val = numptr_val;
13229 } else if (op == TOK_CONDITIONAL) {
13231 numptr_val : numptr_m1->contidional_second_val;
13232 } else if (op == TOK_EXPONENT) {
13233 if (numptr_val < 0)
13234 return -3; /* exponent less than 0 */
13239 while (numptr_val--)
13243 } else if (numptr_val==0) /* zero divisor check */
13245 else if (op == TOK_DIV || op == TOK_DIV_ASSIGN)
13247 else if (op == TOK_REM || op == TOK_REM_ASSIGN)
13250 if (tok_have_assign(op)) {
13251 char buf[sizeof(arith_t_type)*3 + 2];
13253 if (numptr_m1->var == NULL) {
13257 /* save to shell variable */
13258 #if ENABLE_ASH_MATH_SUPPORT_64
13259 snprintf(buf, sizeof(buf), "%lld", (arith_t_type) rez);
13261 snprintf(buf, sizeof(buf), "%ld", (arith_t_type) rez);
13263 setvar(numptr_m1->var, buf, 0);
13264 /* after saving, make previous value for v++ or v-- */
13265 if (op == TOK_POST_INC)
13267 else if (op == TOK_POST_DEC)
13270 numptr_m1->val = rez;
13271 /* protect geting var value, is number now */
13272 numptr_m1->var = NULL;
13278 /* longest must be first */
13279 static const char op_tokens[] ALIGN1 = {
13280 '<','<','=',0, TOK_LSHIFT_ASSIGN,
13281 '>','>','=',0, TOK_RSHIFT_ASSIGN,
13282 '<','<', 0, TOK_LSHIFT,
13283 '>','>', 0, TOK_RSHIFT,
13284 '|','|', 0, TOK_OR,
13285 '&','&', 0, TOK_AND,
13286 '!','=', 0, TOK_NE,
13287 '<','=', 0, TOK_LE,
13288 '>','=', 0, TOK_GE,
13289 '=','=', 0, TOK_EQ,
13290 '|','=', 0, TOK_OR_ASSIGN,
13291 '&','=', 0, TOK_AND_ASSIGN,
13292 '*','=', 0, TOK_MUL_ASSIGN,
13293 '/','=', 0, TOK_DIV_ASSIGN,
13294 '%','=', 0, TOK_REM_ASSIGN,
13295 '+','=', 0, TOK_PLUS_ASSIGN,
13296 '-','=', 0, TOK_MINUS_ASSIGN,
13297 '-','-', 0, TOK_POST_DEC,
13298 '^','=', 0, TOK_XOR_ASSIGN,
13299 '+','+', 0, TOK_POST_INC,
13300 '*','*', 0, TOK_EXPONENT,
13304 '=', 0, TOK_ASSIGN,
13316 '?', 0, TOK_CONDITIONAL,
13317 ':', 0, TOK_CONDITIONAL_SEP,
13318 ')', 0, TOK_RPAREN,
13319 '(', 0, TOK_LPAREN,
13323 #define endexpression (&op_tokens[sizeof(op_tokens)-7])
13326 arith(const char *expr, int *perrcode)
13328 char arithval; /* Current character under analysis */
13329 operator lasttok, op;
13331 operator *stack, *stackptr;
13332 const char *p = endexpression;
13334 v_n_t *numstack, *numstackptr;
13335 unsigned datasizes = strlen(expr) + 2;
13337 /* Stack of integers */
13338 /* The proof that there can be no more than strlen(startbuf)/2+1 integers
13339 * in any given correct or incorrect expression is left as an exercise to
13341 numstackptr = numstack = alloca((datasizes / 2) * sizeof(numstack[0]));
13342 /* Stack of operator tokens */
13343 stackptr = stack = alloca(datasizes * sizeof(stack[0]));
13345 *stackptr++ = lasttok = TOK_LPAREN; /* start off with a left paren */
13346 *perrcode = errcode = 0;
13350 if (arithval == 0) {
13351 if (p == endexpression) {
13352 /* Null expression. */
13356 /* This is only reached after all tokens have been extracted from the
13357 * input stream. If there are still tokens on the operator stack, they
13358 * are to be applied in order. At the end, there should be a final
13359 * result on the integer stack */
13361 if (expr != endexpression + 1) {
13362 /* If we haven't done so already, */
13363 /* append a closing right paren */
13364 expr = endexpression;
13365 /* and let the loop process it. */
13368 /* At this point, we're done with the expression. */
13369 if (numstackptr != numstack+1) {
13370 /* ... but if there isn't, it's bad */
13375 if (numstack->var) {
13376 /* expression is $((var)) only, lookup now */
13377 errcode = arith_lookup_val(numstack);
13380 *perrcode = errcode;
13381 return numstack->val;
13384 /* Continue processing the expression. */
13385 if (arith_isspace(arithval)) {
13386 /* Skip whitespace */
13389 p = endofname(expr);
13391 size_t var_name_size = (p-expr) + 1; /* trailing zero */
13393 numstackptr->var = alloca(var_name_size);
13394 safe_strncpy(numstackptr->var, expr, var_name_size);
13397 numstackptr->contidional_second_val_initialized = 0;
13402 if (isdigit(arithval)) {
13403 numstackptr->var = NULL;
13404 #if ENABLE_ASH_MATH_SUPPORT_64
13405 numstackptr->val = strtoll(expr, (char **) &expr, 0);
13407 numstackptr->val = strtol(expr, (char **) &expr, 0);
13411 for (p = op_tokens; ; p++) {
13415 /* strange operator not found */
13418 for (o = expr; *p && *o == *p; p++)
13425 /* skip tail uncompared token */
13428 /* skip zero delim */
13433 /* post grammar: a++ reduce to num */
13434 if (lasttok == TOK_POST_INC || lasttok == TOK_POST_DEC)
13437 /* Plus and minus are binary (not unary) _only_ if the last
13438 * token was as number, or a right paren (which pretends to be
13439 * a number, since it evaluates to one). Think about it.
13440 * It makes sense. */
13441 if (lasttok != TOK_NUM) {
13457 /* We don't want a unary operator to cause recursive descent on the
13458 * stack, because there can be many in a row and it could cause an
13459 * operator to be evaluated before its argument is pushed onto the
13460 * integer stack. */
13461 /* But for binary operators, "apply" everything on the operator
13462 * stack until we find an operator with a lesser priority than the
13463 * one we have just extracted. */
13464 /* Left paren is given the lowest priority so it will never be
13465 * "applied" in this way.
13466 * if associativity is right and priority eq, applied also skip
13469 if ((prec > 0 && prec < UNARYPREC) || prec == SPEC_PREC) {
13470 /* not left paren or unary */
13471 if (lasttok != TOK_NUM) {
13472 /* binary op must be preceded by a num */
13475 while (stackptr != stack) {
13476 if (op == TOK_RPAREN) {
13477 /* The algorithm employed here is simple: while we don't
13478 * hit an open paren nor the bottom of the stack, pop
13479 * tokens and apply them */
13480 if (stackptr[-1] == TOK_LPAREN) {
13482 /* Any operator directly after a */
13484 /* close paren should consider itself binary */
13488 operator prev_prec = PREC(stackptr[-1]);
13490 convert_prec_is_assing(prec);
13491 convert_prec_is_assing(prev_prec);
13492 if (prev_prec < prec)
13494 /* check right assoc */
13495 if (prev_prec == prec && is_right_associativity(prec))
13498 errcode = arith_apply(*--stackptr, numstack, &numstackptr);
13499 if (errcode) goto ret;
13501 if (op == TOK_RPAREN) {
13506 /* Push this operator to the stack and remember it. */
13507 *stackptr++ = lasttok = op;
13512 #endif /* ASH_MATH_SUPPORT */
13515 /* ============ main() and helpers */
13518 * Called to exit the shell.
13520 static void exitshell(void) NORETURN;
13528 status = exitstatus;
13529 TRACE(("pid %d, exitshell(%d)\n", getpid(), status));
13530 if (setjmp(loc.loc)) {
13531 if (exception == EXEXIT)
13532 /* dash bug: it just does _exit(exitstatus) here
13533 * but we have to do setjobctl(0) first!
13534 * (bug is still not fixed in dash-0.5.3 - if you run dash
13535 * under Midnight Commander, on exit from dash MC is backgrounded) */
13536 status = exitstatus;
13539 exception_handler = &loc;
13545 flush_stdout_stderr();
13555 /* from input.c: */
13556 basepf.next_to_pgetc = basepf.buf = basebuf;
13559 signal(SIGCHLD, SIG_DFL);
13564 char ppid[sizeof(int)*3 + 1];
13566 struct stat st1, st2;
13569 for (envp = environ; envp && *envp; envp++) {
13570 if (strchr(*envp, '=')) {
13571 setvareq(*envp, VEXPORT|VTEXTFIXED);
13575 snprintf(ppid, sizeof(ppid), "%u", (unsigned) getppid());
13576 setvar("PPID", ppid, 0);
13578 p = lookupvar("PWD");
13580 if (*p != '/' || stat(p, &st1) || stat(".", &st2)
13581 || st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino)
13588 * Process the shell command line arguments.
13591 procargs(char **argv)
13594 const char *xminusc;
13599 /* if (xargv[0]) - mmm, this is always true! */
13601 for (i = 0; i < NOPTS; i++)
13605 /* it already printed err message */
13606 raise_exception(EXERROR);
13610 if (*xargv == NULL) {
13612 ash_msg_and_raise_error(bb_msg_requires_arg, "-c");
13615 if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
13619 for (i = 0; i < NOPTS; i++)
13620 if (optlist[i] == 2)
13625 /* POSIX 1003.2: first arg after -c cmd is $0, remainder $1... */
13630 } else if (!sflag) {
13631 setinputfile(*xargv, 0);
13634 commandname = arg0;
13637 shellparam.p = xargv;
13638 #if ENABLE_ASH_GETOPTS
13639 shellparam.optind = 1;
13640 shellparam.optoff = -1;
13642 /* assert(shellparam.malloced == 0 && shellparam.nparam == 0); */
13644 shellparam.nparam++;
13651 * Read /etc/profile or .profile.
13654 read_profile(const char *name)
13658 if (setinputfile(name, INPUT_PUSH_FILE | INPUT_NOFILE_OK) < 0)
13667 * This routine is called when an error or an interrupt occurs in an
13668 * interactive shell and control is returned to the main command loop.
13676 /* from input.c: */
13677 g_parsefile->left_in_buffer = 0;
13678 g_parsefile->left_in_line = 0; /* clear input buffer */
13680 /* from parser.c: */
13683 /* from redir.c: */
13684 clearredir(/*drop:*/ 0);
13688 static short profile_buf[16384];
13689 extern int etext();
13693 * Main routine. We initialize things, parse the arguments, execute
13694 * profiles if we're a login shell, and then call cmdloop to execute
13695 * commands. The setjmp call sets up the location to jump to when an
13696 * exception occurs. When an exception occurs the variable "state"
13697 * is used to figure out how far we had gotten.
13699 int ash_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
13700 int ash_main(int argc UNUSED_PARAM, char **argv)
13703 volatile smallint state;
13704 struct jmploc jmploc;
13705 struct stackmark smark;
13707 /* Initialize global data */
13711 #if ENABLE_ASH_ALIAS
13717 monitor(4, etext, profile_buf, sizeof(profile_buf), 50);
13720 #if ENABLE_FEATURE_EDITING
13721 line_input_state = new_line_input_t(FOR_SHELL | WITH_PATH_LOOKUP);
13724 if (setjmp(jmploc.loc)) {
13734 if (e == EXEXIT || s == 0 || iflag == 0 || shlvl)
13738 outcslow('\n', stderr);
13740 popstackmark(&smark);
13741 FORCE_INT_ON; /* enable interrupts */
13750 exception_handler = &jmploc;
13753 trace_puts("Shell args: ");
13754 trace_puts_args(argv);
13756 rootpid = getpid();
13758 #if ENABLE_ASH_RANDOM_SUPPORT
13759 /* Can use monotonic_ns() for better randomness but for now it is
13760 * not used anywhere else in busybox... so avoid bloat */
13761 random_galois_LFSR = random_LCG = rootpid + monotonic_us();
13764 setstackmark(&smark);
13767 #if ENABLE_FEATURE_EDITING_SAVEHISTORY
13769 const char *hp = lookupvar("HISTFILE");
13772 hp = lookupvar("HOME");
13774 char *defhp = concat_path_file(hp, ".ash_history");
13775 setvar("HISTFILE", defhp, 0);
13781 if (/* argv[0] && */ argv[0][0] == '-')
13785 read_profile("/etc/profile");
13788 read_profile(".profile");
13794 getuid() == geteuid() && getgid() == getegid() &&
13798 shinit = lookupvar("ENV");
13799 if (shinit != NULL && *shinit != '\0') {
13800 read_profile(shinit);
13806 evalstring(minusc, 0);
13808 if (sflag || minusc == NULL) {
13809 #if ENABLE_FEATURE_EDITING_SAVEHISTORY
13811 const char *hp = lookupvar("HISTFILE");
13814 line_input_state->hist_file = hp;
13817 state4: /* XXX ??? - why isn't this before the "if" statement */
13825 extern void _mcleanup(void);
13834 const char *applet_name = "debug stuff usage";
13835 int main(int argc, char **argv)
13837 return ash_main(argc, argv);
13843 * Copyright (c) 1989, 1991, 1993, 1994
13844 * The Regents of the University of California. All rights reserved.
13846 * This code is derived from software contributed to Berkeley by
13847 * Kenneth Almquist.
13849 * Redistribution and use in source and binary forms, with or without
13850 * modification, are permitted provided that the following conditions
13852 * 1. Redistributions of source code must retain the above copyright
13853 * notice, this list of conditions and the following disclaimer.
13854 * 2. Redistributions in binary form must reproduce the above copyright
13855 * notice, this list of conditions and the following disclaimer in the
13856 * documentation and/or other materials provided with the distribution.
13857 * 3. Neither the name of the University nor the names of its contributors
13858 * may be used to endorse or promote products derived from this software
13859 * without specific prior written permission.
13861 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
13862 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
13863 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
13864 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
13865 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
13866 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
13867 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
13868 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
13869 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
13870 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF