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 */
166 // pendingsig -> pending_sig
167 // intpending -> pending_int
168 volatile /*sig_atomic_t*/ smallint intpending; /* 1 = got SIGINT */
169 /* last pending signal */
170 volatile /*sig_atomic_t*/ smallint pendingsig;
171 smallint exception_type; /* kind of exception (0..5) */
173 #define EXINT 0 /* SIGINT received */
174 #define EXERROR 1 /* a generic error */
175 #define EXSHELLPROC 2 /* execute a shell procedure */
176 #define EXEXEC 3 /* command execution failed */
177 #define EXEXIT 4 /* exit the shell */
178 #define EXSIG 5 /* trapped signal in wait(1) */
181 char nullstr[1]; /* zero length string */
184 #define eflag optlist[0]
185 #define fflag optlist[1]
186 #define Iflag optlist[2]
187 #define iflag optlist[3]
188 #define mflag optlist[4]
189 #define nflag optlist[5]
190 #define sflag optlist[6]
191 #define xflag optlist[7]
192 #define vflag optlist[8]
193 #define Cflag optlist[9]
194 #define aflag optlist[10]
195 #define bflag optlist[11]
196 #define uflag optlist[12]
197 #define viflag optlist[13]
199 #define nolog optlist[14]
200 #define debug optlist[15]
203 /* trap handler commands */
205 * Sigmode records the current value of the signal handlers for the various
206 * modes. A value of zero means that the current handler is not known.
207 * S_HARD_IGN indicates that the signal was ignored on entry to the shell.
209 char sigmode[NSIG - 1];
210 #define S_DFL 1 /* default signal handling (SIG_DFL) */
211 #define S_CATCH 2 /* signal is caught */
212 #define S_IGN 3 /* signal is ignored (SIG_IGN) */
213 #define S_HARD_IGN 4 /* signal is ignored permenantly */
215 /* indicates specified signal received */
216 uint8_t gotsig[NSIG - 1]; /* offset by 1: "signal" 0 is meaningless */
219 /* Rarely referenced stuff */
220 #if ENABLE_ASH_RANDOM_SUPPORT
221 /* Random number generators */
222 int32_t random_galois_LFSR; /* Galois LFSR (fast but weak). signed! */
223 uint32_t random_LCG; /* LCG (fast but weak) */
225 pid_t backgndpid; /* pid of last background process */
226 smallint job_warning; /* user was warned about stopped jobs (can be 2, 1 or 0). */
228 extern struct globals_misc *const ash_ptr_to_globals_misc;
229 #define G_misc (*ash_ptr_to_globals_misc)
230 #define rootpid (G_misc.rootpid )
231 #define shlvl (G_misc.shlvl )
232 #define minusc (G_misc.minusc )
233 #define curdir (G_misc.curdir )
234 #define physdir (G_misc.physdir )
235 #define arg0 (G_misc.arg0 )
236 #define exception_handler (G_misc.exception_handler)
237 #define exception_type (G_misc.exception_type )
238 #define suppressint (G_misc.suppressint )
239 #define intpending (G_misc.intpending )
240 //#define exsig (G_misc.exsig )
241 #define pendingsig (G_misc.pendingsig )
242 #define isloginsh (G_misc.isloginsh )
243 #define nullstr (G_misc.nullstr )
244 #define optlist (G_misc.optlist )
245 #define sigmode (G_misc.sigmode )
246 #define gotsig (G_misc.gotsig )
247 #define trap (G_misc.trap )
248 #define random_galois_LFSR (G_misc.random_galois_LFSR)
249 #define random_LCG (G_misc.random_LCG )
250 #define backgndpid (G_misc.backgndpid )
251 #define job_warning (G_misc.job_warning)
252 #define INIT_G_misc() do { \
253 (*(struct globals_misc**)&ash_ptr_to_globals_misc) = xzalloc(sizeof(G_misc)); \
260 /* ============ Utility functions */
261 static int isdigit_str9(const char *str)
263 int maxlen = 9 + 1; /* max 9 digits: 999999999 */
264 while (--maxlen && isdigit(*str))
266 return (*str == '\0');
270 /* ============ Interrupts / exceptions */
272 * These macros allow the user to suspend the handling of interrupt signals
273 * over a period of time. This is similar to SIGHOLD or to sigblock, but
274 * much more efficient and portable. (But hacking the kernel is so much
275 * more fun than worrying about efficiency and portability. :-))
277 #define INT_OFF do { \
283 * Called to raise an exception. Since C doesn't include exceptions, we
284 * just do a longjmp to the exception handler. The type of exception is
285 * stored in the global variable "exception_type".
287 static void raise_exception(int) NORETURN;
289 raise_exception(int e)
292 if (exception_handler == NULL)
297 longjmp(exception_handler->loc, 1);
301 * Called from trap.c when a SIGINT is received. (If the user specifies
302 * that SIGINT is to be trapped or ignored using the trap builtin, then
303 * this routine is not called.) Suppressint is nonzero when interrupts
304 * are held using the INT_OFF macro. (The test for iflag is just
305 * defensive programming.)
307 static void raise_interrupt(void) NORETURN;
309 raise_interrupt(void)
314 /* Signal is not automatically unmasked after it is raised,
315 * do it ourself - unmask all signals */
316 sigprocmask_allsigs(SIG_UNBLOCK);
317 /* pendingsig = 0; - now done in onsig() */
320 if (gotsig[SIGINT - 1] && !trap[SIGINT]) {
321 if (!(rootshell && iflag)) {
322 /* Kill ourself with SIGINT */
323 signal(SIGINT, SIG_DFL);
328 raise_exception(ex_type);
332 #if ENABLE_ASH_OPTIMIZE_FOR_SIZE
336 if (--suppressint == 0 && intpending) {
340 #define INT_ON int_on()
348 #define FORCE_INT_ON force_int_on()
350 #define INT_ON do { \
352 if (--suppressint == 0 && intpending) \
355 #define FORCE_INT_ON do { \
361 #endif /* ASH_OPTIMIZE_FOR_SIZE */
363 #define SAVE_INT(v) ((v) = suppressint)
365 #define RESTORE_INT(v) do { \
368 if (suppressint == 0 && intpending) \
373 /* ============ Stdout/stderr output */
376 outstr(const char *p, FILE *file)
384 flush_stdout_stderr(void)
401 outcslow(int c, FILE *dest)
409 static int out1fmt(const char *, ...) __attribute__((__format__(__printf__,1,2)));
411 out1fmt(const char *fmt, ...)
418 r = vprintf(fmt, ap);
424 static int fmtstr(char *, size_t, const char *, ...) __attribute__((__format__(__printf__,3,4)));
426 fmtstr(char *outbuf, size_t length, const char *fmt, ...)
433 ret = vsnprintf(outbuf, length, fmt, ap);
440 out1str(const char *p)
446 out2str(const char *p)
453 /* ============ Parser structures */
455 /* control characters in argument strings */
456 #define CTLESC '\201' /* escape next character */
457 #define CTLVAR '\202' /* variable defn */
458 #define CTLENDVAR '\203'
459 #define CTLBACKQ '\204'
460 #define CTLQUOTE 01 /* ored with CTLBACKQ code if in quotes */
461 /* CTLBACKQ | CTLQUOTE == '\205' */
462 #define CTLARI '\206' /* arithmetic expression */
463 #define CTLENDARI '\207'
464 #define CTLQUOTEMARK '\210'
466 /* variable substitution byte (follows CTLVAR) */
467 #define VSTYPE 0x0f /* type of variable substitution */
468 #define VSNUL 0x10 /* colon--treat the empty string as unset */
469 #define VSQUOTE 0x80 /* inside double quotes--suppress splitting */
471 /* values of VSTYPE field */
472 #define VSNORMAL 0x1 /* normal variable: $var or ${var} */
473 #define VSMINUS 0x2 /* ${var-text} */
474 #define VSPLUS 0x3 /* ${var+text} */
475 #define VSQUESTION 0x4 /* ${var?message} */
476 #define VSASSIGN 0x5 /* ${var=text} */
477 #define VSTRIMRIGHT 0x6 /* ${var%pattern} */
478 #define VSTRIMRIGHTMAX 0x7 /* ${var%%pattern} */
479 #define VSTRIMLEFT 0x8 /* ${var#pattern} */
480 #define VSTRIMLEFTMAX 0x9 /* ${var##pattern} */
481 #define VSLENGTH 0xa /* ${#var} */
482 #if ENABLE_ASH_BASH_COMPAT
483 #define VSSUBSTR 0xc /* ${var:position:length} */
484 #define VSREPLACE 0xd /* ${var/pattern/replacement} */
485 #define VSREPLACEALL 0xe /* ${var//pattern/replacement} */
488 static const char dolatstr[] ALIGN1 = {
489 CTLVAR, VSNORMAL|VSQUOTE, '@', '=', '\0'
509 #if ENABLE_ASH_BASH_COMPAT
526 smallint type; /* Nxxxx */
529 union node *redirect;
534 smallint pipe_backgnd;
535 struct nodelist *cmdlist;
541 union node *redirect;
554 union node *elsepart;
581 struct nodelist *backquote;
584 /* nfile and ndup layout must match!
585 * NTOFD (>&fdnum) uses ndup structure, but we may discover mid-flight
586 * that it is actually NTO2 (>&file), and change its type.
603 char *_unused_expfname;
622 struct nredir nredir;
623 struct nbinary nbinary;
627 struct nclist nclist;
636 struct nodelist *next;
649 freefunc(struct funcnode *f)
651 if (f && --f->count < 0)
656 /* ============ Debugging output */
660 static FILE *tracefile;
663 trace_printf(const char *fmt, ...)
670 vfprintf(tracefile, fmt, va);
675 trace_vprintf(const char *fmt, va_list va)
679 vfprintf(tracefile, fmt, va);
683 trace_puts(const char *s)
691 trace_puts_quoted(char *s)
698 putc('"', tracefile);
699 for (p = s; *p; p++) {
701 case '\n': c = 'n'; goto backslash;
702 case '\t': c = 't'; goto backslash;
703 case '\r': c = 'r'; goto backslash;
704 case '"': c = '"'; goto backslash;
705 case '\\': c = '\\'; goto backslash;
706 case CTLESC: c = 'e'; goto backslash;
707 case CTLVAR: c = 'v'; goto backslash;
708 case CTLVAR+CTLQUOTE: c = 'V'; goto backslash;
709 case CTLBACKQ: c = 'q'; goto backslash;
710 case CTLBACKQ+CTLQUOTE: c = 'Q'; goto backslash;
712 putc('\\', tracefile);
716 if (*p >= ' ' && *p <= '~')
719 putc('\\', tracefile);
720 putc(*p >> 6 & 03, tracefile);
721 putc(*p >> 3 & 07, tracefile);
722 putc(*p & 07, tracefile);
727 putc('"', tracefile);
731 trace_puts_args(char **ap)
738 trace_puts_quoted(*ap);
740 putc('\n', tracefile);
743 putc(' ', tracefile);
758 /* leave open because libedit might be using it */
761 strcpy(s, "./trace");
763 if (!freopen(s, "a", tracefile)) {
764 fprintf(stderr, "Can't re-open %s\n", s);
769 tracefile = fopen(s, "a");
770 if (tracefile == NULL) {
771 fprintf(stderr, "Can't open %s\n", s);
777 flags = fcntl(fileno(tracefile), F_GETFL);
779 fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND);
781 setlinebuf(tracefile);
782 fputs("\nTracing started.\n", tracefile);
786 indent(int amount, char *pfx, FILE *fp)
790 for (i = 0; i < amount; i++) {
791 if (pfx && i == amount - 1)
797 /* little circular references here... */
798 static void shtree(union node *n, int ind, char *pfx, FILE *fp);
801 sharg(union node *arg, FILE *fp)
804 struct nodelist *bqlist;
807 if (arg->type != NARG) {
808 out1fmt("<node type %d>\n", arg->type);
811 bqlist = arg->narg.backquote;
812 for (p = arg->narg.text; *p; p++) {
821 if (subtype == VSLENGTH)
830 switch (subtype & VSTYPE) {
863 out1fmt("<subtype %d>", subtype);
870 case CTLBACKQ|CTLQUOTE:
873 shtree(bqlist->n, -1, NULL, fp);
884 shcmd(union node *cmd, FILE *fp)
892 for (np = cmd->ncmd.args; np; np = np->narg.next) {
898 for (np = cmd->ncmd.redirect; np; np = np->nfile.next) {
902 switch (np->nfile.type) {
903 case NTO: s = ">>"+1; dftfd = 1; break;
904 case NCLOBBER: s = ">|"; dftfd = 1; break;
905 case NAPPEND: s = ">>"; dftfd = 1; break;
906 #if ENABLE_ASH_BASH_COMPAT
909 case NTOFD: s = ">&"; dftfd = 1; break;
910 case NFROM: s = "<"; break;
911 case NFROMFD: s = "<&"; break;
912 case NFROMTO: s = "<>"; break;
913 default: s = "*error*"; break;
915 if (np->nfile.fd != dftfd)
916 fprintf(fp, "%d", np->nfile.fd);
918 if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) {
919 fprintf(fp, "%d", np->ndup.dupfd);
921 sharg(np->nfile.fname, fp);
928 shtree(union node *n, int ind, char *pfx, FILE *fp)
936 indent(ind, pfx, fp);
947 shtree(n->nbinary.ch1, ind, NULL, fp);
950 shtree(n->nbinary.ch2, ind, NULL, fp);
958 for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
963 if (n->npipe.pipe_backgnd)
969 fprintf(fp, "<node type %d>", n->type);
977 showtree(union node *n)
979 trace_puts("showtree called\n");
980 shtree(n, 1, NULL, stdout);
983 #define TRACE(param) trace_printf param
984 #define TRACEV(param) trace_vprintf param
989 #define TRACEV(param)
994 /* ============ Parser data */
997 * ash_vmsg() needs parsefile->fd, hence parsefile definition is moved up.
1000 struct strlist *next;
1007 struct strpush *prev; /* preceding string on stack */
1009 int prev_left_in_line;
1010 #if ENABLE_ASH_ALIAS
1011 struct alias *ap; /* if push was associated with an alias */
1013 char *string; /* remember the string since it may change */
1017 struct parsefile *prev; /* preceding file on stack */
1018 int linno; /* current line */
1019 int fd; /* file descriptor (or -1 if string) */
1020 int left_in_line; /* number of chars left in this line */
1021 int left_in_buffer; /* number of chars left in this buffer past the line */
1022 char *next_to_pgetc; /* next char in buffer */
1023 char *buf; /* input buffer */
1024 struct strpush *strpush; /* for pushing strings at this level */
1025 struct strpush basestrpush; /* so pushing one is fast */
1028 static struct parsefile basepf; /* top level input file */
1029 static struct parsefile *g_parsefile = &basepf; /* current input file */
1030 static int startlinno; /* line # where last token started */
1031 static char *commandname; /* currently executing command */
1032 static struct strlist *cmdenviron; /* environment for builtin command */
1033 static uint8_t exitstatus; /* exit status of last command */
1036 /* ============ Message printing */
1039 ash_vmsg(const char *msg, va_list ap)
1041 fprintf(stderr, "%s: ", arg0);
1043 if (strcmp(arg0, commandname))
1044 fprintf(stderr, "%s: ", commandname);
1045 if (!iflag || g_parsefile->fd)
1046 fprintf(stderr, "line %d: ", startlinno);
1048 vfprintf(stderr, msg, ap);
1049 outcslow('\n', stderr);
1053 * Exverror is called to raise the error exception. If the second argument
1054 * is not NULL then error prints an error message using printf style
1055 * formatting. It then raises the error exception.
1057 static void ash_vmsg_and_raise(int, const char *, va_list) NORETURN;
1059 ash_vmsg_and_raise(int cond, const char *msg, va_list ap)
1063 TRACE(("ash_vmsg_and_raise(%d, \"", cond));
1065 TRACE(("\") pid=%d\n", getpid()));
1067 TRACE(("ash_vmsg_and_raise(%d, NULL) pid=%d\n", cond, getpid()));
1072 flush_stdout_stderr();
1073 raise_exception(cond);
1077 static void ash_msg_and_raise_error(const char *, ...) NORETURN;
1079 ash_msg_and_raise_error(const char *msg, ...)
1084 ash_vmsg_and_raise(EXERROR, msg, ap);
1089 static void ash_msg_and_raise(int, const char *, ...) NORETURN;
1091 ash_msg_and_raise(int cond, const char *msg, ...)
1096 ash_vmsg_and_raise(cond, msg, ap);
1102 * error/warning routines for external builtins
1105 ash_msg(const char *fmt, ...)
1115 * Return a string describing an error. The returned string may be a
1116 * pointer to a static buffer that will be overwritten on the next call.
1117 * Action describes the operation that got the error.
1120 errmsg(int e, const char *em)
1122 if (e == ENOENT || e == ENOTDIR) {
1129 /* ============ Memory allocation */
1132 * It appears that grabstackstr() will barf with such alignments
1133 * because stalloc() will return a string allocated in a new stackblock.
1135 #define SHELL_ALIGN(nbytes) (((nbytes) + SHELL_SIZE) & ~SHELL_SIZE)
1137 /* Most machines require the value returned from malloc to be aligned
1138 * in some way. The following macro will get this right
1139 * on many machines. */
1140 SHELL_SIZE = sizeof(union {int i; char *cp; double d; }) - 1,
1141 /* Minimum size of a block */
1142 MINSIZE = SHELL_ALIGN(504),
1145 struct stack_block {
1146 struct stack_block *prev;
1147 char space[MINSIZE];
1151 struct stack_block *stackp;
1154 struct stackmark *marknext;
1158 struct globals_memstack {
1159 struct stack_block *g_stackp; // = &stackbase;
1160 struct stackmark *markp;
1161 char *g_stacknxt; // = stackbase.space;
1162 char *sstrend; // = stackbase.space + MINSIZE;
1163 size_t g_stacknleft; // = MINSIZE;
1164 int herefd; // = -1;
1165 struct stack_block stackbase;
1167 extern struct globals_memstack *const ash_ptr_to_globals_memstack;
1168 #define G_memstack (*ash_ptr_to_globals_memstack)
1169 #define g_stackp (G_memstack.g_stackp )
1170 #define markp (G_memstack.markp )
1171 #define g_stacknxt (G_memstack.g_stacknxt )
1172 #define sstrend (G_memstack.sstrend )
1173 #define g_stacknleft (G_memstack.g_stacknleft)
1174 #define herefd (G_memstack.herefd )
1175 #define stackbase (G_memstack.stackbase )
1176 #define INIT_G_memstack() do { \
1177 (*(struct globals_memstack**)&ash_ptr_to_globals_memstack) = xzalloc(sizeof(G_memstack)); \
1179 g_stackp = &stackbase; \
1180 g_stacknxt = stackbase.space; \
1181 g_stacknleft = MINSIZE; \
1182 sstrend = stackbase.space + MINSIZE; \
1186 #define stackblock() ((void *)g_stacknxt)
1187 #define stackblocksize() g_stacknleft
1191 ckrealloc(void * p, size_t nbytes)
1193 p = realloc(p, nbytes);
1195 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1200 ckmalloc(size_t nbytes)
1202 return ckrealloc(NULL, nbytes);
1206 ckzalloc(size_t nbytes)
1208 return memset(ckmalloc(nbytes), 0, nbytes);
1212 * Make a copy of a string in safe storage.
1215 ckstrdup(const char *s)
1217 char *p = strdup(s);
1219 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1224 * Parse trees for commands are allocated in lifo order, so we use a stack
1225 * to make this more efficient, and also to avoid all sorts of exception
1226 * handling code to handle interrupts in the middle of a parse.
1228 * The size 504 was chosen because the Ultrix malloc handles that size
1232 stalloc(size_t nbytes)
1237 aligned = SHELL_ALIGN(nbytes);
1238 if (aligned > g_stacknleft) {
1241 struct stack_block *sp;
1243 blocksize = aligned;
1244 if (blocksize < MINSIZE)
1245 blocksize = MINSIZE;
1246 len = sizeof(struct stack_block) - MINSIZE + blocksize;
1247 if (len < blocksize)
1248 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1251 sp->prev = g_stackp;
1252 g_stacknxt = sp->space;
1253 g_stacknleft = blocksize;
1254 sstrend = g_stacknxt + blocksize;
1259 g_stacknxt += aligned;
1260 g_stacknleft -= aligned;
1265 stzalloc(size_t nbytes)
1267 return memset(stalloc(nbytes), 0, nbytes);
1274 if (!p || (g_stacknxt < (char *)p) || ((char *)p < g_stackp->space)) {
1275 write(STDERR_FILENO, "stunalloc\n", 10);
1279 g_stacknleft += g_stacknxt - (char *)p;
1284 * Like strdup but works with the ash stack.
1287 ststrdup(const char *p)
1289 size_t len = strlen(p) + 1;
1290 return memcpy(stalloc(len), p, len);
1294 setstackmark(struct stackmark *mark)
1296 mark->stackp = g_stackp;
1297 mark->stacknxt = g_stacknxt;
1298 mark->stacknleft = g_stacknleft;
1299 mark->marknext = markp;
1304 popstackmark(struct stackmark *mark)
1306 struct stack_block *sp;
1312 markp = mark->marknext;
1313 while (g_stackp != mark->stackp) {
1315 g_stackp = sp->prev;
1318 g_stacknxt = mark->stacknxt;
1319 g_stacknleft = mark->stacknleft;
1320 sstrend = mark->stacknxt + mark->stacknleft;
1325 * When the parser reads in a string, it wants to stick the string on the
1326 * stack and only adjust the stack pointer when it knows how big the
1327 * string is. Stackblock (defined in stack.h) returns a pointer to a block
1328 * of space on top of the stack and stackblocklen returns the length of
1329 * this block. Growstackblock will grow this space by at least one byte,
1330 * possibly moving it (like realloc). Grabstackblock actually allocates the
1331 * part of the block that has been used.
1334 growstackblock(void)
1338 newlen = g_stacknleft * 2;
1339 if (newlen < g_stacknleft)
1340 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1344 if (g_stacknxt == g_stackp->space && g_stackp != &stackbase) {
1345 struct stack_block *oldstackp;
1346 struct stackmark *xmark;
1347 struct stack_block *sp;
1348 struct stack_block *prevstackp;
1352 oldstackp = g_stackp;
1354 prevstackp = sp->prev;
1355 grosslen = newlen + sizeof(struct stack_block) - MINSIZE;
1356 sp = ckrealloc(sp, grosslen);
1357 sp->prev = prevstackp;
1359 g_stacknxt = sp->space;
1360 g_stacknleft = newlen;
1361 sstrend = sp->space + newlen;
1364 * Stack marks pointing to the start of the old block
1365 * must be relocated to point to the new block
1368 while (xmark != NULL && xmark->stackp == oldstackp) {
1369 xmark->stackp = g_stackp;
1370 xmark->stacknxt = g_stacknxt;
1371 xmark->stacknleft = g_stacknleft;
1372 xmark = xmark->marknext;
1376 char *oldspace = g_stacknxt;
1377 size_t oldlen = g_stacknleft;
1378 char *p = stalloc(newlen);
1380 /* free the space we just allocated */
1381 g_stacknxt = memcpy(p, oldspace, oldlen);
1382 g_stacknleft += newlen;
1387 grabstackblock(size_t len)
1389 len = SHELL_ALIGN(len);
1391 g_stacknleft -= len;
1395 * The following routines are somewhat easier to use than the above.
1396 * The user declares a variable of type STACKSTR, which may be declared
1397 * to be a register. The macro STARTSTACKSTR initializes things. Then
1398 * the user uses the macro STPUTC to add characters to the string. In
1399 * effect, STPUTC(c, p) is the same as *p++ = c except that the stack is
1400 * grown as necessary. When the user is done, she can just leave the
1401 * string there and refer to it using stackblock(). Or she can allocate
1402 * the space for it using grabstackstr(). If it is necessary to allow
1403 * someone else to use the stack temporarily and then continue to grow
1404 * the string, the user should use grabstack to allocate the space, and
1405 * then call ungrabstr(p) to return to the previous mode of operation.
1407 * USTPUTC is like STPUTC except that it doesn't check for overflow.
1408 * CHECKSTACKSPACE can be called before USTPUTC to ensure that there
1409 * is space for at least one character.
1414 size_t len = stackblocksize();
1415 if (herefd >= 0 && len >= 1024) {
1416 full_write(herefd, stackblock(), len);
1417 return stackblock();
1420 return (char *)stackblock() + len;
1424 * Called from CHECKSTRSPACE.
1427 makestrspace(size_t newlen, char *p)
1429 size_t len = p - g_stacknxt;
1430 size_t size = stackblocksize();
1435 size = stackblocksize();
1437 if (nleft >= newlen)
1441 return (char *)stackblock() + len;
1445 stack_nputstr(const char *s, size_t n, char *p)
1447 p = makestrspace(n, p);
1448 p = (char *)memcpy(p, s, n) + n;
1453 stack_putstr(const char *s, char *p)
1455 return stack_nputstr(s, strlen(s), p);
1459 _STPUTC(int c, char *p)
1467 #define STARTSTACKSTR(p) ((p) = stackblock())
1468 #define STPUTC(c, p) ((p) = _STPUTC((c), (p)))
1469 #define CHECKSTRSPACE(n, p) do { \
1472 size_t m = sstrend - q; \
1474 (p) = makestrspace(l, q); \
1476 #define USTPUTC(c, p) (*(p)++ = (c))
1477 #define STACKSTRNUL(p) do { \
1478 if ((p) == sstrend) \
1479 (p) = growstackstr(); \
1482 #define STUNPUTC(p) (--(p))
1483 #define STTOPC(p) ((p)[-1])
1484 #define STADJUST(amount, p) ((p) += (amount))
1486 #define grabstackstr(p) stalloc((char *)(p) - (char *)stackblock())
1487 #define ungrabstackstr(s, p) stunalloc(s)
1488 #define stackstrend() ((void *)sstrend)
1491 /* ============ String helpers */
1494 * prefix -- see if pfx is a prefix of string.
1497 prefix(const char *string, const char *pfx)
1500 if (*pfx++ != *string++)
1503 return (char *) string;
1507 * Check for a valid number. This should be elsewhere.
1510 is_number(const char *p)
1515 } while (*++p != '\0');
1520 * Convert a string of digits to an integer, printing an error message on
1524 number(const char *s)
1527 ash_msg_and_raise_error(illnum, s);
1532 * Produce a possibly single quoted string suitable as input to the shell.
1533 * The return string is allocated on the stack.
1536 single_quote(const char *s)
1546 len = strchrnul(s, '\'') - s;
1548 q = p = makestrspace(len + 3, p);
1551 q = (char *)memcpy(q, s, len) + len;
1557 len = strspn(s, "'");
1561 q = p = makestrspace(len + 3, p);
1564 q = (char *)memcpy(q, s, len) + len;
1573 return stackblock();
1577 /* ============ nextopt */
1579 static char **argptr; /* argument list for builtin commands */
1580 static char *optionarg; /* set by nextopt (like getopt) */
1581 static char *optptr; /* used by nextopt */
1584 * XXX - should get rid of. Have all builtins use getopt(3).
1585 * The library getopt must have the BSD extension static variable
1586 * "optreset", otherwise it can't be used within the shell safely.
1588 * Standard option processing (a la getopt) for builtin routines.
1589 * The only argument that is passed to nextopt is the option string;
1590 * the other arguments are unnecessary. It returns the character,
1591 * or '\0' on end of input.
1594 nextopt(const char *optstring)
1601 if (p == NULL || *p == '\0') {
1602 /* We ate entire "-param", take next one */
1608 if (*++p == '\0') /* just "-" ? */
1611 if (LONE_DASH(p)) /* "--" ? */
1613 /* p => next "-param" */
1615 /* p => some option char in the middle of a "-param" */
1617 for (q = optstring; *q != c;) {
1619 ash_msg_and_raise_error("illegal option -%c", c);
1627 ash_msg_and_raise_error("no arg for -%c option", c);
1637 /* ============ Shell variables */
1640 * The parsefile structure pointed to by the global variable parsefile
1641 * contains information about the current file being read.
1644 int nparam; /* # of positional parameters (without $0) */
1645 #if ENABLE_ASH_GETOPTS
1646 int optind; /* next parameter to be processed by getopts */
1647 int optoff; /* used by getopts */
1649 unsigned char malloced; /* if parameter list dynamically allocated */
1650 char **p; /* parameter list */
1654 * Free the list of positional parameters.
1657 freeparam(volatile struct shparam *param)
1659 if (param->malloced) {
1661 ap = ap1 = param->p;
1668 #if ENABLE_ASH_GETOPTS
1669 static void getoptsreset(const char *value);
1673 struct var *next; /* next entry in hash list */
1674 int flags; /* flags are defined above */
1675 const char *text; /* name=value */
1676 void (*func)(const char *); /* function to be called when */
1677 /* the variable gets set/unset */
1681 struct localvar *next; /* next local variable in list */
1682 struct var *vp; /* the variable that was made local */
1683 int flags; /* saved flags */
1684 const char *text; /* saved text */
1688 #define VEXPORT 0x01 /* variable is exported */
1689 #define VREADONLY 0x02 /* variable cannot be modified */
1690 #define VSTRFIXED 0x04 /* variable struct is statically allocated */
1691 #define VTEXTFIXED 0x08 /* text is statically allocated */
1692 #define VSTACK 0x10 /* text is allocated on the stack */
1693 #define VUNSET 0x20 /* the variable is not set */
1694 #define VNOFUNC 0x40 /* don't call the callback function */
1695 #define VNOSET 0x80 /* do not set variable - just readonly test */
1696 #define VNOSAVE 0x100 /* when text is on the heap before setvareq */
1697 #if ENABLE_ASH_RANDOM_SUPPORT
1698 # define VDYNAMIC 0x200 /* dynamic variable */
1704 static const char defifsvar[] ALIGN1 = "IFS= \t\n";
1705 #define defifs (defifsvar + 4)
1707 static const char defifs[] ALIGN1 = " \t\n";
1711 /* Need to be before varinit_data[] */
1712 #if ENABLE_LOCALE_SUPPORT
1714 change_lc_all(const char *value)
1716 if (value && *value != '\0')
1717 setlocale(LC_ALL, value);
1720 change_lc_ctype(const char *value)
1722 if (value && *value != '\0')
1723 setlocale(LC_CTYPE, value);
1727 static void chkmail(void);
1728 static void changemail(const char *);
1730 static void changepath(const char *);
1731 #if ENABLE_ASH_RANDOM_SUPPORT
1732 static void change_random(const char *);
1735 static const struct {
1738 void (*func)(const char *);
1739 } varinit_data[] = {
1741 { VSTRFIXED|VTEXTFIXED , defifsvar , NULL },
1743 { VSTRFIXED|VTEXTFIXED|VUNSET, "IFS\0" , NULL },
1746 { VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL\0" , changemail },
1747 { VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH\0", changemail },
1749 { VSTRFIXED|VTEXTFIXED , bb_PATH_root_path, changepath },
1750 { VSTRFIXED|VTEXTFIXED , "PS1=$ " , NULL },
1751 { VSTRFIXED|VTEXTFIXED , "PS2=> " , NULL },
1752 { VSTRFIXED|VTEXTFIXED , "PS4=+ " , NULL },
1753 #if ENABLE_ASH_GETOPTS
1754 { VSTRFIXED|VTEXTFIXED , "OPTIND=1" , getoptsreset },
1756 #if ENABLE_ASH_RANDOM_SUPPORT
1757 { VSTRFIXED|VTEXTFIXED|VUNSET|VDYNAMIC, "RANDOM\0", change_random },
1759 #if ENABLE_LOCALE_SUPPORT
1760 { VSTRFIXED|VTEXTFIXED|VUNSET, "LC_ALL\0" , change_lc_all },
1761 { VSTRFIXED|VTEXTFIXED|VUNSET, "LC_CTYPE\0", change_lc_ctype },
1763 #if ENABLE_FEATURE_EDITING_SAVEHISTORY
1764 { VSTRFIXED|VTEXTFIXED|VUNSET, "HISTFILE\0", NULL },
1770 struct globals_var {
1771 struct shparam shellparam; /* $@ current positional parameters */
1772 struct redirtab *redirlist;
1774 int preverrout_fd; /* save fd2 before print debug if xflag is set. */
1775 struct var *vartab[VTABSIZE];
1776 struct var varinit[ARRAY_SIZE(varinit_data)];
1778 extern struct globals_var *const ash_ptr_to_globals_var;
1779 #define G_var (*ash_ptr_to_globals_var)
1780 #define shellparam (G_var.shellparam )
1781 //#define redirlist (G_var.redirlist )
1782 #define g_nullredirs (G_var.g_nullredirs )
1783 #define preverrout_fd (G_var.preverrout_fd)
1784 #define vartab (G_var.vartab )
1785 #define varinit (G_var.varinit )
1786 #define INIT_G_var() do { \
1788 (*(struct globals_var**)&ash_ptr_to_globals_var) = xzalloc(sizeof(G_var)); \
1790 for (i = 0; i < ARRAY_SIZE(varinit_data); i++) { \
1791 varinit[i].flags = varinit_data[i].flags; \
1792 varinit[i].text = varinit_data[i].text; \
1793 varinit[i].func = varinit_data[i].func; \
1797 #define vifs varinit[0]
1799 # define vmail (&vifs)[1]
1800 # define vmpath (&vmail)[1]
1801 # define vpath (&vmpath)[1]
1803 # define vpath (&vifs)[1]
1805 #define vps1 (&vpath)[1]
1806 #define vps2 (&vps1)[1]
1807 #define vps4 (&vps2)[1]
1808 #if ENABLE_ASH_GETOPTS
1809 # define voptind (&vps4)[1]
1810 # if ENABLE_ASH_RANDOM_SUPPORT
1811 # define vrandom (&voptind)[1]
1814 # if ENABLE_ASH_RANDOM_SUPPORT
1815 # define vrandom (&vps4)[1]
1820 * The following macros access the values of the above variables.
1821 * They have to skip over the name. They return the null string
1822 * for unset variables.
1824 #define ifsval() (vifs.text + 4)
1825 #define ifsset() ((vifs.flags & VUNSET) == 0)
1827 # define mailval() (vmail.text + 5)
1828 # define mpathval() (vmpath.text + 9)
1829 # define mpathset() ((vmpath.flags & VUNSET) == 0)
1831 #define pathval() (vpath.text + 5)
1832 #define ps1val() (vps1.text + 4)
1833 #define ps2val() (vps2.text + 4)
1834 #define ps4val() (vps4.text + 4)
1835 #if ENABLE_ASH_GETOPTS
1836 # define optindval() (voptind.text + 7)
1840 #define is_name(c) ((c) == '_' || isalpha((unsigned char)(c)))
1841 #define is_in_name(c) ((c) == '_' || isalnum((unsigned char)(c)))
1843 #if ENABLE_ASH_GETOPTS
1845 getoptsreset(const char *value)
1847 shellparam.optind = number(value);
1848 shellparam.optoff = -1;
1853 * Return of a legal variable name (a letter or underscore followed by zero or
1854 * more letters, underscores, and digits).
1857 endofname(const char *name)
1865 if (!is_in_name(*p))
1872 * Compares two strings up to the first = or '\0'. The first
1873 * string must be terminated by '='; the second may be terminated by
1874 * either '=' or '\0'.
1877 varcmp(const char *p, const char *q)
1881 while ((c = *p) == (d = *q)) {
1896 varequal(const char *a, const char *b)
1898 return !varcmp(a, b);
1902 * Find the appropriate entry in the hash table from the name.
1904 static struct var **
1905 hashvar(const char *p)
1909 hashval = ((unsigned char) *p) << 4;
1910 while (*p && *p != '=')
1911 hashval += (unsigned char) *p++;
1912 return &vartab[hashval % VTABSIZE];
1916 vpcmp(const void *a, const void *b)
1918 return varcmp(*(const char **)a, *(const char **)b);
1922 * This routine initializes the builtin variables.
1932 * PS1 depends on uid
1934 #if ENABLE_FEATURE_EDITING && ENABLE_FEATURE_EDITING_FANCY_PROMPT
1935 vps1.text = "PS1=\\w \\$ ";
1938 vps1.text = "PS1=# ";
1941 end = vp + ARRAY_SIZE(varinit);
1943 vpp = hashvar(vp->text);
1946 } while (++vp < end);
1949 static struct var **
1950 findvar(struct var **vpp, const char *name)
1952 for (; *vpp; vpp = &(*vpp)->next) {
1953 if (varequal((*vpp)->text, name)) {
1961 * Find the value of a variable. Returns NULL if not set.
1964 lookupvar(const char *name)
1968 v = *findvar(hashvar(name), name);
1970 #if ENABLE_ASH_RANDOM_SUPPORT
1972 * Dynamic variables are implemented roughly the same way they are
1973 * in bash. Namely, they're "special" so long as they aren't unset.
1974 * As soon as they're unset, they're no longer dynamic, and dynamic
1975 * lookup will no longer happen at that point. -- PFM.
1977 if ((v->flags & VDYNAMIC))
1980 if (!(v->flags & VUNSET))
1981 return strchrnul(v->text, '=') + 1;
1987 * Search the environment of a builtin command.
1990 bltinlookup(const char *name)
1994 for (sp = cmdenviron; sp; sp = sp->next) {
1995 if (varequal(sp->text, name))
1996 return strchrnul(sp->text, '=') + 1;
1998 return lookupvar(name);
2002 * Same as setvar except that the variable and value are passed in
2003 * the first argument as name=value. Since the first argument will
2004 * be actually stored in the table, it should not be a string that
2006 * Called with interrupts off.
2009 setvareq(char *s, int flags)
2011 struct var *vp, **vpp;
2014 flags |= (VEXPORT & (((unsigned) (1 - aflag)) - 1));
2015 vp = *findvar(vpp, s);
2017 if ((vp->flags & (VREADONLY|VDYNAMIC)) == VREADONLY) {
2020 if (flags & VNOSAVE)
2023 ash_msg_and_raise_error("%.*s: is read only", strchrnul(n, '=') - n, n);
2029 if (vp->func && (flags & VNOFUNC) == 0)
2030 (*vp->func)(strchrnul(s, '=') + 1);
2032 if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
2033 free((char*)vp->text);
2035 flags |= vp->flags & ~(VTEXTFIXED|VSTACK|VNOSAVE|VUNSET);
2040 vp = ckzalloc(sizeof(*vp));
2042 /*vp->func = NULL; - ckzalloc did it */
2045 if (!(flags & (VTEXTFIXED|VSTACK|VNOSAVE)))
2052 * Set the value of a variable. The flags argument is ored with the
2053 * flags of the variable. If val is NULL, the variable is unset.
2056 setvar(const char *name, const char *val, int flags)
2063 q = endofname(name);
2064 p = strchrnul(q, '=');
2066 if (!namelen || p != q)
2067 ash_msg_and_raise_error("%.*s: bad variable name", namelen, name);
2072 vallen = strlen(val);
2075 nameeq = ckmalloc(namelen + vallen + 2);
2076 p = (char *)memcpy(nameeq, name, namelen) + namelen;
2079 p = (char *)memcpy(p, val, vallen) + vallen;
2082 setvareq(nameeq, flags | VNOSAVE);
2086 #if ENABLE_ASH_GETOPTS
2088 * Safe version of setvar, returns 1 on success 0 on failure.
2091 setvarsafe(const char *name, const char *val, int flags)
2094 volatile int saveint;
2095 struct jmploc *volatile savehandler = exception_handler;
2096 struct jmploc jmploc;
2099 if (setjmp(jmploc.loc))
2102 exception_handler = &jmploc;
2103 setvar(name, val, flags);
2106 exception_handler = savehandler;
2107 RESTORE_INT(saveint);
2113 * Unset the specified variable.
2116 unsetvar(const char *s)
2122 vpp = findvar(hashvar(s), s);
2126 int flags = vp->flags;
2129 if (flags & VREADONLY)
2131 #if ENABLE_ASH_RANDOM_SUPPORT
2132 vp->flags &= ~VDYNAMIC;
2136 if ((flags & VSTRFIXED) == 0) {
2138 if ((flags & (VTEXTFIXED|VSTACK)) == 0)
2139 free((char*)vp->text);
2145 vp->flags &= ~VEXPORT;
2155 * Process a linked list of variable assignments.
2158 listsetvar(struct strlist *list_set_var, int flags)
2160 struct strlist *lp = list_set_var;
2166 setvareq(lp->text, flags);
2173 * Generate a list of variables satisfying the given conditions.
2176 listvars(int on, int off, char ***end)
2187 for (vp = *vpp; vp; vp = vp->next) {
2188 if ((vp->flags & mask) == on) {
2189 if (ep == stackstrend())
2190 ep = growstackstr();
2191 *ep++ = (char *) vp->text;
2194 } while (++vpp < vartab + VTABSIZE);
2195 if (ep == stackstrend())
2196 ep = growstackstr();
2200 return grabstackstr(ep);
2204 /* ============ Path search helper
2206 * The variable path (passed by reference) should be set to the start
2207 * of the path before the first call; padvance will update
2208 * this value as it proceeds. Successive calls to padvance will return
2209 * the possible path expansions in sequence. If an option (indicated by
2210 * a percent sign) appears in the path entry then the global variable
2211 * pathopt will be set to point to it; otherwise pathopt will be set to
2214 static const char *pathopt; /* set by padvance */
2217 padvance(const char **path, const char *name)
2227 for (p = start; *p && *p != ':' && *p != '%'; p++)
2229 len = p - start + strlen(name) + 2; /* "2" is for '/' and '\0' */
2230 while (stackblocksize() < len)
2234 memcpy(q, start, p - start);
2242 while (*p && *p != ':')
2249 return stalloc(len);
2253 /* ============ Prompt */
2255 static smallint doprompt; /* if set, prompt the user */
2256 static smallint needprompt; /* true if interactive and at start of line */
2258 #if ENABLE_FEATURE_EDITING
2259 static line_input_t *line_input_state;
2260 static const char *cmdedit_prompt;
2262 putprompt(const char *s)
2264 if (ENABLE_ASH_EXPAND_PRMT) {
2265 free((char*)cmdedit_prompt);
2266 cmdedit_prompt = ckstrdup(s);
2273 putprompt(const char *s)
2279 #if ENABLE_ASH_EXPAND_PRMT
2280 /* expandstr() needs parsing machinery, so it is far away ahead... */
2281 static const char *expandstr(const char *ps);
2283 #define expandstr(s) s
2287 setprompt(int whichprompt)
2290 #if ENABLE_ASH_EXPAND_PRMT
2291 struct stackmark smark;
2296 switch (whichprompt) {
2306 #if ENABLE_ASH_EXPAND_PRMT
2307 setstackmark(&smark);
2308 stalloc(stackblocksize());
2310 putprompt(expandstr(prompt));
2311 #if ENABLE_ASH_EXPAND_PRMT
2312 popstackmark(&smark);
2317 /* ============ The cd and pwd commands */
2319 #define CD_PHYSICAL 1
2322 static int docd(const char *, int);
2331 while ((i = nextopt("LP"))) {
2333 flags ^= CD_PHYSICAL;
2342 * Update curdir (the name of the current directory) in response to a
2346 updatepwd(const char *dir)
2353 cdcomppath = ststrdup(dir);
2356 if (curdir == nullstr)
2358 new = stack_putstr(curdir, new);
2360 new = makestrspace(strlen(dir) + 2, new);
2361 lim = (char *)stackblock() + 1;
2365 if (new > lim && *lim == '/')
2370 if (dir[1] == '/' && dir[2] != '/') {
2376 p = strtok(cdcomppath, "/");
2380 if (p[1] == '.' && p[2] == '\0') {
2392 new = stack_putstr(p, new);
2400 return stackblock();
2404 * Find out what the current directory is. If we already know the current
2405 * directory, this routine returns immediately.
2410 char *dir = getcwd(NULL, 0); /* huh, using glibc extension? */
2411 return dir ? dir : nullstr;
2415 setpwd(const char *val, int setold)
2419 oldcur = dir = curdir;
2422 setvar("OLDPWD", oldcur, VEXPORT);
2425 if (physdir != nullstr) {
2426 if (physdir != oldcur)
2430 if (oldcur == val || !val) {
2436 dir = ckstrdup(val);
2437 if (oldcur != dir && oldcur != nullstr) {
2442 setvar("PWD", dir, VEXPORT);
2445 static void hashcd(void);
2448 * Actually do the chdir. We also call hashcd to let the routines in exec.c
2449 * know that the current directory has changed.
2452 docd(const char *dest, int flags)
2454 const char *dir = 0;
2457 TRACE(("docd(\"%s\", %d) called\n", dest, flags));
2460 if (!(flags & CD_PHYSICAL)) {
2461 dir = updatepwd(dest);
2476 cdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
2488 dest = bltinlookup(homestr);
2489 else if (LONE_DASH(dest)) {
2490 dest = bltinlookup("OLDPWD");
2512 path = bltinlookup("CDPATH");
2521 p = padvance(&path, dest);
2522 if (stat(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) {
2526 if (!docd(p, flags))
2531 ash_msg_and_raise_error("can't cd to %s", dest);
2534 if (flags & CD_PRINT)
2535 out1fmt(snlfmt, curdir);
2540 pwdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
2543 const char *dir = curdir;
2547 if (physdir == nullstr)
2551 out1fmt(snlfmt, dir);
2556 /* ============ ... */
2559 #define IBUFSIZ COMMON_BUFSIZE
2560 /* buffer for top level input file */
2561 #define basebuf bb_common_bufsiz1
2563 /* Syntax classes */
2564 #define CWORD 0 /* character is nothing special */
2565 #define CNL 1 /* newline character */
2566 #define CBACK 2 /* a backslash character */
2567 #define CSQUOTE 3 /* single quote */
2568 #define CDQUOTE 4 /* double quote */
2569 #define CENDQUOTE 5 /* a terminating quote */
2570 #define CBQUOTE 6 /* backwards single quote */
2571 #define CVAR 7 /* a dollar sign */
2572 #define CENDVAR 8 /* a '}' character */
2573 #define CLP 9 /* a left paren in arithmetic */
2574 #define CRP 10 /* a right paren in arithmetic */
2575 #define CENDFILE 11 /* end of file */
2576 #define CCTL 12 /* like CWORD, except it must be escaped */
2577 #define CSPCL 13 /* these terminate a word */
2578 #define CIGN 14 /* character should be ignored */
2580 #if ENABLE_ASH_ALIAS
2584 #define PEOA_OR_PEOF PEOA
2588 #define PEOA_OR_PEOF PEOF
2591 /* number syntax index */
2592 #define BASESYNTAX 0 /* not in quotes */
2593 #define DQSYNTAX 1 /* in double quotes */
2594 #define SQSYNTAX 2 /* in single quotes */
2595 #define ARISYNTAX 3 /* in arithmetic */
2596 #define PSSYNTAX 4 /* prompt */
2598 #if ENABLE_ASH_OPTIMIZE_FOR_SIZE
2599 #define USE_SIT_FUNCTION
2602 #if ENABLE_ASH_MATH_SUPPORT
2603 static const char S_I_T[][4] = {
2604 #if ENABLE_ASH_ALIAS
2605 { CSPCL, CIGN, CIGN, CIGN }, /* 0, PEOA */
2607 { CSPCL, CWORD, CWORD, CWORD }, /* 1, ' ' */
2608 { CNL, CNL, CNL, CNL }, /* 2, \n */
2609 { CWORD, CCTL, CCTL, CWORD }, /* 3, !*-/:=?[]~ */
2610 { CDQUOTE, CENDQUOTE, CWORD, CWORD }, /* 4, '"' */
2611 { CVAR, CVAR, CWORD, CVAR }, /* 5, $ */
2612 { CSQUOTE, CWORD, CENDQUOTE, CWORD }, /* 6, "'" */
2613 { CSPCL, CWORD, CWORD, CLP }, /* 7, ( */
2614 { CSPCL, CWORD, CWORD, CRP }, /* 8, ) */
2615 { CBACK, CBACK, CCTL, CBACK }, /* 9, \ */
2616 { CBQUOTE, CBQUOTE, CWORD, CBQUOTE }, /* 10, ` */
2617 { CENDVAR, CENDVAR, CWORD, CENDVAR }, /* 11, } */
2618 #ifndef USE_SIT_FUNCTION
2619 { CENDFILE, CENDFILE, CENDFILE, CENDFILE }, /* 12, PEOF */
2620 { CWORD, CWORD, CWORD, CWORD }, /* 13, 0-9A-Za-z */
2621 { CCTL, CCTL, CCTL, CCTL } /* 14, CTLESC ... */
2625 static const char S_I_T[][3] = {
2626 #if ENABLE_ASH_ALIAS
2627 { CSPCL, CIGN, CIGN }, /* 0, PEOA */
2629 { CSPCL, CWORD, CWORD }, /* 1, ' ' */
2630 { CNL, CNL, CNL }, /* 2, \n */
2631 { CWORD, CCTL, CCTL }, /* 3, !*-/:=?[]~ */
2632 { CDQUOTE, CENDQUOTE, CWORD }, /* 4, '"' */
2633 { CVAR, CVAR, CWORD }, /* 5, $ */
2634 { CSQUOTE, CWORD, CENDQUOTE }, /* 6, "'" */
2635 { CSPCL, CWORD, CWORD }, /* 7, ( */
2636 { CSPCL, CWORD, CWORD }, /* 8, ) */
2637 { CBACK, CBACK, CCTL }, /* 9, \ */
2638 { CBQUOTE, CBQUOTE, CWORD }, /* 10, ` */
2639 { CENDVAR, CENDVAR, CWORD }, /* 11, } */
2640 #ifndef USE_SIT_FUNCTION
2641 { CENDFILE, CENDFILE, CENDFILE }, /* 12, PEOF */
2642 { CWORD, CWORD, CWORD }, /* 13, 0-9A-Za-z */
2643 { CCTL, CCTL, CCTL } /* 14, CTLESC ... */
2646 #endif /* ASH_MATH_SUPPORT */
2648 #ifdef USE_SIT_FUNCTION
2651 SIT(int c, int syntax)
2653 static const char spec_symbls[] ALIGN1 = "\t\n !\"$&'()*-/:;<=>?[\\]`|}~";
2654 #if ENABLE_ASH_ALIAS
2655 static const char syntax_index_table[] ALIGN1 = {
2656 1, 2, 1, 3, 4, 5, 1, 6, /* "\t\n !\"$&'" */
2657 7, 8, 3, 3, 3, 3, 1, 1, /* "()*-/:;<" */
2658 3, 1, 3, 3, 9, 3, 10, 1, /* "=>?[\\]`|" */
2662 static const char syntax_index_table[] ALIGN1 = {
2663 0, 1, 0, 2, 3, 4, 0, 5, /* "\t\n !\"$&'" */
2664 6, 7, 2, 2, 2, 2, 0, 0, /* "()*-/:;<" */
2665 2, 0, 2, 2, 8, 2, 9, 0, /* "=>?[\\]`|" */
2672 if (c == PEOF) /* 2^8+2 */
2674 #if ENABLE_ASH_ALIAS
2675 if (c == PEOA) /* 2^8+1 */
2680 if ((unsigned char)c >= (unsigned char)(CTLESC)
2681 && (unsigned char)c <= (unsigned char)(CTLQUOTEMARK)
2685 s = strchrnul(spec_symbls, c);
2688 indx = syntax_index_table[s - spec_symbls];
2689 return S_I_T[indx][syntax];
2692 #else /* !USE_SIT_FUNCTION */
2694 #if ENABLE_ASH_ALIAS
2695 #define CSPCL_CIGN_CIGN_CIGN 0
2696 #define CSPCL_CWORD_CWORD_CWORD 1
2697 #define CNL_CNL_CNL_CNL 2
2698 #define CWORD_CCTL_CCTL_CWORD 3
2699 #define CDQUOTE_CENDQUOTE_CWORD_CWORD 4
2700 #define CVAR_CVAR_CWORD_CVAR 5
2701 #define CSQUOTE_CWORD_CENDQUOTE_CWORD 6
2702 #define CSPCL_CWORD_CWORD_CLP 7
2703 #define CSPCL_CWORD_CWORD_CRP 8
2704 #define CBACK_CBACK_CCTL_CBACK 9
2705 #define CBQUOTE_CBQUOTE_CWORD_CBQUOTE 10
2706 #define CENDVAR_CENDVAR_CWORD_CENDVAR 11
2707 #define CENDFILE_CENDFILE_CENDFILE_CENDFILE 12
2708 #define CWORD_CWORD_CWORD_CWORD 13
2709 #define CCTL_CCTL_CCTL_CCTL 14
2711 #define CSPCL_CWORD_CWORD_CWORD 0
2712 #define CNL_CNL_CNL_CNL 1
2713 #define CWORD_CCTL_CCTL_CWORD 2
2714 #define CDQUOTE_CENDQUOTE_CWORD_CWORD 3
2715 #define CVAR_CVAR_CWORD_CVAR 4
2716 #define CSQUOTE_CWORD_CENDQUOTE_CWORD 5
2717 #define CSPCL_CWORD_CWORD_CLP 6
2718 #define CSPCL_CWORD_CWORD_CRP 7
2719 #define CBACK_CBACK_CCTL_CBACK 8
2720 #define CBQUOTE_CBQUOTE_CWORD_CBQUOTE 9
2721 #define CENDVAR_CENDVAR_CWORD_CENDVAR 10
2722 #define CENDFILE_CENDFILE_CENDFILE_CENDFILE 11
2723 #define CWORD_CWORD_CWORD_CWORD 12
2724 #define CCTL_CCTL_CCTL_CCTL 13
2727 static const char syntax_index_table[258] = {
2728 /* BASESYNTAX_DQSYNTAX_SQSYNTAX_ARISYNTAX */
2729 /* 0 PEOF */ CENDFILE_CENDFILE_CENDFILE_CENDFILE,
2730 #if ENABLE_ASH_ALIAS
2731 /* 1 PEOA */ CSPCL_CIGN_CIGN_CIGN,
2733 /* 2 -128 0x80 */ CWORD_CWORD_CWORD_CWORD,
2734 /* 3 -127 CTLESC */ CCTL_CCTL_CCTL_CCTL,
2735 /* 4 -126 CTLVAR */ CCTL_CCTL_CCTL_CCTL,
2736 /* 5 -125 CTLENDVAR */ CCTL_CCTL_CCTL_CCTL,
2737 /* 6 -124 CTLBACKQ */ CCTL_CCTL_CCTL_CCTL,
2738 /* 7 -123 CTLQUOTE */ CCTL_CCTL_CCTL_CCTL,
2739 /* 8 -122 CTLARI */ CCTL_CCTL_CCTL_CCTL,
2740 /* 9 -121 CTLENDARI */ CCTL_CCTL_CCTL_CCTL,
2741 /* 10 -120 CTLQUOTEMARK */ CCTL_CCTL_CCTL_CCTL,
2742 /* 11 -119 */ CWORD_CWORD_CWORD_CWORD,
2743 /* 12 -118 */ CWORD_CWORD_CWORD_CWORD,
2744 /* 13 -117 */ CWORD_CWORD_CWORD_CWORD,
2745 /* 14 -116 */ CWORD_CWORD_CWORD_CWORD,
2746 /* 15 -115 */ CWORD_CWORD_CWORD_CWORD,
2747 /* 16 -114 */ CWORD_CWORD_CWORD_CWORD,
2748 /* 17 -113 */ CWORD_CWORD_CWORD_CWORD,
2749 /* 18 -112 */ CWORD_CWORD_CWORD_CWORD,
2750 /* 19 -111 */ CWORD_CWORD_CWORD_CWORD,
2751 /* 20 -110 */ CWORD_CWORD_CWORD_CWORD,
2752 /* 21 -109 */ CWORD_CWORD_CWORD_CWORD,
2753 /* 22 -108 */ CWORD_CWORD_CWORD_CWORD,
2754 /* 23 -107 */ CWORD_CWORD_CWORD_CWORD,
2755 /* 24 -106 */ CWORD_CWORD_CWORD_CWORD,
2756 /* 25 -105 */ CWORD_CWORD_CWORD_CWORD,
2757 /* 26 -104 */ CWORD_CWORD_CWORD_CWORD,
2758 /* 27 -103 */ CWORD_CWORD_CWORD_CWORD,
2759 /* 28 -102 */ CWORD_CWORD_CWORD_CWORD,
2760 /* 29 -101 */ CWORD_CWORD_CWORD_CWORD,
2761 /* 30 -100 */ CWORD_CWORD_CWORD_CWORD,
2762 /* 31 -99 */ CWORD_CWORD_CWORD_CWORD,
2763 /* 32 -98 */ CWORD_CWORD_CWORD_CWORD,
2764 /* 33 -97 */ CWORD_CWORD_CWORD_CWORD,
2765 /* 34 -96 */ CWORD_CWORD_CWORD_CWORD,
2766 /* 35 -95 */ CWORD_CWORD_CWORD_CWORD,
2767 /* 36 -94 */ CWORD_CWORD_CWORD_CWORD,
2768 /* 37 -93 */ CWORD_CWORD_CWORD_CWORD,
2769 /* 38 -92 */ CWORD_CWORD_CWORD_CWORD,
2770 /* 39 -91 */ CWORD_CWORD_CWORD_CWORD,
2771 /* 40 -90 */ CWORD_CWORD_CWORD_CWORD,
2772 /* 41 -89 */ CWORD_CWORD_CWORD_CWORD,
2773 /* 42 -88 */ CWORD_CWORD_CWORD_CWORD,
2774 /* 43 -87 */ CWORD_CWORD_CWORD_CWORD,
2775 /* 44 -86 */ CWORD_CWORD_CWORD_CWORD,
2776 /* 45 -85 */ CWORD_CWORD_CWORD_CWORD,
2777 /* 46 -84 */ CWORD_CWORD_CWORD_CWORD,
2778 /* 47 -83 */ CWORD_CWORD_CWORD_CWORD,
2779 /* 48 -82 */ CWORD_CWORD_CWORD_CWORD,
2780 /* 49 -81 */ CWORD_CWORD_CWORD_CWORD,
2781 /* 50 -80 */ CWORD_CWORD_CWORD_CWORD,
2782 /* 51 -79 */ CWORD_CWORD_CWORD_CWORD,
2783 /* 52 -78 */ CWORD_CWORD_CWORD_CWORD,
2784 /* 53 -77 */ CWORD_CWORD_CWORD_CWORD,
2785 /* 54 -76 */ CWORD_CWORD_CWORD_CWORD,
2786 /* 55 -75 */ CWORD_CWORD_CWORD_CWORD,
2787 /* 56 -74 */ CWORD_CWORD_CWORD_CWORD,
2788 /* 57 -73 */ CWORD_CWORD_CWORD_CWORD,
2789 /* 58 -72 */ CWORD_CWORD_CWORD_CWORD,
2790 /* 59 -71 */ CWORD_CWORD_CWORD_CWORD,
2791 /* 60 -70 */ CWORD_CWORD_CWORD_CWORD,
2792 /* 61 -69 */ CWORD_CWORD_CWORD_CWORD,
2793 /* 62 -68 */ CWORD_CWORD_CWORD_CWORD,
2794 /* 63 -67 */ CWORD_CWORD_CWORD_CWORD,
2795 /* 64 -66 */ CWORD_CWORD_CWORD_CWORD,
2796 /* 65 -65 */ CWORD_CWORD_CWORD_CWORD,
2797 /* 66 -64 */ CWORD_CWORD_CWORD_CWORD,
2798 /* 67 -63 */ CWORD_CWORD_CWORD_CWORD,
2799 /* 68 -62 */ CWORD_CWORD_CWORD_CWORD,
2800 /* 69 -61 */ CWORD_CWORD_CWORD_CWORD,
2801 /* 70 -60 */ CWORD_CWORD_CWORD_CWORD,
2802 /* 71 -59 */ CWORD_CWORD_CWORD_CWORD,
2803 /* 72 -58 */ CWORD_CWORD_CWORD_CWORD,
2804 /* 73 -57 */ CWORD_CWORD_CWORD_CWORD,
2805 /* 74 -56 */ CWORD_CWORD_CWORD_CWORD,
2806 /* 75 -55 */ CWORD_CWORD_CWORD_CWORD,
2807 /* 76 -54 */ CWORD_CWORD_CWORD_CWORD,
2808 /* 77 -53 */ CWORD_CWORD_CWORD_CWORD,
2809 /* 78 -52 */ CWORD_CWORD_CWORD_CWORD,
2810 /* 79 -51 */ CWORD_CWORD_CWORD_CWORD,
2811 /* 80 -50 */ CWORD_CWORD_CWORD_CWORD,
2812 /* 81 -49 */ CWORD_CWORD_CWORD_CWORD,
2813 /* 82 -48 */ CWORD_CWORD_CWORD_CWORD,
2814 /* 83 -47 */ CWORD_CWORD_CWORD_CWORD,
2815 /* 84 -46 */ CWORD_CWORD_CWORD_CWORD,
2816 /* 85 -45 */ CWORD_CWORD_CWORD_CWORD,
2817 /* 86 -44 */ CWORD_CWORD_CWORD_CWORD,
2818 /* 87 -43 */ CWORD_CWORD_CWORD_CWORD,
2819 /* 88 -42 */ CWORD_CWORD_CWORD_CWORD,
2820 /* 89 -41 */ CWORD_CWORD_CWORD_CWORD,
2821 /* 90 -40 */ CWORD_CWORD_CWORD_CWORD,
2822 /* 91 -39 */ CWORD_CWORD_CWORD_CWORD,
2823 /* 92 -38 */ CWORD_CWORD_CWORD_CWORD,
2824 /* 93 -37 */ CWORD_CWORD_CWORD_CWORD,
2825 /* 94 -36 */ CWORD_CWORD_CWORD_CWORD,
2826 /* 95 -35 */ CWORD_CWORD_CWORD_CWORD,
2827 /* 96 -34 */ CWORD_CWORD_CWORD_CWORD,
2828 /* 97 -33 */ CWORD_CWORD_CWORD_CWORD,
2829 /* 98 -32 */ CWORD_CWORD_CWORD_CWORD,
2830 /* 99 -31 */ CWORD_CWORD_CWORD_CWORD,
2831 /* 100 -30 */ CWORD_CWORD_CWORD_CWORD,
2832 /* 101 -29 */ CWORD_CWORD_CWORD_CWORD,
2833 /* 102 -28 */ CWORD_CWORD_CWORD_CWORD,
2834 /* 103 -27 */ CWORD_CWORD_CWORD_CWORD,
2835 /* 104 -26 */ CWORD_CWORD_CWORD_CWORD,
2836 /* 105 -25 */ CWORD_CWORD_CWORD_CWORD,
2837 /* 106 -24 */ CWORD_CWORD_CWORD_CWORD,
2838 /* 107 -23 */ CWORD_CWORD_CWORD_CWORD,
2839 /* 108 -22 */ CWORD_CWORD_CWORD_CWORD,
2840 /* 109 -21 */ CWORD_CWORD_CWORD_CWORD,
2841 /* 110 -20 */ CWORD_CWORD_CWORD_CWORD,
2842 /* 111 -19 */ CWORD_CWORD_CWORD_CWORD,
2843 /* 112 -18 */ CWORD_CWORD_CWORD_CWORD,
2844 /* 113 -17 */ CWORD_CWORD_CWORD_CWORD,
2845 /* 114 -16 */ CWORD_CWORD_CWORD_CWORD,
2846 /* 115 -15 */ CWORD_CWORD_CWORD_CWORD,
2847 /* 116 -14 */ CWORD_CWORD_CWORD_CWORD,
2848 /* 117 -13 */ CWORD_CWORD_CWORD_CWORD,
2849 /* 118 -12 */ CWORD_CWORD_CWORD_CWORD,
2850 /* 119 -11 */ CWORD_CWORD_CWORD_CWORD,
2851 /* 120 -10 */ CWORD_CWORD_CWORD_CWORD,
2852 /* 121 -9 */ CWORD_CWORD_CWORD_CWORD,
2853 /* 122 -8 */ CWORD_CWORD_CWORD_CWORD,
2854 /* 123 -7 */ CWORD_CWORD_CWORD_CWORD,
2855 /* 124 -6 */ CWORD_CWORD_CWORD_CWORD,
2856 /* 125 -5 */ CWORD_CWORD_CWORD_CWORD,
2857 /* 126 -4 */ CWORD_CWORD_CWORD_CWORD,
2858 /* 127 -3 */ CWORD_CWORD_CWORD_CWORD,
2859 /* 128 -2 */ CWORD_CWORD_CWORD_CWORD,
2860 /* 129 -1 */ CWORD_CWORD_CWORD_CWORD,
2861 /* 130 0 */ CWORD_CWORD_CWORD_CWORD,
2862 /* 131 1 */ CWORD_CWORD_CWORD_CWORD,
2863 /* 132 2 */ CWORD_CWORD_CWORD_CWORD,
2864 /* 133 3 */ CWORD_CWORD_CWORD_CWORD,
2865 /* 134 4 */ CWORD_CWORD_CWORD_CWORD,
2866 /* 135 5 */ CWORD_CWORD_CWORD_CWORD,
2867 /* 136 6 */ CWORD_CWORD_CWORD_CWORD,
2868 /* 137 7 */ CWORD_CWORD_CWORD_CWORD,
2869 /* 138 8 */ CWORD_CWORD_CWORD_CWORD,
2870 /* 139 9 "\t" */ CSPCL_CWORD_CWORD_CWORD,
2871 /* 140 10 "\n" */ CNL_CNL_CNL_CNL,
2872 /* 141 11 */ CWORD_CWORD_CWORD_CWORD,
2873 /* 142 12 */ CWORD_CWORD_CWORD_CWORD,
2874 /* 143 13 */ CWORD_CWORD_CWORD_CWORD,
2875 /* 144 14 */ CWORD_CWORD_CWORD_CWORD,
2876 /* 145 15 */ CWORD_CWORD_CWORD_CWORD,
2877 /* 146 16 */ CWORD_CWORD_CWORD_CWORD,
2878 /* 147 17 */ CWORD_CWORD_CWORD_CWORD,
2879 /* 148 18 */ CWORD_CWORD_CWORD_CWORD,
2880 /* 149 19 */ CWORD_CWORD_CWORD_CWORD,
2881 /* 150 20 */ CWORD_CWORD_CWORD_CWORD,
2882 /* 151 21 */ CWORD_CWORD_CWORD_CWORD,
2883 /* 152 22 */ CWORD_CWORD_CWORD_CWORD,
2884 /* 153 23 */ CWORD_CWORD_CWORD_CWORD,
2885 /* 154 24 */ CWORD_CWORD_CWORD_CWORD,
2886 /* 155 25 */ CWORD_CWORD_CWORD_CWORD,
2887 /* 156 26 */ CWORD_CWORD_CWORD_CWORD,
2888 /* 157 27 */ CWORD_CWORD_CWORD_CWORD,
2889 /* 158 28 */ CWORD_CWORD_CWORD_CWORD,
2890 /* 159 29 */ CWORD_CWORD_CWORD_CWORD,
2891 /* 160 30 */ CWORD_CWORD_CWORD_CWORD,
2892 /* 161 31 */ CWORD_CWORD_CWORD_CWORD,
2893 /* 162 32 " " */ CSPCL_CWORD_CWORD_CWORD,
2894 /* 163 33 "!" */ CWORD_CCTL_CCTL_CWORD,
2895 /* 164 34 """ */ CDQUOTE_CENDQUOTE_CWORD_CWORD,
2896 /* 165 35 "#" */ CWORD_CWORD_CWORD_CWORD,
2897 /* 166 36 "$" */ CVAR_CVAR_CWORD_CVAR,
2898 /* 167 37 "%" */ CWORD_CWORD_CWORD_CWORD,
2899 /* 168 38 "&" */ CSPCL_CWORD_CWORD_CWORD,
2900 /* 169 39 "'" */ CSQUOTE_CWORD_CENDQUOTE_CWORD,
2901 /* 170 40 "(" */ CSPCL_CWORD_CWORD_CLP,
2902 /* 171 41 ")" */ CSPCL_CWORD_CWORD_CRP,
2903 /* 172 42 "*" */ CWORD_CCTL_CCTL_CWORD,
2904 /* 173 43 "+" */ CWORD_CWORD_CWORD_CWORD,
2905 /* 174 44 "," */ CWORD_CWORD_CWORD_CWORD,
2906 /* 175 45 "-" */ CWORD_CCTL_CCTL_CWORD,
2907 /* 176 46 "." */ CWORD_CWORD_CWORD_CWORD,
2908 /* 177 47 "/" */ CWORD_CCTL_CCTL_CWORD,
2909 /* 178 48 "0" */ CWORD_CWORD_CWORD_CWORD,
2910 /* 179 49 "1" */ CWORD_CWORD_CWORD_CWORD,
2911 /* 180 50 "2" */ CWORD_CWORD_CWORD_CWORD,
2912 /* 181 51 "3" */ CWORD_CWORD_CWORD_CWORD,
2913 /* 182 52 "4" */ CWORD_CWORD_CWORD_CWORD,
2914 /* 183 53 "5" */ CWORD_CWORD_CWORD_CWORD,
2915 /* 184 54 "6" */ CWORD_CWORD_CWORD_CWORD,
2916 /* 185 55 "7" */ CWORD_CWORD_CWORD_CWORD,
2917 /* 186 56 "8" */ CWORD_CWORD_CWORD_CWORD,
2918 /* 187 57 "9" */ CWORD_CWORD_CWORD_CWORD,
2919 /* 188 58 ":" */ CWORD_CCTL_CCTL_CWORD,
2920 /* 189 59 ";" */ CSPCL_CWORD_CWORD_CWORD,
2921 /* 190 60 "<" */ CSPCL_CWORD_CWORD_CWORD,
2922 /* 191 61 "=" */ CWORD_CCTL_CCTL_CWORD,
2923 /* 192 62 ">" */ CSPCL_CWORD_CWORD_CWORD,
2924 /* 193 63 "?" */ CWORD_CCTL_CCTL_CWORD,
2925 /* 194 64 "@" */ CWORD_CWORD_CWORD_CWORD,
2926 /* 195 65 "A" */ CWORD_CWORD_CWORD_CWORD,
2927 /* 196 66 "B" */ CWORD_CWORD_CWORD_CWORD,
2928 /* 197 67 "C" */ CWORD_CWORD_CWORD_CWORD,
2929 /* 198 68 "D" */ CWORD_CWORD_CWORD_CWORD,
2930 /* 199 69 "E" */ CWORD_CWORD_CWORD_CWORD,
2931 /* 200 70 "F" */ CWORD_CWORD_CWORD_CWORD,
2932 /* 201 71 "G" */ CWORD_CWORD_CWORD_CWORD,
2933 /* 202 72 "H" */ CWORD_CWORD_CWORD_CWORD,
2934 /* 203 73 "I" */ CWORD_CWORD_CWORD_CWORD,
2935 /* 204 74 "J" */ CWORD_CWORD_CWORD_CWORD,
2936 /* 205 75 "K" */ CWORD_CWORD_CWORD_CWORD,
2937 /* 206 76 "L" */ CWORD_CWORD_CWORD_CWORD,
2938 /* 207 77 "M" */ CWORD_CWORD_CWORD_CWORD,
2939 /* 208 78 "N" */ CWORD_CWORD_CWORD_CWORD,
2940 /* 209 79 "O" */ CWORD_CWORD_CWORD_CWORD,
2941 /* 210 80 "P" */ CWORD_CWORD_CWORD_CWORD,
2942 /* 211 81 "Q" */ CWORD_CWORD_CWORD_CWORD,
2943 /* 212 82 "R" */ CWORD_CWORD_CWORD_CWORD,
2944 /* 213 83 "S" */ CWORD_CWORD_CWORD_CWORD,
2945 /* 214 84 "T" */ CWORD_CWORD_CWORD_CWORD,
2946 /* 215 85 "U" */ CWORD_CWORD_CWORD_CWORD,
2947 /* 216 86 "V" */ CWORD_CWORD_CWORD_CWORD,
2948 /* 217 87 "W" */ CWORD_CWORD_CWORD_CWORD,
2949 /* 218 88 "X" */ CWORD_CWORD_CWORD_CWORD,
2950 /* 219 89 "Y" */ CWORD_CWORD_CWORD_CWORD,
2951 /* 220 90 "Z" */ CWORD_CWORD_CWORD_CWORD,
2952 /* 221 91 "[" */ CWORD_CCTL_CCTL_CWORD,
2953 /* 222 92 "\" */ CBACK_CBACK_CCTL_CBACK,
2954 /* 223 93 "]" */ CWORD_CCTL_CCTL_CWORD,
2955 /* 224 94 "^" */ CWORD_CWORD_CWORD_CWORD,
2956 /* 225 95 "_" */ CWORD_CWORD_CWORD_CWORD,
2957 /* 226 96 "`" */ CBQUOTE_CBQUOTE_CWORD_CBQUOTE,
2958 /* 227 97 "a" */ CWORD_CWORD_CWORD_CWORD,
2959 /* 228 98 "b" */ CWORD_CWORD_CWORD_CWORD,
2960 /* 229 99 "c" */ CWORD_CWORD_CWORD_CWORD,
2961 /* 230 100 "d" */ CWORD_CWORD_CWORD_CWORD,
2962 /* 231 101 "e" */ CWORD_CWORD_CWORD_CWORD,
2963 /* 232 102 "f" */ CWORD_CWORD_CWORD_CWORD,
2964 /* 233 103 "g" */ CWORD_CWORD_CWORD_CWORD,
2965 /* 234 104 "h" */ CWORD_CWORD_CWORD_CWORD,
2966 /* 235 105 "i" */ CWORD_CWORD_CWORD_CWORD,
2967 /* 236 106 "j" */ CWORD_CWORD_CWORD_CWORD,
2968 /* 237 107 "k" */ CWORD_CWORD_CWORD_CWORD,
2969 /* 238 108 "l" */ CWORD_CWORD_CWORD_CWORD,
2970 /* 239 109 "m" */ CWORD_CWORD_CWORD_CWORD,
2971 /* 240 110 "n" */ CWORD_CWORD_CWORD_CWORD,
2972 /* 241 111 "o" */ CWORD_CWORD_CWORD_CWORD,
2973 /* 242 112 "p" */ CWORD_CWORD_CWORD_CWORD,
2974 /* 243 113 "q" */ CWORD_CWORD_CWORD_CWORD,
2975 /* 244 114 "r" */ CWORD_CWORD_CWORD_CWORD,
2976 /* 245 115 "s" */ CWORD_CWORD_CWORD_CWORD,
2977 /* 246 116 "t" */ CWORD_CWORD_CWORD_CWORD,
2978 /* 247 117 "u" */ CWORD_CWORD_CWORD_CWORD,
2979 /* 248 118 "v" */ CWORD_CWORD_CWORD_CWORD,
2980 /* 249 119 "w" */ CWORD_CWORD_CWORD_CWORD,
2981 /* 250 120 "x" */ CWORD_CWORD_CWORD_CWORD,
2982 /* 251 121 "y" */ CWORD_CWORD_CWORD_CWORD,
2983 /* 252 122 "z" */ CWORD_CWORD_CWORD_CWORD,
2984 /* 253 123 "{" */ CWORD_CWORD_CWORD_CWORD,
2985 /* 254 124 "|" */ CSPCL_CWORD_CWORD_CWORD,
2986 /* 255 125 "}" */ CENDVAR_CENDVAR_CWORD_CENDVAR,
2987 /* 256 126 "~" */ CWORD_CCTL_CCTL_CWORD,
2988 /* 257 127 */ CWORD_CWORD_CWORD_CWORD,
2991 #define SIT(c, syntax) (S_I_T[(int)syntax_index_table[((int)c)+SYNBASE]][syntax])
2993 #endif /* USE_SIT_FUNCTION */
2996 /* ============ Alias handling */
2998 #if ENABLE_ASH_ALIAS
3000 #define ALIASINUSE 1
3011 static struct alias **atab; // [ATABSIZE];
3012 #define INIT_G_alias() do { \
3013 atab = xzalloc(ATABSIZE * sizeof(atab[0])); \
3017 static struct alias **
3018 __lookupalias(const char *name) {
3019 unsigned int hashval;
3026 ch = (unsigned char)*p;
3030 ch = (unsigned char)*++p;
3032 app = &atab[hashval % ATABSIZE];
3034 for (; *app; app = &(*app)->next) {
3035 if (strcmp(name, (*app)->name) == 0) {
3043 static struct alias *
3044 lookupalias(const char *name, int check)
3046 struct alias *ap = *__lookupalias(name);
3048 if (check && ap && (ap->flag & ALIASINUSE))
3053 static struct alias *
3054 freealias(struct alias *ap)
3058 if (ap->flag & ALIASINUSE) {
3059 ap->flag |= ALIASDEAD;
3071 setalias(const char *name, const char *val)
3073 struct alias *ap, **app;
3075 app = __lookupalias(name);
3079 if (!(ap->flag & ALIASINUSE)) {
3082 ap->val = ckstrdup(val);
3083 ap->flag &= ~ALIASDEAD;
3086 ap = ckzalloc(sizeof(struct alias));
3087 ap->name = ckstrdup(name);
3088 ap->val = ckstrdup(val);
3089 /*ap->flag = 0; - ckzalloc did it */
3090 /*ap->next = NULL;*/
3097 unalias(const char *name)
3101 app = __lookupalias(name);
3105 *app = freealias(*app);
3116 struct alias *ap, **app;
3120 for (i = 0; i < ATABSIZE; i++) {
3122 for (ap = *app; ap; ap = *app) {
3123 *app = freealias(*app);
3133 printalias(const struct alias *ap)
3135 out1fmt("%s=%s\n", ap->name, single_quote(ap->val));
3139 * TODO - sort output
3142 aliascmd(int argc UNUSED_PARAM, char **argv)
3151 for (i = 0; i < ATABSIZE; i++) {
3152 for (ap = atab[i]; ap; ap = ap->next) {
3158 while ((n = *++argv) != NULL) {
3159 v = strchr(n+1, '=');
3160 if (v == NULL) { /* n+1: funny ksh stuff */
3161 ap = *__lookupalias(n);
3163 fprintf(stderr, "%s: %s not found\n", "alias", n);
3177 unaliascmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
3181 while ((i = nextopt("a")) != '\0') {
3187 for (i = 0; *argptr; argptr++) {
3188 if (unalias(*argptr)) {
3189 fprintf(stderr, "%s: %s not found\n", "unalias", *argptr);
3197 #endif /* ASH_ALIAS */
3200 /* ============ jobs.c */
3202 /* Mode argument to forkshell. Don't change FORK_FG or FORK_BG. */
3205 #define FORK_NOJOB 2
3207 /* mode flags for showjob(s) */
3208 #define SHOW_PGID 0x01 /* only show pgid - for jobs -p */
3209 #define SHOW_PID 0x04 /* include process pid */
3210 #define SHOW_CHANGED 0x08 /* only jobs whose state has changed */
3213 * A job structure contains information about a job. A job is either a
3214 * single process or a set of processes contained in a pipeline. In the
3215 * latter case, pidlist will be non-NULL, and will point to a -1 terminated
3220 pid_t pid; /* process id */
3221 int status; /* last process status from wait() */
3222 char *cmd; /* text of command being run */
3226 struct procstat ps0; /* status of process */
3227 struct procstat *ps; /* status or processes when more than one */
3229 int stopstatus; /* status of a stopped job */
3232 nprocs: 16, /* number of processes */
3234 #define JOBRUNNING 0 /* at least one proc running */
3235 #define JOBSTOPPED 1 /* all procs are stopped */
3236 #define JOBDONE 2 /* all procs are completed */
3238 sigint: 1, /* job was killed by SIGINT */
3239 jobctl: 1, /* job running under job control */
3241 waited: 1, /* true if this entry has been waited for */
3242 used: 1, /* true if this entry is in used */
3243 changed: 1; /* true if status has changed */
3244 struct job *prev_job; /* previous job */
3247 static struct job *makejob(/*union node *,*/ int);
3249 #define forkshell(job, node, mode) forkshell(job, mode)
3251 static int forkshell(struct job *, union node *, int);
3252 static int waitforjob(struct job *);
3255 enum { doing_jobctl = 0 };
3256 #define setjobctl(on) do {} while (0)
3258 static smallint doing_jobctl; //references:8
3259 static void setjobctl(int);
3266 ignoresig(int signo)
3268 /* Avoid unnecessary system calls. Is it already SIG_IGNed? */
3269 if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) {
3270 /* No, need to do it */
3271 signal(signo, SIG_IGN);
3273 sigmode[signo - 1] = S_HARD_IGN;
3277 * Signal handler. Only one usage site - in setsignal()
3282 gotsig[signo - 1] = 1;
3284 if (/* exsig || */ (signo == SIGINT && !trap[SIGINT])) {
3287 raise_interrupt(); /* does not return */
3296 * Set the signal handler for the specified signal. The routine figures
3297 * out what it should be set to.
3300 setsignal(int signo)
3303 char cur_act, new_act;
3304 struct sigaction act;
3308 if (t != NULL) { /* trap for this sig is set */
3310 if (t[0] == '\0') /* trap is "": ignore this sig */
3314 if (rootshell && new_act == S_DFL) {
3317 if (iflag || minusc || sflag == 0)
3326 * "In all cases, bash ignores SIGQUIT. Non-builtin
3327 * commands run by bash have signal handlers
3328 * set to the values inherited by the shell
3329 * from its parent". */
3345 //TODO: if !rootshell, we reset SIGQUIT to DFL,
3346 //whereas we have to restore it to what shell got on entry
3347 //from the parent. See comment above
3349 t = &sigmode[signo - 1];
3352 /* current setting is not yet known */
3353 if (sigaction(signo, NULL, &act)) {
3354 /* pretend it worked; maybe we should give a warning,
3355 * but other shells don't. We don't alter sigmode,
3356 * so we retry every time.
3357 * btw, in Linux it never fails. --vda */
3360 if (act.sa_handler == SIG_IGN) {
3361 cur_act = S_HARD_IGN;
3363 && (signo == SIGTSTP || signo == SIGTTIN || signo == SIGTTOU)
3365 cur_act = S_IGN; /* don't hard ignore these */
3369 if (cur_act == S_HARD_IGN || cur_act == new_act)
3372 act.sa_handler = SIG_DFL;
3375 act.sa_handler = onsig;
3376 act.sa_flags = 0; /* matters only if !DFL and !IGN */
3377 sigfillset(&act.sa_mask); /* ditto */
3380 act.sa_handler = SIG_IGN;
3383 sigaction_set(signo, &act);
3388 /* mode flags for set_curjob */
3389 #define CUR_DELETE 2
3390 #define CUR_RUNNING 1
3391 #define CUR_STOPPED 0
3393 /* mode flags for dowait */
3394 #define DOWAIT_NONBLOCK WNOHANG
3395 #define DOWAIT_BLOCK 0
3398 /* pgrp of shell on invocation */
3399 static int initialpgrp; //references:2
3400 static int ttyfd = -1; //5
3403 static struct job *jobtab; //5
3405 static unsigned njobs; //4
3407 static struct job *curjob; //lots
3408 /* number of presumed living untracked jobs */
3409 static int jobless; //4
3412 set_curjob(struct job *jp, unsigned mode)
3415 struct job **jpp, **curp;
3417 /* first remove from list */
3418 jpp = curp = &curjob;
3423 jpp = &jp1->prev_job;
3425 *jpp = jp1->prev_job;
3427 /* Then re-insert in correct position */
3435 /* job being deleted */
3438 /* newly created job or backgrounded job,
3439 put after all stopped jobs. */
3443 if (!jp1 || jp1->state != JOBSTOPPED)
3446 jpp = &jp1->prev_job;
3452 /* newly stopped job - becomes curjob */
3453 jp->prev_job = *jpp;
3461 jobno(const struct job *jp)
3463 return jp - jobtab + 1;
3468 * Convert a job name to a job structure.
3471 #define getjob(name, getctl) getjob(name)
3474 getjob(const char *name, int getctl)
3478 const char *err_msg = "No such job: %s";
3482 char *(*match)(const char *, const char *);
3497 if (c == '+' || c == '%') {
3499 err_msg = "No current job";
3505 err_msg = "No previous job";
3514 // TODO: number() instead? It does error checking...
3517 jp = jobtab + num - 1;
3534 if (match(jp->ps[0].cmd, p)) {
3538 err_msg = "%s: ambiguous";
3545 err_msg = "job %s not created under job control";
3546 if (getctl && jp->jobctl == 0)
3551 ash_msg_and_raise_error(err_msg, name);
3555 * Mark a job structure as unused.
3558 freejob(struct job *jp)
3560 struct procstat *ps;
3564 for (i = jp->nprocs, ps = jp->ps; --i >= 0; ps++) {
3565 if (ps->cmd != nullstr)
3568 if (jp->ps != &jp->ps0)
3571 set_curjob(jp, CUR_DELETE);
3577 xtcsetpgrp(int fd, pid_t pgrp)
3579 if (tcsetpgrp(fd, pgrp))
3580 ash_msg_and_raise_error("can't set tty process group (%m)");
3584 * Turn job control on and off.
3586 * Note: This code assumes that the third arg to ioctl is a character
3587 * pointer, which is true on Berkeley systems but not System V. Since
3588 * System V doesn't have job control yet, this isn't a problem now.
3590 * Called with interrupts off.
3598 if (on == doing_jobctl || rootshell == 0)
3602 ofd = fd = open(_PATH_TTY, O_RDWR);
3604 /* BTW, bash will try to open(ttyname(0)) if open("/dev/tty") fails.
3605 * That sometimes helps to acquire controlling tty.
3606 * Obviously, a workaround for bugs when someone
3607 * failed to provide a controlling tty to bash! :) */
3613 fd = fcntl(fd, F_DUPFD, 10);
3618 /* fd is a tty at this point */
3619 close_on_exec_on(fd);
3620 do { /* while we are in the background */
3621 pgrp = tcgetpgrp(fd);
3624 ash_msg("can't access tty; job control turned off");
3628 if (pgrp == getpgrp())
3639 xtcsetpgrp(fd, pgrp);
3641 /* turning job control off */
3644 /* was xtcsetpgrp, but this can make exiting ash
3645 * loop forever if pty is already deleted */
3646 tcsetpgrp(fd, pgrp);
3661 killcmd(int argc, char **argv)
3664 if (argv[1] && strcmp(argv[1], "-l") != 0) {
3666 if (argv[i][0] == '%') {
3667 struct job *jp = getjob(argv[i], 0);
3668 unsigned pid = jp->ps[0].pid;
3669 /* Enough space for ' -NNN<nul>' */
3670 argv[i] = alloca(sizeof(int)*3 + 3);
3671 /* kill_main has matching code to expect
3672 * leading space. Needed to not confuse
3673 * negative pids with "kill -SIGNAL_NO" syntax */
3674 sprintf(argv[i], " -%u", pid);
3676 } while (argv[++i]);
3678 return kill_main(argc, argv);
3682 showpipe(struct job *jp, FILE *out)
3684 struct procstat *sp;
3685 struct procstat *spend;
3687 spend = jp->ps + jp->nprocs;
3688 for (sp = jp->ps + 1; sp < spend; sp++)
3689 fprintf(out, " | %s", sp->cmd);
3690 outcslow('\n', out);
3691 flush_stdout_stderr();
3696 restartjob(struct job *jp, int mode)
3698 struct procstat *ps;
3704 if (jp->state == JOBDONE)
3706 jp->state = JOBRUNNING;
3708 if (mode == FORK_FG)
3709 xtcsetpgrp(ttyfd, pgid);
3710 killpg(pgid, SIGCONT);
3714 if (WIFSTOPPED(ps->status)) {
3720 status = (mode == FORK_FG) ? waitforjob(jp) : 0;
3726 fg_bgcmd(int argc UNUSED_PARAM, char **argv)
3733 mode = (**argv == 'f') ? FORK_FG : FORK_BG;
3738 jp = getjob(*argv, 1);
3739 if (mode == FORK_BG) {
3740 set_curjob(jp, CUR_RUNNING);
3741 fprintf(out, "[%d] ", jobno(jp));
3743 outstr(jp->ps->cmd, out);
3745 retval = restartjob(jp, mode);
3746 } while (*argv && *++argv);
3752 sprint_status(char *s, int status, int sigonly)
3758 if (!WIFEXITED(status)) {
3760 if (WIFSTOPPED(status))
3761 st = WSTOPSIG(status);
3764 st = WTERMSIG(status);
3766 if (st == SIGINT || st == SIGPIPE)
3769 if (WIFSTOPPED(status))
3774 col = fmtstr(s, 32, strsignal(st));
3775 if (WCOREDUMP(status)) {
3776 col += fmtstr(s + col, 16, " (core dumped)");
3778 } else if (!sigonly) {
3779 st = WEXITSTATUS(status);
3781 col = fmtstr(s, 16, "Done(%d)", st);
3783 col = fmtstr(s, 16, "Done");
3790 dowait(int wait_flags, struct job *job)
3795 struct job *thisjob;
3798 TRACE(("dowait(0x%x) called\n", wait_flags));
3800 /* Do a wait system call. If job control is compiled in, we accept
3801 * stopped processes. wait_flags may have WNOHANG, preventing blocking.
3802 * NB: _not_ safe_waitpid, we need to detect EINTR */
3803 pid = waitpid(-1, &status,
3804 (doing_jobctl ? (wait_flags | WUNTRACED) : wait_flags));
3805 TRACE(("wait returns pid=%d, status=0x%x\n", pid, status));
3811 for (jp = curjob; jp; jp = jp->prev_job) {
3812 struct procstat *sp;
3813 struct procstat *spend;
3814 if (jp->state == JOBDONE)
3817 spend = jp->ps + jp->nprocs;
3820 if (sp->pid == pid) {
3821 TRACE(("Job %d: changing status of proc %d "
3822 "from 0x%x to 0x%x\n",
3823 jobno(jp), pid, sp->status, status));
3824 sp->status = status;
3827 if (sp->status == -1)
3830 if (state == JOBRUNNING)
3832 if (WIFSTOPPED(sp->status)) {
3833 jp->stopstatus = sp->status;
3837 } while (++sp < spend);
3842 if (!WIFSTOPPED(status))
3848 if (state != JOBRUNNING) {
3849 thisjob->changed = 1;
3851 if (thisjob->state != state) {
3852 TRACE(("Job %d: changing state from %d to %d\n",
3853 jobno(thisjob), thisjob->state, state));
3854 thisjob->state = state;
3856 if (state == JOBSTOPPED) {
3857 set_curjob(thisjob, CUR_STOPPED);
3866 if (thisjob && thisjob == job) {
3870 len = sprint_status(s, status, 1);
3881 blocking_wait_with_raise_on_sig(struct job *job)
3883 pid_t pid = dowait(DOWAIT_BLOCK, job);
3884 if (pid <= 0 && pendingsig)
3885 raise_exception(EXSIG);
3891 showjob(FILE *out, struct job *jp, int mode)
3893 struct procstat *ps;
3894 struct procstat *psend;
3901 if (mode & SHOW_PGID) {
3902 /* just output process (group) id of pipeline */
3903 fprintf(out, "%d\n", ps->pid);
3907 col = fmtstr(s, 16, "[%d] ", jobno(jp));
3912 else if (curjob && jp == curjob->prev_job)
3915 if (mode & SHOW_PID)
3916 col += fmtstr(s + col, 16, "%d ", ps->pid);
3918 psend = ps + jp->nprocs;
3920 if (jp->state == JOBRUNNING) {
3921 strcpy(s + col, "Running");
3922 col += sizeof("Running") - 1;
3924 int status = psend[-1].status;
3925 if (jp->state == JOBSTOPPED)
3926 status = jp->stopstatus;
3927 col += sprint_status(s + col, status, 0);
3933 /* for each process */
3934 col = fmtstr(s, 48, " |\n%*c%d ", indent_col, ' ', ps->pid) - 3;
3936 fprintf(out, "%s%*c%s",
3937 s, 33 - col >= 0 ? 33 - col : 0, ' ', ps->cmd
3939 if (!(mode & SHOW_PID)) {
3943 if (++ps == psend) {
3944 outcslow('\n', out);
3951 if (jp->state == JOBDONE) {
3952 TRACE(("showjob: freeing job %d\n", jobno(jp)));
3958 * Print a list of jobs. If "change" is nonzero, only print jobs whose
3959 * statuses have changed since the last call to showjobs.
3962 showjobs(FILE *out, int mode)
3966 TRACE(("showjobs(%x) called\n", mode));
3968 /* Handle all finished jobs */
3969 while (dowait(DOWAIT_NONBLOCK, NULL) > 0)
3972 for (jp = curjob; jp; jp = jp->prev_job) {
3973 if (!(mode & SHOW_CHANGED) || jp->changed) {
3974 showjob(out, jp, mode);
3980 jobscmd(int argc UNUSED_PARAM, char **argv)
3985 while ((m = nextopt("lp"))) {
3995 showjob(stdout, getjob(*argv,0), mode);
3998 showjobs(stdout, mode);
4005 getstatus(struct job *job)
4010 status = job->ps[job->nprocs - 1].status;
4011 retval = WEXITSTATUS(status);
4012 if (!WIFEXITED(status)) {
4014 retval = WSTOPSIG(status);
4015 if (!WIFSTOPPED(status))
4018 /* XXX: limits number of signals */
4019 retval = WTERMSIG(status);
4021 if (retval == SIGINT)
4027 TRACE(("getstatus: job %d, nproc %d, status %x, retval %x\n",
4028 jobno(job), job->nprocs, status, retval));
4033 waitcmd(int argc UNUSED_PARAM, char **argv)
4042 raise_exception(EXSIG);
4049 /* wait for all jobs */
4053 if (!jp) /* no running procs */
4055 if (jp->state == JOBRUNNING)
4061 * "When bash is waiting for an asynchronous command via
4062 * the wait builtin, the reception of a signal for which a trap
4063 * has been set will cause the wait builtin to return immediately
4064 * with an exit status greater than 128, immediately after which
4065 * the trap is executed."
4066 * Do we do it that way? */
4067 blocking_wait_with_raise_on_sig(NULL);
4073 if (**argv != '%') {
4074 pid_t pid = number(*argv);
4079 if (job->ps[job->nprocs - 1].pid == pid)
4081 job = job->prev_job;
4084 job = getjob(*argv, 0);
4085 /* loop until process terminated or stopped */
4086 while (job->state == JOBRUNNING)
4087 blocking_wait_with_raise_on_sig(NULL);
4089 retval = getstatus(job);
4102 struct job *jp, *jq;
4104 len = njobs * sizeof(*jp);
4106 jp = ckrealloc(jq, len + 4 * sizeof(*jp));
4108 offset = (char *)jp - (char *)jq;
4110 /* Relocate pointers */
4113 jq = (struct job *)((char *)jq + l);
4117 #define joff(p) ((struct job *)((char *)(p) + l))
4118 #define jmove(p) (p) = (void *)((char *)(p) + offset)
4119 if (joff(jp)->ps == &jq->ps0)
4120 jmove(joff(jp)->ps);
4121 if (joff(jp)->prev_job)
4122 jmove(joff(jp)->prev_job);
4132 jp = (struct job *)((char *)jp + len);
4136 } while (--jq >= jp);
4141 * Return a new job structure.
4142 * Called with interrupts off.
4145 makejob(/*union node *node,*/ int nprocs)
4150 for (i = njobs, jp = jobtab; ; jp++) {
4157 if (jp->state != JOBDONE || !jp->waited)
4166 memset(jp, 0, sizeof(*jp));
4168 /* jp->jobctl is a bitfield.
4169 * "jp->jobctl |= jobctl" likely to give awful code */
4173 jp->prev_job = curjob;
4178 jp->ps = ckmalloc(nprocs * sizeof(struct procstat));
4180 TRACE(("makejob(%d) returns %%%d\n", nprocs,
4187 * Return a string identifying a command (to be printed by the
4190 static char *cmdnextc;
4193 cmdputs(const char *s)
4195 static const char vstype[VSTYPE + 1][3] = {
4196 "", "}", "-", "+", "?", "=",
4197 "%", "%%", "#", "##"
4198 USE_ASH_BASH_COMPAT(, ":", "/", "//")
4201 const char *p, *str;
4202 char c, cc[2] = " ";
4207 nextc = makestrspace((strlen(s) + 1) * 8, cmdnextc);
4209 while ((c = *p++) != 0) {
4217 if ((subtype & VSTYPE) == VSLENGTH)
4221 if (!(subtype & VSQUOTE) == !(quoted & 1))
4227 str = "\"}" + !(quoted & 1);
4234 case CTLBACKQ+CTLQUOTE:
4237 #if ENABLE_ASH_MATH_SUPPORT
4252 if ((subtype & VSTYPE) != VSNORMAL)
4254 str = vstype[subtype & VSTYPE];
4255 if (subtype & VSNUL)
4264 /* These can only happen inside quotes */
4277 while ((c = *str++)) {
4282 USTPUTC('"', nextc);
4288 /* cmdtxt() and cmdlist() call each other */
4289 static void cmdtxt(union node *n);
4292 cmdlist(union node *np, int sep)
4294 for (; np; np = np->narg.next) {
4298 if (sep && np->narg.next)
4304 cmdtxt(union node *n)
4307 struct nodelist *lp;
4318 lp = n->npipe.cmdlist;
4336 cmdtxt(n->nbinary.ch1);
4352 cmdtxt(n->nif.test);
4355 if (n->nif.elsepart) {
4358 n = n->nif.elsepart;
4374 cmdtxt(n->nbinary.ch1);
4384 cmdputs(n->nfor.var);
4386 cmdlist(n->nfor.args, 1);
4391 cmdputs(n->narg.text);
4395 cmdlist(n->ncmd.args, 1);
4396 cmdlist(n->ncmd.redirect, 0);
4409 cmdputs(n->ncase.expr->narg.text);
4411 for (np = n->ncase.cases; np; np = np->nclist.next) {
4412 cmdtxt(np->nclist.pattern);
4414 cmdtxt(np->nclist.body);
4428 #if ENABLE_ASH_BASH_COMPAT
4443 cmdputs(utoa(n->nfile.fd));
4445 if (n->type == NTOFD || n->type == NFROMFD) {
4446 cmdputs(utoa(n->ndup.dupfd));
4455 commandtext(union node *n)
4459 STARTSTACKSTR(cmdnextc);
4461 name = stackblock();
4462 TRACE(("commandtext: name %p, end %p\n\t\"%s\"\n",
4463 name, cmdnextc, cmdnextc));
4464 return ckstrdup(name);
4469 * Fork off a subshell. If we are doing job control, give the subshell its
4470 * own process group. Jp is a job structure that the job is to be added to.
4471 * N is the command that will be evaluated by the child. Both jp and n may
4472 * be NULL. The mode parameter can be one of the following:
4473 * FORK_FG - Fork off a foreground process.
4474 * FORK_BG - Fork off a background process.
4475 * FORK_NOJOB - Like FORK_FG, but don't give the process its own
4476 * process group even if job control is on.
4478 * When job control is turned off, background processes have their standard
4479 * input redirected to /dev/null (except for the second and later processes
4482 * Called with interrupts off.
4485 * Clear traps on a fork.
4492 for (tp = trap; tp < &trap[NSIG]; tp++) {
4493 if (*tp && **tp) { /* trap not NULL or "" (SIG_IGN) */
4498 setsignal(tp - trap);
4504 /* Lives far away from here, needed for forkchild */
4505 static void closescript(void);
4507 /* Called after fork(), in child */
4509 forkchild(struct job *jp, /*union node *n,*/ int mode)
4513 TRACE(("Child shell %d\n", getpid()));
4517 /* man bash: "Non-builtin commands run by bash have signal handlers
4518 * set to the values inherited by the shell from its parent".
4519 * Do we do it correctly? */
4524 /* do job control only in root shell */
4526 if (mode != FORK_NOJOB && jp->jobctl && !oldlvl) {
4529 if (jp->nprocs == 0)
4532 pgrp = jp->ps[0].pid;
4533 /* this can fail because we are doing it in the parent also */
4535 if (mode == FORK_FG)
4536 xtcsetpgrp(ttyfd, pgrp);
4541 if (mode == FORK_BG) {
4542 /* man bash: "When job control is not in effect,
4543 * asynchronous commands ignore SIGINT and SIGQUIT" */
4546 if (jp->nprocs == 0) {
4548 if (open(bb_dev_null, O_RDONLY) != 0)
4549 ash_msg_and_raise_error("can't open '%s'", bb_dev_null);
4553 if (iflag) { /* why if iflag only? */
4558 * "In all cases, bash ignores SIGQUIT. Non-builtin
4559 * commands run by bash have signal handlers
4560 * set to the values inherited by the shell
4562 * Take care of the second rule: */
4565 for (jp = curjob; jp; jp = jp->prev_job)
4570 /* Called after fork(), in parent */
4572 #define forkparent(jp, n, mode, pid) forkparent(jp, mode, pid)
4575 forkparent(struct job *jp, union node *n, int mode, pid_t pid)
4577 TRACE(("In parent shell: child = %d\n", pid));
4579 while (jobless && dowait(DOWAIT_NONBLOCK, NULL) > 0)
4585 if (mode != FORK_NOJOB && jp->jobctl) {
4588 if (jp->nprocs == 0)
4591 pgrp = jp->ps[0].pid;
4592 /* This can fail because we are doing it in the child also */
4596 if (mode == FORK_BG) {
4597 backgndpid = pid; /* set $! */
4598 set_curjob(jp, CUR_RUNNING);
4601 struct procstat *ps = &jp->ps[jp->nprocs++];
4606 if (doing_jobctl && n)
4607 ps->cmd = commandtext(n);
4613 forkshell(struct job *jp, union node *n, int mode)
4617 TRACE(("forkshell(%%%d, %p, %d) called\n", jobno(jp), n, mode));
4620 TRACE(("Fork failed, errno=%d", errno));
4623 ash_msg_and_raise_error("can't fork");
4626 forkchild(jp, /*n,*/ mode);
4628 forkparent(jp, n, mode, pid);
4633 * Wait for job to finish.
4635 * Under job control we have the problem that while a child process
4636 * is running interrupts generated by the user are sent to the child
4637 * but not to the shell. This means that an infinite loop started by
4638 * an interactive user may be hard to kill. With job control turned off,
4639 * an interactive user may place an interactive program inside a loop.
4640 * If the interactive program catches interrupts, the user doesn't want
4641 * these interrupts to also abort the loop. The approach we take here
4642 * is to have the shell ignore interrupt signals while waiting for a
4643 * foreground process to terminate, and then send itself an interrupt
4644 * signal if the child process was terminated by an interrupt signal.
4645 * Unfortunately, some programs want to do a bit of cleanup and then
4646 * exit on interrupt; unless these processes terminate themselves by
4647 * sending a signal to themselves (instead of calling exit) they will
4648 * confuse this approach.
4650 * Called with interrupts off.
4653 waitforjob(struct job *jp)
4657 TRACE(("waitforjob(%%%d) called\n", jobno(jp)));
4660 while (jp->state == JOBRUNNING) {
4661 /* In non-interactive shells, we _can_ get
4662 * a keyboard signal here and be EINTRed,
4663 * but we just loop back, waiting for command to complete.
4666 * "If bash is waiting for a command to complete and receives
4667 * a signal for which a trap has been set, the trap
4668 * will not be executed until the command completes."
4670 * Reality is that even if trap is not set, bash
4671 * will not act on the signal until command completes.
4672 * Try this. sleep5intoff.c:
4673 * #include <signal.h>
4674 * #include <unistd.h>
4677 * sigemptyset(&set);
4678 * sigaddset(&set, SIGINT);
4679 * sigaddset(&set, SIGQUIT);
4680 * sigprocmask(SIG_BLOCK, &set, NULL);
4684 * $ bash -c './sleep5intoff; echo hi'
4685 * ^C^C^C^C <--- pressing ^C once a second
4687 * $ bash -c './sleep5intoff; echo hi'
4688 * ^\^\^\^\hi <--- pressing ^\ (SIGQUIT)
4691 dowait(DOWAIT_BLOCK, jp);
4698 xtcsetpgrp(ttyfd, rootpid);
4700 * This is truly gross.
4701 * If we're doing job control, then we did a TIOCSPGRP which
4702 * caused us (the shell) to no longer be in the controlling
4703 * session -- so we wouldn't have seen any ^C/SIGINT. So, we
4704 * intuit from the subprocess exit status whether a SIGINT
4705 * occurred, and if so interrupt ourselves. Yuck. - mycroft
4707 if (jp->sigint) /* TODO: do the same with all signals */
4708 raise(SIGINT); /* ... by raise(jp->sig) instead? */
4710 if (jp->state == JOBDONE)
4717 * return 1 if there are stopped jobs, otherwise 0
4729 if (jp && jp->state == JOBSTOPPED) {
4730 out2str("You have stopped jobs.\n");
4739 /* ============ redir.c
4741 * Code for dealing with input/output redirection.
4744 #define EMPTY -2 /* marks an unused slot in redirtab */
4745 #define CLOSED -3 /* marks a slot of previously-closed fd */
4748 * Open a file in noclobber mode.
4749 * The code was copied from bash.
4752 noclobberopen(const char *fname)
4755 struct stat finfo, finfo2;
4758 * If the file exists and is a regular file, return an error
4761 r = stat(fname, &finfo);
4762 if (r == 0 && S_ISREG(finfo.st_mode)) {
4768 * If the file was not present (r != 0), make sure we open it
4769 * exclusively so that if it is created before we open it, our open
4770 * will fail. Make sure that we do not truncate an existing file.
4771 * Note that we don't turn on O_EXCL unless the stat failed -- if the
4772 * file was not a regular file, we leave O_EXCL off.
4775 return open(fname, O_WRONLY|O_CREAT|O_EXCL, 0666);
4776 fd = open(fname, O_WRONLY|O_CREAT, 0666);
4778 /* If the open failed, return the file descriptor right away. */
4783 * OK, the open succeeded, but the file may have been changed from a
4784 * non-regular file to a regular file between the stat and the open.
4785 * We are assuming that the O_EXCL open handles the case where FILENAME
4786 * did not exist and is symlinked to an existing file between the stat
4791 * If we can open it and fstat the file descriptor, and neither check
4792 * revealed that it was a regular file, and the file has not been
4793 * replaced, return the file descriptor.
4795 if (fstat(fd, &finfo2) == 0 && !S_ISREG(finfo2.st_mode)
4796 && finfo.st_dev == finfo2.st_dev && finfo.st_ino == finfo2.st_ino)
4799 /* The file has been replaced. badness. */
4806 * Handle here documents. Normally we fork off a process to write the
4807 * data to a pipe. If the document is short, we can stuff the data in
4808 * the pipe without forking.
4810 /* openhere needs this forward reference */
4811 static void expandhere(union node *arg, int fd);
4813 openhere(union node *redir)
4819 ash_msg_and_raise_error("pipe call failed");
4820 if (redir->type == NHERE) {
4821 len = strlen(redir->nhere.doc->narg.text);
4822 if (len <= PIPE_BUF) {
4823 full_write(pip[1], redir->nhere.doc->narg.text, len);
4827 if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) {
4830 ignoresig(SIGINT); //signal(SIGINT, SIG_IGN);
4831 ignoresig(SIGQUIT); //signal(SIGQUIT, SIG_IGN);
4832 ignoresig(SIGHUP); //signal(SIGHUP, SIG_IGN);
4833 ignoresig(SIGTSTP); //signal(SIGTSTP, SIG_IGN);
4834 signal(SIGPIPE, SIG_DFL);
4835 if (redir->type == NHERE)
4836 full_write(pip[1], redir->nhere.doc->narg.text, len);
4838 expandhere(redir->nhere.doc, pip[1]);
4839 _exit(EXIT_SUCCESS);
4847 openredirect(union node *redir)
4852 switch (redir->nfile.type) {
4854 fname = redir->nfile.expfname;
4855 f = open(fname, O_RDONLY);
4860 fname = redir->nfile.expfname;
4861 f = open(fname, O_RDWR|O_CREAT|O_TRUNC, 0666);
4866 #if ENABLE_ASH_BASH_COMPAT
4869 /* Take care of noclobber mode. */
4871 fname = redir->nfile.expfname;
4872 f = noclobberopen(fname);
4879 fname = redir->nfile.expfname;
4880 f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666);
4885 fname = redir->nfile.expfname;
4886 f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666);
4894 /* Fall through to eliminate warning. */
4895 /* Our single caller does this itself */
4902 f = openhere(redir);
4908 ash_msg_and_raise_error("can't create %s: %s", fname, errmsg(errno, "nonexistent directory"));
4910 ash_msg_and_raise_error("can't open %s: %s", fname, errmsg(errno, "no such file"));
4914 * Copy a file descriptor to be >= to. Returns -1
4915 * if the source file descriptor is closed, EMPTY if there are no unused
4916 * file descriptors left.
4918 /* 0x800..00: bit to set in "to" to request dup2 instead of fcntl(F_DUPFD).
4919 * old code was doing close(to) prior to copyfd() to achieve the same */
4921 COPYFD_EXACT = (int)~(INT_MAX),
4922 COPYFD_RESTORE = (int)((unsigned)COPYFD_EXACT >> 1),
4925 copyfd(int from, int to)
4929 if (to & COPYFD_EXACT) {
4930 to &= ~COPYFD_EXACT;
4932 newfd = dup2(from, to);
4934 newfd = fcntl(from, F_DUPFD, to);
4937 if (errno == EMFILE)
4939 /* Happens when source fd is not open: try "echo >&99" */
4940 ash_msg_and_raise_error("%d: %m", from);
4945 /* Struct def and variable are moved down to the first usage site */
4950 struct redirtab *next;
4953 struct two_fd_t two_fd[0];
4955 #define redirlist (G_var.redirlist)
4957 static int need_to_remember(struct redirtab *rp, int fd)
4961 if (!rp) /* remembering was not requested */
4964 for (i = 0; i < rp->pair_count; i++) {
4965 if (rp->two_fd[i].orig == fd) {
4966 /* already remembered */
4973 /* "hidden" fd is a fd used to read scripts, or a copy of such */
4974 static int is_hidden_fd(struct redirtab *rp, int fd)
4977 struct parsefile *pf;
4990 fd |= COPYFD_RESTORE;
4991 for (i = 0; i < rp->pair_count; i++) {
4992 if (rp->two_fd[i].copy == fd) {
5000 * Process a list of redirection commands. If the REDIR_PUSH flag is set,
5001 * old file descriptors are stashed away so that the redirection can be
5002 * undone by calling popredir. If the REDIR_BACKQ flag is set, then the
5003 * standard output, and the standard error if it becomes a duplicate of
5004 * stdout, is saved in memory.
5006 /* flags passed to redirect */
5007 #define REDIR_PUSH 01 /* save previous values of file descriptors */
5008 #define REDIR_SAVEFD2 03 /* set preverrout */
5010 redirect(union node *redir, int flags)
5012 struct redirtab *sv;
5017 int copied_fd2 = -1;
5027 if (flags & REDIR_PUSH) {
5028 union node *tmp = redir;
5031 #if ENABLE_ASH_BASH_COMPAT
5032 if (redir->nfile.type == NTO2)
5035 tmp = tmp->nfile.next;
5037 sv = ckmalloc(sizeof(*sv) + sv_pos * sizeof(sv->two_fd[0]));
5038 sv->next = redirlist;
5039 sv->pair_count = sv_pos;
5041 sv->nullredirs = g_nullredirs - 1;
5043 while (sv_pos > 0) {
5045 sv->two_fd[sv_pos].orig = sv->two_fd[sv_pos].copy = EMPTY;
5050 fd = redir->nfile.fd;
5051 if (redir->nfile.type == NTOFD || redir->nfile.type == NFROMFD) {
5052 int right_fd = redir->ndup.dupfd;
5053 /* redirect from/to same file descriptor? */
5056 /* echo >&10 and 10 is a fd opened to the sh script? */
5057 if (is_hidden_fd(sv, right_fd)) {
5058 errno = EBADF; /* as if it is closed */
5059 ash_msg_and_raise_error("%d: %m", right_fd);
5063 newfd = openredirect(redir); /* always >= 0 */
5065 /* Descriptor wasn't open before redirect.
5066 * Mark it for close in the future */
5067 if (need_to_remember(sv, fd)) {
5068 goto remember_to_close;
5073 #if ENABLE_ASH_BASH_COMPAT
5076 if (need_to_remember(sv, fd)) {
5077 /* Copy old descriptor */
5078 i = fcntl(fd, F_DUPFD, 10);
5079 /* You'd expect copy to be CLOEXECed. Currently these extra "saved" fds
5080 * are closed in popredir() in the child, preventing them from leaking
5081 * into child. (popredir() also cleans up the mess in case of failures)
5086 /* Strange error (e.g. "too many files" EMFILE?) */
5090 ash_msg_and_raise_error("%d: %m", fd);
5093 /* EBADF: it is not open - good, remember to close it */
5096 } else { /* fd is open, save its copy */
5097 /* "exec fd>&-" should not close fds
5098 * which point to script file(s).
5099 * Force them to be restored afterwards */
5100 if (is_hidden_fd(sv, fd))
5101 i |= COPYFD_RESTORE;
5105 sv->two_fd[sv_pos].orig = fd;
5106 sv->two_fd[sv_pos].copy = i;
5110 /* NTOFD/NFROMFD: copy redir->ndup.dupfd to fd */
5111 if (redir->ndup.dupfd < 0) { /* "fd>&-" */
5114 copyfd(redir->ndup.dupfd, fd | COPYFD_EXACT);
5116 } else if (fd != newfd) { /* move newfd to fd */
5117 copyfd(newfd, fd | COPYFD_EXACT);
5118 #if ENABLE_ASH_BASH_COMPAT
5119 if (!(redir->nfile.type == NTO2 && fd == 2))
5123 #if ENABLE_ASH_BASH_COMPAT
5124 if (redir->nfile.type == NTO2 && fd == 1) {
5125 /* We already redirected it to fd 1, now copy it to 2 */
5131 } while ((redir = redir->nfile.next) != NULL);
5134 if ((flags & REDIR_SAVEFD2) && copied_fd2 >= 0)
5135 preverrout_fd = copied_fd2;
5139 * Undo the effects of the last redirection.
5142 popredir(int drop, int restore)
5144 struct redirtab *rp;
5147 if (--g_nullredirs >= 0)
5151 for (i = 0; i < rp->pair_count; i++) {
5152 int fd = rp->two_fd[i].orig;
5153 int copy = rp->two_fd[i].copy;
5154 if (copy == CLOSED) {
5159 if (copy != EMPTY) {
5160 if (!drop || (restore && (copy & COPYFD_RESTORE))) {
5161 copy &= ~COPYFD_RESTORE;
5163 copyfd(copy, fd | COPYFD_EXACT);
5168 redirlist = rp->next;
5169 g_nullredirs = rp->nullredirs;
5175 * Undo all redirections. Called on error or interrupt.
5179 * Discard all saved file descriptors.
5182 clearredir(int drop)
5188 popredir(drop, /*restore:*/ 0);
5193 redirectsafe(union node *redir, int flags)
5196 volatile int saveint;
5197 struct jmploc *volatile savehandler = exception_handler;
5198 struct jmploc jmploc;
5201 /* "echo 9>/dev/null; echo >&9; echo result: $?" - result should be 1, not 2! */
5202 err = setjmp(jmploc.loc); // huh?? was = setjmp(jmploc.loc) * 2;
5204 exception_handler = &jmploc;
5205 redirect(redir, flags);
5207 exception_handler = savehandler;
5208 if (err && exception_type != EXERROR)
5209 longjmp(exception_handler->loc, 1);
5210 RESTORE_INT(saveint);
5215 /* ============ Routines to expand arguments to commands
5217 * We have to deal with backquotes, shell variables, and file metacharacters.
5220 #if ENABLE_ASH_MATH_SUPPORT_64
5221 typedef int64_t arith_t;
5222 #define arith_t_type long long
5224 typedef long arith_t;
5225 #define arith_t_type long
5228 #if ENABLE_ASH_MATH_SUPPORT
5229 static arith_t dash_arith(const char *);
5230 static arith_t arith(const char *expr, int *perrcode);
5236 #define EXP_FULL 0x1 /* perform word splitting & file globbing */
5237 #define EXP_TILDE 0x2 /* do normal tilde expansion */
5238 #define EXP_VARTILDE 0x4 /* expand tildes in an assignment */
5239 #define EXP_REDIR 0x8 /* file glob for a redirection (1 match only) */
5240 #define EXP_CASE 0x10 /* keeps quotes around for CASE pattern */
5241 #define EXP_RECORD 0x20 /* need to record arguments for ifs breakup */
5242 #define EXP_VARTILDE2 0x40 /* expand tildes after colons only */
5243 #define EXP_WORD 0x80 /* expand word in parameter expansion */
5244 #define EXP_QWORD 0x100 /* expand word in quoted parameter expansion */
5248 #define RMESCAPE_ALLOC 0x1 /* Allocate a new string */
5249 #define RMESCAPE_GLOB 0x2 /* Add backslashes for glob */
5250 #define RMESCAPE_QUOTED 0x4 /* Remove CTLESC unless in quotes */
5251 #define RMESCAPE_GROW 0x8 /* Grow strings instead of stalloc */
5252 #define RMESCAPE_HEAP 0x10 /* Malloc strings instead of stalloc */
5255 * Structure specifying which parts of the string should be searched
5256 * for IFS characters.
5259 struct ifsregion *next; /* next region in list */
5260 int begoff; /* offset of start of region */
5261 int endoff; /* offset of end of region */
5262 int nulonly; /* search for nul bytes only */
5266 struct strlist *list;
5267 struct strlist **lastp;
5270 /* output of current string */
5271 static char *expdest;
5272 /* list of back quote expressions */
5273 static struct nodelist *argbackq;
5274 /* first struct in list of ifs regions */
5275 static struct ifsregion ifsfirst;
5276 /* last struct in list */
5277 static struct ifsregion *ifslastp;
5278 /* holds expanded arg list */
5279 static struct arglist exparg;
5289 expdest = makestrspace(32, expdest);
5290 #if ENABLE_ASH_MATH_SUPPORT_64
5291 len = fmtstr(expdest, 32, "%lld", (long long) num);
5293 len = fmtstr(expdest, 32, "%ld", num);
5295 STADJUST(len, expdest);
5300 esclen(const char *start, const char *p)
5304 while (p > start && *--p == CTLESC) {
5311 * Remove any CTLESC characters from a string.
5314 _rmescapes(char *str, int flag)
5316 static const char qchars[] ALIGN1 = { CTLESC, CTLQUOTEMARK, '\0' };
5323 p = strpbrk(str, qchars);
5329 if (flag & RMESCAPE_ALLOC) {
5330 size_t len = p - str;
5331 size_t fulllen = len + strlen(p) + 1;
5333 if (flag & RMESCAPE_GROW) {
5334 r = makestrspace(fulllen, expdest);
5335 } else if (flag & RMESCAPE_HEAP) {
5336 r = ckmalloc(fulllen);
5338 r = stalloc(fulllen);
5342 q = (char *)memcpy(q, str, len) + len;
5345 inquotes = (flag & RMESCAPE_QUOTED) ^ RMESCAPE_QUOTED;
5346 globbing = flag & RMESCAPE_GLOB;
5347 notescaped = globbing;
5349 if (*p == CTLQUOTEMARK) {
5350 inquotes = ~inquotes;
5352 notescaped = globbing;
5356 /* naked back slash */
5362 if (notescaped && inquotes && *p != '/') {
5366 notescaped = globbing;
5371 if (flag & RMESCAPE_GROW) {
5373 STADJUST(q - r + 1, expdest);
5377 #define rmescapes(p) _rmescapes((p), 0)
5379 #define pmatch(a, b) !fnmatch((a), (b), 0)
5382 * Prepare a pattern for a expmeta (internal glob(3)) call.
5384 * Returns an stalloced string.
5387 preglob(const char *pattern, int quoted, int flag)
5389 flag |= RMESCAPE_GLOB;
5391 flag |= RMESCAPE_QUOTED;
5393 return _rmescapes((char *)pattern, flag);
5397 * Put a string on the stack.
5400 memtodest(const char *p, size_t len, int syntax, int quotes)
5404 q = makestrspace(len * 2, q);
5407 int c = signed_char2int(*p++);
5410 if (quotes && (SIT(c, syntax) == CCTL || SIT(c, syntax) == CBACK))
5419 strtodest(const char *p, int syntax, int quotes)
5421 memtodest(p, strlen(p), syntax, quotes);
5425 * Record the fact that we have to scan this region of the
5426 * string for IFS characters.
5429 recordregion(int start, int end, int nulonly)
5431 struct ifsregion *ifsp;
5433 if (ifslastp == NULL) {
5437 ifsp = ckzalloc(sizeof(*ifsp));
5438 /*ifsp->next = NULL; - ckzalloc did it */
5439 ifslastp->next = ifsp;
5443 ifslastp->begoff = start;
5444 ifslastp->endoff = end;
5445 ifslastp->nulonly = nulonly;
5449 removerecordregions(int endoff)
5451 if (ifslastp == NULL)
5454 if (ifsfirst.endoff > endoff) {
5455 while (ifsfirst.next != NULL) {
5456 struct ifsregion *ifsp;
5458 ifsp = ifsfirst.next->next;
5459 free(ifsfirst.next);
5460 ifsfirst.next = ifsp;
5463 if (ifsfirst.begoff > endoff)
5466 ifslastp = &ifsfirst;
5467 ifsfirst.endoff = endoff;
5472 ifslastp = &ifsfirst;
5473 while (ifslastp->next && ifslastp->next->begoff < endoff)
5474 ifslastp=ifslastp->next;
5475 while (ifslastp->next != NULL) {
5476 struct ifsregion *ifsp;
5478 ifsp = ifslastp->next->next;
5479 free(ifslastp->next);
5480 ifslastp->next = ifsp;
5483 if (ifslastp->endoff > endoff)
5484 ifslastp->endoff = endoff;
5488 exptilde(char *startp, char *p, int flag)
5494 int quotes = flag & (EXP_FULL | EXP_CASE);
5499 while ((c = *++p) != '\0') {
5506 if (flag & EXP_VARTILDE)
5516 if (*name == '\0') {
5517 home = lookupvar(homestr);
5519 pw = getpwnam(name);
5524 if (!home || !*home)
5527 startloc = expdest - (char *)stackblock();
5528 strtodest(home, SQSYNTAX, quotes);
5529 recordregion(startloc, expdest - (char *)stackblock(), 0);
5537 * Execute a command inside back quotes. If it's a builtin command, we
5538 * want to save its output in a block obtained from malloc. Otherwise
5539 * we fork off a subprocess and get the output of the command via a pipe.
5540 * Should be called with interrupts off.
5542 struct backcmd { /* result of evalbackcmd */
5543 int fd; /* file descriptor to read from */
5544 int nleft; /* number of chars in buffer */
5545 char *buf; /* buffer */
5546 struct job *jp; /* job structure for command */
5549 /* These forward decls are needed to use "eval" code for backticks handling: */
5550 static uint8_t back_exitstatus; /* exit status of backquoted command */
5551 #define EV_EXIT 01 /* exit after evaluating tree */
5552 static void evaltree(union node *, int);
5555 evalbackcmd(union node *n, struct backcmd *result)
5566 saveherefd = herefd;
5574 ash_msg_and_raise_error("pipe call failed");
5575 jp = makejob(/*n,*/ 1);
5576 if (forkshell(jp, n, FORK_NOJOB) == 0) {
5581 copyfd(pip[1], 1 | COPYFD_EXACT);
5585 evaltree(n, EV_EXIT); /* actually evaltreenr... */
5589 result->fd = pip[0];
5592 herefd = saveherefd;
5594 TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n",
5595 result->fd, result->buf, result->nleft, result->jp));
5599 * Expand stuff in backwards quotes.
5602 expbackq(union node *cmd, int quoted, int quotes)
5610 int syntax = quoted ? DQSYNTAX : BASESYNTAX;
5611 struct stackmark smark;
5614 setstackmark(&smark);
5616 startloc = dest - (char *)stackblock();
5618 evalbackcmd(cmd, &in);
5619 popstackmark(&smark);
5626 memtodest(p, i, syntax, quotes);
5630 i = nonblock_safe_read(in.fd, buf, sizeof(buf));
5631 TRACE(("expbackq: read returns %d\n", i));
5640 back_exitstatus = waitforjob(in.jp);
5644 /* Eat all trailing newlines */
5646 for (; dest > (char *)stackblock() && dest[-1] == '\n';)
5651 recordregion(startloc, dest - (char *)stackblock(), 0);
5652 TRACE(("evalbackq: size=%d: \"%.*s\"\n",
5653 (dest - (char *)stackblock()) - startloc,
5654 (dest - (char *)stackblock()) - startloc,
5655 stackblock() + startloc));
5658 #if ENABLE_ASH_MATH_SUPPORT
5660 * Expand arithmetic expression. Backup to start of expression,
5661 * evaluate, place result in (backed up) result, adjust string position.
5674 * This routine is slightly over-complicated for
5675 * efficiency. Next we scan backwards looking for the
5676 * start of arithmetic.
5678 start = stackblock();
5685 while (*p != CTLARI) {
5689 ash_msg_and_raise_error("missing CTLARI (shouldn't happen)");
5694 esc = esclen(start, p);
5704 removerecordregions(begoff);
5713 len = cvtnum(dash_arith(p + 2));
5716 recordregion(begoff, begoff + len, 0);
5720 /* argstr needs it */
5721 static char *evalvar(char *p, int flag, struct strlist *var_str_list);
5724 * Perform variable and command substitution. If EXP_FULL is set, output CTLESC
5725 * characters to allow for further processing. Otherwise treat
5726 * $@ like $* since no splitting will be performed.
5728 * var_str_list (can be NULL) is a list of "VAR=val" strings which take precedence
5729 * over shell varables. Needed for "A=a B=$A; echo $B" case - we use it
5730 * for correct expansion of "B=$A" word.
5733 argstr(char *p, int flag, struct strlist *var_str_list)
5735 static const char spclchars[] ALIGN1 = {
5743 CTLBACKQ | CTLQUOTE,
5744 #if ENABLE_ASH_MATH_SUPPORT
5749 const char *reject = spclchars;
5751 int quotes = flag & (EXP_FULL | EXP_CASE); /* do CTLESC */
5752 int breakall = flag & EXP_WORD;
5757 if (!(flag & EXP_VARTILDE)) {
5759 } else if (flag & EXP_VARTILDE2) {
5764 if (flag & EXP_TILDE) {
5770 if (*q == CTLESC && (flag & EXP_QWORD))
5773 p = exptilde(p, q, flag);
5776 startloc = expdest - (char *)stackblock();
5778 length += strcspn(p + length, reject);
5780 if (c && (!(c & 0x80)
5781 #if ENABLE_ASH_MATH_SUPPORT
5785 /* c == '=' || c == ':' || c == CTLENDARI */
5790 expdest = stack_nputstr(p, length, expdest);
5791 newloc = expdest - (char *)stackblock();
5792 if (breakall && !inquotes && newloc > startloc) {
5793 recordregion(startloc, newloc, 0);
5804 if (flag & EXP_VARTILDE2) {
5808 flag |= EXP_VARTILDE2;
5813 * sort of a hack - expand tildes in variable
5814 * assignments (after the first '=' and after ':'s).
5823 case CTLENDVAR: /* ??? */
5826 /* "$@" syntax adherence hack */
5829 !memcmp(p, dolatstr, 4) &&
5830 (p[4] == CTLQUOTEMARK || (
5831 p[4] == CTLENDVAR &&
5832 p[5] == CTLQUOTEMARK
5835 p = evalvar(p + 1, flag, /* var_str_list: */ NULL) + 1;
5838 inquotes = !inquotes;
5851 p = evalvar(p, flag, var_str_list);
5855 case CTLBACKQ|CTLQUOTE:
5856 expbackq(argbackq->n, c, quotes);
5857 argbackq = argbackq->next;
5859 #if ENABLE_ASH_MATH_SUPPORT
5872 scanleft(char *startp, char *rmesc, char *rmescend UNUSED_PARAM, char *str, int quotes,
5875 // This commented out code was added by James Simmons <jsimmons@infradead.org>
5876 // as part of a larger change when he added support for ${var/a/b}.
5877 // However, it broke # and % operators:
5881 //echo ${var#ab} abcdcd abcdcd
5882 //echo ${var##ab} abcdcd abcdcd
5883 //echo ${var#a*b} abcdcd ababcdcd (!)
5884 //echo ${var##a*b} cdcd cdcd
5885 //echo ${var#?} babcdcd ababcdcd (!)
5886 //echo ${var##?} babcdcd babcdcd
5887 //echo ${var#*} ababcdcd babcdcd (!)
5889 //echo ${var%cd} ababcd ababcd
5890 //echo ${var%%cd} ababcd abab (!)
5891 //echo ${var%c*d} ababcd ababcd
5892 //echo ${var%%c*d} abab ababcdcd (!)
5893 //echo ${var%?} ababcdc ababcdc
5894 //echo ${var%%?} ababcdc ababcdcd (!)
5895 //echo ${var%*} ababcdcd ababcdcd
5898 // Commenting it back out helped. Remove it completely if it really
5901 char *loc, *loc2; //, *full;
5907 int match; // = strlen(str);
5908 const char *s = loc2;
5915 match = pmatch(str, s); // this line was deleted
5917 // // chop off end if its '*'
5918 // full = strrchr(str, '*');
5919 // if (full && full != str)
5922 // // If str starts with '*' replace with s.
5923 // if ((*str == '*') && strlen(s) >= match) {
5924 // full = xstrdup(s);
5925 // strncpy(full+strlen(s)-match+1, str+1, match-1);
5927 // full = xstrndup(str, match);
5928 // match = strncmp(s, full, strlen(full));
5932 if (match) // if (!match)
5934 if (quotes && *loc == CTLESC)
5943 scanright(char *startp, char *rmesc, char *rmescend, char *str, int quotes,
5950 for (loc = str - 1, loc2 = rmescend; loc >= startp; loc2--) {
5953 const char *s = loc2;
5958 match = pmatch(str, s);
5965 esc = esclen(startp, loc);
5976 static void varunset(const char *, const char *, const char *, int) NORETURN;
5978 varunset(const char *end, const char *var, const char *umsg, int varflags)
5984 msg = "parameter not set";
5986 if (*end == CTLENDVAR) {
5987 if (varflags & VSNUL)
5993 ash_msg_and_raise_error("%.*s: %s%s", end - var - 1, var, msg, tail);
5996 #if ENABLE_ASH_BASH_COMPAT
5998 parse_sub_pattern(char *arg, int inquotes)
6000 char *idx, *repl = NULL;
6009 /* Only the first '/' seen is our separator */
6016 if (!inquotes && c == '\\' && arg[1] == '\\')
6017 arg++; /* skip both \\, not just first one */
6024 #endif /* ENABLE_ASH_BASH_COMPAT */
6027 subevalvar(char *p, char *str, int strloc, int subtype,
6028 int startloc, int varflags, int quotes, struct strlist *var_str_list)
6030 struct nodelist *saveargbackq = argbackq;
6033 char *rmesc, *rmescend;
6034 USE_ASH_BASH_COMPAT(char *repl = NULL;)
6035 USE_ASH_BASH_COMPAT(char null = '\0';)
6036 USE_ASH_BASH_COMPAT(int pos, len, orig_len;)
6037 int saveherefd = herefd;
6038 int amount, workloc, resetloc;
6040 char *(*scan)(char*, char*, char*, char*, int, int);
6043 argstr(p, (subtype != VSASSIGN && subtype != VSQUESTION) ? EXP_CASE : 0,
6045 STPUTC('\0', expdest);
6046 herefd = saveherefd;
6047 argbackq = saveargbackq;
6048 startp = (char *)stackblock() + startloc;
6052 setvar(str, startp, 0);
6053 amount = startp - expdest;
6054 STADJUST(amount, expdest);
6057 #if ENABLE_ASH_BASH_COMPAT
6059 loc = str = stackblock() + strloc;
6060 // TODO: number() instead? It does error checking...
6062 len = str - startp - 1;
6064 /* *loc != '\0', guaranteed by parser */
6068 /* We must adjust the length by the number of escapes we find. */
6069 for (ptr = startp; ptr < (str - 1); ptr++) {
6070 if (*ptr == CTLESC) {
6078 if (*loc++ == ':') {
6079 // TODO: number() instead? It does error checking...
6083 while (*loc && *loc != ':')
6086 // TODO: number() instead? It does error checking...
6089 if (pos >= orig_len) {
6093 if (len > (orig_len - pos))
6094 len = orig_len - pos;
6096 for (str = startp; pos; str++, pos--) {
6097 if (quotes && *str == CTLESC)
6100 for (loc = startp; len; len--) {
6101 if (quotes && *str == CTLESC)
6106 amount = loc - expdest;
6107 STADJUST(amount, expdest);
6112 varunset(p, str, startp, varflags);
6115 resetloc = expdest - (char *)stackblock();
6117 /* We'll comeback here if we grow the stack while handling
6118 * a VSREPLACE or VSREPLACEALL, since our pointers into the
6119 * stack will need rebasing, and we'll need to remove our work
6122 USE_ASH_BASH_COMPAT(restart:)
6124 amount = expdest - ((char *)stackblock() + resetloc);
6125 STADJUST(-amount, expdest);
6126 startp = (char *)stackblock() + startloc;
6129 rmescend = (char *)stackblock() + strloc;
6131 rmesc = _rmescapes(startp, RMESCAPE_ALLOC | RMESCAPE_GROW);
6132 if (rmesc != startp) {
6134 startp = (char *)stackblock() + startloc;
6138 str = (char *)stackblock() + strloc;
6139 preglob(str, varflags & VSQUOTE, 0);
6140 workloc = expdest - (char *)stackblock();
6142 #if ENABLE_ASH_BASH_COMPAT
6143 if (subtype == VSREPLACE || subtype == VSREPLACEALL) {
6144 char *idx, *end, *restart_detect;
6147 repl = parse_sub_pattern(str, varflags & VSQUOTE);
6152 /* If there's no pattern to match, return the expansion unmolested */
6160 loc = scanright(idx, rmesc, rmescend, str, quotes, 1);
6162 /* No match, advance */
6163 restart_detect = stackblock();
6164 STPUTC(*idx, expdest);
6165 if (quotes && *idx == CTLESC) {
6168 STPUTC(*idx, expdest);
6170 if (stackblock() != restart_detect)
6178 if (subtype == VSREPLACEALL) {
6180 if (quotes && *idx == CTLESC)
6189 for (loc = repl; *loc; loc++) {
6190 restart_detect = stackblock();
6191 STPUTC(*loc, expdest);
6192 if (stackblock() != restart_detect)
6197 if (subtype == VSREPLACE) {
6199 restart_detect = stackblock();
6200 STPUTC(*idx, expdest);
6201 if (stackblock() != restart_detect)
6210 /* We've put the replaced text into a buffer at workloc, now
6211 * move it to the right place and adjust the stack.
6213 startp = stackblock() + startloc;
6214 STPUTC('\0', expdest);
6215 memmove(startp, stackblock() + workloc, len);
6216 startp[len++] = '\0';
6217 amount = expdest - ((char *)stackblock() + startloc + len - 1);
6218 STADJUST(-amount, expdest);
6221 #endif /* ENABLE_ASH_BASH_COMPAT */
6223 subtype -= VSTRIMRIGHT;
6225 if (subtype < 0 || subtype > 7)
6228 /* zero = subtype == VSTRIMLEFT || subtype == VSTRIMLEFTMAX */
6229 zero = subtype >> 1;
6230 /* VSTRIMLEFT/VSTRIMRIGHTMAX -> scanleft */
6231 scan = (subtype & 1) ^ zero ? scanleft : scanright;
6233 loc = scan(startp, rmesc, rmescend, str, quotes, zero);
6236 memmove(startp, loc, str - loc);
6237 loc = startp + (str - loc) - 1;
6240 amount = loc - expdest;
6241 STADJUST(amount, expdest);
6247 * Add the value of a specialized variable to the stack string.
6250 varvalue(char *name, int varflags, int flags, struct strlist *var_str_list)
6260 int quoted = varflags & VSQUOTE;
6261 int subtype = varflags & VSTYPE;
6262 int quotes = flags & (EXP_FULL | EXP_CASE);
6264 if (quoted && (flags & EXP_FULL))
6265 sep = 1 << CHAR_BIT;
6267 syntax = quoted ? DQSYNTAX : BASESYNTAX;
6276 num = shellparam.nparam;
6286 p = makestrspace(NOPTS, expdest);
6287 for (i = NOPTS - 1; i >= 0; i--) {
6289 USTPUTC(optletters(i), p);
6300 sep = ifsset() ? signed_char2int(ifsval()[0]) : ' ';
6301 if (quotes && (SIT(sep, syntax) == CCTL || SIT(sep, syntax) == CBACK))
6307 while ((p = *ap++)) {
6310 partlen = strlen(p);
6313 if (!(subtype == VSPLUS || subtype == VSLENGTH))
6314 memtodest(p, partlen, syntax, quotes);
6320 if (subtype == VSPLUS || subtype == VSLENGTH) {
6341 // TODO: number() instead? It does error checking...
6343 if (num < 0 || num > shellparam.nparam)
6345 p = num ? shellparam.p[num - 1] : arg0;
6348 /* NB: name has form "VAR=..." */
6350 /* "A=a B=$A" case: var_str_list is a list of "A=a" strings
6351 * which should be considered before we check variables. */
6353 unsigned name_len = (strchrnul(name, '=') - name) + 1;
6357 str = var_str_list->text;
6358 eq = strchr(str, '=');
6359 if (!eq) /* stop at first non-assignment */
6362 if (name_len == (unsigned)(eq - str)
6363 && strncmp(str, name, name_len) == 0) {
6365 /* goto value; - WRONG! */
6366 /* think "A=1 A=2 B=$A" */
6368 var_str_list = var_str_list->next;
6369 } while (var_str_list);
6373 p = lookupvar(name);
6379 if (!(subtype == VSPLUS || subtype == VSLENGTH))
6380 memtodest(p, len, syntax, quotes);
6384 if (subtype == VSPLUS || subtype == VSLENGTH)
6385 STADJUST(-len, expdest);
6390 * Expand a variable, and return a pointer to the next character in the
6394 evalvar(char *p, int flag, struct strlist *var_str_list)
6406 subtype = varflags & VSTYPE;
6407 quoted = varflags & VSQUOTE;
6409 easy = (!quoted || (*var == '@' && shellparam.nparam));
6410 startloc = expdest - (char *)stackblock();
6411 p = strchr(p, '=') + 1;
6414 varlen = varvalue(var, varflags, flag, var_str_list);
6415 if (varflags & VSNUL)
6418 if (subtype == VSPLUS) {
6419 varlen = -1 - varlen;
6423 if (subtype == VSMINUS) {
6427 p, flag | EXP_TILDE |
6428 (quoted ? EXP_QWORD : EXP_WORD),
6438 if (subtype == VSASSIGN || subtype == VSQUESTION) {
6440 if (subevalvar(p, var, /* strloc: */ 0,
6441 subtype, startloc, varflags,
6447 * Remove any recorded regions beyond
6450 removerecordregions(startloc);
6460 if (varlen < 0 && uflag)
6461 varunset(p, var, 0, 0);
6463 if (subtype == VSLENGTH) {
6464 cvtnum(varlen > 0 ? varlen : 0);
6468 if (subtype == VSNORMAL) {
6479 case VSTRIMRIGHTMAX:
6480 #if ENABLE_ASH_BASH_COMPAT
6493 * Terminate the string and start recording the pattern
6496 STPUTC('\0', expdest);
6497 patloc = expdest - (char *)stackblock();
6498 if (0 == subevalvar(p, /* str: */ NULL, patloc, subtype,
6500 /* quotes: */ flag & (EXP_FULL | EXP_CASE),
6503 int amount = expdest - (
6504 (char *)stackblock() + patloc - 1
6506 STADJUST(-amount, expdest);
6508 /* Remove any recorded regions beyond start of variable */
6509 removerecordregions(startloc);
6511 recordregion(startloc, expdest - (char *)stackblock(), quoted);
6515 if (subtype != VSNORMAL) { /* skip to end of alternative */
6521 else if (c == CTLBACKQ || c == (CTLBACKQ|CTLQUOTE)) {
6523 argbackq = argbackq->next;
6524 } else if (c == CTLVAR) {
6525 if ((*p++ & VSTYPE) != VSNORMAL)
6527 } else if (c == CTLENDVAR) {
6537 * Break the argument string into pieces based upon IFS and add the
6538 * strings to the argument list. The regions of the string to be
6539 * searched for IFS characters have been stored by recordregion.
6542 ifsbreakup(char *string, struct arglist *arglist)
6544 struct ifsregion *ifsp;
6549 const char *ifs, *realifs;
6554 if (ifslastp != NULL) {
6557 realifs = ifsset() ? ifsval() : defifs;
6560 p = string + ifsp->begoff;
6561 nulonly = ifsp->nulonly;
6562 ifs = nulonly ? nullstr : realifs;
6564 while (p < string + ifsp->endoff) {
6568 if (!strchr(ifs, *p)) {
6573 ifsspc = (strchr(defifs, *p) != NULL);
6574 /* Ignore IFS whitespace at start */
6575 if (q == start && ifsspc) {
6581 sp = stzalloc(sizeof(*sp));
6583 *arglist->lastp = sp;
6584 arglist->lastp = &sp->next;
6588 if (p >= string + ifsp->endoff) {
6594 if (strchr(ifs, *p) == NULL) {
6598 if (strchr(defifs, *p) == NULL) {
6613 } while (ifsp != NULL);
6622 sp = stzalloc(sizeof(*sp));
6624 *arglist->lastp = sp;
6625 arglist->lastp = &sp->next;
6631 struct ifsregion *p;
6636 struct ifsregion *ifsp;
6642 ifsfirst.next = NULL;
6647 * Add a file name to the list.
6650 addfname(const char *name)
6654 sp = stzalloc(sizeof(*sp));
6655 sp->text = ststrdup(name);
6657 exparg.lastp = &sp->next;
6660 static char *expdir;
6663 * Do metacharacter (i.e. *, ?, [...]) expansion.
6666 expmeta(char *enddir, char *name)
6681 for (p = name; *p; p++) {
6682 if (*p == '*' || *p == '?')
6684 else if (*p == '[') {
6691 if (*q == '/' || *q == '\0')
6698 } else if (*p == '\\')
6700 else if (*p == '/') {
6707 if (metaflag == 0) { /* we've reached the end of the file name */
6708 if (enddir != expdir)
6716 if (metaflag == 0 || lstat(expdir, &statb) >= 0)
6727 } while (p < start);
6729 if (enddir == expdir) {
6731 } else if (enddir == expdir + 1 && *expdir == '/') {
6740 if (enddir != expdir)
6742 if (*endname == 0) {
6754 while (!intpending && (dp = readdir(dirp)) != NULL) {
6755 if (dp->d_name[0] == '.' && !matchdot)
6757 if (pmatch(start, dp->d_name)) {
6759 strcpy(enddir, dp->d_name);
6762 for (p = enddir, cp = dp->d_name; (*p++ = *cp++) != '\0';)
6765 expmeta(p, endname);
6774 static struct strlist *
6775 msort(struct strlist *list, int len)
6777 struct strlist *p, *q = NULL;
6778 struct strlist **lpp;
6786 for (n = half; --n >= 0;) {
6790 q->next = NULL; /* terminate first half of list */
6791 q = msort(list, half); /* sort first half of list */
6792 p = msort(p, len - half); /* sort second half */
6795 #if ENABLE_LOCALE_SUPPORT
6796 if (strcoll(p->text, q->text) < 0)
6798 if (strcmp(p->text, q->text) < 0)
6822 * Sort the results of file name expansion. It calculates the number of
6823 * strings to sort and then calls msort (short for merge sort) to do the
6826 static struct strlist *
6827 expsort(struct strlist *str)
6833 for (sp = str; sp; sp = sp->next)
6835 return msort(str, len);
6839 expandmeta(struct strlist *str /*, int flag*/)
6841 static const char metachars[] ALIGN1 = {
6844 /* TODO - EXP_REDIR */
6847 struct strlist **savelastp;
6853 if (!strpbrk(str->text, metachars))
6855 savelastp = exparg.lastp;
6858 p = preglob(str->text, 0, RMESCAPE_ALLOC | RMESCAPE_HEAP);
6860 int i = strlen(str->text);
6861 expdir = ckmalloc(i < 2048 ? 2048 : i); /* XXX */
6869 if (exparg.lastp == savelastp) {
6874 *exparg.lastp = str;
6875 rmescapes(str->text);
6876 exparg.lastp = &str->next;
6878 *exparg.lastp = NULL;
6879 *savelastp = sp = expsort(*savelastp);
6880 while (sp->next != NULL)
6882 exparg.lastp = &sp->next;
6889 * Perform variable substitution and command substitution on an argument,
6890 * placing the resulting list of arguments in arglist. If EXP_FULL is true,
6891 * perform splitting and file name expansion. When arglist is NULL, perform
6892 * here document expansion.
6895 expandarg(union node *arg, struct arglist *arglist, int flag)
6900 argbackq = arg->narg.backquote;
6901 STARTSTACKSTR(expdest);
6902 ifsfirst.next = NULL;
6904 argstr(arg->narg.text, flag,
6905 /* var_str_list: */ arglist ? arglist->list : NULL);
6906 p = _STPUTC('\0', expdest);
6908 if (arglist == NULL) {
6909 return; /* here document expanded */
6911 p = grabstackstr(p);
6912 exparg.lastp = &exparg.list;
6916 if (flag & EXP_FULL) {
6917 ifsbreakup(p, &exparg);
6918 *exparg.lastp = NULL;
6919 exparg.lastp = &exparg.list;
6920 expandmeta(exparg.list /*, flag*/);
6922 if (flag & EXP_REDIR) /*XXX - for now, just remove escapes */
6924 sp = stzalloc(sizeof(*sp));
6927 exparg.lastp = &sp->next;
6931 *exparg.lastp = NULL;
6933 *arglist->lastp = exparg.list;
6934 arglist->lastp = exparg.lastp;
6939 * Expand shell variables and backquotes inside a here document.
6942 expandhere(union node *arg, int fd)
6945 expandarg(arg, (struct arglist *)NULL, 0);
6946 full_write(fd, stackblock(), expdest - (char *)stackblock());
6950 * Returns true if the pattern matches the string.
6953 patmatch(char *pattern, const char *string)
6955 return pmatch(preglob(pattern, 0, 0), string);
6959 * See if a pattern matches in a case statement.
6962 casematch(union node *pattern, char *val)
6964 struct stackmark smark;
6967 setstackmark(&smark);
6968 argbackq = pattern->narg.backquote;
6969 STARTSTACKSTR(expdest);
6971 argstr(pattern->narg.text, EXP_TILDE | EXP_CASE,
6972 /* var_str_list: */ NULL);
6973 STACKSTRNUL(expdest);
6974 result = patmatch(stackblock(), val);
6975 popstackmark(&smark);
6980 /* ============ find_command */
6984 int (*builtin)(int, char **);
6985 /* unsigned flags; */
6987 #define IS_BUILTIN_SPECIAL(b) ((b)->name[0] & 1)
6988 /* "regular" builtins always take precedence over commands,
6989 * regardless of PATH=....%builtin... position */
6990 #define IS_BUILTIN_REGULAR(b) ((b)->name[0] & 2)
6991 #define IS_BUILTIN_ASSIGN(b) ((b)->name[0] & 4)
6994 smallint cmdtype; /* CMDxxx */
6997 /* index >= 0 for commands without path (slashes) */
6998 /* (TODO: what exactly does the value mean? PATH position?) */
6999 /* index == -1 for commands with slashes */
7000 /* index == (-2 - applet_no) for NOFORK applets */
7001 const struct builtincmd *cmd;
7002 struct funcnode *func;
7005 /* values of cmdtype */
7006 #define CMDUNKNOWN -1 /* no entry in table for command */
7007 #define CMDNORMAL 0 /* command is an executable program */
7008 #define CMDFUNCTION 1 /* command is a shell function */
7009 #define CMDBUILTIN 2 /* command is a shell builtin */
7011 /* action to find_command() */
7012 #define DO_ERR 0x01 /* prints errors */
7013 #define DO_ABS 0x02 /* checks absolute paths */
7014 #define DO_NOFUNC 0x04 /* don't return shell functions, for command */
7015 #define DO_ALTPATH 0x08 /* using alternate path */
7016 #define DO_ALTBLTIN 0x20 /* %builtin in alt. path */
7018 static void find_command(char *, struct cmdentry *, int, const char *);
7021 /* ============ Hashing commands */
7024 * When commands are first encountered, they are entered in a hash table.
7025 * This ensures that a full path search will not have to be done for them
7026 * on each invocation.
7028 * We should investigate converting to a linear search, even though that
7029 * would make the command name "hash" a misnomer.
7033 struct tblentry *next; /* next entry in hash chain */
7034 union param param; /* definition of builtin function */
7035 smallint cmdtype; /* CMDxxx */
7036 char rehash; /* if set, cd done since entry created */
7037 char cmdname[1]; /* name of command */
7040 static struct tblentry **cmdtable;
7041 #define INIT_G_cmdtable() do { \
7042 cmdtable = xzalloc(CMDTABLESIZE * sizeof(cmdtable[0])); \
7045 static int builtinloc = -1; /* index in path of %builtin, or -1 */
7049 tryexec(USE_FEATURE_SH_STANDALONE(int applet_no,) char *cmd, char **argv, char **envp)
7053 #if ENABLE_FEATURE_SH_STANDALONE
7054 if (applet_no >= 0) {
7055 if (APPLET_IS_NOEXEC(applet_no)) {
7058 run_applet_no_and_exit(applet_no, argv);
7060 /* re-exec ourselves with the new arguments */
7061 execve(bb_busybox_exec_path, argv, envp);
7062 /* If they called chroot or otherwise made the binary no longer
7063 * executable, fall through */
7070 execve(cmd, argv, envp);
7071 } while (errno == EINTR);
7073 execve(cmd, argv, envp);
7079 if (errno == ENOEXEC) {
7083 for (ap = argv; *ap; ap++)
7085 ap = new = ckmalloc((ap - argv + 2) * sizeof(ap[0]));
7087 ap[0] = cmd = (char *)DEFAULT_SHELL;
7090 while ((*ap++ = *argv++) != NULL)
7099 * Exec a program. Never returns. If you change this routine, you may
7100 * have to change the find_command routine as well.
7102 static void shellexec(char **, const char *, int) NORETURN;
7104 shellexec(char **argv, const char *path, int idx)
7110 #if ENABLE_FEATURE_SH_STANDALONE
7114 clearredir(/*drop:*/ 1);
7115 envp = listvars(VEXPORT, VUNSET, 0);
7116 if (strchr(argv[0], '/') != NULL
7117 #if ENABLE_FEATURE_SH_STANDALONE
7118 || (applet_no = find_applet_by_name(argv[0])) >= 0
7121 tryexec(USE_FEATURE_SH_STANDALONE(applet_no,) argv[0], argv, envp);
7125 while ((cmdname = padvance(&path, argv[0])) != NULL) {
7126 if (--idx < 0 && pathopt == NULL) {
7127 tryexec(USE_FEATURE_SH_STANDALONE(-1,) cmdname, argv, envp);
7128 if (errno != ENOENT && errno != ENOTDIR)
7135 /* Map to POSIX errors */
7147 exitstatus = exerrno;
7148 TRACE(("shellexec failed for %s, errno %d, suppressint %d\n",
7149 argv[0], e, suppressint));
7150 ash_msg_and_raise(EXEXEC, "%s: %s", argv[0], errmsg(e, "not found"));
7155 printentry(struct tblentry *cmdp)
7161 idx = cmdp->param.index;
7164 name = padvance(&path, cmdp->cmdname);
7166 } while (--idx >= 0);
7167 out1fmt("%s%s\n", name, (cmdp->rehash ? "*" : nullstr));
7171 * Clear out command entries. The argument specifies the first entry in
7172 * PATH which has changed.
7175 clearcmdentry(int firstchange)
7177 struct tblentry **tblp;
7178 struct tblentry **pp;
7179 struct tblentry *cmdp;
7182 for (tblp = cmdtable; tblp < &cmdtable[CMDTABLESIZE]; tblp++) {
7184 while ((cmdp = *pp) != NULL) {
7185 if ((cmdp->cmdtype == CMDNORMAL &&
7186 cmdp->param.index >= firstchange)
7187 || (cmdp->cmdtype == CMDBUILTIN &&
7188 builtinloc >= firstchange)
7201 * Locate a command in the command hash table. If "add" is nonzero,
7202 * add the command to the table if it is not already present. The
7203 * variable "lastcmdentry" is set to point to the address of the link
7204 * pointing to the entry, so that delete_cmd_entry can delete the
7207 * Interrupts must be off if called with add != 0.
7209 static struct tblentry **lastcmdentry;
7211 static struct tblentry *
7212 cmdlookup(const char *name, int add)
7214 unsigned int hashval;
7216 struct tblentry *cmdp;
7217 struct tblentry **pp;
7220 hashval = (unsigned char)*p << 4;
7222 hashval += (unsigned char)*p++;
7224 pp = &cmdtable[hashval % CMDTABLESIZE];
7225 for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
7226 if (strcmp(cmdp->cmdname, name) == 0)
7230 if (add && cmdp == NULL) {
7231 cmdp = *pp = ckzalloc(sizeof(struct tblentry)
7233 /* + 1 - already done because
7234 * tblentry::cmdname is char[1] */);
7235 /*cmdp->next = NULL; - ckzalloc did it */
7236 cmdp->cmdtype = CMDUNKNOWN;
7237 strcpy(cmdp->cmdname, name);
7244 * Delete the command entry returned on the last lookup.
7247 delete_cmd_entry(void)
7249 struct tblentry *cmdp;
7252 cmdp = *lastcmdentry;
7253 *lastcmdentry = cmdp->next;
7254 if (cmdp->cmdtype == CMDFUNCTION)
7255 freefunc(cmdp->param.func);
7261 * Add a new command entry, replacing any existing command entry for
7262 * the same name - except special builtins.
7265 addcmdentry(char *name, struct cmdentry *entry)
7267 struct tblentry *cmdp;
7269 cmdp = cmdlookup(name, 1);
7270 if (cmdp->cmdtype == CMDFUNCTION) {
7271 freefunc(cmdp->param.func);
7273 cmdp->cmdtype = entry->cmdtype;
7274 cmdp->param = entry->u;
7279 hashcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
7281 struct tblentry **pp;
7282 struct tblentry *cmdp;
7284 struct cmdentry entry;
7287 if (nextopt("r") != '\0') {
7292 if (*argptr == NULL) {
7293 for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
7294 for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
7295 if (cmdp->cmdtype == CMDNORMAL)
7303 while ((name = *argptr) != NULL) {
7304 cmdp = cmdlookup(name, 0);
7306 && (cmdp->cmdtype == CMDNORMAL
7307 || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0))
7311 find_command(name, &entry, DO_ERR, pathval());
7312 if (entry.cmdtype == CMDUNKNOWN)
7320 * Called when a cd is done. Marks all commands so the next time they
7321 * are executed they will be rehashed.
7326 struct tblentry **pp;
7327 struct tblentry *cmdp;
7329 for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
7330 for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
7331 if (cmdp->cmdtype == CMDNORMAL
7332 || (cmdp->cmdtype == CMDBUILTIN
7333 && !IS_BUILTIN_REGULAR(cmdp->param.cmd)
7343 * Fix command hash table when PATH changed.
7344 * Called before PATH is changed. The argument is the new value of PATH;
7345 * pathval() still returns the old value at this point.
7346 * Called with interrupts off.
7349 changepath(const char *new)
7357 firstchange = 9999; /* assume no change */
7363 if ((*old == '\0' && *new == ':')
7364 || (*old == ':' && *new == '\0'))
7366 old = new; /* ignore subsequent differences */
7370 if (*new == '%' && idx_bltin < 0 && prefix(new + 1, "builtin"))
7376 if (builtinloc < 0 && idx_bltin >= 0)
7377 builtinloc = idx_bltin; /* zap builtins */
7378 if (builtinloc >= 0 && idx_bltin < 0)
7380 clearcmdentry(firstchange);
7381 builtinloc = idx_bltin;
7396 #define TENDBQUOTE 12
7413 typedef smallint token_id_t;
7415 /* first char is indicating which tokens mark the end of a list */
7416 static const char *const tokname_array[] = {
7430 #define KWDOFFSET 13
7431 /* the following are keywords */
7453 static char buf[16];
7456 //if (tok < TSEMI) return tokname_array[tok] + 1;
7457 //sprintf(buf, "\"%s\"", tokname_array[tok] + 1);
7462 sprintf(buf + (tok >= TSEMI), "%s%c",
7463 tokname_array[tok] + 1, (tok >= TSEMI ? '"' : 0));
7467 /* Wrapper around strcmp for qsort/bsearch/... */
7469 pstrcmp(const void *a, const void *b)
7471 return strcmp((char*) a, (*(char**) b) + 1);
7474 static const char *const *
7475 findkwd(const char *s)
7477 return bsearch(s, tokname_array + KWDOFFSET,
7478 ARRAY_SIZE(tokname_array) - KWDOFFSET,
7479 sizeof(tokname_array[0]), pstrcmp);
7483 * Locate and print what a word is...
7486 describe_command(char *command, int describe_command_verbose)
7488 struct cmdentry entry;
7489 struct tblentry *cmdp;
7490 #if ENABLE_ASH_ALIAS
7491 const struct alias *ap;
7493 const char *path = pathval();
7495 if (describe_command_verbose) {
7499 /* First look at the keywords */
7500 if (findkwd(command)) {
7501 out1str(describe_command_verbose ? " is a shell keyword" : command);
7505 #if ENABLE_ASH_ALIAS
7506 /* Then look at the aliases */
7507 ap = lookupalias(command, 0);
7509 if (!describe_command_verbose) {
7514 out1fmt(" is an alias for %s", ap->val);
7518 /* Then check if it is a tracked alias */
7519 cmdp = cmdlookup(command, 0);
7521 entry.cmdtype = cmdp->cmdtype;
7522 entry.u = cmdp->param;
7524 /* Finally use brute force */
7525 find_command(command, &entry, DO_ABS, path);
7528 switch (entry.cmdtype) {
7530 int j = entry.u.index;
7536 p = padvance(&path, command);
7540 if (describe_command_verbose) {
7542 (cmdp ? " a tracked alias for" : nullstr), p
7551 if (describe_command_verbose) {
7552 out1str(" is a shell function");
7559 if (describe_command_verbose) {
7560 out1fmt(" is a %sshell builtin",
7561 IS_BUILTIN_SPECIAL(entry.u.cmd) ?
7562 "special " : nullstr
7570 if (describe_command_verbose) {
7571 out1str(": not found\n");
7576 outstr("\n", stdout);
7581 typecmd(int argc UNUSED_PARAM, char **argv)
7587 /* type -p ... ? (we don't bother checking for 'p') */
7588 if (argv[1] && argv[1][0] == '-') {
7593 err |= describe_command(argv[i++], verbose);
7598 #if ENABLE_ASH_CMDCMD
7600 commandcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
7608 while ((c = nextopt("pvV")) != '\0')
7610 verify |= VERIFY_VERBOSE;
7612 verify |= VERIFY_BRIEF;
7617 /* Mimic bash: just "command -v" doesn't complain, it's a nop */
7618 if (verify && (*argptr != NULL)) {
7619 return describe_command(*argptr, verify - VERIFY_BRIEF);
7627 /* ============ eval.c */
7629 static int funcblocksize; /* size of structures in function */
7630 static int funcstringsize; /* size of strings in node */
7631 static void *funcblock; /* block to allocate function from */
7632 static char *funcstring; /* block to allocate strings from */
7634 /* flags in argument to evaltree */
7635 #define EV_EXIT 01 /* exit after evaluating tree */
7636 #define EV_TESTED 02 /* exit status is checked; ignore -e flag */
7637 #define EV_BACKCMD 04 /* command executing within back quotes */
7639 static const short nodesize[N_NUMBER] = {
7640 [NCMD ] = SHELL_ALIGN(sizeof(struct ncmd)),
7641 [NPIPE ] = SHELL_ALIGN(sizeof(struct npipe)),
7642 [NREDIR ] = SHELL_ALIGN(sizeof(struct nredir)),
7643 [NBACKGND ] = SHELL_ALIGN(sizeof(struct nredir)),
7644 [NSUBSHELL] = SHELL_ALIGN(sizeof(struct nredir)),
7645 [NAND ] = SHELL_ALIGN(sizeof(struct nbinary)),
7646 [NOR ] = SHELL_ALIGN(sizeof(struct nbinary)),
7647 [NSEMI ] = SHELL_ALIGN(sizeof(struct nbinary)),
7648 [NIF ] = SHELL_ALIGN(sizeof(struct nif)),
7649 [NWHILE ] = SHELL_ALIGN(sizeof(struct nbinary)),
7650 [NUNTIL ] = SHELL_ALIGN(sizeof(struct nbinary)),
7651 [NFOR ] = SHELL_ALIGN(sizeof(struct nfor)),
7652 [NCASE ] = SHELL_ALIGN(sizeof(struct ncase)),
7653 [NCLIST ] = SHELL_ALIGN(sizeof(struct nclist)),
7654 [NDEFUN ] = SHELL_ALIGN(sizeof(struct narg)),
7655 [NARG ] = SHELL_ALIGN(sizeof(struct narg)),
7656 [NTO ] = SHELL_ALIGN(sizeof(struct nfile)),
7657 #if ENABLE_ASH_BASH_COMPAT
7658 [NTO2 ] = SHELL_ALIGN(sizeof(struct nfile)),
7660 [NCLOBBER ] = SHELL_ALIGN(sizeof(struct nfile)),
7661 [NFROM ] = SHELL_ALIGN(sizeof(struct nfile)),
7662 [NFROMTO ] = SHELL_ALIGN(sizeof(struct nfile)),
7663 [NAPPEND ] = SHELL_ALIGN(sizeof(struct nfile)),
7664 [NTOFD ] = SHELL_ALIGN(sizeof(struct ndup)),
7665 [NFROMFD ] = SHELL_ALIGN(sizeof(struct ndup)),
7666 [NHERE ] = SHELL_ALIGN(sizeof(struct nhere)),
7667 [NXHERE ] = SHELL_ALIGN(sizeof(struct nhere)),
7668 [NNOT ] = SHELL_ALIGN(sizeof(struct nnot)),
7671 static void calcsize(union node *n);
7674 sizenodelist(struct nodelist *lp)
7677 funcblocksize += SHELL_ALIGN(sizeof(struct nodelist));
7684 calcsize(union node *n)
7688 funcblocksize += nodesize[n->type];
7691 calcsize(n->ncmd.redirect);
7692 calcsize(n->ncmd.args);
7693 calcsize(n->ncmd.assign);
7696 sizenodelist(n->npipe.cmdlist);
7701 calcsize(n->nredir.redirect);
7702 calcsize(n->nredir.n);
7709 calcsize(n->nbinary.ch2);
7710 calcsize(n->nbinary.ch1);
7713 calcsize(n->nif.elsepart);
7714 calcsize(n->nif.ifpart);
7715 calcsize(n->nif.test);
7718 funcstringsize += strlen(n->nfor.var) + 1;
7719 calcsize(n->nfor.body);
7720 calcsize(n->nfor.args);
7723 calcsize(n->ncase.cases);
7724 calcsize(n->ncase.expr);
7727 calcsize(n->nclist.body);
7728 calcsize(n->nclist.pattern);
7729 calcsize(n->nclist.next);
7733 sizenodelist(n->narg.backquote);
7734 funcstringsize += strlen(n->narg.text) + 1;
7735 calcsize(n->narg.next);
7738 #if ENABLE_ASH_BASH_COMPAT
7745 calcsize(n->nfile.fname);
7746 calcsize(n->nfile.next);
7750 calcsize(n->ndup.vname);
7751 calcsize(n->ndup.next);
7755 calcsize(n->nhere.doc);
7756 calcsize(n->nhere.next);
7759 calcsize(n->nnot.com);
7765 nodeckstrdup(char *s)
7767 char *rtn = funcstring;
7769 strcpy(funcstring, s);
7770 funcstring += strlen(s) + 1;
7774 static union node *copynode(union node *);
7776 static struct nodelist *
7777 copynodelist(struct nodelist *lp)
7779 struct nodelist *start;
7780 struct nodelist **lpp;
7785 funcblock = (char *) funcblock + SHELL_ALIGN(sizeof(struct nodelist));
7786 (*lpp)->n = copynode(lp->n);
7788 lpp = &(*lpp)->next;
7795 copynode(union node *n)
7802 funcblock = (char *) funcblock + nodesize[n->type];
7806 new->ncmd.redirect = copynode(n->ncmd.redirect);
7807 new->ncmd.args = copynode(n->ncmd.args);
7808 new->ncmd.assign = copynode(n->ncmd.assign);
7811 new->npipe.cmdlist = copynodelist(n->npipe.cmdlist);
7812 new->npipe.pipe_backgnd = n->npipe.pipe_backgnd;
7817 new->nredir.redirect = copynode(n->nredir.redirect);
7818 new->nredir.n = copynode(n->nredir.n);
7825 new->nbinary.ch2 = copynode(n->nbinary.ch2);
7826 new->nbinary.ch1 = copynode(n->nbinary.ch1);
7829 new->nif.elsepart = copynode(n->nif.elsepart);
7830 new->nif.ifpart = copynode(n->nif.ifpart);
7831 new->nif.test = copynode(n->nif.test);
7834 new->nfor.var = nodeckstrdup(n->nfor.var);
7835 new->nfor.body = copynode(n->nfor.body);
7836 new->nfor.args = copynode(n->nfor.args);
7839 new->ncase.cases = copynode(n->ncase.cases);
7840 new->ncase.expr = copynode(n->ncase.expr);
7843 new->nclist.body = copynode(n->nclist.body);
7844 new->nclist.pattern = copynode(n->nclist.pattern);
7845 new->nclist.next = copynode(n->nclist.next);
7849 new->narg.backquote = copynodelist(n->narg.backquote);
7850 new->narg.text = nodeckstrdup(n->narg.text);
7851 new->narg.next = copynode(n->narg.next);
7854 #if ENABLE_ASH_BASH_COMPAT
7861 new->nfile.fname = copynode(n->nfile.fname);
7862 new->nfile.fd = n->nfile.fd;
7863 new->nfile.next = copynode(n->nfile.next);
7867 new->ndup.vname = copynode(n->ndup.vname);
7868 new->ndup.dupfd = n->ndup.dupfd;
7869 new->ndup.fd = n->ndup.fd;
7870 new->ndup.next = copynode(n->ndup.next);
7874 new->nhere.doc = copynode(n->nhere.doc);
7875 new->nhere.fd = n->nhere.fd;
7876 new->nhere.next = copynode(n->nhere.next);
7879 new->nnot.com = copynode(n->nnot.com);
7882 new->type = n->type;
7887 * Make a copy of a parse tree.
7889 static struct funcnode *
7890 copyfunc(union node *n)
7895 funcblocksize = offsetof(struct funcnode, n);
7898 blocksize = funcblocksize;
7899 f = ckmalloc(blocksize + funcstringsize);
7900 funcblock = (char *) f + offsetof(struct funcnode, n);
7901 funcstring = (char *) f + blocksize;
7908 * Define a shell function.
7911 defun(char *name, union node *func)
7913 struct cmdentry entry;
7916 entry.cmdtype = CMDFUNCTION;
7917 entry.u.func = copyfunc(func);
7918 addcmdentry(name, &entry);
7922 /* Reasons for skipping commands (see comment on breakcmd routine) */
7923 #define SKIPBREAK (1 << 0)
7924 #define SKIPCONT (1 << 1)
7925 #define SKIPFUNC (1 << 2)
7926 #define SKIPFILE (1 << 3)
7927 #define SKIPEVAL (1 << 4)
7928 static smallint evalskip; /* set to SKIPxxx if we are skipping commands */
7929 static int skipcount; /* number of levels to skip */
7930 static int funcnest; /* depth of function calls */
7931 static int loopnest; /* current loop nesting level */
7933 /* Forward decl way out to parsing code - dotrap needs it */
7934 static int evalstring(char *s, int mask);
7936 /* Called to execute a trap.
7937 * Single callsite - at the end of evaltree().
7938 * If we return non-zero, exaltree raises EXEXIT exception.
7940 * Perhaps we should avoid entering new trap handlers
7941 * while we are executing a trap handler. [is it a TODO?]
7950 savestatus = exitstatus;
7954 for (sig = 1, g = gotsig; sig < NSIG; sig++, g++) {
7961 /* non-trapped SIGINT is handled separately by raise_interrupt,
7962 * don't upset it by resetting gotsig[SIGINT-1] */
7963 if (sig == SIGINT && !t)
7968 want_exexit = evalstring(t, SKIPEVAL);
7969 exitstatus = savestatus;
7977 /* forward declarations - evaluation is fairly recursive business... */
7978 static void evalloop(union node *, int);
7979 static void evalfor(union node *, int);
7980 static void evalcase(union node *, int);
7981 static void evalsubshell(union node *, int);
7982 static void expredir(union node *);
7983 static void evalpipe(union node *, int);
7984 static void evalcommand(union node *, int);
7985 static int evalbltin(const struct builtincmd *, int, char **);
7986 static void prehash(union node *);
7989 * Evaluate a parse tree. The value is left in the global variable
7993 evaltree(union node *n, int flags)
7995 struct jmploc *volatile savehandler = exception_handler;
7996 struct jmploc jmploc;
7998 void (*evalfn)(union node *, int);
8002 TRACE(("evaltree(NULL) called\n"));
8005 TRACE(("pid %d, evaltree(%p: %d, %d) called\n",
8006 getpid(), n, n->type, flags));
8008 exception_handler = &jmploc;
8010 int err = setjmp(jmploc.loc);
8012 /* if it was a signal, check for trap handlers */
8013 if (exception_type == EXSIG)
8015 /* continue on the way out */
8016 exception_handler = savehandler;
8017 longjmp(exception_handler->loc, err);
8024 out1fmt("Node type = %d\n", n->type);
8029 evaltree(n->nnot.com, EV_TESTED);
8030 status = !exitstatus;
8033 expredir(n->nredir.redirect);
8034 status = redirectsafe(n->nredir.redirect, REDIR_PUSH);
8036 evaltree(n->nredir.n, flags & EV_TESTED);
8037 status = exitstatus;
8039 popredir(/*drop:*/ 0, /*restore:*/ 0 /* not sure */);
8042 evalfn = evalcommand;
8044 if (eflag && !(flags & EV_TESTED))
8056 evalfn = evalsubshell;
8069 #error NAND + 1 != NOR
8071 #if NOR + 1 != NSEMI
8072 #error NOR + 1 != NSEMI
8074 unsigned is_or = n->type - NAND;
8077 (flags | ((is_or >> 1) - 1)) & EV_TESTED
8079 if (!exitstatus == is_or)
8092 evaltree(n->nif.test, EV_TESTED);
8095 if (exitstatus == 0) {
8098 } else if (n->nif.elsepart) {
8099 n = n->nif.elsepart;
8104 defun(n->narg.text, n->narg.next);
8108 exitstatus = status;
8113 exception_handler = savehandler;
8115 if (checkexit & exitstatus)
8116 evalskip |= SKIPEVAL;
8117 else if (pendingsig && dotrap())
8120 if (flags & EV_EXIT) {
8122 raise_exception(EXEXIT);
8126 #if !defined(__alpha__) || (defined(__GNUC__) && __GNUC__ >= 3)
8129 void evaltreenr(union node *, int) __attribute__ ((alias("evaltree"),__noreturn__));
8132 evalloop(union node *n, int flags)
8142 evaltree(n->nbinary.ch1, EV_TESTED);
8145 if (evalskip == SKIPCONT && --skipcount <= 0) {
8149 if (evalskip == SKIPBREAK && --skipcount <= 0)
8154 if (n->type != NWHILE)
8158 evaltree(n->nbinary.ch2, flags);
8159 status = exitstatus;
8164 exitstatus = status;
8168 evalfor(union node *n, int flags)
8170 struct arglist arglist;
8173 struct stackmark smark;
8175 setstackmark(&smark);
8176 arglist.list = NULL;
8177 arglist.lastp = &arglist.list;
8178 for (argp = n->nfor.args; argp; argp = argp->narg.next) {
8179 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE | EXP_RECORD);
8184 *arglist.lastp = NULL;
8189 for (sp = arglist.list; sp; sp = sp->next) {
8190 setvar(n->nfor.var, sp->text, 0);
8191 evaltree(n->nfor.body, flags);
8193 if (evalskip == SKIPCONT && --skipcount <= 0) {
8197 if (evalskip == SKIPBREAK && --skipcount <= 0)
8204 popstackmark(&smark);
8208 evalcase(union node *n, int flags)
8212 struct arglist arglist;
8213 struct stackmark smark;
8215 setstackmark(&smark);
8216 arglist.list = NULL;
8217 arglist.lastp = &arglist.list;
8218 expandarg(n->ncase.expr, &arglist, EXP_TILDE);
8220 for (cp = n->ncase.cases; cp && evalskip == 0; cp = cp->nclist.next) {
8221 for (patp = cp->nclist.pattern; patp; patp = patp->narg.next) {
8222 if (casematch(patp, arglist.list->text)) {
8223 if (evalskip == 0) {
8224 evaltree(cp->nclist.body, flags);
8231 popstackmark(&smark);
8235 * Kick off a subshell to evaluate a tree.
8238 evalsubshell(union node *n, int flags)
8241 int backgnd = (n->type == NBACKGND);
8244 expredir(n->nredir.redirect);
8245 if (!backgnd && flags & EV_EXIT && !trap[0])
8248 jp = makejob(/*n,*/ 1);
8249 if (forkshell(jp, n, backgnd) == 0) {
8253 flags &=~ EV_TESTED;
8255 redirect(n->nredir.redirect, 0);
8256 evaltreenr(n->nredir.n, flags);
8261 status = waitforjob(jp);
8262 exitstatus = status;
8267 * Compute the names of the files in a redirection list.
8269 static void fixredir(union node *, const char *, int);
8271 expredir(union node *n)
8275 for (redir = n; redir; redir = redir->nfile.next) {
8279 fn.lastp = &fn.list;
8280 switch (redir->type) {
8284 #if ENABLE_ASH_BASH_COMPAT
8289 expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
8290 #if ENABLE_ASH_BASH_COMPAT
8293 redir->nfile.expfname = fn.list->text;
8296 case NTOFD: /* >& */
8297 if (redir->ndup.vname) {
8298 expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE);
8299 if (fn.list == NULL)
8300 ash_msg_and_raise_error("redir error");
8301 #if ENABLE_ASH_BASH_COMPAT
8302 //FIXME: we used expandarg with different args!
8303 if (!isdigit_str9(fn.list->text)) {
8304 /* >&file, not >&fd */
8305 if (redir->nfile.fd != 1) /* 123>&file - BAD */
8306 ash_msg_and_raise_error("redir error");
8308 goto store_expfname;
8311 fixredir(redir, fn.list->text, 1);
8319 * Evaluate a pipeline. All the processes in the pipeline are children
8320 * of the process creating the pipeline. (This differs from some versions
8321 * of the shell, which make the last process in a pipeline the parent
8325 evalpipe(union node *n, int flags)
8328 struct nodelist *lp;
8333 TRACE(("evalpipe(0x%lx) called\n", (long)n));
8335 for (lp = n->npipe.cmdlist; lp; lp = lp->next)
8339 jp = makejob(/*n,*/ pipelen);
8341 for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
8345 if (pipe(pip) < 0) {
8347 ash_msg_and_raise_error("pipe call failed");
8350 if (forkshell(jp, lp->n, n->npipe.pipe_backgnd) == 0) {
8363 evaltreenr(lp->n, flags);
8371 if (n->npipe.pipe_backgnd == 0) {
8372 exitstatus = waitforjob(jp);
8373 TRACE(("evalpipe: job done exit status %d\n", exitstatus));
8379 * Controls whether the shell is interactive or not.
8382 setinteractive(int on)
8384 static smallint is_interactive;
8386 if (++on == is_interactive)
8388 is_interactive = on;
8392 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
8393 if (is_interactive > 1) {
8394 /* Looks like they want an interactive shell */
8395 static smallint did_banner;
8400 "%s built-in shell (ash)\n"
8401 "Enter 'help' for a list of built-in commands."
8416 setinteractive(iflag);
8418 #if ENABLE_FEATURE_EDITING_VI
8420 line_input_state->flags |= VI_MODE;
8422 line_input_state->flags &= ~VI_MODE;
8424 viflag = 0; /* forcibly keep the option off */
8428 static struct localvar *localvars;
8431 * Called after a function returns.
8432 * Interrupts must be off.
8437 struct localvar *lvp;
8440 while ((lvp = localvars) != NULL) {
8441 localvars = lvp->next;
8443 TRACE(("poplocalvar %s", vp ? vp->text : "-"));
8444 if (vp == NULL) { /* $- saved */
8445 memcpy(optlist, lvp->text, sizeof(optlist));
8446 free((char*)lvp->text);
8448 } else if ((lvp->flags & (VUNSET|VSTRFIXED)) == VUNSET) {
8452 (*vp->func)(strchrnul(lvp->text, '=') + 1);
8453 if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
8454 free((char*)vp->text);
8455 vp->flags = lvp->flags;
8456 vp->text = lvp->text;
8463 evalfun(struct funcnode *func, int argc, char **argv, int flags)
8465 volatile struct shparam saveparam;
8466 struct localvar *volatile savelocalvars;
8467 struct jmploc *volatile savehandler;
8468 struct jmploc jmploc;
8471 saveparam = shellparam;
8472 savelocalvars = localvars;
8473 e = setjmp(jmploc.loc);
8478 savehandler = exception_handler;
8479 exception_handler = &jmploc;
8481 shellparam.malloced = 0;
8485 shellparam.nparam = argc - 1;
8486 shellparam.p = argv + 1;
8487 #if ENABLE_ASH_GETOPTS
8488 shellparam.optind = 1;
8489 shellparam.optoff = -1;
8491 evaltree(&func->n, flags & EV_TESTED);
8497 localvars = savelocalvars;
8498 freeparam(&shellparam);
8499 shellparam = saveparam;
8500 exception_handler = savehandler;
8502 evalskip &= ~SKIPFUNC;
8506 #if ENABLE_ASH_CMDCMD
8508 parse_command_args(char **argv, const char **path)
8521 if (c == '-' && !*cp) {
8528 *path = bb_default_path;
8531 /* run 'typecmd' for other options */
8542 * Make a variable a local variable. When a variable is made local, it's
8543 * value and flags are saved in a localvar structure. The saved values
8544 * will be restored when the shell function returns. We handle the name
8545 * "-" as a special case.
8550 struct localvar *lvp;
8555 lvp = ckzalloc(sizeof(struct localvar));
8556 if (LONE_DASH(name)) {
8558 p = ckmalloc(sizeof(optlist));
8559 lvp->text = memcpy(p, optlist, sizeof(optlist));
8564 vpp = hashvar(name);
8565 vp = *findvar(vpp, name);
8566 eq = strchr(name, '=');
8569 setvareq(name, VSTRFIXED);
8571 setvar(name, NULL, VSTRFIXED);
8572 vp = *vpp; /* the new variable */
8573 lvp->flags = VUNSET;
8575 lvp->text = vp->text;
8576 lvp->flags = vp->flags;
8577 vp->flags |= VSTRFIXED|VTEXTFIXED;
8583 lvp->next = localvars;
8589 * The "local" command.
8592 localcmd(int argc UNUSED_PARAM, char **argv)
8597 while ((name = *argv++) != NULL) {
8604 falsecmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
8610 truecmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
8616 execcmd(int argc UNUSED_PARAM, char **argv)
8619 iflag = 0; /* exit on error */
8622 shellexec(argv + 1, pathval(), 0);
8628 * The return command.
8631 returncmd(int argc UNUSED_PARAM, char **argv)
8634 * If called outside a function, do what ksh does;
8635 * skip the rest of the file.
8637 evalskip = funcnest ? SKIPFUNC : SKIPFILE;
8638 return argv[1] ? number(argv[1]) : exitstatus;
8641 /* Forward declarations for builtintab[] */
8642 static int breakcmd(int, char **);
8643 static int dotcmd(int, char **);
8644 static int evalcmd(int, char **);
8645 static int exitcmd(int, char **);
8646 static int exportcmd(int, char **);
8647 #if ENABLE_ASH_GETOPTS
8648 static int getoptscmd(int, char **);
8650 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
8651 static int helpcmd(int, char **);
8653 #if ENABLE_ASH_MATH_SUPPORT
8654 static int letcmd(int, char **);
8656 static int readcmd(int, char **);
8657 static int setcmd(int, char **);
8658 static int shiftcmd(int, char **);
8659 static int timescmd(int, char **);
8660 static int trapcmd(int, char **);
8661 static int umaskcmd(int, char **);
8662 static int unsetcmd(int, char **);
8663 static int ulimitcmd(int, char **);
8665 #define BUILTIN_NOSPEC "0"
8666 #define BUILTIN_SPECIAL "1"
8667 #define BUILTIN_REGULAR "2"
8668 #define BUILTIN_SPEC_REG "3"
8669 #define BUILTIN_ASSIGN "4"
8670 #define BUILTIN_SPEC_ASSG "5"
8671 #define BUILTIN_REG_ASSG "6"
8672 #define BUILTIN_SPEC_REG_ASSG "7"
8674 /* We do not handle [[ expr ]] bashism bash-compatibly,
8675 * we make it a synonym of [ expr ].
8676 * Basically, word splitting and pathname expansion should NOT be performed
8678 * no word splitting: a="a b"; [[ $a = "a b" ]]; echo $? should print "0"
8679 * no pathname expansion: [[ /bin/m* = "/bin/m*" ]]; echo $? should print "0"
8680 * Additional operators:
8681 * || and && should work as -o and -a
8683 * Apart from the above, [[ expr ]] should work as [ expr ]
8686 #define echocmd echo_main
8687 #define printfcmd printf_main
8688 #define testcmd test_main
8690 /* Keep these in proper order since it is searched via bsearch() */
8691 static const struct builtincmd builtintab[] = {
8692 { BUILTIN_SPEC_REG ".", dotcmd },
8693 { BUILTIN_SPEC_REG ":", truecmd },
8694 #if ENABLE_ASH_BUILTIN_TEST
8695 { BUILTIN_REGULAR "[", testcmd },
8696 #if ENABLE_ASH_BASH_COMPAT
8697 { BUILTIN_REGULAR "[[", testcmd },
8700 #if ENABLE_ASH_ALIAS
8701 { BUILTIN_REG_ASSG "alias", aliascmd },
8704 { BUILTIN_REGULAR "bg", fg_bgcmd },
8706 { BUILTIN_SPEC_REG "break", breakcmd },
8707 { BUILTIN_REGULAR "cd", cdcmd },
8708 { BUILTIN_NOSPEC "chdir", cdcmd },
8709 #if ENABLE_ASH_CMDCMD
8710 { BUILTIN_REGULAR "command", commandcmd },
8712 { BUILTIN_SPEC_REG "continue", breakcmd },
8713 #if ENABLE_ASH_BUILTIN_ECHO
8714 { BUILTIN_REGULAR "echo", echocmd },
8716 { BUILTIN_SPEC_REG "eval", evalcmd },
8717 { BUILTIN_SPEC_REG "exec", execcmd },
8718 { BUILTIN_SPEC_REG "exit", exitcmd },
8719 { BUILTIN_SPEC_REG_ASSG "export", exportcmd },
8720 { BUILTIN_REGULAR "false", falsecmd },
8722 { BUILTIN_REGULAR "fg", fg_bgcmd },
8724 #if ENABLE_ASH_GETOPTS
8725 { BUILTIN_REGULAR "getopts", getoptscmd },
8727 { BUILTIN_NOSPEC "hash", hashcmd },
8728 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
8729 { BUILTIN_NOSPEC "help", helpcmd },
8732 { BUILTIN_REGULAR "jobs", jobscmd },
8733 { BUILTIN_REGULAR "kill", killcmd },
8735 #if ENABLE_ASH_MATH_SUPPORT
8736 { BUILTIN_NOSPEC "let", letcmd },
8738 { BUILTIN_ASSIGN "local", localcmd },
8739 #if ENABLE_ASH_BUILTIN_PRINTF
8740 { BUILTIN_REGULAR "printf", printfcmd },
8742 { BUILTIN_NOSPEC "pwd", pwdcmd },
8743 { BUILTIN_REGULAR "read", readcmd },
8744 { BUILTIN_SPEC_REG_ASSG "readonly", exportcmd },
8745 { BUILTIN_SPEC_REG "return", returncmd },
8746 { BUILTIN_SPEC_REG "set", setcmd },
8747 { BUILTIN_SPEC_REG "shift", shiftcmd },
8748 { BUILTIN_SPEC_REG "source", dotcmd },
8749 #if ENABLE_ASH_BUILTIN_TEST
8750 { BUILTIN_REGULAR "test", testcmd },
8752 { BUILTIN_SPEC_REG "times", timescmd },
8753 { BUILTIN_SPEC_REG "trap", trapcmd },
8754 { BUILTIN_REGULAR "true", truecmd },
8755 { BUILTIN_NOSPEC "type", typecmd },
8756 { BUILTIN_NOSPEC "ulimit", ulimitcmd },
8757 { BUILTIN_REGULAR "umask", umaskcmd },
8758 #if ENABLE_ASH_ALIAS
8759 { BUILTIN_REGULAR "unalias", unaliascmd },
8761 { BUILTIN_SPEC_REG "unset", unsetcmd },
8762 { BUILTIN_REGULAR "wait", waitcmd },
8765 /* Should match the above table! */
8766 #define COMMANDCMD (builtintab + \
8768 1 * ENABLE_ASH_BUILTIN_TEST + \
8769 1 * ENABLE_ASH_BUILTIN_TEST * ENABLE_ASH_BASH_COMPAT + \
8770 1 * ENABLE_ASH_ALIAS + \
8771 1 * ENABLE_ASH_JOB_CONTROL + \
8773 #define EXECCMD (builtintab + \
8775 1 * ENABLE_ASH_BUILTIN_TEST + \
8776 1 * ENABLE_ASH_BUILTIN_TEST * ENABLE_ASH_BASH_COMPAT + \
8777 1 * ENABLE_ASH_ALIAS + \
8778 1 * ENABLE_ASH_JOB_CONTROL + \
8780 1 * ENABLE_ASH_CMDCMD + \
8782 ENABLE_ASH_BUILTIN_ECHO + \
8786 * Search the table of builtin commands.
8788 static struct builtincmd *
8789 find_builtin(const char *name)
8791 struct builtincmd *bp;
8794 name, builtintab, ARRAY_SIZE(builtintab), sizeof(builtintab[0]),
8801 * Execute a simple command.
8804 isassignment(const char *p)
8806 const char *q = endofname(p);
8812 bltincmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
8814 /* Preserve exitstatus of a previous possible redirection
8815 * as POSIX mandates */
8816 return back_exitstatus;
8819 evalcommand(union node *cmd, int flags)
8821 static const struct builtincmd null_bltin = {
8822 "\0\0", bltincmd /* why three NULs? */
8824 struct stackmark smark;
8826 struct arglist arglist;
8827 struct arglist varlist;
8830 const struct strlist *sp;
8831 struct cmdentry cmdentry;
8838 struct builtincmd *bcmd;
8839 smallint cmd_is_exec;
8840 smallint pseudovarflag = 0;
8842 /* First expand the arguments. */
8843 TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
8844 setstackmark(&smark);
8845 back_exitstatus = 0;
8847 cmdentry.cmdtype = CMDBUILTIN;
8848 cmdentry.u.cmd = &null_bltin;
8849 varlist.lastp = &varlist.list;
8850 *varlist.lastp = NULL;
8851 arglist.lastp = &arglist.list;
8852 *arglist.lastp = NULL;
8855 if (cmd->ncmd.args) {
8856 bcmd = find_builtin(cmd->ncmd.args->narg.text);
8857 pseudovarflag = bcmd && IS_BUILTIN_ASSIGN(bcmd);
8860 for (argp = cmd->ncmd.args; argp; argp = argp->narg.next) {
8861 struct strlist **spp;
8863 spp = arglist.lastp;
8864 if (pseudovarflag && isassignment(argp->narg.text))
8865 expandarg(argp, &arglist, EXP_VARTILDE);
8867 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
8869 for (sp = *spp; sp; sp = sp->next)
8873 argv = nargv = stalloc(sizeof(char *) * (argc + 1));
8874 for (sp = arglist.list; sp; sp = sp->next) {
8875 TRACE(("evalcommand arg: %s\n", sp->text));
8876 *nargv++ = sp->text;
8881 if (iflag && funcnest == 0 && argc > 0)
8882 lastarg = nargv[-1];
8885 expredir(cmd->ncmd.redirect);
8886 status = redirectsafe(cmd->ncmd.redirect, REDIR_PUSH | REDIR_SAVEFD2);
8889 for (argp = cmd->ncmd.assign; argp; argp = argp->narg.next) {
8890 struct strlist **spp;
8893 spp = varlist.lastp;
8894 expandarg(argp, &varlist, EXP_VARTILDE);
8897 * Modify the command lookup path, if a PATH= assignment
8901 if (varequal(p, path))
8905 /* Print the command if xflag is set. */
8908 const char *p = " %s";
8911 fdprintf(preverrout_fd, p, expandstr(ps4val()));
8914 for (n = 0; n < 2; n++) {
8916 fdprintf(preverrout_fd, p, sp->text);
8924 safe_write(preverrout_fd, "\n", 1);
8930 /* Now locate the command. */
8932 const char *oldpath;
8933 int cmd_flag = DO_ERR;
8938 find_command(argv[0], &cmdentry, cmd_flag, path);
8939 if (cmdentry.cmdtype == CMDUNKNOWN) {
8945 /* implement bltin and command here */
8946 if (cmdentry.cmdtype != CMDBUILTIN)
8949 spclbltin = IS_BUILTIN_SPECIAL(cmdentry.u.cmd);
8950 if (cmdentry.u.cmd == EXECCMD)
8952 #if ENABLE_ASH_CMDCMD
8953 if (cmdentry.u.cmd == COMMANDCMD) {
8955 nargv = parse_command_args(argv, &path);
8958 argc -= nargv - argv;
8960 cmd_flag |= DO_NOFUNC;
8968 /* We have a redirection error. */
8970 raise_exception(EXERROR);
8972 exitstatus = status;
8976 /* Execute the command. */
8977 switch (cmdentry.cmdtype) {
8980 #if ENABLE_FEATURE_SH_NOFORK
8981 /* Hmmm... shouldn't it happen somewhere in forkshell() instead?
8982 * Why "fork off a child process if necessary" doesn't apply to NOFORK? */
8984 /* find_command() encodes applet_no as (-2 - applet_no) */
8985 int applet_no = (- cmdentry.u.index - 2);
8986 if (applet_no >= 0 && APPLET_IS_NOFORK(applet_no)) {
8987 listsetvar(varlist.list, VEXPORT|VSTACK);
8988 /* run <applet>_main() */
8989 exitstatus = run_nofork_applet(applet_no, argv);
8994 /* Fork off a child process if necessary. */
8995 if (!(flags & EV_EXIT) || trap[0]) {
8997 jp = makejob(/*cmd,*/ 1);
8998 if (forkshell(jp, cmd, FORK_FG) != 0) {
8999 exitstatus = waitforjob(jp);
9005 listsetvar(varlist.list, VEXPORT|VSTACK);
9006 shellexec(argv, path, cmdentry.u.index);
9010 cmdenviron = varlist.list;
9012 struct strlist *list = cmdenviron;
9014 if (spclbltin > 0 || argc == 0) {
9016 if (cmd_is_exec && argc > 1)
9019 listsetvar(list, i);
9021 /* Tight loop with builtins only:
9022 * "while kill -0 $child; do true; done"
9023 * will never exit even if $child died, unless we do this
9024 * to reap the zombie and make kill detect that it's gone: */
9025 dowait(DOWAIT_NONBLOCK, NULL);
9027 if (evalbltin(cmdentry.u.cmd, argc, argv)) {
9029 int i = exception_type;
9034 exit_status = 128 + SIGINT;
9036 exit_status = 128 + pendingsig;
9037 exitstatus = exit_status;
9038 if (i == EXINT || spclbltin > 0) {
9040 longjmp(exception_handler->loc, 1);
9047 listsetvar(varlist.list, 0);
9048 /* See above for the rationale */
9049 dowait(DOWAIT_NONBLOCK, NULL);
9050 if (evalfun(cmdentry.u.func, argc, argv, flags))
9056 popredir(/*drop:*/ cmd_is_exec, /*restore:*/ cmd_is_exec);
9058 /* dsl: I think this is intended to be used to support
9059 * '_' in 'vi' command mode during line editing...
9060 * However I implemented that within libedit itself.
9062 setvar("_", lastarg, 0);
9064 popstackmark(&smark);
9068 evalbltin(const struct builtincmd *cmd, int argc, char **argv)
9070 char *volatile savecmdname;
9071 struct jmploc *volatile savehandler;
9072 struct jmploc jmploc;
9075 savecmdname = commandname;
9076 i = setjmp(jmploc.loc);
9079 savehandler = exception_handler;
9080 exception_handler = &jmploc;
9081 commandname = argv[0];
9083 optptr = NULL; /* initialize nextopt */
9084 exitstatus = (*cmd->builtin)(argc, argv);
9085 flush_stdout_stderr();
9087 exitstatus |= ferror(stdout);
9089 commandname = savecmdname;
9091 exception_handler = savehandler;
9097 goodname(const char *p)
9099 return !*endofname(p);
9104 * Search for a command. This is called before we fork so that the
9105 * location of the command will be available in the parent as well as
9106 * the child. The check for "goodname" is an overly conservative
9107 * check that the name will not be subject to expansion.
9110 prehash(union node *n)
9112 struct cmdentry entry;
9114 if (n->type == NCMD && n->ncmd.args && goodname(n->ncmd.args->narg.text))
9115 find_command(n->ncmd.args->narg.text, &entry, 0, pathval());
9119 /* ============ Builtin commands
9121 * Builtin commands whose functions are closely tied to evaluation
9122 * are implemented here.
9126 * Handle break and continue commands. Break, continue, and return are
9127 * all handled by setting the evalskip flag. The evaluation routines
9128 * above all check this flag, and if it is set they start skipping
9129 * commands rather than executing them. The variable skipcount is
9130 * the number of loops to break/continue, or the number of function
9131 * levels to return. (The latter is always 1.) It should probably
9132 * be an error to break out of more loops than exist, but it isn't
9133 * in the standard shell so we don't make it one here.
9136 breakcmd(int argc UNUSED_PARAM, char **argv)
9138 int n = argv[1] ? number(argv[1]) : 1;
9141 ash_msg_and_raise_error(illnum, argv[1]);
9145 evalskip = (**argv == 'c') ? SKIPCONT : SKIPBREAK;
9152 /* ============ input.c
9154 * This implements the input routines used by the parser.
9158 INPUT_PUSH_FILE = 1,
9159 INPUT_NOFILE_OK = 2,
9162 static smallint checkkwd;
9163 /* values of checkkwd variable */
9164 #define CHKALIAS 0x1
9169 * Push a string back onto the input at this current parsefile level.
9170 * We handle aliases this way.
9172 #if !ENABLE_ASH_ALIAS
9173 #define pushstring(s, ap) pushstring(s)
9176 pushstring(char *s, struct alias *ap)
9183 if (g_parsefile->strpush) {
9184 sp = ckzalloc(sizeof(*sp));
9185 sp->prev = g_parsefile->strpush;
9187 sp = &(g_parsefile->basestrpush);
9189 g_parsefile->strpush = sp;
9190 sp->prev_string = g_parsefile->next_to_pgetc;
9191 sp->prev_left_in_line = g_parsefile->left_in_line;
9192 #if ENABLE_ASH_ALIAS
9195 ap->flag |= ALIASINUSE;
9199 g_parsefile->next_to_pgetc = s;
9200 g_parsefile->left_in_line = len;
9207 struct strpush *sp = g_parsefile->strpush;
9210 #if ENABLE_ASH_ALIAS
9212 if (g_parsefile->next_to_pgetc[-1] == ' '
9213 || g_parsefile->next_to_pgetc[-1] == '\t'
9215 checkkwd |= CHKALIAS;
9217 if (sp->string != sp->ap->val) {
9220 sp->ap->flag &= ~ALIASINUSE;
9221 if (sp->ap->flag & ALIASDEAD) {
9222 unalias(sp->ap->name);
9226 g_parsefile->next_to_pgetc = sp->prev_string;
9227 g_parsefile->left_in_line = sp->prev_left_in_line;
9228 g_parsefile->strpush = sp->prev;
9229 if (sp != &(g_parsefile->basestrpush))
9234 //FIXME: BASH_COMPAT with "...&" does TWO pungetc():
9235 //it peeks whether it is &>, and then pushes back both chars.
9236 //This function needs to save last *next_to_pgetc to buf[0]
9237 //to make two pungetc() reliable. Currently,
9238 // pgetc (out of buf: does preadfd), pgetc, pungetc, pungetc won't work...
9243 char *buf = g_parsefile->buf;
9245 g_parsefile->next_to_pgetc = buf;
9246 #if ENABLE_FEATURE_EDITING
9248 if (!iflag || g_parsefile->fd != STDIN_FILENO)
9249 nr = nonblock_safe_read(g_parsefile->fd, buf, BUFSIZ - 1);
9251 #if ENABLE_FEATURE_TAB_COMPLETION
9252 line_input_state->path_lookup = pathval();
9254 nr = read_line_input(cmdedit_prompt, buf, BUFSIZ, line_input_state);
9256 /* Ctrl+C pressed */
9265 if (nr < 0 && errno == 0) {
9266 /* Ctrl+D pressed */
9271 nr = nonblock_safe_read(g_parsefile->fd, buf, BUFSIZ - 1);
9275 /* nonblock_safe_read() handles this problem */
9277 if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
9278 int flags = fcntl(0, F_GETFL);
9279 if (flags >= 0 && (flags & O_NONBLOCK)) {
9280 flags &= ~O_NONBLOCK;
9281 if (fcntl(0, F_SETFL, flags) >= 0) {
9282 out2str("sh: turning off NDELAY mode\n");
9293 * Refill the input buffer and return the next input character:
9295 * 1) If a string was pushed back on the input, pop it;
9296 * 2) If an EOF was pushed back (g_parsefile->left_in_line < -BIGNUM)
9297 * or we are reading from a string so we can't refill the buffer,
9299 * 3) If the is more stuff in this buffer, use it else call read to fill it.
9300 * 4) Process input up to the next newline, deleting nul characters.
9302 //#define pgetc_debug(...) bb_error_msg(__VA_ARGS__)
9303 #define pgetc_debug(...) ((void)0)
9305 * NB: due to SIT(c) internals (syntax_index_table[] vector),
9306 * pgetc() and related functions must return chars SIGN-EXTENDED into ints,
9307 * not zero-extended. Seems fragile to me. Affects only !USE_SIT_FUNCTION case,
9308 * so we can fix it by ditching !USE_SIT_FUNCTION if Unicode requires that.
9316 while (g_parsefile->strpush) {
9317 #if ENABLE_ASH_ALIAS
9318 if (g_parsefile->left_in_line == -1
9319 && g_parsefile->strpush->ap
9320 && g_parsefile->next_to_pgetc[-1] != ' '
9321 && g_parsefile->next_to_pgetc[-1] != '\t'
9323 pgetc_debug("preadbuffer PEOA");
9328 /* try "pgetc" now: */
9329 pgetc_debug("preadbuffer internal pgetc at %d:%p'%s'",
9330 g_parsefile->left_in_line,
9331 g_parsefile->next_to_pgetc,
9332 g_parsefile->next_to_pgetc);
9333 if (--g_parsefile->left_in_line >= 0)
9334 return (unsigned char)(*g_parsefile->next_to_pgetc++);
9336 /* on both branches above g_parsefile->left_in_line < 0.
9337 * "pgetc" needs refilling.
9340 /* -90 is our -BIGNUM. Below we use -99 to mark "EOF on read",
9341 * pungetc() may increment it a few times.
9342 * Assuming it won't increment it to less than -90.
9344 if (g_parsefile->left_in_line < -90 || g_parsefile->buf == NULL) {
9345 pgetc_debug("preadbuffer PEOF1");
9346 /* even in failure keep left_in_line and next_to_pgetc
9347 * in lock step, for correct multi-layer pungetc.
9348 * left_in_line was decremented before preadbuffer(),
9349 * must inc next_to_pgetc: */
9350 g_parsefile->next_to_pgetc++;
9354 more = g_parsefile->left_in_buffer;
9356 flush_stdout_stderr();
9360 /* don't try reading again */
9361 g_parsefile->left_in_line = -99;
9362 pgetc_debug("preadbuffer PEOF2");
9363 g_parsefile->next_to_pgetc++;
9368 /* Find out where's the end of line.
9369 * Set g_parsefile->left_in_line
9370 * and g_parsefile->left_in_buffer acordingly.
9371 * NUL chars are deleted.
9373 q = g_parsefile->next_to_pgetc;
9381 memmove(q, q + 1, more);
9385 g_parsefile->left_in_line = q - g_parsefile->next_to_pgetc - 1;
9391 g_parsefile->left_in_line = q - g_parsefile->next_to_pgetc - 1;
9392 if (g_parsefile->left_in_line < 0)
9397 g_parsefile->left_in_buffer = more;
9402 out2str(g_parsefile->next_to_pgetc);
9406 pgetc_debug("preadbuffer at %d:%p'%s'",
9407 g_parsefile->left_in_line,
9408 g_parsefile->next_to_pgetc,
9409 g_parsefile->next_to_pgetc);
9410 return signed_char2int(*g_parsefile->next_to_pgetc++);
9413 #define pgetc_as_macro() \
9414 (--g_parsefile->left_in_line >= 0 \
9415 ? signed_char2int(*g_parsefile->next_to_pgetc++) \
9422 pgetc_debug("pgetc_fast at %d:%p'%s'",
9423 g_parsefile->left_in_line,
9424 g_parsefile->next_to_pgetc,
9425 g_parsefile->next_to_pgetc);
9426 return pgetc_as_macro();
9429 #if ENABLE_ASH_OPTIMIZE_FOR_SIZE
9430 #define pgetc_fast() pgetc()
9432 #define pgetc_fast() pgetc_as_macro()
9436 * Same as pgetc(), but ignores PEOA.
9438 #if ENABLE_ASH_ALIAS
9444 pgetc_debug("pgetc_fast at %d:%p'%s'",
9445 g_parsefile->left_in_line,
9446 g_parsefile->next_to_pgetc,
9447 g_parsefile->next_to_pgetc);
9449 } while (c == PEOA);
9453 #define pgetc2() pgetc()
9457 * Read a line from the script.
9460 pfgets(char *line, int len)
9466 while (--nleft > 0) {
9482 * Undo the last call to pgetc. Only one character may be pushed back.
9483 * PEOF may be pushed back.
9488 g_parsefile->left_in_line++;
9489 g_parsefile->next_to_pgetc--;
9490 pgetc_debug("pushed back to %d:%p'%s'",
9491 g_parsefile->left_in_line,
9492 g_parsefile->next_to_pgetc,
9493 g_parsefile->next_to_pgetc);
9497 * To handle the "." command, a stack of input files is used. Pushfile
9498 * adds a new entry to the stack and popfile restores the previous level.
9503 struct parsefile *pf;
9505 pf = ckzalloc(sizeof(*pf));
9506 pf->prev = g_parsefile;
9508 /*pf->strpush = NULL; - ckzalloc did it */
9509 /*pf->basestrpush.prev = NULL;*/
9516 struct parsefile *pf = g_parsefile;
9524 g_parsefile = pf->prev;
9530 * Return to top level.
9535 while (g_parsefile != &basepf)
9540 * Close the file(s) that the shell is reading commands from. Called
9541 * after a fork is done.
9547 if (g_parsefile->fd > 0) {
9548 close(g_parsefile->fd);
9549 g_parsefile->fd = 0;
9554 * Like setinputfile, but takes an open file descriptor. Call this with
9558 setinputfd(int fd, int push)
9560 close_on_exec_on(fd);
9563 g_parsefile->buf = NULL;
9565 g_parsefile->fd = fd;
9566 if (g_parsefile->buf == NULL)
9567 g_parsefile->buf = ckmalloc(IBUFSIZ);
9568 g_parsefile->left_in_buffer = 0;
9569 g_parsefile->left_in_line = 0;
9570 g_parsefile->linno = 1;
9574 * Set the input to take input from a file. If push is set, push the
9575 * old input onto the stack first.
9578 setinputfile(const char *fname, int flags)
9584 fd = open(fname, O_RDONLY);
9586 if (flags & INPUT_NOFILE_OK)
9588 ash_msg_and_raise_error("can't open '%s'", fname);
9591 fd2 = copyfd(fd, 10);
9594 ash_msg_and_raise_error("out of file descriptors");
9597 setinputfd(fd, flags & INPUT_PUSH_FILE);
9604 * Like setinputfile, but takes input from a string.
9607 setinputstring(char *string)
9611 g_parsefile->next_to_pgetc = string;
9612 g_parsefile->left_in_line = strlen(string);
9613 g_parsefile->buf = NULL;
9614 g_parsefile->linno = 1;
9619 /* ============ mail.c
9621 * Routines to check for mail.
9626 #define MAXMBOXES 10
9628 /* times of mailboxes */
9629 static time_t mailtime[MAXMBOXES];
9630 /* Set if MAIL or MAILPATH is changed. */
9631 static smallint mail_var_path_changed;
9634 * Print appropriate message(s) if mail has arrived.
9635 * If mail_var_path_changed is set,
9636 * then the value of MAIL has mail_var_path_changed,
9637 * so we just update the values.
9646 struct stackmark smark;
9649 setstackmark(&smark);
9650 mpath = mpathset() ? mpathval() : mailval();
9651 for (mtp = mailtime; mtp < mailtime + MAXMBOXES; mtp++) {
9652 p = padvance(&mpath, nullstr);
9657 for (q = p; *q; q++)
9663 q[-1] = '\0'; /* delete trailing '/' */
9664 if (stat(p, &statb) < 0) {
9668 if (!mail_var_path_changed && statb.st_mtime != *mtp) {
9671 pathopt ? pathopt : "you have mail"
9674 *mtp = statb.st_mtime;
9676 mail_var_path_changed = 0;
9677 popstackmark(&smark);
9681 changemail(const char *val UNUSED_PARAM)
9683 mail_var_path_changed = 1;
9686 #endif /* ASH_MAIL */
9689 /* ============ ??? */
9692 * Set the shell parameters.
9695 setparam(char **argv)
9701 for (nparam = 0; argv[nparam]; nparam++)
9703 ap = newparam = ckmalloc((nparam + 1) * sizeof(*ap));
9705 *ap++ = ckstrdup(*argv++);
9708 freeparam(&shellparam);
9709 shellparam.malloced = 1;
9710 shellparam.nparam = nparam;
9711 shellparam.p = newparam;
9712 #if ENABLE_ASH_GETOPTS
9713 shellparam.optind = 1;
9714 shellparam.optoff = -1;
9719 * Process shell options. The global variable argptr contains a pointer
9720 * to the argument list; we advance it past the options.
9722 * SUSv3 section 2.8.1 "Consequences of Shell Errors" says:
9723 * For a non-interactive shell, an error condition encountered
9724 * by a special built-in ... shall cause the shell to write a diagnostic message
9725 * to standard error and exit as shown in the following table:
9726 * Error Special Built-In
9728 * Utility syntax error (option or operand error) Shall exit
9730 * However, in bug 1142 (http://busybox.net/bugs/view.php?id=1142)
9731 * we see that bash does not do that (set "finishes" with error code 1 instead,
9732 * and shell continues), and people rely on this behavior!
9734 * set -o barfoo 2>/dev/null
9737 * Oh well. Let's mimic that.
9740 plus_minus_o(char *name, int val)
9745 for (i = 0; i < NOPTS; i++) {
9746 if (strcmp(name, optnames(i)) == 0) {
9751 ash_msg("illegal option %co %s", val ? '-' : '+', name);
9754 for (i = 0; i < NOPTS; i++) {
9756 out1fmt("%-16s%s\n", optnames(i), optlist[i] ? "on" : "off");
9758 out1fmt("set %co %s\n", optlist[i] ? '-' : '+', optnames(i));
9764 setoption(int flag, int val)
9768 for (i = 0; i < NOPTS; i++) {
9769 if (optletters(i) == flag) {
9774 ash_msg_and_raise_error("illegal option %c%c", val ? '-' : '+', flag);
9778 options(int cmdline)
9786 while ((p = *argptr) != NULL) {
9788 if (c != '-' && c != '+')
9791 val = 0; /* val = 0 if c == '+' */
9794 if (p[0] == '\0' || LONE_DASH(p)) {
9796 /* "-" means turn off -x and -v */
9799 /* "--" means reset params */
9800 else if (*argptr == NULL)
9803 break; /* "-" or "--" terminates options */
9806 /* first char was + or - */
9807 while ((c = *p++) != '\0') {
9808 /* bash 3.2 indeed handles -c CMD and +c CMD the same */
9809 if (c == 'c' && cmdline) {
9810 minusc = p; /* command is after shell args */
9811 } else if (c == 'o') {
9812 if (plus_minus_o(*argptr, val)) {
9813 /* it already printed err message */
9814 return 1; /* error */
9818 } else if (cmdline && (c == 'l')) { /* -l or +l == --login */
9820 /* bash does not accept +-login, we also won't */
9821 } else if (cmdline && val && (c == '-')) { /* long options */
9822 if (strcmp(p, "login") == 0)
9834 * The shift builtin command.
9837 shiftcmd(int argc UNUSED_PARAM, char **argv)
9844 n = number(argv[1]);
9845 if (n > shellparam.nparam)
9846 n = 0; /* bash compat, was = shellparam.nparam; */
9848 shellparam.nparam -= n;
9849 for (ap1 = shellparam.p; --n >= 0; ap1++) {
9850 if (shellparam.malloced)
9854 while ((*ap2++ = *ap1++) != NULL)
9856 #if ENABLE_ASH_GETOPTS
9857 shellparam.optind = 1;
9858 shellparam.optoff = -1;
9865 * POSIX requires that 'set' (but not export or readonly) output the
9866 * variables in lexicographic order - by the locale's collating order (sigh).
9867 * Maybe we could keep them in an ordered balanced binary tree
9868 * instead of hashed lists.
9869 * For now just roll 'em through qsort for printing...
9872 showvars(const char *sep_prefix, int on, int off)
9877 ep = listvars(on, off, &epend);
9878 qsort(ep, epend - ep, sizeof(char *), vpcmp);
9880 sep = *sep_prefix ? " " : sep_prefix;
9882 for (; ep < epend; ep++) {
9886 p = strchrnul(*ep, '=');
9889 q = single_quote(++p);
9890 out1fmt("%s%s%.*s%s\n", sep_prefix, sep, (int)(p - *ep), *ep, q);
9896 * The set command builtin.
9899 setcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9904 return showvars(nullstr, 0, VUNSET);
9907 if (!options(0)) { /* if no parse error... */
9910 if (*argptr != NULL) {
9918 #if ENABLE_ASH_RANDOM_SUPPORT
9920 change_random(const char *value)
9922 /* Galois LFSR parameter */
9923 /* Taps at 32 31 29 1: */
9924 enum { MASK = 0x8000000b };
9925 /* Another example - taps at 32 31 30 10: */
9926 /* MASK = 0x00400007 */
9928 if (value == NULL) {
9929 /* "get", generate */
9932 /* LCG has period of 2^32 and alternating lowest bit */
9933 random_LCG = 1664525 * random_LCG + 1013904223;
9934 /* Galois LFSR has period of 2^32-1 = 3 * 5 * 17 * 257 * 65537 */
9935 t = (random_galois_LFSR << 1);
9936 if (random_galois_LFSR < 0) /* if we just shifted 1 out of msb... */
9938 random_galois_LFSR = t;
9939 /* Both are weak, combining them gives better randomness
9940 * and ~2^64 period. & 0x7fff is probably bash compat
9941 * for $RANDOM range. Combining with subtraction is
9942 * just for fun. + and ^ would work equally well. */
9943 t = (t - random_LCG) & 0x7fff;
9944 /* set without recursion */
9945 setvar(vrandom.text, utoa(t), VNOFUNC);
9946 vrandom.flags &= ~VNOFUNC;
9949 random_galois_LFSR = random_LCG = strtoul(value, (char **)NULL, 10);
9954 #if ENABLE_ASH_GETOPTS
9956 getopts(char *optstr, char *optvar, char **optfirst, int *param_optind, int *optoff)
9965 if (*param_optind < 1)
9967 optnext = optfirst + *param_optind - 1;
9969 if (*param_optind <= 1 || *optoff < 0 || (int)strlen(optnext[-1]) < *optoff)
9972 p = optnext[-1] + *optoff;
9973 if (p == NULL || *p == '\0') {
9974 /* Current word is done, advance */
9976 if (p == NULL || *p != '-' || *++p == '\0') {
9983 if (LONE_DASH(p)) /* check for "--" */
9988 for (q = optstr; *q != c;) {
9990 if (optstr[0] == ':') {
9993 err |= setvarsafe("OPTARG", s, 0);
9995 fprintf(stderr, "Illegal option -%c\n", c);
10006 if (*p == '\0' && (p = *optnext) == NULL) {
10007 if (optstr[0] == ':') {
10010 err |= setvarsafe("OPTARG", s, 0);
10013 fprintf(stderr, "No arg for -%c option\n", c);
10014 unsetvar("OPTARG");
10022 err |= setvarsafe("OPTARG", p, 0);
10025 err |= setvarsafe("OPTARG", nullstr, 0);
10027 *optoff = p ? p - *(optnext - 1) : -1;
10028 *param_optind = optnext - optfirst + 1;
10029 fmtstr(s, sizeof(s), "%d", *param_optind);
10030 err |= setvarsafe("OPTIND", s, VNOFUNC);
10033 err |= setvarsafe(optvar, s, 0);
10037 flush_stdout_stderr();
10038 raise_exception(EXERROR);
10044 * The getopts builtin. Shellparam.optnext points to the next argument
10045 * to be processed. Shellparam.optptr points to the next character to
10046 * be processed in the current argument. If shellparam.optnext is NULL,
10047 * then it's the first time getopts has been called.
10050 getoptscmd(int argc, char **argv)
10055 ash_msg_and_raise_error("usage: getopts optstring var [arg]");
10057 optbase = shellparam.p;
10058 if (shellparam.optind > shellparam.nparam + 1) {
10059 shellparam.optind = 1;
10060 shellparam.optoff = -1;
10063 optbase = &argv[3];
10064 if (shellparam.optind > argc - 2) {
10065 shellparam.optind = 1;
10066 shellparam.optoff = -1;
10070 return getopts(argv[1], argv[2], optbase, &shellparam.optind,
10071 &shellparam.optoff);
10073 #endif /* ASH_GETOPTS */
10076 /* ============ Shell parser */
10079 struct heredoc *next; /* next here document in list */
10080 union node *here; /* redirection node */
10081 char *eofmark; /* string indicating end of input */
10082 smallint striptabs; /* if set, strip leading tabs */
10085 static smallint tokpushback; /* last token pushed back */
10086 static smallint parsebackquote; /* nonzero if we are inside backquotes */
10087 static smallint quoteflag; /* set if (part of) last token was quoted */
10088 static token_id_t lasttoken; /* last token read (integer id Txxx) */
10089 static struct heredoc *heredoclist; /* list of here documents to read */
10090 static char *wordtext; /* text of last word returned by readtoken */
10091 static struct nodelist *backquotelist;
10092 static union node *redirnode;
10093 static struct heredoc *heredoc;
10095 * NEOF is returned by parsecmd when it encounters an end of file. It
10096 * must be distinct from NULL, so we use the address of a variable that
10097 * happens to be handy.
10099 #define NEOF ((union node *)&tokpushback)
10101 static void raise_error_syntax(const char *) NORETURN;
10103 raise_error_syntax(const char *msg)
10105 ash_msg_and_raise_error("syntax error: %s", msg);
10110 * Called when an unexpected token is read during the parse. The argument
10111 * is the token that is expected, or -1 if more than one type of token can
10112 * occur at this point.
10114 static void raise_error_unexpected_syntax(int) NORETURN;
10116 raise_error_unexpected_syntax(int token)
10121 l = sprintf(msg, "unexpected %s", tokname(lasttoken));
10123 sprintf(msg + l, " (expecting %s)", tokname(token));
10124 raise_error_syntax(msg);
10128 #define EOFMARKLEN 79
10130 /* parsing is heavily cross-recursive, need these forward decls */
10131 static union node *andor(void);
10132 static union node *pipeline(void);
10133 static union node *parse_command(void);
10134 static void parseheredoc(void);
10135 static char peektoken(void);
10136 static int readtoken(void);
10138 static union node *
10141 union node *n1, *n2, *n3;
10144 checkkwd = CHKNL | CHKKWD | CHKALIAS;
10145 if (nlflag == 2 && peektoken())
10151 if (tok == TBACKGND) {
10152 if (n2->type == NPIPE) {
10153 n2->npipe.pipe_backgnd = 1;
10155 if (n2->type != NREDIR) {
10156 n3 = stzalloc(sizeof(struct nredir));
10158 /*n3->nredir.redirect = NULL; - stzalloc did it */
10161 n2->type = NBACKGND;
10167 n3 = stzalloc(sizeof(struct nbinary));
10169 n3->nbinary.ch1 = n1;
10170 n3->nbinary.ch2 = n2;
10186 checkkwd = CHKNL | CHKKWD | CHKALIAS;
10194 pungetc(); /* push back EOF on input */
10198 raise_error_unexpected_syntax(-1);
10205 static union node *
10208 union node *n1, *n2, *n3;
10216 } else if (t == TOR) {
10222 checkkwd = CHKNL | CHKKWD | CHKALIAS;
10224 n3 = stzalloc(sizeof(struct nbinary));
10226 n3->nbinary.ch1 = n1;
10227 n3->nbinary.ch2 = n2;
10232 static union node *
10235 union node *n1, *n2, *pipenode;
10236 struct nodelist *lp, *prev;
10240 TRACE(("pipeline: entered\n"));
10241 if (readtoken() == TNOT) {
10243 checkkwd = CHKKWD | CHKALIAS;
10246 n1 = parse_command();
10247 if (readtoken() == TPIPE) {
10248 pipenode = stzalloc(sizeof(struct npipe));
10249 pipenode->type = NPIPE;
10250 /*pipenode->npipe.pipe_backgnd = 0; - stzalloc did it */
10251 lp = stzalloc(sizeof(struct nodelist));
10252 pipenode->npipe.cmdlist = lp;
10256 lp = stzalloc(sizeof(struct nodelist));
10257 checkkwd = CHKNL | CHKKWD | CHKALIAS;
10258 lp->n = parse_command();
10260 } while (readtoken() == TPIPE);
10266 n2 = stzalloc(sizeof(struct nnot));
10274 static union node *
10279 n = stzalloc(sizeof(struct narg));
10281 /*n->narg.next = NULL; - stzalloc did it */
10282 n->narg.text = wordtext;
10283 n->narg.backquote = backquotelist;
10288 fixredir(union node *n, const char *text, int err)
10292 TRACE(("Fix redir %s %d\n", text, err));
10294 n->ndup.vname = NULL;
10296 fd = bb_strtou(text, NULL, 10);
10297 if (!errno && fd >= 0)
10298 n->ndup.dupfd = fd;
10299 else if (LONE_DASH(text))
10300 n->ndup.dupfd = -1;
10303 raise_error_syntax("bad fd number");
10304 n->ndup.vname = makename();
10309 * Returns true if the text contains nothing to expand (no dollar signs
10313 noexpand(const char *text)
10319 while ((c = *p++) != '\0') {
10320 if (c == CTLQUOTEMARK)
10324 else if (SIT((signed char)c, BASESYNTAX) == CCTL)
10333 union node *n = redirnode;
10335 if (readtoken() != TWORD)
10336 raise_error_unexpected_syntax(-1);
10337 if (n->type == NHERE) {
10338 struct heredoc *here = heredoc;
10342 if (quoteflag == 0)
10344 TRACE(("Here document %d\n", n->type));
10345 if (!noexpand(wordtext) || (i = strlen(wordtext)) == 0 || i > EOFMARKLEN)
10346 raise_error_syntax("illegal eof marker for << redirection");
10347 rmescapes(wordtext);
10348 here->eofmark = wordtext;
10350 if (heredoclist == NULL)
10351 heredoclist = here;
10353 for (p = heredoclist; p->next; p = p->next)
10357 } else if (n->type == NTOFD || n->type == NFROMFD) {
10358 fixredir(n, wordtext, 0);
10360 n->nfile.fname = makename();
10364 static union node *
10367 union node *args, **app;
10368 union node *n = NULL;
10369 union node *vars, **vpp;
10370 union node **rpp, *redir;
10372 #if ENABLE_ASH_BASH_COMPAT
10373 smallint double_brackets_flag = 0;
10383 savecheckkwd = CHKALIAS;
10386 checkkwd = savecheckkwd;
10389 #if ENABLE_ASH_BASH_COMPAT
10390 case TAND: /* "&&" */
10391 case TOR: /* "||" */
10392 if (!double_brackets_flag) {
10396 wordtext = (char *) (t == TAND ? "-a" : "-o");
10399 n = stzalloc(sizeof(struct narg));
10401 /*n->narg.next = NULL; - stzalloc did it */
10402 n->narg.text = wordtext;
10403 #if ENABLE_ASH_BASH_COMPAT
10404 if (strcmp("[[", wordtext) == 0)
10405 double_brackets_flag = 1;
10406 else if (strcmp("]]", wordtext) == 0)
10407 double_brackets_flag = 0;
10409 n->narg.backquote = backquotelist;
10410 if (savecheckkwd && isassignment(wordtext)) {
10412 vpp = &n->narg.next;
10415 app = &n->narg.next;
10420 *rpp = n = redirnode;
10421 rpp = &n->nfile.next;
10422 parsefname(); /* read name of redirection file */
10425 if (args && app == &args->narg.next
10428 struct builtincmd *bcmd;
10431 /* We have a function */
10432 if (readtoken() != TRP)
10433 raise_error_unexpected_syntax(TRP);
10434 name = n->narg.text;
10435 if (!goodname(name)
10436 || ((bcmd = find_builtin(name)) && IS_BUILTIN_SPECIAL(bcmd))
10438 raise_error_syntax("bad function name");
10441 checkkwd = CHKNL | CHKKWD | CHKALIAS;
10442 n->narg.next = parse_command();
10455 n = stzalloc(sizeof(struct ncmd));
10457 n->ncmd.args = args;
10458 n->ncmd.assign = vars;
10459 n->ncmd.redirect = redir;
10463 static union node *
10464 parse_command(void)
10466 union node *n1, *n2;
10467 union node *ap, **app;
10468 union node *cp, **cpp;
10469 union node *redir, **rpp;
10476 switch (readtoken()) {
10478 raise_error_unexpected_syntax(-1);
10481 n1 = stzalloc(sizeof(struct nif));
10483 n1->nif.test = list(0);
10484 if (readtoken() != TTHEN)
10485 raise_error_unexpected_syntax(TTHEN);
10486 n1->nif.ifpart = list(0);
10488 while (readtoken() == TELIF) {
10489 n2->nif.elsepart = stzalloc(sizeof(struct nif));
10490 n2 = n2->nif.elsepart;
10492 n2->nif.test = list(0);
10493 if (readtoken() != TTHEN)
10494 raise_error_unexpected_syntax(TTHEN);
10495 n2->nif.ifpart = list(0);
10497 if (lasttoken == TELSE)
10498 n2->nif.elsepart = list(0);
10500 n2->nif.elsepart = NULL;
10508 n1 = stzalloc(sizeof(struct nbinary));
10509 n1->type = (lasttoken == TWHILE) ? NWHILE : NUNTIL;
10510 n1->nbinary.ch1 = list(0);
10513 TRACE(("expecting DO got %s %s\n", tokname(got),
10514 got == TWORD ? wordtext : ""));
10515 raise_error_unexpected_syntax(TDO);
10517 n1->nbinary.ch2 = list(0);
10522 if (readtoken() != TWORD || quoteflag || !goodname(wordtext))
10523 raise_error_syntax("bad for loop variable");
10524 n1 = stzalloc(sizeof(struct nfor));
10526 n1->nfor.var = wordtext;
10527 checkkwd = CHKKWD | CHKALIAS;
10528 if (readtoken() == TIN) {
10530 while (readtoken() == TWORD) {
10531 n2 = stzalloc(sizeof(struct narg));
10533 /*n2->narg.next = NULL; - stzalloc did it */
10534 n2->narg.text = wordtext;
10535 n2->narg.backquote = backquotelist;
10537 app = &n2->narg.next;
10540 n1->nfor.args = ap;
10541 if (lasttoken != TNL && lasttoken != TSEMI)
10542 raise_error_unexpected_syntax(-1);
10544 n2 = stzalloc(sizeof(struct narg));
10546 /*n2->narg.next = NULL; - stzalloc did it */
10547 n2->narg.text = (char *)dolatstr;
10548 /*n2->narg.backquote = NULL;*/
10549 n1->nfor.args = n2;
10551 * Newline or semicolon here is optional (but note
10552 * that the original Bourne shell only allowed NL).
10554 if (lasttoken != TNL && lasttoken != TSEMI)
10557 checkkwd = CHKNL | CHKKWD | CHKALIAS;
10558 if (readtoken() != TDO)
10559 raise_error_unexpected_syntax(TDO);
10560 n1->nfor.body = list(0);
10564 n1 = stzalloc(sizeof(struct ncase));
10566 if (readtoken() != TWORD)
10567 raise_error_unexpected_syntax(TWORD);
10568 n1->ncase.expr = n2 = stzalloc(sizeof(struct narg));
10570 /*n2->narg.next = NULL; - stzalloc did it */
10571 n2->narg.text = wordtext;
10572 n2->narg.backquote = backquotelist;
10574 checkkwd = CHKKWD | CHKALIAS;
10575 } while (readtoken() == TNL);
10576 if (lasttoken != TIN)
10577 raise_error_unexpected_syntax(TIN);
10578 cpp = &n1->ncase.cases;
10580 checkkwd = CHKNL | CHKKWD;
10582 while (t != TESAC) {
10583 if (lasttoken == TLP)
10585 *cpp = cp = stzalloc(sizeof(struct nclist));
10587 app = &cp->nclist.pattern;
10589 *app = ap = stzalloc(sizeof(struct narg));
10591 /*ap->narg.next = NULL; - stzalloc did it */
10592 ap->narg.text = wordtext;
10593 ap->narg.backquote = backquotelist;
10594 if (readtoken() != TPIPE)
10596 app = &ap->narg.next;
10599 //ap->narg.next = NULL;
10600 if (lasttoken != TRP)
10601 raise_error_unexpected_syntax(TRP);
10602 cp->nclist.body = list(2);
10604 cpp = &cp->nclist.next;
10606 checkkwd = CHKNL | CHKKWD;
10610 raise_error_unexpected_syntax(TENDCASE);
10617 n1 = stzalloc(sizeof(struct nredir));
10618 n1->type = NSUBSHELL;
10619 n1->nredir.n = list(0);
10620 /*n1->nredir.redirect = NULL; - stzalloc did it */
10630 return simplecmd();
10633 if (readtoken() != t)
10634 raise_error_unexpected_syntax(t);
10637 /* Now check for redirection which may follow command */
10638 checkkwd = CHKKWD | CHKALIAS;
10640 while (readtoken() == TREDIR) {
10641 *rpp = n2 = redirnode;
10642 rpp = &n2->nfile.next;
10648 if (n1->type != NSUBSHELL) {
10649 n2 = stzalloc(sizeof(struct nredir));
10654 n1->nredir.redirect = redir;
10659 #if ENABLE_ASH_BASH_COMPAT
10660 static int decode_dollar_squote(void)
10662 static const char C_escapes[] ALIGN1 = "nrbtfav""x\\01234567";
10668 p = strchr(C_escapes, c);
10673 if ((unsigned char)(c - '0') <= 7) { /* \ooo */
10677 } while ((unsigned char)(c - '0') <= 7 && --cnt);
10679 } else if (c == 'x') { /* \xHH */
10683 } while (isxdigit(c) && --cnt);
10685 if (cnt == 3) { /* \x but next char is "bad" */
10689 } else { /* simple seq like \\ or \t */
10694 c = bb_process_escape_sequence((void*)&p);
10695 } else { /* unrecognized "\z": print both chars unless ' or " */
10696 if (c != '\'' && c != '"') {
10698 c |= 0x100; /* "please encode \, then me" */
10706 * If eofmark is NULL, read a word or a redirection symbol. If eofmark
10707 * is not NULL, read a here document. In the latter case, eofmark is the
10708 * word which marks the end of the document and striptabs is true if
10709 * leading tabs should be stripped from the document. The argument firstc
10710 * is the first character of the input token or document.
10712 * Because C does not have internal subroutines, I have simulated them
10713 * using goto's to implement the subroutine linkage. The following macros
10714 * will run code that appears at the end of readtoken1.
10716 #define CHECKEND() {goto checkend; checkend_return:;}
10717 #define PARSEREDIR() {goto parseredir; parseredir_return:;}
10718 #define PARSESUB() {goto parsesub; parsesub_return:;}
10719 #define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
10720 #define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
10721 #define PARSEARITH() {goto parsearith; parsearith_return:;}
10723 readtoken1(int firstc, int syntax, char *eofmark, int striptabs)
10725 /* NB: syntax parameter fits into smallint */
10729 char line[EOFMARKLEN + 1];
10730 struct nodelist *bqlist;
10734 smallint prevsyntax; /* syntax before arithmetic */
10735 #if ENABLE_ASH_EXPAND_PRMT
10736 smallint pssyntax; /* we are expanding a prompt string */
10738 int varnest; /* levels of variables expansion */
10739 int arinest; /* levels of arithmetic expansion */
10740 int parenlevel; /* levels of parens in arithmetic */
10741 int dqvarnest; /* levels of variables expansion within double quotes */
10743 USE_ASH_BASH_COMPAT(smallint bash_dollar_squote = 0;)
10746 /* Avoid longjmp clobbering */
10752 (void) &parenlevel;
10755 (void) &prevsyntax;
10758 startlinno = g_parsefile->linno;
10763 #if ENABLE_ASH_EXPAND_PRMT
10764 pssyntax = (syntax == PSSYNTAX);
10768 dblquote = (syntax == DQSYNTAX);
10774 STARTSTACKSTR(out);
10776 /* For each line, until end of word */
10778 CHECKEND(); /* set c to PEOF if at end of here document */
10779 for (;;) { /* until end of line or end of word */
10780 CHECKSTRSPACE(4, out); /* permit 4 calls to USTPUTC */
10781 switch (SIT(c, syntax)) {
10782 case CNL: /* '\n' */
10783 if (syntax == BASESYNTAX)
10784 goto endword; /* exit outer loop */
10786 g_parsefile->linno++;
10790 goto loop; /* continue outer loop */
10795 if (eofmark == NULL || dblquote)
10796 USTPUTC(CTLESC, out);
10797 #if ENABLE_ASH_BASH_COMPAT
10798 if (c == '\\' && bash_dollar_squote) {
10799 c = decode_dollar_squote();
10801 USTPUTC('\\', out);
10802 c = (unsigned char)c;
10808 case CBACK: /* backslash */
10811 USTPUTC(CTLESC, out);
10812 USTPUTC('\\', out);
10814 } else if (c == '\n') {
10818 #if ENABLE_ASH_EXPAND_PRMT
10819 if (c == '$' && pssyntax) {
10820 USTPUTC(CTLESC, out);
10821 USTPUTC('\\', out);
10824 if (dblquote && c != '\\'
10825 && c != '`' && c != '$'
10826 && (c != '"' || eofmark != NULL)
10828 USTPUTC(CTLESC, out);
10829 USTPUTC('\\', out);
10831 if (SIT(c, SQSYNTAX) == CCTL)
10832 USTPUTC(CTLESC, out);
10840 if (eofmark == NULL) {
10841 USTPUTC(CTLQUOTEMARK, out);
10849 USE_ASH_BASH_COMPAT(bash_dollar_squote = 0;)
10850 if (eofmark != NULL && arinest == 0
10855 if (dqvarnest == 0) {
10856 syntax = BASESYNTAX;
10863 case CVAR: /* '$' */
10864 PARSESUB(); /* parse substitution */
10866 case CENDVAR: /* '}' */
10869 if (dqvarnest > 0) {
10872 USTPUTC(CTLENDVAR, out);
10877 #if ENABLE_ASH_MATH_SUPPORT
10878 case CLP: /* '(' in arithmetic */
10882 case CRP: /* ')' in arithmetic */
10883 if (parenlevel > 0) {
10887 if (pgetc() == ')') {
10888 if (--arinest == 0) {
10889 USTPUTC(CTLENDARI, out);
10890 syntax = prevsyntax;
10891 dblquote = (syntax == DQSYNTAX);
10896 * unbalanced parens
10897 * (don't 2nd guess - no error)
10905 case CBQUOTE: /* '`' */
10909 goto endword; /* exit outer loop */
10913 if (varnest == 0) {
10914 #if ENABLE_ASH_BASH_COMPAT
10916 if (pgetc() == '>')
10917 c = 0x100 + '>'; /* flag &> */
10921 goto endword; /* exit outer loop */
10923 #if ENABLE_ASH_ALIAS
10933 #if ENABLE_ASH_MATH_SUPPORT
10934 if (syntax == ARISYNTAX)
10935 raise_error_syntax("missing '))'");
10937 if (syntax != BASESYNTAX && !parsebackquote && eofmark == NULL)
10938 raise_error_syntax("unterminated quoted string");
10939 if (varnest != 0) {
10940 startlinno = g_parsefile->linno;
10942 raise_error_syntax("missing '}'");
10944 USTPUTC('\0', out);
10945 len = out - (char *)stackblock();
10946 out = stackblock();
10947 if (eofmark == NULL) {
10948 if ((c == '>' || c == '<' USE_ASH_BASH_COMPAT( || c == 0x100 + '>'))
10951 if (isdigit_str9(out)) {
10952 PARSEREDIR(); /* passed as params: out, c */
10953 lasttoken = TREDIR;
10956 /* else: non-number X seen, interpret it
10957 * as "NNNX>file" = "NNNX >file" */
10961 quoteflag = quotef;
10962 backquotelist = bqlist;
10963 grabstackblock(len);
10967 /* end of readtoken routine */
10970 * Check to see whether we are at the end of the here document. When this
10971 * is called, c is set to the first character of the next input line. If
10972 * we are at the end of the here document, this routine sets the c to PEOF.
10976 #if ENABLE_ASH_ALIAS
10982 while (c == '\t') {
10986 if (c == *eofmark) {
10987 if (pfgets(line, sizeof(line)) != NULL) {
10991 for (q = eofmark + 1; *q && *p == *q; p++, q++)
10993 if (*p == '\n' && *q == '\0') {
10995 g_parsefile->linno++;
10996 needprompt = doprompt;
10998 pushstring(line, NULL);
11003 goto checkend_return;
11007 * Parse a redirection operator. The variable "out" points to a string
11008 * specifying the fd to be redirected. The variable "c" contains the
11009 * first character of the redirection operator.
11012 /* out is already checked to be a valid number or "" */
11013 int fd = (*out == '\0' ? -1 : atoi(out));
11016 np = stzalloc(sizeof(struct nfile));
11021 np->type = NAPPEND;
11023 np->type = NCLOBBER;
11026 /* it also can be NTO2 (>&file), but we can't figure it out yet */
11032 #if ENABLE_ASH_BASH_COMPAT
11033 else if (c == 0x100 + '>') { /* this flags &> redirection */
11035 pgetc(); /* this is '>', no need to check */
11039 else { /* c == '<' */
11040 /*np->nfile.fd = 0; - stzalloc did it */
11044 if (sizeof(struct nfile) != sizeof(struct nhere)) {
11045 np = stzalloc(sizeof(struct nhere));
11046 /*np->nfile.fd = 0; - stzalloc did it */
11049 heredoc = stzalloc(sizeof(struct heredoc));
11050 heredoc->here = np;
11053 heredoc->striptabs = 1;
11055 /*heredoc->striptabs = 0; - stzalloc did it */
11061 np->type = NFROMFD;
11065 np->type = NFROMTO;
11077 goto parseredir_return;
11081 * Parse a substitution. At this point, we have read the dollar sign
11082 * and nothing else.
11085 /* is_special(c) evaluates to 1 for c in "!#$*-0123456789?@"; 0 otherwise
11086 * (assuming ascii char codes, as the original implementation did) */
11087 #define is_special(c) \
11088 (((unsigned)(c) - 33 < 32) \
11089 && ((0xc1ff920dU >> ((unsigned)(c) - 33)) & 1))
11095 static const char types[] ALIGN1 = "}-+?=";
11098 if (c <= PEOA_OR_PEOF
11099 || (c != '(' && c != '{' && !is_name(c) && !is_special(c))
11101 #if ENABLE_ASH_BASH_COMPAT
11103 bash_dollar_squote = 1;
11108 } else if (c == '(') { /* $(command) or $((arith)) */
11109 if (pgetc() == '(') {
11110 #if ENABLE_ASH_MATH_SUPPORT
11113 raise_error_syntax("you disabled math support for $((arith)) syntax");
11120 USTPUTC(CTLVAR, out);
11121 typeloc = out - (char *)stackblock();
11122 USTPUTC(VSNORMAL, out);
11123 subtype = VSNORMAL;
11131 subtype = VSLENGTH;
11135 if (c > PEOA_OR_PEOF && is_name(c)) {
11139 } while (c > PEOA_OR_PEOF && is_in_name(c));
11140 } else if (isdigit(c)) {
11144 } while (isdigit(c));
11145 } else if (is_special(c)) {
11150 raise_error_syntax("bad substitution");
11155 if (subtype == 0) {
11159 #if ENABLE_ASH_BASH_COMPAT
11160 if (c == ':' || c == '$' || isdigit(c)) {
11162 subtype = VSSUBSTR;
11169 p = strchr(types, c);
11172 subtype = p - types + VSNORMAL;
11177 subtype = c == '#' ? VSTRIMLEFT : VSTRIMRIGHT;
11185 #if ENABLE_ASH_BASH_COMPAT
11187 subtype = VSREPLACE;
11190 subtype++; /* VSREPLACEALL */
11199 if (dblquote || arinest)
11201 *((char *)stackblock() + typeloc) = subtype | flags;
11202 if (subtype != VSNORMAL) {
11204 if (dblquote || arinest) {
11209 goto parsesub_return;
11213 * Called to parse command substitutions. Newstyle is set if the command
11214 * is enclosed inside $(...); nlpp is a pointer to the head of the linked
11215 * list of commands (passed by reference), and savelen is the number of
11216 * characters on the top of the stack which must be preserved.
11219 struct nodelist **nlpp;
11222 char *volatile str;
11223 struct jmploc jmploc;
11224 struct jmploc *volatile savehandler;
11226 smallint saveprompt = 0;
11229 (void) &saveprompt;
11231 savepbq = parsebackquote;
11232 if (setjmp(jmploc.loc)) {
11234 parsebackquote = 0;
11235 exception_handler = savehandler;
11236 longjmp(exception_handler->loc, 1);
11240 savelen = out - (char *)stackblock();
11242 str = ckmalloc(savelen);
11243 memcpy(str, stackblock(), savelen);
11245 savehandler = exception_handler;
11246 exception_handler = &jmploc;
11249 /* We must read until the closing backquote, giving special
11250 treatment to some slashes, and then push the string and
11251 reread it as input, interpreting it normally. */
11258 STARTSTACKSTR(pout);
11271 g_parsefile->linno++;
11275 * If eating a newline, avoid putting
11276 * the newline into the new character
11277 * stream (via the STPUTC after the
11282 if (pc != '\\' && pc != '`' && pc != '$'
11283 && (!dblquote || pc != '"'))
11284 STPUTC('\\', pout);
11285 if (pc > PEOA_OR_PEOF) {
11291 #if ENABLE_ASH_ALIAS
11294 startlinno = g_parsefile->linno;
11295 raise_error_syntax("EOF in backquote substitution");
11298 g_parsefile->linno++;
11299 needprompt = doprompt;
11308 STPUTC('\0', pout);
11309 psavelen = pout - (char *)stackblock();
11310 if (psavelen > 0) {
11311 pstr = grabstackstr(pout);
11312 setinputstring(pstr);
11317 nlpp = &(*nlpp)->next;
11318 *nlpp = stzalloc(sizeof(**nlpp));
11319 /* (*nlpp)->next = NULL; - stzalloc did it */
11320 parsebackquote = oldstyle;
11323 saveprompt = doprompt;
11330 doprompt = saveprompt;
11331 else if (readtoken() != TRP)
11332 raise_error_unexpected_syntax(TRP);
11337 * Start reading from old file again, ignoring any pushed back
11338 * tokens left from the backquote parsing
11343 while (stackblocksize() <= savelen)
11345 STARTSTACKSTR(out);
11347 memcpy(out, str, savelen);
11348 STADJUST(savelen, out);
11354 parsebackquote = savepbq;
11355 exception_handler = savehandler;
11356 if (arinest || dblquote)
11357 USTPUTC(CTLBACKQ | CTLQUOTE, out);
11359 USTPUTC(CTLBACKQ, out);
11361 goto parsebackq_oldreturn;
11362 goto parsebackq_newreturn;
11365 #if ENABLE_ASH_MATH_SUPPORT
11367 * Parse an arithmetic expansion (indicate start of one and set state)
11370 if (++arinest == 1) {
11371 prevsyntax = syntax;
11372 syntax = ARISYNTAX;
11373 USTPUTC(CTLARI, out);
11380 * we collapse embedded arithmetic expansion to
11381 * parenthesis, which should be equivalent
11385 goto parsearith_return;
11389 } /* end of readtoken */
11392 * Read the next input token.
11393 * If the token is a word, we set backquotelist to the list of cmds in
11394 * backquotes. We set quoteflag to true if any part of the word was
11396 * If the token is TREDIR, then we set redirnode to a structure containing
11398 * In all cases, the variable startlinno is set to the number of the line
11399 * on which the token starts.
11401 * [Change comment: here documents and internal procedures]
11402 * [Readtoken shouldn't have any arguments. Perhaps we should make the
11403 * word parsing code into a separate routine. In this case, readtoken
11404 * doesn't need to have any internal procedures, but parseword does.
11405 * We could also make parseoperator in essence the main routine, and
11406 * have parseword (readtoken1?) handle both words and redirection.]
11408 #define NEW_xxreadtoken
11409 #ifdef NEW_xxreadtoken
11410 /* singles must be first! */
11411 static const char xxreadtoken_chars[7] ALIGN1 = {
11412 '\n', '(', ')', /* singles */
11413 '&', '|', ';', /* doubles */
11417 #define xxreadtoken_singles 3
11418 #define xxreadtoken_doubles 3
11420 static const char xxreadtoken_tokens[] ALIGN1 = {
11421 TNL, TLP, TRP, /* only single occurrence allowed */
11422 TBACKGND, TPIPE, TSEMI, /* if single occurrence */
11423 TEOF, /* corresponds to trailing nul */
11424 TAND, TOR, TENDCASE /* if double occurrence */
11439 startlinno = g_parsefile->linno;
11440 for (;;) { /* until token or start of word found */
11442 if (c == ' ' || c == '\t' USE_ASH_ALIAS( || c == PEOA))
11446 while ((c = pgetc()) != '\n' && c != PEOF)
11449 } else if (c == '\\') {
11450 if (pgetc() != '\n') {
11452 break; /* return readtoken1(...) */
11454 startlinno = ++g_parsefile->linno;
11460 p = xxreadtoken_chars + sizeof(xxreadtoken_chars) - 1;
11463 g_parsefile->linno++;
11464 needprompt = doprompt;
11467 p = strchr(xxreadtoken_chars, c);
11469 break; /* return readtoken1(...) */
11471 if ((int)(p - xxreadtoken_chars) >= xxreadtoken_singles) {
11473 if (cc == c) { /* double occurrence? */
11474 p += xxreadtoken_doubles + 1;
11477 #if ENABLE_ASH_BASH_COMPAT
11478 if (c == '&' && cc == '>') /* &> */
11479 break; /* return readtoken1(...) */
11484 lasttoken = xxreadtoken_tokens[p - xxreadtoken_chars];
11489 return readtoken1(c, BASESYNTAX, (char *) NULL, 0);
11491 #else /* old xxreadtoken */
11492 #define RETURN(token) return lasttoken = token
11505 startlinno = g_parsefile->linno;
11506 for (;;) { /* until token or start of word found */
11509 case ' ': case '\t':
11510 #if ENABLE_ASH_ALIAS
11515 while ((c = pgetc()) != '\n' && c != PEOF)
11520 if (pgetc() == '\n') {
11521 startlinno = ++g_parsefile->linno;
11529 g_parsefile->linno++;
11530 needprompt = doprompt;
11535 if (pgetc() == '&')
11540 if (pgetc() == '|')
11545 if (pgetc() == ';')
11558 return readtoken1(c, BASESYNTAX, (char *)NULL, 0);
11561 #endif /* old xxreadtoken */
11568 smallint alreadyseen = tokpushback;
11571 #if ENABLE_ASH_ALIAS
11580 if (checkkwd & CHKNL) {
11587 if (t != TWORD || quoteflag) {
11592 * check for keywords
11594 if (checkkwd & CHKKWD) {
11595 const char *const *pp;
11597 pp = findkwd(wordtext);
11599 lasttoken = t = pp - tokname_array;
11600 TRACE(("keyword %s recognized\n", tokname(t)));
11605 if (checkkwd & CHKALIAS) {
11606 #if ENABLE_ASH_ALIAS
11608 ap = lookupalias(wordtext, 1);
11611 pushstring(ap->val, ap);
11621 TRACE(("token %s %s\n", tokname(t), t == TWORD ? wordtext : ""));
11623 TRACE(("reread token %s %s\n", tokname(t), t == TWORD ? wordtext : ""));
11635 return tokname_array[t][0];
11639 * Read and parse a command. Returns NEOF on end of file. (NULL is a
11640 * valid parse tree indicating a blank line.)
11642 static union node *
11643 parsecmd(int interact)
11648 doprompt = interact;
11650 setprompt(doprompt);
11662 * Input any here documents.
11667 struct heredoc *here;
11670 here = heredoclist;
11671 heredoclist = NULL;
11677 readtoken1(pgetc(), here->here->type == NHERE? SQSYNTAX : DQSYNTAX,
11678 here->eofmark, here->striptabs);
11679 n = stzalloc(sizeof(struct narg));
11680 n->narg.type = NARG;
11681 /*n->narg.next = NULL; - stzalloc did it */
11682 n->narg.text = wordtext;
11683 n->narg.backquote = backquotelist;
11684 here->here->nhere.doc = n;
11691 * called by editline -- any expansions to the prompt should be added here.
11693 #if ENABLE_ASH_EXPAND_PRMT
11694 static const char *
11695 expandstr(const char *ps)
11699 /* XXX Fix (char *) cast. It _is_ a bug. ps is variable's value,
11700 * and token processing _can_ alter it (delete NULs etc). */
11701 setinputstring((char *)ps);
11702 readtoken1(pgetc(), PSSYNTAX, nullstr, 0);
11705 n.narg.type = NARG;
11706 n.narg.next = NULL;
11707 n.narg.text = wordtext;
11708 n.narg.backquote = backquotelist;
11710 expandarg(&n, NULL, 0);
11711 return stackblock();
11716 * Execute a command or commands contained in a string.
11719 evalstring(char *s, int mask)
11722 struct stackmark smark;
11726 setstackmark(&smark);
11729 while ((n = parsecmd(0)) != NEOF) {
11731 popstackmark(&smark);
11744 * The eval command.
11747 evalcmd(int argc UNUSED_PARAM, char **argv)
11756 STARTSTACKSTR(concat);
11758 concat = stack_putstr(p, concat);
11762 STPUTC(' ', concat);
11764 STPUTC('\0', concat);
11765 p = grabstackstr(concat);
11767 evalstring(p, ~SKIPEVAL);
11774 * Read and execute commands. "Top" is nonzero for the top level command
11775 * loop; it turns on prompting if the shell is interactive.
11781 struct stackmark smark;
11785 TRACE(("cmdloop(%d) called\n", top));
11789 setstackmark(&smark);
11792 showjobs(stderr, SHOW_CHANGED);
11795 if (iflag && top) {
11797 #if ENABLE_ASH_MAIL
11801 n = parsecmd(inter);
11802 /* showtree(n); DEBUG */
11804 if (!top || numeof >= 50)
11806 if (!stoppedjobs()) {
11809 out2str("\nUse \"exit\" to leave shell.\n");
11812 } else if (nflag == 0) {
11813 /* job_warning can only be 2,1,0. Here 2->1, 1/0->0 */
11818 popstackmark(&smark);
11823 return skip & SKIPEVAL;
11830 * Take commands from a file. To be compatible we should do a path
11831 * search for the file, which is necessary to find sub-commands.
11834 find_dot_file(char *name)
11837 const char *path = pathval();
11840 /* don't try this for absolute or relative paths */
11841 if (strchr(name, '/'))
11844 /* IIRC standards do not say whether . is to be searched.
11845 * And it is even smaller this way, making it unconditional for now:
11847 if (1) { /* ENABLE_ASH_BASH_COMPAT */
11852 while ((fullname = padvance(&path, name)) != NULL) {
11854 if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) {
11856 * Don't bother freeing here, since it will
11857 * be freed by the caller.
11861 stunalloc(fullname);
11864 /* not found in the PATH */
11865 ash_msg_and_raise_error("%s: not found", name);
11870 dotcmd(int argc, char **argv)
11872 struct strlist *sp;
11873 volatile struct shparam saveparam;
11876 for (sp = cmdenviron; sp; sp = sp->next)
11877 setvareq(ckstrdup(sp->text), VSTRFIXED | VTEXTFIXED);
11879 if (argv[1]) { /* That's what SVR2 does */
11880 char *fullname = find_dot_file(argv[1]);
11883 if (argc) { /* argc > 0, argv[0] != NULL */
11884 saveparam = shellparam;
11885 shellparam.malloced = 0;
11886 shellparam.nparam = argc;
11887 shellparam.p = argv;
11890 setinputfile(fullname, INPUT_PUSH_FILE);
11891 commandname = fullname;
11896 freeparam(&shellparam);
11897 shellparam = saveparam;
11899 status = exitstatus;
11905 exitcmd(int argc UNUSED_PARAM, char **argv)
11910 exitstatus = number(argv[1]);
11911 raise_exception(EXEXIT);
11916 * Read a file containing shell functions.
11919 readcmdfile(char *name)
11921 setinputfile(name, INPUT_PUSH_FILE);
11927 /* ============ find_command inplementation */
11930 * Resolve a command name. If you change this routine, you may have to
11931 * change the shellexec routine as well.
11934 find_command(char *name, struct cmdentry *entry, int act, const char *path)
11936 struct tblentry *cmdp;
11943 struct builtincmd *bcmd;
11945 /* If name contains a slash, don't use PATH or hash table */
11946 if (strchr(name, '/') != NULL) {
11947 entry->u.index = -1;
11948 if (act & DO_ABS) {
11949 while (stat(name, &statb) < 0) {
11951 if (errno == EINTR)
11954 entry->cmdtype = CMDUNKNOWN;
11958 entry->cmdtype = CMDNORMAL;
11962 /* #if ENABLE_FEATURE_SH_STANDALONE... moved after builtin check */
11964 updatetbl = (path == pathval());
11967 if (strstr(path, "%builtin") != NULL)
11968 act |= DO_ALTBLTIN;
11971 /* If name is in the table, check answer will be ok */
11972 cmdp = cmdlookup(name, 0);
11973 if (cmdp != NULL) {
11976 switch (cmdp->cmdtype) {
11994 } else if (cmdp->rehash == 0)
11995 /* if not invalidated by cd, we're done */
11999 /* If %builtin not in path, check for builtin next */
12000 bcmd = find_builtin(name);
12002 if (IS_BUILTIN_REGULAR(bcmd))
12003 goto builtin_success;
12004 if (act & DO_ALTPATH) {
12005 if (!(act & DO_ALTBLTIN))
12006 goto builtin_success;
12007 } else if (builtinloc <= 0) {
12008 goto builtin_success;
12012 #if ENABLE_FEATURE_SH_STANDALONE
12014 int applet_no = find_applet_by_name(name);
12015 if (applet_no >= 0) {
12016 entry->cmdtype = CMDNORMAL;
12017 entry->u.index = -2 - applet_no;
12023 /* We have to search path. */
12024 prev = -1; /* where to start */
12025 if (cmdp && cmdp->rehash) { /* doing a rehash */
12026 if (cmdp->cmdtype == CMDBUILTIN)
12029 prev = cmdp->param.index;
12035 while ((fullname = padvance(&path, name)) != NULL) {
12036 stunalloc(fullname);
12037 /* NB: code below will still use fullname
12038 * despite it being "unallocated" */
12041 if (prefix(pathopt, "builtin")) {
12043 goto builtin_success;
12046 if ((act & DO_NOFUNC)
12047 || !prefix(pathopt, "func")
12048 ) { /* ignore unimplemented options */
12052 /* if rehash, don't redo absolute path names */
12053 if (fullname[0] == '/' && idx <= prev) {
12056 TRACE(("searchexec \"%s\": no change\n", name));
12059 while (stat(fullname, &statb) < 0) {
12061 if (errno == EINTR)
12064 if (errno != ENOENT && errno != ENOTDIR)
12068 e = EACCES; /* if we fail, this will be the error */
12069 if (!S_ISREG(statb.st_mode))
12071 if (pathopt) { /* this is a %func directory */
12072 stalloc(strlen(fullname) + 1);
12073 /* NB: stalloc will return space pointed by fullname
12074 * (because we don't have any intervening allocations
12075 * between stunalloc above and this stalloc) */
12076 readcmdfile(fullname);
12077 cmdp = cmdlookup(name, 0);
12078 if (cmdp == NULL || cmdp->cmdtype != CMDFUNCTION)
12079 ash_msg_and_raise_error("%s not defined in %s", name, fullname);
12080 stunalloc(fullname);
12083 TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
12085 entry->cmdtype = CMDNORMAL;
12086 entry->u.index = idx;
12090 cmdp = cmdlookup(name, 1);
12091 cmdp->cmdtype = CMDNORMAL;
12092 cmdp->param.index = idx;
12097 /* We failed. If there was an entry for this command, delete it */
12098 if (cmdp && updatetbl)
12099 delete_cmd_entry();
12101 ash_msg("%s: %s", name, errmsg(e, "not found"));
12102 entry->cmdtype = CMDUNKNOWN;
12107 entry->cmdtype = CMDBUILTIN;
12108 entry->u.cmd = bcmd;
12112 cmdp = cmdlookup(name, 1);
12113 cmdp->cmdtype = CMDBUILTIN;
12114 cmdp->param.cmd = bcmd;
12118 entry->cmdtype = cmdp->cmdtype;
12119 entry->u = cmdp->param;
12123 /* ============ trap.c */
12126 * The trap builtin.
12129 trapcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
12138 for (signo = 0; signo < NSIG; signo++) {
12139 if (trap[signo] != NULL) {
12140 out1fmt("trap -- %s %s\n",
12141 single_quote(trap[signo]),
12142 get_signame(signo));
12151 signo = get_signum(*ap);
12153 ash_msg_and_raise_error("%s: bad trap", *ap);
12156 if (LONE_DASH(action))
12159 action = ckstrdup(action);
12162 trap[signo] = action;
12172 /* ============ Builtins */
12174 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
12176 * Lists available builtins
12179 helpcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
12184 out1fmt("\nBuilt-in commands:\n-------------------\n");
12185 for (col = 0, i = 0; i < ARRAY_SIZE(builtintab); i++) {
12186 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '),
12187 builtintab[i].name + 1);
12193 #if ENABLE_FEATURE_SH_STANDALONE
12195 const char *a = applet_names;
12197 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '), a);
12202 a += strlen(a) + 1;
12207 return EXIT_SUCCESS;
12209 #endif /* FEATURE_SH_EXTRA_QUIET */
12212 * The export and readonly commands.
12215 exportcmd(int argc UNUSED_PARAM, char **argv)
12221 int flag = argv[0][0] == 'r' ? VREADONLY : VEXPORT;
12223 if (nextopt("p") != 'p') {
12228 p = strchr(name, '=');
12232 vp = *findvar(hashvar(name), name);
12238 setvar(name, p, flag);
12239 } while ((name = *++aptr) != NULL);
12243 showvars(argv[0], flag, 0);
12248 * Delete a function if it exists.
12251 unsetfunc(const char *name)
12253 struct tblentry *cmdp;
12255 cmdp = cmdlookup(name, 0);
12256 if (cmdp!= NULL && cmdp->cmdtype == CMDFUNCTION)
12257 delete_cmd_entry();
12261 * The unset builtin command. We unset the function before we unset the
12262 * variable to allow a function to be unset when there is a readonly variable
12263 * with the same name.
12266 unsetcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
12273 while ((i = nextopt("vf")) != '\0') {
12277 for (ap = argptr; *ap; ap++) {
12293 #include <sys/times.h>
12295 static const unsigned char timescmd_str[] ALIGN1 = {
12296 ' ', offsetof(struct tms, tms_utime),
12297 '\n', offsetof(struct tms, tms_stime),
12298 ' ', offsetof(struct tms, tms_cutime),
12299 '\n', offsetof(struct tms, tms_cstime),
12304 timescmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
12306 long clk_tck, s, t;
12307 const unsigned char *p;
12310 clk_tck = sysconf(_SC_CLK_TCK);
12315 t = *(clock_t *)(((char *) &buf) + p[1]);
12317 out1fmt("%ldm%ld.%.3lds%c",
12319 ((t - s * clk_tck) * 1000) / clk_tck,
12321 } while (*(p += 2));
12326 #if ENABLE_ASH_MATH_SUPPORT
12328 dash_arith(const char *s)
12334 result = arith(s, &errcode);
12337 ash_msg_and_raise_error("exponent less than 0");
12339 ash_msg_and_raise_error("divide by zero");
12341 ash_msg_and_raise_error("expression recursion loop detected");
12342 raise_error_syntax(s);
12350 * The let builtin. partial stolen from GNU Bash, the Bourne Again SHell.
12351 * Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
12353 * Copyright (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
12356 letcmd(int argc UNUSED_PARAM, char **argv)
12362 ash_msg_and_raise_error("expression expected");
12364 i = dash_arith(*argv);
12369 #endif /* ASH_MATH_SUPPORT */
12372 /* ============ miscbltin.c
12374 * Miscellaneous builtins.
12379 #if defined(__GLIBC__) && __GLIBC__ == 2 && __GLIBC_MINOR__ < 1
12380 typedef enum __rlimit_resource rlim_t;
12384 * The read builtin. Options:
12385 * -r Do not interpret '\' specially
12386 * -s Turn off echo (tty only)
12387 * -n NCHARS Read NCHARS max
12388 * -p PROMPT Display PROMPT on stderr (if input is from tty)
12389 * -t SECONDS Timeout after SECONDS (tty or pipe only)
12390 * -u FD Read from given FD instead of fd 0
12391 * This uses unbuffered input, which may be avoidable in some cases.
12392 * TODO: bash also has:
12393 * -a ARRAY Read into array[0],[1],etc
12394 * -d DELIM End on DELIM char, not newline
12395 * -e Use line editing (tty only)
12398 readcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
12400 static const char *const arg_REPLY[] = { "REPLY", NULL };
12413 #if ENABLE_ASH_READ_NCHARS
12414 int nchars = 0; /* if != 0, -n is in effect */
12416 struct termios tty, old_tty;
12418 #if ENABLE_ASH_READ_TIMEOUT
12419 unsigned end_ms = 0;
12420 unsigned timeout = 0;
12425 while ((i = nextopt("p:u:r"
12426 USE_ASH_READ_TIMEOUT("t:")
12427 USE_ASH_READ_NCHARS("n:s")
12431 prompt = optionarg;
12433 #if ENABLE_ASH_READ_NCHARS
12435 nchars = bb_strtou(optionarg, NULL, 10);
12436 if (nchars < 0 || errno)
12437 ash_msg_and_raise_error("invalid count");
12438 /* nchars == 0: off (bash 3.2 does this too) */
12444 #if ENABLE_ASH_READ_TIMEOUT
12446 timeout = bb_strtou(optionarg, NULL, 10);
12447 if (errno || timeout > UINT_MAX / 2048)
12448 ash_msg_and_raise_error("invalid timeout");
12450 #if 0 /* even bash have no -t N.NNN support */
12451 ts.tv_sec = bb_strtou(optionarg, &p, 10);
12453 /* EINVAL means number is ok, but not terminated by NUL */
12454 if (*p == '.' && errno == EINVAL) {
12458 ts.tv_usec = bb_strtou(p, &p2, 10);
12460 ash_msg_and_raise_error("invalid timeout");
12462 /* normalize to usec */
12464 ash_msg_and_raise_error("invalid timeout");
12465 while (scale++ < 6)
12468 } else if (ts.tv_sec < 0 || errno) {
12469 ash_msg_and_raise_error("invalid timeout");
12471 if (!(ts.tv_sec | ts.tv_usec)) { /* both are 0? */
12472 ash_msg_and_raise_error("invalid timeout");
12481 fd = bb_strtou(optionarg, NULL, 10);
12482 if (fd < 0 || errno)
12483 ash_msg_and_raise_error("invalid file descriptor");
12489 if (prompt && isatty(fd)) {
12494 ap = (char**)arg_REPLY;
12495 ifs = bltinlookup("IFS");
12498 #if ENABLE_ASH_READ_NCHARS
12499 tcgetattr(fd, &tty);
12501 if (nchars || silent) {
12503 tty.c_lflag &= ~ICANON;
12504 tty.c_cc[VMIN] = nchars < 256 ? nchars : 255;
12507 tty.c_lflag &= ~(ECHO | ECHOK | ECHONL);
12509 /* if tcgetattr failed, tcsetattr will fail too.
12510 * Ignoring, it's harmless. */
12511 tcsetattr(fd, TCSANOW, &tty);
12518 #if ENABLE_ASH_READ_TIMEOUT
12519 if (timeout) /* NB: ensuring end_ms is nonzero */
12520 end_ms = ((unsigned)(monotonic_us() / 1000) + timeout) | 1;
12524 #if ENABLE_ASH_READ_TIMEOUT
12526 struct pollfd pfd[1];
12528 pfd[0].events = POLLIN;
12529 timeout = end_ms - (unsigned)(monotonic_us() / 1000);
12530 if ((int)timeout <= 0 /* already late? */
12531 || safe_poll(pfd, 1, timeout) != 1 /* no? wait... */
12532 ) { /* timed out! */
12533 #if ENABLE_ASH_READ_NCHARS
12534 tcsetattr(fd, TCSANOW, &old_tty);
12540 if (nonblock_safe_read(fd, &c, 1) != 1) {
12552 if (!rflag && c == '\\') {
12558 if (startword && *ifs == ' ' && strchr(ifs, c)) {
12562 if (ap[1] != NULL && strchr(ifs, c) != NULL) {
12564 setvar(*ap, stackblock(), 0);
12573 /* end of do {} while: */
12574 #if ENABLE_ASH_READ_NCHARS
12580 #if ENABLE_ASH_READ_NCHARS
12581 tcsetattr(fd, TCSANOW, &old_tty);
12585 /* Remove trailing blanks */
12586 while ((char *)stackblock() <= --p && strchr(ifs, *p) != NULL)
12588 setvar(*ap, stackblock(), 0);
12589 while (*++ap != NULL)
12590 setvar(*ap, nullstr, 0);
12595 umaskcmd(int argc UNUSED_PARAM, char **argv)
12597 static const char permuser[3] ALIGN1 = "ugo";
12598 static const char permmode[3] ALIGN1 = "rwx";
12599 static const short permmask[] ALIGN2 = {
12600 S_IRUSR, S_IWUSR, S_IXUSR,
12601 S_IRGRP, S_IWGRP, S_IXGRP,
12602 S_IROTH, S_IWOTH, S_IXOTH
12608 int symbolic_mode = 0;
12610 while (nextopt("S") != '\0') {
12621 if (symbolic_mode) {
12625 for (i = 0; i < 3; i++) {
12628 *p++ = permuser[i];
12630 for (j = 0; j < 3; j++) {
12631 if ((mask & permmask[3 * i + j]) == 0) {
12632 *p++ = permmode[j];
12640 out1fmt("%.4o\n", mask);
12643 if (isdigit((unsigned char) *ap)) {
12646 if (*ap >= '8' || *ap < '0')
12647 ash_msg_and_raise_error(illnum, argv[1]);
12648 mask = (mask << 3) + (*ap - '0');
12649 } while (*++ap != '\0');
12652 mask = ~mask & 0777;
12653 if (!bb_parse_mode(ap, &mask)) {
12654 ash_msg_and_raise_error("illegal mode: %s", ap);
12656 umask(~mask & 0777);
12665 * This code, originally by Doug Gwyn, Doug Kingston, Eric Gisin, and
12666 * Michael Rendell was ripped from pdksh 5.0.8 and hacked for use with
12667 * ash by J.T. Conklin.
12673 uint8_t cmd; /* RLIMIT_xxx fit into it */
12674 uint8_t factor_shift; /* shift by to get rlim_{cur,max} values */
12678 static const struct limits limits_tbl[] = {
12680 { RLIMIT_CPU, 0, 't' },
12682 #ifdef RLIMIT_FSIZE
12683 { RLIMIT_FSIZE, 9, 'f' },
12686 { RLIMIT_DATA, 10, 'd' },
12688 #ifdef RLIMIT_STACK
12689 { RLIMIT_STACK, 10, 's' },
12692 { RLIMIT_CORE, 9, 'c' },
12695 { RLIMIT_RSS, 10, 'm' },
12697 #ifdef RLIMIT_MEMLOCK
12698 { RLIMIT_MEMLOCK, 10, 'l' },
12700 #ifdef RLIMIT_NPROC
12701 { RLIMIT_NPROC, 0, 'p' },
12703 #ifdef RLIMIT_NOFILE
12704 { RLIMIT_NOFILE, 0, 'n' },
12707 { RLIMIT_AS, 10, 'v' },
12709 #ifdef RLIMIT_LOCKS
12710 { RLIMIT_LOCKS, 0, 'w' },
12713 static const char limits_name[] =
12715 "time(seconds)" "\0"
12717 #ifdef RLIMIT_FSIZE
12718 "file(blocks)" "\0"
12723 #ifdef RLIMIT_STACK
12727 "coredump(blocks)" "\0"
12732 #ifdef RLIMIT_MEMLOCK
12733 "locked memory(kb)" "\0"
12735 #ifdef RLIMIT_NPROC
12738 #ifdef RLIMIT_NOFILE
12744 #ifdef RLIMIT_LOCKS
12749 enum limtype { SOFT = 0x1, HARD = 0x2 };
12752 printlim(enum limtype how, const struct rlimit *limit,
12753 const struct limits *l)
12757 val = limit->rlim_max;
12759 val = limit->rlim_cur;
12761 if (val == RLIM_INFINITY)
12762 out1fmt("unlimited\n");
12764 val >>= l->factor_shift;
12765 out1fmt("%lld\n", (long long) val);
12770 ulimitcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
12774 enum limtype how = SOFT | HARD;
12775 const struct limits *l;
12778 struct rlimit limit;
12781 while ((optc = nextopt("HSa"
12785 #ifdef RLIMIT_FSIZE
12791 #ifdef RLIMIT_STACK
12800 #ifdef RLIMIT_MEMLOCK
12803 #ifdef RLIMIT_NPROC
12806 #ifdef RLIMIT_NOFILE
12812 #ifdef RLIMIT_LOCKS
12830 for (l = limits_tbl; l->option != what; l++)
12833 set = *argptr ? 1 : 0;
12837 if (all || argptr[1])
12838 ash_msg_and_raise_error("too many arguments");
12839 if (strncmp(p, "unlimited\n", 9) == 0)
12840 val = RLIM_INFINITY;
12844 while ((c = *p++) >= '0' && c <= '9') {
12845 val = (val * 10) + (long)(c - '0');
12846 // val is actually 'unsigned long int' and can't get < 0
12847 if (val < (rlim_t) 0)
12851 ash_msg_and_raise_error("bad number");
12852 val <<= l->factor_shift;
12856 const char *lname = limits_name;
12857 for (l = limits_tbl; l != &limits_tbl[ARRAY_SIZE(limits_tbl)]; l++) {
12858 getrlimit(l->cmd, &limit);
12859 out1fmt("%-20s ", lname);
12860 lname += strlen(lname) + 1;
12861 printlim(how, &limit, l);
12866 getrlimit(l->cmd, &limit);
12869 limit.rlim_max = val;
12871 limit.rlim_cur = val;
12872 if (setrlimit(l->cmd, &limit) < 0)
12873 ash_msg_and_raise_error("error setting limit (%m)");
12875 printlim(how, &limit, l);
12881 /* ============ Math support */
12883 #if ENABLE_ASH_MATH_SUPPORT
12885 /* Copyright (c) 2001 Aaron Lehmann <aaronl@vitelus.com>
12887 Permission is hereby granted, free of charge, to any person obtaining
12888 a copy of this software and associated documentation files (the
12889 "Software"), to deal in the Software without restriction, including
12890 without limitation the rights to use, copy, modify, merge, publish,
12891 distribute, sublicense, and/or sell copies of the Software, and to
12892 permit persons to whom the Software is furnished to do so, subject to
12893 the following conditions:
12895 The above copyright notice and this permission notice shall be
12896 included in all copies or substantial portions of the Software.
12898 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
12899 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
12900 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
12901 IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
12902 CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
12903 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
12904 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
12907 /* This is my infix parser/evaluator. It is optimized for size, intended
12908 * as a replacement for yacc-based parsers. However, it may well be faster
12909 * than a comparable parser written in yacc. The supported operators are
12910 * listed in #defines below. Parens, order of operations, and error handling
12911 * are supported. This code is thread safe. The exact expression format should
12912 * be that which POSIX specifies for shells. */
12914 /* The code uses a simple two-stack algorithm. See
12915 * http://www.onthenet.com.au/~grahamis/int2008/week02/lect02.html
12916 * for a detailed explanation of the infix-to-postfix algorithm on which
12917 * this is based (this code differs in that it applies operators immediately
12918 * to the stack instead of adding them to a queue to end up with an
12921 /* To use the routine, call it with an expression string and error return
12925 * Aug 24, 2001 Manuel Novoa III
12927 * Reduced the generated code size by about 30% (i386) and fixed several bugs.
12929 * 1) In arith_apply():
12930 * a) Cached values of *numptr and &(numptr[-1]).
12931 * b) Removed redundant test for zero denominator.
12934 * a) Eliminated redundant code for processing operator tokens by moving
12935 * to a table-based implementation. Also folded handling of parens
12937 * b) Combined all 3 loops which called arith_apply to reduce generated
12938 * code size at the cost of speed.
12940 * 3) The following expressions were treated as valid by the original code:
12941 * 1() , 0! , 1 ( *3 ) .
12942 * These bugs have been fixed by internally enclosing the expression in
12943 * parens and then checking that all binary ops and right parens are
12944 * preceded by a valid expression (NUM_TOKEN).
12946 * Note: It may be desirable to replace Aaron's test for whitespace with
12947 * ctype's isspace() if it is used by another busybox applet or if additional
12948 * whitespace chars should be considered. Look below the "#include"s for a
12949 * precompiler test.
12953 * Aug 26, 2001 Manuel Novoa III
12955 * Return 0 for null expressions. Pointed out by Vladimir Oleynik.
12957 * Merge in Aaron's comments previously posted to the busybox list,
12958 * modified slightly to take account of my changes to the code.
12963 * (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
12965 * - allow access to variable,
12966 * used recursive find value indirection (c=2*2; a="c"; $((a+=2)) produce 6)
12967 * - realize assign syntax (VAR=expr, +=, *= etc)
12968 * - realize exponentiation (** operator)
12969 * - realize comma separated - expr, expr
12970 * - realise ++expr --expr expr++ expr--
12971 * - realise expr ? expr : expr (but, second expr calculate always)
12972 * - allow hexadecimal and octal numbers
12973 * - was restored loses XOR operator
12974 * - remove one goto label, added three ;-)
12975 * - protect $((num num)) as true zero expr (Manuel`s error)
12976 * - always use special isspace(), see comment from bash ;-)
12979 #define arith_isspace(arithval) \
12980 (arithval == ' ' || arithval == '\n' || arithval == '\t')
12982 typedef unsigned char operator;
12984 /* An operator's token id is a bit of a bitfield. The lower 5 bits are the
12985 * precedence, and 3 high bits are an ID unique across operators of that
12986 * precedence. The ID portion is so that multiple operators can have the
12987 * same precedence, ensuring that the leftmost one is evaluated first.
12988 * Consider * and /. */
12990 #define tok_decl(prec,id) (((id)<<5)|(prec))
12991 #define PREC(op) ((op) & 0x1F)
12993 #define TOK_LPAREN tok_decl(0,0)
12995 #define TOK_COMMA tok_decl(1,0)
12997 #define TOK_ASSIGN tok_decl(2,0)
12998 #define TOK_AND_ASSIGN tok_decl(2,1)
12999 #define TOK_OR_ASSIGN tok_decl(2,2)
13000 #define TOK_XOR_ASSIGN tok_decl(2,3)
13001 #define TOK_PLUS_ASSIGN tok_decl(2,4)
13002 #define TOK_MINUS_ASSIGN tok_decl(2,5)
13003 #define TOK_LSHIFT_ASSIGN tok_decl(2,6)
13004 #define TOK_RSHIFT_ASSIGN tok_decl(2,7)
13006 #define TOK_MUL_ASSIGN tok_decl(3,0)
13007 #define TOK_DIV_ASSIGN tok_decl(3,1)
13008 #define TOK_REM_ASSIGN tok_decl(3,2)
13010 /* all assign is right associativity and precedence eq, but (7+3)<<5 > 256 */
13011 #define convert_prec_is_assing(prec) do { if (prec == 3) prec = 2; } while (0)
13013 /* conditional is right associativity too */
13014 #define TOK_CONDITIONAL tok_decl(4,0)
13015 #define TOK_CONDITIONAL_SEP tok_decl(4,1)
13017 #define TOK_OR tok_decl(5,0)
13019 #define TOK_AND tok_decl(6,0)
13021 #define TOK_BOR tok_decl(7,0)
13023 #define TOK_BXOR tok_decl(8,0)
13025 #define TOK_BAND tok_decl(9,0)
13027 #define TOK_EQ tok_decl(10,0)
13028 #define TOK_NE tok_decl(10,1)
13030 #define TOK_LT tok_decl(11,0)
13031 #define TOK_GT tok_decl(11,1)
13032 #define TOK_GE tok_decl(11,2)
13033 #define TOK_LE tok_decl(11,3)
13035 #define TOK_LSHIFT tok_decl(12,0)
13036 #define TOK_RSHIFT tok_decl(12,1)
13038 #define TOK_ADD tok_decl(13,0)
13039 #define TOK_SUB tok_decl(13,1)
13041 #define TOK_MUL tok_decl(14,0)
13042 #define TOK_DIV tok_decl(14,1)
13043 #define TOK_REM tok_decl(14,2)
13045 /* exponent is right associativity */
13046 #define TOK_EXPONENT tok_decl(15,1)
13048 /* For now unary operators. */
13049 #define UNARYPREC 16
13050 #define TOK_BNOT tok_decl(UNARYPREC,0)
13051 #define TOK_NOT tok_decl(UNARYPREC,1)
13053 #define TOK_UMINUS tok_decl(UNARYPREC+1,0)
13054 #define TOK_UPLUS tok_decl(UNARYPREC+1,1)
13056 #define PREC_PRE (UNARYPREC+2)
13058 #define TOK_PRE_INC tok_decl(PREC_PRE, 0)
13059 #define TOK_PRE_DEC tok_decl(PREC_PRE, 1)
13061 #define PREC_POST (UNARYPREC+3)
13063 #define TOK_POST_INC tok_decl(PREC_POST, 0)
13064 #define TOK_POST_DEC tok_decl(PREC_POST, 1)
13066 #define SPEC_PREC (UNARYPREC+4)
13068 #define TOK_NUM tok_decl(SPEC_PREC, 0)
13069 #define TOK_RPAREN tok_decl(SPEC_PREC, 1)
13071 #define NUMPTR (*numstackptr)
13074 tok_have_assign(operator op)
13076 operator prec = PREC(op);
13078 convert_prec_is_assing(prec);
13079 return (prec == PREC(TOK_ASSIGN) ||
13080 prec == PREC_PRE || prec == PREC_POST);
13084 is_right_associativity(operator prec)
13086 return (prec == PREC(TOK_ASSIGN) || prec == PREC(TOK_EXPONENT)
13087 || prec == PREC(TOK_CONDITIONAL));
13092 arith_t contidional_second_val;
13093 char contidional_second_val_initialized;
13094 char *var; /* if NULL then is regular number,
13095 else is variable name */
13098 typedef struct chk_var_recursive_looped_t {
13100 struct chk_var_recursive_looped_t *next;
13101 } chk_var_recursive_looped_t;
13103 static chk_var_recursive_looped_t *prev_chk_var_recursive;
13106 arith_lookup_val(v_n_t *t)
13109 const char * p = lookupvar(t->var);
13114 /* recursive try as expression */
13115 chk_var_recursive_looped_t *cur;
13116 chk_var_recursive_looped_t cur_save;
13118 for (cur = prev_chk_var_recursive; cur; cur = cur->next) {
13119 if (strcmp(cur->var, t->var) == 0) {
13120 /* expression recursion loop detected */
13124 /* save current lookuped var name */
13125 cur = prev_chk_var_recursive;
13126 cur_save.var = t->var;
13127 cur_save.next = cur;
13128 prev_chk_var_recursive = &cur_save;
13130 t->val = arith (p, &errcode);
13131 /* restore previous ptr after recursiving */
13132 prev_chk_var_recursive = cur;
13135 /* allow undefined var as 0 */
13141 /* "applying" a token means performing it on the top elements on the integer
13142 * stack. For a unary operator it will only change the top element, but a
13143 * binary operator will pop two arguments and push a result */
13145 arith_apply(operator op, v_n_t *numstack, v_n_t **numstackptr)
13148 arith_t numptr_val, rez;
13149 int ret_arith_lookup_val;
13151 /* There is no operator that can work without arguments */
13152 if (NUMPTR == numstack) goto err;
13153 numptr_m1 = NUMPTR - 1;
13155 /* check operand is var with noninteger value */
13156 ret_arith_lookup_val = arith_lookup_val(numptr_m1);
13157 if (ret_arith_lookup_val)
13158 return ret_arith_lookup_val;
13160 rez = numptr_m1->val;
13161 if (op == TOK_UMINUS)
13163 else if (op == TOK_NOT)
13165 else if (op == TOK_BNOT)
13167 else if (op == TOK_POST_INC || op == TOK_PRE_INC)
13169 else if (op == TOK_POST_DEC || op == TOK_PRE_DEC)
13171 else if (op != TOK_UPLUS) {
13172 /* Binary operators */
13174 /* check and binary operators need two arguments */
13175 if (numptr_m1 == numstack) goto err;
13177 /* ... and they pop one */
13180 if (op == TOK_CONDITIONAL) {
13181 if (!numptr_m1->contidional_second_val_initialized) {
13182 /* protect $((expr1 ? expr2)) without ": expr" */
13185 rez = numptr_m1->contidional_second_val;
13186 } else if (numptr_m1->contidional_second_val_initialized) {
13187 /* protect $((expr1 : expr2)) without "expr ? " */
13190 numptr_m1 = NUMPTR - 1;
13191 if (op != TOK_ASSIGN) {
13192 /* check operand is var with noninteger value for not '=' */
13193 ret_arith_lookup_val = arith_lookup_val(numptr_m1);
13194 if (ret_arith_lookup_val)
13195 return ret_arith_lookup_val;
13197 if (op == TOK_CONDITIONAL) {
13198 numptr_m1->contidional_second_val = rez;
13200 rez = numptr_m1->val;
13201 if (op == TOK_BOR || op == TOK_OR_ASSIGN)
13203 else if (op == TOK_OR)
13204 rez = numptr_val || rez;
13205 else if (op == TOK_BAND || op == TOK_AND_ASSIGN)
13207 else if (op == TOK_BXOR || op == TOK_XOR_ASSIGN)
13209 else if (op == TOK_AND)
13210 rez = rez && numptr_val;
13211 else if (op == TOK_EQ)
13212 rez = (rez == numptr_val);
13213 else if (op == TOK_NE)
13214 rez = (rez != numptr_val);
13215 else if (op == TOK_GE)
13216 rez = (rez >= numptr_val);
13217 else if (op == TOK_RSHIFT || op == TOK_RSHIFT_ASSIGN)
13218 rez >>= numptr_val;
13219 else if (op == TOK_LSHIFT || op == TOK_LSHIFT_ASSIGN)
13220 rez <<= numptr_val;
13221 else if (op == TOK_GT)
13222 rez = (rez > numptr_val);
13223 else if (op == TOK_LT)
13224 rez = (rez < numptr_val);
13225 else if (op == TOK_LE)
13226 rez = (rez <= numptr_val);
13227 else if (op == TOK_MUL || op == TOK_MUL_ASSIGN)
13229 else if (op == TOK_ADD || op == TOK_PLUS_ASSIGN)
13231 else if (op == TOK_SUB || op == TOK_MINUS_ASSIGN)
13233 else if (op == TOK_ASSIGN || op == TOK_COMMA)
13235 else if (op == TOK_CONDITIONAL_SEP) {
13236 if (numptr_m1 == numstack) {
13237 /* protect $((expr : expr)) without "expr ? " */
13240 numptr_m1->contidional_second_val_initialized = op;
13241 numptr_m1->contidional_second_val = numptr_val;
13242 } else if (op == TOK_CONDITIONAL) {
13244 numptr_val : numptr_m1->contidional_second_val;
13245 } else if (op == TOK_EXPONENT) {
13246 if (numptr_val < 0)
13247 return -3; /* exponent less than 0 */
13252 while (numptr_val--)
13256 } else if (numptr_val==0) /* zero divisor check */
13258 else if (op == TOK_DIV || op == TOK_DIV_ASSIGN)
13260 else if (op == TOK_REM || op == TOK_REM_ASSIGN)
13263 if (tok_have_assign(op)) {
13264 char buf[sizeof(arith_t_type)*3 + 2];
13266 if (numptr_m1->var == NULL) {
13270 /* save to shell variable */
13271 #if ENABLE_ASH_MATH_SUPPORT_64
13272 snprintf(buf, sizeof(buf), "%lld", (arith_t_type) rez);
13274 snprintf(buf, sizeof(buf), "%ld", (arith_t_type) rez);
13276 setvar(numptr_m1->var, buf, 0);
13277 /* after saving, make previous value for v++ or v-- */
13278 if (op == TOK_POST_INC)
13280 else if (op == TOK_POST_DEC)
13283 numptr_m1->val = rez;
13284 /* protect geting var value, is number now */
13285 numptr_m1->var = NULL;
13291 /* longest must be first */
13292 static const char op_tokens[] ALIGN1 = {
13293 '<','<','=',0, TOK_LSHIFT_ASSIGN,
13294 '>','>','=',0, TOK_RSHIFT_ASSIGN,
13295 '<','<', 0, TOK_LSHIFT,
13296 '>','>', 0, TOK_RSHIFT,
13297 '|','|', 0, TOK_OR,
13298 '&','&', 0, TOK_AND,
13299 '!','=', 0, TOK_NE,
13300 '<','=', 0, TOK_LE,
13301 '>','=', 0, TOK_GE,
13302 '=','=', 0, TOK_EQ,
13303 '|','=', 0, TOK_OR_ASSIGN,
13304 '&','=', 0, TOK_AND_ASSIGN,
13305 '*','=', 0, TOK_MUL_ASSIGN,
13306 '/','=', 0, TOK_DIV_ASSIGN,
13307 '%','=', 0, TOK_REM_ASSIGN,
13308 '+','=', 0, TOK_PLUS_ASSIGN,
13309 '-','=', 0, TOK_MINUS_ASSIGN,
13310 '-','-', 0, TOK_POST_DEC,
13311 '^','=', 0, TOK_XOR_ASSIGN,
13312 '+','+', 0, TOK_POST_INC,
13313 '*','*', 0, TOK_EXPONENT,
13317 '=', 0, TOK_ASSIGN,
13329 '?', 0, TOK_CONDITIONAL,
13330 ':', 0, TOK_CONDITIONAL_SEP,
13331 ')', 0, TOK_RPAREN,
13332 '(', 0, TOK_LPAREN,
13336 #define endexpression (&op_tokens[sizeof(op_tokens)-7])
13339 arith(const char *expr, int *perrcode)
13341 char arithval; /* Current character under analysis */
13342 operator lasttok, op;
13344 operator *stack, *stackptr;
13345 const char *p = endexpression;
13347 v_n_t *numstack, *numstackptr;
13348 unsigned datasizes = strlen(expr) + 2;
13350 /* Stack of integers */
13351 /* The proof that there can be no more than strlen(startbuf)/2+1 integers
13352 * in any given correct or incorrect expression is left as an exercise to
13354 numstackptr = numstack = alloca((datasizes / 2) * sizeof(numstack[0]));
13355 /* Stack of operator tokens */
13356 stackptr = stack = alloca(datasizes * sizeof(stack[0]));
13358 *stackptr++ = lasttok = TOK_LPAREN; /* start off with a left paren */
13359 *perrcode = errcode = 0;
13363 if (arithval == 0) {
13364 if (p == endexpression) {
13365 /* Null expression. */
13369 /* This is only reached after all tokens have been extracted from the
13370 * input stream. If there are still tokens on the operator stack, they
13371 * are to be applied in order. At the end, there should be a final
13372 * result on the integer stack */
13374 if (expr != endexpression + 1) {
13375 /* If we haven't done so already, */
13376 /* append a closing right paren */
13377 expr = endexpression;
13378 /* and let the loop process it. */
13381 /* At this point, we're done with the expression. */
13382 if (numstackptr != numstack+1) {
13383 /* ... but if there isn't, it's bad */
13388 if (numstack->var) {
13389 /* expression is $((var)) only, lookup now */
13390 errcode = arith_lookup_val(numstack);
13393 *perrcode = errcode;
13394 return numstack->val;
13397 /* Continue processing the expression. */
13398 if (arith_isspace(arithval)) {
13399 /* Skip whitespace */
13402 p = endofname(expr);
13404 size_t var_name_size = (p-expr) + 1; /* trailing zero */
13406 numstackptr->var = alloca(var_name_size);
13407 safe_strncpy(numstackptr->var, expr, var_name_size);
13410 numstackptr->contidional_second_val_initialized = 0;
13415 if (isdigit(arithval)) {
13416 numstackptr->var = NULL;
13417 #if ENABLE_ASH_MATH_SUPPORT_64
13418 numstackptr->val = strtoll(expr, (char **) &expr, 0);
13420 numstackptr->val = strtol(expr, (char **) &expr, 0);
13424 for (p = op_tokens; ; p++) {
13428 /* strange operator not found */
13431 for (o = expr; *p && *o == *p; p++)
13438 /* skip tail uncompared token */
13441 /* skip zero delim */
13446 /* post grammar: a++ reduce to num */
13447 if (lasttok == TOK_POST_INC || lasttok == TOK_POST_DEC)
13450 /* Plus and minus are binary (not unary) _only_ if the last
13451 * token was as number, or a right paren (which pretends to be
13452 * a number, since it evaluates to one). Think about it.
13453 * It makes sense. */
13454 if (lasttok != TOK_NUM) {
13470 /* We don't want a unary operator to cause recursive descent on the
13471 * stack, because there can be many in a row and it could cause an
13472 * operator to be evaluated before its argument is pushed onto the
13473 * integer stack. */
13474 /* But for binary operators, "apply" everything on the operator
13475 * stack until we find an operator with a lesser priority than the
13476 * one we have just extracted. */
13477 /* Left paren is given the lowest priority so it will never be
13478 * "applied" in this way.
13479 * if associativity is right and priority eq, applied also skip
13482 if ((prec > 0 && prec < UNARYPREC) || prec == SPEC_PREC) {
13483 /* not left paren or unary */
13484 if (lasttok != TOK_NUM) {
13485 /* binary op must be preceded by a num */
13488 while (stackptr != stack) {
13489 if (op == TOK_RPAREN) {
13490 /* The algorithm employed here is simple: while we don't
13491 * hit an open paren nor the bottom of the stack, pop
13492 * tokens and apply them */
13493 if (stackptr[-1] == TOK_LPAREN) {
13495 /* Any operator directly after a */
13497 /* close paren should consider itself binary */
13501 operator prev_prec = PREC(stackptr[-1]);
13503 convert_prec_is_assing(prec);
13504 convert_prec_is_assing(prev_prec);
13505 if (prev_prec < prec)
13507 /* check right assoc */
13508 if (prev_prec == prec && is_right_associativity(prec))
13511 errcode = arith_apply(*--stackptr, numstack, &numstackptr);
13512 if (errcode) goto ret;
13514 if (op == TOK_RPAREN) {
13519 /* Push this operator to the stack and remember it. */
13520 *stackptr++ = lasttok = op;
13525 #endif /* ASH_MATH_SUPPORT */
13528 /* ============ main() and helpers */
13531 * Called to exit the shell.
13533 static void exitshell(void) NORETURN;
13541 status = exitstatus;
13542 TRACE(("pid %d, exitshell(%d)\n", getpid(), status));
13543 if (setjmp(loc.loc)) {
13544 if (exception_type == EXEXIT)
13545 /* dash bug: it just does _exit(exitstatus) here
13546 * but we have to do setjobctl(0) first!
13547 * (bug is still not fixed in dash-0.5.3 - if you run dash
13548 * under Midnight Commander, on exit from dash MC is backgrounded) */
13549 status = exitstatus;
13552 exception_handler = &loc;
13558 flush_stdout_stderr();
13568 /* from input.c: */
13569 basepf.next_to_pgetc = basepf.buf = basebuf;
13572 signal(SIGCHLD, SIG_DFL);
13577 char ppid[sizeof(int)*3 + 1];
13579 struct stat st1, st2;
13582 for (envp = environ; envp && *envp; envp++) {
13583 if (strchr(*envp, '=')) {
13584 setvareq(*envp, VEXPORT|VTEXTFIXED);
13588 snprintf(ppid, sizeof(ppid), "%u", (unsigned) getppid());
13589 setvar("PPID", ppid, 0);
13591 p = lookupvar("PWD");
13593 if (*p != '/' || stat(p, &st1) || stat(".", &st2)
13594 || st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino)
13601 * Process the shell command line arguments.
13604 procargs(char **argv)
13607 const char *xminusc;
13612 /* if (xargv[0]) - mmm, this is always true! */
13614 for (i = 0; i < NOPTS; i++)
13618 /* it already printed err message */
13619 raise_exception(EXERROR);
13623 if (*xargv == NULL) {
13625 ash_msg_and_raise_error(bb_msg_requires_arg, "-c");
13628 if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
13632 for (i = 0; i < NOPTS; i++)
13633 if (optlist[i] == 2)
13638 /* POSIX 1003.2: first arg after -c cmd is $0, remainder $1... */
13643 } else if (!sflag) {
13644 setinputfile(*xargv, 0);
13647 commandname = arg0;
13650 shellparam.p = xargv;
13651 #if ENABLE_ASH_GETOPTS
13652 shellparam.optind = 1;
13653 shellparam.optoff = -1;
13655 /* assert(shellparam.malloced == 0 && shellparam.nparam == 0); */
13657 shellparam.nparam++;
13664 * Read /etc/profile or .profile.
13667 read_profile(const char *name)
13671 if (setinputfile(name, INPUT_PUSH_FILE | INPUT_NOFILE_OK) < 0)
13680 * This routine is called when an error or an interrupt occurs in an
13681 * interactive shell and control is returned to the main command loop.
13689 /* from input.c: */
13690 g_parsefile->left_in_buffer = 0;
13691 g_parsefile->left_in_line = 0; /* clear input buffer */
13693 /* from parser.c: */
13696 /* from redir.c: */
13697 clearredir(/*drop:*/ 0);
13701 static short profile_buf[16384];
13702 extern int etext();
13706 * Main routine. We initialize things, parse the arguments, execute
13707 * profiles if we're a login shell, and then call cmdloop to execute
13708 * commands. The setjmp call sets up the location to jump to when an
13709 * exception occurs. When an exception occurs the variable "state"
13710 * is used to figure out how far we had gotten.
13712 int ash_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
13713 int ash_main(int argc UNUSED_PARAM, char **argv)
13716 volatile smallint state;
13717 struct jmploc jmploc;
13718 struct stackmark smark;
13720 /* Initialize global data */
13724 #if ENABLE_ASH_ALIAS
13730 monitor(4, etext, profile_buf, sizeof(profile_buf), 50);
13733 #if ENABLE_FEATURE_EDITING
13734 line_input_state = new_line_input_t(FOR_SHELL | WITH_PATH_LOOKUP);
13737 if (setjmp(jmploc.loc)) {
13743 e = exception_type;
13747 if (e == EXEXIT || s == 0 || iflag == 0 || shlvl)
13750 outcslow('\n', stderr);
13752 popstackmark(&smark);
13753 FORCE_INT_ON; /* enable interrupts */
13762 exception_handler = &jmploc;
13765 trace_puts("Shell args: ");
13766 trace_puts_args(argv);
13768 rootpid = getpid();
13770 #if ENABLE_ASH_RANDOM_SUPPORT
13771 /* Can use monotonic_ns() for better randomness but for now it is
13772 * not used anywhere else in busybox... so avoid bloat */
13773 random_galois_LFSR = random_LCG = rootpid + monotonic_us();
13776 setstackmark(&smark);
13779 #if ENABLE_FEATURE_EDITING_SAVEHISTORY
13781 const char *hp = lookupvar("HISTFILE");
13784 hp = lookupvar("HOME");
13786 char *defhp = concat_path_file(hp, ".ash_history");
13787 setvar("HISTFILE", defhp, 0);
13793 if (/* argv[0] && */ argv[0][0] == '-')
13797 read_profile("/etc/profile");
13800 read_profile(".profile");
13806 getuid() == geteuid() && getgid() == getegid() &&
13810 shinit = lookupvar("ENV");
13811 if (shinit != NULL && *shinit != '\0') {
13812 read_profile(shinit);
13818 /* evalstring pushes parsefile stack.
13819 * Ensure we don't falsely claim that 0 (stdin)
13820 * is one of stacked source fds */
13822 g_parsefile->fd = -1;
13823 evalstring(minusc, 0);
13826 if (sflag || minusc == NULL) {
13827 #if ENABLE_FEATURE_EDITING_SAVEHISTORY
13829 const char *hp = lookupvar("HISTFILE");
13831 line_input_state->hist_file = hp;
13834 state4: /* XXX ??? - why isn't this before the "if" statement */
13842 extern void _mcleanup(void);
13851 const char *applet_name = "debug stuff usage";
13852 int main(int argc, char **argv)
13854 return ash_main(argc, argv);
13860 * Copyright (c) 1989, 1991, 1993, 1994
13861 * The Regents of the University of California. All rights reserved.
13863 * This code is derived from software contributed to Berkeley by
13864 * Kenneth Almquist.
13866 * Redistribution and use in source and binary forms, with or without
13867 * modification, are permitted provided that the following conditions
13869 * 1. Redistributions of source code must retain the above copyright
13870 * notice, this list of conditions and the following disclaimer.
13871 * 2. Redistributions in binary form must reproduce the above copyright
13872 * notice, this list of conditions and the following disclaimer in the
13873 * documentation and/or other materials provided with the distribution.
13874 * 3. Neither the name of the University nor the names of its contributors
13875 * may be used to endorse or promote products derived from this software
13876 * without specific prior written permission.
13878 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
13879 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
13880 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
13881 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
13882 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
13883 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
13884 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
13885 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
13886 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
13887 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF