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 following 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.
43 /* Tweak debug output verbosity here */
52 #define JOBS ENABLE_ASH_JOB_CONTROL
60 #include "busybox.h" /* for applet_names */
61 //TODO: pull in some .h and find out do we have SINGLE_APPLET_MAIN?
62 //#include "applet_tables.h" doesn't work
67 #if defined SINGLE_APPLET_MAIN
68 /* STANDALONE does not make sense, and won't compile */
69 #undef CONFIG_FEATURE_SH_STANDALONE
70 #undef ENABLE_FEATURE_SH_STANDALONE
71 #undef USE_FEATURE_SH_STANDALONE
72 #undef SKIP_FEATURE_SH_STANDALONE(...)
73 #define ENABLE_FEATURE_SH_STANDALONE 0
74 #define USE_FEATURE_SH_STANDALONE(...)
75 #define SKIP_FEATURE_SH_STANDALONE(...) __VA_ARGS__
79 # define PIPE_BUF 4096 /* amount of buffering in a pipe */
82 #if defined(__uClinux__)
83 # error "Do not even bother, ash will not run on NOMMU machine"
87 /* ============ Hash table sizes. Configurable. */
91 #define CMDTABLESIZE 31 /* should be prime */
94 /* ============ Shell options */
96 static const char *const optletters_optnames[] = {
117 #define optletters(n) optletters_optnames[(n)][0]
118 #define optnames(n) (&optletters_optnames[(n)][1])
120 enum { NOPTS = ARRAY_SIZE(optletters_optnames) };
123 /* ============ Misc data */
125 static const char homestr[] ALIGN1 = "HOME";
126 static const char snlfmt[] ALIGN1 = "%s\n";
127 static const char illnum[] ALIGN1 = "Illegal number: %s";
130 * We enclose jmp_buf in a structure so that we can declare pointers to
131 * jump locations. The global variable handler contains the location to
132 * jump to when an exception occurs, and the global variable exception_type
133 * contains a code identifying the exception. To implement nested
134 * exception handlers, the user should save the value of handler on entry
135 * to an inner scope, set handler to point to a jmploc structure for the
136 * inner scope, and restore handler on exit from the scope.
142 struct globals_misc {
143 /* pid of main shell */
145 /* shell level: 0 for the main shell, 1 for its children, and so on */
147 #define rootshell (!shlvl)
148 char *minusc; /* argument to -c option */
150 char *curdir; // = nullstr; /* current working directory */
151 char *physdir; // = nullstr; /* physical working directory */
153 char *arg0; /* value of $0 */
155 struct jmploc *exception_handler;
157 // disabled by vda: cannot understand how it was supposed to work -
158 // cannot fix bugs. That's why you have to explain your non-trivial designs!
159 // /* do we generate EXSIG events */
160 // int exsig; /* counter */
161 volatile int suppressint; /* counter */
163 // pendingsig -> pending_sig
164 // intpending -> pending_int
165 volatile /*sig_atomic_t*/ smallint intpending; /* 1 = got SIGINT */
166 /* last pending signal */
167 volatile /*sig_atomic_t*/ smallint pendingsig;
168 smallint exception_type; /* kind of exception (0..5) */
170 #define EXINT 0 /* SIGINT received */
171 #define EXERROR 1 /* a generic error */
172 #define EXSHELLPROC 2 /* execute a shell procedure */
173 #define EXEXEC 3 /* command execution failed */
174 #define EXEXIT 4 /* exit the shell */
175 #define EXSIG 5 /* trapped signal in wait(1) */
178 char nullstr[1]; /* zero length string */
181 #define eflag optlist[0]
182 #define fflag optlist[1]
183 #define Iflag optlist[2]
184 #define iflag optlist[3]
185 #define mflag optlist[4]
186 #define nflag optlist[5]
187 #define sflag optlist[6]
188 #define xflag optlist[7]
189 #define vflag optlist[8]
190 #define Cflag optlist[9]
191 #define aflag optlist[10]
192 #define bflag optlist[11]
193 #define uflag optlist[12]
194 #define viflag optlist[13]
196 #define nolog optlist[14]
197 #define debug optlist[15]
200 /* trap handler commands */
202 * Sigmode records the current value of the signal handlers for the various
203 * modes. A value of zero means that the current handler is not known.
204 * S_HARD_IGN indicates that the signal was ignored on entry to the shell.
206 char sigmode[NSIG - 1];
207 #define S_DFL 1 /* default signal handling (SIG_DFL) */
208 #define S_CATCH 2 /* signal is caught */
209 #define S_IGN 3 /* signal is ignored (SIG_IGN) */
210 #define S_HARD_IGN 4 /* signal is ignored permenantly */
212 /* indicates specified signal received */
213 uint8_t gotsig[NSIG - 1]; /* offset by 1: "signal" 0 is meaningless */
216 /* Rarely referenced stuff */
217 #if ENABLE_ASH_RANDOM_SUPPORT
218 /* Random number generators */
219 int32_t random_galois_LFSR; /* Galois LFSR (fast but weak). signed! */
220 uint32_t random_LCG; /* LCG (fast but weak) */
222 pid_t backgndpid; /* pid of last background process */
223 smallint job_warning; /* user was warned about stopped jobs (can be 2, 1 or 0). */
225 extern struct globals_misc *const ash_ptr_to_globals_misc;
226 #define G_misc (*ash_ptr_to_globals_misc)
227 #define rootpid (G_misc.rootpid )
228 #define shlvl (G_misc.shlvl )
229 #define minusc (G_misc.minusc )
230 #define curdir (G_misc.curdir )
231 #define physdir (G_misc.physdir )
232 #define arg0 (G_misc.arg0 )
233 #define exception_handler (G_misc.exception_handler)
234 #define exception_type (G_misc.exception_type )
235 #define suppressint (G_misc.suppressint )
236 #define intpending (G_misc.intpending )
237 //#define exsig (G_misc.exsig )
238 #define pendingsig (G_misc.pendingsig )
239 #define isloginsh (G_misc.isloginsh )
240 #define nullstr (G_misc.nullstr )
241 #define optlist (G_misc.optlist )
242 #define sigmode (G_misc.sigmode )
243 #define gotsig (G_misc.gotsig )
244 #define trap (G_misc.trap )
245 #define random_galois_LFSR (G_misc.random_galois_LFSR)
246 #define random_LCG (G_misc.random_LCG )
247 #define backgndpid (G_misc.backgndpid )
248 #define job_warning (G_misc.job_warning)
249 #define INIT_G_misc() do { \
250 (*(struct globals_misc**)&ash_ptr_to_globals_misc) = xzalloc(sizeof(G_misc)); \
257 /* ============ DEBUG */
259 static void trace_printf(const char *fmt, ...);
260 static void trace_vprintf(const char *fmt, va_list va);
261 # define TRACE(param) trace_printf param
262 # define TRACEV(param) trace_vprintf param
264 # define TRACE(param)
265 # define TRACEV(param)
269 /* ============ Utility functions */
270 #define xbarrier() do { __asm__ __volatile__ ("": : :"memory"); } while (0)
272 /* C99 say: "char" declaration may be signed or unsigned by default */
273 #define signed_char2int(sc) ((int)(signed char)(sc))
275 static int isdigit_str9(const char *str)
277 int maxlen = 9 + 1; /* max 9 digits: 999999999 */
278 while (--maxlen && isdigit(*str))
280 return (*str == '\0');
284 /* ============ Interrupts / exceptions */
286 * These macros allow the user to suspend the handling of interrupt signals
287 * over a period of time. This is similar to SIGHOLD or to sigblock, but
288 * much more efficient and portable. (But hacking the kernel is so much
289 * more fun than worrying about efficiency and portability. :-))
291 #define INT_OFF do { \
297 * Called to raise an exception. Since C doesn't include exceptions, we
298 * just do a longjmp to the exception handler. The type of exception is
299 * stored in the global variable "exception_type".
301 static void raise_exception(int) NORETURN;
303 raise_exception(int e)
306 if (exception_handler == NULL)
311 longjmp(exception_handler->loc, 1);
314 #define raise_exception(e) do { \
315 TRACE(("raising exception %d on line %d\n", (e), __LINE__)); \
316 raise_exception(e); \
321 * Called from trap.c when a SIGINT is received. (If the user specifies
322 * that SIGINT is to be trapped or ignored using the trap builtin, then
323 * this routine is not called.) Suppressint is nonzero when interrupts
324 * are held using the INT_OFF macro. (The test for iflag is just
325 * defensive programming.)
327 static void raise_interrupt(void) NORETURN;
329 raise_interrupt(void)
334 /* Signal is not automatically unmasked after it is raised,
335 * do it ourself - unmask all signals */
336 sigprocmask_allsigs(SIG_UNBLOCK);
337 /* pendingsig = 0; - now done in onsig() */
340 if (gotsig[SIGINT - 1] && !trap[SIGINT]) {
341 if (!(rootshell && iflag)) {
342 /* Kill ourself with SIGINT */
343 signal(SIGINT, SIG_DFL);
348 raise_exception(ex_type);
352 #define raise_interrupt() do { \
353 TRACE(("raising interrupt on line %d\n", __LINE__)); \
358 #if ENABLE_ASH_OPTIMIZE_FOR_SIZE
362 if (--suppressint == 0 && intpending) {
366 #define INT_ON int_on()
374 #define FORCE_INT_ON force_int_on()
376 #else /* !ASH_OPTIMIZE_FOR_SIZE */
378 #define INT_ON do { \
380 if (--suppressint == 0 && intpending) \
383 #define FORCE_INT_ON do { \
389 #endif /* !ASH_OPTIMIZE_FOR_SIZE */
391 #define SAVE_INT(v) ((v) = suppressint)
393 #define RESTORE_INT(v) do { \
396 if (suppressint == 0 && intpending) \
401 /* ============ Stdout/stderr output */
404 outstr(const char *p, FILE *file)
412 flush_stdout_stderr(void)
429 outcslow(int c, FILE *dest)
437 static int out1fmt(const char *, ...) __attribute__((__format__(__printf__,1,2)));
439 out1fmt(const char *fmt, ...)
446 r = vprintf(fmt, ap);
452 static int fmtstr(char *, size_t, const char *, ...) __attribute__((__format__(__printf__,3,4)));
454 fmtstr(char *outbuf, size_t length, const char *fmt, ...)
461 ret = vsnprintf(outbuf, length, fmt, ap);
468 out1str(const char *p)
474 out2str(const char *p)
481 /* ============ Parser structures */
483 /* control characters in argument strings */
484 #define CTLESC '\201' /* escape next character */
485 #define CTLVAR '\202' /* variable defn */
486 #define CTLENDVAR '\203'
487 #define CTLBACKQ '\204'
488 #define CTLQUOTE 01 /* ored with CTLBACKQ code if in quotes */
489 /* CTLBACKQ | CTLQUOTE == '\205' */
490 #define CTLARI '\206' /* arithmetic expression */
491 #define CTLENDARI '\207'
492 #define CTLQUOTEMARK '\210'
494 /* variable substitution byte (follows CTLVAR) */
495 #define VSTYPE 0x0f /* type of variable substitution */
496 #define VSNUL 0x10 /* colon--treat the empty string as unset */
497 #define VSQUOTE 0x80 /* inside double quotes--suppress splitting */
499 /* values of VSTYPE field */
500 #define VSNORMAL 0x1 /* normal variable: $var or ${var} */
501 #define VSMINUS 0x2 /* ${var-text} */
502 #define VSPLUS 0x3 /* ${var+text} */
503 #define VSQUESTION 0x4 /* ${var?message} */
504 #define VSASSIGN 0x5 /* ${var=text} */
505 #define VSTRIMRIGHT 0x6 /* ${var%pattern} */
506 #define VSTRIMRIGHTMAX 0x7 /* ${var%%pattern} */
507 #define VSTRIMLEFT 0x8 /* ${var#pattern} */
508 #define VSTRIMLEFTMAX 0x9 /* ${var##pattern} */
509 #define VSLENGTH 0xa /* ${#var} */
510 #if ENABLE_ASH_BASH_COMPAT
511 #define VSSUBSTR 0xc /* ${var:position:length} */
512 #define VSREPLACE 0xd /* ${var/pattern/replacement} */
513 #define VSREPLACEALL 0xe /* ${var//pattern/replacement} */
516 static const char dolatstr[] ALIGN1 = {
517 CTLVAR, VSNORMAL|VSQUOTE, '@', '=', '\0'
537 #if ENABLE_ASH_BASH_COMPAT
554 smallint type; /* Nxxxx */
557 union node *redirect;
562 smallint pipe_backgnd;
563 struct nodelist *cmdlist;
569 union node *redirect;
582 union node *elsepart;
609 struct nodelist *backquote;
612 /* nfile and ndup layout must match!
613 * NTOFD (>&fdnum) uses ndup structure, but we may discover mid-flight
614 * that it is actually NTO2 (>&file), and change its type.
631 char *_unused_expfname;
650 struct nredir nredir;
651 struct nbinary nbinary;
655 struct nclist nclist;
664 struct nodelist *next;
677 freefunc(struct funcnode *f)
679 if (f && --f->count < 0)
684 /* ============ Debugging output */
688 static FILE *tracefile;
691 trace_printf(const char *fmt, ...)
698 fprintf(tracefile, "%u ", (int) time(NULL));
700 fprintf(tracefile, "[%u] ", (int) getpid());
702 fprintf(tracefile, "pending s:%d i:%d(supp:%d) ", pendingsig, intpending, suppressint);
704 vfprintf(tracefile, fmt, va);
709 trace_vprintf(const char *fmt, va_list va)
714 fprintf(tracefile, "%u ", (int) time(NULL));
716 fprintf(tracefile, "[%u] ", (int) getpid());
718 fprintf(tracefile, "pending s:%d i:%d(supp:%d) ", pendingsig, intpending, suppressint);
719 vfprintf(tracefile, fmt, va);
723 trace_puts(const char *s)
731 trace_puts_quoted(char *s)
738 putc('"', tracefile);
739 for (p = s; *p; p++) {
741 case '\n': c = 'n'; goto backslash;
742 case '\t': c = 't'; goto backslash;
743 case '\r': c = 'r'; goto backslash;
744 case '"': c = '"'; goto backslash;
745 case '\\': c = '\\'; goto backslash;
746 case CTLESC: c = 'e'; goto backslash;
747 case CTLVAR: c = 'v'; goto backslash;
748 case CTLVAR+CTLQUOTE: c = 'V'; goto backslash;
749 case CTLBACKQ: c = 'q'; goto backslash;
750 case CTLBACKQ+CTLQUOTE: c = 'Q'; goto backslash;
752 putc('\\', tracefile);
756 if (*p >= ' ' && *p <= '~')
759 putc('\\', tracefile);
760 putc(*p >> 6 & 03, tracefile);
761 putc(*p >> 3 & 07, tracefile);
762 putc(*p & 07, tracefile);
767 putc('"', tracefile);
771 trace_puts_args(char **ap)
778 trace_puts_quoted(*ap);
780 putc('\n', tracefile);
783 putc(' ', tracefile);
798 /* leave open because libedit might be using it */
801 strcpy(s, "./trace");
803 if (!freopen(s, "a", tracefile)) {
804 fprintf(stderr, "Can't re-open %s\n", s);
809 tracefile = fopen(s, "a");
810 if (tracefile == NULL) {
811 fprintf(stderr, "Can't open %s\n", s);
817 flags = fcntl(fileno(tracefile), F_GETFL);
819 fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND);
821 setlinebuf(tracefile);
822 fputs("\nTracing started.\n", tracefile);
826 indent(int amount, char *pfx, FILE *fp)
830 for (i = 0; i < amount; i++) {
831 if (pfx && i == amount - 1)
837 /* little circular references here... */
838 static void shtree(union node *n, int ind, char *pfx, FILE *fp);
841 sharg(union node *arg, FILE *fp)
844 struct nodelist *bqlist;
847 if (arg->type != NARG) {
848 out1fmt("<node type %d>\n", arg->type);
851 bqlist = arg->narg.backquote;
852 for (p = arg->narg.text; *p; p++) {
861 if (subtype == VSLENGTH)
870 switch (subtype & VSTYPE) {
903 out1fmt("<subtype %d>", subtype);
910 case CTLBACKQ|CTLQUOTE:
913 shtree(bqlist->n, -1, NULL, fp);
924 shcmd(union node *cmd, FILE *fp)
932 for (np = cmd->ncmd.args; np; np = np->narg.next) {
938 for (np = cmd->ncmd.redirect; np; np = np->nfile.next) {
942 switch (np->nfile.type) {
943 case NTO: s = ">>"+1; dftfd = 1; break;
944 case NCLOBBER: s = ">|"; dftfd = 1; break;
945 case NAPPEND: s = ">>"; dftfd = 1; break;
946 #if ENABLE_ASH_BASH_COMPAT
949 case NTOFD: s = ">&"; dftfd = 1; break;
950 case NFROM: s = "<"; break;
951 case NFROMFD: s = "<&"; break;
952 case NFROMTO: s = "<>"; break;
953 default: s = "*error*"; break;
955 if (np->nfile.fd != dftfd)
956 fprintf(fp, "%d", np->nfile.fd);
958 if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) {
959 fprintf(fp, "%d", np->ndup.dupfd);
961 sharg(np->nfile.fname, fp);
968 shtree(union node *n, int ind, char *pfx, FILE *fp)
976 indent(ind, pfx, fp);
987 shtree(n->nbinary.ch1, ind, NULL, fp);
990 shtree(n->nbinary.ch2, ind, NULL, fp);
998 for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
1003 if (n->npipe.pipe_backgnd)
1009 fprintf(fp, "<node type %d>", n->type);
1017 showtree(union node *n)
1019 trace_puts("showtree called\n");
1020 shtree(n, 1, NULL, stdout);
1026 /* ============ Parser data */
1029 * ash_vmsg() needs parsefile->fd, hence parsefile definition is moved up.
1032 struct strlist *next;
1039 struct strpush *prev; /* preceding string on stack */
1041 int prev_left_in_line;
1042 #if ENABLE_ASH_ALIAS
1043 struct alias *ap; /* if push was associated with an alias */
1045 char *string; /* remember the string since it may change */
1049 struct parsefile *prev; /* preceding file on stack */
1050 int linno; /* current line */
1051 int fd; /* file descriptor (or -1 if string) */
1052 int left_in_line; /* number of chars left in this line */
1053 int left_in_buffer; /* number of chars left in this buffer past the line */
1054 char *next_to_pgetc; /* next char in buffer */
1055 char *buf; /* input buffer */
1056 struct strpush *strpush; /* for pushing strings at this level */
1057 struct strpush basestrpush; /* so pushing one is fast */
1060 static struct parsefile basepf; /* top level input file */
1061 static struct parsefile *g_parsefile = &basepf; /* current input file */
1062 static int startlinno; /* line # where last token started */
1063 static char *commandname; /* currently executing command */
1064 static struct strlist *cmdenviron; /* environment for builtin command */
1065 static uint8_t exitstatus; /* exit status of last command */
1068 /* ============ Message printing */
1071 ash_vmsg(const char *msg, va_list ap)
1073 fprintf(stderr, "%s: ", arg0);
1075 if (strcmp(arg0, commandname))
1076 fprintf(stderr, "%s: ", commandname);
1077 if (!iflag || g_parsefile->fd)
1078 fprintf(stderr, "line %d: ", startlinno);
1080 vfprintf(stderr, msg, ap);
1081 outcslow('\n', stderr);
1085 * Exverror is called to raise the error exception. If the second argument
1086 * is not NULL then error prints an error message using printf style
1087 * formatting. It then raises the error exception.
1089 static void ash_vmsg_and_raise(int, const char *, va_list) NORETURN;
1091 ash_vmsg_and_raise(int cond, const char *msg, va_list ap)
1095 TRACE(("ash_vmsg_and_raise(%d, \"", cond));
1097 TRACE(("\") pid=%d\n", getpid()));
1099 TRACE(("ash_vmsg_and_raise(%d, NULL) pid=%d\n", cond, getpid()));
1104 flush_stdout_stderr();
1105 raise_exception(cond);
1109 static void ash_msg_and_raise_error(const char *, ...) NORETURN;
1111 ash_msg_and_raise_error(const char *msg, ...)
1116 ash_vmsg_and_raise(EXERROR, msg, ap);
1121 static void ash_msg_and_raise(int, const char *, ...) NORETURN;
1123 ash_msg_and_raise(int cond, const char *msg, ...)
1128 ash_vmsg_and_raise(cond, msg, ap);
1134 * error/warning routines for external builtins
1137 ash_msg(const char *fmt, ...)
1147 * Return a string describing an error. The returned string may be a
1148 * pointer to a static buffer that will be overwritten on the next call.
1149 * Action describes the operation that got the error.
1152 errmsg(int e, const char *em)
1154 if (e == ENOENT || e == ENOTDIR) {
1161 /* ============ Memory allocation */
1164 * It appears that grabstackstr() will barf with such alignments
1165 * because stalloc() will return a string allocated in a new stackblock.
1167 #define SHELL_ALIGN(nbytes) (((nbytes) + SHELL_SIZE) & ~SHELL_SIZE)
1169 /* Most machines require the value returned from malloc to be aligned
1170 * in some way. The following macro will get this right
1171 * on many machines. */
1172 SHELL_SIZE = sizeof(union {int i; char *cp; double d; }) - 1,
1173 /* Minimum size of a block */
1174 MINSIZE = SHELL_ALIGN(504),
1177 struct stack_block {
1178 struct stack_block *prev;
1179 char space[MINSIZE];
1183 struct stack_block *stackp;
1186 struct stackmark *marknext;
1190 struct globals_memstack {
1191 struct stack_block *g_stackp; // = &stackbase;
1192 struct stackmark *markp;
1193 char *g_stacknxt; // = stackbase.space;
1194 char *sstrend; // = stackbase.space + MINSIZE;
1195 size_t g_stacknleft; // = MINSIZE;
1196 int herefd; // = -1;
1197 struct stack_block stackbase;
1199 extern struct globals_memstack *const ash_ptr_to_globals_memstack;
1200 #define G_memstack (*ash_ptr_to_globals_memstack)
1201 #define g_stackp (G_memstack.g_stackp )
1202 #define markp (G_memstack.markp )
1203 #define g_stacknxt (G_memstack.g_stacknxt )
1204 #define sstrend (G_memstack.sstrend )
1205 #define g_stacknleft (G_memstack.g_stacknleft)
1206 #define herefd (G_memstack.herefd )
1207 #define stackbase (G_memstack.stackbase )
1208 #define INIT_G_memstack() do { \
1209 (*(struct globals_memstack**)&ash_ptr_to_globals_memstack) = xzalloc(sizeof(G_memstack)); \
1211 g_stackp = &stackbase; \
1212 g_stacknxt = stackbase.space; \
1213 g_stacknleft = MINSIZE; \
1214 sstrend = stackbase.space + MINSIZE; \
1218 #define stackblock() ((void *)g_stacknxt)
1219 #define stackblocksize() g_stacknleft
1223 ckrealloc(void * p, size_t nbytes)
1225 p = realloc(p, nbytes);
1227 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1232 ckmalloc(size_t nbytes)
1234 return ckrealloc(NULL, nbytes);
1238 ckzalloc(size_t nbytes)
1240 return memset(ckmalloc(nbytes), 0, nbytes);
1244 * Make a copy of a string in safe storage.
1247 ckstrdup(const char *s)
1249 char *p = strdup(s);
1251 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1256 * Parse trees for commands are allocated in lifo order, so we use a stack
1257 * to make this more efficient, and also to avoid all sorts of exception
1258 * handling code to handle interrupts in the middle of a parse.
1260 * The size 504 was chosen because the Ultrix malloc handles that size
1264 stalloc(size_t nbytes)
1269 aligned = SHELL_ALIGN(nbytes);
1270 if (aligned > g_stacknleft) {
1273 struct stack_block *sp;
1275 blocksize = aligned;
1276 if (blocksize < MINSIZE)
1277 blocksize = MINSIZE;
1278 len = sizeof(struct stack_block) - MINSIZE + blocksize;
1279 if (len < blocksize)
1280 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1283 sp->prev = g_stackp;
1284 g_stacknxt = sp->space;
1285 g_stacknleft = blocksize;
1286 sstrend = g_stacknxt + blocksize;
1291 g_stacknxt += aligned;
1292 g_stacknleft -= aligned;
1297 stzalloc(size_t nbytes)
1299 return memset(stalloc(nbytes), 0, nbytes);
1306 if (!p || (g_stacknxt < (char *)p) || ((char *)p < g_stackp->space)) {
1307 write(STDERR_FILENO, "stunalloc\n", 10);
1311 g_stacknleft += g_stacknxt - (char *)p;
1316 * Like strdup but works with the ash stack.
1319 ststrdup(const char *p)
1321 size_t len = strlen(p) + 1;
1322 return memcpy(stalloc(len), p, len);
1326 setstackmark(struct stackmark *mark)
1328 mark->stackp = g_stackp;
1329 mark->stacknxt = g_stacknxt;
1330 mark->stacknleft = g_stacknleft;
1331 mark->marknext = markp;
1336 popstackmark(struct stackmark *mark)
1338 struct stack_block *sp;
1344 markp = mark->marknext;
1345 while (g_stackp != mark->stackp) {
1347 g_stackp = sp->prev;
1350 g_stacknxt = mark->stacknxt;
1351 g_stacknleft = mark->stacknleft;
1352 sstrend = mark->stacknxt + mark->stacknleft;
1357 * When the parser reads in a string, it wants to stick the string on the
1358 * stack and only adjust the stack pointer when it knows how big the
1359 * string is. Stackblock (defined in stack.h) returns a pointer to a block
1360 * of space on top of the stack and stackblocklen returns the length of
1361 * this block. Growstackblock will grow this space by at least one byte,
1362 * possibly moving it (like realloc). Grabstackblock actually allocates the
1363 * part of the block that has been used.
1366 growstackblock(void)
1370 newlen = g_stacknleft * 2;
1371 if (newlen < g_stacknleft)
1372 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1376 if (g_stacknxt == g_stackp->space && g_stackp != &stackbase) {
1377 struct stack_block *oldstackp;
1378 struct stackmark *xmark;
1379 struct stack_block *sp;
1380 struct stack_block *prevstackp;
1384 oldstackp = g_stackp;
1386 prevstackp = sp->prev;
1387 grosslen = newlen + sizeof(struct stack_block) - MINSIZE;
1388 sp = ckrealloc(sp, grosslen);
1389 sp->prev = prevstackp;
1391 g_stacknxt = sp->space;
1392 g_stacknleft = newlen;
1393 sstrend = sp->space + newlen;
1396 * Stack marks pointing to the start of the old block
1397 * must be relocated to point to the new block
1400 while (xmark != NULL && xmark->stackp == oldstackp) {
1401 xmark->stackp = g_stackp;
1402 xmark->stacknxt = g_stacknxt;
1403 xmark->stacknleft = g_stacknleft;
1404 xmark = xmark->marknext;
1408 char *oldspace = g_stacknxt;
1409 size_t oldlen = g_stacknleft;
1410 char *p = stalloc(newlen);
1412 /* free the space we just allocated */
1413 g_stacknxt = memcpy(p, oldspace, oldlen);
1414 g_stacknleft += newlen;
1419 grabstackblock(size_t len)
1421 len = SHELL_ALIGN(len);
1423 g_stacknleft -= len;
1427 * The following routines are somewhat easier to use than the above.
1428 * The user declares a variable of type STACKSTR, which may be declared
1429 * to be a register. The macro STARTSTACKSTR initializes things. Then
1430 * the user uses the macro STPUTC to add characters to the string. In
1431 * effect, STPUTC(c, p) is the same as *p++ = c except that the stack is
1432 * grown as necessary. When the user is done, she can just leave the
1433 * string there and refer to it using stackblock(). Or she can allocate
1434 * the space for it using grabstackstr(). If it is necessary to allow
1435 * someone else to use the stack temporarily and then continue to grow
1436 * the string, the user should use grabstack to allocate the space, and
1437 * then call ungrabstr(p) to return to the previous mode of operation.
1439 * USTPUTC is like STPUTC except that it doesn't check for overflow.
1440 * CHECKSTACKSPACE can be called before USTPUTC to ensure that there
1441 * is space for at least one character.
1446 size_t len = stackblocksize();
1447 if (herefd >= 0 && len >= 1024) {
1448 full_write(herefd, stackblock(), len);
1449 return stackblock();
1452 return (char *)stackblock() + len;
1456 * Called from CHECKSTRSPACE.
1459 makestrspace(size_t newlen, char *p)
1461 size_t len = p - g_stacknxt;
1462 size_t size = stackblocksize();
1467 size = stackblocksize();
1469 if (nleft >= newlen)
1473 return (char *)stackblock() + len;
1477 stack_nputstr(const char *s, size_t n, char *p)
1479 p = makestrspace(n, p);
1480 p = (char *)memcpy(p, s, n) + n;
1485 stack_putstr(const char *s, char *p)
1487 return stack_nputstr(s, strlen(s), p);
1491 _STPUTC(int c, char *p)
1499 #define STARTSTACKSTR(p) ((p) = stackblock())
1500 #define STPUTC(c, p) ((p) = _STPUTC((c), (p)))
1501 #define CHECKSTRSPACE(n, p) do { \
1504 size_t m = sstrend - q; \
1506 (p) = makestrspace(l, q); \
1508 #define USTPUTC(c, p) (*(p)++ = (c))
1509 #define STACKSTRNUL(p) do { \
1510 if ((p) == sstrend) \
1511 (p) = growstackstr(); \
1514 #define STUNPUTC(p) (--(p))
1515 #define STTOPC(p) ((p)[-1])
1516 #define STADJUST(amount, p) ((p) += (amount))
1518 #define grabstackstr(p) stalloc((char *)(p) - (char *)stackblock())
1519 #define ungrabstackstr(s, p) stunalloc(s)
1520 #define stackstrend() ((void *)sstrend)
1523 /* ============ String helpers */
1526 * prefix -- see if pfx is a prefix of string.
1529 prefix(const char *string, const char *pfx)
1532 if (*pfx++ != *string++)
1535 return (char *) string;
1539 * Check for a valid number. This should be elsewhere.
1542 is_number(const char *p)
1547 } while (*++p != '\0');
1552 * Convert a string of digits to an integer, printing an error message on
1556 number(const char *s)
1559 ash_msg_and_raise_error(illnum, s);
1564 * Produce a possibly single quoted string suitable as input to the shell.
1565 * The return string is allocated on the stack.
1568 single_quote(const char *s)
1578 len = strchrnul(s, '\'') - s;
1580 q = p = makestrspace(len + 3, p);
1583 q = (char *)memcpy(q, s, len) + len;
1589 len = strspn(s, "'");
1593 q = p = makestrspace(len + 3, p);
1596 q = (char *)memcpy(q, s, len) + len;
1605 return stackblock();
1609 /* ============ nextopt */
1611 static char **argptr; /* argument list for builtin commands */
1612 static char *optionarg; /* set by nextopt (like getopt) */
1613 static char *optptr; /* used by nextopt */
1616 * XXX - should get rid of. Have all builtins use getopt(3).
1617 * The library getopt must have the BSD extension static variable
1618 * "optreset", otherwise it can't be used within the shell safely.
1620 * Standard option processing (a la getopt) for builtin routines.
1621 * The only argument that is passed to nextopt is the option string;
1622 * the other arguments are unnecessary. It returns the character,
1623 * or '\0' on end of input.
1626 nextopt(const char *optstring)
1633 if (p == NULL || *p == '\0') {
1634 /* We ate entire "-param", take next one */
1640 if (*++p == '\0') /* just "-" ? */
1643 if (LONE_DASH(p)) /* "--" ? */
1645 /* p => next "-param" */
1647 /* p => some option char in the middle of a "-param" */
1649 for (q = optstring; *q != c;) {
1651 ash_msg_and_raise_error("illegal option -%c", c);
1659 ash_msg_and_raise_error("no arg for -%c option", c);
1669 /* ============ Shell variables */
1672 * The parsefile structure pointed to by the global variable parsefile
1673 * contains information about the current file being read.
1676 int nparam; /* # of positional parameters (without $0) */
1677 #if ENABLE_ASH_GETOPTS
1678 int optind; /* next parameter to be processed by getopts */
1679 int optoff; /* used by getopts */
1681 unsigned char malloced; /* if parameter list dynamically allocated */
1682 char **p; /* parameter list */
1686 * Free the list of positional parameters.
1689 freeparam(volatile struct shparam *param)
1691 if (param->malloced) {
1693 ap = ap1 = param->p;
1700 #if ENABLE_ASH_GETOPTS
1701 static void getoptsreset(const char *value);
1705 struct var *next; /* next entry in hash list */
1706 int flags; /* flags are defined above */
1707 const char *text; /* name=value */
1708 void (*func)(const char *); /* function to be called when */
1709 /* the variable gets set/unset */
1713 struct localvar *next; /* next local variable in list */
1714 struct var *vp; /* the variable that was made local */
1715 int flags; /* saved flags */
1716 const char *text; /* saved text */
1720 #define VEXPORT 0x01 /* variable is exported */
1721 #define VREADONLY 0x02 /* variable cannot be modified */
1722 #define VSTRFIXED 0x04 /* variable struct is statically allocated */
1723 #define VTEXTFIXED 0x08 /* text is statically allocated */
1724 #define VSTACK 0x10 /* text is allocated on the stack */
1725 #define VUNSET 0x20 /* the variable is not set */
1726 #define VNOFUNC 0x40 /* don't call the callback function */
1727 #define VNOSET 0x80 /* do not set variable - just readonly test */
1728 #define VNOSAVE 0x100 /* when text is on the heap before setvareq */
1729 #if ENABLE_ASH_RANDOM_SUPPORT
1730 # define VDYNAMIC 0x200 /* dynamic variable */
1736 static const char defifsvar[] ALIGN1 = "IFS= \t\n";
1737 #define defifs (defifsvar + 4)
1739 static const char defifs[] ALIGN1 = " \t\n";
1743 /* Need to be before varinit_data[] */
1744 #if ENABLE_LOCALE_SUPPORT
1746 change_lc_all(const char *value)
1748 if (value && *value != '\0')
1749 setlocale(LC_ALL, value);
1752 change_lc_ctype(const char *value)
1754 if (value && *value != '\0')
1755 setlocale(LC_CTYPE, value);
1759 static void chkmail(void);
1760 static void changemail(const char *);
1762 static void changepath(const char *);
1763 #if ENABLE_ASH_RANDOM_SUPPORT
1764 static void change_random(const char *);
1767 static const struct {
1770 void (*func)(const char *);
1771 } varinit_data[] = {
1773 { VSTRFIXED|VTEXTFIXED , defifsvar , NULL },
1775 { VSTRFIXED|VTEXTFIXED|VUNSET, "IFS\0" , NULL },
1778 { VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL\0" , changemail },
1779 { VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH\0", changemail },
1781 { VSTRFIXED|VTEXTFIXED , bb_PATH_root_path, changepath },
1782 { VSTRFIXED|VTEXTFIXED , "PS1=$ " , NULL },
1783 { VSTRFIXED|VTEXTFIXED , "PS2=> " , NULL },
1784 { VSTRFIXED|VTEXTFIXED , "PS4=+ " , NULL },
1785 #if ENABLE_ASH_GETOPTS
1786 { VSTRFIXED|VTEXTFIXED , "OPTIND=1" , getoptsreset },
1788 #if ENABLE_ASH_RANDOM_SUPPORT
1789 { VSTRFIXED|VTEXTFIXED|VUNSET|VDYNAMIC, "RANDOM\0", change_random },
1791 #if ENABLE_LOCALE_SUPPORT
1792 { VSTRFIXED|VTEXTFIXED|VUNSET, "LC_ALL\0" , change_lc_all },
1793 { VSTRFIXED|VTEXTFIXED|VUNSET, "LC_CTYPE\0", change_lc_ctype },
1795 #if ENABLE_FEATURE_EDITING_SAVEHISTORY
1796 { VSTRFIXED|VTEXTFIXED|VUNSET, "HISTFILE\0", NULL },
1802 struct globals_var {
1803 struct shparam shellparam; /* $@ current positional parameters */
1804 struct redirtab *redirlist;
1806 int preverrout_fd; /* save fd2 before print debug if xflag is set. */
1807 struct var *vartab[VTABSIZE];
1808 struct var varinit[ARRAY_SIZE(varinit_data)];
1810 extern struct globals_var *const ash_ptr_to_globals_var;
1811 #define G_var (*ash_ptr_to_globals_var)
1812 #define shellparam (G_var.shellparam )
1813 //#define redirlist (G_var.redirlist )
1814 #define g_nullredirs (G_var.g_nullredirs )
1815 #define preverrout_fd (G_var.preverrout_fd)
1816 #define vartab (G_var.vartab )
1817 #define varinit (G_var.varinit )
1818 #define INIT_G_var() do { \
1820 (*(struct globals_var**)&ash_ptr_to_globals_var) = xzalloc(sizeof(G_var)); \
1822 for (i = 0; i < ARRAY_SIZE(varinit_data); i++) { \
1823 varinit[i].flags = varinit_data[i].flags; \
1824 varinit[i].text = varinit_data[i].text; \
1825 varinit[i].func = varinit_data[i].func; \
1829 #define vifs varinit[0]
1831 # define vmail (&vifs)[1]
1832 # define vmpath (&vmail)[1]
1833 # define vpath (&vmpath)[1]
1835 # define vpath (&vifs)[1]
1837 #define vps1 (&vpath)[1]
1838 #define vps2 (&vps1)[1]
1839 #define vps4 (&vps2)[1]
1840 #if ENABLE_ASH_GETOPTS
1841 # define voptind (&vps4)[1]
1842 # if ENABLE_ASH_RANDOM_SUPPORT
1843 # define vrandom (&voptind)[1]
1846 # if ENABLE_ASH_RANDOM_SUPPORT
1847 # define vrandom (&vps4)[1]
1852 * The following macros access the values of the above variables.
1853 * They have to skip over the name. They return the null string
1854 * for unset variables.
1856 #define ifsval() (vifs.text + 4)
1857 #define ifsset() ((vifs.flags & VUNSET) == 0)
1859 # define mailval() (vmail.text + 5)
1860 # define mpathval() (vmpath.text + 9)
1861 # define mpathset() ((vmpath.flags & VUNSET) == 0)
1863 #define pathval() (vpath.text + 5)
1864 #define ps1val() (vps1.text + 4)
1865 #define ps2val() (vps2.text + 4)
1866 #define ps4val() (vps4.text + 4)
1867 #if ENABLE_ASH_GETOPTS
1868 # define optindval() (voptind.text + 7)
1872 #define is_name(c) ((c) == '_' || isalpha((unsigned char)(c)))
1873 #define is_in_name(c) ((c) == '_' || isalnum((unsigned char)(c)))
1875 #if ENABLE_ASH_GETOPTS
1877 getoptsreset(const char *value)
1879 shellparam.optind = number(value);
1880 shellparam.optoff = -1;
1885 * Return of a legal variable name (a letter or underscore followed by zero or
1886 * more letters, underscores, and digits).
1889 endofname(const char *name)
1897 if (!is_in_name(*p))
1904 * Compares two strings up to the first = or '\0'. The first
1905 * string must be terminated by '='; the second may be terminated by
1906 * either '=' or '\0'.
1909 varcmp(const char *p, const char *q)
1913 while ((c = *p) == (d = *q)) {
1928 varequal(const char *a, const char *b)
1930 return !varcmp(a, b);
1934 * Find the appropriate entry in the hash table from the name.
1936 static struct var **
1937 hashvar(const char *p)
1941 hashval = ((unsigned char) *p) << 4;
1942 while (*p && *p != '=')
1943 hashval += (unsigned char) *p++;
1944 return &vartab[hashval % VTABSIZE];
1948 vpcmp(const void *a, const void *b)
1950 return varcmp(*(const char **)a, *(const char **)b);
1954 * This routine initializes the builtin variables.
1964 * PS1 depends on uid
1966 #if ENABLE_FEATURE_EDITING && ENABLE_FEATURE_EDITING_FANCY_PROMPT
1967 vps1.text = "PS1=\\w \\$ ";
1970 vps1.text = "PS1=# ";
1973 end = vp + ARRAY_SIZE(varinit);
1975 vpp = hashvar(vp->text);
1978 } while (++vp < end);
1981 static struct var **
1982 findvar(struct var **vpp, const char *name)
1984 for (; *vpp; vpp = &(*vpp)->next) {
1985 if (varequal((*vpp)->text, name)) {
1993 * Find the value of a variable. Returns NULL if not set.
1996 lookupvar(const char *name)
2000 v = *findvar(hashvar(name), name);
2002 #if ENABLE_ASH_RANDOM_SUPPORT
2004 * Dynamic variables are implemented roughly the same way they are
2005 * in bash. Namely, they're "special" so long as they aren't unset.
2006 * As soon as they're unset, they're no longer dynamic, and dynamic
2007 * lookup will no longer happen at that point. -- PFM.
2009 if ((v->flags & VDYNAMIC))
2012 if (!(v->flags & VUNSET))
2013 return strchrnul(v->text, '=') + 1;
2019 * Search the environment of a builtin command.
2022 bltinlookup(const char *name)
2026 for (sp = cmdenviron; sp; sp = sp->next) {
2027 if (varequal(sp->text, name))
2028 return strchrnul(sp->text, '=') + 1;
2030 return lookupvar(name);
2034 * Same as setvar except that the variable and value are passed in
2035 * the first argument as name=value. Since the first argument will
2036 * be actually stored in the table, it should not be a string that
2038 * Called with interrupts off.
2041 setvareq(char *s, int flags)
2043 struct var *vp, **vpp;
2046 flags |= (VEXPORT & (((unsigned) (1 - aflag)) - 1));
2047 vp = *findvar(vpp, s);
2049 if ((vp->flags & (VREADONLY|VDYNAMIC)) == VREADONLY) {
2052 if (flags & VNOSAVE)
2055 ash_msg_and_raise_error("%.*s: is read only", strchrnul(n, '=') - n, n);
2061 if (vp->func && (flags & VNOFUNC) == 0)
2062 (*vp->func)(strchrnul(s, '=') + 1);
2064 if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
2065 free((char*)vp->text);
2067 flags |= vp->flags & ~(VTEXTFIXED|VSTACK|VNOSAVE|VUNSET);
2072 vp = ckzalloc(sizeof(*vp));
2074 /*vp->func = NULL; - ckzalloc did it */
2077 if (!(flags & (VTEXTFIXED|VSTACK|VNOSAVE)))
2084 * Set the value of a variable. The flags argument is ored with the
2085 * flags of the variable. If val is NULL, the variable is unset.
2088 setvar(const char *name, const char *val, int flags)
2095 q = endofname(name);
2096 p = strchrnul(q, '=');
2098 if (!namelen || p != q)
2099 ash_msg_and_raise_error("%.*s: bad variable name", namelen, name);
2104 vallen = strlen(val);
2107 nameeq = ckmalloc(namelen + vallen + 2);
2108 p = (char *)memcpy(nameeq, name, namelen) + namelen;
2111 p = (char *)memcpy(p, val, vallen) + vallen;
2114 setvareq(nameeq, flags | VNOSAVE);
2118 #if ENABLE_ASH_GETOPTS
2120 * Safe version of setvar, returns 1 on success 0 on failure.
2123 setvarsafe(const char *name, const char *val, int flags)
2126 volatile int saveint;
2127 struct jmploc *volatile savehandler = exception_handler;
2128 struct jmploc jmploc;
2131 if (setjmp(jmploc.loc))
2134 exception_handler = &jmploc;
2135 setvar(name, val, flags);
2138 exception_handler = savehandler;
2139 RESTORE_INT(saveint);
2145 * Unset the specified variable.
2148 unsetvar(const char *s)
2154 vpp = findvar(hashvar(s), s);
2158 int flags = vp->flags;
2161 if (flags & VREADONLY)
2163 #if ENABLE_ASH_RANDOM_SUPPORT
2164 vp->flags &= ~VDYNAMIC;
2168 if ((flags & VSTRFIXED) == 0) {
2170 if ((flags & (VTEXTFIXED|VSTACK)) == 0)
2171 free((char*)vp->text);
2177 vp->flags &= ~VEXPORT;
2187 * Process a linked list of variable assignments.
2190 listsetvar(struct strlist *list_set_var, int flags)
2192 struct strlist *lp = list_set_var;
2198 setvareq(lp->text, flags);
2205 * Generate a list of variables satisfying the given conditions.
2208 listvars(int on, int off, char ***end)
2219 for (vp = *vpp; vp; vp = vp->next) {
2220 if ((vp->flags & mask) == on) {
2221 if (ep == stackstrend())
2222 ep = growstackstr();
2223 *ep++ = (char *) vp->text;
2226 } while (++vpp < vartab + VTABSIZE);
2227 if (ep == stackstrend())
2228 ep = growstackstr();
2232 return grabstackstr(ep);
2236 /* ============ Path search helper
2238 * The variable path (passed by reference) should be set to the start
2239 * of the path before the first call; padvance will update
2240 * this value as it proceeds. Successive calls to padvance will return
2241 * the possible path expansions in sequence. If an option (indicated by
2242 * a percent sign) appears in the path entry then the global variable
2243 * pathopt will be set to point to it; otherwise pathopt will be set to
2246 static const char *pathopt; /* set by padvance */
2249 padvance(const char **path, const char *name)
2259 for (p = start; *p && *p != ':' && *p != '%'; p++)
2261 len = p - start + strlen(name) + 2; /* "2" is for '/' and '\0' */
2262 while (stackblocksize() < len)
2266 memcpy(q, start, p - start);
2274 while (*p && *p != ':')
2281 return stalloc(len);
2285 /* ============ Prompt */
2287 static smallint doprompt; /* if set, prompt the user */
2288 static smallint needprompt; /* true if interactive and at start of line */
2290 #if ENABLE_FEATURE_EDITING
2291 static line_input_t *line_input_state;
2292 static const char *cmdedit_prompt;
2294 putprompt(const char *s)
2296 if (ENABLE_ASH_EXPAND_PRMT) {
2297 free((char*)cmdedit_prompt);
2298 cmdedit_prompt = ckstrdup(s);
2305 putprompt(const char *s)
2311 #if ENABLE_ASH_EXPAND_PRMT
2312 /* expandstr() needs parsing machinery, so it is far away ahead... */
2313 static const char *expandstr(const char *ps);
2315 #define expandstr(s) s
2319 setprompt(int whichprompt)
2322 #if ENABLE_ASH_EXPAND_PRMT
2323 struct stackmark smark;
2328 switch (whichprompt) {
2338 #if ENABLE_ASH_EXPAND_PRMT
2339 setstackmark(&smark);
2340 stalloc(stackblocksize());
2342 putprompt(expandstr(prompt));
2343 #if ENABLE_ASH_EXPAND_PRMT
2344 popstackmark(&smark);
2349 /* ============ The cd and pwd commands */
2351 #define CD_PHYSICAL 1
2354 static int docd(const char *, int);
2363 while ((i = nextopt("LP"))) {
2365 flags ^= CD_PHYSICAL;
2374 * Update curdir (the name of the current directory) in response to a
2378 updatepwd(const char *dir)
2385 cdcomppath = ststrdup(dir);
2388 if (curdir == nullstr)
2390 new = stack_putstr(curdir, new);
2392 new = makestrspace(strlen(dir) + 2, new);
2393 lim = (char *)stackblock() + 1;
2397 if (new > lim && *lim == '/')
2402 if (dir[1] == '/' && dir[2] != '/') {
2408 p = strtok(cdcomppath, "/");
2412 if (p[1] == '.' && p[2] == '\0') {
2424 new = stack_putstr(p, new);
2432 return stackblock();
2436 * Find out what the current directory is. If we already know the current
2437 * directory, this routine returns immediately.
2442 char *dir = getcwd(NULL, 0); /* huh, using glibc extension? */
2443 return dir ? dir : nullstr;
2447 setpwd(const char *val, int setold)
2451 oldcur = dir = curdir;
2454 setvar("OLDPWD", oldcur, VEXPORT);
2457 if (physdir != nullstr) {
2458 if (physdir != oldcur)
2462 if (oldcur == val || !val) {
2468 dir = ckstrdup(val);
2469 if (oldcur != dir && oldcur != nullstr) {
2474 setvar("PWD", dir, VEXPORT);
2477 static void hashcd(void);
2480 * Actually do the chdir. We also call hashcd to let the routines in exec.c
2481 * know that the current directory has changed.
2484 docd(const char *dest, int flags)
2486 const char *dir = 0;
2489 TRACE(("docd(\"%s\", %d) called\n", dest, flags));
2492 if (!(flags & CD_PHYSICAL)) {
2493 dir = updatepwd(dest);
2508 cdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
2520 dest = bltinlookup(homestr);
2521 else if (LONE_DASH(dest)) {
2522 dest = bltinlookup("OLDPWD");
2544 path = bltinlookup("CDPATH");
2553 p = padvance(&path, dest);
2554 if (stat(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) {
2558 if (!docd(p, flags))
2563 ash_msg_and_raise_error("can't cd to %s", dest);
2566 if (flags & CD_PRINT)
2567 out1fmt(snlfmt, curdir);
2572 pwdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
2575 const char *dir = curdir;
2579 if (physdir == nullstr)
2583 out1fmt(snlfmt, dir);
2588 /* ============ ... */
2591 #define IBUFSIZ COMMON_BUFSIZE
2592 /* buffer for top level input file */
2593 #define basebuf bb_common_bufsiz1
2595 /* Syntax classes */
2596 #define CWORD 0 /* character is nothing special */
2597 #define CNL 1 /* newline character */
2598 #define CBACK 2 /* a backslash character */
2599 #define CSQUOTE 3 /* single quote */
2600 #define CDQUOTE 4 /* double quote */
2601 #define CENDQUOTE 5 /* a terminating quote */
2602 #define CBQUOTE 6 /* backwards single quote */
2603 #define CVAR 7 /* a dollar sign */
2604 #define CENDVAR 8 /* a '}' character */
2605 #define CLP 9 /* a left paren in arithmetic */
2606 #define CRP 10 /* a right paren in arithmetic */
2607 #define CENDFILE 11 /* end of file */
2608 #define CCTL 12 /* like CWORD, except it must be escaped */
2609 #define CSPCL 13 /* these terminate a word */
2610 #define CIGN 14 /* character should be ignored */
2612 #if ENABLE_ASH_ALIAS
2616 #define PEOA_OR_PEOF PEOA
2620 #define PEOA_OR_PEOF PEOF
2623 /* number syntax index */
2624 #define BASESYNTAX 0 /* not in quotes */
2625 #define DQSYNTAX 1 /* in double quotes */
2626 #define SQSYNTAX 2 /* in single quotes */
2627 #define ARISYNTAX 3 /* in arithmetic */
2628 #define PSSYNTAX 4 /* prompt */
2630 #if ENABLE_ASH_OPTIMIZE_FOR_SIZE
2631 #define USE_SIT_FUNCTION
2634 #if ENABLE_ASH_MATH_SUPPORT
2635 static const char S_I_T[][4] = {
2636 #if ENABLE_ASH_ALIAS
2637 { CSPCL, CIGN, CIGN, CIGN }, /* 0, PEOA */
2639 { CSPCL, CWORD, CWORD, CWORD }, /* 1, ' ' */
2640 { CNL, CNL, CNL, CNL }, /* 2, \n */
2641 { CWORD, CCTL, CCTL, CWORD }, /* 3, !*-/:=?[]~ */
2642 { CDQUOTE, CENDQUOTE, CWORD, CWORD }, /* 4, '"' */
2643 { CVAR, CVAR, CWORD, CVAR }, /* 5, $ */
2644 { CSQUOTE, CWORD, CENDQUOTE, CWORD }, /* 6, "'" */
2645 { CSPCL, CWORD, CWORD, CLP }, /* 7, ( */
2646 { CSPCL, CWORD, CWORD, CRP }, /* 8, ) */
2647 { CBACK, CBACK, CCTL, CBACK }, /* 9, \ */
2648 { CBQUOTE, CBQUOTE, CWORD, CBQUOTE }, /* 10, ` */
2649 { CENDVAR, CENDVAR, CWORD, CENDVAR }, /* 11, } */
2650 #ifndef USE_SIT_FUNCTION
2651 { CENDFILE, CENDFILE, CENDFILE, CENDFILE }, /* 12, PEOF */
2652 { CWORD, CWORD, CWORD, CWORD }, /* 13, 0-9A-Za-z */
2653 { CCTL, CCTL, CCTL, CCTL } /* 14, CTLESC ... */
2657 static const char S_I_T[][3] = {
2658 #if ENABLE_ASH_ALIAS
2659 { CSPCL, CIGN, CIGN }, /* 0, PEOA */
2661 { CSPCL, CWORD, CWORD }, /* 1, ' ' */
2662 { CNL, CNL, CNL }, /* 2, \n */
2663 { CWORD, CCTL, CCTL }, /* 3, !*-/:=?[]~ */
2664 { CDQUOTE, CENDQUOTE, CWORD }, /* 4, '"' */
2665 { CVAR, CVAR, CWORD }, /* 5, $ */
2666 { CSQUOTE, CWORD, CENDQUOTE }, /* 6, "'" */
2667 { CSPCL, CWORD, CWORD }, /* 7, ( */
2668 { CSPCL, CWORD, CWORD }, /* 8, ) */
2669 { CBACK, CBACK, CCTL }, /* 9, \ */
2670 { CBQUOTE, CBQUOTE, CWORD }, /* 10, ` */
2671 { CENDVAR, CENDVAR, CWORD }, /* 11, } */
2672 #ifndef USE_SIT_FUNCTION
2673 { CENDFILE, CENDFILE, CENDFILE }, /* 12, PEOF */
2674 { CWORD, CWORD, CWORD }, /* 13, 0-9A-Za-z */
2675 { CCTL, CCTL, CCTL } /* 14, CTLESC ... */
2678 #endif /* ASH_MATH_SUPPORT */
2680 #ifdef USE_SIT_FUNCTION
2683 SIT(int c, int syntax)
2685 static const char spec_symbls[] ALIGN1 = "\t\n !\"$&'()*-/:;<=>?[\\]`|}~";
2686 #if ENABLE_ASH_ALIAS
2687 static const char syntax_index_table[] ALIGN1 = {
2688 1, 2, 1, 3, 4, 5, 1, 6, /* "\t\n !\"$&'" */
2689 7, 8, 3, 3, 3, 3, 1, 1, /* "()*-/:;<" */
2690 3, 1, 3, 3, 9, 3, 10, 1, /* "=>?[\\]`|" */
2694 static const char syntax_index_table[] ALIGN1 = {
2695 0, 1, 0, 2, 3, 4, 0, 5, /* "\t\n !\"$&'" */
2696 6, 7, 2, 2, 2, 2, 0, 0, /* "()*-/:;<" */
2697 2, 0, 2, 2, 8, 2, 9, 0, /* "=>?[\\]`|" */
2704 if (c == PEOF) /* 2^8+2 */
2706 #if ENABLE_ASH_ALIAS
2707 if (c == PEOA) /* 2^8+1 */
2712 if ((unsigned char)c >= (unsigned char)(CTLESC)
2713 && (unsigned char)c <= (unsigned char)(CTLQUOTEMARK)
2717 s = strchrnul(spec_symbls, c);
2720 indx = syntax_index_table[s - spec_symbls];
2721 return S_I_T[indx][syntax];
2724 #else /* !USE_SIT_FUNCTION */
2726 #if ENABLE_ASH_ALIAS
2727 #define CSPCL_CIGN_CIGN_CIGN 0
2728 #define CSPCL_CWORD_CWORD_CWORD 1
2729 #define CNL_CNL_CNL_CNL 2
2730 #define CWORD_CCTL_CCTL_CWORD 3
2731 #define CDQUOTE_CENDQUOTE_CWORD_CWORD 4
2732 #define CVAR_CVAR_CWORD_CVAR 5
2733 #define CSQUOTE_CWORD_CENDQUOTE_CWORD 6
2734 #define CSPCL_CWORD_CWORD_CLP 7
2735 #define CSPCL_CWORD_CWORD_CRP 8
2736 #define CBACK_CBACK_CCTL_CBACK 9
2737 #define CBQUOTE_CBQUOTE_CWORD_CBQUOTE 10
2738 #define CENDVAR_CENDVAR_CWORD_CENDVAR 11
2739 #define CENDFILE_CENDFILE_CENDFILE_CENDFILE 12
2740 #define CWORD_CWORD_CWORD_CWORD 13
2741 #define CCTL_CCTL_CCTL_CCTL 14
2743 #define CSPCL_CWORD_CWORD_CWORD 0
2744 #define CNL_CNL_CNL_CNL 1
2745 #define CWORD_CCTL_CCTL_CWORD 2
2746 #define CDQUOTE_CENDQUOTE_CWORD_CWORD 3
2747 #define CVAR_CVAR_CWORD_CVAR 4
2748 #define CSQUOTE_CWORD_CENDQUOTE_CWORD 5
2749 #define CSPCL_CWORD_CWORD_CLP 6
2750 #define CSPCL_CWORD_CWORD_CRP 7
2751 #define CBACK_CBACK_CCTL_CBACK 8
2752 #define CBQUOTE_CBQUOTE_CWORD_CBQUOTE 9
2753 #define CENDVAR_CENDVAR_CWORD_CENDVAR 10
2754 #define CENDFILE_CENDFILE_CENDFILE_CENDFILE 11
2755 #define CWORD_CWORD_CWORD_CWORD 12
2756 #define CCTL_CCTL_CCTL_CCTL 13
2759 static const char syntax_index_table[258] = {
2760 /* BASESYNTAX_DQSYNTAX_SQSYNTAX_ARISYNTAX */
2761 /* 0 PEOF */ CENDFILE_CENDFILE_CENDFILE_CENDFILE,
2762 #if ENABLE_ASH_ALIAS
2763 /* 1 PEOA */ CSPCL_CIGN_CIGN_CIGN,
2765 /* 2 -128 0x80 */ CWORD_CWORD_CWORD_CWORD,
2766 /* 3 -127 CTLESC */ CCTL_CCTL_CCTL_CCTL,
2767 /* 4 -126 CTLVAR */ CCTL_CCTL_CCTL_CCTL,
2768 /* 5 -125 CTLENDVAR */ CCTL_CCTL_CCTL_CCTL,
2769 /* 6 -124 CTLBACKQ */ CCTL_CCTL_CCTL_CCTL,
2770 /* 7 -123 CTLQUOTE */ CCTL_CCTL_CCTL_CCTL,
2771 /* 8 -122 CTLARI */ CCTL_CCTL_CCTL_CCTL,
2772 /* 9 -121 CTLENDARI */ CCTL_CCTL_CCTL_CCTL,
2773 /* 10 -120 CTLQUOTEMARK */ CCTL_CCTL_CCTL_CCTL,
2774 /* 11 -119 */ CWORD_CWORD_CWORD_CWORD,
2775 /* 12 -118 */ CWORD_CWORD_CWORD_CWORD,
2776 /* 13 -117 */ CWORD_CWORD_CWORD_CWORD,
2777 /* 14 -116 */ CWORD_CWORD_CWORD_CWORD,
2778 /* 15 -115 */ CWORD_CWORD_CWORD_CWORD,
2779 /* 16 -114 */ CWORD_CWORD_CWORD_CWORD,
2780 /* 17 -113 */ CWORD_CWORD_CWORD_CWORD,
2781 /* 18 -112 */ CWORD_CWORD_CWORD_CWORD,
2782 /* 19 -111 */ CWORD_CWORD_CWORD_CWORD,
2783 /* 20 -110 */ CWORD_CWORD_CWORD_CWORD,
2784 /* 21 -109 */ CWORD_CWORD_CWORD_CWORD,
2785 /* 22 -108 */ CWORD_CWORD_CWORD_CWORD,
2786 /* 23 -107 */ CWORD_CWORD_CWORD_CWORD,
2787 /* 24 -106 */ CWORD_CWORD_CWORD_CWORD,
2788 /* 25 -105 */ CWORD_CWORD_CWORD_CWORD,
2789 /* 26 -104 */ CWORD_CWORD_CWORD_CWORD,
2790 /* 27 -103 */ CWORD_CWORD_CWORD_CWORD,
2791 /* 28 -102 */ CWORD_CWORD_CWORD_CWORD,
2792 /* 29 -101 */ CWORD_CWORD_CWORD_CWORD,
2793 /* 30 -100 */ CWORD_CWORD_CWORD_CWORD,
2794 /* 31 -99 */ CWORD_CWORD_CWORD_CWORD,
2795 /* 32 -98 */ CWORD_CWORD_CWORD_CWORD,
2796 /* 33 -97 */ CWORD_CWORD_CWORD_CWORD,
2797 /* 34 -96 */ CWORD_CWORD_CWORD_CWORD,
2798 /* 35 -95 */ CWORD_CWORD_CWORD_CWORD,
2799 /* 36 -94 */ CWORD_CWORD_CWORD_CWORD,
2800 /* 37 -93 */ CWORD_CWORD_CWORD_CWORD,
2801 /* 38 -92 */ CWORD_CWORD_CWORD_CWORD,
2802 /* 39 -91 */ CWORD_CWORD_CWORD_CWORD,
2803 /* 40 -90 */ CWORD_CWORD_CWORD_CWORD,
2804 /* 41 -89 */ CWORD_CWORD_CWORD_CWORD,
2805 /* 42 -88 */ CWORD_CWORD_CWORD_CWORD,
2806 /* 43 -87 */ CWORD_CWORD_CWORD_CWORD,
2807 /* 44 -86 */ CWORD_CWORD_CWORD_CWORD,
2808 /* 45 -85 */ CWORD_CWORD_CWORD_CWORD,
2809 /* 46 -84 */ CWORD_CWORD_CWORD_CWORD,
2810 /* 47 -83 */ CWORD_CWORD_CWORD_CWORD,
2811 /* 48 -82 */ CWORD_CWORD_CWORD_CWORD,
2812 /* 49 -81 */ CWORD_CWORD_CWORD_CWORD,
2813 /* 50 -80 */ CWORD_CWORD_CWORD_CWORD,
2814 /* 51 -79 */ CWORD_CWORD_CWORD_CWORD,
2815 /* 52 -78 */ CWORD_CWORD_CWORD_CWORD,
2816 /* 53 -77 */ CWORD_CWORD_CWORD_CWORD,
2817 /* 54 -76 */ CWORD_CWORD_CWORD_CWORD,
2818 /* 55 -75 */ CWORD_CWORD_CWORD_CWORD,
2819 /* 56 -74 */ CWORD_CWORD_CWORD_CWORD,
2820 /* 57 -73 */ CWORD_CWORD_CWORD_CWORD,
2821 /* 58 -72 */ CWORD_CWORD_CWORD_CWORD,
2822 /* 59 -71 */ CWORD_CWORD_CWORD_CWORD,
2823 /* 60 -70 */ CWORD_CWORD_CWORD_CWORD,
2824 /* 61 -69 */ CWORD_CWORD_CWORD_CWORD,
2825 /* 62 -68 */ CWORD_CWORD_CWORD_CWORD,
2826 /* 63 -67 */ CWORD_CWORD_CWORD_CWORD,
2827 /* 64 -66 */ CWORD_CWORD_CWORD_CWORD,
2828 /* 65 -65 */ CWORD_CWORD_CWORD_CWORD,
2829 /* 66 -64 */ CWORD_CWORD_CWORD_CWORD,
2830 /* 67 -63 */ CWORD_CWORD_CWORD_CWORD,
2831 /* 68 -62 */ CWORD_CWORD_CWORD_CWORD,
2832 /* 69 -61 */ CWORD_CWORD_CWORD_CWORD,
2833 /* 70 -60 */ CWORD_CWORD_CWORD_CWORD,
2834 /* 71 -59 */ CWORD_CWORD_CWORD_CWORD,
2835 /* 72 -58 */ CWORD_CWORD_CWORD_CWORD,
2836 /* 73 -57 */ CWORD_CWORD_CWORD_CWORD,
2837 /* 74 -56 */ CWORD_CWORD_CWORD_CWORD,
2838 /* 75 -55 */ CWORD_CWORD_CWORD_CWORD,
2839 /* 76 -54 */ CWORD_CWORD_CWORD_CWORD,
2840 /* 77 -53 */ CWORD_CWORD_CWORD_CWORD,
2841 /* 78 -52 */ CWORD_CWORD_CWORD_CWORD,
2842 /* 79 -51 */ CWORD_CWORD_CWORD_CWORD,
2843 /* 80 -50 */ CWORD_CWORD_CWORD_CWORD,
2844 /* 81 -49 */ CWORD_CWORD_CWORD_CWORD,
2845 /* 82 -48 */ CWORD_CWORD_CWORD_CWORD,
2846 /* 83 -47 */ CWORD_CWORD_CWORD_CWORD,
2847 /* 84 -46 */ CWORD_CWORD_CWORD_CWORD,
2848 /* 85 -45 */ CWORD_CWORD_CWORD_CWORD,
2849 /* 86 -44 */ CWORD_CWORD_CWORD_CWORD,
2850 /* 87 -43 */ CWORD_CWORD_CWORD_CWORD,
2851 /* 88 -42 */ CWORD_CWORD_CWORD_CWORD,
2852 /* 89 -41 */ CWORD_CWORD_CWORD_CWORD,
2853 /* 90 -40 */ CWORD_CWORD_CWORD_CWORD,
2854 /* 91 -39 */ CWORD_CWORD_CWORD_CWORD,
2855 /* 92 -38 */ CWORD_CWORD_CWORD_CWORD,
2856 /* 93 -37 */ CWORD_CWORD_CWORD_CWORD,
2857 /* 94 -36 */ CWORD_CWORD_CWORD_CWORD,
2858 /* 95 -35 */ CWORD_CWORD_CWORD_CWORD,
2859 /* 96 -34 */ CWORD_CWORD_CWORD_CWORD,
2860 /* 97 -33 */ CWORD_CWORD_CWORD_CWORD,
2861 /* 98 -32 */ CWORD_CWORD_CWORD_CWORD,
2862 /* 99 -31 */ CWORD_CWORD_CWORD_CWORD,
2863 /* 100 -30 */ CWORD_CWORD_CWORD_CWORD,
2864 /* 101 -29 */ CWORD_CWORD_CWORD_CWORD,
2865 /* 102 -28 */ CWORD_CWORD_CWORD_CWORD,
2866 /* 103 -27 */ CWORD_CWORD_CWORD_CWORD,
2867 /* 104 -26 */ CWORD_CWORD_CWORD_CWORD,
2868 /* 105 -25 */ CWORD_CWORD_CWORD_CWORD,
2869 /* 106 -24 */ CWORD_CWORD_CWORD_CWORD,
2870 /* 107 -23 */ CWORD_CWORD_CWORD_CWORD,
2871 /* 108 -22 */ CWORD_CWORD_CWORD_CWORD,
2872 /* 109 -21 */ CWORD_CWORD_CWORD_CWORD,
2873 /* 110 -20 */ CWORD_CWORD_CWORD_CWORD,
2874 /* 111 -19 */ CWORD_CWORD_CWORD_CWORD,
2875 /* 112 -18 */ CWORD_CWORD_CWORD_CWORD,
2876 /* 113 -17 */ CWORD_CWORD_CWORD_CWORD,
2877 /* 114 -16 */ CWORD_CWORD_CWORD_CWORD,
2878 /* 115 -15 */ CWORD_CWORD_CWORD_CWORD,
2879 /* 116 -14 */ CWORD_CWORD_CWORD_CWORD,
2880 /* 117 -13 */ CWORD_CWORD_CWORD_CWORD,
2881 /* 118 -12 */ CWORD_CWORD_CWORD_CWORD,
2882 /* 119 -11 */ CWORD_CWORD_CWORD_CWORD,
2883 /* 120 -10 */ CWORD_CWORD_CWORD_CWORD,
2884 /* 121 -9 */ CWORD_CWORD_CWORD_CWORD,
2885 /* 122 -8 */ CWORD_CWORD_CWORD_CWORD,
2886 /* 123 -7 */ CWORD_CWORD_CWORD_CWORD,
2887 /* 124 -6 */ CWORD_CWORD_CWORD_CWORD,
2888 /* 125 -5 */ CWORD_CWORD_CWORD_CWORD,
2889 /* 126 -4 */ CWORD_CWORD_CWORD_CWORD,
2890 /* 127 -3 */ CWORD_CWORD_CWORD_CWORD,
2891 /* 128 -2 */ CWORD_CWORD_CWORD_CWORD,
2892 /* 129 -1 */ CWORD_CWORD_CWORD_CWORD,
2893 /* 130 0 */ CWORD_CWORD_CWORD_CWORD,
2894 /* 131 1 */ CWORD_CWORD_CWORD_CWORD,
2895 /* 132 2 */ CWORD_CWORD_CWORD_CWORD,
2896 /* 133 3 */ CWORD_CWORD_CWORD_CWORD,
2897 /* 134 4 */ CWORD_CWORD_CWORD_CWORD,
2898 /* 135 5 */ CWORD_CWORD_CWORD_CWORD,
2899 /* 136 6 */ CWORD_CWORD_CWORD_CWORD,
2900 /* 137 7 */ CWORD_CWORD_CWORD_CWORD,
2901 /* 138 8 */ CWORD_CWORD_CWORD_CWORD,
2902 /* 139 9 "\t" */ CSPCL_CWORD_CWORD_CWORD,
2903 /* 140 10 "\n" */ CNL_CNL_CNL_CNL,
2904 /* 141 11 */ CWORD_CWORD_CWORD_CWORD,
2905 /* 142 12 */ CWORD_CWORD_CWORD_CWORD,
2906 /* 143 13 */ CWORD_CWORD_CWORD_CWORD,
2907 /* 144 14 */ CWORD_CWORD_CWORD_CWORD,
2908 /* 145 15 */ CWORD_CWORD_CWORD_CWORD,
2909 /* 146 16 */ CWORD_CWORD_CWORD_CWORD,
2910 /* 147 17 */ CWORD_CWORD_CWORD_CWORD,
2911 /* 148 18 */ CWORD_CWORD_CWORD_CWORD,
2912 /* 149 19 */ CWORD_CWORD_CWORD_CWORD,
2913 /* 150 20 */ CWORD_CWORD_CWORD_CWORD,
2914 /* 151 21 */ CWORD_CWORD_CWORD_CWORD,
2915 /* 152 22 */ CWORD_CWORD_CWORD_CWORD,
2916 /* 153 23 */ CWORD_CWORD_CWORD_CWORD,
2917 /* 154 24 */ CWORD_CWORD_CWORD_CWORD,
2918 /* 155 25 */ CWORD_CWORD_CWORD_CWORD,
2919 /* 156 26 */ CWORD_CWORD_CWORD_CWORD,
2920 /* 157 27 */ CWORD_CWORD_CWORD_CWORD,
2921 /* 158 28 */ CWORD_CWORD_CWORD_CWORD,
2922 /* 159 29 */ CWORD_CWORD_CWORD_CWORD,
2923 /* 160 30 */ CWORD_CWORD_CWORD_CWORD,
2924 /* 161 31 */ CWORD_CWORD_CWORD_CWORD,
2925 /* 162 32 " " */ CSPCL_CWORD_CWORD_CWORD,
2926 /* 163 33 "!" */ CWORD_CCTL_CCTL_CWORD,
2927 /* 164 34 """ */ CDQUOTE_CENDQUOTE_CWORD_CWORD,
2928 /* 165 35 "#" */ CWORD_CWORD_CWORD_CWORD,
2929 /* 166 36 "$" */ CVAR_CVAR_CWORD_CVAR,
2930 /* 167 37 "%" */ CWORD_CWORD_CWORD_CWORD,
2931 /* 168 38 "&" */ CSPCL_CWORD_CWORD_CWORD,
2932 /* 169 39 "'" */ CSQUOTE_CWORD_CENDQUOTE_CWORD,
2933 /* 170 40 "(" */ CSPCL_CWORD_CWORD_CLP,
2934 /* 171 41 ")" */ CSPCL_CWORD_CWORD_CRP,
2935 /* 172 42 "*" */ CWORD_CCTL_CCTL_CWORD,
2936 /* 173 43 "+" */ CWORD_CWORD_CWORD_CWORD,
2937 /* 174 44 "," */ CWORD_CWORD_CWORD_CWORD,
2938 /* 175 45 "-" */ CWORD_CCTL_CCTL_CWORD,
2939 /* 176 46 "." */ CWORD_CWORD_CWORD_CWORD,
2940 /* 177 47 "/" */ CWORD_CCTL_CCTL_CWORD,
2941 /* 178 48 "0" */ CWORD_CWORD_CWORD_CWORD,
2942 /* 179 49 "1" */ CWORD_CWORD_CWORD_CWORD,
2943 /* 180 50 "2" */ CWORD_CWORD_CWORD_CWORD,
2944 /* 181 51 "3" */ CWORD_CWORD_CWORD_CWORD,
2945 /* 182 52 "4" */ CWORD_CWORD_CWORD_CWORD,
2946 /* 183 53 "5" */ CWORD_CWORD_CWORD_CWORD,
2947 /* 184 54 "6" */ CWORD_CWORD_CWORD_CWORD,
2948 /* 185 55 "7" */ CWORD_CWORD_CWORD_CWORD,
2949 /* 186 56 "8" */ CWORD_CWORD_CWORD_CWORD,
2950 /* 187 57 "9" */ CWORD_CWORD_CWORD_CWORD,
2951 /* 188 58 ":" */ CWORD_CCTL_CCTL_CWORD,
2952 /* 189 59 ";" */ CSPCL_CWORD_CWORD_CWORD,
2953 /* 190 60 "<" */ CSPCL_CWORD_CWORD_CWORD,
2954 /* 191 61 "=" */ CWORD_CCTL_CCTL_CWORD,
2955 /* 192 62 ">" */ CSPCL_CWORD_CWORD_CWORD,
2956 /* 193 63 "?" */ CWORD_CCTL_CCTL_CWORD,
2957 /* 194 64 "@" */ CWORD_CWORD_CWORD_CWORD,
2958 /* 195 65 "A" */ CWORD_CWORD_CWORD_CWORD,
2959 /* 196 66 "B" */ CWORD_CWORD_CWORD_CWORD,
2960 /* 197 67 "C" */ CWORD_CWORD_CWORD_CWORD,
2961 /* 198 68 "D" */ CWORD_CWORD_CWORD_CWORD,
2962 /* 199 69 "E" */ CWORD_CWORD_CWORD_CWORD,
2963 /* 200 70 "F" */ CWORD_CWORD_CWORD_CWORD,
2964 /* 201 71 "G" */ CWORD_CWORD_CWORD_CWORD,
2965 /* 202 72 "H" */ CWORD_CWORD_CWORD_CWORD,
2966 /* 203 73 "I" */ CWORD_CWORD_CWORD_CWORD,
2967 /* 204 74 "J" */ CWORD_CWORD_CWORD_CWORD,
2968 /* 205 75 "K" */ CWORD_CWORD_CWORD_CWORD,
2969 /* 206 76 "L" */ CWORD_CWORD_CWORD_CWORD,
2970 /* 207 77 "M" */ CWORD_CWORD_CWORD_CWORD,
2971 /* 208 78 "N" */ CWORD_CWORD_CWORD_CWORD,
2972 /* 209 79 "O" */ CWORD_CWORD_CWORD_CWORD,
2973 /* 210 80 "P" */ CWORD_CWORD_CWORD_CWORD,
2974 /* 211 81 "Q" */ CWORD_CWORD_CWORD_CWORD,
2975 /* 212 82 "R" */ CWORD_CWORD_CWORD_CWORD,
2976 /* 213 83 "S" */ CWORD_CWORD_CWORD_CWORD,
2977 /* 214 84 "T" */ CWORD_CWORD_CWORD_CWORD,
2978 /* 215 85 "U" */ CWORD_CWORD_CWORD_CWORD,
2979 /* 216 86 "V" */ CWORD_CWORD_CWORD_CWORD,
2980 /* 217 87 "W" */ CWORD_CWORD_CWORD_CWORD,
2981 /* 218 88 "X" */ CWORD_CWORD_CWORD_CWORD,
2982 /* 219 89 "Y" */ CWORD_CWORD_CWORD_CWORD,
2983 /* 220 90 "Z" */ CWORD_CWORD_CWORD_CWORD,
2984 /* 221 91 "[" */ CWORD_CCTL_CCTL_CWORD,
2985 /* 222 92 "\" */ CBACK_CBACK_CCTL_CBACK,
2986 /* 223 93 "]" */ CWORD_CCTL_CCTL_CWORD,
2987 /* 224 94 "^" */ CWORD_CWORD_CWORD_CWORD,
2988 /* 225 95 "_" */ CWORD_CWORD_CWORD_CWORD,
2989 /* 226 96 "`" */ CBQUOTE_CBQUOTE_CWORD_CBQUOTE,
2990 /* 227 97 "a" */ CWORD_CWORD_CWORD_CWORD,
2991 /* 228 98 "b" */ CWORD_CWORD_CWORD_CWORD,
2992 /* 229 99 "c" */ CWORD_CWORD_CWORD_CWORD,
2993 /* 230 100 "d" */ CWORD_CWORD_CWORD_CWORD,
2994 /* 231 101 "e" */ CWORD_CWORD_CWORD_CWORD,
2995 /* 232 102 "f" */ CWORD_CWORD_CWORD_CWORD,
2996 /* 233 103 "g" */ CWORD_CWORD_CWORD_CWORD,
2997 /* 234 104 "h" */ CWORD_CWORD_CWORD_CWORD,
2998 /* 235 105 "i" */ CWORD_CWORD_CWORD_CWORD,
2999 /* 236 106 "j" */ CWORD_CWORD_CWORD_CWORD,
3000 /* 237 107 "k" */ CWORD_CWORD_CWORD_CWORD,
3001 /* 238 108 "l" */ CWORD_CWORD_CWORD_CWORD,
3002 /* 239 109 "m" */ CWORD_CWORD_CWORD_CWORD,
3003 /* 240 110 "n" */ CWORD_CWORD_CWORD_CWORD,
3004 /* 241 111 "o" */ CWORD_CWORD_CWORD_CWORD,
3005 /* 242 112 "p" */ CWORD_CWORD_CWORD_CWORD,
3006 /* 243 113 "q" */ CWORD_CWORD_CWORD_CWORD,
3007 /* 244 114 "r" */ CWORD_CWORD_CWORD_CWORD,
3008 /* 245 115 "s" */ CWORD_CWORD_CWORD_CWORD,
3009 /* 246 116 "t" */ CWORD_CWORD_CWORD_CWORD,
3010 /* 247 117 "u" */ CWORD_CWORD_CWORD_CWORD,
3011 /* 248 118 "v" */ CWORD_CWORD_CWORD_CWORD,
3012 /* 249 119 "w" */ CWORD_CWORD_CWORD_CWORD,
3013 /* 250 120 "x" */ CWORD_CWORD_CWORD_CWORD,
3014 /* 251 121 "y" */ CWORD_CWORD_CWORD_CWORD,
3015 /* 252 122 "z" */ CWORD_CWORD_CWORD_CWORD,
3016 /* 253 123 "{" */ CWORD_CWORD_CWORD_CWORD,
3017 /* 254 124 "|" */ CSPCL_CWORD_CWORD_CWORD,
3018 /* 255 125 "}" */ CENDVAR_CENDVAR_CWORD_CENDVAR,
3019 /* 256 126 "~" */ CWORD_CCTL_CCTL_CWORD,
3020 /* 257 127 */ CWORD_CWORD_CWORD_CWORD,
3023 #define SIT(c, syntax) (S_I_T[(int)syntax_index_table[((int)c)+SYNBASE]][syntax])
3025 #endif /* USE_SIT_FUNCTION */
3028 /* ============ Alias handling */
3030 #if ENABLE_ASH_ALIAS
3032 #define ALIASINUSE 1
3043 static struct alias **atab; // [ATABSIZE];
3044 #define INIT_G_alias() do { \
3045 atab = xzalloc(ATABSIZE * sizeof(atab[0])); \
3049 static struct alias **
3050 __lookupalias(const char *name) {
3051 unsigned int hashval;
3058 ch = (unsigned char)*p;
3062 ch = (unsigned char)*++p;
3064 app = &atab[hashval % ATABSIZE];
3066 for (; *app; app = &(*app)->next) {
3067 if (strcmp(name, (*app)->name) == 0) {
3075 static struct alias *
3076 lookupalias(const char *name, int check)
3078 struct alias *ap = *__lookupalias(name);
3080 if (check && ap && (ap->flag & ALIASINUSE))
3085 static struct alias *
3086 freealias(struct alias *ap)
3090 if (ap->flag & ALIASINUSE) {
3091 ap->flag |= ALIASDEAD;
3103 setalias(const char *name, const char *val)
3105 struct alias *ap, **app;
3107 app = __lookupalias(name);
3111 if (!(ap->flag & ALIASINUSE)) {
3114 ap->val = ckstrdup(val);
3115 ap->flag &= ~ALIASDEAD;
3118 ap = ckzalloc(sizeof(struct alias));
3119 ap->name = ckstrdup(name);
3120 ap->val = ckstrdup(val);
3121 /*ap->flag = 0; - ckzalloc did it */
3122 /*ap->next = NULL;*/
3129 unalias(const char *name)
3133 app = __lookupalias(name);
3137 *app = freealias(*app);
3148 struct alias *ap, **app;
3152 for (i = 0; i < ATABSIZE; i++) {
3154 for (ap = *app; ap; ap = *app) {
3155 *app = freealias(*app);
3165 printalias(const struct alias *ap)
3167 out1fmt("%s=%s\n", ap->name, single_quote(ap->val));
3171 * TODO - sort output
3174 aliascmd(int argc UNUSED_PARAM, char **argv)
3183 for (i = 0; i < ATABSIZE; i++) {
3184 for (ap = atab[i]; ap; ap = ap->next) {
3190 while ((n = *++argv) != NULL) {
3191 v = strchr(n+1, '=');
3192 if (v == NULL) { /* n+1: funny ksh stuff */
3193 ap = *__lookupalias(n);
3195 fprintf(stderr, "%s: %s not found\n", "alias", n);
3209 unaliascmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
3213 while ((i = nextopt("a")) != '\0') {
3219 for (i = 0; *argptr; argptr++) {
3220 if (unalias(*argptr)) {
3221 fprintf(stderr, "%s: %s not found\n", "unalias", *argptr);
3229 #endif /* ASH_ALIAS */
3232 /* ============ jobs.c */
3234 /* Mode argument to forkshell. Don't change FORK_FG or FORK_BG. */
3237 #define FORK_NOJOB 2
3239 /* mode flags for showjob(s) */
3240 #define SHOW_PGID 0x01 /* only show pgid - for jobs -p */
3241 #define SHOW_PID 0x04 /* include process pid */
3242 #define SHOW_CHANGED 0x08 /* only jobs whose state has changed */
3245 * A job structure contains information about a job. A job is either a
3246 * single process or a set of processes contained in a pipeline. In the
3247 * latter case, pidlist will be non-NULL, and will point to a -1 terminated
3252 pid_t pid; /* process id */
3253 int status; /* last process status from wait() */
3254 char *cmd; /* text of command being run */
3258 struct procstat ps0; /* status of process */
3259 struct procstat *ps; /* status or processes when more than one */
3261 int stopstatus; /* status of a stopped job */
3264 nprocs: 16, /* number of processes */
3266 #define JOBRUNNING 0 /* at least one proc running */
3267 #define JOBSTOPPED 1 /* all procs are stopped */
3268 #define JOBDONE 2 /* all procs are completed */
3270 sigint: 1, /* job was killed by SIGINT */
3271 jobctl: 1, /* job running under job control */
3273 waited: 1, /* true if this entry has been waited for */
3274 used: 1, /* true if this entry is in used */
3275 changed: 1; /* true if status has changed */
3276 struct job *prev_job; /* previous job */
3279 static struct job *makejob(/*union node *,*/ int);
3281 #define forkshell(job, node, mode) forkshell(job, mode)
3283 static int forkshell(struct job *, union node *, int);
3284 static int waitforjob(struct job *);
3287 enum { doing_jobctl = 0 };
3288 #define setjobctl(on) do {} while (0)
3290 static smallint doing_jobctl; //references:8
3291 static void setjobctl(int);
3298 ignoresig(int signo)
3300 /* Avoid unnecessary system calls. Is it already SIG_IGNed? */
3301 if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) {
3302 /* No, need to do it */
3303 signal(signo, SIG_IGN);
3305 sigmode[signo - 1] = S_HARD_IGN;
3309 * Signal handler. Only one usage site - in setsignal()
3314 gotsig[signo - 1] = 1;
3316 if (/* exsig || */ (signo == SIGINT && !trap[SIGINT])) {
3319 raise_interrupt(); /* does not return */
3328 * Set the signal handler for the specified signal. The routine figures
3329 * out what it should be set to.
3332 setsignal(int signo)
3335 char cur_act, new_act;
3336 struct sigaction act;
3340 if (t != NULL) { /* trap for this sig is set */
3342 if (t[0] == '\0') /* trap is "": ignore this sig */
3346 if (rootshell && new_act == S_DFL) {
3349 if (iflag || minusc || sflag == 0)
3358 * "In all cases, bash ignores SIGQUIT. Non-builtin
3359 * commands run by bash have signal handlers
3360 * set to the values inherited by the shell
3361 * from its parent". */
3377 //TODO: if !rootshell, we reset SIGQUIT to DFL,
3378 //whereas we have to restore it to what shell got on entry
3379 //from the parent. See comment above
3381 t = &sigmode[signo - 1];
3384 /* current setting is not yet known */
3385 if (sigaction(signo, NULL, &act)) {
3386 /* pretend it worked; maybe we should give a warning,
3387 * but other shells don't. We don't alter sigmode,
3388 * so we retry every time.
3389 * btw, in Linux it never fails. --vda */
3392 if (act.sa_handler == SIG_IGN) {
3393 cur_act = S_HARD_IGN;
3395 && (signo == SIGTSTP || signo == SIGTTIN || signo == SIGTTOU)
3397 cur_act = S_IGN; /* don't hard ignore these */
3401 if (cur_act == S_HARD_IGN || cur_act == new_act)
3404 act.sa_handler = SIG_DFL;
3407 act.sa_handler = onsig;
3408 act.sa_flags = 0; /* matters only if !DFL and !IGN */
3409 sigfillset(&act.sa_mask); /* ditto */
3412 act.sa_handler = SIG_IGN;
3415 sigaction_set(signo, &act);
3420 /* mode flags for set_curjob */
3421 #define CUR_DELETE 2
3422 #define CUR_RUNNING 1
3423 #define CUR_STOPPED 0
3425 /* mode flags for dowait */
3426 #define DOWAIT_NONBLOCK WNOHANG
3427 #define DOWAIT_BLOCK 0
3430 /* pgrp of shell on invocation */
3431 static int initialpgrp; //references:2
3432 static int ttyfd = -1; //5
3435 static struct job *jobtab; //5
3437 static unsigned njobs; //4
3439 static struct job *curjob; //lots
3440 /* number of presumed living untracked jobs */
3441 static int jobless; //4
3444 set_curjob(struct job *jp, unsigned mode)
3447 struct job **jpp, **curp;
3449 /* first remove from list */
3450 jpp = curp = &curjob;
3455 jpp = &jp1->prev_job;
3457 *jpp = jp1->prev_job;
3459 /* Then re-insert in correct position */
3467 /* job being deleted */
3470 /* newly created job or backgrounded job,
3471 put after all stopped jobs. */
3475 if (!jp1 || jp1->state != JOBSTOPPED)
3478 jpp = &jp1->prev_job;
3484 /* newly stopped job - becomes curjob */
3485 jp->prev_job = *jpp;
3493 jobno(const struct job *jp)
3495 return jp - jobtab + 1;
3500 * Convert a job name to a job structure.
3503 #define getjob(name, getctl) getjob(name)
3506 getjob(const char *name, int getctl)
3510 const char *err_msg = "No such job: %s";
3514 char *(*match)(const char *, const char *);
3529 if (c == '+' || c == '%') {
3531 err_msg = "No current job";
3537 err_msg = "No previous job";
3546 // TODO: number() instead? It does error checking...
3549 jp = jobtab + num - 1;
3566 if (match(jp->ps[0].cmd, p)) {
3570 err_msg = "%s: ambiguous";
3577 err_msg = "job %s not created under job control";
3578 if (getctl && jp->jobctl == 0)
3583 ash_msg_and_raise_error(err_msg, name);
3587 * Mark a job structure as unused.
3590 freejob(struct job *jp)
3592 struct procstat *ps;
3596 for (i = jp->nprocs, ps = jp->ps; --i >= 0; ps++) {
3597 if (ps->cmd != nullstr)
3600 if (jp->ps != &jp->ps0)
3603 set_curjob(jp, CUR_DELETE);
3609 xtcsetpgrp(int fd, pid_t pgrp)
3611 if (tcsetpgrp(fd, pgrp))
3612 ash_msg_and_raise_error("can't set tty process group (%m)");
3616 * Turn job control on and off.
3618 * Note: This code assumes that the third arg to ioctl is a character
3619 * pointer, which is true on Berkeley systems but not System V. Since
3620 * System V doesn't have job control yet, this isn't a problem now.
3622 * Called with interrupts off.
3630 if (on == doing_jobctl || rootshell == 0)
3634 ofd = fd = open(_PATH_TTY, O_RDWR);
3636 /* BTW, bash will try to open(ttyname(0)) if open("/dev/tty") fails.
3637 * That sometimes helps to acquire controlling tty.
3638 * Obviously, a workaround for bugs when someone
3639 * failed to provide a controlling tty to bash! :) */
3645 fd = fcntl(fd, F_DUPFD, 10);
3650 /* fd is a tty at this point */
3651 close_on_exec_on(fd);
3652 do { /* while we are in the background */
3653 pgrp = tcgetpgrp(fd);
3656 ash_msg("can't access tty; job control turned off");
3660 if (pgrp == getpgrp())
3671 xtcsetpgrp(fd, pgrp);
3673 /* turning job control off */
3676 /* was xtcsetpgrp, but this can make exiting ash
3677 * loop forever if pty is already deleted */
3678 tcsetpgrp(fd, pgrp);
3693 killcmd(int argc, char **argv)
3696 if (argv[1] && strcmp(argv[1], "-l") != 0) {
3698 if (argv[i][0] == '%') {
3699 struct job *jp = getjob(argv[i], 0);
3700 unsigned pid = jp->ps[0].pid;
3701 /* Enough space for ' -NNN<nul>' */
3702 argv[i] = alloca(sizeof(int)*3 + 3);
3703 /* kill_main has matching code to expect
3704 * leading space. Needed to not confuse
3705 * negative pids with "kill -SIGNAL_NO" syntax */
3706 sprintf(argv[i], " -%u", pid);
3708 } while (argv[++i]);
3710 return kill_main(argc, argv);
3714 showpipe(struct job *jp, FILE *out)
3716 struct procstat *sp;
3717 struct procstat *spend;
3719 spend = jp->ps + jp->nprocs;
3720 for (sp = jp->ps + 1; sp < spend; sp++)
3721 fprintf(out, " | %s", sp->cmd);
3722 outcslow('\n', out);
3723 flush_stdout_stderr();
3728 restartjob(struct job *jp, int mode)
3730 struct procstat *ps;
3736 if (jp->state == JOBDONE)
3738 jp->state = JOBRUNNING;
3740 if (mode == FORK_FG)
3741 xtcsetpgrp(ttyfd, pgid);
3742 killpg(pgid, SIGCONT);
3746 if (WIFSTOPPED(ps->status)) {
3752 status = (mode == FORK_FG) ? waitforjob(jp) : 0;
3758 fg_bgcmd(int argc UNUSED_PARAM, char **argv)
3765 mode = (**argv == 'f') ? FORK_FG : FORK_BG;
3770 jp = getjob(*argv, 1);
3771 if (mode == FORK_BG) {
3772 set_curjob(jp, CUR_RUNNING);
3773 fprintf(out, "[%d] ", jobno(jp));
3775 outstr(jp->ps->cmd, out);
3777 retval = restartjob(jp, mode);
3778 } while (*argv && *++argv);
3784 sprint_status(char *s, int status, int sigonly)
3790 if (!WIFEXITED(status)) {
3792 if (WIFSTOPPED(status))
3793 st = WSTOPSIG(status);
3796 st = WTERMSIG(status);
3798 if (st == SIGINT || st == SIGPIPE)
3801 if (WIFSTOPPED(status))
3806 col = fmtstr(s, 32, strsignal(st));
3807 if (WCOREDUMP(status)) {
3808 col += fmtstr(s + col, 16, " (core dumped)");
3810 } else if (!sigonly) {
3811 st = WEXITSTATUS(status);
3813 col = fmtstr(s, 16, "Done(%d)", st);
3815 col = fmtstr(s, 16, "Done");
3822 dowait(int wait_flags, struct job *job)
3827 struct job *thisjob;
3830 TRACE(("dowait(0x%x) called\n", wait_flags));
3832 /* Do a wait system call. If job control is compiled in, we accept
3833 * stopped processes. wait_flags may have WNOHANG, preventing blocking.
3834 * NB: _not_ safe_waitpid, we need to detect EINTR */
3835 pid = waitpid(-1, &status,
3836 (doing_jobctl ? (wait_flags | WUNTRACED) : wait_flags));
3837 TRACE(("wait returns pid=%d, status=0x%x, errno=%d(%s)\n",
3838 pid, status, errno, strerror(errno)));
3844 for (jp = curjob; jp; jp = jp->prev_job) {
3845 struct procstat *sp;
3846 struct procstat *spend;
3847 if (jp->state == JOBDONE)
3850 spend = jp->ps + jp->nprocs;
3853 if (sp->pid == pid) {
3854 TRACE(("Job %d: changing status of proc %d "
3855 "from 0x%x to 0x%x\n",
3856 jobno(jp), pid, sp->status, status));
3857 sp->status = status;
3860 if (sp->status == -1)
3863 if (state == JOBRUNNING)
3865 if (WIFSTOPPED(sp->status)) {
3866 jp->stopstatus = sp->status;
3870 } while (++sp < spend);
3875 if (!WIFSTOPPED(status))
3881 if (state != JOBRUNNING) {
3882 thisjob->changed = 1;
3884 if (thisjob->state != state) {
3885 TRACE(("Job %d: changing state from %d to %d\n",
3886 jobno(thisjob), thisjob->state, state));
3887 thisjob->state = state;
3889 if (state == JOBSTOPPED) {
3890 set_curjob(thisjob, CUR_STOPPED);
3899 if (thisjob && thisjob == job) {
3903 len = sprint_status(s, status, 1);
3914 blocking_wait_with_raise_on_sig(struct job *job)
3916 pid_t pid = dowait(DOWAIT_BLOCK, job);
3917 if (pid <= 0 && pendingsig)
3918 raise_exception(EXSIG);
3924 showjob(FILE *out, struct job *jp, int mode)
3926 struct procstat *ps;
3927 struct procstat *psend;
3934 if (mode & SHOW_PGID) {
3935 /* just output process (group) id of pipeline */
3936 fprintf(out, "%d\n", ps->pid);
3940 col = fmtstr(s, 16, "[%d] ", jobno(jp));
3945 else if (curjob && jp == curjob->prev_job)
3948 if (mode & SHOW_PID)
3949 col += fmtstr(s + col, 16, "%d ", ps->pid);
3951 psend = ps + jp->nprocs;
3953 if (jp->state == JOBRUNNING) {
3954 strcpy(s + col, "Running");
3955 col += sizeof("Running") - 1;
3957 int status = psend[-1].status;
3958 if (jp->state == JOBSTOPPED)
3959 status = jp->stopstatus;
3960 col += sprint_status(s + col, status, 0);
3966 /* for each process */
3967 col = fmtstr(s, 48, " |\n%*c%d ", indent_col, ' ', ps->pid) - 3;
3969 fprintf(out, "%s%*c%s",
3970 s, 33 - col >= 0 ? 33 - col : 0, ' ', ps->cmd
3972 if (!(mode & SHOW_PID)) {
3976 if (++ps == psend) {
3977 outcslow('\n', out);
3984 if (jp->state == JOBDONE) {
3985 TRACE(("showjob: freeing job %d\n", jobno(jp)));
3991 * Print a list of jobs. If "change" is nonzero, only print jobs whose
3992 * statuses have changed since the last call to showjobs.
3995 showjobs(FILE *out, int mode)
3999 TRACE(("showjobs(%x) called\n", mode));
4001 /* Handle all finished jobs */
4002 while (dowait(DOWAIT_NONBLOCK, NULL) > 0)
4005 for (jp = curjob; jp; jp = jp->prev_job) {
4006 if (!(mode & SHOW_CHANGED) || jp->changed) {
4007 showjob(out, jp, mode);
4013 jobscmd(int argc UNUSED_PARAM, char **argv)
4018 while ((m = nextopt("lp"))) {
4028 showjob(stdout, getjob(*argv,0), mode);
4031 showjobs(stdout, mode);
4038 getstatus(struct job *job)
4043 status = job->ps[job->nprocs - 1].status;
4044 retval = WEXITSTATUS(status);
4045 if (!WIFEXITED(status)) {
4047 retval = WSTOPSIG(status);
4048 if (!WIFSTOPPED(status))
4051 /* XXX: limits number of signals */
4052 retval = WTERMSIG(status);
4054 if (retval == SIGINT)
4060 TRACE(("getstatus: job %d, nproc %d, status %x, retval %x\n",
4061 jobno(job), job->nprocs, status, retval));
4066 waitcmd(int argc UNUSED_PARAM, char **argv)
4075 raise_exception(EXSIG);
4082 /* wait for all jobs */
4086 if (!jp) /* no running procs */
4088 if (jp->state == JOBRUNNING)
4094 * "When bash is waiting for an asynchronous command via
4095 * the wait builtin, the reception of a signal for which a trap
4096 * has been set will cause the wait builtin to return immediately
4097 * with an exit status greater than 128, immediately after which
4098 * the trap is executed."
4099 * Do we do it that way? */
4100 blocking_wait_with_raise_on_sig(NULL);
4106 if (**argv != '%') {
4107 pid_t pid = number(*argv);
4112 if (job->ps[job->nprocs - 1].pid == pid)
4114 job = job->prev_job;
4117 job = getjob(*argv, 0);
4118 /* loop until process terminated or stopped */
4119 while (job->state == JOBRUNNING)
4120 blocking_wait_with_raise_on_sig(NULL);
4122 retval = getstatus(job);
4135 struct job *jp, *jq;
4137 len = njobs * sizeof(*jp);
4139 jp = ckrealloc(jq, len + 4 * sizeof(*jp));
4141 offset = (char *)jp - (char *)jq;
4143 /* Relocate pointers */
4146 jq = (struct job *)((char *)jq + l);
4150 #define joff(p) ((struct job *)((char *)(p) + l))
4151 #define jmove(p) (p) = (void *)((char *)(p) + offset)
4152 if (joff(jp)->ps == &jq->ps0)
4153 jmove(joff(jp)->ps);
4154 if (joff(jp)->prev_job)
4155 jmove(joff(jp)->prev_job);
4165 jp = (struct job *)((char *)jp + len);
4169 } while (--jq >= jp);
4174 * Return a new job structure.
4175 * Called with interrupts off.
4178 makejob(/*union node *node,*/ int nprocs)
4183 for (i = njobs, jp = jobtab; ; jp++) {
4190 if (jp->state != JOBDONE || !jp->waited)
4199 memset(jp, 0, sizeof(*jp));
4201 /* jp->jobctl is a bitfield.
4202 * "jp->jobctl |= jobctl" likely to give awful code */
4206 jp->prev_job = curjob;
4211 jp->ps = ckmalloc(nprocs * sizeof(struct procstat));
4213 TRACE(("makejob(%d) returns %%%d\n", nprocs,
4220 * Return a string identifying a command (to be printed by the
4223 static char *cmdnextc;
4226 cmdputs(const char *s)
4228 static const char vstype[VSTYPE + 1][3] = {
4229 "", "}", "-", "+", "?", "=",
4230 "%", "%%", "#", "##"
4231 USE_ASH_BASH_COMPAT(, ":", "/", "//")
4234 const char *p, *str;
4235 char c, cc[2] = " ";
4240 nextc = makestrspace((strlen(s) + 1) * 8, cmdnextc);
4242 while ((c = *p++) != 0) {
4250 if ((subtype & VSTYPE) == VSLENGTH)
4254 if (!(subtype & VSQUOTE) == !(quoted & 1))
4260 str = "\"}" + !(quoted & 1);
4267 case CTLBACKQ+CTLQUOTE:
4270 #if ENABLE_ASH_MATH_SUPPORT
4285 if ((subtype & VSTYPE) != VSNORMAL)
4287 str = vstype[subtype & VSTYPE];
4288 if (subtype & VSNUL)
4297 /* These can only happen inside quotes */
4310 while ((c = *str++)) {
4315 USTPUTC('"', nextc);
4321 /* cmdtxt() and cmdlist() call each other */
4322 static void cmdtxt(union node *n);
4325 cmdlist(union node *np, int sep)
4327 for (; np; np = np->narg.next) {
4331 if (sep && np->narg.next)
4337 cmdtxt(union node *n)
4340 struct nodelist *lp;
4351 lp = n->npipe.cmdlist;
4369 cmdtxt(n->nbinary.ch1);
4385 cmdtxt(n->nif.test);
4388 if (n->nif.elsepart) {
4391 n = n->nif.elsepart;
4407 cmdtxt(n->nbinary.ch1);
4417 cmdputs(n->nfor.var);
4419 cmdlist(n->nfor.args, 1);
4424 cmdputs(n->narg.text);
4428 cmdlist(n->ncmd.args, 1);
4429 cmdlist(n->ncmd.redirect, 0);
4442 cmdputs(n->ncase.expr->narg.text);
4444 for (np = n->ncase.cases; np; np = np->nclist.next) {
4445 cmdtxt(np->nclist.pattern);
4447 cmdtxt(np->nclist.body);
4461 #if ENABLE_ASH_BASH_COMPAT
4476 cmdputs(utoa(n->nfile.fd));
4478 if (n->type == NTOFD || n->type == NFROMFD) {
4479 cmdputs(utoa(n->ndup.dupfd));
4488 commandtext(union node *n)
4492 STARTSTACKSTR(cmdnextc);
4494 name = stackblock();
4495 TRACE(("commandtext: name %p, end %p\n\t\"%s\"\n",
4496 name, cmdnextc, cmdnextc));
4497 return ckstrdup(name);
4502 * Fork off a subshell. If we are doing job control, give the subshell its
4503 * own process group. Jp is a job structure that the job is to be added to.
4504 * N is the command that will be evaluated by the child. Both jp and n may
4505 * be NULL. The mode parameter can be one of the following:
4506 * FORK_FG - Fork off a foreground process.
4507 * FORK_BG - Fork off a background process.
4508 * FORK_NOJOB - Like FORK_FG, but don't give the process its own
4509 * process group even if job control is on.
4511 * When job control is turned off, background processes have their standard
4512 * input redirected to /dev/null (except for the second and later processes
4515 * Called with interrupts off.
4518 * Clear traps on a fork.
4525 for (tp = trap; tp < &trap[NSIG]; tp++) {
4526 if (*tp && **tp) { /* trap not NULL or "" (SIG_IGN) */
4531 setsignal(tp - trap);
4537 /* Lives far away from here, needed for forkchild */
4538 static void closescript(void);
4540 /* Called after fork(), in child */
4542 forkchild(struct job *jp, /*union node *n,*/ int mode)
4546 TRACE(("Child shell %d\n", getpid()));
4550 /* man bash: "Non-builtin commands run by bash have signal handlers
4551 * set to the values inherited by the shell from its parent".
4552 * Do we do it correctly? */
4557 /* do job control only in root shell */
4559 if (mode != FORK_NOJOB && jp->jobctl && !oldlvl) {
4562 if (jp->nprocs == 0)
4565 pgrp = jp->ps[0].pid;
4566 /* this can fail because we are doing it in the parent also */
4568 if (mode == FORK_FG)
4569 xtcsetpgrp(ttyfd, pgrp);
4574 if (mode == FORK_BG) {
4575 /* man bash: "When job control is not in effect,
4576 * asynchronous commands ignore SIGINT and SIGQUIT" */
4579 if (jp->nprocs == 0) {
4581 if (open(bb_dev_null, O_RDONLY) != 0)
4582 ash_msg_and_raise_error("can't open '%s'", bb_dev_null);
4586 if (iflag) { /* why if iflag only? */
4591 * "In all cases, bash ignores SIGQUIT. Non-builtin
4592 * commands run by bash have signal handlers
4593 * set to the values inherited by the shell
4595 * Take care of the second rule: */
4598 for (jp = curjob; jp; jp = jp->prev_job)
4603 /* Called after fork(), in parent */
4605 #define forkparent(jp, n, mode, pid) forkparent(jp, mode, pid)
4608 forkparent(struct job *jp, union node *n, int mode, pid_t pid)
4610 TRACE(("In parent shell: child = %d\n", pid));
4612 while (jobless && dowait(DOWAIT_NONBLOCK, NULL) > 0)
4618 if (mode != FORK_NOJOB && jp->jobctl) {
4621 if (jp->nprocs == 0)
4624 pgrp = jp->ps[0].pid;
4625 /* This can fail because we are doing it in the child also */
4629 if (mode == FORK_BG) {
4630 backgndpid = pid; /* set $! */
4631 set_curjob(jp, CUR_RUNNING);
4634 struct procstat *ps = &jp->ps[jp->nprocs++];
4639 if (doing_jobctl && n)
4640 ps->cmd = commandtext(n);
4646 forkshell(struct job *jp, union node *n, int mode)
4650 TRACE(("forkshell(%%%d, %p, %d) called\n", jobno(jp), n, mode));
4653 TRACE(("Fork failed, errno=%d", errno));
4656 ash_msg_and_raise_error("can't fork");
4659 forkchild(jp, /*n,*/ mode);
4661 forkparent(jp, n, mode, pid);
4666 * Wait for job to finish.
4668 * Under job control we have the problem that while a child process
4669 * is running interrupts generated by the user are sent to the child
4670 * but not to the shell. This means that an infinite loop started by
4671 * an interactive user may be hard to kill. With job control turned off,
4672 * an interactive user may place an interactive program inside a loop.
4673 * If the interactive program catches interrupts, the user doesn't want
4674 * these interrupts to also abort the loop. The approach we take here
4675 * is to have the shell ignore interrupt signals while waiting for a
4676 * foreground process to terminate, and then send itself an interrupt
4677 * signal if the child process was terminated by an interrupt signal.
4678 * Unfortunately, some programs want to do a bit of cleanup and then
4679 * exit on interrupt; unless these processes terminate themselves by
4680 * sending a signal to themselves (instead of calling exit) they will
4681 * confuse this approach.
4683 * Called with interrupts off.
4686 waitforjob(struct job *jp)
4690 TRACE(("waitforjob(%%%d) called\n", jobno(jp)));
4693 while (jp->state == JOBRUNNING) {
4694 /* In non-interactive shells, we _can_ get
4695 * a keyboard signal here and be EINTRed,
4696 * but we just loop back, waiting for command to complete.
4699 * "If bash is waiting for a command to complete and receives
4700 * a signal for which a trap has been set, the trap
4701 * will not be executed until the command completes."
4703 * Reality is that even if trap is not set, bash
4704 * will not act on the signal until command completes.
4705 * Try this. sleep5intoff.c:
4706 * #include <signal.h>
4707 * #include <unistd.h>
4710 * sigemptyset(&set);
4711 * sigaddset(&set, SIGINT);
4712 * sigaddset(&set, SIGQUIT);
4713 * sigprocmask(SIG_BLOCK, &set, NULL);
4717 * $ bash -c './sleep5intoff; echo hi'
4718 * ^C^C^C^C <--- pressing ^C once a second
4720 * $ bash -c './sleep5intoff; echo hi'
4721 * ^\^\^\^\hi <--- pressing ^\ (SIGQUIT)
4724 dowait(DOWAIT_BLOCK, jp);
4731 xtcsetpgrp(ttyfd, rootpid);
4733 * This is truly gross.
4734 * If we're doing job control, then we did a TIOCSPGRP which
4735 * caused us (the shell) to no longer be in the controlling
4736 * session -- so we wouldn't have seen any ^C/SIGINT. So, we
4737 * intuit from the subprocess exit status whether a SIGINT
4738 * occurred, and if so interrupt ourselves. Yuck. - mycroft
4740 if (jp->sigint) /* TODO: do the same with all signals */
4741 raise(SIGINT); /* ... by raise(jp->sig) instead? */
4743 if (jp->state == JOBDONE)
4750 * return 1 if there are stopped jobs, otherwise 0
4762 if (jp && jp->state == JOBSTOPPED) {
4763 out2str("You have stopped jobs.\n");
4772 /* ============ redir.c
4774 * Code for dealing with input/output redirection.
4777 #define EMPTY -2 /* marks an unused slot in redirtab */
4778 #define CLOSED -3 /* marks a slot of previously-closed fd */
4781 * Open a file in noclobber mode.
4782 * The code was copied from bash.
4785 noclobberopen(const char *fname)
4788 struct stat finfo, finfo2;
4791 * If the file exists and is a regular file, return an error
4794 r = stat(fname, &finfo);
4795 if (r == 0 && S_ISREG(finfo.st_mode)) {
4801 * If the file was not present (r != 0), make sure we open it
4802 * exclusively so that if it is created before we open it, our open
4803 * will fail. Make sure that we do not truncate an existing file.
4804 * Note that we don't turn on O_EXCL unless the stat failed -- if the
4805 * file was not a regular file, we leave O_EXCL off.
4808 return open(fname, O_WRONLY|O_CREAT|O_EXCL, 0666);
4809 fd = open(fname, O_WRONLY|O_CREAT, 0666);
4811 /* If the open failed, return the file descriptor right away. */
4816 * OK, the open succeeded, but the file may have been changed from a
4817 * non-regular file to a regular file between the stat and the open.
4818 * We are assuming that the O_EXCL open handles the case where FILENAME
4819 * did not exist and is symlinked to an existing file between the stat
4824 * If we can open it and fstat the file descriptor, and neither check
4825 * revealed that it was a regular file, and the file has not been
4826 * replaced, return the file descriptor.
4828 if (fstat(fd, &finfo2) == 0 && !S_ISREG(finfo2.st_mode)
4829 && finfo.st_dev == finfo2.st_dev && finfo.st_ino == finfo2.st_ino)
4832 /* The file has been replaced. badness. */
4839 * Handle here documents. Normally we fork off a process to write the
4840 * data to a pipe. If the document is short, we can stuff the data in
4841 * the pipe without forking.
4843 /* openhere needs this forward reference */
4844 static void expandhere(union node *arg, int fd);
4846 openhere(union node *redir)
4852 ash_msg_and_raise_error("pipe call failed");
4853 if (redir->type == NHERE) {
4854 len = strlen(redir->nhere.doc->narg.text);
4855 if (len <= PIPE_BUF) {
4856 full_write(pip[1], redir->nhere.doc->narg.text, len);
4860 if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) {
4863 ignoresig(SIGINT); //signal(SIGINT, SIG_IGN);
4864 ignoresig(SIGQUIT); //signal(SIGQUIT, SIG_IGN);
4865 ignoresig(SIGHUP); //signal(SIGHUP, SIG_IGN);
4866 ignoresig(SIGTSTP); //signal(SIGTSTP, SIG_IGN);
4867 signal(SIGPIPE, SIG_DFL);
4868 if (redir->type == NHERE)
4869 full_write(pip[1], redir->nhere.doc->narg.text, len);
4871 expandhere(redir->nhere.doc, pip[1]);
4872 _exit(EXIT_SUCCESS);
4880 openredirect(union node *redir)
4885 switch (redir->nfile.type) {
4887 fname = redir->nfile.expfname;
4888 f = open(fname, O_RDONLY);
4893 fname = redir->nfile.expfname;
4894 f = open(fname, O_RDWR|O_CREAT|O_TRUNC, 0666);
4899 #if ENABLE_ASH_BASH_COMPAT
4902 /* Take care of noclobber mode. */
4904 fname = redir->nfile.expfname;
4905 f = noclobberopen(fname);
4912 fname = redir->nfile.expfname;
4913 f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666);
4918 fname = redir->nfile.expfname;
4919 f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666);
4927 /* Fall through to eliminate warning. */
4928 /* Our single caller does this itself */
4935 f = openhere(redir);
4941 ash_msg_and_raise_error("can't create %s: %s", fname, errmsg(errno, "nonexistent directory"));
4943 ash_msg_and_raise_error("can't open %s: %s", fname, errmsg(errno, "no such file"));
4947 * Copy a file descriptor to be >= to. Returns -1
4948 * if the source file descriptor is closed, EMPTY if there are no unused
4949 * file descriptors left.
4951 /* 0x800..00: bit to set in "to" to request dup2 instead of fcntl(F_DUPFD).
4952 * old code was doing close(to) prior to copyfd() to achieve the same */
4954 COPYFD_EXACT = (int)~(INT_MAX),
4955 COPYFD_RESTORE = (int)((unsigned)COPYFD_EXACT >> 1),
4958 copyfd(int from, int to)
4962 if (to & COPYFD_EXACT) {
4963 to &= ~COPYFD_EXACT;
4965 newfd = dup2(from, to);
4967 newfd = fcntl(from, F_DUPFD, to);
4970 if (errno == EMFILE)
4972 /* Happens when source fd is not open: try "echo >&99" */
4973 ash_msg_and_raise_error("%d: %m", from);
4978 /* Struct def and variable are moved down to the first usage site */
4983 struct redirtab *next;
4986 struct two_fd_t two_fd[0];
4988 #define redirlist (G_var.redirlist)
4990 static int need_to_remember(struct redirtab *rp, int fd)
4994 if (!rp) /* remembering was not requested */
4997 for (i = 0; i < rp->pair_count; i++) {
4998 if (rp->two_fd[i].orig == fd) {
4999 /* already remembered */
5006 /* "hidden" fd is a fd used to read scripts, or a copy of such */
5007 static int is_hidden_fd(struct redirtab *rp, int fd)
5010 struct parsefile *pf;
5023 fd |= COPYFD_RESTORE;
5024 for (i = 0; i < rp->pair_count; i++) {
5025 if (rp->two_fd[i].copy == fd) {
5033 * Process a list of redirection commands. If the REDIR_PUSH flag is set,
5034 * old file descriptors are stashed away so that the redirection can be
5035 * undone by calling popredir. If the REDIR_BACKQ flag is set, then the
5036 * standard output, and the standard error if it becomes a duplicate of
5037 * stdout, is saved in memory.
5039 /* flags passed to redirect */
5040 #define REDIR_PUSH 01 /* save previous values of file descriptors */
5041 #define REDIR_SAVEFD2 03 /* set preverrout */
5043 redirect(union node *redir, int flags)
5045 struct redirtab *sv;
5050 int copied_fd2 = -1;
5060 if (flags & REDIR_PUSH) {
5061 union node *tmp = redir;
5064 #if ENABLE_ASH_BASH_COMPAT
5065 if (redir->nfile.type == NTO2)
5068 tmp = tmp->nfile.next;
5070 sv = ckmalloc(sizeof(*sv) + sv_pos * sizeof(sv->two_fd[0]));
5071 sv->next = redirlist;
5072 sv->pair_count = sv_pos;
5074 sv->nullredirs = g_nullredirs - 1;
5076 while (sv_pos > 0) {
5078 sv->two_fd[sv_pos].orig = sv->two_fd[sv_pos].copy = EMPTY;
5083 fd = redir->nfile.fd;
5084 if (redir->nfile.type == NTOFD || redir->nfile.type == NFROMFD) {
5085 int right_fd = redir->ndup.dupfd;
5086 /* redirect from/to same file descriptor? */
5089 /* echo >&10 and 10 is a fd opened to the sh script? */
5090 if (is_hidden_fd(sv, right_fd)) {
5091 errno = EBADF; /* as if it is closed */
5092 ash_msg_and_raise_error("%d: %m", right_fd);
5096 newfd = openredirect(redir); /* always >= 0 */
5098 /* Descriptor wasn't open before redirect.
5099 * Mark it for close in the future */
5100 if (need_to_remember(sv, fd)) {
5101 goto remember_to_close;
5106 #if ENABLE_ASH_BASH_COMPAT
5109 if (need_to_remember(sv, fd)) {
5110 /* Copy old descriptor */
5111 i = fcntl(fd, F_DUPFD, 10);
5112 /* You'd expect copy to be CLOEXECed. Currently these extra "saved" fds
5113 * are closed in popredir() in the child, preventing them from leaking
5114 * into child. (popredir() also cleans up the mess in case of failures)
5119 /* Strange error (e.g. "too many files" EMFILE?) */
5123 ash_msg_and_raise_error("%d: %m", fd);
5126 /* EBADF: it is not open - good, remember to close it */
5129 } else { /* fd is open, save its copy */
5130 /* "exec fd>&-" should not close fds
5131 * which point to script file(s).
5132 * Force them to be restored afterwards */
5133 if (is_hidden_fd(sv, fd))
5134 i |= COPYFD_RESTORE;
5138 sv->two_fd[sv_pos].orig = fd;
5139 sv->two_fd[sv_pos].copy = i;
5143 /* NTOFD/NFROMFD: copy redir->ndup.dupfd to fd */
5144 if (redir->ndup.dupfd < 0) { /* "fd>&-" */
5147 copyfd(redir->ndup.dupfd, fd | COPYFD_EXACT);
5149 } else if (fd != newfd) { /* move newfd to fd */
5150 copyfd(newfd, fd | COPYFD_EXACT);
5151 #if ENABLE_ASH_BASH_COMPAT
5152 if (!(redir->nfile.type == NTO2 && fd == 2))
5156 #if ENABLE_ASH_BASH_COMPAT
5157 if (redir->nfile.type == NTO2 && fd == 1) {
5158 /* We already redirected it to fd 1, now copy it to 2 */
5164 } while ((redir = redir->nfile.next) != NULL);
5167 if ((flags & REDIR_SAVEFD2) && copied_fd2 >= 0)
5168 preverrout_fd = copied_fd2;
5172 * Undo the effects of the last redirection.
5175 popredir(int drop, int restore)
5177 struct redirtab *rp;
5180 if (--g_nullredirs >= 0)
5184 for (i = 0; i < rp->pair_count; i++) {
5185 int fd = rp->two_fd[i].orig;
5186 int copy = rp->two_fd[i].copy;
5187 if (copy == CLOSED) {
5192 if (copy != EMPTY) {
5193 if (!drop || (restore && (copy & COPYFD_RESTORE))) {
5194 copy &= ~COPYFD_RESTORE;
5196 copyfd(copy, fd | COPYFD_EXACT);
5201 redirlist = rp->next;
5202 g_nullredirs = rp->nullredirs;
5208 * Undo all redirections. Called on error or interrupt.
5212 * Discard all saved file descriptors.
5215 clearredir(int drop)
5221 popredir(drop, /*restore:*/ 0);
5226 redirectsafe(union node *redir, int flags)
5229 volatile int saveint;
5230 struct jmploc *volatile savehandler = exception_handler;
5231 struct jmploc jmploc;
5234 /* "echo 9>/dev/null; echo >&9; echo result: $?" - result should be 1, not 2! */
5235 err = setjmp(jmploc.loc); // huh?? was = setjmp(jmploc.loc) * 2;
5237 exception_handler = &jmploc;
5238 redirect(redir, flags);
5240 exception_handler = savehandler;
5241 if (err && exception_type != EXERROR)
5242 longjmp(exception_handler->loc, 1);
5243 RESTORE_INT(saveint);
5248 /* ============ Routines to expand arguments to commands
5250 * We have to deal with backquotes, shell variables, and file metacharacters.
5253 #if ENABLE_ASH_MATH_SUPPORT_64
5254 typedef int64_t arith_t;
5255 #define arith_t_type long long
5257 typedef long arith_t;
5258 #define arith_t_type long
5261 #if ENABLE_ASH_MATH_SUPPORT
5262 static arith_t dash_arith(const char *);
5263 static arith_t arith(const char *expr, int *perrcode);
5269 #define EXP_FULL 0x1 /* perform word splitting & file globbing */
5270 #define EXP_TILDE 0x2 /* do normal tilde expansion */
5271 #define EXP_VARTILDE 0x4 /* expand tildes in an assignment */
5272 #define EXP_REDIR 0x8 /* file glob for a redirection (1 match only) */
5273 #define EXP_CASE 0x10 /* keeps quotes around for CASE pattern */
5274 #define EXP_RECORD 0x20 /* need to record arguments for ifs breakup */
5275 #define EXP_VARTILDE2 0x40 /* expand tildes after colons only */
5276 #define EXP_WORD 0x80 /* expand word in parameter expansion */
5277 #define EXP_QWORD 0x100 /* expand word in quoted parameter expansion */
5281 #define RMESCAPE_ALLOC 0x1 /* Allocate a new string */
5282 #define RMESCAPE_GLOB 0x2 /* Add backslashes for glob */
5283 #define RMESCAPE_QUOTED 0x4 /* Remove CTLESC unless in quotes */
5284 #define RMESCAPE_GROW 0x8 /* Grow strings instead of stalloc */
5285 #define RMESCAPE_HEAP 0x10 /* Malloc strings instead of stalloc */
5288 * Structure specifying which parts of the string should be searched
5289 * for IFS characters.
5292 struct ifsregion *next; /* next region in list */
5293 int begoff; /* offset of start of region */
5294 int endoff; /* offset of end of region */
5295 int nulonly; /* search for nul bytes only */
5299 struct strlist *list;
5300 struct strlist **lastp;
5303 /* output of current string */
5304 static char *expdest;
5305 /* list of back quote expressions */
5306 static struct nodelist *argbackq;
5307 /* first struct in list of ifs regions */
5308 static struct ifsregion ifsfirst;
5309 /* last struct in list */
5310 static struct ifsregion *ifslastp;
5311 /* holds expanded arg list */
5312 static struct arglist exparg;
5322 expdest = makestrspace(32, expdest);
5323 #if ENABLE_ASH_MATH_SUPPORT_64
5324 len = fmtstr(expdest, 32, "%lld", (long long) num);
5326 len = fmtstr(expdest, 32, "%ld", num);
5328 STADJUST(len, expdest);
5333 esclen(const char *start, const char *p)
5337 while (p > start && *--p == CTLESC) {
5344 * Remove any CTLESC characters from a string.
5347 _rmescapes(char *str, int flag)
5349 static const char qchars[] ALIGN1 = { CTLESC, CTLQUOTEMARK, '\0' };
5356 p = strpbrk(str, qchars);
5362 if (flag & RMESCAPE_ALLOC) {
5363 size_t len = p - str;
5364 size_t fulllen = len + strlen(p) + 1;
5366 if (flag & RMESCAPE_GROW) {
5367 r = makestrspace(fulllen, expdest);
5368 } else if (flag & RMESCAPE_HEAP) {
5369 r = ckmalloc(fulllen);
5371 r = stalloc(fulllen);
5375 q = (char *)memcpy(q, str, len) + len;
5378 inquotes = (flag & RMESCAPE_QUOTED) ^ RMESCAPE_QUOTED;
5379 globbing = flag & RMESCAPE_GLOB;
5380 notescaped = globbing;
5382 if (*p == CTLQUOTEMARK) {
5383 inquotes = ~inquotes;
5385 notescaped = globbing;
5389 /* naked back slash */
5395 if (notescaped && inquotes && *p != '/') {
5399 notescaped = globbing;
5404 if (flag & RMESCAPE_GROW) {
5406 STADJUST(q - r + 1, expdest);
5410 #define rmescapes(p) _rmescapes((p), 0)
5412 #define pmatch(a, b) !fnmatch((a), (b), 0)
5415 * Prepare a pattern for a expmeta (internal glob(3)) call.
5417 * Returns an stalloced string.
5420 preglob(const char *pattern, int quoted, int flag)
5422 flag |= RMESCAPE_GLOB;
5424 flag |= RMESCAPE_QUOTED;
5426 return _rmescapes((char *)pattern, flag);
5430 * Put a string on the stack.
5433 memtodest(const char *p, size_t len, int syntax, int quotes)
5437 q = makestrspace(len * 2, q);
5440 int c = signed_char2int(*p++);
5443 if (quotes && (SIT(c, syntax) == CCTL || SIT(c, syntax) == CBACK))
5452 strtodest(const char *p, int syntax, int quotes)
5454 memtodest(p, strlen(p), syntax, quotes);
5458 * Record the fact that we have to scan this region of the
5459 * string for IFS characters.
5462 recordregion(int start, int end, int nulonly)
5464 struct ifsregion *ifsp;
5466 if (ifslastp == NULL) {
5470 ifsp = ckzalloc(sizeof(*ifsp));
5471 /*ifsp->next = NULL; - ckzalloc did it */
5472 ifslastp->next = ifsp;
5476 ifslastp->begoff = start;
5477 ifslastp->endoff = end;
5478 ifslastp->nulonly = nulonly;
5482 removerecordregions(int endoff)
5484 if (ifslastp == NULL)
5487 if (ifsfirst.endoff > endoff) {
5488 while (ifsfirst.next != NULL) {
5489 struct ifsregion *ifsp;
5491 ifsp = ifsfirst.next->next;
5492 free(ifsfirst.next);
5493 ifsfirst.next = ifsp;
5496 if (ifsfirst.begoff > endoff)
5499 ifslastp = &ifsfirst;
5500 ifsfirst.endoff = endoff;
5505 ifslastp = &ifsfirst;
5506 while (ifslastp->next && ifslastp->next->begoff < endoff)
5507 ifslastp=ifslastp->next;
5508 while (ifslastp->next != NULL) {
5509 struct ifsregion *ifsp;
5511 ifsp = ifslastp->next->next;
5512 free(ifslastp->next);
5513 ifslastp->next = ifsp;
5516 if (ifslastp->endoff > endoff)
5517 ifslastp->endoff = endoff;
5521 exptilde(char *startp, char *p, int flag)
5527 int quotes = flag & (EXP_FULL | EXP_CASE);
5532 while ((c = *++p) != '\0') {
5539 if (flag & EXP_VARTILDE)
5549 if (*name == '\0') {
5550 home = lookupvar(homestr);
5552 pw = getpwnam(name);
5557 if (!home || !*home)
5560 startloc = expdest - (char *)stackblock();
5561 strtodest(home, SQSYNTAX, quotes);
5562 recordregion(startloc, expdest - (char *)stackblock(), 0);
5570 * Execute a command inside back quotes. If it's a builtin command, we
5571 * want to save its output in a block obtained from malloc. Otherwise
5572 * we fork off a subprocess and get the output of the command via a pipe.
5573 * Should be called with interrupts off.
5575 struct backcmd { /* result of evalbackcmd */
5576 int fd; /* file descriptor to read from */
5577 int nleft; /* number of chars in buffer */
5578 char *buf; /* buffer */
5579 struct job *jp; /* job structure for command */
5582 /* These forward decls are needed to use "eval" code for backticks handling: */
5583 static uint8_t back_exitstatus; /* exit status of backquoted command */
5584 #define EV_EXIT 01 /* exit after evaluating tree */
5585 static void evaltree(union node *, int);
5588 evalbackcmd(union node *n, struct backcmd *result)
5599 saveherefd = herefd;
5607 ash_msg_and_raise_error("pipe call failed");
5608 jp = makejob(/*n,*/ 1);
5609 if (forkshell(jp, n, FORK_NOJOB) == 0) {
5614 copyfd(pip[1], 1 | COPYFD_EXACT);
5618 evaltree(n, EV_EXIT); /* actually evaltreenr... */
5622 result->fd = pip[0];
5625 herefd = saveherefd;
5627 TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n",
5628 result->fd, result->buf, result->nleft, result->jp));
5632 * Expand stuff in backwards quotes.
5635 expbackq(union node *cmd, int quoted, int quotes)
5643 int syntax = quoted ? DQSYNTAX : BASESYNTAX;
5644 struct stackmark smark;
5647 setstackmark(&smark);
5649 startloc = dest - (char *)stackblock();
5651 evalbackcmd(cmd, &in);
5652 popstackmark(&smark);
5659 memtodest(p, i, syntax, quotes);
5663 i = nonblock_safe_read(in.fd, buf, sizeof(buf));
5664 TRACE(("expbackq: read returns %d\n", i));
5673 back_exitstatus = waitforjob(in.jp);
5677 /* Eat all trailing newlines */
5679 for (; dest > (char *)stackblock() && dest[-1] == '\n';)
5684 recordregion(startloc, dest - (char *)stackblock(), 0);
5685 TRACE(("evalbackq: size=%d: \"%.*s\"\n",
5686 (dest - (char *)stackblock()) - startloc,
5687 (dest - (char *)stackblock()) - startloc,
5688 stackblock() + startloc));
5691 #if ENABLE_ASH_MATH_SUPPORT
5693 * Expand arithmetic expression. Backup to start of expression,
5694 * evaluate, place result in (backed up) result, adjust string position.
5707 * This routine is slightly over-complicated for
5708 * efficiency. Next we scan backwards looking for the
5709 * start of arithmetic.
5711 start = stackblock();
5718 while (*p != CTLARI) {
5722 ash_msg_and_raise_error("missing CTLARI (shouldn't happen)");
5727 esc = esclen(start, p);
5737 removerecordregions(begoff);
5746 len = cvtnum(dash_arith(p + 2));
5749 recordregion(begoff, begoff + len, 0);
5753 /* argstr needs it */
5754 static char *evalvar(char *p, int flag, struct strlist *var_str_list);
5757 * Perform variable and command substitution. If EXP_FULL is set, output CTLESC
5758 * characters to allow for further processing. Otherwise treat
5759 * $@ like $* since no splitting will be performed.
5761 * var_str_list (can be NULL) is a list of "VAR=val" strings which take precedence
5762 * over shell varables. Needed for "A=a B=$A; echo $B" case - we use it
5763 * for correct expansion of "B=$A" word.
5766 argstr(char *p, int flag, struct strlist *var_str_list)
5768 static const char spclchars[] ALIGN1 = {
5776 CTLBACKQ | CTLQUOTE,
5777 #if ENABLE_ASH_MATH_SUPPORT
5782 const char *reject = spclchars;
5784 int quotes = flag & (EXP_FULL | EXP_CASE); /* do CTLESC */
5785 int breakall = flag & EXP_WORD;
5790 if (!(flag & EXP_VARTILDE)) {
5792 } else if (flag & EXP_VARTILDE2) {
5797 if (flag & EXP_TILDE) {
5803 if (*q == CTLESC && (flag & EXP_QWORD))
5806 p = exptilde(p, q, flag);
5809 startloc = expdest - (char *)stackblock();
5811 length += strcspn(p + length, reject);
5813 if (c && (!(c & 0x80)
5814 #if ENABLE_ASH_MATH_SUPPORT
5818 /* c == '=' || c == ':' || c == CTLENDARI */
5823 expdest = stack_nputstr(p, length, expdest);
5824 newloc = expdest - (char *)stackblock();
5825 if (breakall && !inquotes && newloc > startloc) {
5826 recordregion(startloc, newloc, 0);
5837 if (flag & EXP_VARTILDE2) {
5841 flag |= EXP_VARTILDE2;
5846 * sort of a hack - expand tildes in variable
5847 * assignments (after the first '=' and after ':'s).
5856 case CTLENDVAR: /* ??? */
5859 /* "$@" syntax adherence hack */
5862 !memcmp(p, dolatstr, 4) &&
5863 (p[4] == CTLQUOTEMARK || (
5864 p[4] == CTLENDVAR &&
5865 p[5] == CTLQUOTEMARK
5868 p = evalvar(p + 1, flag, /* var_str_list: */ NULL) + 1;
5871 inquotes = !inquotes;
5884 p = evalvar(p, flag, var_str_list);
5888 case CTLBACKQ|CTLQUOTE:
5889 expbackq(argbackq->n, c, quotes);
5890 argbackq = argbackq->next;
5892 #if ENABLE_ASH_MATH_SUPPORT
5905 scanleft(char *startp, char *rmesc, char *rmescend UNUSED_PARAM, char *str, int quotes,
5908 // This commented out code was added by James Simmons <jsimmons@infradead.org>
5909 // as part of a larger change when he added support for ${var/a/b}.
5910 // However, it broke # and % operators:
5914 //echo ${var#ab} abcdcd abcdcd
5915 //echo ${var##ab} abcdcd abcdcd
5916 //echo ${var#a*b} abcdcd ababcdcd (!)
5917 //echo ${var##a*b} cdcd cdcd
5918 //echo ${var#?} babcdcd ababcdcd (!)
5919 //echo ${var##?} babcdcd babcdcd
5920 //echo ${var#*} ababcdcd babcdcd (!)
5922 //echo ${var%cd} ababcd ababcd
5923 //echo ${var%%cd} ababcd abab (!)
5924 //echo ${var%c*d} ababcd ababcd
5925 //echo ${var%%c*d} abab ababcdcd (!)
5926 //echo ${var%?} ababcdc ababcdc
5927 //echo ${var%%?} ababcdc ababcdcd (!)
5928 //echo ${var%*} ababcdcd ababcdcd
5931 // Commenting it back out helped. Remove it completely if it really
5934 char *loc, *loc2; //, *full;
5940 int match; // = strlen(str);
5941 const char *s = loc2;
5948 match = pmatch(str, s); // this line was deleted
5950 // // chop off end if its '*'
5951 // full = strrchr(str, '*');
5952 // if (full && full != str)
5955 // // If str starts with '*' replace with s.
5956 // if ((*str == '*') && strlen(s) >= match) {
5957 // full = xstrdup(s);
5958 // strncpy(full+strlen(s)-match+1, str+1, match-1);
5960 // full = xstrndup(str, match);
5961 // match = strncmp(s, full, strlen(full));
5965 if (match) // if (!match)
5967 if (quotes && *loc == CTLESC)
5976 scanright(char *startp, char *rmesc, char *rmescend, char *str, int quotes,
5983 for (loc = str - 1, loc2 = rmescend; loc >= startp; loc2--) {
5986 const char *s = loc2;
5991 match = pmatch(str, s);
5998 esc = esclen(startp, loc);
6009 static void varunset(const char *, const char *, const char *, int) NORETURN;
6011 varunset(const char *end, const char *var, const char *umsg, int varflags)
6017 msg = "parameter not set";
6019 if (*end == CTLENDVAR) {
6020 if (varflags & VSNUL)
6026 ash_msg_and_raise_error("%.*s: %s%s", end - var - 1, var, msg, tail);
6029 #if ENABLE_ASH_BASH_COMPAT
6031 parse_sub_pattern(char *arg, int inquotes)
6033 char *idx, *repl = NULL;
6042 /* Only the first '/' seen is our separator */
6049 if (!inquotes && c == '\\' && arg[1] == '\\')
6050 arg++; /* skip both \\, not just first one */
6057 #endif /* ENABLE_ASH_BASH_COMPAT */
6060 subevalvar(char *p, char *str, int strloc, int subtype,
6061 int startloc, int varflags, int quotes, struct strlist *var_str_list)
6063 struct nodelist *saveargbackq = argbackq;
6066 char *rmesc, *rmescend;
6067 USE_ASH_BASH_COMPAT(char *repl = NULL;)
6068 USE_ASH_BASH_COMPAT(char null = '\0';)
6069 USE_ASH_BASH_COMPAT(int pos, len, orig_len;)
6070 int saveherefd = herefd;
6071 int amount, workloc, resetloc;
6073 char *(*scan)(char*, char*, char*, char*, int, int);
6076 argstr(p, (subtype != VSASSIGN && subtype != VSQUESTION) ? EXP_CASE : 0,
6078 STPUTC('\0', expdest);
6079 herefd = saveherefd;
6080 argbackq = saveargbackq;
6081 startp = (char *)stackblock() + startloc;
6085 setvar(str, startp, 0);
6086 amount = startp - expdest;
6087 STADJUST(amount, expdest);
6090 #if ENABLE_ASH_BASH_COMPAT
6092 loc = str = stackblock() + strloc;
6093 // TODO: number() instead? It does error checking...
6095 len = str - startp - 1;
6097 /* *loc != '\0', guaranteed by parser */
6101 /* We must adjust the length by the number of escapes we find. */
6102 for (ptr = startp; ptr < (str - 1); ptr++) {
6103 if (*ptr == CTLESC) {
6111 if (*loc++ == ':') {
6112 // TODO: number() instead? It does error checking...
6116 while (*loc && *loc != ':')
6119 // TODO: number() instead? It does error checking...
6122 if (pos >= orig_len) {
6126 if (len > (orig_len - pos))
6127 len = orig_len - pos;
6129 for (str = startp; pos; str++, pos--) {
6130 if (quotes && *str == CTLESC)
6133 for (loc = startp; len; len--) {
6134 if (quotes && *str == CTLESC)
6139 amount = loc - expdest;
6140 STADJUST(amount, expdest);
6145 varunset(p, str, startp, varflags);
6148 resetloc = expdest - (char *)stackblock();
6150 /* We'll comeback here if we grow the stack while handling
6151 * a VSREPLACE or VSREPLACEALL, since our pointers into the
6152 * stack will need rebasing, and we'll need to remove our work
6155 USE_ASH_BASH_COMPAT(restart:)
6157 amount = expdest - ((char *)stackblock() + resetloc);
6158 STADJUST(-amount, expdest);
6159 startp = (char *)stackblock() + startloc;
6162 rmescend = (char *)stackblock() + strloc;
6164 rmesc = _rmescapes(startp, RMESCAPE_ALLOC | RMESCAPE_GROW);
6165 if (rmesc != startp) {
6167 startp = (char *)stackblock() + startloc;
6171 str = (char *)stackblock() + strloc;
6172 preglob(str, varflags & VSQUOTE, 0);
6173 workloc = expdest - (char *)stackblock();
6175 #if ENABLE_ASH_BASH_COMPAT
6176 if (subtype == VSREPLACE || subtype == VSREPLACEALL) {
6177 char *idx, *end, *restart_detect;
6180 repl = parse_sub_pattern(str, varflags & VSQUOTE);
6185 /* If there's no pattern to match, return the expansion unmolested */
6193 loc = scanright(idx, rmesc, rmescend, str, quotes, 1);
6195 /* No match, advance */
6196 restart_detect = stackblock();
6197 STPUTC(*idx, expdest);
6198 if (quotes && *idx == CTLESC) {
6201 STPUTC(*idx, expdest);
6203 if (stackblock() != restart_detect)
6211 if (subtype == VSREPLACEALL) {
6213 if (quotes && *idx == CTLESC)
6222 for (loc = repl; *loc; loc++) {
6223 restart_detect = stackblock();
6224 STPUTC(*loc, expdest);
6225 if (stackblock() != restart_detect)
6230 if (subtype == VSREPLACE) {
6232 restart_detect = stackblock();
6233 STPUTC(*idx, expdest);
6234 if (stackblock() != restart_detect)
6243 /* We've put the replaced text into a buffer at workloc, now
6244 * move it to the right place and adjust the stack.
6246 startp = stackblock() + startloc;
6247 STPUTC('\0', expdest);
6248 memmove(startp, stackblock() + workloc, len);
6249 startp[len++] = '\0';
6250 amount = expdest - ((char *)stackblock() + startloc + len - 1);
6251 STADJUST(-amount, expdest);
6254 #endif /* ENABLE_ASH_BASH_COMPAT */
6256 subtype -= VSTRIMRIGHT;
6258 if (subtype < 0 || subtype > 7)
6261 /* zero = subtype == VSTRIMLEFT || subtype == VSTRIMLEFTMAX */
6262 zero = subtype >> 1;
6263 /* VSTRIMLEFT/VSTRIMRIGHTMAX -> scanleft */
6264 scan = (subtype & 1) ^ zero ? scanleft : scanright;
6266 loc = scan(startp, rmesc, rmescend, str, quotes, zero);
6269 memmove(startp, loc, str - loc);
6270 loc = startp + (str - loc) - 1;
6273 amount = loc - expdest;
6274 STADJUST(amount, expdest);
6280 * Add the value of a specialized variable to the stack string.
6283 varvalue(char *name, int varflags, int flags, struct strlist *var_str_list)
6293 int quoted = varflags & VSQUOTE;
6294 int subtype = varflags & VSTYPE;
6295 int quotes = flags & (EXP_FULL | EXP_CASE);
6297 if (quoted && (flags & EXP_FULL))
6298 sep = 1 << CHAR_BIT;
6300 syntax = quoted ? DQSYNTAX : BASESYNTAX;
6309 num = shellparam.nparam;
6319 p = makestrspace(NOPTS, expdest);
6320 for (i = NOPTS - 1; i >= 0; i--) {
6322 USTPUTC(optletters(i), p);
6333 sep = ifsset() ? signed_char2int(ifsval()[0]) : ' ';
6334 if (quotes && (SIT(sep, syntax) == CCTL || SIT(sep, syntax) == CBACK))
6340 while ((p = *ap++)) {
6343 partlen = strlen(p);
6346 if (!(subtype == VSPLUS || subtype == VSLENGTH))
6347 memtodest(p, partlen, syntax, quotes);
6353 if (subtype == VSPLUS || subtype == VSLENGTH) {
6374 // TODO: number() instead? It does error checking...
6376 if (num < 0 || num > shellparam.nparam)
6378 p = num ? shellparam.p[num - 1] : arg0;
6381 /* NB: name has form "VAR=..." */
6383 /* "A=a B=$A" case: var_str_list is a list of "A=a" strings
6384 * which should be considered before we check variables. */
6386 unsigned name_len = (strchrnul(name, '=') - name) + 1;
6390 str = var_str_list->text;
6391 eq = strchr(str, '=');
6392 if (!eq) /* stop at first non-assignment */
6395 if (name_len == (unsigned)(eq - str)
6396 && strncmp(str, name, name_len) == 0) {
6398 /* goto value; - WRONG! */
6399 /* think "A=1 A=2 B=$A" */
6401 var_str_list = var_str_list->next;
6402 } while (var_str_list);
6406 p = lookupvar(name);
6412 if (!(subtype == VSPLUS || subtype == VSLENGTH))
6413 memtodest(p, len, syntax, quotes);
6417 if (subtype == VSPLUS || subtype == VSLENGTH)
6418 STADJUST(-len, expdest);
6423 * Expand a variable, and return a pointer to the next character in the
6427 evalvar(char *p, int flag, struct strlist *var_str_list)
6439 subtype = varflags & VSTYPE;
6440 quoted = varflags & VSQUOTE;
6442 easy = (!quoted || (*var == '@' && shellparam.nparam));
6443 startloc = expdest - (char *)stackblock();
6444 p = strchr(p, '=') + 1;
6447 varlen = varvalue(var, varflags, flag, var_str_list);
6448 if (varflags & VSNUL)
6451 if (subtype == VSPLUS) {
6452 varlen = -1 - varlen;
6456 if (subtype == VSMINUS) {
6460 p, flag | EXP_TILDE |
6461 (quoted ? EXP_QWORD : EXP_WORD),
6471 if (subtype == VSASSIGN || subtype == VSQUESTION) {
6473 if (subevalvar(p, var, /* strloc: */ 0,
6474 subtype, startloc, varflags,
6480 * Remove any recorded regions beyond
6483 removerecordregions(startloc);
6493 if (varlen < 0 && uflag)
6494 varunset(p, var, 0, 0);
6496 if (subtype == VSLENGTH) {
6497 cvtnum(varlen > 0 ? varlen : 0);
6501 if (subtype == VSNORMAL) {
6512 case VSTRIMRIGHTMAX:
6513 #if ENABLE_ASH_BASH_COMPAT
6526 * Terminate the string and start recording the pattern
6529 STPUTC('\0', expdest);
6530 patloc = expdest - (char *)stackblock();
6531 if (0 == subevalvar(p, /* str: */ NULL, patloc, subtype,
6533 /* quotes: */ flag & (EXP_FULL | EXP_CASE),
6536 int amount = expdest - (
6537 (char *)stackblock() + patloc - 1
6539 STADJUST(-amount, expdest);
6541 /* Remove any recorded regions beyond start of variable */
6542 removerecordregions(startloc);
6544 recordregion(startloc, expdest - (char *)stackblock(), quoted);
6548 if (subtype != VSNORMAL) { /* skip to end of alternative */
6554 else if (c == CTLBACKQ || c == (CTLBACKQ|CTLQUOTE)) {
6556 argbackq = argbackq->next;
6557 } else if (c == CTLVAR) {
6558 if ((*p++ & VSTYPE) != VSNORMAL)
6560 } else if (c == CTLENDVAR) {
6570 * Break the argument string into pieces based upon IFS and add the
6571 * strings to the argument list. The regions of the string to be
6572 * searched for IFS characters have been stored by recordregion.
6575 ifsbreakup(char *string, struct arglist *arglist)
6577 struct ifsregion *ifsp;
6582 const char *ifs, *realifs;
6587 if (ifslastp != NULL) {
6590 realifs = ifsset() ? ifsval() : defifs;
6593 p = string + ifsp->begoff;
6594 nulonly = ifsp->nulonly;
6595 ifs = nulonly ? nullstr : realifs;
6597 while (p < string + ifsp->endoff) {
6601 if (!strchr(ifs, *p)) {
6606 ifsspc = (strchr(defifs, *p) != NULL);
6607 /* Ignore IFS whitespace at start */
6608 if (q == start && ifsspc) {
6614 sp = stzalloc(sizeof(*sp));
6616 *arglist->lastp = sp;
6617 arglist->lastp = &sp->next;
6621 if (p >= string + ifsp->endoff) {
6627 if (strchr(ifs, *p) == NULL) {
6631 if (strchr(defifs, *p) == NULL) {
6646 } while (ifsp != NULL);
6655 sp = stzalloc(sizeof(*sp));
6657 *arglist->lastp = sp;
6658 arglist->lastp = &sp->next;
6664 struct ifsregion *p;
6669 struct ifsregion *ifsp;
6675 ifsfirst.next = NULL;
6680 * Add a file name to the list.
6683 addfname(const char *name)
6687 sp = stzalloc(sizeof(*sp));
6688 sp->text = ststrdup(name);
6690 exparg.lastp = &sp->next;
6693 static char *expdir;
6696 * Do metacharacter (i.e. *, ?, [...]) expansion.
6699 expmeta(char *enddir, char *name)
6714 for (p = name; *p; p++) {
6715 if (*p == '*' || *p == '?')
6717 else if (*p == '[') {
6724 if (*q == '/' || *q == '\0')
6731 } else if (*p == '\\')
6733 else if (*p == '/') {
6740 if (metaflag == 0) { /* we've reached the end of the file name */
6741 if (enddir != expdir)
6749 if (metaflag == 0 || lstat(expdir, &statb) >= 0)
6760 } while (p < start);
6762 if (enddir == expdir) {
6764 } else if (enddir == expdir + 1 && *expdir == '/') {
6773 if (enddir != expdir)
6775 if (*endname == 0) {
6787 while (!intpending && (dp = readdir(dirp)) != NULL) {
6788 if (dp->d_name[0] == '.' && !matchdot)
6790 if (pmatch(start, dp->d_name)) {
6792 strcpy(enddir, dp->d_name);
6795 for (p = enddir, cp = dp->d_name; (*p++ = *cp++) != '\0';)
6798 expmeta(p, endname);
6807 static struct strlist *
6808 msort(struct strlist *list, int len)
6810 struct strlist *p, *q = NULL;
6811 struct strlist **lpp;
6819 for (n = half; --n >= 0;) {
6823 q->next = NULL; /* terminate first half of list */
6824 q = msort(list, half); /* sort first half of list */
6825 p = msort(p, len - half); /* sort second half */
6828 #if ENABLE_LOCALE_SUPPORT
6829 if (strcoll(p->text, q->text) < 0)
6831 if (strcmp(p->text, q->text) < 0)
6855 * Sort the results of file name expansion. It calculates the number of
6856 * strings to sort and then calls msort (short for merge sort) to do the
6859 static struct strlist *
6860 expsort(struct strlist *str)
6866 for (sp = str; sp; sp = sp->next)
6868 return msort(str, len);
6872 expandmeta(struct strlist *str /*, int flag*/)
6874 static const char metachars[] ALIGN1 = {
6877 /* TODO - EXP_REDIR */
6880 struct strlist **savelastp;
6886 if (!strpbrk(str->text, metachars))
6888 savelastp = exparg.lastp;
6891 p = preglob(str->text, 0, RMESCAPE_ALLOC | RMESCAPE_HEAP);
6893 int i = strlen(str->text);
6894 expdir = ckmalloc(i < 2048 ? 2048 : i); /* XXX */
6902 if (exparg.lastp == savelastp) {
6907 *exparg.lastp = str;
6908 rmescapes(str->text);
6909 exparg.lastp = &str->next;
6911 *exparg.lastp = NULL;
6912 *savelastp = sp = expsort(*savelastp);
6913 while (sp->next != NULL)
6915 exparg.lastp = &sp->next;
6922 * Perform variable substitution and command substitution on an argument,
6923 * placing the resulting list of arguments in arglist. If EXP_FULL is true,
6924 * perform splitting and file name expansion. When arglist is NULL, perform
6925 * here document expansion.
6928 expandarg(union node *arg, struct arglist *arglist, int flag)
6933 argbackq = arg->narg.backquote;
6934 STARTSTACKSTR(expdest);
6935 ifsfirst.next = NULL;
6937 argstr(arg->narg.text, flag,
6938 /* var_str_list: */ arglist ? arglist->list : NULL);
6939 p = _STPUTC('\0', expdest);
6941 if (arglist == NULL) {
6942 return; /* here document expanded */
6944 p = grabstackstr(p);
6945 exparg.lastp = &exparg.list;
6949 if (flag & EXP_FULL) {
6950 ifsbreakup(p, &exparg);
6951 *exparg.lastp = NULL;
6952 exparg.lastp = &exparg.list;
6953 expandmeta(exparg.list /*, flag*/);
6955 if (flag & EXP_REDIR) /*XXX - for now, just remove escapes */
6957 sp = stzalloc(sizeof(*sp));
6960 exparg.lastp = &sp->next;
6964 *exparg.lastp = NULL;
6966 *arglist->lastp = exparg.list;
6967 arglist->lastp = exparg.lastp;
6972 * Expand shell variables and backquotes inside a here document.
6975 expandhere(union node *arg, int fd)
6978 expandarg(arg, (struct arglist *)NULL, 0);
6979 full_write(fd, stackblock(), expdest - (char *)stackblock());
6983 * Returns true if the pattern matches the string.
6986 patmatch(char *pattern, const char *string)
6988 return pmatch(preglob(pattern, 0, 0), string);
6992 * See if a pattern matches in a case statement.
6995 casematch(union node *pattern, char *val)
6997 struct stackmark smark;
7000 setstackmark(&smark);
7001 argbackq = pattern->narg.backquote;
7002 STARTSTACKSTR(expdest);
7004 argstr(pattern->narg.text, EXP_TILDE | EXP_CASE,
7005 /* var_str_list: */ NULL);
7006 STACKSTRNUL(expdest);
7007 result = patmatch(stackblock(), val);
7008 popstackmark(&smark);
7013 /* ============ find_command */
7017 int (*builtin)(int, char **);
7018 /* unsigned flags; */
7020 #define IS_BUILTIN_SPECIAL(b) ((b)->name[0] & 1)
7021 /* "regular" builtins always take precedence over commands,
7022 * regardless of PATH=....%builtin... position */
7023 #define IS_BUILTIN_REGULAR(b) ((b)->name[0] & 2)
7024 #define IS_BUILTIN_ASSIGN(b) ((b)->name[0] & 4)
7027 smallint cmdtype; /* CMDxxx */
7030 /* index >= 0 for commands without path (slashes) */
7031 /* (TODO: what exactly does the value mean? PATH position?) */
7032 /* index == -1 for commands with slashes */
7033 /* index == (-2 - applet_no) for NOFORK applets */
7034 const struct builtincmd *cmd;
7035 struct funcnode *func;
7038 /* values of cmdtype */
7039 #define CMDUNKNOWN -1 /* no entry in table for command */
7040 #define CMDNORMAL 0 /* command is an executable program */
7041 #define CMDFUNCTION 1 /* command is a shell function */
7042 #define CMDBUILTIN 2 /* command is a shell builtin */
7044 /* action to find_command() */
7045 #define DO_ERR 0x01 /* prints errors */
7046 #define DO_ABS 0x02 /* checks absolute paths */
7047 #define DO_NOFUNC 0x04 /* don't return shell functions, for command */
7048 #define DO_ALTPATH 0x08 /* using alternate path */
7049 #define DO_ALTBLTIN 0x20 /* %builtin in alt. path */
7051 static void find_command(char *, struct cmdentry *, int, const char *);
7054 /* ============ Hashing commands */
7057 * When commands are first encountered, they are entered in a hash table.
7058 * This ensures that a full path search will not have to be done for them
7059 * on each invocation.
7061 * We should investigate converting to a linear search, even though that
7062 * would make the command name "hash" a misnomer.
7066 struct tblentry *next; /* next entry in hash chain */
7067 union param param; /* definition of builtin function */
7068 smallint cmdtype; /* CMDxxx */
7069 char rehash; /* if set, cd done since entry created */
7070 char cmdname[1]; /* name of command */
7073 static struct tblentry **cmdtable;
7074 #define INIT_G_cmdtable() do { \
7075 cmdtable = xzalloc(CMDTABLESIZE * sizeof(cmdtable[0])); \
7078 static int builtinloc = -1; /* index in path of %builtin, or -1 */
7082 tryexec(USE_FEATURE_SH_STANDALONE(int applet_no,) char *cmd, char **argv, char **envp)
7086 #if ENABLE_FEATURE_SH_STANDALONE
7087 if (applet_no >= 0) {
7088 if (APPLET_IS_NOEXEC(applet_no)) {
7091 run_applet_no_and_exit(applet_no, argv);
7093 /* re-exec ourselves with the new arguments */
7094 execve(bb_busybox_exec_path, argv, envp);
7095 /* If they called chroot or otherwise made the binary no longer
7096 * executable, fall through */
7103 execve(cmd, argv, envp);
7104 } while (errno == EINTR);
7106 execve(cmd, argv, envp);
7112 if (errno == ENOEXEC) {
7116 for (ap = argv; *ap; ap++)
7118 ap = new = ckmalloc((ap - argv + 2) * sizeof(ap[0]));
7120 ap[0] = cmd = (char *)DEFAULT_SHELL;
7123 while ((*ap++ = *argv++) != NULL)
7132 * Exec a program. Never returns. If you change this routine, you may
7133 * have to change the find_command routine as well.
7135 static void shellexec(char **, const char *, int) NORETURN;
7137 shellexec(char **argv, const char *path, int idx)
7143 #if ENABLE_FEATURE_SH_STANDALONE
7147 clearredir(/*drop:*/ 1);
7148 envp = listvars(VEXPORT, VUNSET, 0);
7149 if (strchr(argv[0], '/') != NULL
7150 #if ENABLE_FEATURE_SH_STANDALONE
7151 || (applet_no = find_applet_by_name(argv[0])) >= 0
7154 tryexec(USE_FEATURE_SH_STANDALONE(applet_no,) argv[0], argv, envp);
7158 while ((cmdname = padvance(&path, argv[0])) != NULL) {
7159 if (--idx < 0 && pathopt == NULL) {
7160 tryexec(USE_FEATURE_SH_STANDALONE(-1,) cmdname, argv, envp);
7161 if (errno != ENOENT && errno != ENOTDIR)
7168 /* Map to POSIX errors */
7180 exitstatus = exerrno;
7181 TRACE(("shellexec failed for %s, errno %d, suppressint %d\n",
7182 argv[0], e, suppressint));
7183 ash_msg_and_raise(EXEXEC, "%s: %s", argv[0], errmsg(e, "not found"));
7188 printentry(struct tblentry *cmdp)
7194 idx = cmdp->param.index;
7197 name = padvance(&path, cmdp->cmdname);
7199 } while (--idx >= 0);
7200 out1fmt("%s%s\n", name, (cmdp->rehash ? "*" : nullstr));
7204 * Clear out command entries. The argument specifies the first entry in
7205 * PATH which has changed.
7208 clearcmdentry(int firstchange)
7210 struct tblentry **tblp;
7211 struct tblentry **pp;
7212 struct tblentry *cmdp;
7215 for (tblp = cmdtable; tblp < &cmdtable[CMDTABLESIZE]; tblp++) {
7217 while ((cmdp = *pp) != NULL) {
7218 if ((cmdp->cmdtype == CMDNORMAL &&
7219 cmdp->param.index >= firstchange)
7220 || (cmdp->cmdtype == CMDBUILTIN &&
7221 builtinloc >= firstchange)
7234 * Locate a command in the command hash table. If "add" is nonzero,
7235 * add the command to the table if it is not already present. The
7236 * variable "lastcmdentry" is set to point to the address of the link
7237 * pointing to the entry, so that delete_cmd_entry can delete the
7240 * Interrupts must be off if called with add != 0.
7242 static struct tblentry **lastcmdentry;
7244 static struct tblentry *
7245 cmdlookup(const char *name, int add)
7247 unsigned int hashval;
7249 struct tblentry *cmdp;
7250 struct tblentry **pp;
7253 hashval = (unsigned char)*p << 4;
7255 hashval += (unsigned char)*p++;
7257 pp = &cmdtable[hashval % CMDTABLESIZE];
7258 for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
7259 if (strcmp(cmdp->cmdname, name) == 0)
7263 if (add && cmdp == NULL) {
7264 cmdp = *pp = ckzalloc(sizeof(struct tblentry)
7266 /* + 1 - already done because
7267 * tblentry::cmdname is char[1] */);
7268 /*cmdp->next = NULL; - ckzalloc did it */
7269 cmdp->cmdtype = CMDUNKNOWN;
7270 strcpy(cmdp->cmdname, name);
7277 * Delete the command entry returned on the last lookup.
7280 delete_cmd_entry(void)
7282 struct tblentry *cmdp;
7285 cmdp = *lastcmdentry;
7286 *lastcmdentry = cmdp->next;
7287 if (cmdp->cmdtype == CMDFUNCTION)
7288 freefunc(cmdp->param.func);
7294 * Add a new command entry, replacing any existing command entry for
7295 * the same name - except special builtins.
7298 addcmdentry(char *name, struct cmdentry *entry)
7300 struct tblentry *cmdp;
7302 cmdp = cmdlookup(name, 1);
7303 if (cmdp->cmdtype == CMDFUNCTION) {
7304 freefunc(cmdp->param.func);
7306 cmdp->cmdtype = entry->cmdtype;
7307 cmdp->param = entry->u;
7312 hashcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
7314 struct tblentry **pp;
7315 struct tblentry *cmdp;
7317 struct cmdentry entry;
7320 if (nextopt("r") != '\0') {
7325 if (*argptr == NULL) {
7326 for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
7327 for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
7328 if (cmdp->cmdtype == CMDNORMAL)
7336 while ((name = *argptr) != NULL) {
7337 cmdp = cmdlookup(name, 0);
7339 && (cmdp->cmdtype == CMDNORMAL
7340 || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0))
7344 find_command(name, &entry, DO_ERR, pathval());
7345 if (entry.cmdtype == CMDUNKNOWN)
7353 * Called when a cd is done. Marks all commands so the next time they
7354 * are executed they will be rehashed.
7359 struct tblentry **pp;
7360 struct tblentry *cmdp;
7362 for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
7363 for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
7364 if (cmdp->cmdtype == CMDNORMAL
7365 || (cmdp->cmdtype == CMDBUILTIN
7366 && !IS_BUILTIN_REGULAR(cmdp->param.cmd)
7376 * Fix command hash table when PATH changed.
7377 * Called before PATH is changed. The argument is the new value of PATH;
7378 * pathval() still returns the old value at this point.
7379 * Called with interrupts off.
7382 changepath(const char *new)
7390 firstchange = 9999; /* assume no change */
7396 if ((*old == '\0' && *new == ':')
7397 || (*old == ':' && *new == '\0'))
7399 old = new; /* ignore subsequent differences */
7403 if (*new == '%' && idx_bltin < 0 && prefix(new + 1, "builtin"))
7409 if (builtinloc < 0 && idx_bltin >= 0)
7410 builtinloc = idx_bltin; /* zap builtins */
7411 if (builtinloc >= 0 && idx_bltin < 0)
7413 clearcmdentry(firstchange);
7414 builtinloc = idx_bltin;
7429 #define TENDBQUOTE 12
7446 typedef smallint token_id_t;
7448 /* first char is indicating which tokens mark the end of a list */
7449 static const char *const tokname_array[] = {
7463 #define KWDOFFSET 13
7464 /* the following are keywords */
7486 static char buf[16];
7489 //if (tok < TSEMI) return tokname_array[tok] + 1;
7490 //sprintf(buf, "\"%s\"", tokname_array[tok] + 1);
7495 sprintf(buf + (tok >= TSEMI), "%s%c",
7496 tokname_array[tok] + 1, (tok >= TSEMI ? '"' : 0));
7500 /* Wrapper around strcmp for qsort/bsearch/... */
7502 pstrcmp(const void *a, const void *b)
7504 return strcmp((char*) a, (*(char**) b) + 1);
7507 static const char *const *
7508 findkwd(const char *s)
7510 return bsearch(s, tokname_array + KWDOFFSET,
7511 ARRAY_SIZE(tokname_array) - KWDOFFSET,
7512 sizeof(tokname_array[0]), pstrcmp);
7516 * Locate and print what a word is...
7519 describe_command(char *command, int describe_command_verbose)
7521 struct cmdentry entry;
7522 struct tblentry *cmdp;
7523 #if ENABLE_ASH_ALIAS
7524 const struct alias *ap;
7526 const char *path = pathval();
7528 if (describe_command_verbose) {
7532 /* First look at the keywords */
7533 if (findkwd(command)) {
7534 out1str(describe_command_verbose ? " is a shell keyword" : command);
7538 #if ENABLE_ASH_ALIAS
7539 /* Then look at the aliases */
7540 ap = lookupalias(command, 0);
7542 if (!describe_command_verbose) {
7547 out1fmt(" is an alias for %s", ap->val);
7551 /* Then check if it is a tracked alias */
7552 cmdp = cmdlookup(command, 0);
7554 entry.cmdtype = cmdp->cmdtype;
7555 entry.u = cmdp->param;
7557 /* Finally use brute force */
7558 find_command(command, &entry, DO_ABS, path);
7561 switch (entry.cmdtype) {
7563 int j = entry.u.index;
7569 p = padvance(&path, command);
7573 if (describe_command_verbose) {
7575 (cmdp ? " a tracked alias for" : nullstr), p
7584 if (describe_command_verbose) {
7585 out1str(" is a shell function");
7592 if (describe_command_verbose) {
7593 out1fmt(" is a %sshell builtin",
7594 IS_BUILTIN_SPECIAL(entry.u.cmd) ?
7595 "special " : nullstr
7603 if (describe_command_verbose) {
7604 out1str(": not found\n");
7609 outstr("\n", stdout);
7614 typecmd(int argc UNUSED_PARAM, char **argv)
7620 /* type -p ... ? (we don't bother checking for 'p') */
7621 if (argv[1] && argv[1][0] == '-') {
7626 err |= describe_command(argv[i++], verbose);
7631 #if ENABLE_ASH_CMDCMD
7633 commandcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
7641 while ((c = nextopt("pvV")) != '\0')
7643 verify |= VERIFY_VERBOSE;
7645 verify |= VERIFY_BRIEF;
7650 /* Mimic bash: just "command -v" doesn't complain, it's a nop */
7651 if (verify && (*argptr != NULL)) {
7652 return describe_command(*argptr, verify - VERIFY_BRIEF);
7660 /* ============ eval.c */
7662 static int funcblocksize; /* size of structures in function */
7663 static int funcstringsize; /* size of strings in node */
7664 static void *funcblock; /* block to allocate function from */
7665 static char *funcstring; /* block to allocate strings from */
7667 /* flags in argument to evaltree */
7668 #define EV_EXIT 01 /* exit after evaluating tree */
7669 #define EV_TESTED 02 /* exit status is checked; ignore -e flag */
7670 #define EV_BACKCMD 04 /* command executing within back quotes */
7672 static const short nodesize[N_NUMBER] = {
7673 [NCMD ] = SHELL_ALIGN(sizeof(struct ncmd)),
7674 [NPIPE ] = SHELL_ALIGN(sizeof(struct npipe)),
7675 [NREDIR ] = SHELL_ALIGN(sizeof(struct nredir)),
7676 [NBACKGND ] = SHELL_ALIGN(sizeof(struct nredir)),
7677 [NSUBSHELL] = SHELL_ALIGN(sizeof(struct nredir)),
7678 [NAND ] = SHELL_ALIGN(sizeof(struct nbinary)),
7679 [NOR ] = SHELL_ALIGN(sizeof(struct nbinary)),
7680 [NSEMI ] = SHELL_ALIGN(sizeof(struct nbinary)),
7681 [NIF ] = SHELL_ALIGN(sizeof(struct nif)),
7682 [NWHILE ] = SHELL_ALIGN(sizeof(struct nbinary)),
7683 [NUNTIL ] = SHELL_ALIGN(sizeof(struct nbinary)),
7684 [NFOR ] = SHELL_ALIGN(sizeof(struct nfor)),
7685 [NCASE ] = SHELL_ALIGN(sizeof(struct ncase)),
7686 [NCLIST ] = SHELL_ALIGN(sizeof(struct nclist)),
7687 [NDEFUN ] = SHELL_ALIGN(sizeof(struct narg)),
7688 [NARG ] = SHELL_ALIGN(sizeof(struct narg)),
7689 [NTO ] = SHELL_ALIGN(sizeof(struct nfile)),
7690 #if ENABLE_ASH_BASH_COMPAT
7691 [NTO2 ] = SHELL_ALIGN(sizeof(struct nfile)),
7693 [NCLOBBER ] = SHELL_ALIGN(sizeof(struct nfile)),
7694 [NFROM ] = SHELL_ALIGN(sizeof(struct nfile)),
7695 [NFROMTO ] = SHELL_ALIGN(sizeof(struct nfile)),
7696 [NAPPEND ] = SHELL_ALIGN(sizeof(struct nfile)),
7697 [NTOFD ] = SHELL_ALIGN(sizeof(struct ndup)),
7698 [NFROMFD ] = SHELL_ALIGN(sizeof(struct ndup)),
7699 [NHERE ] = SHELL_ALIGN(sizeof(struct nhere)),
7700 [NXHERE ] = SHELL_ALIGN(sizeof(struct nhere)),
7701 [NNOT ] = SHELL_ALIGN(sizeof(struct nnot)),
7704 static void calcsize(union node *n);
7707 sizenodelist(struct nodelist *lp)
7710 funcblocksize += SHELL_ALIGN(sizeof(struct nodelist));
7717 calcsize(union node *n)
7721 funcblocksize += nodesize[n->type];
7724 calcsize(n->ncmd.redirect);
7725 calcsize(n->ncmd.args);
7726 calcsize(n->ncmd.assign);
7729 sizenodelist(n->npipe.cmdlist);
7734 calcsize(n->nredir.redirect);
7735 calcsize(n->nredir.n);
7742 calcsize(n->nbinary.ch2);
7743 calcsize(n->nbinary.ch1);
7746 calcsize(n->nif.elsepart);
7747 calcsize(n->nif.ifpart);
7748 calcsize(n->nif.test);
7751 funcstringsize += strlen(n->nfor.var) + 1;
7752 calcsize(n->nfor.body);
7753 calcsize(n->nfor.args);
7756 calcsize(n->ncase.cases);
7757 calcsize(n->ncase.expr);
7760 calcsize(n->nclist.body);
7761 calcsize(n->nclist.pattern);
7762 calcsize(n->nclist.next);
7766 sizenodelist(n->narg.backquote);
7767 funcstringsize += strlen(n->narg.text) + 1;
7768 calcsize(n->narg.next);
7771 #if ENABLE_ASH_BASH_COMPAT
7778 calcsize(n->nfile.fname);
7779 calcsize(n->nfile.next);
7783 calcsize(n->ndup.vname);
7784 calcsize(n->ndup.next);
7788 calcsize(n->nhere.doc);
7789 calcsize(n->nhere.next);
7792 calcsize(n->nnot.com);
7798 nodeckstrdup(char *s)
7800 char *rtn = funcstring;
7802 strcpy(funcstring, s);
7803 funcstring += strlen(s) + 1;
7807 static union node *copynode(union node *);
7809 static struct nodelist *
7810 copynodelist(struct nodelist *lp)
7812 struct nodelist *start;
7813 struct nodelist **lpp;
7818 funcblock = (char *) funcblock + SHELL_ALIGN(sizeof(struct nodelist));
7819 (*lpp)->n = copynode(lp->n);
7821 lpp = &(*lpp)->next;
7828 copynode(union node *n)
7835 funcblock = (char *) funcblock + nodesize[n->type];
7839 new->ncmd.redirect = copynode(n->ncmd.redirect);
7840 new->ncmd.args = copynode(n->ncmd.args);
7841 new->ncmd.assign = copynode(n->ncmd.assign);
7844 new->npipe.cmdlist = copynodelist(n->npipe.cmdlist);
7845 new->npipe.pipe_backgnd = n->npipe.pipe_backgnd;
7850 new->nredir.redirect = copynode(n->nredir.redirect);
7851 new->nredir.n = copynode(n->nredir.n);
7858 new->nbinary.ch2 = copynode(n->nbinary.ch2);
7859 new->nbinary.ch1 = copynode(n->nbinary.ch1);
7862 new->nif.elsepart = copynode(n->nif.elsepart);
7863 new->nif.ifpart = copynode(n->nif.ifpart);
7864 new->nif.test = copynode(n->nif.test);
7867 new->nfor.var = nodeckstrdup(n->nfor.var);
7868 new->nfor.body = copynode(n->nfor.body);
7869 new->nfor.args = copynode(n->nfor.args);
7872 new->ncase.cases = copynode(n->ncase.cases);
7873 new->ncase.expr = copynode(n->ncase.expr);
7876 new->nclist.body = copynode(n->nclist.body);
7877 new->nclist.pattern = copynode(n->nclist.pattern);
7878 new->nclist.next = copynode(n->nclist.next);
7882 new->narg.backquote = copynodelist(n->narg.backquote);
7883 new->narg.text = nodeckstrdup(n->narg.text);
7884 new->narg.next = copynode(n->narg.next);
7887 #if ENABLE_ASH_BASH_COMPAT
7894 new->nfile.fname = copynode(n->nfile.fname);
7895 new->nfile.fd = n->nfile.fd;
7896 new->nfile.next = copynode(n->nfile.next);
7900 new->ndup.vname = copynode(n->ndup.vname);
7901 new->ndup.dupfd = n->ndup.dupfd;
7902 new->ndup.fd = n->ndup.fd;
7903 new->ndup.next = copynode(n->ndup.next);
7907 new->nhere.doc = copynode(n->nhere.doc);
7908 new->nhere.fd = n->nhere.fd;
7909 new->nhere.next = copynode(n->nhere.next);
7912 new->nnot.com = copynode(n->nnot.com);
7915 new->type = n->type;
7920 * Make a copy of a parse tree.
7922 static struct funcnode *
7923 copyfunc(union node *n)
7928 funcblocksize = offsetof(struct funcnode, n);
7931 blocksize = funcblocksize;
7932 f = ckmalloc(blocksize + funcstringsize);
7933 funcblock = (char *) f + offsetof(struct funcnode, n);
7934 funcstring = (char *) f + blocksize;
7941 * Define a shell function.
7944 defun(char *name, union node *func)
7946 struct cmdentry entry;
7949 entry.cmdtype = CMDFUNCTION;
7950 entry.u.func = copyfunc(func);
7951 addcmdentry(name, &entry);
7955 /* Reasons for skipping commands (see comment on breakcmd routine) */
7956 #define SKIPBREAK (1 << 0)
7957 #define SKIPCONT (1 << 1)
7958 #define SKIPFUNC (1 << 2)
7959 #define SKIPFILE (1 << 3)
7960 #define SKIPEVAL (1 << 4)
7961 static smallint evalskip; /* set to SKIPxxx if we are skipping commands */
7962 static int skipcount; /* number of levels to skip */
7963 static int funcnest; /* depth of function calls */
7964 static int loopnest; /* current loop nesting level */
7966 /* Forward decl way out to parsing code - dotrap needs it */
7967 static int evalstring(char *s, int mask);
7969 /* Called to execute a trap.
7970 * Single callsite - at the end of evaltree().
7971 * If we return non-zero, exaltree raises EXEXIT exception.
7973 * Perhaps we should avoid entering new trap handlers
7974 * while we are executing a trap handler. [is it a TODO?]
7983 savestatus = exitstatus;
7987 TRACE(("dotrap entered\n"));
7988 for (sig = 1, g = gotsig; sig < NSIG; sig++, g++) {
7995 /* non-trapped SIGINT is handled separately by raise_interrupt,
7996 * don't upset it by resetting gotsig[SIGINT-1] */
7997 if (sig == SIGINT && !t)
8000 TRACE(("sig %d is active, will run handler '%s'\n", sig, t));
8004 want_exexit = evalstring(t, SKIPEVAL);
8005 exitstatus = savestatus;
8007 TRACE(("dotrap returns %d\n", want_exexit));
8012 TRACE(("dotrap returns 0\n"));
8016 /* forward declarations - evaluation is fairly recursive business... */
8017 static void evalloop(union node *, int);
8018 static void evalfor(union node *, int);
8019 static void evalcase(union node *, int);
8020 static void evalsubshell(union node *, int);
8021 static void expredir(union node *);
8022 static void evalpipe(union node *, int);
8023 static void evalcommand(union node *, int);
8024 static int evalbltin(const struct builtincmd *, int, char **);
8025 static void prehash(union node *);
8028 * Evaluate a parse tree. The value is left in the global variable
8032 evaltree(union node *n, int flags)
8034 struct jmploc *volatile savehandler = exception_handler;
8035 struct jmploc jmploc;
8037 void (*evalfn)(union node *, int);
8041 SAVE_INT(int_level);
8044 TRACE(("evaltree(NULL) called\n"));
8047 TRACE(("evaltree(%p: %d, %d) called\n", n, n->type, flags));
8049 exception_handler = &jmploc;
8051 int err = setjmp(jmploc.loc);
8053 /* if it was a signal, check for trap handlers */
8054 if (exception_type == EXSIG) {
8055 TRACE(("exception %d (EXSIG) in evaltree, err=%d\n",
8056 exception_type, err));
8059 /* continue on the way out */
8060 TRACE(("exception %d in evaltree, propagating err=%d\n",
8061 exception_type, err));
8062 exception_handler = savehandler;
8063 longjmp(exception_handler->loc, err);
8070 out1fmt("Node type = %d\n", n->type);
8075 evaltree(n->nnot.com, EV_TESTED);
8076 status = !exitstatus;
8079 expredir(n->nredir.redirect);
8080 status = redirectsafe(n->nredir.redirect, REDIR_PUSH);
8082 evaltree(n->nredir.n, flags & EV_TESTED);
8083 status = exitstatus;
8085 popredir(/*drop:*/ 0, /*restore:*/ 0 /* not sure */);
8088 evalfn = evalcommand;
8090 if (eflag && !(flags & EV_TESTED))
8102 evalfn = evalsubshell;
8115 #error NAND + 1 != NOR
8117 #if NOR + 1 != NSEMI
8118 #error NOR + 1 != NSEMI
8120 unsigned is_or = n->type - NAND;
8123 (flags | ((is_or >> 1) - 1)) & EV_TESTED
8125 if (!exitstatus == is_or)
8138 evaltree(n->nif.test, EV_TESTED);
8141 if (exitstatus == 0) {
8145 if (n->nif.elsepart) {
8146 n = n->nif.elsepart;
8151 defun(n->narg.text, n->narg.next);
8155 exitstatus = status;
8160 exception_handler = savehandler;
8162 if (checkexit & exitstatus)
8163 evalskip |= SKIPEVAL;
8164 else if (pendingsig && dotrap())
8167 if (flags & EV_EXIT) {
8169 raise_exception(EXEXIT);
8172 RESTORE_INT(int_level);
8173 TRACE(("leaving evaltree (no interrupts)\n"));
8176 #if !defined(__alpha__) || (defined(__GNUC__) && __GNUC__ >= 3)
8179 void evaltreenr(union node *, int) __attribute__ ((alias("evaltree"),__noreturn__));
8182 evalloop(union node *n, int flags)
8192 evaltree(n->nbinary.ch1, EV_TESTED);
8195 if (evalskip == SKIPCONT && --skipcount <= 0) {
8199 if (evalskip == SKIPBREAK && --skipcount <= 0)
8204 if (n->type != NWHILE)
8208 evaltree(n->nbinary.ch2, flags);
8209 status = exitstatus;
8214 exitstatus = status;
8218 evalfor(union node *n, int flags)
8220 struct arglist arglist;
8223 struct stackmark smark;
8225 setstackmark(&smark);
8226 arglist.list = NULL;
8227 arglist.lastp = &arglist.list;
8228 for (argp = n->nfor.args; argp; argp = argp->narg.next) {
8229 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE | EXP_RECORD);
8234 *arglist.lastp = NULL;
8239 for (sp = arglist.list; sp; sp = sp->next) {
8240 setvar(n->nfor.var, sp->text, 0);
8241 evaltree(n->nfor.body, flags);
8243 if (evalskip == SKIPCONT && --skipcount <= 0) {
8247 if (evalskip == SKIPBREAK && --skipcount <= 0)
8254 popstackmark(&smark);
8258 evalcase(union node *n, int flags)
8262 struct arglist arglist;
8263 struct stackmark smark;
8265 setstackmark(&smark);
8266 arglist.list = NULL;
8267 arglist.lastp = &arglist.list;
8268 expandarg(n->ncase.expr, &arglist, EXP_TILDE);
8270 for (cp = n->ncase.cases; cp && evalskip == 0; cp = cp->nclist.next) {
8271 for (patp = cp->nclist.pattern; patp; patp = patp->narg.next) {
8272 if (casematch(patp, arglist.list->text)) {
8273 if (evalskip == 0) {
8274 evaltree(cp->nclist.body, flags);
8281 popstackmark(&smark);
8285 * Kick off a subshell to evaluate a tree.
8288 evalsubshell(union node *n, int flags)
8291 int backgnd = (n->type == NBACKGND);
8294 expredir(n->nredir.redirect);
8295 if (!backgnd && flags & EV_EXIT && !trap[0])
8298 jp = makejob(/*n,*/ 1);
8299 if (forkshell(jp, n, backgnd) == 0) {
8303 flags &=~ EV_TESTED;
8305 redirect(n->nredir.redirect, 0);
8306 evaltreenr(n->nredir.n, flags);
8311 status = waitforjob(jp);
8312 exitstatus = status;
8317 * Compute the names of the files in a redirection list.
8319 static void fixredir(union node *, const char *, int);
8321 expredir(union node *n)
8325 for (redir = n; redir; redir = redir->nfile.next) {
8329 fn.lastp = &fn.list;
8330 switch (redir->type) {
8334 #if ENABLE_ASH_BASH_COMPAT
8339 expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
8340 #if ENABLE_ASH_BASH_COMPAT
8343 redir->nfile.expfname = fn.list->text;
8346 case NTOFD: /* >& */
8347 if (redir->ndup.vname) {
8348 expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE);
8349 if (fn.list == NULL)
8350 ash_msg_and_raise_error("redir error");
8351 #if ENABLE_ASH_BASH_COMPAT
8352 //FIXME: we used expandarg with different args!
8353 if (!isdigit_str9(fn.list->text)) {
8354 /* >&file, not >&fd */
8355 if (redir->nfile.fd != 1) /* 123>&file - BAD */
8356 ash_msg_and_raise_error("redir error");
8358 goto store_expfname;
8361 fixredir(redir, fn.list->text, 1);
8369 * Evaluate a pipeline. All the processes in the pipeline are children
8370 * of the process creating the pipeline. (This differs from some versions
8371 * of the shell, which make the last process in a pipeline the parent
8375 evalpipe(union node *n, int flags)
8378 struct nodelist *lp;
8383 TRACE(("evalpipe(0x%lx) called\n", (long)n));
8385 for (lp = n->npipe.cmdlist; lp; lp = lp->next)
8389 jp = makejob(/*n,*/ pipelen);
8391 for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
8395 if (pipe(pip) < 0) {
8397 ash_msg_and_raise_error("pipe call failed");
8400 if (forkshell(jp, lp->n, n->npipe.pipe_backgnd) == 0) {
8413 evaltreenr(lp->n, flags);
8421 if (n->npipe.pipe_backgnd == 0) {
8422 exitstatus = waitforjob(jp);
8423 TRACE(("evalpipe: job done exit status %d\n", exitstatus));
8429 * Controls whether the shell is interactive or not.
8432 setinteractive(int on)
8434 static smallint is_interactive;
8436 if (++on == is_interactive)
8438 is_interactive = on;
8442 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
8443 if (is_interactive > 1) {
8444 /* Looks like they want an interactive shell */
8445 static smallint did_banner;
8450 "%s built-in shell (ash)\n"
8451 "Enter 'help' for a list of built-in commands."
8466 setinteractive(iflag);
8468 #if ENABLE_FEATURE_EDITING_VI
8470 line_input_state->flags |= VI_MODE;
8472 line_input_state->flags &= ~VI_MODE;
8474 viflag = 0; /* forcibly keep the option off */
8478 static struct localvar *localvars;
8481 * Called after a function returns.
8482 * Interrupts must be off.
8487 struct localvar *lvp;
8490 while ((lvp = localvars) != NULL) {
8491 localvars = lvp->next;
8493 TRACE(("poplocalvar %s", vp ? vp->text : "-"));
8494 if (vp == NULL) { /* $- saved */
8495 memcpy(optlist, lvp->text, sizeof(optlist));
8496 free((char*)lvp->text);
8498 } else if ((lvp->flags & (VUNSET|VSTRFIXED)) == VUNSET) {
8502 (*vp->func)(strchrnul(lvp->text, '=') + 1);
8503 if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
8504 free((char*)vp->text);
8505 vp->flags = lvp->flags;
8506 vp->text = lvp->text;
8513 evalfun(struct funcnode *func, int argc, char **argv, int flags)
8515 volatile struct shparam saveparam;
8516 struct localvar *volatile savelocalvars;
8517 struct jmploc *volatile savehandler;
8518 struct jmploc jmploc;
8521 saveparam = shellparam;
8522 savelocalvars = localvars;
8523 e = setjmp(jmploc.loc);
8528 savehandler = exception_handler;
8529 exception_handler = &jmploc;
8531 shellparam.malloced = 0;
8535 shellparam.nparam = argc - 1;
8536 shellparam.p = argv + 1;
8537 #if ENABLE_ASH_GETOPTS
8538 shellparam.optind = 1;
8539 shellparam.optoff = -1;
8541 evaltree(&func->n, flags & EV_TESTED);
8547 localvars = savelocalvars;
8548 freeparam(&shellparam);
8549 shellparam = saveparam;
8550 exception_handler = savehandler;
8552 evalskip &= ~SKIPFUNC;
8556 #if ENABLE_ASH_CMDCMD
8558 parse_command_args(char **argv, const char **path)
8571 if (c == '-' && !*cp) {
8578 *path = bb_default_path;
8581 /* run 'typecmd' for other options */
8592 * Make a variable a local variable. When a variable is made local, it's
8593 * value and flags are saved in a localvar structure. The saved values
8594 * will be restored when the shell function returns. We handle the name
8595 * "-" as a special case.
8600 struct localvar *lvp;
8605 lvp = ckzalloc(sizeof(struct localvar));
8606 if (LONE_DASH(name)) {
8608 p = ckmalloc(sizeof(optlist));
8609 lvp->text = memcpy(p, optlist, sizeof(optlist));
8614 vpp = hashvar(name);
8615 vp = *findvar(vpp, name);
8616 eq = strchr(name, '=');
8619 setvareq(name, VSTRFIXED);
8621 setvar(name, NULL, VSTRFIXED);
8622 vp = *vpp; /* the new variable */
8623 lvp->flags = VUNSET;
8625 lvp->text = vp->text;
8626 lvp->flags = vp->flags;
8627 vp->flags |= VSTRFIXED|VTEXTFIXED;
8633 lvp->next = localvars;
8639 * The "local" command.
8642 localcmd(int argc UNUSED_PARAM, char **argv)
8647 while ((name = *argv++) != NULL) {
8654 falsecmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
8660 truecmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
8666 execcmd(int argc UNUSED_PARAM, char **argv)
8669 iflag = 0; /* exit on error */
8672 shellexec(argv + 1, pathval(), 0);
8678 * The return command.
8681 returncmd(int argc UNUSED_PARAM, char **argv)
8684 * If called outside a function, do what ksh does;
8685 * skip the rest of the file.
8687 evalskip = funcnest ? SKIPFUNC : SKIPFILE;
8688 return argv[1] ? number(argv[1]) : exitstatus;
8691 /* Forward declarations for builtintab[] */
8692 static int breakcmd(int, char **);
8693 static int dotcmd(int, char **);
8694 static int evalcmd(int, char **);
8695 static int exitcmd(int, char **);
8696 static int exportcmd(int, char **);
8697 #if ENABLE_ASH_GETOPTS
8698 static int getoptscmd(int, char **);
8700 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
8701 static int helpcmd(int, char **);
8703 #if ENABLE_ASH_MATH_SUPPORT
8704 static int letcmd(int, char **);
8706 static int readcmd(int, char **);
8707 static int setcmd(int, char **);
8708 static int shiftcmd(int, char **);
8709 static int timescmd(int, char **);
8710 static int trapcmd(int, char **);
8711 static int umaskcmd(int, char **);
8712 static int unsetcmd(int, char **);
8713 static int ulimitcmd(int, char **);
8715 #define BUILTIN_NOSPEC "0"
8716 #define BUILTIN_SPECIAL "1"
8717 #define BUILTIN_REGULAR "2"
8718 #define BUILTIN_SPEC_REG "3"
8719 #define BUILTIN_ASSIGN "4"
8720 #define BUILTIN_SPEC_ASSG "5"
8721 #define BUILTIN_REG_ASSG "6"
8722 #define BUILTIN_SPEC_REG_ASSG "7"
8724 /* We do not handle [[ expr ]] bashism bash-compatibly,
8725 * we make it a synonym of [ expr ].
8726 * Basically, word splitting and pathname expansion should NOT be performed
8728 * no word splitting: a="a b"; [[ $a = "a b" ]]; echo $? should print "0"
8729 * no pathname expansion: [[ /bin/m* = "/bin/m*" ]]; echo $? should print "0"
8730 * Additional operators:
8731 * || and && should work as -o and -a
8733 * Apart from the above, [[ expr ]] should work as [ expr ]
8736 #define echocmd echo_main
8737 #define printfcmd printf_main
8738 #define testcmd test_main
8740 /* Keep these in proper order since it is searched via bsearch() */
8741 static const struct builtincmd builtintab[] = {
8742 { BUILTIN_SPEC_REG ".", dotcmd },
8743 { BUILTIN_SPEC_REG ":", truecmd },
8744 #if ENABLE_ASH_BUILTIN_TEST
8745 { BUILTIN_REGULAR "[", testcmd },
8746 #if ENABLE_ASH_BASH_COMPAT
8747 { BUILTIN_REGULAR "[[", testcmd },
8750 #if ENABLE_ASH_ALIAS
8751 { BUILTIN_REG_ASSG "alias", aliascmd },
8754 { BUILTIN_REGULAR "bg", fg_bgcmd },
8756 { BUILTIN_SPEC_REG "break", breakcmd },
8757 { BUILTIN_REGULAR "cd", cdcmd },
8758 { BUILTIN_NOSPEC "chdir", cdcmd },
8759 #if ENABLE_ASH_CMDCMD
8760 { BUILTIN_REGULAR "command", commandcmd },
8762 { BUILTIN_SPEC_REG "continue", breakcmd },
8763 #if ENABLE_ASH_BUILTIN_ECHO
8764 { BUILTIN_REGULAR "echo", echocmd },
8766 { BUILTIN_SPEC_REG "eval", evalcmd },
8767 { BUILTIN_SPEC_REG "exec", execcmd },
8768 { BUILTIN_SPEC_REG "exit", exitcmd },
8769 { BUILTIN_SPEC_REG_ASSG "export", exportcmd },
8770 { BUILTIN_REGULAR "false", falsecmd },
8772 { BUILTIN_REGULAR "fg", fg_bgcmd },
8774 #if ENABLE_ASH_GETOPTS
8775 { BUILTIN_REGULAR "getopts", getoptscmd },
8777 { BUILTIN_NOSPEC "hash", hashcmd },
8778 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
8779 { BUILTIN_NOSPEC "help", helpcmd },
8782 { BUILTIN_REGULAR "jobs", jobscmd },
8783 { BUILTIN_REGULAR "kill", killcmd },
8785 #if ENABLE_ASH_MATH_SUPPORT
8786 { BUILTIN_NOSPEC "let", letcmd },
8788 { BUILTIN_ASSIGN "local", localcmd },
8789 #if ENABLE_ASH_BUILTIN_PRINTF
8790 { BUILTIN_REGULAR "printf", printfcmd },
8792 { BUILTIN_NOSPEC "pwd", pwdcmd },
8793 { BUILTIN_REGULAR "read", readcmd },
8794 { BUILTIN_SPEC_REG_ASSG "readonly", exportcmd },
8795 { BUILTIN_SPEC_REG "return", returncmd },
8796 { BUILTIN_SPEC_REG "set", setcmd },
8797 { BUILTIN_SPEC_REG "shift", shiftcmd },
8798 { BUILTIN_SPEC_REG "source", dotcmd },
8799 #if ENABLE_ASH_BUILTIN_TEST
8800 { BUILTIN_REGULAR "test", testcmd },
8802 { BUILTIN_SPEC_REG "times", timescmd },
8803 { BUILTIN_SPEC_REG "trap", trapcmd },
8804 { BUILTIN_REGULAR "true", truecmd },
8805 { BUILTIN_NOSPEC "type", typecmd },
8806 { BUILTIN_NOSPEC "ulimit", ulimitcmd },
8807 { BUILTIN_REGULAR "umask", umaskcmd },
8808 #if ENABLE_ASH_ALIAS
8809 { BUILTIN_REGULAR "unalias", unaliascmd },
8811 { BUILTIN_SPEC_REG "unset", unsetcmd },
8812 { BUILTIN_REGULAR "wait", waitcmd },
8815 /* Should match the above table! */
8816 #define COMMANDCMD (builtintab + \
8818 1 * ENABLE_ASH_BUILTIN_TEST + \
8819 1 * ENABLE_ASH_BUILTIN_TEST * ENABLE_ASH_BASH_COMPAT + \
8820 1 * ENABLE_ASH_ALIAS + \
8821 1 * ENABLE_ASH_JOB_CONTROL + \
8823 #define EXECCMD (builtintab + \
8825 1 * ENABLE_ASH_BUILTIN_TEST + \
8826 1 * ENABLE_ASH_BUILTIN_TEST * ENABLE_ASH_BASH_COMPAT + \
8827 1 * ENABLE_ASH_ALIAS + \
8828 1 * ENABLE_ASH_JOB_CONTROL + \
8830 1 * ENABLE_ASH_CMDCMD + \
8832 ENABLE_ASH_BUILTIN_ECHO + \
8836 * Search the table of builtin commands.
8838 static struct builtincmd *
8839 find_builtin(const char *name)
8841 struct builtincmd *bp;
8844 name, builtintab, ARRAY_SIZE(builtintab), sizeof(builtintab[0]),
8851 * Execute a simple command.
8854 isassignment(const char *p)
8856 const char *q = endofname(p);
8862 bltincmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
8864 /* Preserve exitstatus of a previous possible redirection
8865 * as POSIX mandates */
8866 return back_exitstatus;
8869 evalcommand(union node *cmd, int flags)
8871 static const struct builtincmd null_bltin = {
8872 "\0\0", bltincmd /* why three NULs? */
8874 struct stackmark smark;
8876 struct arglist arglist;
8877 struct arglist varlist;
8880 const struct strlist *sp;
8881 struct cmdentry cmdentry;
8888 struct builtincmd *bcmd;
8889 smallint cmd_is_exec;
8890 smallint pseudovarflag = 0;
8892 /* First expand the arguments. */
8893 TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
8894 setstackmark(&smark);
8895 back_exitstatus = 0;
8897 cmdentry.cmdtype = CMDBUILTIN;
8898 cmdentry.u.cmd = &null_bltin;
8899 varlist.lastp = &varlist.list;
8900 *varlist.lastp = NULL;
8901 arglist.lastp = &arglist.list;
8902 *arglist.lastp = NULL;
8905 if (cmd->ncmd.args) {
8906 bcmd = find_builtin(cmd->ncmd.args->narg.text);
8907 pseudovarflag = bcmd && IS_BUILTIN_ASSIGN(bcmd);
8910 for (argp = cmd->ncmd.args; argp; argp = argp->narg.next) {
8911 struct strlist **spp;
8913 spp = arglist.lastp;
8914 if (pseudovarflag && isassignment(argp->narg.text))
8915 expandarg(argp, &arglist, EXP_VARTILDE);
8917 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
8919 for (sp = *spp; sp; sp = sp->next)
8923 argv = nargv = stalloc(sizeof(char *) * (argc + 1));
8924 for (sp = arglist.list; sp; sp = sp->next) {
8925 TRACE(("evalcommand arg: %s\n", sp->text));
8926 *nargv++ = sp->text;
8931 if (iflag && funcnest == 0 && argc > 0)
8932 lastarg = nargv[-1];
8935 expredir(cmd->ncmd.redirect);
8936 status = redirectsafe(cmd->ncmd.redirect, REDIR_PUSH | REDIR_SAVEFD2);
8939 for (argp = cmd->ncmd.assign; argp; argp = argp->narg.next) {
8940 struct strlist **spp;
8943 spp = varlist.lastp;
8944 expandarg(argp, &varlist, EXP_VARTILDE);
8947 * Modify the command lookup path, if a PATH= assignment
8951 if (varequal(p, path))
8955 /* Print the command if xflag is set. */
8958 const char *p = " %s";
8961 fdprintf(preverrout_fd, p, expandstr(ps4val()));
8964 for (n = 0; n < 2; n++) {
8966 fdprintf(preverrout_fd, p, sp->text);
8974 safe_write(preverrout_fd, "\n", 1);
8980 /* Now locate the command. */
8982 const char *oldpath;
8983 int cmd_flag = DO_ERR;
8988 find_command(argv[0], &cmdentry, cmd_flag, path);
8989 if (cmdentry.cmdtype == CMDUNKNOWN) {
8995 /* implement bltin and command here */
8996 if (cmdentry.cmdtype != CMDBUILTIN)
8999 spclbltin = IS_BUILTIN_SPECIAL(cmdentry.u.cmd);
9000 if (cmdentry.u.cmd == EXECCMD)
9002 #if ENABLE_ASH_CMDCMD
9003 if (cmdentry.u.cmd == COMMANDCMD) {
9005 nargv = parse_command_args(argv, &path);
9008 argc -= nargv - argv;
9010 cmd_flag |= DO_NOFUNC;
9018 /* We have a redirection error. */
9020 raise_exception(EXERROR);
9022 exitstatus = status;
9026 /* Execute the command. */
9027 switch (cmdentry.cmdtype) {
9030 #if ENABLE_FEATURE_SH_NOFORK
9031 /* Hmmm... shouldn't it happen somewhere in forkshell() instead?
9032 * Why "fork off a child process if necessary" doesn't apply to NOFORK? */
9034 /* find_command() encodes applet_no as (-2 - applet_no) */
9035 int applet_no = (- cmdentry.u.index - 2);
9036 if (applet_no >= 0 && APPLET_IS_NOFORK(applet_no)) {
9037 listsetvar(varlist.list, VEXPORT|VSTACK);
9038 /* run <applet>_main() */
9039 exitstatus = run_nofork_applet(applet_no, argv);
9044 /* Fork off a child process if necessary. */
9045 if (!(flags & EV_EXIT) || trap[0]) {
9047 jp = makejob(/*cmd,*/ 1);
9048 if (forkshell(jp, cmd, FORK_FG) != 0) {
9049 exitstatus = waitforjob(jp);
9051 TRACE(("forked child exited with %d\n", exitstatus));
9056 listsetvar(varlist.list, VEXPORT|VSTACK);
9057 shellexec(argv, path, cmdentry.u.index);
9061 cmdenviron = varlist.list;
9063 struct strlist *list = cmdenviron;
9065 if (spclbltin > 0 || argc == 0) {
9067 if (cmd_is_exec && argc > 1)
9070 listsetvar(list, i);
9072 /* Tight loop with builtins only:
9073 * "while kill -0 $child; do true; done"
9074 * will never exit even if $child died, unless we do this
9075 * to reap the zombie and make kill detect that it's gone: */
9076 dowait(DOWAIT_NONBLOCK, NULL);
9078 if (evalbltin(cmdentry.u.cmd, argc, argv)) {
9080 int i = exception_type;
9085 exit_status = 128 + SIGINT;
9087 exit_status = 128 + pendingsig;
9088 exitstatus = exit_status;
9089 if (i == EXINT || spclbltin > 0) {
9091 longjmp(exception_handler->loc, 1);
9098 listsetvar(varlist.list, 0);
9099 /* See above for the rationale */
9100 dowait(DOWAIT_NONBLOCK, NULL);
9101 if (evalfun(cmdentry.u.func, argc, argv, flags))
9107 popredir(/*drop:*/ cmd_is_exec, /*restore:*/ cmd_is_exec);
9109 /* dsl: I think this is intended to be used to support
9110 * '_' in 'vi' command mode during line editing...
9111 * However I implemented that within libedit itself.
9113 setvar("_", lastarg, 0);
9115 popstackmark(&smark);
9119 evalbltin(const struct builtincmd *cmd, int argc, char **argv)
9121 char *volatile savecmdname;
9122 struct jmploc *volatile savehandler;
9123 struct jmploc jmploc;
9126 savecmdname = commandname;
9127 i = setjmp(jmploc.loc);
9130 savehandler = exception_handler;
9131 exception_handler = &jmploc;
9132 commandname = argv[0];
9134 optptr = NULL; /* initialize nextopt */
9135 exitstatus = (*cmd->builtin)(argc, argv);
9136 flush_stdout_stderr();
9138 exitstatus |= ferror(stdout);
9140 commandname = savecmdname;
9142 exception_handler = savehandler;
9148 goodname(const char *p)
9150 return !*endofname(p);
9155 * Search for a command. This is called before we fork so that the
9156 * location of the command will be available in the parent as well as
9157 * the child. The check for "goodname" is an overly conservative
9158 * check that the name will not be subject to expansion.
9161 prehash(union node *n)
9163 struct cmdentry entry;
9165 if (n->type == NCMD && n->ncmd.args && goodname(n->ncmd.args->narg.text))
9166 find_command(n->ncmd.args->narg.text, &entry, 0, pathval());
9170 /* ============ Builtin commands
9172 * Builtin commands whose functions are closely tied to evaluation
9173 * are implemented here.
9177 * Handle break and continue commands. Break, continue, and return are
9178 * all handled by setting the evalskip flag. The evaluation routines
9179 * above all check this flag, and if it is set they start skipping
9180 * commands rather than executing them. The variable skipcount is
9181 * the number of loops to break/continue, or the number of function
9182 * levels to return. (The latter is always 1.) It should probably
9183 * be an error to break out of more loops than exist, but it isn't
9184 * in the standard shell so we don't make it one here.
9187 breakcmd(int argc UNUSED_PARAM, char **argv)
9189 int n = argv[1] ? number(argv[1]) : 1;
9192 ash_msg_and_raise_error(illnum, argv[1]);
9196 evalskip = (**argv == 'c') ? SKIPCONT : SKIPBREAK;
9203 /* ============ input.c
9205 * This implements the input routines used by the parser.
9209 INPUT_PUSH_FILE = 1,
9210 INPUT_NOFILE_OK = 2,
9213 static smallint checkkwd;
9214 /* values of checkkwd variable */
9215 #define CHKALIAS 0x1
9220 * Push a string back onto the input at this current parsefile level.
9221 * We handle aliases this way.
9223 #if !ENABLE_ASH_ALIAS
9224 #define pushstring(s, ap) pushstring(s)
9227 pushstring(char *s, struct alias *ap)
9234 if (g_parsefile->strpush) {
9235 sp = ckzalloc(sizeof(*sp));
9236 sp->prev = g_parsefile->strpush;
9238 sp = &(g_parsefile->basestrpush);
9240 g_parsefile->strpush = sp;
9241 sp->prev_string = g_parsefile->next_to_pgetc;
9242 sp->prev_left_in_line = g_parsefile->left_in_line;
9243 #if ENABLE_ASH_ALIAS
9246 ap->flag |= ALIASINUSE;
9250 g_parsefile->next_to_pgetc = s;
9251 g_parsefile->left_in_line = len;
9258 struct strpush *sp = g_parsefile->strpush;
9261 #if ENABLE_ASH_ALIAS
9263 if (g_parsefile->next_to_pgetc[-1] == ' '
9264 || g_parsefile->next_to_pgetc[-1] == '\t'
9266 checkkwd |= CHKALIAS;
9268 if (sp->string != sp->ap->val) {
9271 sp->ap->flag &= ~ALIASINUSE;
9272 if (sp->ap->flag & ALIASDEAD) {
9273 unalias(sp->ap->name);
9277 g_parsefile->next_to_pgetc = sp->prev_string;
9278 g_parsefile->left_in_line = sp->prev_left_in_line;
9279 g_parsefile->strpush = sp->prev;
9280 if (sp != &(g_parsefile->basestrpush))
9285 //FIXME: BASH_COMPAT with "...&" does TWO pungetc():
9286 //it peeks whether it is &>, and then pushes back both chars.
9287 //This function needs to save last *next_to_pgetc to buf[0]
9288 //to make two pungetc() reliable. Currently,
9289 // pgetc (out of buf: does preadfd), pgetc, pungetc, pungetc won't work...
9294 char *buf = g_parsefile->buf;
9296 g_parsefile->next_to_pgetc = buf;
9297 #if ENABLE_FEATURE_EDITING
9299 if (!iflag || g_parsefile->fd != STDIN_FILENO)
9300 nr = nonblock_safe_read(g_parsefile->fd, buf, BUFSIZ - 1);
9302 #if ENABLE_FEATURE_TAB_COMPLETION
9303 line_input_state->path_lookup = pathval();
9305 nr = read_line_input(cmdedit_prompt, buf, BUFSIZ, line_input_state);
9307 /* Ctrl+C pressed */
9316 if (nr < 0 && errno == 0) {
9317 /* Ctrl+D pressed */
9322 nr = nonblock_safe_read(g_parsefile->fd, buf, BUFSIZ - 1);
9326 /* nonblock_safe_read() handles this problem */
9328 if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
9329 int flags = fcntl(0, F_GETFL);
9330 if (flags >= 0 && (flags & O_NONBLOCK)) {
9331 flags &= ~O_NONBLOCK;
9332 if (fcntl(0, F_SETFL, flags) >= 0) {
9333 out2str("sh: turning off NDELAY mode\n");
9344 * Refill the input buffer and return the next input character:
9346 * 1) If a string was pushed back on the input, pop it;
9347 * 2) If an EOF was pushed back (g_parsefile->left_in_line < -BIGNUM)
9348 * or we are reading from a string so we can't refill the buffer,
9350 * 3) If the is more stuff in this buffer, use it else call read to fill it.
9351 * 4) Process input up to the next newline, deleting nul characters.
9353 //#define pgetc_debug(...) bb_error_msg(__VA_ARGS__)
9354 #define pgetc_debug(...) ((void)0)
9356 * NB: due to SIT(c) internals (syntax_index_table[] vector),
9357 * pgetc() and related functions must return chars SIGN-EXTENDED into ints,
9358 * not zero-extended. Seems fragile to me. Affects only !USE_SIT_FUNCTION case,
9359 * so we can fix it by ditching !USE_SIT_FUNCTION if Unicode requires that.
9367 while (g_parsefile->strpush) {
9368 #if ENABLE_ASH_ALIAS
9369 if (g_parsefile->left_in_line == -1
9370 && g_parsefile->strpush->ap
9371 && g_parsefile->next_to_pgetc[-1] != ' '
9372 && g_parsefile->next_to_pgetc[-1] != '\t'
9374 pgetc_debug("preadbuffer PEOA");
9379 /* try "pgetc" now: */
9380 pgetc_debug("preadbuffer internal pgetc at %d:%p'%s'",
9381 g_parsefile->left_in_line,
9382 g_parsefile->next_to_pgetc,
9383 g_parsefile->next_to_pgetc);
9384 if (--g_parsefile->left_in_line >= 0)
9385 return (unsigned char)(*g_parsefile->next_to_pgetc++);
9387 /* on both branches above g_parsefile->left_in_line < 0.
9388 * "pgetc" needs refilling.
9391 /* -90 is our -BIGNUM. Below we use -99 to mark "EOF on read",
9392 * pungetc() may increment it a few times.
9393 * Assuming it won't increment it to less than -90.
9395 if (g_parsefile->left_in_line < -90 || g_parsefile->buf == NULL) {
9396 pgetc_debug("preadbuffer PEOF1");
9397 /* even in failure keep left_in_line and next_to_pgetc
9398 * in lock step, for correct multi-layer pungetc.
9399 * left_in_line was decremented before preadbuffer(),
9400 * must inc next_to_pgetc: */
9401 g_parsefile->next_to_pgetc++;
9405 more = g_parsefile->left_in_buffer;
9407 flush_stdout_stderr();
9411 /* don't try reading again */
9412 g_parsefile->left_in_line = -99;
9413 pgetc_debug("preadbuffer PEOF2");
9414 g_parsefile->next_to_pgetc++;
9419 /* Find out where's the end of line.
9420 * Set g_parsefile->left_in_line
9421 * and g_parsefile->left_in_buffer acordingly.
9422 * NUL chars are deleted.
9424 q = g_parsefile->next_to_pgetc;
9432 memmove(q, q + 1, more);
9436 g_parsefile->left_in_line = q - g_parsefile->next_to_pgetc - 1;
9442 g_parsefile->left_in_line = q - g_parsefile->next_to_pgetc - 1;
9443 if (g_parsefile->left_in_line < 0)
9448 g_parsefile->left_in_buffer = more;
9453 out2str(g_parsefile->next_to_pgetc);
9457 pgetc_debug("preadbuffer at %d:%p'%s'",
9458 g_parsefile->left_in_line,
9459 g_parsefile->next_to_pgetc,
9460 g_parsefile->next_to_pgetc);
9461 return signed_char2int(*g_parsefile->next_to_pgetc++);
9464 #define pgetc_as_macro() \
9465 (--g_parsefile->left_in_line >= 0 \
9466 ? signed_char2int(*g_parsefile->next_to_pgetc++) \
9473 pgetc_debug("pgetc_fast at %d:%p'%s'",
9474 g_parsefile->left_in_line,
9475 g_parsefile->next_to_pgetc,
9476 g_parsefile->next_to_pgetc);
9477 return pgetc_as_macro();
9480 #if ENABLE_ASH_OPTIMIZE_FOR_SIZE
9481 #define pgetc_fast() pgetc()
9483 #define pgetc_fast() pgetc_as_macro()
9487 * Same as pgetc(), but ignores PEOA.
9489 #if ENABLE_ASH_ALIAS
9495 pgetc_debug("pgetc_fast at %d:%p'%s'",
9496 g_parsefile->left_in_line,
9497 g_parsefile->next_to_pgetc,
9498 g_parsefile->next_to_pgetc);
9500 } while (c == PEOA);
9504 #define pgetc2() pgetc()
9508 * Read a line from the script.
9511 pfgets(char *line, int len)
9517 while (--nleft > 0) {
9533 * Undo the last call to pgetc. Only one character may be pushed back.
9534 * PEOF may be pushed back.
9539 g_parsefile->left_in_line++;
9540 g_parsefile->next_to_pgetc--;
9541 pgetc_debug("pushed back to %d:%p'%s'",
9542 g_parsefile->left_in_line,
9543 g_parsefile->next_to_pgetc,
9544 g_parsefile->next_to_pgetc);
9548 * To handle the "." command, a stack of input files is used. Pushfile
9549 * adds a new entry to the stack and popfile restores the previous level.
9554 struct parsefile *pf;
9556 pf = ckzalloc(sizeof(*pf));
9557 pf->prev = g_parsefile;
9559 /*pf->strpush = NULL; - ckzalloc did it */
9560 /*pf->basestrpush.prev = NULL;*/
9567 struct parsefile *pf = g_parsefile;
9575 g_parsefile = pf->prev;
9581 * Return to top level.
9586 while (g_parsefile != &basepf)
9591 * Close the file(s) that the shell is reading commands from. Called
9592 * after a fork is done.
9598 if (g_parsefile->fd > 0) {
9599 close(g_parsefile->fd);
9600 g_parsefile->fd = 0;
9605 * Like setinputfile, but takes an open file descriptor. Call this with
9609 setinputfd(int fd, int push)
9611 close_on_exec_on(fd);
9614 g_parsefile->buf = NULL;
9616 g_parsefile->fd = fd;
9617 if (g_parsefile->buf == NULL)
9618 g_parsefile->buf = ckmalloc(IBUFSIZ);
9619 g_parsefile->left_in_buffer = 0;
9620 g_parsefile->left_in_line = 0;
9621 g_parsefile->linno = 1;
9625 * Set the input to take input from a file. If push is set, push the
9626 * old input onto the stack first.
9629 setinputfile(const char *fname, int flags)
9635 fd = open(fname, O_RDONLY);
9637 if (flags & INPUT_NOFILE_OK)
9639 ash_msg_and_raise_error("can't open '%s'", fname);
9642 fd2 = copyfd(fd, 10);
9645 ash_msg_and_raise_error("out of file descriptors");
9648 setinputfd(fd, flags & INPUT_PUSH_FILE);
9655 * Like setinputfile, but takes input from a string.
9658 setinputstring(char *string)
9662 g_parsefile->next_to_pgetc = string;
9663 g_parsefile->left_in_line = strlen(string);
9664 g_parsefile->buf = NULL;
9665 g_parsefile->linno = 1;
9670 /* ============ mail.c
9672 * Routines to check for mail.
9677 #define MAXMBOXES 10
9679 /* times of mailboxes */
9680 static time_t mailtime[MAXMBOXES];
9681 /* Set if MAIL or MAILPATH is changed. */
9682 static smallint mail_var_path_changed;
9685 * Print appropriate message(s) if mail has arrived.
9686 * If mail_var_path_changed is set,
9687 * then the value of MAIL has mail_var_path_changed,
9688 * so we just update the values.
9697 struct stackmark smark;
9700 setstackmark(&smark);
9701 mpath = mpathset() ? mpathval() : mailval();
9702 for (mtp = mailtime; mtp < mailtime + MAXMBOXES; mtp++) {
9703 p = padvance(&mpath, nullstr);
9708 for (q = p; *q; q++)
9714 q[-1] = '\0'; /* delete trailing '/' */
9715 if (stat(p, &statb) < 0) {
9719 if (!mail_var_path_changed && statb.st_mtime != *mtp) {
9722 pathopt ? pathopt : "you have mail"
9725 *mtp = statb.st_mtime;
9727 mail_var_path_changed = 0;
9728 popstackmark(&smark);
9732 changemail(const char *val UNUSED_PARAM)
9734 mail_var_path_changed = 1;
9737 #endif /* ASH_MAIL */
9740 /* ============ ??? */
9743 * Set the shell parameters.
9746 setparam(char **argv)
9752 for (nparam = 0; argv[nparam]; nparam++)
9754 ap = newparam = ckmalloc((nparam + 1) * sizeof(*ap));
9756 *ap++ = ckstrdup(*argv++);
9759 freeparam(&shellparam);
9760 shellparam.malloced = 1;
9761 shellparam.nparam = nparam;
9762 shellparam.p = newparam;
9763 #if ENABLE_ASH_GETOPTS
9764 shellparam.optind = 1;
9765 shellparam.optoff = -1;
9770 * Process shell options. The global variable argptr contains a pointer
9771 * to the argument list; we advance it past the options.
9773 * SUSv3 section 2.8.1 "Consequences of Shell Errors" says:
9774 * For a non-interactive shell, an error condition encountered
9775 * by a special built-in ... shall cause the shell to write a diagnostic message
9776 * to standard error and exit as shown in the following table:
9777 * Error Special Built-In
9779 * Utility syntax error (option or operand error) Shall exit
9781 * However, in bug 1142 (http://busybox.net/bugs/view.php?id=1142)
9782 * we see that bash does not do that (set "finishes" with error code 1 instead,
9783 * and shell continues), and people rely on this behavior!
9785 * set -o barfoo 2>/dev/null
9788 * Oh well. Let's mimic that.
9791 plus_minus_o(char *name, int val)
9796 for (i = 0; i < NOPTS; i++) {
9797 if (strcmp(name, optnames(i)) == 0) {
9802 ash_msg("illegal option %co %s", val ? '-' : '+', name);
9805 for (i = 0; i < NOPTS; i++) {
9807 out1fmt("%-16s%s\n", optnames(i), optlist[i] ? "on" : "off");
9809 out1fmt("set %co %s\n", optlist[i] ? '-' : '+', optnames(i));
9815 setoption(int flag, int val)
9819 for (i = 0; i < NOPTS; i++) {
9820 if (optletters(i) == flag) {
9825 ash_msg_and_raise_error("illegal option %c%c", val ? '-' : '+', flag);
9829 options(int cmdline)
9837 while ((p = *argptr) != NULL) {
9839 if (c != '-' && c != '+')
9842 val = 0; /* val = 0 if c == '+' */
9845 if (p[0] == '\0' || LONE_DASH(p)) {
9847 /* "-" means turn off -x and -v */
9850 /* "--" means reset params */
9851 else if (*argptr == NULL)
9854 break; /* "-" or "--" terminates options */
9857 /* first char was + or - */
9858 while ((c = *p++) != '\0') {
9859 /* bash 3.2 indeed handles -c CMD and +c CMD the same */
9860 if (c == 'c' && cmdline) {
9861 minusc = p; /* command is after shell args */
9862 } else if (c == 'o') {
9863 if (plus_minus_o(*argptr, val)) {
9864 /* it already printed err message */
9865 return 1; /* error */
9869 } else if (cmdline && (c == 'l')) { /* -l or +l == --login */
9871 /* bash does not accept +-login, we also won't */
9872 } else if (cmdline && val && (c == '-')) { /* long options */
9873 if (strcmp(p, "login") == 0)
9885 * The shift builtin command.
9888 shiftcmd(int argc UNUSED_PARAM, char **argv)
9895 n = number(argv[1]);
9896 if (n > shellparam.nparam)
9897 n = 0; /* bash compat, was = shellparam.nparam; */
9899 shellparam.nparam -= n;
9900 for (ap1 = shellparam.p; --n >= 0; ap1++) {
9901 if (shellparam.malloced)
9905 while ((*ap2++ = *ap1++) != NULL)
9907 #if ENABLE_ASH_GETOPTS
9908 shellparam.optind = 1;
9909 shellparam.optoff = -1;
9916 * POSIX requires that 'set' (but not export or readonly) output the
9917 * variables in lexicographic order - by the locale's collating order (sigh).
9918 * Maybe we could keep them in an ordered balanced binary tree
9919 * instead of hashed lists.
9920 * For now just roll 'em through qsort for printing...
9923 showvars(const char *sep_prefix, int on, int off)
9928 ep = listvars(on, off, &epend);
9929 qsort(ep, epend - ep, sizeof(char *), vpcmp);
9931 sep = *sep_prefix ? " " : sep_prefix;
9933 for (; ep < epend; ep++) {
9937 p = strchrnul(*ep, '=');
9940 q = single_quote(++p);
9941 out1fmt("%s%s%.*s%s\n", sep_prefix, sep, (int)(p - *ep), *ep, q);
9947 * The set command builtin.
9950 setcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9955 return showvars(nullstr, 0, VUNSET);
9958 if (!options(0)) { /* if no parse error... */
9961 if (*argptr != NULL) {
9969 #if ENABLE_ASH_RANDOM_SUPPORT
9971 change_random(const char *value)
9973 /* Galois LFSR parameter */
9974 /* Taps at 32 31 29 1: */
9975 enum { MASK = 0x8000000b };
9976 /* Another example - taps at 32 31 30 10: */
9977 /* MASK = 0x00400007 */
9979 if (value == NULL) {
9980 /* "get", generate */
9983 /* LCG has period of 2^32 and alternating lowest bit */
9984 random_LCG = 1664525 * random_LCG + 1013904223;
9985 /* Galois LFSR has period of 2^32-1 = 3 * 5 * 17 * 257 * 65537 */
9986 t = (random_galois_LFSR << 1);
9987 if (random_galois_LFSR < 0) /* if we just shifted 1 out of msb... */
9989 random_galois_LFSR = t;
9990 /* Both are weak, combining them gives better randomness
9991 * and ~2^64 period. & 0x7fff is probably bash compat
9992 * for $RANDOM range. Combining with subtraction is
9993 * just for fun. + and ^ would work equally well. */
9994 t = (t - random_LCG) & 0x7fff;
9995 /* set without recursion */
9996 setvar(vrandom.text, utoa(t), VNOFUNC);
9997 vrandom.flags &= ~VNOFUNC;
10000 random_galois_LFSR = random_LCG = strtoul(value, (char **)NULL, 10);
10005 #if ENABLE_ASH_GETOPTS
10007 getopts(char *optstr, char *optvar, char **optfirst, int *param_optind, int *optoff)
10016 if (*param_optind < 1)
10018 optnext = optfirst + *param_optind - 1;
10020 if (*param_optind <= 1 || *optoff < 0 || (int)strlen(optnext[-1]) < *optoff)
10023 p = optnext[-1] + *optoff;
10024 if (p == NULL || *p == '\0') {
10025 /* Current word is done, advance */
10027 if (p == NULL || *p != '-' || *++p == '\0') {
10034 if (LONE_DASH(p)) /* check for "--" */
10039 for (q = optstr; *q != c;) {
10041 if (optstr[0] == ':') {
10044 err |= setvarsafe("OPTARG", s, 0);
10046 fprintf(stderr, "Illegal option -%c\n", c);
10047 unsetvar("OPTARG");
10057 if (*p == '\0' && (p = *optnext) == NULL) {
10058 if (optstr[0] == ':') {
10061 err |= setvarsafe("OPTARG", s, 0);
10064 fprintf(stderr, "No arg for -%c option\n", c);
10065 unsetvar("OPTARG");
10073 err |= setvarsafe("OPTARG", p, 0);
10076 err |= setvarsafe("OPTARG", nullstr, 0);
10078 *optoff = p ? p - *(optnext - 1) : -1;
10079 *param_optind = optnext - optfirst + 1;
10080 fmtstr(s, sizeof(s), "%d", *param_optind);
10081 err |= setvarsafe("OPTIND", s, VNOFUNC);
10084 err |= setvarsafe(optvar, s, 0);
10088 flush_stdout_stderr();
10089 raise_exception(EXERROR);
10095 * The getopts builtin. Shellparam.optnext points to the next argument
10096 * to be processed. Shellparam.optptr points to the next character to
10097 * be processed in the current argument. If shellparam.optnext is NULL,
10098 * then it's the first time getopts has been called.
10101 getoptscmd(int argc, char **argv)
10106 ash_msg_and_raise_error("usage: getopts optstring var [arg]");
10108 optbase = shellparam.p;
10109 if (shellparam.optind > shellparam.nparam + 1) {
10110 shellparam.optind = 1;
10111 shellparam.optoff = -1;
10114 optbase = &argv[3];
10115 if (shellparam.optind > argc - 2) {
10116 shellparam.optind = 1;
10117 shellparam.optoff = -1;
10121 return getopts(argv[1], argv[2], optbase, &shellparam.optind,
10122 &shellparam.optoff);
10124 #endif /* ASH_GETOPTS */
10127 /* ============ Shell parser */
10130 struct heredoc *next; /* next here document in list */
10131 union node *here; /* redirection node */
10132 char *eofmark; /* string indicating end of input */
10133 smallint striptabs; /* if set, strip leading tabs */
10136 static smallint tokpushback; /* last token pushed back */
10137 static smallint parsebackquote; /* nonzero if we are inside backquotes */
10138 static smallint quoteflag; /* set if (part of) last token was quoted */
10139 static token_id_t lasttoken; /* last token read (integer id Txxx) */
10140 static struct heredoc *heredoclist; /* list of here documents to read */
10141 static char *wordtext; /* text of last word returned by readtoken */
10142 static struct nodelist *backquotelist;
10143 static union node *redirnode;
10144 static struct heredoc *heredoc;
10146 * NEOF is returned by parsecmd when it encounters an end of file. It
10147 * must be distinct from NULL, so we use the address of a variable that
10148 * happens to be handy.
10150 #define NEOF ((union node *)&tokpushback)
10152 static void raise_error_syntax(const char *) NORETURN;
10154 raise_error_syntax(const char *msg)
10156 ash_msg_and_raise_error("syntax error: %s", msg);
10161 * Called when an unexpected token is read during the parse. The argument
10162 * is the token that is expected, or -1 if more than one type of token can
10163 * occur at this point.
10165 static void raise_error_unexpected_syntax(int) NORETURN;
10167 raise_error_unexpected_syntax(int token)
10172 l = sprintf(msg, "unexpected %s", tokname(lasttoken));
10174 sprintf(msg + l, " (expecting %s)", tokname(token));
10175 raise_error_syntax(msg);
10179 #define EOFMARKLEN 79
10181 /* parsing is heavily cross-recursive, need these forward decls */
10182 static union node *andor(void);
10183 static union node *pipeline(void);
10184 static union node *parse_command(void);
10185 static void parseheredoc(void);
10186 static char peektoken(void);
10187 static int readtoken(void);
10189 static union node *
10192 union node *n1, *n2, *n3;
10195 checkkwd = CHKNL | CHKKWD | CHKALIAS;
10196 if (nlflag == 2 && peektoken())
10202 if (tok == TBACKGND) {
10203 if (n2->type == NPIPE) {
10204 n2->npipe.pipe_backgnd = 1;
10206 if (n2->type != NREDIR) {
10207 n3 = stzalloc(sizeof(struct nredir));
10209 /*n3->nredir.redirect = NULL; - stzalloc did it */
10212 n2->type = NBACKGND;
10218 n3 = stzalloc(sizeof(struct nbinary));
10220 n3->nbinary.ch1 = n1;
10221 n3->nbinary.ch2 = n2;
10237 checkkwd = CHKNL | CHKKWD | CHKALIAS;
10245 pungetc(); /* push back EOF on input */
10249 raise_error_unexpected_syntax(-1);
10256 static union node *
10259 union node *n1, *n2, *n3;
10267 } else if (t == TOR) {
10273 checkkwd = CHKNL | CHKKWD | CHKALIAS;
10275 n3 = stzalloc(sizeof(struct nbinary));
10277 n3->nbinary.ch1 = n1;
10278 n3->nbinary.ch2 = n2;
10283 static union node *
10286 union node *n1, *n2, *pipenode;
10287 struct nodelist *lp, *prev;
10291 TRACE(("pipeline: entered\n"));
10292 if (readtoken() == TNOT) {
10294 checkkwd = CHKKWD | CHKALIAS;
10297 n1 = parse_command();
10298 if (readtoken() == TPIPE) {
10299 pipenode = stzalloc(sizeof(struct npipe));
10300 pipenode->type = NPIPE;
10301 /*pipenode->npipe.pipe_backgnd = 0; - stzalloc did it */
10302 lp = stzalloc(sizeof(struct nodelist));
10303 pipenode->npipe.cmdlist = lp;
10307 lp = stzalloc(sizeof(struct nodelist));
10308 checkkwd = CHKNL | CHKKWD | CHKALIAS;
10309 lp->n = parse_command();
10311 } while (readtoken() == TPIPE);
10317 n2 = stzalloc(sizeof(struct nnot));
10325 static union node *
10330 n = stzalloc(sizeof(struct narg));
10332 /*n->narg.next = NULL; - stzalloc did it */
10333 n->narg.text = wordtext;
10334 n->narg.backquote = backquotelist;
10339 fixredir(union node *n, const char *text, int err)
10343 TRACE(("Fix redir %s %d\n", text, err));
10345 n->ndup.vname = NULL;
10347 fd = bb_strtou(text, NULL, 10);
10348 if (!errno && fd >= 0)
10349 n->ndup.dupfd = fd;
10350 else if (LONE_DASH(text))
10351 n->ndup.dupfd = -1;
10354 raise_error_syntax("bad fd number");
10355 n->ndup.vname = makename();
10360 * Returns true if the text contains nothing to expand (no dollar signs
10364 noexpand(const char *text)
10370 while ((c = *p++) != '\0') {
10371 if (c == CTLQUOTEMARK)
10375 else if (SIT((signed char)c, BASESYNTAX) == CCTL)
10384 union node *n = redirnode;
10386 if (readtoken() != TWORD)
10387 raise_error_unexpected_syntax(-1);
10388 if (n->type == NHERE) {
10389 struct heredoc *here = heredoc;
10393 if (quoteflag == 0)
10395 TRACE(("Here document %d\n", n->type));
10396 if (!noexpand(wordtext) || (i = strlen(wordtext)) == 0 || i > EOFMARKLEN)
10397 raise_error_syntax("illegal eof marker for << redirection");
10398 rmescapes(wordtext);
10399 here->eofmark = wordtext;
10401 if (heredoclist == NULL)
10402 heredoclist = here;
10404 for (p = heredoclist; p->next; p = p->next)
10408 } else if (n->type == NTOFD || n->type == NFROMFD) {
10409 fixredir(n, wordtext, 0);
10411 n->nfile.fname = makename();
10415 static union node *
10418 union node *args, **app;
10419 union node *n = NULL;
10420 union node *vars, **vpp;
10421 union node **rpp, *redir;
10423 #if ENABLE_ASH_BASH_COMPAT
10424 smallint double_brackets_flag = 0;
10434 savecheckkwd = CHKALIAS;
10437 checkkwd = savecheckkwd;
10440 #if ENABLE_ASH_BASH_COMPAT
10441 case TAND: /* "&&" */
10442 case TOR: /* "||" */
10443 if (!double_brackets_flag) {
10447 wordtext = (char *) (t == TAND ? "-a" : "-o");
10450 n = stzalloc(sizeof(struct narg));
10452 /*n->narg.next = NULL; - stzalloc did it */
10453 n->narg.text = wordtext;
10454 #if ENABLE_ASH_BASH_COMPAT
10455 if (strcmp("[[", wordtext) == 0)
10456 double_brackets_flag = 1;
10457 else if (strcmp("]]", wordtext) == 0)
10458 double_brackets_flag = 0;
10460 n->narg.backquote = backquotelist;
10461 if (savecheckkwd && isassignment(wordtext)) {
10463 vpp = &n->narg.next;
10466 app = &n->narg.next;
10471 *rpp = n = redirnode;
10472 rpp = &n->nfile.next;
10473 parsefname(); /* read name of redirection file */
10476 if (args && app == &args->narg.next
10479 struct builtincmd *bcmd;
10482 /* We have a function */
10483 if (readtoken() != TRP)
10484 raise_error_unexpected_syntax(TRP);
10485 name = n->narg.text;
10486 if (!goodname(name)
10487 || ((bcmd = find_builtin(name)) && IS_BUILTIN_SPECIAL(bcmd))
10489 raise_error_syntax("bad function name");
10492 checkkwd = CHKNL | CHKKWD | CHKALIAS;
10493 n->narg.next = parse_command();
10506 n = stzalloc(sizeof(struct ncmd));
10508 n->ncmd.args = args;
10509 n->ncmd.assign = vars;
10510 n->ncmd.redirect = redir;
10514 static union node *
10515 parse_command(void)
10517 union node *n1, *n2;
10518 union node *ap, **app;
10519 union node *cp, **cpp;
10520 union node *redir, **rpp;
10527 switch (readtoken()) {
10529 raise_error_unexpected_syntax(-1);
10532 n1 = stzalloc(sizeof(struct nif));
10534 n1->nif.test = list(0);
10535 if (readtoken() != TTHEN)
10536 raise_error_unexpected_syntax(TTHEN);
10537 n1->nif.ifpart = list(0);
10539 while (readtoken() == TELIF) {
10540 n2->nif.elsepart = stzalloc(sizeof(struct nif));
10541 n2 = n2->nif.elsepart;
10543 n2->nif.test = list(0);
10544 if (readtoken() != TTHEN)
10545 raise_error_unexpected_syntax(TTHEN);
10546 n2->nif.ifpart = list(0);
10548 if (lasttoken == TELSE)
10549 n2->nif.elsepart = list(0);
10551 n2->nif.elsepart = NULL;
10559 n1 = stzalloc(sizeof(struct nbinary));
10560 n1->type = (lasttoken == TWHILE) ? NWHILE : NUNTIL;
10561 n1->nbinary.ch1 = list(0);
10564 TRACE(("expecting DO got %s %s\n", tokname(got),
10565 got == TWORD ? wordtext : ""));
10566 raise_error_unexpected_syntax(TDO);
10568 n1->nbinary.ch2 = list(0);
10573 if (readtoken() != TWORD || quoteflag || !goodname(wordtext))
10574 raise_error_syntax("bad for loop variable");
10575 n1 = stzalloc(sizeof(struct nfor));
10577 n1->nfor.var = wordtext;
10578 checkkwd = CHKKWD | CHKALIAS;
10579 if (readtoken() == TIN) {
10581 while (readtoken() == TWORD) {
10582 n2 = stzalloc(sizeof(struct narg));
10584 /*n2->narg.next = NULL; - stzalloc did it */
10585 n2->narg.text = wordtext;
10586 n2->narg.backquote = backquotelist;
10588 app = &n2->narg.next;
10591 n1->nfor.args = ap;
10592 if (lasttoken != TNL && lasttoken != TSEMI)
10593 raise_error_unexpected_syntax(-1);
10595 n2 = stzalloc(sizeof(struct narg));
10597 /*n2->narg.next = NULL; - stzalloc did it */
10598 n2->narg.text = (char *)dolatstr;
10599 /*n2->narg.backquote = NULL;*/
10600 n1->nfor.args = n2;
10602 * Newline or semicolon here is optional (but note
10603 * that the original Bourne shell only allowed NL).
10605 if (lasttoken != TNL && lasttoken != TSEMI)
10608 checkkwd = CHKNL | CHKKWD | CHKALIAS;
10609 if (readtoken() != TDO)
10610 raise_error_unexpected_syntax(TDO);
10611 n1->nfor.body = list(0);
10615 n1 = stzalloc(sizeof(struct ncase));
10617 if (readtoken() != TWORD)
10618 raise_error_unexpected_syntax(TWORD);
10619 n1->ncase.expr = n2 = stzalloc(sizeof(struct narg));
10621 /*n2->narg.next = NULL; - stzalloc did it */
10622 n2->narg.text = wordtext;
10623 n2->narg.backquote = backquotelist;
10625 checkkwd = CHKKWD | CHKALIAS;
10626 } while (readtoken() == TNL);
10627 if (lasttoken != TIN)
10628 raise_error_unexpected_syntax(TIN);
10629 cpp = &n1->ncase.cases;
10631 checkkwd = CHKNL | CHKKWD;
10633 while (t != TESAC) {
10634 if (lasttoken == TLP)
10636 *cpp = cp = stzalloc(sizeof(struct nclist));
10638 app = &cp->nclist.pattern;
10640 *app = ap = stzalloc(sizeof(struct narg));
10642 /*ap->narg.next = NULL; - stzalloc did it */
10643 ap->narg.text = wordtext;
10644 ap->narg.backquote = backquotelist;
10645 if (readtoken() != TPIPE)
10647 app = &ap->narg.next;
10650 //ap->narg.next = NULL;
10651 if (lasttoken != TRP)
10652 raise_error_unexpected_syntax(TRP);
10653 cp->nclist.body = list(2);
10655 cpp = &cp->nclist.next;
10657 checkkwd = CHKNL | CHKKWD;
10661 raise_error_unexpected_syntax(TENDCASE);
10668 n1 = stzalloc(sizeof(struct nredir));
10669 n1->type = NSUBSHELL;
10670 n1->nredir.n = list(0);
10671 /*n1->nredir.redirect = NULL; - stzalloc did it */
10681 return simplecmd();
10684 if (readtoken() != t)
10685 raise_error_unexpected_syntax(t);
10688 /* Now check for redirection which may follow command */
10689 checkkwd = CHKKWD | CHKALIAS;
10691 while (readtoken() == TREDIR) {
10692 *rpp = n2 = redirnode;
10693 rpp = &n2->nfile.next;
10699 if (n1->type != NSUBSHELL) {
10700 n2 = stzalloc(sizeof(struct nredir));
10705 n1->nredir.redirect = redir;
10710 #if ENABLE_ASH_BASH_COMPAT
10711 static int decode_dollar_squote(void)
10713 static const char C_escapes[] ALIGN1 = "nrbtfav""x\\01234567";
10719 p = strchr(C_escapes, c);
10724 if ((unsigned char)(c - '0') <= 7) { /* \ooo */
10728 } while ((unsigned char)(c - '0') <= 7 && --cnt);
10730 } else if (c == 'x') { /* \xHH */
10734 } while (isxdigit(c) && --cnt);
10736 if (cnt == 3) { /* \x but next char is "bad" */
10740 } else { /* simple seq like \\ or \t */
10745 c = bb_process_escape_sequence((void*)&p);
10746 } else { /* unrecognized "\z": print both chars unless ' or " */
10747 if (c != '\'' && c != '"') {
10749 c |= 0x100; /* "please encode \, then me" */
10757 * If eofmark is NULL, read a word or a redirection symbol. If eofmark
10758 * is not NULL, read a here document. In the latter case, eofmark is the
10759 * word which marks the end of the document and striptabs is true if
10760 * leading tabs should be stripped from the document. The argument firstc
10761 * is the first character of the input token or document.
10763 * Because C does not have internal subroutines, I have simulated them
10764 * using goto's to implement the subroutine linkage. The following macros
10765 * will run code that appears at the end of readtoken1.
10767 #define CHECKEND() {goto checkend; checkend_return:;}
10768 #define PARSEREDIR() {goto parseredir; parseredir_return:;}
10769 #define PARSESUB() {goto parsesub; parsesub_return:;}
10770 #define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
10771 #define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
10772 #define PARSEARITH() {goto parsearith; parsearith_return:;}
10774 readtoken1(int firstc, int syntax, char *eofmark, int striptabs)
10776 /* NB: syntax parameter fits into smallint */
10780 char line[EOFMARKLEN + 1];
10781 struct nodelist *bqlist;
10785 smallint prevsyntax; /* syntax before arithmetic */
10786 #if ENABLE_ASH_EXPAND_PRMT
10787 smallint pssyntax; /* we are expanding a prompt string */
10789 int varnest; /* levels of variables expansion */
10790 int arinest; /* levels of arithmetic expansion */
10791 int parenlevel; /* levels of parens in arithmetic */
10792 int dqvarnest; /* levels of variables expansion within double quotes */
10794 USE_ASH_BASH_COMPAT(smallint bash_dollar_squote = 0;)
10797 /* Avoid longjmp clobbering */
10803 (void) &parenlevel;
10806 (void) &prevsyntax;
10809 startlinno = g_parsefile->linno;
10814 #if ENABLE_ASH_EXPAND_PRMT
10815 pssyntax = (syntax == PSSYNTAX);
10819 dblquote = (syntax == DQSYNTAX);
10825 STARTSTACKSTR(out);
10827 /* For each line, until end of word */
10829 CHECKEND(); /* set c to PEOF if at end of here document */
10830 for (;;) { /* until end of line or end of word */
10831 CHECKSTRSPACE(4, out); /* permit 4 calls to USTPUTC */
10832 switch (SIT(c, syntax)) {
10833 case CNL: /* '\n' */
10834 if (syntax == BASESYNTAX)
10835 goto endword; /* exit outer loop */
10837 g_parsefile->linno++;
10841 goto loop; /* continue outer loop */
10846 if (eofmark == NULL || dblquote)
10847 USTPUTC(CTLESC, out);
10848 #if ENABLE_ASH_BASH_COMPAT
10849 if (c == '\\' && bash_dollar_squote) {
10850 c = decode_dollar_squote();
10852 USTPUTC('\\', out);
10853 c = (unsigned char)c;
10859 case CBACK: /* backslash */
10862 USTPUTC(CTLESC, out);
10863 USTPUTC('\\', out);
10865 } else if (c == '\n') {
10869 #if ENABLE_ASH_EXPAND_PRMT
10870 if (c == '$' && pssyntax) {
10871 USTPUTC(CTLESC, out);
10872 USTPUTC('\\', out);
10875 if (dblquote && c != '\\'
10876 && c != '`' && c != '$'
10877 && (c != '"' || eofmark != NULL)
10879 USTPUTC(CTLESC, out);
10880 USTPUTC('\\', out);
10882 if (SIT(c, SQSYNTAX) == CCTL)
10883 USTPUTC(CTLESC, out);
10891 if (eofmark == NULL) {
10892 USTPUTC(CTLQUOTEMARK, out);
10900 USE_ASH_BASH_COMPAT(bash_dollar_squote = 0;)
10901 if (eofmark != NULL && arinest == 0
10906 if (dqvarnest == 0) {
10907 syntax = BASESYNTAX;
10914 case CVAR: /* '$' */
10915 PARSESUB(); /* parse substitution */
10917 case CENDVAR: /* '}' */
10920 if (dqvarnest > 0) {
10923 USTPUTC(CTLENDVAR, out);
10928 #if ENABLE_ASH_MATH_SUPPORT
10929 case CLP: /* '(' in arithmetic */
10933 case CRP: /* ')' in arithmetic */
10934 if (parenlevel > 0) {
10938 if (pgetc() == ')') {
10939 if (--arinest == 0) {
10940 USTPUTC(CTLENDARI, out);
10941 syntax = prevsyntax;
10942 dblquote = (syntax == DQSYNTAX);
10947 * unbalanced parens
10948 * (don't 2nd guess - no error)
10956 case CBQUOTE: /* '`' */
10960 goto endword; /* exit outer loop */
10964 if (varnest == 0) {
10965 #if ENABLE_ASH_BASH_COMPAT
10967 if (pgetc() == '>')
10968 c = 0x100 + '>'; /* flag &> */
10972 goto endword; /* exit outer loop */
10974 #if ENABLE_ASH_ALIAS
10984 #if ENABLE_ASH_MATH_SUPPORT
10985 if (syntax == ARISYNTAX)
10986 raise_error_syntax("missing '))'");
10988 if (syntax != BASESYNTAX && !parsebackquote && eofmark == NULL)
10989 raise_error_syntax("unterminated quoted string");
10990 if (varnest != 0) {
10991 startlinno = g_parsefile->linno;
10993 raise_error_syntax("missing '}'");
10995 USTPUTC('\0', out);
10996 len = out - (char *)stackblock();
10997 out = stackblock();
10998 if (eofmark == NULL) {
10999 if ((c == '>' || c == '<' USE_ASH_BASH_COMPAT( || c == 0x100 + '>'))
11002 if (isdigit_str9(out)) {
11003 PARSEREDIR(); /* passed as params: out, c */
11004 lasttoken = TREDIR;
11007 /* else: non-number X seen, interpret it
11008 * as "NNNX>file" = "NNNX >file" */
11012 quoteflag = quotef;
11013 backquotelist = bqlist;
11014 grabstackblock(len);
11018 /* end of readtoken routine */
11021 * Check to see whether we are at the end of the here document. When this
11022 * is called, c is set to the first character of the next input line. If
11023 * we are at the end of the here document, this routine sets the c to PEOF.
11027 #if ENABLE_ASH_ALIAS
11033 while (c == '\t') {
11037 if (c == *eofmark) {
11038 if (pfgets(line, sizeof(line)) != NULL) {
11042 for (q = eofmark + 1; *q && *p == *q; p++, q++)
11044 if (*p == '\n' && *q == '\0') {
11046 g_parsefile->linno++;
11047 needprompt = doprompt;
11049 pushstring(line, NULL);
11054 goto checkend_return;
11058 * Parse a redirection operator. The variable "out" points to a string
11059 * specifying the fd to be redirected. The variable "c" contains the
11060 * first character of the redirection operator.
11063 /* out is already checked to be a valid number or "" */
11064 int fd = (*out == '\0' ? -1 : atoi(out));
11067 np = stzalloc(sizeof(struct nfile));
11072 np->type = NAPPEND;
11074 np->type = NCLOBBER;
11077 /* it also can be NTO2 (>&file), but we can't figure it out yet */
11083 #if ENABLE_ASH_BASH_COMPAT
11084 else if (c == 0x100 + '>') { /* this flags &> redirection */
11086 pgetc(); /* this is '>', no need to check */
11090 else { /* c == '<' */
11091 /*np->nfile.fd = 0; - stzalloc did it */
11095 if (sizeof(struct nfile) != sizeof(struct nhere)) {
11096 np = stzalloc(sizeof(struct nhere));
11097 /*np->nfile.fd = 0; - stzalloc did it */
11100 heredoc = stzalloc(sizeof(struct heredoc));
11101 heredoc->here = np;
11104 heredoc->striptabs = 1;
11106 /*heredoc->striptabs = 0; - stzalloc did it */
11112 np->type = NFROMFD;
11116 np->type = NFROMTO;
11128 goto parseredir_return;
11132 * Parse a substitution. At this point, we have read the dollar sign
11133 * and nothing else.
11136 /* is_special(c) evaluates to 1 for c in "!#$*-0123456789?@"; 0 otherwise
11137 * (assuming ascii char codes, as the original implementation did) */
11138 #define is_special(c) \
11139 (((unsigned)(c) - 33 < 32) \
11140 && ((0xc1ff920dU >> ((unsigned)(c) - 33)) & 1))
11146 static const char types[] ALIGN1 = "}-+?=";
11149 if (c <= PEOA_OR_PEOF
11150 || (c != '(' && c != '{' && !is_name(c) && !is_special(c))
11152 #if ENABLE_ASH_BASH_COMPAT
11154 bash_dollar_squote = 1;
11159 } else if (c == '(') { /* $(command) or $((arith)) */
11160 if (pgetc() == '(') {
11161 #if ENABLE_ASH_MATH_SUPPORT
11164 raise_error_syntax("you disabled math support for $((arith)) syntax");
11171 USTPUTC(CTLVAR, out);
11172 typeloc = out - (char *)stackblock();
11173 USTPUTC(VSNORMAL, out);
11174 subtype = VSNORMAL;
11182 subtype = VSLENGTH;
11186 if (c > PEOA_OR_PEOF && is_name(c)) {
11190 } while (c > PEOA_OR_PEOF && is_in_name(c));
11191 } else if (isdigit(c)) {
11195 } while (isdigit(c));
11196 } else if (is_special(c)) {
11201 raise_error_syntax("bad substitution");
11206 if (subtype == 0) {
11210 #if ENABLE_ASH_BASH_COMPAT
11211 if (c == ':' || c == '$' || isdigit(c)) {
11213 subtype = VSSUBSTR;
11220 p = strchr(types, c);
11223 subtype = p - types + VSNORMAL;
11228 subtype = c == '#' ? VSTRIMLEFT : VSTRIMRIGHT;
11236 #if ENABLE_ASH_BASH_COMPAT
11238 subtype = VSREPLACE;
11241 subtype++; /* VSREPLACEALL */
11250 if (dblquote || arinest)
11252 *((char *)stackblock() + typeloc) = subtype | flags;
11253 if (subtype != VSNORMAL) {
11255 if (dblquote || arinest) {
11260 goto parsesub_return;
11264 * Called to parse command substitutions. Newstyle is set if the command
11265 * is enclosed inside $(...); nlpp is a pointer to the head of the linked
11266 * list of commands (passed by reference), and savelen is the number of
11267 * characters on the top of the stack which must be preserved.
11270 struct nodelist **nlpp;
11273 char *volatile str;
11274 struct jmploc jmploc;
11275 struct jmploc *volatile savehandler;
11277 smallint saveprompt = 0;
11280 (void) &saveprompt;
11282 savepbq = parsebackquote;
11283 if (setjmp(jmploc.loc)) {
11285 parsebackquote = 0;
11286 exception_handler = savehandler;
11287 longjmp(exception_handler->loc, 1);
11291 savelen = out - (char *)stackblock();
11293 str = ckmalloc(savelen);
11294 memcpy(str, stackblock(), savelen);
11296 savehandler = exception_handler;
11297 exception_handler = &jmploc;
11300 /* We must read until the closing backquote, giving special
11301 treatment to some slashes, and then push the string and
11302 reread it as input, interpreting it normally. */
11309 STARTSTACKSTR(pout);
11322 g_parsefile->linno++;
11326 * If eating a newline, avoid putting
11327 * the newline into the new character
11328 * stream (via the STPUTC after the
11333 if (pc != '\\' && pc != '`' && pc != '$'
11334 && (!dblquote || pc != '"'))
11335 STPUTC('\\', pout);
11336 if (pc > PEOA_OR_PEOF) {
11342 #if ENABLE_ASH_ALIAS
11345 startlinno = g_parsefile->linno;
11346 raise_error_syntax("EOF in backquote substitution");
11349 g_parsefile->linno++;
11350 needprompt = doprompt;
11359 STPUTC('\0', pout);
11360 psavelen = pout - (char *)stackblock();
11361 if (psavelen > 0) {
11362 pstr = grabstackstr(pout);
11363 setinputstring(pstr);
11368 nlpp = &(*nlpp)->next;
11369 *nlpp = stzalloc(sizeof(**nlpp));
11370 /* (*nlpp)->next = NULL; - stzalloc did it */
11371 parsebackquote = oldstyle;
11374 saveprompt = doprompt;
11381 doprompt = saveprompt;
11382 else if (readtoken() != TRP)
11383 raise_error_unexpected_syntax(TRP);
11388 * Start reading from old file again, ignoring any pushed back
11389 * tokens left from the backquote parsing
11394 while (stackblocksize() <= savelen)
11396 STARTSTACKSTR(out);
11398 memcpy(out, str, savelen);
11399 STADJUST(savelen, out);
11405 parsebackquote = savepbq;
11406 exception_handler = savehandler;
11407 if (arinest || dblquote)
11408 USTPUTC(CTLBACKQ | CTLQUOTE, out);
11410 USTPUTC(CTLBACKQ, out);
11412 goto parsebackq_oldreturn;
11413 goto parsebackq_newreturn;
11416 #if ENABLE_ASH_MATH_SUPPORT
11418 * Parse an arithmetic expansion (indicate start of one and set state)
11421 if (++arinest == 1) {
11422 prevsyntax = syntax;
11423 syntax = ARISYNTAX;
11424 USTPUTC(CTLARI, out);
11431 * we collapse embedded arithmetic expansion to
11432 * parenthesis, which should be equivalent
11436 goto parsearith_return;
11440 } /* end of readtoken */
11443 * Read the next input token.
11444 * If the token is a word, we set backquotelist to the list of cmds in
11445 * backquotes. We set quoteflag to true if any part of the word was
11447 * If the token is TREDIR, then we set redirnode to a structure containing
11449 * In all cases, the variable startlinno is set to the number of the line
11450 * on which the token starts.
11452 * [Change comment: here documents and internal procedures]
11453 * [Readtoken shouldn't have any arguments. Perhaps we should make the
11454 * word parsing code into a separate routine. In this case, readtoken
11455 * doesn't need to have any internal procedures, but parseword does.
11456 * We could also make parseoperator in essence the main routine, and
11457 * have parseword (readtoken1?) handle both words and redirection.]
11459 #define NEW_xxreadtoken
11460 #ifdef NEW_xxreadtoken
11461 /* singles must be first! */
11462 static const char xxreadtoken_chars[7] ALIGN1 = {
11463 '\n', '(', ')', /* singles */
11464 '&', '|', ';', /* doubles */
11468 #define xxreadtoken_singles 3
11469 #define xxreadtoken_doubles 3
11471 static const char xxreadtoken_tokens[] ALIGN1 = {
11472 TNL, TLP, TRP, /* only single occurrence allowed */
11473 TBACKGND, TPIPE, TSEMI, /* if single occurrence */
11474 TEOF, /* corresponds to trailing nul */
11475 TAND, TOR, TENDCASE /* if double occurrence */
11490 startlinno = g_parsefile->linno;
11491 for (;;) { /* until token or start of word found */
11493 if (c == ' ' || c == '\t' USE_ASH_ALIAS( || c == PEOA))
11497 while ((c = pgetc()) != '\n' && c != PEOF)
11500 } else if (c == '\\') {
11501 if (pgetc() != '\n') {
11503 break; /* return readtoken1(...) */
11505 startlinno = ++g_parsefile->linno;
11511 p = xxreadtoken_chars + sizeof(xxreadtoken_chars) - 1;
11514 g_parsefile->linno++;
11515 needprompt = doprompt;
11518 p = strchr(xxreadtoken_chars, c);
11520 break; /* return readtoken1(...) */
11522 if ((int)(p - xxreadtoken_chars) >= xxreadtoken_singles) {
11524 if (cc == c) { /* double occurrence? */
11525 p += xxreadtoken_doubles + 1;
11528 #if ENABLE_ASH_BASH_COMPAT
11529 if (c == '&' && cc == '>') /* &> */
11530 break; /* return readtoken1(...) */
11535 lasttoken = xxreadtoken_tokens[p - xxreadtoken_chars];
11540 return readtoken1(c, BASESYNTAX, (char *) NULL, 0);
11542 #else /* old xxreadtoken */
11543 #define RETURN(token) return lasttoken = token
11556 startlinno = g_parsefile->linno;
11557 for (;;) { /* until token or start of word found */
11560 case ' ': case '\t':
11561 #if ENABLE_ASH_ALIAS
11566 while ((c = pgetc()) != '\n' && c != PEOF)
11571 if (pgetc() == '\n') {
11572 startlinno = ++g_parsefile->linno;
11580 g_parsefile->linno++;
11581 needprompt = doprompt;
11586 if (pgetc() == '&')
11591 if (pgetc() == '|')
11596 if (pgetc() == ';')
11609 return readtoken1(c, BASESYNTAX, (char *)NULL, 0);
11612 #endif /* old xxreadtoken */
11619 smallint alreadyseen = tokpushback;
11622 #if ENABLE_ASH_ALIAS
11631 if (checkkwd & CHKNL) {
11638 if (t != TWORD || quoteflag) {
11643 * check for keywords
11645 if (checkkwd & CHKKWD) {
11646 const char *const *pp;
11648 pp = findkwd(wordtext);
11650 lasttoken = t = pp - tokname_array;
11651 TRACE(("keyword %s recognized\n", tokname(t)));
11656 if (checkkwd & CHKALIAS) {
11657 #if ENABLE_ASH_ALIAS
11659 ap = lookupalias(wordtext, 1);
11662 pushstring(ap->val, ap);
11672 TRACE(("token %s %s\n", tokname(t), t == TWORD ? wordtext : ""));
11674 TRACE(("reread token %s %s\n", tokname(t), t == TWORD ? wordtext : ""));
11686 return tokname_array[t][0];
11690 * Read and parse a command. Returns NEOF on end of file. (NULL is a
11691 * valid parse tree indicating a blank line.)
11693 static union node *
11694 parsecmd(int interact)
11699 doprompt = interact;
11701 setprompt(doprompt);
11713 * Input any here documents.
11718 struct heredoc *here;
11721 here = heredoclist;
11722 heredoclist = NULL;
11728 readtoken1(pgetc(), here->here->type == NHERE? SQSYNTAX : DQSYNTAX,
11729 here->eofmark, here->striptabs);
11730 n = stzalloc(sizeof(struct narg));
11731 n->narg.type = NARG;
11732 /*n->narg.next = NULL; - stzalloc did it */
11733 n->narg.text = wordtext;
11734 n->narg.backquote = backquotelist;
11735 here->here->nhere.doc = n;
11742 * called by editline -- any expansions to the prompt should be added here.
11744 #if ENABLE_ASH_EXPAND_PRMT
11745 static const char *
11746 expandstr(const char *ps)
11750 /* XXX Fix (char *) cast. It _is_ a bug. ps is variable's value,
11751 * and token processing _can_ alter it (delete NULs etc). */
11752 setinputstring((char *)ps);
11753 readtoken1(pgetc(), PSSYNTAX, nullstr, 0);
11756 n.narg.type = NARG;
11757 n.narg.next = NULL;
11758 n.narg.text = wordtext;
11759 n.narg.backquote = backquotelist;
11761 expandarg(&n, NULL, 0);
11762 return stackblock();
11767 * Execute a command or commands contained in a string.
11770 evalstring(char *s, int mask)
11773 struct stackmark smark;
11777 setstackmark(&smark);
11780 while ((n = parsecmd(0)) != NEOF) {
11782 popstackmark(&smark);
11795 * The eval command.
11798 evalcmd(int argc UNUSED_PARAM, char **argv)
11807 STARTSTACKSTR(concat);
11809 concat = stack_putstr(p, concat);
11813 STPUTC(' ', concat);
11815 STPUTC('\0', concat);
11816 p = grabstackstr(concat);
11818 evalstring(p, ~SKIPEVAL);
11825 * Read and execute commands. "Top" is nonzero for the top level command
11826 * loop; it turns on prompting if the shell is interactive.
11832 struct stackmark smark;
11836 TRACE(("cmdloop(%d) called\n", top));
11840 setstackmark(&smark);
11843 showjobs(stderr, SHOW_CHANGED);
11846 if (iflag && top) {
11848 #if ENABLE_ASH_MAIL
11852 n = parsecmd(inter);
11853 /* showtree(n); DEBUG */
11855 if (!top || numeof >= 50)
11857 if (!stoppedjobs()) {
11860 out2str("\nUse \"exit\" to leave shell.\n");
11863 } else if (nflag == 0) {
11864 /* job_warning can only be 2,1,0. Here 2->1, 1/0->0 */
11869 popstackmark(&smark);
11874 return skip & SKIPEVAL;
11881 * Take commands from a file. To be compatible we should do a path
11882 * search for the file, which is necessary to find sub-commands.
11885 find_dot_file(char *name)
11888 const char *path = pathval();
11891 /* don't try this for absolute or relative paths */
11892 if (strchr(name, '/'))
11895 /* IIRC standards do not say whether . is to be searched.
11896 * And it is even smaller this way, making it unconditional for now:
11898 if (1) { /* ENABLE_ASH_BASH_COMPAT */
11903 while ((fullname = padvance(&path, name)) != NULL) {
11905 if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) {
11907 * Don't bother freeing here, since it will
11908 * be freed by the caller.
11912 stunalloc(fullname);
11915 /* not found in the PATH */
11916 ash_msg_and_raise_error("%s: not found", name);
11921 dotcmd(int argc, char **argv)
11923 struct strlist *sp;
11924 volatile struct shparam saveparam;
11927 for (sp = cmdenviron; sp; sp = sp->next)
11928 setvareq(ckstrdup(sp->text), VSTRFIXED | VTEXTFIXED);
11930 if (argv[1]) { /* That's what SVR2 does */
11931 char *fullname = find_dot_file(argv[1]);
11934 if (argc) { /* argc > 0, argv[0] != NULL */
11935 saveparam = shellparam;
11936 shellparam.malloced = 0;
11937 shellparam.nparam = argc;
11938 shellparam.p = argv;
11941 setinputfile(fullname, INPUT_PUSH_FILE);
11942 commandname = fullname;
11947 freeparam(&shellparam);
11948 shellparam = saveparam;
11950 status = exitstatus;
11956 exitcmd(int argc UNUSED_PARAM, char **argv)
11961 exitstatus = number(argv[1]);
11962 raise_exception(EXEXIT);
11967 * Read a file containing shell functions.
11970 readcmdfile(char *name)
11972 setinputfile(name, INPUT_PUSH_FILE);
11978 /* ============ find_command inplementation */
11981 * Resolve a command name. If you change this routine, you may have to
11982 * change the shellexec routine as well.
11985 find_command(char *name, struct cmdentry *entry, int act, const char *path)
11987 struct tblentry *cmdp;
11994 struct builtincmd *bcmd;
11996 /* If name contains a slash, don't use PATH or hash table */
11997 if (strchr(name, '/') != NULL) {
11998 entry->u.index = -1;
11999 if (act & DO_ABS) {
12000 while (stat(name, &statb) < 0) {
12002 if (errno == EINTR)
12005 entry->cmdtype = CMDUNKNOWN;
12009 entry->cmdtype = CMDNORMAL;
12013 /* #if ENABLE_FEATURE_SH_STANDALONE... moved after builtin check */
12015 updatetbl = (path == pathval());
12018 if (strstr(path, "%builtin") != NULL)
12019 act |= DO_ALTBLTIN;
12022 /* If name is in the table, check answer will be ok */
12023 cmdp = cmdlookup(name, 0);
12024 if (cmdp != NULL) {
12027 switch (cmdp->cmdtype) {
12045 } else if (cmdp->rehash == 0)
12046 /* if not invalidated by cd, we're done */
12050 /* If %builtin not in path, check for builtin next */
12051 bcmd = find_builtin(name);
12053 if (IS_BUILTIN_REGULAR(bcmd))
12054 goto builtin_success;
12055 if (act & DO_ALTPATH) {
12056 if (!(act & DO_ALTBLTIN))
12057 goto builtin_success;
12058 } else if (builtinloc <= 0) {
12059 goto builtin_success;
12063 #if ENABLE_FEATURE_SH_STANDALONE
12065 int applet_no = find_applet_by_name(name);
12066 if (applet_no >= 0) {
12067 entry->cmdtype = CMDNORMAL;
12068 entry->u.index = -2 - applet_no;
12074 /* We have to search path. */
12075 prev = -1; /* where to start */
12076 if (cmdp && cmdp->rehash) { /* doing a rehash */
12077 if (cmdp->cmdtype == CMDBUILTIN)
12080 prev = cmdp->param.index;
12086 while ((fullname = padvance(&path, name)) != NULL) {
12087 stunalloc(fullname);
12088 /* NB: code below will still use fullname
12089 * despite it being "unallocated" */
12092 if (prefix(pathopt, "builtin")) {
12094 goto builtin_success;
12097 if ((act & DO_NOFUNC)
12098 || !prefix(pathopt, "func")
12099 ) { /* ignore unimplemented options */
12103 /* if rehash, don't redo absolute path names */
12104 if (fullname[0] == '/' && idx <= prev) {
12107 TRACE(("searchexec \"%s\": no change\n", name));
12110 while (stat(fullname, &statb) < 0) {
12112 if (errno == EINTR)
12115 if (errno != ENOENT && errno != ENOTDIR)
12119 e = EACCES; /* if we fail, this will be the error */
12120 if (!S_ISREG(statb.st_mode))
12122 if (pathopt) { /* this is a %func directory */
12123 stalloc(strlen(fullname) + 1);
12124 /* NB: stalloc will return space pointed by fullname
12125 * (because we don't have any intervening allocations
12126 * between stunalloc above and this stalloc) */
12127 readcmdfile(fullname);
12128 cmdp = cmdlookup(name, 0);
12129 if (cmdp == NULL || cmdp->cmdtype != CMDFUNCTION)
12130 ash_msg_and_raise_error("%s not defined in %s", name, fullname);
12131 stunalloc(fullname);
12134 TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
12136 entry->cmdtype = CMDNORMAL;
12137 entry->u.index = idx;
12141 cmdp = cmdlookup(name, 1);
12142 cmdp->cmdtype = CMDNORMAL;
12143 cmdp->param.index = idx;
12148 /* We failed. If there was an entry for this command, delete it */
12149 if (cmdp && updatetbl)
12150 delete_cmd_entry();
12152 ash_msg("%s: %s", name, errmsg(e, "not found"));
12153 entry->cmdtype = CMDUNKNOWN;
12158 entry->cmdtype = CMDBUILTIN;
12159 entry->u.cmd = bcmd;
12163 cmdp = cmdlookup(name, 1);
12164 cmdp->cmdtype = CMDBUILTIN;
12165 cmdp->param.cmd = bcmd;
12169 entry->cmdtype = cmdp->cmdtype;
12170 entry->u = cmdp->param;
12174 /* ============ trap.c */
12177 * The trap builtin.
12180 trapcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
12189 for (signo = 0; signo < NSIG; signo++) {
12190 if (trap[signo] != NULL) {
12191 out1fmt("trap -- %s %s\n",
12192 single_quote(trap[signo]),
12193 get_signame(signo));
12202 signo = get_signum(*ap);
12204 ash_msg_and_raise_error("%s: bad trap", *ap);
12207 if (LONE_DASH(action))
12210 action = ckstrdup(action);
12213 trap[signo] = action;
12223 /* ============ Builtins */
12225 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
12227 * Lists available builtins
12230 helpcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
12235 out1fmt("\nBuilt-in commands:\n-------------------\n");
12236 for (col = 0, i = 0; i < ARRAY_SIZE(builtintab); i++) {
12237 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '),
12238 builtintab[i].name + 1);
12244 #if ENABLE_FEATURE_SH_STANDALONE
12246 const char *a = applet_names;
12248 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '), a);
12253 a += strlen(a) + 1;
12258 return EXIT_SUCCESS;
12260 #endif /* FEATURE_SH_EXTRA_QUIET */
12263 * The export and readonly commands.
12266 exportcmd(int argc UNUSED_PARAM, char **argv)
12272 int flag = argv[0][0] == 'r' ? VREADONLY : VEXPORT;
12274 if (nextopt("p") != 'p') {
12279 p = strchr(name, '=');
12283 vp = *findvar(hashvar(name), name);
12289 setvar(name, p, flag);
12290 } while ((name = *++aptr) != NULL);
12294 showvars(argv[0], flag, 0);
12299 * Delete a function if it exists.
12302 unsetfunc(const char *name)
12304 struct tblentry *cmdp;
12306 cmdp = cmdlookup(name, 0);
12307 if (cmdp!= NULL && cmdp->cmdtype == CMDFUNCTION)
12308 delete_cmd_entry();
12312 * The unset builtin command. We unset the function before we unset the
12313 * variable to allow a function to be unset when there is a readonly variable
12314 * with the same name.
12317 unsetcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
12324 while ((i = nextopt("vf")) != '\0') {
12328 for (ap = argptr; *ap; ap++) {
12344 #include <sys/times.h>
12346 static const unsigned char timescmd_str[] ALIGN1 = {
12347 ' ', offsetof(struct tms, tms_utime),
12348 '\n', offsetof(struct tms, tms_stime),
12349 ' ', offsetof(struct tms, tms_cutime),
12350 '\n', offsetof(struct tms, tms_cstime),
12355 timescmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
12357 long clk_tck, s, t;
12358 const unsigned char *p;
12361 clk_tck = sysconf(_SC_CLK_TCK);
12366 t = *(clock_t *)(((char *) &buf) + p[1]);
12368 out1fmt("%ldm%ld.%.3lds%c",
12370 ((t - s * clk_tck) * 1000) / clk_tck,
12372 } while (*(p += 2));
12377 #if ENABLE_ASH_MATH_SUPPORT
12379 dash_arith(const char *s)
12385 result = arith(s, &errcode);
12388 ash_msg_and_raise_error("exponent less than 0");
12390 ash_msg_and_raise_error("divide by zero");
12392 ash_msg_and_raise_error("expression recursion loop detected");
12393 raise_error_syntax(s);
12401 * The let builtin. partial stolen from GNU Bash, the Bourne Again SHell.
12402 * Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
12404 * Copyright (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
12407 letcmd(int argc UNUSED_PARAM, char **argv)
12413 ash_msg_and_raise_error("expression expected");
12415 i = dash_arith(*argv);
12420 #endif /* ASH_MATH_SUPPORT */
12423 /* ============ miscbltin.c
12425 * Miscellaneous builtins.
12430 #if defined(__GLIBC__) && __GLIBC__ == 2 && __GLIBC_MINOR__ < 1
12431 typedef enum __rlimit_resource rlim_t;
12435 * The read builtin. Options:
12436 * -r Do not interpret '\' specially
12437 * -s Turn off echo (tty only)
12438 * -n NCHARS Read NCHARS max
12439 * -p PROMPT Display PROMPT on stderr (if input is from tty)
12440 * -t SECONDS Timeout after SECONDS (tty or pipe only)
12441 * -u FD Read from given FD instead of fd 0
12442 * This uses unbuffered input, which may be avoidable in some cases.
12443 * TODO: bash also has:
12444 * -a ARRAY Read into array[0],[1],etc
12445 * -d DELIM End on DELIM char, not newline
12446 * -e Use line editing (tty only)
12449 readcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
12451 static const char *const arg_REPLY[] = { "REPLY", NULL };
12464 #if ENABLE_ASH_READ_NCHARS
12465 int nchars = 0; /* if != 0, -n is in effect */
12467 struct termios tty, old_tty;
12469 #if ENABLE_ASH_READ_TIMEOUT
12470 unsigned end_ms = 0;
12471 unsigned timeout = 0;
12476 while ((i = nextopt("p:u:r"
12477 USE_ASH_READ_TIMEOUT("t:")
12478 USE_ASH_READ_NCHARS("n:s")
12482 prompt = optionarg;
12484 #if ENABLE_ASH_READ_NCHARS
12486 nchars = bb_strtou(optionarg, NULL, 10);
12487 if (nchars < 0 || errno)
12488 ash_msg_and_raise_error("invalid count");
12489 /* nchars == 0: off (bash 3.2 does this too) */
12495 #if ENABLE_ASH_READ_TIMEOUT
12497 timeout = bb_strtou(optionarg, NULL, 10);
12498 if (errno || timeout > UINT_MAX / 2048)
12499 ash_msg_and_raise_error("invalid timeout");
12501 #if 0 /* even bash have no -t N.NNN support */
12502 ts.tv_sec = bb_strtou(optionarg, &p, 10);
12504 /* EINVAL means number is ok, but not terminated by NUL */
12505 if (*p == '.' && errno == EINVAL) {
12509 ts.tv_usec = bb_strtou(p, &p2, 10);
12511 ash_msg_and_raise_error("invalid timeout");
12513 /* normalize to usec */
12515 ash_msg_and_raise_error("invalid timeout");
12516 while (scale++ < 6)
12519 } else if (ts.tv_sec < 0 || errno) {
12520 ash_msg_and_raise_error("invalid timeout");
12522 if (!(ts.tv_sec | ts.tv_usec)) { /* both are 0? */
12523 ash_msg_and_raise_error("invalid timeout");
12532 fd = bb_strtou(optionarg, NULL, 10);
12533 if (fd < 0 || errno)
12534 ash_msg_and_raise_error("invalid file descriptor");
12540 if (prompt && isatty(fd)) {
12545 ap = (char**)arg_REPLY;
12546 ifs = bltinlookup("IFS");
12549 #if ENABLE_ASH_READ_NCHARS
12550 tcgetattr(fd, &tty);
12552 if (nchars || silent) {
12554 tty.c_lflag &= ~ICANON;
12555 tty.c_cc[VMIN] = nchars < 256 ? nchars : 255;
12558 tty.c_lflag &= ~(ECHO | ECHOK | ECHONL);
12560 /* if tcgetattr failed, tcsetattr will fail too.
12561 * Ignoring, it's harmless. */
12562 tcsetattr(fd, TCSANOW, &tty);
12569 #if ENABLE_ASH_READ_TIMEOUT
12570 if (timeout) /* NB: ensuring end_ms is nonzero */
12571 end_ms = ((unsigned)(monotonic_us() / 1000) + timeout) | 1;
12575 #if ENABLE_ASH_READ_TIMEOUT
12577 struct pollfd pfd[1];
12579 pfd[0].events = POLLIN;
12580 timeout = end_ms - (unsigned)(monotonic_us() / 1000);
12581 if ((int)timeout <= 0 /* already late? */
12582 || safe_poll(pfd, 1, timeout) != 1 /* no? wait... */
12583 ) { /* timed out! */
12584 #if ENABLE_ASH_READ_NCHARS
12585 tcsetattr(fd, TCSANOW, &old_tty);
12591 if (nonblock_safe_read(fd, &c, 1) != 1) {
12603 if (!rflag && c == '\\') {
12609 if (startword && *ifs == ' ' && strchr(ifs, c)) {
12613 if (ap[1] != NULL && strchr(ifs, c) != NULL) {
12615 setvar(*ap, stackblock(), 0);
12624 /* end of do {} while: */
12625 #if ENABLE_ASH_READ_NCHARS
12631 #if ENABLE_ASH_READ_NCHARS
12632 tcsetattr(fd, TCSANOW, &old_tty);
12636 /* Remove trailing blanks */
12637 while ((char *)stackblock() <= --p && strchr(ifs, *p) != NULL)
12639 setvar(*ap, stackblock(), 0);
12640 while (*++ap != NULL)
12641 setvar(*ap, nullstr, 0);
12646 umaskcmd(int argc UNUSED_PARAM, char **argv)
12648 static const char permuser[3] ALIGN1 = "ugo";
12649 static const char permmode[3] ALIGN1 = "rwx";
12650 static const short permmask[] ALIGN2 = {
12651 S_IRUSR, S_IWUSR, S_IXUSR,
12652 S_IRGRP, S_IWGRP, S_IXGRP,
12653 S_IROTH, S_IWOTH, S_IXOTH
12659 int symbolic_mode = 0;
12661 while (nextopt("S") != '\0') {
12672 if (symbolic_mode) {
12676 for (i = 0; i < 3; i++) {
12679 *p++ = permuser[i];
12681 for (j = 0; j < 3; j++) {
12682 if ((mask & permmask[3 * i + j]) == 0) {
12683 *p++ = permmode[j];
12691 out1fmt("%.4o\n", mask);
12694 if (isdigit((unsigned char) *ap)) {
12697 if (*ap >= '8' || *ap < '0')
12698 ash_msg_and_raise_error(illnum, argv[1]);
12699 mask = (mask << 3) + (*ap - '0');
12700 } while (*++ap != '\0');
12703 mask = ~mask & 0777;
12704 if (!bb_parse_mode(ap, &mask)) {
12705 ash_msg_and_raise_error("illegal mode: %s", ap);
12707 umask(~mask & 0777);
12716 * This code, originally by Doug Gwyn, Doug Kingston, Eric Gisin, and
12717 * Michael Rendell was ripped from pdksh 5.0.8 and hacked for use with
12718 * ash by J.T. Conklin.
12724 uint8_t cmd; /* RLIMIT_xxx fit into it */
12725 uint8_t factor_shift; /* shift by to get rlim_{cur,max} values */
12729 static const struct limits limits_tbl[] = {
12731 { RLIMIT_CPU, 0, 't' },
12733 #ifdef RLIMIT_FSIZE
12734 { RLIMIT_FSIZE, 9, 'f' },
12737 { RLIMIT_DATA, 10, 'd' },
12739 #ifdef RLIMIT_STACK
12740 { RLIMIT_STACK, 10, 's' },
12743 { RLIMIT_CORE, 9, 'c' },
12746 { RLIMIT_RSS, 10, 'm' },
12748 #ifdef RLIMIT_MEMLOCK
12749 { RLIMIT_MEMLOCK, 10, 'l' },
12751 #ifdef RLIMIT_NPROC
12752 { RLIMIT_NPROC, 0, 'p' },
12754 #ifdef RLIMIT_NOFILE
12755 { RLIMIT_NOFILE, 0, 'n' },
12758 { RLIMIT_AS, 10, 'v' },
12760 #ifdef RLIMIT_LOCKS
12761 { RLIMIT_LOCKS, 0, 'w' },
12764 static const char limits_name[] =
12766 "time(seconds)" "\0"
12768 #ifdef RLIMIT_FSIZE
12769 "file(blocks)" "\0"
12774 #ifdef RLIMIT_STACK
12778 "coredump(blocks)" "\0"
12783 #ifdef RLIMIT_MEMLOCK
12784 "locked memory(kb)" "\0"
12786 #ifdef RLIMIT_NPROC
12789 #ifdef RLIMIT_NOFILE
12795 #ifdef RLIMIT_LOCKS
12800 enum limtype { SOFT = 0x1, HARD = 0x2 };
12803 printlim(enum limtype how, const struct rlimit *limit,
12804 const struct limits *l)
12808 val = limit->rlim_max;
12810 val = limit->rlim_cur;
12812 if (val == RLIM_INFINITY)
12813 out1fmt("unlimited\n");
12815 val >>= l->factor_shift;
12816 out1fmt("%lld\n", (long long) val);
12821 ulimitcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
12825 enum limtype how = SOFT | HARD;
12826 const struct limits *l;
12829 struct rlimit limit;
12832 while ((optc = nextopt("HSa"
12836 #ifdef RLIMIT_FSIZE
12842 #ifdef RLIMIT_STACK
12851 #ifdef RLIMIT_MEMLOCK
12854 #ifdef RLIMIT_NPROC
12857 #ifdef RLIMIT_NOFILE
12863 #ifdef RLIMIT_LOCKS
12881 for (l = limits_tbl; l->option != what; l++)
12884 set = *argptr ? 1 : 0;
12888 if (all || argptr[1])
12889 ash_msg_and_raise_error("too many arguments");
12890 if (strncmp(p, "unlimited\n", 9) == 0)
12891 val = RLIM_INFINITY;
12895 while ((c = *p++) >= '0' && c <= '9') {
12896 val = (val * 10) + (long)(c - '0');
12897 // val is actually 'unsigned long int' and can't get < 0
12898 if (val < (rlim_t) 0)
12902 ash_msg_and_raise_error("bad number");
12903 val <<= l->factor_shift;
12907 const char *lname = limits_name;
12908 for (l = limits_tbl; l != &limits_tbl[ARRAY_SIZE(limits_tbl)]; l++) {
12909 getrlimit(l->cmd, &limit);
12910 out1fmt("%-20s ", lname);
12911 lname += strlen(lname) + 1;
12912 printlim(how, &limit, l);
12917 getrlimit(l->cmd, &limit);
12920 limit.rlim_max = val;
12922 limit.rlim_cur = val;
12923 if (setrlimit(l->cmd, &limit) < 0)
12924 ash_msg_and_raise_error("error setting limit (%m)");
12926 printlim(how, &limit, l);
12932 /* ============ Math support */
12934 #if ENABLE_ASH_MATH_SUPPORT
12936 /* Copyright (c) 2001 Aaron Lehmann <aaronl@vitelus.com>
12938 Permission is hereby granted, free of charge, to any person obtaining
12939 a copy of this software and associated documentation files (the
12940 "Software"), to deal in the Software without restriction, including
12941 without limitation the rights to use, copy, modify, merge, publish,
12942 distribute, sublicense, and/or sell copies of the Software, and to
12943 permit persons to whom the Software is furnished to do so, subject to
12944 the following conditions:
12946 The above copyright notice and this permission notice shall be
12947 included in all copies or substantial portions of the Software.
12949 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
12950 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
12951 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
12952 IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
12953 CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
12954 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
12955 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
12958 /* This is my infix parser/evaluator. It is optimized for size, intended
12959 * as a replacement for yacc-based parsers. However, it may well be faster
12960 * than a comparable parser written in yacc. The supported operators are
12961 * listed in #defines below. Parens, order of operations, and error handling
12962 * are supported. This code is thread safe. The exact expression format should
12963 * be that which POSIX specifies for shells. */
12965 /* The code uses a simple two-stack algorithm. See
12966 * http://www.onthenet.com.au/~grahamis/int2008/week02/lect02.html
12967 * for a detailed explanation of the infix-to-postfix algorithm on which
12968 * this is based (this code differs in that it applies operators immediately
12969 * to the stack instead of adding them to a queue to end up with an
12972 /* To use the routine, call it with an expression string and error return
12976 * Aug 24, 2001 Manuel Novoa III
12978 * Reduced the generated code size by about 30% (i386) and fixed several bugs.
12980 * 1) In arith_apply():
12981 * a) Cached values of *numptr and &(numptr[-1]).
12982 * b) Removed redundant test for zero denominator.
12985 * a) Eliminated redundant code for processing operator tokens by moving
12986 * to a table-based implementation. Also folded handling of parens
12988 * b) Combined all 3 loops which called arith_apply to reduce generated
12989 * code size at the cost of speed.
12991 * 3) The following expressions were treated as valid by the original code:
12992 * 1() , 0! , 1 ( *3 ) .
12993 * These bugs have been fixed by internally enclosing the expression in
12994 * parens and then checking that all binary ops and right parens are
12995 * preceded by a valid expression (NUM_TOKEN).
12997 * Note: It may be desirable to replace Aaron's test for whitespace with
12998 * ctype's isspace() if it is used by another busybox applet or if additional
12999 * whitespace chars should be considered. Look below the "#include"s for a
13000 * precompiler test.
13004 * Aug 26, 2001 Manuel Novoa III
13006 * Return 0 for null expressions. Pointed out by Vladimir Oleynik.
13008 * Merge in Aaron's comments previously posted to the busybox list,
13009 * modified slightly to take account of my changes to the code.
13014 * (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
13016 * - allow access to variable,
13017 * used recursive find value indirection (c=2*2; a="c"; $((a+=2)) produce 6)
13018 * - realize assign syntax (VAR=expr, +=, *= etc)
13019 * - realize exponentiation (** operator)
13020 * - realize comma separated - expr, expr
13021 * - realise ++expr --expr expr++ expr--
13022 * - realise expr ? expr : expr (but, second expr calculate always)
13023 * - allow hexadecimal and octal numbers
13024 * - was restored loses XOR operator
13025 * - remove one goto label, added three ;-)
13026 * - protect $((num num)) as true zero expr (Manuel`s error)
13027 * - always use special isspace(), see comment from bash ;-)
13030 #define arith_isspace(arithval) \
13031 (arithval == ' ' || arithval == '\n' || arithval == '\t')
13033 typedef unsigned char operator;
13035 /* An operator's token id is a bit of a bitfield. The lower 5 bits are the
13036 * precedence, and 3 high bits are an ID unique across operators of that
13037 * precedence. The ID portion is so that multiple operators can have the
13038 * same precedence, ensuring that the leftmost one is evaluated first.
13039 * Consider * and /. */
13041 #define tok_decl(prec,id) (((id)<<5)|(prec))
13042 #define PREC(op) ((op) & 0x1F)
13044 #define TOK_LPAREN tok_decl(0,0)
13046 #define TOK_COMMA tok_decl(1,0)
13048 #define TOK_ASSIGN tok_decl(2,0)
13049 #define TOK_AND_ASSIGN tok_decl(2,1)
13050 #define TOK_OR_ASSIGN tok_decl(2,2)
13051 #define TOK_XOR_ASSIGN tok_decl(2,3)
13052 #define TOK_PLUS_ASSIGN tok_decl(2,4)
13053 #define TOK_MINUS_ASSIGN tok_decl(2,5)
13054 #define TOK_LSHIFT_ASSIGN tok_decl(2,6)
13055 #define TOK_RSHIFT_ASSIGN tok_decl(2,7)
13057 #define TOK_MUL_ASSIGN tok_decl(3,0)
13058 #define TOK_DIV_ASSIGN tok_decl(3,1)
13059 #define TOK_REM_ASSIGN tok_decl(3,2)
13061 /* all assign is right associativity and precedence eq, but (7+3)<<5 > 256 */
13062 #define convert_prec_is_assing(prec) do { if (prec == 3) prec = 2; } while (0)
13064 /* conditional is right associativity too */
13065 #define TOK_CONDITIONAL tok_decl(4,0)
13066 #define TOK_CONDITIONAL_SEP tok_decl(4,1)
13068 #define TOK_OR tok_decl(5,0)
13070 #define TOK_AND tok_decl(6,0)
13072 #define TOK_BOR tok_decl(7,0)
13074 #define TOK_BXOR tok_decl(8,0)
13076 #define TOK_BAND tok_decl(9,0)
13078 #define TOK_EQ tok_decl(10,0)
13079 #define TOK_NE tok_decl(10,1)
13081 #define TOK_LT tok_decl(11,0)
13082 #define TOK_GT tok_decl(11,1)
13083 #define TOK_GE tok_decl(11,2)
13084 #define TOK_LE tok_decl(11,3)
13086 #define TOK_LSHIFT tok_decl(12,0)
13087 #define TOK_RSHIFT tok_decl(12,1)
13089 #define TOK_ADD tok_decl(13,0)
13090 #define TOK_SUB tok_decl(13,1)
13092 #define TOK_MUL tok_decl(14,0)
13093 #define TOK_DIV tok_decl(14,1)
13094 #define TOK_REM tok_decl(14,2)
13096 /* exponent is right associativity */
13097 #define TOK_EXPONENT tok_decl(15,1)
13099 /* For now unary operators. */
13100 #define UNARYPREC 16
13101 #define TOK_BNOT tok_decl(UNARYPREC,0)
13102 #define TOK_NOT tok_decl(UNARYPREC,1)
13104 #define TOK_UMINUS tok_decl(UNARYPREC+1,0)
13105 #define TOK_UPLUS tok_decl(UNARYPREC+1,1)
13107 #define PREC_PRE (UNARYPREC+2)
13109 #define TOK_PRE_INC tok_decl(PREC_PRE, 0)
13110 #define TOK_PRE_DEC tok_decl(PREC_PRE, 1)
13112 #define PREC_POST (UNARYPREC+3)
13114 #define TOK_POST_INC tok_decl(PREC_POST, 0)
13115 #define TOK_POST_DEC tok_decl(PREC_POST, 1)
13117 #define SPEC_PREC (UNARYPREC+4)
13119 #define TOK_NUM tok_decl(SPEC_PREC, 0)
13120 #define TOK_RPAREN tok_decl(SPEC_PREC, 1)
13122 #define NUMPTR (*numstackptr)
13125 tok_have_assign(operator op)
13127 operator prec = PREC(op);
13129 convert_prec_is_assing(prec);
13130 return (prec == PREC(TOK_ASSIGN) ||
13131 prec == PREC_PRE || prec == PREC_POST);
13135 is_right_associativity(operator prec)
13137 return (prec == PREC(TOK_ASSIGN) || prec == PREC(TOK_EXPONENT)
13138 || prec == PREC(TOK_CONDITIONAL));
13143 arith_t contidional_second_val;
13144 char contidional_second_val_initialized;
13145 char *var; /* if NULL then is regular number,
13146 else is variable name */
13149 typedef struct chk_var_recursive_looped_t {
13151 struct chk_var_recursive_looped_t *next;
13152 } chk_var_recursive_looped_t;
13154 static chk_var_recursive_looped_t *prev_chk_var_recursive;
13157 arith_lookup_val(v_n_t *t)
13160 const char * p = lookupvar(t->var);
13165 /* recursive try as expression */
13166 chk_var_recursive_looped_t *cur;
13167 chk_var_recursive_looped_t cur_save;
13169 for (cur = prev_chk_var_recursive; cur; cur = cur->next) {
13170 if (strcmp(cur->var, t->var) == 0) {
13171 /* expression recursion loop detected */
13175 /* save current lookuped var name */
13176 cur = prev_chk_var_recursive;
13177 cur_save.var = t->var;
13178 cur_save.next = cur;
13179 prev_chk_var_recursive = &cur_save;
13181 t->val = arith (p, &errcode);
13182 /* restore previous ptr after recursiving */
13183 prev_chk_var_recursive = cur;
13186 /* allow undefined var as 0 */
13192 /* "applying" a token means performing it on the top elements on the integer
13193 * stack. For a unary operator it will only change the top element, but a
13194 * binary operator will pop two arguments and push a result */
13196 arith_apply(operator op, v_n_t *numstack, v_n_t **numstackptr)
13199 arith_t numptr_val, rez;
13200 int ret_arith_lookup_val;
13202 /* There is no operator that can work without arguments */
13203 if (NUMPTR == numstack) goto err;
13204 numptr_m1 = NUMPTR - 1;
13206 /* check operand is var with noninteger value */
13207 ret_arith_lookup_val = arith_lookup_val(numptr_m1);
13208 if (ret_arith_lookup_val)
13209 return ret_arith_lookup_val;
13211 rez = numptr_m1->val;
13212 if (op == TOK_UMINUS)
13214 else if (op == TOK_NOT)
13216 else if (op == TOK_BNOT)
13218 else if (op == TOK_POST_INC || op == TOK_PRE_INC)
13220 else if (op == TOK_POST_DEC || op == TOK_PRE_DEC)
13222 else if (op != TOK_UPLUS) {
13223 /* Binary operators */
13225 /* check and binary operators need two arguments */
13226 if (numptr_m1 == numstack) goto err;
13228 /* ... and they pop one */
13231 if (op == TOK_CONDITIONAL) {
13232 if (!numptr_m1->contidional_second_val_initialized) {
13233 /* protect $((expr1 ? expr2)) without ": expr" */
13236 rez = numptr_m1->contidional_second_val;
13237 } else if (numptr_m1->contidional_second_val_initialized) {
13238 /* protect $((expr1 : expr2)) without "expr ? " */
13241 numptr_m1 = NUMPTR - 1;
13242 if (op != TOK_ASSIGN) {
13243 /* check operand is var with noninteger value for not '=' */
13244 ret_arith_lookup_val = arith_lookup_val(numptr_m1);
13245 if (ret_arith_lookup_val)
13246 return ret_arith_lookup_val;
13248 if (op == TOK_CONDITIONAL) {
13249 numptr_m1->contidional_second_val = rez;
13251 rez = numptr_m1->val;
13252 if (op == TOK_BOR || op == TOK_OR_ASSIGN)
13254 else if (op == TOK_OR)
13255 rez = numptr_val || rez;
13256 else if (op == TOK_BAND || op == TOK_AND_ASSIGN)
13258 else if (op == TOK_BXOR || op == TOK_XOR_ASSIGN)
13260 else if (op == TOK_AND)
13261 rez = rez && numptr_val;
13262 else if (op == TOK_EQ)
13263 rez = (rez == numptr_val);
13264 else if (op == TOK_NE)
13265 rez = (rez != numptr_val);
13266 else if (op == TOK_GE)
13267 rez = (rez >= numptr_val);
13268 else if (op == TOK_RSHIFT || op == TOK_RSHIFT_ASSIGN)
13269 rez >>= numptr_val;
13270 else if (op == TOK_LSHIFT || op == TOK_LSHIFT_ASSIGN)
13271 rez <<= numptr_val;
13272 else if (op == TOK_GT)
13273 rez = (rez > numptr_val);
13274 else if (op == TOK_LT)
13275 rez = (rez < numptr_val);
13276 else if (op == TOK_LE)
13277 rez = (rez <= numptr_val);
13278 else if (op == TOK_MUL || op == TOK_MUL_ASSIGN)
13280 else if (op == TOK_ADD || op == TOK_PLUS_ASSIGN)
13282 else if (op == TOK_SUB || op == TOK_MINUS_ASSIGN)
13284 else if (op == TOK_ASSIGN || op == TOK_COMMA)
13286 else if (op == TOK_CONDITIONAL_SEP) {
13287 if (numptr_m1 == numstack) {
13288 /* protect $((expr : expr)) without "expr ? " */
13291 numptr_m1->contidional_second_val_initialized = op;
13292 numptr_m1->contidional_second_val = numptr_val;
13293 } else if (op == TOK_CONDITIONAL) {
13295 numptr_val : numptr_m1->contidional_second_val;
13296 } else if (op == TOK_EXPONENT) {
13297 if (numptr_val < 0)
13298 return -3; /* exponent less than 0 */
13303 while (numptr_val--)
13307 } else if (numptr_val==0) /* zero divisor check */
13309 else if (op == TOK_DIV || op == TOK_DIV_ASSIGN)
13311 else if (op == TOK_REM || op == TOK_REM_ASSIGN)
13314 if (tok_have_assign(op)) {
13315 char buf[sizeof(arith_t_type)*3 + 2];
13317 if (numptr_m1->var == NULL) {
13321 /* save to shell variable */
13322 #if ENABLE_ASH_MATH_SUPPORT_64
13323 snprintf(buf, sizeof(buf), "%lld", (arith_t_type) rez);
13325 snprintf(buf, sizeof(buf), "%ld", (arith_t_type) rez);
13327 setvar(numptr_m1->var, buf, 0);
13328 /* after saving, make previous value for v++ or v-- */
13329 if (op == TOK_POST_INC)
13331 else if (op == TOK_POST_DEC)
13334 numptr_m1->val = rez;
13335 /* protect geting var value, is number now */
13336 numptr_m1->var = NULL;
13342 /* longest must be first */
13343 static const char op_tokens[] ALIGN1 = {
13344 '<','<','=',0, TOK_LSHIFT_ASSIGN,
13345 '>','>','=',0, TOK_RSHIFT_ASSIGN,
13346 '<','<', 0, TOK_LSHIFT,
13347 '>','>', 0, TOK_RSHIFT,
13348 '|','|', 0, TOK_OR,
13349 '&','&', 0, TOK_AND,
13350 '!','=', 0, TOK_NE,
13351 '<','=', 0, TOK_LE,
13352 '>','=', 0, TOK_GE,
13353 '=','=', 0, TOK_EQ,
13354 '|','=', 0, TOK_OR_ASSIGN,
13355 '&','=', 0, TOK_AND_ASSIGN,
13356 '*','=', 0, TOK_MUL_ASSIGN,
13357 '/','=', 0, TOK_DIV_ASSIGN,
13358 '%','=', 0, TOK_REM_ASSIGN,
13359 '+','=', 0, TOK_PLUS_ASSIGN,
13360 '-','=', 0, TOK_MINUS_ASSIGN,
13361 '-','-', 0, TOK_POST_DEC,
13362 '^','=', 0, TOK_XOR_ASSIGN,
13363 '+','+', 0, TOK_POST_INC,
13364 '*','*', 0, TOK_EXPONENT,
13368 '=', 0, TOK_ASSIGN,
13380 '?', 0, TOK_CONDITIONAL,
13381 ':', 0, TOK_CONDITIONAL_SEP,
13382 ')', 0, TOK_RPAREN,
13383 '(', 0, TOK_LPAREN,
13387 #define endexpression (&op_tokens[sizeof(op_tokens)-7])
13390 arith(const char *expr, int *perrcode)
13392 char arithval; /* Current character under analysis */
13393 operator lasttok, op;
13395 operator *stack, *stackptr;
13396 const char *p = endexpression;
13398 v_n_t *numstack, *numstackptr;
13399 unsigned datasizes = strlen(expr) + 2;
13401 /* Stack of integers */
13402 /* The proof that there can be no more than strlen(startbuf)/2+1 integers
13403 * in any given correct or incorrect expression is left as an exercise to
13405 numstackptr = numstack = alloca((datasizes / 2) * sizeof(numstack[0]));
13406 /* Stack of operator tokens */
13407 stackptr = stack = alloca(datasizes * sizeof(stack[0]));
13409 *stackptr++ = lasttok = TOK_LPAREN; /* start off with a left paren */
13410 *perrcode = errcode = 0;
13414 if (arithval == 0) {
13415 if (p == endexpression) {
13416 /* Null expression. */
13420 /* This is only reached after all tokens have been extracted from the
13421 * input stream. If there are still tokens on the operator stack, they
13422 * are to be applied in order. At the end, there should be a final
13423 * result on the integer stack */
13425 if (expr != endexpression + 1) {
13426 /* If we haven't done so already, */
13427 /* append a closing right paren */
13428 expr = endexpression;
13429 /* and let the loop process it. */
13432 /* At this point, we're done with the expression. */
13433 if (numstackptr != numstack+1) {
13434 /* ... but if there isn't, it's bad */
13439 if (numstack->var) {
13440 /* expression is $((var)) only, lookup now */
13441 errcode = arith_lookup_val(numstack);
13444 *perrcode = errcode;
13445 return numstack->val;
13448 /* Continue processing the expression. */
13449 if (arith_isspace(arithval)) {
13450 /* Skip whitespace */
13453 p = endofname(expr);
13455 size_t var_name_size = (p-expr) + 1; /* trailing zero */
13457 numstackptr->var = alloca(var_name_size);
13458 safe_strncpy(numstackptr->var, expr, var_name_size);
13461 numstackptr->contidional_second_val_initialized = 0;
13466 if (isdigit(arithval)) {
13467 numstackptr->var = NULL;
13468 #if ENABLE_ASH_MATH_SUPPORT_64
13469 numstackptr->val = strtoll(expr, (char **) &expr, 0);
13471 numstackptr->val = strtol(expr, (char **) &expr, 0);
13475 for (p = op_tokens; ; p++) {
13479 /* strange operator not found */
13482 for (o = expr; *p && *o == *p; p++)
13489 /* skip tail uncompared token */
13492 /* skip zero delim */
13497 /* post grammar: a++ reduce to num */
13498 if (lasttok == TOK_POST_INC || lasttok == TOK_POST_DEC)
13501 /* Plus and minus are binary (not unary) _only_ if the last
13502 * token was as number, or a right paren (which pretends to be
13503 * a number, since it evaluates to one). Think about it.
13504 * It makes sense. */
13505 if (lasttok != TOK_NUM) {
13521 /* We don't want a unary operator to cause recursive descent on the
13522 * stack, because there can be many in a row and it could cause an
13523 * operator to be evaluated before its argument is pushed onto the
13524 * integer stack. */
13525 /* But for binary operators, "apply" everything on the operator
13526 * stack until we find an operator with a lesser priority than the
13527 * one we have just extracted. */
13528 /* Left paren is given the lowest priority so it will never be
13529 * "applied" in this way.
13530 * if associativity is right and priority eq, applied also skip
13533 if ((prec > 0 && prec < UNARYPREC) || prec == SPEC_PREC) {
13534 /* not left paren or unary */
13535 if (lasttok != TOK_NUM) {
13536 /* binary op must be preceded by a num */
13539 while (stackptr != stack) {
13540 if (op == TOK_RPAREN) {
13541 /* The algorithm employed here is simple: while we don't
13542 * hit an open paren nor the bottom of the stack, pop
13543 * tokens and apply them */
13544 if (stackptr[-1] == TOK_LPAREN) {
13546 /* Any operator directly after a */
13548 /* close paren should consider itself binary */
13552 operator prev_prec = PREC(stackptr[-1]);
13554 convert_prec_is_assing(prec);
13555 convert_prec_is_assing(prev_prec);
13556 if (prev_prec < prec)
13558 /* check right assoc */
13559 if (prev_prec == prec && is_right_associativity(prec))
13562 errcode = arith_apply(*--stackptr, numstack, &numstackptr);
13563 if (errcode) goto ret;
13565 if (op == TOK_RPAREN) {
13570 /* Push this operator to the stack and remember it. */
13571 *stackptr++ = lasttok = op;
13576 #endif /* ASH_MATH_SUPPORT */
13579 /* ============ main() and helpers */
13582 * Called to exit the shell.
13584 static void exitshell(void) NORETURN;
13592 status = exitstatus;
13593 TRACE(("pid %d, exitshell(%d)\n", getpid(), status));
13594 if (setjmp(loc.loc)) {
13595 if (exception_type == EXEXIT)
13596 /* dash bug: it just does _exit(exitstatus) here
13597 * but we have to do setjobctl(0) first!
13598 * (bug is still not fixed in dash-0.5.3 - if you run dash
13599 * under Midnight Commander, on exit from dash MC is backgrounded) */
13600 status = exitstatus;
13603 exception_handler = &loc;
13609 flush_stdout_stderr();
13619 /* from input.c: */
13620 basepf.next_to_pgetc = basepf.buf = basebuf;
13623 signal(SIGCHLD, SIG_DFL);
13628 char ppid[sizeof(int)*3 + 1];
13630 struct stat st1, st2;
13633 for (envp = environ; envp && *envp; envp++) {
13634 if (strchr(*envp, '=')) {
13635 setvareq(*envp, VEXPORT|VTEXTFIXED);
13639 snprintf(ppid, sizeof(ppid), "%u", (unsigned) getppid());
13640 setvar("PPID", ppid, 0);
13642 p = lookupvar("PWD");
13644 if (*p != '/' || stat(p, &st1) || stat(".", &st2)
13645 || st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino)
13652 * Process the shell command line arguments.
13655 procargs(char **argv)
13658 const char *xminusc;
13663 /* if (xargv[0]) - mmm, this is always true! */
13665 for (i = 0; i < NOPTS; i++)
13669 /* it already printed err message */
13670 raise_exception(EXERROR);
13674 if (*xargv == NULL) {
13676 ash_msg_and_raise_error(bb_msg_requires_arg, "-c");
13679 if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
13683 for (i = 0; i < NOPTS; i++)
13684 if (optlist[i] == 2)
13689 /* POSIX 1003.2: first arg after -c cmd is $0, remainder $1... */
13694 } else if (!sflag) {
13695 setinputfile(*xargv, 0);
13698 commandname = arg0;
13701 shellparam.p = xargv;
13702 #if ENABLE_ASH_GETOPTS
13703 shellparam.optind = 1;
13704 shellparam.optoff = -1;
13706 /* assert(shellparam.malloced == 0 && shellparam.nparam == 0); */
13708 shellparam.nparam++;
13715 * Read /etc/profile or .profile.
13718 read_profile(const char *name)
13722 if (setinputfile(name, INPUT_PUSH_FILE | INPUT_NOFILE_OK) < 0)
13731 * This routine is called when an error or an interrupt occurs in an
13732 * interactive shell and control is returned to the main command loop.
13740 /* from input.c: */
13741 g_parsefile->left_in_buffer = 0;
13742 g_parsefile->left_in_line = 0; /* clear input buffer */
13744 /* from parser.c: */
13747 /* from redir.c: */
13748 clearredir(/*drop:*/ 0);
13752 static short profile_buf[16384];
13753 extern int etext();
13757 * Main routine. We initialize things, parse the arguments, execute
13758 * profiles if we're a login shell, and then call cmdloop to execute
13759 * commands. The setjmp call sets up the location to jump to when an
13760 * exception occurs. When an exception occurs the variable "state"
13761 * is used to figure out how far we had gotten.
13763 int ash_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
13764 int ash_main(int argc UNUSED_PARAM, char **argv)
13767 volatile smallint state;
13768 struct jmploc jmploc;
13769 struct stackmark smark;
13771 /* Initialize global data */
13775 #if ENABLE_ASH_ALIAS
13781 monitor(4, etext, profile_buf, sizeof(profile_buf), 50);
13784 #if ENABLE_FEATURE_EDITING
13785 line_input_state = new_line_input_t(FOR_SHELL | WITH_PATH_LOOKUP);
13788 if (setjmp(jmploc.loc)) {
13794 e = exception_type;
13798 if (e == EXEXIT || s == 0 || iflag == 0 || shlvl)
13801 outcslow('\n', stderr);
13803 popstackmark(&smark);
13804 FORCE_INT_ON; /* enable interrupts */
13813 exception_handler = &jmploc;
13816 TRACE(("Shell args: "));
13817 trace_puts_args(argv);
13819 rootpid = getpid();
13821 #if ENABLE_ASH_RANDOM_SUPPORT
13822 /* Can use monotonic_ns() for better randomness but for now it is
13823 * not used anywhere else in busybox... so avoid bloat */
13824 random_galois_LFSR = random_LCG = rootpid + monotonic_us();
13827 setstackmark(&smark);
13830 #if ENABLE_FEATURE_EDITING_SAVEHISTORY
13832 const char *hp = lookupvar("HISTFILE");
13835 hp = lookupvar("HOME");
13837 char *defhp = concat_path_file(hp, ".ash_history");
13838 setvar("HISTFILE", defhp, 0);
13844 if (/* argv[0] && */ argv[0][0] == '-')
13848 read_profile("/etc/profile");
13851 read_profile(".profile");
13857 getuid() == geteuid() && getgid() == getegid() &&
13861 shinit = lookupvar("ENV");
13862 if (shinit != NULL && *shinit != '\0') {
13863 read_profile(shinit);
13869 /* evalstring pushes parsefile stack.
13870 * Ensure we don't falsely claim that 0 (stdin)
13871 * is one of stacked source fds */
13873 g_parsefile->fd = -1;
13874 evalstring(minusc, 0);
13877 if (sflag || minusc == NULL) {
13878 #if ENABLE_FEATURE_EDITING_SAVEHISTORY
13880 const char *hp = lookupvar("HISTFILE");
13882 line_input_state->hist_file = hp;
13885 state4: /* XXX ??? - why isn't this before the "if" statement */
13893 extern void _mcleanup(void);
13903 * Copyright (c) 1989, 1991, 1993, 1994
13904 * The Regents of the University of California. All rights reserved.
13906 * This code is derived from software contributed to Berkeley by
13907 * Kenneth Almquist.
13909 * Redistribution and use in source and binary forms, with or without
13910 * modification, are permitted provided that the following conditions
13912 * 1. Redistributions of source code must retain the above copyright
13913 * notice, this list of conditions and the following disclaimer.
13914 * 2. Redistributions in binary form must reproduce the above copyright
13915 * notice, this list of conditions and the following disclaimer in the
13916 * documentation and/or other materials provided with the distribution.
13917 * 3. Neither the name of the University nor the names of its contributors
13918 * may be used to endorse or promote products derived from this software
13919 * without specific prior written permission.
13921 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
13922 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
13923 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
13924 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
13925 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
13926 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
13927 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
13928 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
13929 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
13930 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF