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
263 # define close(fd) do { \
265 if (close(dfd) < 0) \
266 bb_error_msg("bug on %d: closing %d(%x)", \
267 __LINE__, dfd, dfd); \
270 # define TRACE(param)
271 # define TRACEV(param)
275 /* ============ Utility functions */
276 #define xbarrier() do { __asm__ __volatile__ ("": : :"memory"); } while (0)
278 /* C99 say: "char" declaration may be signed or unsigned by default */
279 #define signed_char2int(sc) ((int)(signed char)(sc))
281 static int isdigit_str9(const char *str)
283 int maxlen = 9 + 1; /* max 9 digits: 999999999 */
284 while (--maxlen && isdigit(*str))
286 return (*str == '\0');
290 /* ============ Interrupts / exceptions */
292 * These macros allow the user to suspend the handling of interrupt signals
293 * over a period of time. This is similar to SIGHOLD or to sigblock, but
294 * much more efficient and portable. (But hacking the kernel is so much
295 * more fun than worrying about efficiency and portability. :-))
297 #define INT_OFF do { \
303 * Called to raise an exception. Since C doesn't include exceptions, we
304 * just do a longjmp to the exception handler. The type of exception is
305 * stored in the global variable "exception_type".
307 static void raise_exception(int) NORETURN;
309 raise_exception(int e)
312 if (exception_handler == NULL)
317 longjmp(exception_handler->loc, 1);
320 #define raise_exception(e) do { \
321 TRACE(("raising exception %d on line %d\n", (e), __LINE__)); \
322 raise_exception(e); \
327 * Called from trap.c when a SIGINT is received. (If the user specifies
328 * that SIGINT is to be trapped or ignored using the trap builtin, then
329 * this routine is not called.) Suppressint is nonzero when interrupts
330 * are held using the INT_OFF macro. (The test for iflag is just
331 * defensive programming.)
333 static void raise_interrupt(void) NORETURN;
335 raise_interrupt(void)
340 /* Signal is not automatically unmasked after it is raised,
341 * do it ourself - unmask all signals */
342 sigprocmask_allsigs(SIG_UNBLOCK);
343 /* pendingsig = 0; - now done in onsig() */
346 if (gotsig[SIGINT - 1] && !trap[SIGINT]) {
347 if (!(rootshell && iflag)) {
348 /* Kill ourself with SIGINT */
349 signal(SIGINT, SIG_DFL);
354 raise_exception(ex_type);
358 #define raise_interrupt() do { \
359 TRACE(("raising interrupt on line %d\n", __LINE__)); \
364 #if ENABLE_ASH_OPTIMIZE_FOR_SIZE
368 if (--suppressint == 0 && intpending) {
372 #define INT_ON int_on()
380 #define FORCE_INT_ON force_int_on()
382 #else /* !ASH_OPTIMIZE_FOR_SIZE */
384 #define INT_ON do { \
386 if (--suppressint == 0 && intpending) \
389 #define FORCE_INT_ON do { \
395 #endif /* !ASH_OPTIMIZE_FOR_SIZE */
397 #define SAVE_INT(v) ((v) = suppressint)
399 #define RESTORE_INT(v) do { \
402 if (suppressint == 0 && intpending) \
407 /* ============ Stdout/stderr output */
410 outstr(const char *p, FILE *file)
418 flush_stdout_stderr(void)
435 outcslow(int c, FILE *dest)
443 static int out1fmt(const char *, ...) __attribute__((__format__(__printf__,1,2)));
445 out1fmt(const char *fmt, ...)
452 r = vprintf(fmt, ap);
458 static int fmtstr(char *, size_t, const char *, ...) __attribute__((__format__(__printf__,3,4)));
460 fmtstr(char *outbuf, size_t length, const char *fmt, ...)
467 ret = vsnprintf(outbuf, length, fmt, ap);
474 out1str(const char *p)
480 out2str(const char *p)
487 /* ============ Parser structures */
489 /* control characters in argument strings */
490 #define CTLESC '\201' /* escape next character */
491 #define CTLVAR '\202' /* variable defn */
492 #define CTLENDVAR '\203'
493 #define CTLBACKQ '\204'
494 #define CTLQUOTE 01 /* ored with CTLBACKQ code if in quotes */
495 /* CTLBACKQ | CTLQUOTE == '\205' */
496 #define CTLARI '\206' /* arithmetic expression */
497 #define CTLENDARI '\207'
498 #define CTLQUOTEMARK '\210'
500 /* variable substitution byte (follows CTLVAR) */
501 #define VSTYPE 0x0f /* type of variable substitution */
502 #define VSNUL 0x10 /* colon--treat the empty string as unset */
503 #define VSQUOTE 0x80 /* inside double quotes--suppress splitting */
505 /* values of VSTYPE field */
506 #define VSNORMAL 0x1 /* normal variable: $var or ${var} */
507 #define VSMINUS 0x2 /* ${var-text} */
508 #define VSPLUS 0x3 /* ${var+text} */
509 #define VSQUESTION 0x4 /* ${var?message} */
510 #define VSASSIGN 0x5 /* ${var=text} */
511 #define VSTRIMRIGHT 0x6 /* ${var%pattern} */
512 #define VSTRIMRIGHTMAX 0x7 /* ${var%%pattern} */
513 #define VSTRIMLEFT 0x8 /* ${var#pattern} */
514 #define VSTRIMLEFTMAX 0x9 /* ${var##pattern} */
515 #define VSLENGTH 0xa /* ${#var} */
516 #if ENABLE_ASH_BASH_COMPAT
517 #define VSSUBSTR 0xc /* ${var:position:length} */
518 #define VSREPLACE 0xd /* ${var/pattern/replacement} */
519 #define VSREPLACEALL 0xe /* ${var//pattern/replacement} */
522 static const char dolatstr[] ALIGN1 = {
523 CTLVAR, VSNORMAL|VSQUOTE, '@', '=', '\0'
543 #if ENABLE_ASH_BASH_COMPAT
560 smallint type; /* Nxxxx */
563 union node *redirect;
568 smallint pipe_backgnd;
569 struct nodelist *cmdlist;
575 union node *redirect;
588 union node *elsepart;
615 struct nodelist *backquote;
618 /* nfile and ndup layout must match!
619 * NTOFD (>&fdnum) uses ndup structure, but we may discover mid-flight
620 * that it is actually NTO2 (>&file), and change its type.
637 char *_unused_expfname;
656 struct nredir nredir;
657 struct nbinary nbinary;
661 struct nclist nclist;
670 struct nodelist *next;
683 freefunc(struct funcnode *f)
685 if (f && --f->count < 0)
690 /* ============ Debugging output */
694 static FILE *tracefile;
697 trace_printf(const char *fmt, ...)
704 fprintf(tracefile, "%u ", (int) time(NULL));
706 fprintf(tracefile, "[%u] ", (int) getpid());
708 fprintf(tracefile, "pending s:%d i:%d(supp:%d) ", pendingsig, intpending, suppressint);
710 vfprintf(tracefile, fmt, va);
715 trace_vprintf(const char *fmt, va_list va)
720 fprintf(tracefile, "%u ", (int) time(NULL));
722 fprintf(tracefile, "[%u] ", (int) getpid());
724 fprintf(tracefile, "pending s:%d i:%d(supp:%d) ", pendingsig, intpending, suppressint);
725 vfprintf(tracefile, fmt, va);
729 trace_puts(const char *s)
737 trace_puts_quoted(char *s)
744 putc('"', tracefile);
745 for (p = s; *p; p++) {
747 case '\n': c = 'n'; goto backslash;
748 case '\t': c = 't'; goto backslash;
749 case '\r': c = 'r'; goto backslash;
750 case '"': c = '"'; goto backslash;
751 case '\\': c = '\\'; goto backslash;
752 case CTLESC: c = 'e'; goto backslash;
753 case CTLVAR: c = 'v'; goto backslash;
754 case CTLVAR+CTLQUOTE: c = 'V'; goto backslash;
755 case CTLBACKQ: c = 'q'; goto backslash;
756 case CTLBACKQ+CTLQUOTE: c = 'Q'; goto backslash;
758 putc('\\', tracefile);
762 if (*p >= ' ' && *p <= '~')
765 putc('\\', tracefile);
766 putc(*p >> 6 & 03, tracefile);
767 putc(*p >> 3 & 07, tracefile);
768 putc(*p & 07, tracefile);
773 putc('"', tracefile);
777 trace_puts_args(char **ap)
784 trace_puts_quoted(*ap);
786 putc('\n', tracefile);
789 putc(' ', tracefile);
804 /* leave open because libedit might be using it */
807 strcpy(s, "./trace");
809 if (!freopen(s, "a", tracefile)) {
810 fprintf(stderr, "Can't re-open %s\n", s);
815 tracefile = fopen(s, "a");
816 if (tracefile == NULL) {
817 fprintf(stderr, "Can't open %s\n", s);
823 flags = fcntl(fileno(tracefile), F_GETFL);
825 fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND);
827 setlinebuf(tracefile);
828 fputs("\nTracing started.\n", tracefile);
832 indent(int amount, char *pfx, FILE *fp)
836 for (i = 0; i < amount; i++) {
837 if (pfx && i == amount - 1)
843 /* little circular references here... */
844 static void shtree(union node *n, int ind, char *pfx, FILE *fp);
847 sharg(union node *arg, FILE *fp)
850 struct nodelist *bqlist;
853 if (arg->type != NARG) {
854 out1fmt("<node type %d>\n", arg->type);
857 bqlist = arg->narg.backquote;
858 for (p = arg->narg.text; *p; p++) {
867 if (subtype == VSLENGTH)
876 switch (subtype & VSTYPE) {
909 out1fmt("<subtype %d>", subtype);
916 case CTLBACKQ|CTLQUOTE:
919 shtree(bqlist->n, -1, NULL, fp);
930 shcmd(union node *cmd, FILE *fp)
938 for (np = cmd->ncmd.args; np; np = np->narg.next) {
944 for (np = cmd->ncmd.redirect; np; np = np->nfile.next) {
948 switch (np->nfile.type) {
949 case NTO: s = ">>"+1; dftfd = 1; break;
950 case NCLOBBER: s = ">|"; dftfd = 1; break;
951 case NAPPEND: s = ">>"; dftfd = 1; break;
952 #if ENABLE_ASH_BASH_COMPAT
955 case NTOFD: s = ">&"; dftfd = 1; break;
956 case NFROM: s = "<"; break;
957 case NFROMFD: s = "<&"; break;
958 case NFROMTO: s = "<>"; break;
959 default: s = "*error*"; break;
961 if (np->nfile.fd != dftfd)
962 fprintf(fp, "%d", np->nfile.fd);
964 if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) {
965 fprintf(fp, "%d", np->ndup.dupfd);
967 sharg(np->nfile.fname, fp);
974 shtree(union node *n, int ind, char *pfx, FILE *fp)
982 indent(ind, pfx, fp);
993 shtree(n->nbinary.ch1, ind, NULL, fp);
996 shtree(n->nbinary.ch2, ind, NULL, fp);
1004 for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
1009 if (n->npipe.pipe_backgnd)
1015 fprintf(fp, "<node type %d>", n->type);
1023 showtree(union node *n)
1025 trace_puts("showtree called\n");
1026 shtree(n, 1, NULL, stdout);
1032 /* ============ Parser data */
1035 * ash_vmsg() needs parsefile->fd, hence parsefile definition is moved up.
1038 struct strlist *next;
1045 struct strpush *prev; /* preceding string on stack */
1047 int prev_left_in_line;
1048 #if ENABLE_ASH_ALIAS
1049 struct alias *ap; /* if push was associated with an alias */
1051 char *string; /* remember the string since it may change */
1055 struct parsefile *prev; /* preceding file on stack */
1056 int linno; /* current line */
1057 int fd; /* file descriptor (or -1 if string) */
1058 int left_in_line; /* number of chars left in this line */
1059 int left_in_buffer; /* number of chars left in this buffer past the line */
1060 char *next_to_pgetc; /* next char in buffer */
1061 char *buf; /* input buffer */
1062 struct strpush *strpush; /* for pushing strings at this level */
1063 struct strpush basestrpush; /* so pushing one is fast */
1066 static struct parsefile basepf; /* top level input file */
1067 static struct parsefile *g_parsefile = &basepf; /* current input file */
1068 static int startlinno; /* line # where last token started */
1069 static char *commandname; /* currently executing command */
1070 static struct strlist *cmdenviron; /* environment for builtin command */
1071 static uint8_t exitstatus; /* exit status of last command */
1074 /* ============ Message printing */
1077 ash_vmsg(const char *msg, va_list ap)
1079 fprintf(stderr, "%s: ", arg0);
1081 if (strcmp(arg0, commandname))
1082 fprintf(stderr, "%s: ", commandname);
1083 if (!iflag || g_parsefile->fd)
1084 fprintf(stderr, "line %d: ", startlinno);
1086 vfprintf(stderr, msg, ap);
1087 outcslow('\n', stderr);
1091 * Exverror is called to raise the error exception. If the second argument
1092 * is not NULL then error prints an error message using printf style
1093 * formatting. It then raises the error exception.
1095 static void ash_vmsg_and_raise(int, const char *, va_list) NORETURN;
1097 ash_vmsg_and_raise(int cond, const char *msg, va_list ap)
1101 TRACE(("ash_vmsg_and_raise(%d, \"", cond));
1103 TRACE(("\") pid=%d\n", getpid()));
1105 TRACE(("ash_vmsg_and_raise(%d, NULL) pid=%d\n", cond, getpid()));
1110 flush_stdout_stderr();
1111 raise_exception(cond);
1115 static void ash_msg_and_raise_error(const char *, ...) NORETURN;
1117 ash_msg_and_raise_error(const char *msg, ...)
1122 ash_vmsg_and_raise(EXERROR, msg, ap);
1127 static void ash_msg_and_raise(int, const char *, ...) NORETURN;
1129 ash_msg_and_raise(int cond, const char *msg, ...)
1134 ash_vmsg_and_raise(cond, msg, ap);
1140 * error/warning routines for external builtins
1143 ash_msg(const char *fmt, ...)
1153 * Return a string describing an error. The returned string may be a
1154 * pointer to a static buffer that will be overwritten on the next call.
1155 * Action describes the operation that got the error.
1158 errmsg(int e, const char *em)
1160 if (e == ENOENT || e == ENOTDIR) {
1167 /* ============ Memory allocation */
1170 * It appears that grabstackstr() will barf with such alignments
1171 * because stalloc() will return a string allocated in a new stackblock.
1173 #define SHELL_ALIGN(nbytes) (((nbytes) + SHELL_SIZE) & ~SHELL_SIZE)
1175 /* Most machines require the value returned from malloc to be aligned
1176 * in some way. The following macro will get this right
1177 * on many machines. */
1178 SHELL_SIZE = sizeof(union {int i; char *cp; double d; }) - 1,
1179 /* Minimum size of a block */
1180 MINSIZE = SHELL_ALIGN(504),
1183 struct stack_block {
1184 struct stack_block *prev;
1185 char space[MINSIZE];
1189 struct stack_block *stackp;
1192 struct stackmark *marknext;
1196 struct globals_memstack {
1197 struct stack_block *g_stackp; // = &stackbase;
1198 struct stackmark *markp;
1199 char *g_stacknxt; // = stackbase.space;
1200 char *sstrend; // = stackbase.space + MINSIZE;
1201 size_t g_stacknleft; // = MINSIZE;
1202 int herefd; // = -1;
1203 struct stack_block stackbase;
1205 extern struct globals_memstack *const ash_ptr_to_globals_memstack;
1206 #define G_memstack (*ash_ptr_to_globals_memstack)
1207 #define g_stackp (G_memstack.g_stackp )
1208 #define markp (G_memstack.markp )
1209 #define g_stacknxt (G_memstack.g_stacknxt )
1210 #define sstrend (G_memstack.sstrend )
1211 #define g_stacknleft (G_memstack.g_stacknleft)
1212 #define herefd (G_memstack.herefd )
1213 #define stackbase (G_memstack.stackbase )
1214 #define INIT_G_memstack() do { \
1215 (*(struct globals_memstack**)&ash_ptr_to_globals_memstack) = xzalloc(sizeof(G_memstack)); \
1217 g_stackp = &stackbase; \
1218 g_stacknxt = stackbase.space; \
1219 g_stacknleft = MINSIZE; \
1220 sstrend = stackbase.space + MINSIZE; \
1224 #define stackblock() ((void *)g_stacknxt)
1225 #define stackblocksize() g_stacknleft
1229 ckrealloc(void * p, size_t nbytes)
1231 p = realloc(p, nbytes);
1233 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1238 ckmalloc(size_t nbytes)
1240 return ckrealloc(NULL, nbytes);
1244 ckzalloc(size_t nbytes)
1246 return memset(ckmalloc(nbytes), 0, nbytes);
1250 * Make a copy of a string in safe storage.
1253 ckstrdup(const char *s)
1255 char *p = strdup(s);
1257 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1262 * Parse trees for commands are allocated in lifo order, so we use a stack
1263 * to make this more efficient, and also to avoid all sorts of exception
1264 * handling code to handle interrupts in the middle of a parse.
1266 * The size 504 was chosen because the Ultrix malloc handles that size
1270 stalloc(size_t nbytes)
1275 aligned = SHELL_ALIGN(nbytes);
1276 if (aligned > g_stacknleft) {
1279 struct stack_block *sp;
1281 blocksize = aligned;
1282 if (blocksize < MINSIZE)
1283 blocksize = MINSIZE;
1284 len = sizeof(struct stack_block) - MINSIZE + blocksize;
1285 if (len < blocksize)
1286 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1289 sp->prev = g_stackp;
1290 g_stacknxt = sp->space;
1291 g_stacknleft = blocksize;
1292 sstrend = g_stacknxt + blocksize;
1297 g_stacknxt += aligned;
1298 g_stacknleft -= aligned;
1303 stzalloc(size_t nbytes)
1305 return memset(stalloc(nbytes), 0, nbytes);
1312 if (!p || (g_stacknxt < (char *)p) || ((char *)p < g_stackp->space)) {
1313 write(STDERR_FILENO, "stunalloc\n", 10);
1317 g_stacknleft += g_stacknxt - (char *)p;
1322 * Like strdup but works with the ash stack.
1325 ststrdup(const char *p)
1327 size_t len = strlen(p) + 1;
1328 return memcpy(stalloc(len), p, len);
1332 setstackmark(struct stackmark *mark)
1334 mark->stackp = g_stackp;
1335 mark->stacknxt = g_stacknxt;
1336 mark->stacknleft = g_stacknleft;
1337 mark->marknext = markp;
1342 popstackmark(struct stackmark *mark)
1344 struct stack_block *sp;
1350 markp = mark->marknext;
1351 while (g_stackp != mark->stackp) {
1353 g_stackp = sp->prev;
1356 g_stacknxt = mark->stacknxt;
1357 g_stacknleft = mark->stacknleft;
1358 sstrend = mark->stacknxt + mark->stacknleft;
1363 * When the parser reads in a string, it wants to stick the string on the
1364 * stack and only adjust the stack pointer when it knows how big the
1365 * string is. Stackblock (defined in stack.h) returns a pointer to a block
1366 * of space on top of the stack and stackblocklen returns the length of
1367 * this block. Growstackblock will grow this space by at least one byte,
1368 * possibly moving it (like realloc). Grabstackblock actually allocates the
1369 * part of the block that has been used.
1372 growstackblock(void)
1376 newlen = g_stacknleft * 2;
1377 if (newlen < g_stacknleft)
1378 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1382 if (g_stacknxt == g_stackp->space && g_stackp != &stackbase) {
1383 struct stack_block *oldstackp;
1384 struct stackmark *xmark;
1385 struct stack_block *sp;
1386 struct stack_block *prevstackp;
1390 oldstackp = g_stackp;
1392 prevstackp = sp->prev;
1393 grosslen = newlen + sizeof(struct stack_block) - MINSIZE;
1394 sp = ckrealloc(sp, grosslen);
1395 sp->prev = prevstackp;
1397 g_stacknxt = sp->space;
1398 g_stacknleft = newlen;
1399 sstrend = sp->space + newlen;
1402 * Stack marks pointing to the start of the old block
1403 * must be relocated to point to the new block
1406 while (xmark != NULL && xmark->stackp == oldstackp) {
1407 xmark->stackp = g_stackp;
1408 xmark->stacknxt = g_stacknxt;
1409 xmark->stacknleft = g_stacknleft;
1410 xmark = xmark->marknext;
1414 char *oldspace = g_stacknxt;
1415 size_t oldlen = g_stacknleft;
1416 char *p = stalloc(newlen);
1418 /* free the space we just allocated */
1419 g_stacknxt = memcpy(p, oldspace, oldlen);
1420 g_stacknleft += newlen;
1425 grabstackblock(size_t len)
1427 len = SHELL_ALIGN(len);
1429 g_stacknleft -= len;
1433 * The following routines are somewhat easier to use than the above.
1434 * The user declares a variable of type STACKSTR, which may be declared
1435 * to be a register. The macro STARTSTACKSTR initializes things. Then
1436 * the user uses the macro STPUTC to add characters to the string. In
1437 * effect, STPUTC(c, p) is the same as *p++ = c except that the stack is
1438 * grown as necessary. When the user is done, she can just leave the
1439 * string there and refer to it using stackblock(). Or she can allocate
1440 * the space for it using grabstackstr(). If it is necessary to allow
1441 * someone else to use the stack temporarily and then continue to grow
1442 * the string, the user should use grabstack to allocate the space, and
1443 * then call ungrabstr(p) to return to the previous mode of operation.
1445 * USTPUTC is like STPUTC except that it doesn't check for overflow.
1446 * CHECKSTACKSPACE can be called before USTPUTC to ensure that there
1447 * is space for at least one character.
1452 size_t len = stackblocksize();
1453 if (herefd >= 0 && len >= 1024) {
1454 full_write(herefd, stackblock(), len);
1455 return stackblock();
1458 return (char *)stackblock() + len;
1462 * Called from CHECKSTRSPACE.
1465 makestrspace(size_t newlen, char *p)
1467 size_t len = p - g_stacknxt;
1468 size_t size = stackblocksize();
1473 size = stackblocksize();
1475 if (nleft >= newlen)
1479 return (char *)stackblock() + len;
1483 stack_nputstr(const char *s, size_t n, char *p)
1485 p = makestrspace(n, p);
1486 p = (char *)memcpy(p, s, n) + n;
1491 stack_putstr(const char *s, char *p)
1493 return stack_nputstr(s, strlen(s), p);
1497 _STPUTC(int c, char *p)
1505 #define STARTSTACKSTR(p) ((p) = stackblock())
1506 #define STPUTC(c, p) ((p) = _STPUTC((c), (p)))
1507 #define CHECKSTRSPACE(n, p) do { \
1510 size_t m = sstrend - q; \
1512 (p) = makestrspace(l, q); \
1514 #define USTPUTC(c, p) (*(p)++ = (c))
1515 #define STACKSTRNUL(p) do { \
1516 if ((p) == sstrend) \
1517 (p) = growstackstr(); \
1520 #define STUNPUTC(p) (--(p))
1521 #define STTOPC(p) ((p)[-1])
1522 #define STADJUST(amount, p) ((p) += (amount))
1524 #define grabstackstr(p) stalloc((char *)(p) - (char *)stackblock())
1525 #define ungrabstackstr(s, p) stunalloc(s)
1526 #define stackstrend() ((void *)sstrend)
1529 /* ============ String helpers */
1532 * prefix -- see if pfx is a prefix of string.
1535 prefix(const char *string, const char *pfx)
1538 if (*pfx++ != *string++)
1541 return (char *) string;
1545 * Check for a valid number. This should be elsewhere.
1548 is_number(const char *p)
1553 } while (*++p != '\0');
1558 * Convert a string of digits to an integer, printing an error message on
1562 number(const char *s)
1565 ash_msg_and_raise_error(illnum, s);
1570 * Produce a possibly single quoted string suitable as input to the shell.
1571 * The return string is allocated on the stack.
1574 single_quote(const char *s)
1584 len = strchrnul(s, '\'') - s;
1586 q = p = makestrspace(len + 3, p);
1589 q = (char *)memcpy(q, s, len) + len;
1595 len = strspn(s, "'");
1599 q = p = makestrspace(len + 3, p);
1602 q = (char *)memcpy(q, s, len) + len;
1611 return stackblock();
1615 /* ============ nextopt */
1617 static char **argptr; /* argument list for builtin commands */
1618 static char *optionarg; /* set by nextopt (like getopt) */
1619 static char *optptr; /* used by nextopt */
1622 * XXX - should get rid of. Have all builtins use getopt(3).
1623 * The library getopt must have the BSD extension static variable
1624 * "optreset", otherwise it can't be used within the shell safely.
1626 * Standard option processing (a la getopt) for builtin routines.
1627 * The only argument that is passed to nextopt is the option string;
1628 * the other arguments are unnecessary. It returns the character,
1629 * or '\0' on end of input.
1632 nextopt(const char *optstring)
1639 if (p == NULL || *p == '\0') {
1640 /* We ate entire "-param", take next one */
1646 if (*++p == '\0') /* just "-" ? */
1649 if (LONE_DASH(p)) /* "--" ? */
1651 /* p => next "-param" */
1653 /* p => some option char in the middle of a "-param" */
1655 for (q = optstring; *q != c;) {
1657 ash_msg_and_raise_error("illegal option -%c", c);
1665 ash_msg_and_raise_error("no arg for -%c option", c);
1675 /* ============ Shell variables */
1678 * The parsefile structure pointed to by the global variable parsefile
1679 * contains information about the current file being read.
1682 int nparam; /* # of positional parameters (without $0) */
1683 #if ENABLE_ASH_GETOPTS
1684 int optind; /* next parameter to be processed by getopts */
1685 int optoff; /* used by getopts */
1687 unsigned char malloced; /* if parameter list dynamically allocated */
1688 char **p; /* parameter list */
1692 * Free the list of positional parameters.
1695 freeparam(volatile struct shparam *param)
1697 if (param->malloced) {
1699 ap = ap1 = param->p;
1706 #if ENABLE_ASH_GETOPTS
1707 static void getoptsreset(const char *value);
1711 struct var *next; /* next entry in hash list */
1712 int flags; /* flags are defined above */
1713 const char *text; /* name=value */
1714 void (*func)(const char *); /* function to be called when */
1715 /* the variable gets set/unset */
1719 struct localvar *next; /* next local variable in list */
1720 struct var *vp; /* the variable that was made local */
1721 int flags; /* saved flags */
1722 const char *text; /* saved text */
1726 #define VEXPORT 0x01 /* variable is exported */
1727 #define VREADONLY 0x02 /* variable cannot be modified */
1728 #define VSTRFIXED 0x04 /* variable struct is statically allocated */
1729 #define VTEXTFIXED 0x08 /* text is statically allocated */
1730 #define VSTACK 0x10 /* text is allocated on the stack */
1731 #define VUNSET 0x20 /* the variable is not set */
1732 #define VNOFUNC 0x40 /* don't call the callback function */
1733 #define VNOSET 0x80 /* do not set variable - just readonly test */
1734 #define VNOSAVE 0x100 /* when text is on the heap before setvareq */
1735 #if ENABLE_ASH_RANDOM_SUPPORT
1736 # define VDYNAMIC 0x200 /* dynamic variable */
1742 static const char defifsvar[] ALIGN1 = "IFS= \t\n";
1743 #define defifs (defifsvar + 4)
1745 static const char defifs[] ALIGN1 = " \t\n";
1749 /* Need to be before varinit_data[] */
1750 #if ENABLE_LOCALE_SUPPORT
1752 change_lc_all(const char *value)
1754 if (value && *value != '\0')
1755 setlocale(LC_ALL, value);
1758 change_lc_ctype(const char *value)
1760 if (value && *value != '\0')
1761 setlocale(LC_CTYPE, value);
1765 static void chkmail(void);
1766 static void changemail(const char *);
1768 static void changepath(const char *);
1769 #if ENABLE_ASH_RANDOM_SUPPORT
1770 static void change_random(const char *);
1773 static const struct {
1776 void (*func)(const char *);
1777 } varinit_data[] = {
1779 { VSTRFIXED|VTEXTFIXED , defifsvar , NULL },
1781 { VSTRFIXED|VTEXTFIXED|VUNSET, "IFS\0" , NULL },
1784 { VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL\0" , changemail },
1785 { VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH\0", changemail },
1787 { VSTRFIXED|VTEXTFIXED , bb_PATH_root_path, changepath },
1788 { VSTRFIXED|VTEXTFIXED , "PS1=$ " , NULL },
1789 { VSTRFIXED|VTEXTFIXED , "PS2=> " , NULL },
1790 { VSTRFIXED|VTEXTFIXED , "PS4=+ " , NULL },
1791 #if ENABLE_ASH_GETOPTS
1792 { VSTRFIXED|VTEXTFIXED , "OPTIND=1" , getoptsreset },
1794 #if ENABLE_ASH_RANDOM_SUPPORT
1795 { VSTRFIXED|VTEXTFIXED|VUNSET|VDYNAMIC, "RANDOM\0", change_random },
1797 #if ENABLE_LOCALE_SUPPORT
1798 { VSTRFIXED|VTEXTFIXED|VUNSET, "LC_ALL\0" , change_lc_all },
1799 { VSTRFIXED|VTEXTFIXED|VUNSET, "LC_CTYPE\0", change_lc_ctype },
1801 #if ENABLE_FEATURE_EDITING_SAVEHISTORY
1802 { VSTRFIXED|VTEXTFIXED|VUNSET, "HISTFILE\0", NULL },
1808 struct globals_var {
1809 struct shparam shellparam; /* $@ current positional parameters */
1810 struct redirtab *redirlist;
1812 int preverrout_fd; /* save fd2 before print debug if xflag is set. */
1813 struct var *vartab[VTABSIZE];
1814 struct var varinit[ARRAY_SIZE(varinit_data)];
1816 extern struct globals_var *const ash_ptr_to_globals_var;
1817 #define G_var (*ash_ptr_to_globals_var)
1818 #define shellparam (G_var.shellparam )
1819 //#define redirlist (G_var.redirlist )
1820 #define g_nullredirs (G_var.g_nullredirs )
1821 #define preverrout_fd (G_var.preverrout_fd)
1822 #define vartab (G_var.vartab )
1823 #define varinit (G_var.varinit )
1824 #define INIT_G_var() do { \
1826 (*(struct globals_var**)&ash_ptr_to_globals_var) = xzalloc(sizeof(G_var)); \
1828 for (i = 0; i < ARRAY_SIZE(varinit_data); i++) { \
1829 varinit[i].flags = varinit_data[i].flags; \
1830 varinit[i].text = varinit_data[i].text; \
1831 varinit[i].func = varinit_data[i].func; \
1835 #define vifs varinit[0]
1837 # define vmail (&vifs)[1]
1838 # define vmpath (&vmail)[1]
1839 # define vpath (&vmpath)[1]
1841 # define vpath (&vifs)[1]
1843 #define vps1 (&vpath)[1]
1844 #define vps2 (&vps1)[1]
1845 #define vps4 (&vps2)[1]
1846 #if ENABLE_ASH_GETOPTS
1847 # define voptind (&vps4)[1]
1848 # if ENABLE_ASH_RANDOM_SUPPORT
1849 # define vrandom (&voptind)[1]
1852 # if ENABLE_ASH_RANDOM_SUPPORT
1853 # define vrandom (&vps4)[1]
1858 * The following macros access the values of the above variables.
1859 * They have to skip over the name. They return the null string
1860 * for unset variables.
1862 #define ifsval() (vifs.text + 4)
1863 #define ifsset() ((vifs.flags & VUNSET) == 0)
1865 # define mailval() (vmail.text + 5)
1866 # define mpathval() (vmpath.text + 9)
1867 # define mpathset() ((vmpath.flags & VUNSET) == 0)
1869 #define pathval() (vpath.text + 5)
1870 #define ps1val() (vps1.text + 4)
1871 #define ps2val() (vps2.text + 4)
1872 #define ps4val() (vps4.text + 4)
1873 #if ENABLE_ASH_GETOPTS
1874 # define optindval() (voptind.text + 7)
1878 #define is_name(c) ((c) == '_' || isalpha((unsigned char)(c)))
1879 #define is_in_name(c) ((c) == '_' || isalnum((unsigned char)(c)))
1881 #if ENABLE_ASH_GETOPTS
1883 getoptsreset(const char *value)
1885 shellparam.optind = number(value);
1886 shellparam.optoff = -1;
1891 * Return of a legal variable name (a letter or underscore followed by zero or
1892 * more letters, underscores, and digits).
1895 endofname(const char *name)
1903 if (!is_in_name(*p))
1910 * Compares two strings up to the first = or '\0'. The first
1911 * string must be terminated by '='; the second may be terminated by
1912 * either '=' or '\0'.
1915 varcmp(const char *p, const char *q)
1919 while ((c = *p) == (d = *q)) {
1934 varequal(const char *a, const char *b)
1936 return !varcmp(a, b);
1940 * Find the appropriate entry in the hash table from the name.
1942 static struct var **
1943 hashvar(const char *p)
1947 hashval = ((unsigned char) *p) << 4;
1948 while (*p && *p != '=')
1949 hashval += (unsigned char) *p++;
1950 return &vartab[hashval % VTABSIZE];
1954 vpcmp(const void *a, const void *b)
1956 return varcmp(*(const char **)a, *(const char **)b);
1960 * This routine initializes the builtin variables.
1970 * PS1 depends on uid
1972 #if ENABLE_FEATURE_EDITING && ENABLE_FEATURE_EDITING_FANCY_PROMPT
1973 vps1.text = "PS1=\\w \\$ ";
1976 vps1.text = "PS1=# ";
1979 end = vp + ARRAY_SIZE(varinit);
1981 vpp = hashvar(vp->text);
1984 } while (++vp < end);
1987 static struct var **
1988 findvar(struct var **vpp, const char *name)
1990 for (; *vpp; vpp = &(*vpp)->next) {
1991 if (varequal((*vpp)->text, name)) {
1999 * Find the value of a variable. Returns NULL if not set.
2002 lookupvar(const char *name)
2006 v = *findvar(hashvar(name), name);
2008 #if ENABLE_ASH_RANDOM_SUPPORT
2010 * Dynamic variables are implemented roughly the same way they are
2011 * in bash. Namely, they're "special" so long as they aren't unset.
2012 * As soon as they're unset, they're no longer dynamic, and dynamic
2013 * lookup will no longer happen at that point. -- PFM.
2015 if ((v->flags & VDYNAMIC))
2018 if (!(v->flags & VUNSET))
2019 return strchrnul(v->text, '=') + 1;
2025 * Search the environment of a builtin command.
2028 bltinlookup(const char *name)
2032 for (sp = cmdenviron; sp; sp = sp->next) {
2033 if (varequal(sp->text, name))
2034 return strchrnul(sp->text, '=') + 1;
2036 return lookupvar(name);
2040 * Same as setvar except that the variable and value are passed in
2041 * the first argument as name=value. Since the first argument will
2042 * be actually stored in the table, it should not be a string that
2044 * Called with interrupts off.
2047 setvareq(char *s, int flags)
2049 struct var *vp, **vpp;
2052 flags |= (VEXPORT & (((unsigned) (1 - aflag)) - 1));
2053 vp = *findvar(vpp, s);
2055 if ((vp->flags & (VREADONLY|VDYNAMIC)) == VREADONLY) {
2058 if (flags & VNOSAVE)
2061 ash_msg_and_raise_error("%.*s: is read only", strchrnul(n, '=') - n, n);
2067 if (vp->func && (flags & VNOFUNC) == 0)
2068 (*vp->func)(strchrnul(s, '=') + 1);
2070 if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
2071 free((char*)vp->text);
2073 flags |= vp->flags & ~(VTEXTFIXED|VSTACK|VNOSAVE|VUNSET);
2078 vp = ckzalloc(sizeof(*vp));
2080 /*vp->func = NULL; - ckzalloc did it */
2083 if (!(flags & (VTEXTFIXED|VSTACK|VNOSAVE)))
2090 * Set the value of a variable. The flags argument is ored with the
2091 * flags of the variable. If val is NULL, the variable is unset.
2094 setvar(const char *name, const char *val, int flags)
2101 q = endofname(name);
2102 p = strchrnul(q, '=');
2104 if (!namelen || p != q)
2105 ash_msg_and_raise_error("%.*s: bad variable name", namelen, name);
2110 vallen = strlen(val);
2113 nameeq = ckmalloc(namelen + vallen + 2);
2114 p = (char *)memcpy(nameeq, name, namelen) + namelen;
2117 p = (char *)memcpy(p, val, vallen) + vallen;
2120 setvareq(nameeq, flags | VNOSAVE);
2124 #if ENABLE_ASH_GETOPTS
2126 * Safe version of setvar, returns 1 on success 0 on failure.
2129 setvarsafe(const char *name, const char *val, int flags)
2132 volatile int saveint;
2133 struct jmploc *volatile savehandler = exception_handler;
2134 struct jmploc jmploc;
2137 if (setjmp(jmploc.loc))
2140 exception_handler = &jmploc;
2141 setvar(name, val, flags);
2144 exception_handler = savehandler;
2145 RESTORE_INT(saveint);
2151 * Unset the specified variable.
2154 unsetvar(const char *s)
2160 vpp = findvar(hashvar(s), s);
2164 int flags = vp->flags;
2167 if (flags & VREADONLY)
2169 #if ENABLE_ASH_RANDOM_SUPPORT
2170 vp->flags &= ~VDYNAMIC;
2174 if ((flags & VSTRFIXED) == 0) {
2176 if ((flags & (VTEXTFIXED|VSTACK)) == 0)
2177 free((char*)vp->text);
2183 vp->flags &= ~VEXPORT;
2193 * Process a linked list of variable assignments.
2196 listsetvar(struct strlist *list_set_var, int flags)
2198 struct strlist *lp = list_set_var;
2204 setvareq(lp->text, flags);
2211 * Generate a list of variables satisfying the given conditions.
2214 listvars(int on, int off, char ***end)
2225 for (vp = *vpp; vp; vp = vp->next) {
2226 if ((vp->flags & mask) == on) {
2227 if (ep == stackstrend())
2228 ep = growstackstr();
2229 *ep++ = (char *) vp->text;
2232 } while (++vpp < vartab + VTABSIZE);
2233 if (ep == stackstrend())
2234 ep = growstackstr();
2238 return grabstackstr(ep);
2242 /* ============ Path search helper
2244 * The variable path (passed by reference) should be set to the start
2245 * of the path before the first call; padvance will update
2246 * this value as it proceeds. Successive calls to padvance will return
2247 * the possible path expansions in sequence. If an option (indicated by
2248 * a percent sign) appears in the path entry then the global variable
2249 * pathopt will be set to point to it; otherwise pathopt will be set to
2252 static const char *pathopt; /* set by padvance */
2255 padvance(const char **path, const char *name)
2265 for (p = start; *p && *p != ':' && *p != '%'; p++)
2267 len = p - start + strlen(name) + 2; /* "2" is for '/' and '\0' */
2268 while (stackblocksize() < len)
2272 memcpy(q, start, p - start);
2280 while (*p && *p != ':')
2287 return stalloc(len);
2291 /* ============ Prompt */
2293 static smallint doprompt; /* if set, prompt the user */
2294 static smallint needprompt; /* true if interactive and at start of line */
2296 #if ENABLE_FEATURE_EDITING
2297 static line_input_t *line_input_state;
2298 static const char *cmdedit_prompt;
2300 putprompt(const char *s)
2302 if (ENABLE_ASH_EXPAND_PRMT) {
2303 free((char*)cmdedit_prompt);
2304 cmdedit_prompt = ckstrdup(s);
2311 putprompt(const char *s)
2317 #if ENABLE_ASH_EXPAND_PRMT
2318 /* expandstr() needs parsing machinery, so it is far away ahead... */
2319 static const char *expandstr(const char *ps);
2321 #define expandstr(s) s
2325 setprompt(int whichprompt)
2328 #if ENABLE_ASH_EXPAND_PRMT
2329 struct stackmark smark;
2334 switch (whichprompt) {
2344 #if ENABLE_ASH_EXPAND_PRMT
2345 setstackmark(&smark);
2346 stalloc(stackblocksize());
2348 putprompt(expandstr(prompt));
2349 #if ENABLE_ASH_EXPAND_PRMT
2350 popstackmark(&smark);
2355 /* ============ The cd and pwd commands */
2357 #define CD_PHYSICAL 1
2360 static int docd(const char *, int);
2369 while ((i = nextopt("LP"))) {
2371 flags ^= CD_PHYSICAL;
2380 * Update curdir (the name of the current directory) in response to a
2384 updatepwd(const char *dir)
2391 cdcomppath = ststrdup(dir);
2394 if (curdir == nullstr)
2396 new = stack_putstr(curdir, new);
2398 new = makestrspace(strlen(dir) + 2, new);
2399 lim = (char *)stackblock() + 1;
2403 if (new > lim && *lim == '/')
2408 if (dir[1] == '/' && dir[2] != '/') {
2414 p = strtok(cdcomppath, "/");
2418 if (p[1] == '.' && p[2] == '\0') {
2430 new = stack_putstr(p, new);
2438 return stackblock();
2442 * Find out what the current directory is. If we already know the current
2443 * directory, this routine returns immediately.
2448 char *dir = getcwd(NULL, 0); /* huh, using glibc extension? */
2449 return dir ? dir : nullstr;
2453 setpwd(const char *val, int setold)
2457 oldcur = dir = curdir;
2460 setvar("OLDPWD", oldcur, VEXPORT);
2463 if (physdir != nullstr) {
2464 if (physdir != oldcur)
2468 if (oldcur == val || !val) {
2474 dir = ckstrdup(val);
2475 if (oldcur != dir && oldcur != nullstr) {
2480 setvar("PWD", dir, VEXPORT);
2483 static void hashcd(void);
2486 * Actually do the chdir. We also call hashcd to let the routines in exec.c
2487 * know that the current directory has changed.
2490 docd(const char *dest, int flags)
2492 const char *dir = 0;
2495 TRACE(("docd(\"%s\", %d) called\n", dest, flags));
2498 if (!(flags & CD_PHYSICAL)) {
2499 dir = updatepwd(dest);
2514 cdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
2526 dest = bltinlookup(homestr);
2527 else if (LONE_DASH(dest)) {
2528 dest = bltinlookup("OLDPWD");
2550 path = bltinlookup("CDPATH");
2559 p = padvance(&path, dest);
2560 if (stat(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) {
2564 if (!docd(p, flags))
2569 ash_msg_and_raise_error("can't cd to %s", dest);
2572 if (flags & CD_PRINT)
2573 out1fmt(snlfmt, curdir);
2578 pwdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
2581 const char *dir = curdir;
2585 if (physdir == nullstr)
2589 out1fmt(snlfmt, dir);
2594 /* ============ ... */
2597 #define IBUFSIZ COMMON_BUFSIZE
2598 /* buffer for top level input file */
2599 #define basebuf bb_common_bufsiz1
2601 /* Syntax classes */
2602 #define CWORD 0 /* character is nothing special */
2603 #define CNL 1 /* newline character */
2604 #define CBACK 2 /* a backslash character */
2605 #define CSQUOTE 3 /* single quote */
2606 #define CDQUOTE 4 /* double quote */
2607 #define CENDQUOTE 5 /* a terminating quote */
2608 #define CBQUOTE 6 /* backwards single quote */
2609 #define CVAR 7 /* a dollar sign */
2610 #define CENDVAR 8 /* a '}' character */
2611 #define CLP 9 /* a left paren in arithmetic */
2612 #define CRP 10 /* a right paren in arithmetic */
2613 #define CENDFILE 11 /* end of file */
2614 #define CCTL 12 /* like CWORD, except it must be escaped */
2615 #define CSPCL 13 /* these terminate a word */
2616 #define CIGN 14 /* character should be ignored */
2618 #if ENABLE_ASH_ALIAS
2622 #define PEOA_OR_PEOF PEOA
2626 #define PEOA_OR_PEOF PEOF
2629 /* number syntax index */
2630 #define BASESYNTAX 0 /* not in quotes */
2631 #define DQSYNTAX 1 /* in double quotes */
2632 #define SQSYNTAX 2 /* in single quotes */
2633 #define ARISYNTAX 3 /* in arithmetic */
2634 #define PSSYNTAX 4 /* prompt */
2636 #if ENABLE_ASH_OPTIMIZE_FOR_SIZE
2637 #define USE_SIT_FUNCTION
2640 #if ENABLE_ASH_MATH_SUPPORT
2641 static const char S_I_T[][4] = {
2642 #if ENABLE_ASH_ALIAS
2643 { CSPCL, CIGN, CIGN, CIGN }, /* 0, PEOA */
2645 { CSPCL, CWORD, CWORD, CWORD }, /* 1, ' ' */
2646 { CNL, CNL, CNL, CNL }, /* 2, \n */
2647 { CWORD, CCTL, CCTL, CWORD }, /* 3, !*-/:=?[]~ */
2648 { CDQUOTE, CENDQUOTE, CWORD, CWORD }, /* 4, '"' */
2649 { CVAR, CVAR, CWORD, CVAR }, /* 5, $ */
2650 { CSQUOTE, CWORD, CENDQUOTE, CWORD }, /* 6, "'" */
2651 { CSPCL, CWORD, CWORD, CLP }, /* 7, ( */
2652 { CSPCL, CWORD, CWORD, CRP }, /* 8, ) */
2653 { CBACK, CBACK, CCTL, CBACK }, /* 9, \ */
2654 { CBQUOTE, CBQUOTE, CWORD, CBQUOTE }, /* 10, ` */
2655 { CENDVAR, CENDVAR, CWORD, CENDVAR }, /* 11, } */
2656 #ifndef USE_SIT_FUNCTION
2657 { CENDFILE, CENDFILE, CENDFILE, CENDFILE }, /* 12, PEOF */
2658 { CWORD, CWORD, CWORD, CWORD }, /* 13, 0-9A-Za-z */
2659 { CCTL, CCTL, CCTL, CCTL } /* 14, CTLESC ... */
2663 static const char S_I_T[][3] = {
2664 #if ENABLE_ASH_ALIAS
2665 { CSPCL, CIGN, CIGN }, /* 0, PEOA */
2667 { CSPCL, CWORD, CWORD }, /* 1, ' ' */
2668 { CNL, CNL, CNL }, /* 2, \n */
2669 { CWORD, CCTL, CCTL }, /* 3, !*-/:=?[]~ */
2670 { CDQUOTE, CENDQUOTE, CWORD }, /* 4, '"' */
2671 { CVAR, CVAR, CWORD }, /* 5, $ */
2672 { CSQUOTE, CWORD, CENDQUOTE }, /* 6, "'" */
2673 { CSPCL, CWORD, CWORD }, /* 7, ( */
2674 { CSPCL, CWORD, CWORD }, /* 8, ) */
2675 { CBACK, CBACK, CCTL }, /* 9, \ */
2676 { CBQUOTE, CBQUOTE, CWORD }, /* 10, ` */
2677 { CENDVAR, CENDVAR, CWORD }, /* 11, } */
2678 #ifndef USE_SIT_FUNCTION
2679 { CENDFILE, CENDFILE, CENDFILE }, /* 12, PEOF */
2680 { CWORD, CWORD, CWORD }, /* 13, 0-9A-Za-z */
2681 { CCTL, CCTL, CCTL } /* 14, CTLESC ... */
2684 #endif /* ASH_MATH_SUPPORT */
2686 #ifdef USE_SIT_FUNCTION
2689 SIT(int c, int syntax)
2691 static const char spec_symbls[] ALIGN1 = "\t\n !\"$&'()*-/:;<=>?[\\]`|}~";
2692 #if ENABLE_ASH_ALIAS
2693 static const char syntax_index_table[] ALIGN1 = {
2694 1, 2, 1, 3, 4, 5, 1, 6, /* "\t\n !\"$&'" */
2695 7, 8, 3, 3, 3, 3, 1, 1, /* "()*-/:;<" */
2696 3, 1, 3, 3, 9, 3, 10, 1, /* "=>?[\\]`|" */
2700 static const char syntax_index_table[] ALIGN1 = {
2701 0, 1, 0, 2, 3, 4, 0, 5, /* "\t\n !\"$&'" */
2702 6, 7, 2, 2, 2, 2, 0, 0, /* "()*-/:;<" */
2703 2, 0, 2, 2, 8, 2, 9, 0, /* "=>?[\\]`|" */
2710 if (c == PEOF) /* 2^8+2 */
2712 #if ENABLE_ASH_ALIAS
2713 if (c == PEOA) /* 2^8+1 */
2718 if ((unsigned char)c >= (unsigned char)(CTLESC)
2719 && (unsigned char)c <= (unsigned char)(CTLQUOTEMARK)
2723 s = strchrnul(spec_symbls, c);
2726 indx = syntax_index_table[s - spec_symbls];
2727 return S_I_T[indx][syntax];
2730 #else /* !USE_SIT_FUNCTION */
2732 #if ENABLE_ASH_ALIAS
2733 #define CSPCL_CIGN_CIGN_CIGN 0
2734 #define CSPCL_CWORD_CWORD_CWORD 1
2735 #define CNL_CNL_CNL_CNL 2
2736 #define CWORD_CCTL_CCTL_CWORD 3
2737 #define CDQUOTE_CENDQUOTE_CWORD_CWORD 4
2738 #define CVAR_CVAR_CWORD_CVAR 5
2739 #define CSQUOTE_CWORD_CENDQUOTE_CWORD 6
2740 #define CSPCL_CWORD_CWORD_CLP 7
2741 #define CSPCL_CWORD_CWORD_CRP 8
2742 #define CBACK_CBACK_CCTL_CBACK 9
2743 #define CBQUOTE_CBQUOTE_CWORD_CBQUOTE 10
2744 #define CENDVAR_CENDVAR_CWORD_CENDVAR 11
2745 #define CENDFILE_CENDFILE_CENDFILE_CENDFILE 12
2746 #define CWORD_CWORD_CWORD_CWORD 13
2747 #define CCTL_CCTL_CCTL_CCTL 14
2749 #define CSPCL_CWORD_CWORD_CWORD 0
2750 #define CNL_CNL_CNL_CNL 1
2751 #define CWORD_CCTL_CCTL_CWORD 2
2752 #define CDQUOTE_CENDQUOTE_CWORD_CWORD 3
2753 #define CVAR_CVAR_CWORD_CVAR 4
2754 #define CSQUOTE_CWORD_CENDQUOTE_CWORD 5
2755 #define CSPCL_CWORD_CWORD_CLP 6
2756 #define CSPCL_CWORD_CWORD_CRP 7
2757 #define CBACK_CBACK_CCTL_CBACK 8
2758 #define CBQUOTE_CBQUOTE_CWORD_CBQUOTE 9
2759 #define CENDVAR_CENDVAR_CWORD_CENDVAR 10
2760 #define CENDFILE_CENDFILE_CENDFILE_CENDFILE 11
2761 #define CWORD_CWORD_CWORD_CWORD 12
2762 #define CCTL_CCTL_CCTL_CCTL 13
2765 static const char syntax_index_table[258] = {
2766 /* BASESYNTAX_DQSYNTAX_SQSYNTAX_ARISYNTAX */
2767 /* 0 PEOF */ CENDFILE_CENDFILE_CENDFILE_CENDFILE,
2768 #if ENABLE_ASH_ALIAS
2769 /* 1 PEOA */ CSPCL_CIGN_CIGN_CIGN,
2771 /* 2 -128 0x80 */ CWORD_CWORD_CWORD_CWORD,
2772 /* 3 -127 CTLESC */ CCTL_CCTL_CCTL_CCTL,
2773 /* 4 -126 CTLVAR */ CCTL_CCTL_CCTL_CCTL,
2774 /* 5 -125 CTLENDVAR */ CCTL_CCTL_CCTL_CCTL,
2775 /* 6 -124 CTLBACKQ */ CCTL_CCTL_CCTL_CCTL,
2776 /* 7 -123 CTLQUOTE */ CCTL_CCTL_CCTL_CCTL,
2777 /* 8 -122 CTLARI */ CCTL_CCTL_CCTL_CCTL,
2778 /* 9 -121 CTLENDARI */ CCTL_CCTL_CCTL_CCTL,
2779 /* 10 -120 CTLQUOTEMARK */ CCTL_CCTL_CCTL_CCTL,
2780 /* 11 -119 */ CWORD_CWORD_CWORD_CWORD,
2781 /* 12 -118 */ CWORD_CWORD_CWORD_CWORD,
2782 /* 13 -117 */ CWORD_CWORD_CWORD_CWORD,
2783 /* 14 -116 */ CWORD_CWORD_CWORD_CWORD,
2784 /* 15 -115 */ CWORD_CWORD_CWORD_CWORD,
2785 /* 16 -114 */ CWORD_CWORD_CWORD_CWORD,
2786 /* 17 -113 */ CWORD_CWORD_CWORD_CWORD,
2787 /* 18 -112 */ CWORD_CWORD_CWORD_CWORD,
2788 /* 19 -111 */ CWORD_CWORD_CWORD_CWORD,
2789 /* 20 -110 */ CWORD_CWORD_CWORD_CWORD,
2790 /* 21 -109 */ CWORD_CWORD_CWORD_CWORD,
2791 /* 22 -108 */ CWORD_CWORD_CWORD_CWORD,
2792 /* 23 -107 */ CWORD_CWORD_CWORD_CWORD,
2793 /* 24 -106 */ CWORD_CWORD_CWORD_CWORD,
2794 /* 25 -105 */ CWORD_CWORD_CWORD_CWORD,
2795 /* 26 -104 */ CWORD_CWORD_CWORD_CWORD,
2796 /* 27 -103 */ CWORD_CWORD_CWORD_CWORD,
2797 /* 28 -102 */ CWORD_CWORD_CWORD_CWORD,
2798 /* 29 -101 */ CWORD_CWORD_CWORD_CWORD,
2799 /* 30 -100 */ CWORD_CWORD_CWORD_CWORD,
2800 /* 31 -99 */ CWORD_CWORD_CWORD_CWORD,
2801 /* 32 -98 */ CWORD_CWORD_CWORD_CWORD,
2802 /* 33 -97 */ CWORD_CWORD_CWORD_CWORD,
2803 /* 34 -96 */ CWORD_CWORD_CWORD_CWORD,
2804 /* 35 -95 */ CWORD_CWORD_CWORD_CWORD,
2805 /* 36 -94 */ CWORD_CWORD_CWORD_CWORD,
2806 /* 37 -93 */ CWORD_CWORD_CWORD_CWORD,
2807 /* 38 -92 */ CWORD_CWORD_CWORD_CWORD,
2808 /* 39 -91 */ CWORD_CWORD_CWORD_CWORD,
2809 /* 40 -90 */ CWORD_CWORD_CWORD_CWORD,
2810 /* 41 -89 */ CWORD_CWORD_CWORD_CWORD,
2811 /* 42 -88 */ CWORD_CWORD_CWORD_CWORD,
2812 /* 43 -87 */ CWORD_CWORD_CWORD_CWORD,
2813 /* 44 -86 */ CWORD_CWORD_CWORD_CWORD,
2814 /* 45 -85 */ CWORD_CWORD_CWORD_CWORD,
2815 /* 46 -84 */ CWORD_CWORD_CWORD_CWORD,
2816 /* 47 -83 */ CWORD_CWORD_CWORD_CWORD,
2817 /* 48 -82 */ CWORD_CWORD_CWORD_CWORD,
2818 /* 49 -81 */ CWORD_CWORD_CWORD_CWORD,
2819 /* 50 -80 */ CWORD_CWORD_CWORD_CWORD,
2820 /* 51 -79 */ CWORD_CWORD_CWORD_CWORD,
2821 /* 52 -78 */ CWORD_CWORD_CWORD_CWORD,
2822 /* 53 -77 */ CWORD_CWORD_CWORD_CWORD,
2823 /* 54 -76 */ CWORD_CWORD_CWORD_CWORD,
2824 /* 55 -75 */ CWORD_CWORD_CWORD_CWORD,
2825 /* 56 -74 */ CWORD_CWORD_CWORD_CWORD,
2826 /* 57 -73 */ CWORD_CWORD_CWORD_CWORD,
2827 /* 58 -72 */ CWORD_CWORD_CWORD_CWORD,
2828 /* 59 -71 */ CWORD_CWORD_CWORD_CWORD,
2829 /* 60 -70 */ CWORD_CWORD_CWORD_CWORD,
2830 /* 61 -69 */ CWORD_CWORD_CWORD_CWORD,
2831 /* 62 -68 */ CWORD_CWORD_CWORD_CWORD,
2832 /* 63 -67 */ CWORD_CWORD_CWORD_CWORD,
2833 /* 64 -66 */ CWORD_CWORD_CWORD_CWORD,
2834 /* 65 -65 */ CWORD_CWORD_CWORD_CWORD,
2835 /* 66 -64 */ CWORD_CWORD_CWORD_CWORD,
2836 /* 67 -63 */ CWORD_CWORD_CWORD_CWORD,
2837 /* 68 -62 */ CWORD_CWORD_CWORD_CWORD,
2838 /* 69 -61 */ CWORD_CWORD_CWORD_CWORD,
2839 /* 70 -60 */ CWORD_CWORD_CWORD_CWORD,
2840 /* 71 -59 */ CWORD_CWORD_CWORD_CWORD,
2841 /* 72 -58 */ CWORD_CWORD_CWORD_CWORD,
2842 /* 73 -57 */ CWORD_CWORD_CWORD_CWORD,
2843 /* 74 -56 */ CWORD_CWORD_CWORD_CWORD,
2844 /* 75 -55 */ CWORD_CWORD_CWORD_CWORD,
2845 /* 76 -54 */ CWORD_CWORD_CWORD_CWORD,
2846 /* 77 -53 */ CWORD_CWORD_CWORD_CWORD,
2847 /* 78 -52 */ CWORD_CWORD_CWORD_CWORD,
2848 /* 79 -51 */ CWORD_CWORD_CWORD_CWORD,
2849 /* 80 -50 */ CWORD_CWORD_CWORD_CWORD,
2850 /* 81 -49 */ CWORD_CWORD_CWORD_CWORD,
2851 /* 82 -48 */ CWORD_CWORD_CWORD_CWORD,
2852 /* 83 -47 */ CWORD_CWORD_CWORD_CWORD,
2853 /* 84 -46 */ CWORD_CWORD_CWORD_CWORD,
2854 /* 85 -45 */ CWORD_CWORD_CWORD_CWORD,
2855 /* 86 -44 */ CWORD_CWORD_CWORD_CWORD,
2856 /* 87 -43 */ CWORD_CWORD_CWORD_CWORD,
2857 /* 88 -42 */ CWORD_CWORD_CWORD_CWORD,
2858 /* 89 -41 */ CWORD_CWORD_CWORD_CWORD,
2859 /* 90 -40 */ CWORD_CWORD_CWORD_CWORD,
2860 /* 91 -39 */ CWORD_CWORD_CWORD_CWORD,
2861 /* 92 -38 */ CWORD_CWORD_CWORD_CWORD,
2862 /* 93 -37 */ CWORD_CWORD_CWORD_CWORD,
2863 /* 94 -36 */ CWORD_CWORD_CWORD_CWORD,
2864 /* 95 -35 */ CWORD_CWORD_CWORD_CWORD,
2865 /* 96 -34 */ CWORD_CWORD_CWORD_CWORD,
2866 /* 97 -33 */ CWORD_CWORD_CWORD_CWORD,
2867 /* 98 -32 */ CWORD_CWORD_CWORD_CWORD,
2868 /* 99 -31 */ CWORD_CWORD_CWORD_CWORD,
2869 /* 100 -30 */ CWORD_CWORD_CWORD_CWORD,
2870 /* 101 -29 */ CWORD_CWORD_CWORD_CWORD,
2871 /* 102 -28 */ CWORD_CWORD_CWORD_CWORD,
2872 /* 103 -27 */ CWORD_CWORD_CWORD_CWORD,
2873 /* 104 -26 */ CWORD_CWORD_CWORD_CWORD,
2874 /* 105 -25 */ CWORD_CWORD_CWORD_CWORD,
2875 /* 106 -24 */ CWORD_CWORD_CWORD_CWORD,
2876 /* 107 -23 */ CWORD_CWORD_CWORD_CWORD,
2877 /* 108 -22 */ CWORD_CWORD_CWORD_CWORD,
2878 /* 109 -21 */ CWORD_CWORD_CWORD_CWORD,
2879 /* 110 -20 */ CWORD_CWORD_CWORD_CWORD,
2880 /* 111 -19 */ CWORD_CWORD_CWORD_CWORD,
2881 /* 112 -18 */ CWORD_CWORD_CWORD_CWORD,
2882 /* 113 -17 */ CWORD_CWORD_CWORD_CWORD,
2883 /* 114 -16 */ CWORD_CWORD_CWORD_CWORD,
2884 /* 115 -15 */ CWORD_CWORD_CWORD_CWORD,
2885 /* 116 -14 */ CWORD_CWORD_CWORD_CWORD,
2886 /* 117 -13 */ CWORD_CWORD_CWORD_CWORD,
2887 /* 118 -12 */ CWORD_CWORD_CWORD_CWORD,
2888 /* 119 -11 */ CWORD_CWORD_CWORD_CWORD,
2889 /* 120 -10 */ CWORD_CWORD_CWORD_CWORD,
2890 /* 121 -9 */ CWORD_CWORD_CWORD_CWORD,
2891 /* 122 -8 */ CWORD_CWORD_CWORD_CWORD,
2892 /* 123 -7 */ CWORD_CWORD_CWORD_CWORD,
2893 /* 124 -6 */ CWORD_CWORD_CWORD_CWORD,
2894 /* 125 -5 */ CWORD_CWORD_CWORD_CWORD,
2895 /* 126 -4 */ CWORD_CWORD_CWORD_CWORD,
2896 /* 127 -3 */ CWORD_CWORD_CWORD_CWORD,
2897 /* 128 -2 */ CWORD_CWORD_CWORD_CWORD,
2898 /* 129 -1 */ CWORD_CWORD_CWORD_CWORD,
2899 /* 130 0 */ CWORD_CWORD_CWORD_CWORD,
2900 /* 131 1 */ CWORD_CWORD_CWORD_CWORD,
2901 /* 132 2 */ CWORD_CWORD_CWORD_CWORD,
2902 /* 133 3 */ CWORD_CWORD_CWORD_CWORD,
2903 /* 134 4 */ CWORD_CWORD_CWORD_CWORD,
2904 /* 135 5 */ CWORD_CWORD_CWORD_CWORD,
2905 /* 136 6 */ CWORD_CWORD_CWORD_CWORD,
2906 /* 137 7 */ CWORD_CWORD_CWORD_CWORD,
2907 /* 138 8 */ CWORD_CWORD_CWORD_CWORD,
2908 /* 139 9 "\t" */ CSPCL_CWORD_CWORD_CWORD,
2909 /* 140 10 "\n" */ CNL_CNL_CNL_CNL,
2910 /* 141 11 */ CWORD_CWORD_CWORD_CWORD,
2911 /* 142 12 */ CWORD_CWORD_CWORD_CWORD,
2912 /* 143 13 */ CWORD_CWORD_CWORD_CWORD,
2913 /* 144 14 */ CWORD_CWORD_CWORD_CWORD,
2914 /* 145 15 */ CWORD_CWORD_CWORD_CWORD,
2915 /* 146 16 */ CWORD_CWORD_CWORD_CWORD,
2916 /* 147 17 */ CWORD_CWORD_CWORD_CWORD,
2917 /* 148 18 */ CWORD_CWORD_CWORD_CWORD,
2918 /* 149 19 */ CWORD_CWORD_CWORD_CWORD,
2919 /* 150 20 */ CWORD_CWORD_CWORD_CWORD,
2920 /* 151 21 */ CWORD_CWORD_CWORD_CWORD,
2921 /* 152 22 */ CWORD_CWORD_CWORD_CWORD,
2922 /* 153 23 */ CWORD_CWORD_CWORD_CWORD,
2923 /* 154 24 */ CWORD_CWORD_CWORD_CWORD,
2924 /* 155 25 */ CWORD_CWORD_CWORD_CWORD,
2925 /* 156 26 */ CWORD_CWORD_CWORD_CWORD,
2926 /* 157 27 */ CWORD_CWORD_CWORD_CWORD,
2927 /* 158 28 */ CWORD_CWORD_CWORD_CWORD,
2928 /* 159 29 */ CWORD_CWORD_CWORD_CWORD,
2929 /* 160 30 */ CWORD_CWORD_CWORD_CWORD,
2930 /* 161 31 */ CWORD_CWORD_CWORD_CWORD,
2931 /* 162 32 " " */ CSPCL_CWORD_CWORD_CWORD,
2932 /* 163 33 "!" */ CWORD_CCTL_CCTL_CWORD,
2933 /* 164 34 """ */ CDQUOTE_CENDQUOTE_CWORD_CWORD,
2934 /* 165 35 "#" */ CWORD_CWORD_CWORD_CWORD,
2935 /* 166 36 "$" */ CVAR_CVAR_CWORD_CVAR,
2936 /* 167 37 "%" */ CWORD_CWORD_CWORD_CWORD,
2937 /* 168 38 "&" */ CSPCL_CWORD_CWORD_CWORD,
2938 /* 169 39 "'" */ CSQUOTE_CWORD_CENDQUOTE_CWORD,
2939 /* 170 40 "(" */ CSPCL_CWORD_CWORD_CLP,
2940 /* 171 41 ")" */ CSPCL_CWORD_CWORD_CRP,
2941 /* 172 42 "*" */ CWORD_CCTL_CCTL_CWORD,
2942 /* 173 43 "+" */ CWORD_CWORD_CWORD_CWORD,
2943 /* 174 44 "," */ CWORD_CWORD_CWORD_CWORD,
2944 /* 175 45 "-" */ CWORD_CCTL_CCTL_CWORD,
2945 /* 176 46 "." */ CWORD_CWORD_CWORD_CWORD,
2946 /* 177 47 "/" */ CWORD_CCTL_CCTL_CWORD,
2947 /* 178 48 "0" */ CWORD_CWORD_CWORD_CWORD,
2948 /* 179 49 "1" */ CWORD_CWORD_CWORD_CWORD,
2949 /* 180 50 "2" */ CWORD_CWORD_CWORD_CWORD,
2950 /* 181 51 "3" */ CWORD_CWORD_CWORD_CWORD,
2951 /* 182 52 "4" */ CWORD_CWORD_CWORD_CWORD,
2952 /* 183 53 "5" */ CWORD_CWORD_CWORD_CWORD,
2953 /* 184 54 "6" */ CWORD_CWORD_CWORD_CWORD,
2954 /* 185 55 "7" */ CWORD_CWORD_CWORD_CWORD,
2955 /* 186 56 "8" */ CWORD_CWORD_CWORD_CWORD,
2956 /* 187 57 "9" */ CWORD_CWORD_CWORD_CWORD,
2957 /* 188 58 ":" */ CWORD_CCTL_CCTL_CWORD,
2958 /* 189 59 ";" */ CSPCL_CWORD_CWORD_CWORD,
2959 /* 190 60 "<" */ CSPCL_CWORD_CWORD_CWORD,
2960 /* 191 61 "=" */ CWORD_CCTL_CCTL_CWORD,
2961 /* 192 62 ">" */ CSPCL_CWORD_CWORD_CWORD,
2962 /* 193 63 "?" */ CWORD_CCTL_CCTL_CWORD,
2963 /* 194 64 "@" */ CWORD_CWORD_CWORD_CWORD,
2964 /* 195 65 "A" */ CWORD_CWORD_CWORD_CWORD,
2965 /* 196 66 "B" */ CWORD_CWORD_CWORD_CWORD,
2966 /* 197 67 "C" */ CWORD_CWORD_CWORD_CWORD,
2967 /* 198 68 "D" */ CWORD_CWORD_CWORD_CWORD,
2968 /* 199 69 "E" */ CWORD_CWORD_CWORD_CWORD,
2969 /* 200 70 "F" */ CWORD_CWORD_CWORD_CWORD,
2970 /* 201 71 "G" */ CWORD_CWORD_CWORD_CWORD,
2971 /* 202 72 "H" */ CWORD_CWORD_CWORD_CWORD,
2972 /* 203 73 "I" */ CWORD_CWORD_CWORD_CWORD,
2973 /* 204 74 "J" */ CWORD_CWORD_CWORD_CWORD,
2974 /* 205 75 "K" */ CWORD_CWORD_CWORD_CWORD,
2975 /* 206 76 "L" */ CWORD_CWORD_CWORD_CWORD,
2976 /* 207 77 "M" */ CWORD_CWORD_CWORD_CWORD,
2977 /* 208 78 "N" */ CWORD_CWORD_CWORD_CWORD,
2978 /* 209 79 "O" */ CWORD_CWORD_CWORD_CWORD,
2979 /* 210 80 "P" */ CWORD_CWORD_CWORD_CWORD,
2980 /* 211 81 "Q" */ CWORD_CWORD_CWORD_CWORD,
2981 /* 212 82 "R" */ CWORD_CWORD_CWORD_CWORD,
2982 /* 213 83 "S" */ CWORD_CWORD_CWORD_CWORD,
2983 /* 214 84 "T" */ CWORD_CWORD_CWORD_CWORD,
2984 /* 215 85 "U" */ CWORD_CWORD_CWORD_CWORD,
2985 /* 216 86 "V" */ CWORD_CWORD_CWORD_CWORD,
2986 /* 217 87 "W" */ CWORD_CWORD_CWORD_CWORD,
2987 /* 218 88 "X" */ CWORD_CWORD_CWORD_CWORD,
2988 /* 219 89 "Y" */ CWORD_CWORD_CWORD_CWORD,
2989 /* 220 90 "Z" */ CWORD_CWORD_CWORD_CWORD,
2990 /* 221 91 "[" */ CWORD_CCTL_CCTL_CWORD,
2991 /* 222 92 "\" */ CBACK_CBACK_CCTL_CBACK,
2992 /* 223 93 "]" */ CWORD_CCTL_CCTL_CWORD,
2993 /* 224 94 "^" */ CWORD_CWORD_CWORD_CWORD,
2994 /* 225 95 "_" */ CWORD_CWORD_CWORD_CWORD,
2995 /* 226 96 "`" */ CBQUOTE_CBQUOTE_CWORD_CBQUOTE,
2996 /* 227 97 "a" */ CWORD_CWORD_CWORD_CWORD,
2997 /* 228 98 "b" */ CWORD_CWORD_CWORD_CWORD,
2998 /* 229 99 "c" */ CWORD_CWORD_CWORD_CWORD,
2999 /* 230 100 "d" */ CWORD_CWORD_CWORD_CWORD,
3000 /* 231 101 "e" */ CWORD_CWORD_CWORD_CWORD,
3001 /* 232 102 "f" */ CWORD_CWORD_CWORD_CWORD,
3002 /* 233 103 "g" */ CWORD_CWORD_CWORD_CWORD,
3003 /* 234 104 "h" */ CWORD_CWORD_CWORD_CWORD,
3004 /* 235 105 "i" */ CWORD_CWORD_CWORD_CWORD,
3005 /* 236 106 "j" */ CWORD_CWORD_CWORD_CWORD,
3006 /* 237 107 "k" */ CWORD_CWORD_CWORD_CWORD,
3007 /* 238 108 "l" */ CWORD_CWORD_CWORD_CWORD,
3008 /* 239 109 "m" */ CWORD_CWORD_CWORD_CWORD,
3009 /* 240 110 "n" */ CWORD_CWORD_CWORD_CWORD,
3010 /* 241 111 "o" */ CWORD_CWORD_CWORD_CWORD,
3011 /* 242 112 "p" */ CWORD_CWORD_CWORD_CWORD,
3012 /* 243 113 "q" */ CWORD_CWORD_CWORD_CWORD,
3013 /* 244 114 "r" */ CWORD_CWORD_CWORD_CWORD,
3014 /* 245 115 "s" */ CWORD_CWORD_CWORD_CWORD,
3015 /* 246 116 "t" */ CWORD_CWORD_CWORD_CWORD,
3016 /* 247 117 "u" */ CWORD_CWORD_CWORD_CWORD,
3017 /* 248 118 "v" */ CWORD_CWORD_CWORD_CWORD,
3018 /* 249 119 "w" */ CWORD_CWORD_CWORD_CWORD,
3019 /* 250 120 "x" */ CWORD_CWORD_CWORD_CWORD,
3020 /* 251 121 "y" */ CWORD_CWORD_CWORD_CWORD,
3021 /* 252 122 "z" */ CWORD_CWORD_CWORD_CWORD,
3022 /* 253 123 "{" */ CWORD_CWORD_CWORD_CWORD,
3023 /* 254 124 "|" */ CSPCL_CWORD_CWORD_CWORD,
3024 /* 255 125 "}" */ CENDVAR_CENDVAR_CWORD_CENDVAR,
3025 /* 256 126 "~" */ CWORD_CCTL_CCTL_CWORD,
3026 /* 257 127 */ CWORD_CWORD_CWORD_CWORD,
3029 #define SIT(c, syntax) (S_I_T[(int)syntax_index_table[((int)c)+SYNBASE]][syntax])
3031 #endif /* USE_SIT_FUNCTION */
3034 /* ============ Alias handling */
3036 #if ENABLE_ASH_ALIAS
3038 #define ALIASINUSE 1
3049 static struct alias **atab; // [ATABSIZE];
3050 #define INIT_G_alias() do { \
3051 atab = xzalloc(ATABSIZE * sizeof(atab[0])); \
3055 static struct alias **
3056 __lookupalias(const char *name) {
3057 unsigned int hashval;
3064 ch = (unsigned char)*p;
3068 ch = (unsigned char)*++p;
3070 app = &atab[hashval % ATABSIZE];
3072 for (; *app; app = &(*app)->next) {
3073 if (strcmp(name, (*app)->name) == 0) {
3081 static struct alias *
3082 lookupalias(const char *name, int check)
3084 struct alias *ap = *__lookupalias(name);
3086 if (check && ap && (ap->flag & ALIASINUSE))
3091 static struct alias *
3092 freealias(struct alias *ap)
3096 if (ap->flag & ALIASINUSE) {
3097 ap->flag |= ALIASDEAD;
3109 setalias(const char *name, const char *val)
3111 struct alias *ap, **app;
3113 app = __lookupalias(name);
3117 if (!(ap->flag & ALIASINUSE)) {
3120 ap->val = ckstrdup(val);
3121 ap->flag &= ~ALIASDEAD;
3124 ap = ckzalloc(sizeof(struct alias));
3125 ap->name = ckstrdup(name);
3126 ap->val = ckstrdup(val);
3127 /*ap->flag = 0; - ckzalloc did it */
3128 /*ap->next = NULL;*/
3135 unalias(const char *name)
3139 app = __lookupalias(name);
3143 *app = freealias(*app);
3154 struct alias *ap, **app;
3158 for (i = 0; i < ATABSIZE; i++) {
3160 for (ap = *app; ap; ap = *app) {
3161 *app = freealias(*app);
3171 printalias(const struct alias *ap)
3173 out1fmt("%s=%s\n", ap->name, single_quote(ap->val));
3177 * TODO - sort output
3180 aliascmd(int argc UNUSED_PARAM, char **argv)
3189 for (i = 0; i < ATABSIZE; i++) {
3190 for (ap = atab[i]; ap; ap = ap->next) {
3196 while ((n = *++argv) != NULL) {
3197 v = strchr(n+1, '=');
3198 if (v == NULL) { /* n+1: funny ksh stuff */
3199 ap = *__lookupalias(n);
3201 fprintf(stderr, "%s: %s not found\n", "alias", n);
3215 unaliascmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
3219 while ((i = nextopt("a")) != '\0') {
3225 for (i = 0; *argptr; argptr++) {
3226 if (unalias(*argptr)) {
3227 fprintf(stderr, "%s: %s not found\n", "unalias", *argptr);
3235 #endif /* ASH_ALIAS */
3238 /* ============ jobs.c */
3240 /* Mode argument to forkshell. Don't change FORK_FG or FORK_BG. */
3243 #define FORK_NOJOB 2
3245 /* mode flags for showjob(s) */
3246 #define SHOW_PGID 0x01 /* only show pgid - for jobs -p */
3247 #define SHOW_PID 0x04 /* include process pid */
3248 #define SHOW_CHANGED 0x08 /* only jobs whose state has changed */
3251 * A job structure contains information about a job. A job is either a
3252 * single process or a set of processes contained in a pipeline. In the
3253 * latter case, pidlist will be non-NULL, and will point to a -1 terminated
3258 pid_t pid; /* process id */
3259 int status; /* last process status from wait() */
3260 char *cmd; /* text of command being run */
3264 struct procstat ps0; /* status of process */
3265 struct procstat *ps; /* status or processes when more than one */
3267 int stopstatus; /* status of a stopped job */
3270 nprocs: 16, /* number of processes */
3272 #define JOBRUNNING 0 /* at least one proc running */
3273 #define JOBSTOPPED 1 /* all procs are stopped */
3274 #define JOBDONE 2 /* all procs are completed */
3276 sigint: 1, /* job was killed by SIGINT */
3277 jobctl: 1, /* job running under job control */
3279 waited: 1, /* true if this entry has been waited for */
3280 used: 1, /* true if this entry is in used */
3281 changed: 1; /* true if status has changed */
3282 struct job *prev_job; /* previous job */
3285 static struct job *makejob(/*union node *,*/ int);
3287 #define forkshell(job, node, mode) forkshell(job, mode)
3289 static int forkshell(struct job *, union node *, int);
3290 static int waitforjob(struct job *);
3293 enum { doing_jobctl = 0 };
3294 #define setjobctl(on) do {} while (0)
3296 static smallint doing_jobctl; //references:8
3297 static void setjobctl(int);
3304 ignoresig(int signo)
3306 /* Avoid unnecessary system calls. Is it already SIG_IGNed? */
3307 if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) {
3308 /* No, need to do it */
3309 signal(signo, SIG_IGN);
3311 sigmode[signo - 1] = S_HARD_IGN;
3315 * Signal handler. Only one usage site - in setsignal()
3320 gotsig[signo - 1] = 1;
3322 if (/* exsig || */ (signo == SIGINT && !trap[SIGINT])) {
3325 raise_interrupt(); /* does not return */
3334 * Set the signal handler for the specified signal. The routine figures
3335 * out what it should be set to.
3338 setsignal(int signo)
3341 char cur_act, new_act;
3342 struct sigaction act;
3346 if (t != NULL) { /* trap for this sig is set */
3348 if (t[0] == '\0') /* trap is "": ignore this sig */
3352 if (rootshell && new_act == S_DFL) {
3355 if (iflag || minusc || sflag == 0)
3364 * "In all cases, bash ignores SIGQUIT. Non-builtin
3365 * commands run by bash have signal handlers
3366 * set to the values inherited by the shell
3367 * from its parent". */
3383 //TODO: if !rootshell, we reset SIGQUIT to DFL,
3384 //whereas we have to restore it to what shell got on entry
3385 //from the parent. See comment above
3387 t = &sigmode[signo - 1];
3390 /* current setting is not yet known */
3391 if (sigaction(signo, NULL, &act)) {
3392 /* pretend it worked; maybe we should give a warning,
3393 * but other shells don't. We don't alter sigmode,
3394 * so we retry every time.
3395 * btw, in Linux it never fails. --vda */
3398 if (act.sa_handler == SIG_IGN) {
3399 cur_act = S_HARD_IGN;
3401 && (signo == SIGTSTP || signo == SIGTTIN || signo == SIGTTOU)
3403 cur_act = S_IGN; /* don't hard ignore these */
3407 if (cur_act == S_HARD_IGN || cur_act == new_act)
3410 act.sa_handler = SIG_DFL;
3413 act.sa_handler = onsig;
3414 act.sa_flags = 0; /* matters only if !DFL and !IGN */
3415 sigfillset(&act.sa_mask); /* ditto */
3418 act.sa_handler = SIG_IGN;
3421 sigaction_set(signo, &act);
3426 /* mode flags for set_curjob */
3427 #define CUR_DELETE 2
3428 #define CUR_RUNNING 1
3429 #define CUR_STOPPED 0
3431 /* mode flags for dowait */
3432 #define DOWAIT_NONBLOCK WNOHANG
3433 #define DOWAIT_BLOCK 0
3436 /* pgrp of shell on invocation */
3437 static int initialpgrp; //references:2
3438 static int ttyfd = -1; //5
3441 static struct job *jobtab; //5
3443 static unsigned njobs; //4
3445 static struct job *curjob; //lots
3446 /* number of presumed living untracked jobs */
3447 static int jobless; //4
3450 set_curjob(struct job *jp, unsigned mode)
3453 struct job **jpp, **curp;
3455 /* first remove from list */
3456 jpp = curp = &curjob;
3461 jpp = &jp1->prev_job;
3463 *jpp = jp1->prev_job;
3465 /* Then re-insert in correct position */
3473 /* job being deleted */
3476 /* newly created job or backgrounded job,
3477 put after all stopped jobs. */
3481 if (!jp1 || jp1->state != JOBSTOPPED)
3484 jpp = &jp1->prev_job;
3490 /* newly stopped job - becomes curjob */
3491 jp->prev_job = *jpp;
3499 jobno(const struct job *jp)
3501 return jp - jobtab + 1;
3506 * Convert a job name to a job structure.
3509 #define getjob(name, getctl) getjob(name)
3512 getjob(const char *name, int getctl)
3516 const char *err_msg = "No such job: %s";
3520 char *(*match)(const char *, const char *);
3535 if (c == '+' || c == '%') {
3537 err_msg = "No current job";
3543 err_msg = "No previous job";
3552 // TODO: number() instead? It does error checking...
3555 jp = jobtab + num - 1;
3572 if (match(jp->ps[0].cmd, p)) {
3576 err_msg = "%s: ambiguous";
3583 err_msg = "job %s not created under job control";
3584 if (getctl && jp->jobctl == 0)
3589 ash_msg_and_raise_error(err_msg, name);
3593 * Mark a job structure as unused.
3596 freejob(struct job *jp)
3598 struct procstat *ps;
3602 for (i = jp->nprocs, ps = jp->ps; --i >= 0; ps++) {
3603 if (ps->cmd != nullstr)
3606 if (jp->ps != &jp->ps0)
3609 set_curjob(jp, CUR_DELETE);
3615 xtcsetpgrp(int fd, pid_t pgrp)
3617 if (tcsetpgrp(fd, pgrp))
3618 ash_msg_and_raise_error("can't set tty process group (%m)");
3622 * Turn job control on and off.
3624 * Note: This code assumes that the third arg to ioctl is a character
3625 * pointer, which is true on Berkeley systems but not System V. Since
3626 * System V doesn't have job control yet, this isn't a problem now.
3628 * Called with interrupts off.
3636 if (on == doing_jobctl || rootshell == 0)
3640 ofd = fd = open(_PATH_TTY, O_RDWR);
3642 /* BTW, bash will try to open(ttyname(0)) if open("/dev/tty") fails.
3643 * That sometimes helps to acquire controlling tty.
3644 * Obviously, a workaround for bugs when someone
3645 * failed to provide a controlling tty to bash! :) */
3651 fd = fcntl(fd, F_DUPFD, 10);
3656 /* fd is a tty at this point */
3657 close_on_exec_on(fd);
3658 do { /* while we are in the background */
3659 pgrp = tcgetpgrp(fd);
3662 ash_msg("can't access tty; job control turned off");
3666 if (pgrp == getpgrp())
3677 xtcsetpgrp(fd, pgrp);
3679 /* turning job control off */
3682 /* was xtcsetpgrp, but this can make exiting ash
3683 * loop forever if pty is already deleted */
3684 tcsetpgrp(fd, pgrp);
3699 killcmd(int argc, char **argv)
3702 if (argv[1] && strcmp(argv[1], "-l") != 0) {
3704 if (argv[i][0] == '%') {
3705 struct job *jp = getjob(argv[i], 0);
3706 unsigned pid = jp->ps[0].pid;
3707 /* Enough space for ' -NNN<nul>' */
3708 argv[i] = alloca(sizeof(int)*3 + 3);
3709 /* kill_main has matching code to expect
3710 * leading space. Needed to not confuse
3711 * negative pids with "kill -SIGNAL_NO" syntax */
3712 sprintf(argv[i], " -%u", pid);
3714 } while (argv[++i]);
3716 return kill_main(argc, argv);
3720 showpipe(struct job *jp, FILE *out)
3722 struct procstat *sp;
3723 struct procstat *spend;
3725 spend = jp->ps + jp->nprocs;
3726 for (sp = jp->ps + 1; sp < spend; sp++)
3727 fprintf(out, " | %s", sp->cmd);
3728 outcslow('\n', out);
3729 flush_stdout_stderr();
3734 restartjob(struct job *jp, int mode)
3736 struct procstat *ps;
3742 if (jp->state == JOBDONE)
3744 jp->state = JOBRUNNING;
3746 if (mode == FORK_FG)
3747 xtcsetpgrp(ttyfd, pgid);
3748 killpg(pgid, SIGCONT);
3752 if (WIFSTOPPED(ps->status)) {
3758 status = (mode == FORK_FG) ? waitforjob(jp) : 0;
3764 fg_bgcmd(int argc UNUSED_PARAM, char **argv)
3771 mode = (**argv == 'f') ? FORK_FG : FORK_BG;
3776 jp = getjob(*argv, 1);
3777 if (mode == FORK_BG) {
3778 set_curjob(jp, CUR_RUNNING);
3779 fprintf(out, "[%d] ", jobno(jp));
3781 outstr(jp->ps->cmd, out);
3783 retval = restartjob(jp, mode);
3784 } while (*argv && *++argv);
3790 sprint_status(char *s, int status, int sigonly)
3796 if (!WIFEXITED(status)) {
3798 if (WIFSTOPPED(status))
3799 st = WSTOPSIG(status);
3802 st = WTERMSIG(status);
3804 if (st == SIGINT || st == SIGPIPE)
3807 if (WIFSTOPPED(status))
3812 col = fmtstr(s, 32, strsignal(st));
3813 if (WCOREDUMP(status)) {
3814 col += fmtstr(s + col, 16, " (core dumped)");
3816 } else if (!sigonly) {
3817 st = WEXITSTATUS(status);
3819 col = fmtstr(s, 16, "Done(%d)", st);
3821 col = fmtstr(s, 16, "Done");
3828 dowait(int wait_flags, struct job *job)
3833 struct job *thisjob;
3836 TRACE(("dowait(0x%x) called\n", wait_flags));
3838 /* Do a wait system call. If job control is compiled in, we accept
3839 * stopped processes. wait_flags may have WNOHANG, preventing blocking.
3840 * NB: _not_ safe_waitpid, we need to detect EINTR */
3841 pid = waitpid(-1, &status,
3842 (doing_jobctl ? (wait_flags | WUNTRACED) : wait_flags));
3843 TRACE(("wait returns pid=%d, status=0x%x, errno=%d(%s)\n",
3844 pid, status, errno, strerror(errno)));
3850 for (jp = curjob; jp; jp = jp->prev_job) {
3851 struct procstat *sp;
3852 struct procstat *spend;
3853 if (jp->state == JOBDONE)
3856 spend = jp->ps + jp->nprocs;
3859 if (sp->pid == pid) {
3860 TRACE(("Job %d: changing status of proc %d "
3861 "from 0x%x to 0x%x\n",
3862 jobno(jp), pid, sp->status, status));
3863 sp->status = status;
3866 if (sp->status == -1)
3869 if (state == JOBRUNNING)
3871 if (WIFSTOPPED(sp->status)) {
3872 jp->stopstatus = sp->status;
3876 } while (++sp < spend);
3881 if (!WIFSTOPPED(status))
3887 if (state != JOBRUNNING) {
3888 thisjob->changed = 1;
3890 if (thisjob->state != state) {
3891 TRACE(("Job %d: changing state from %d to %d\n",
3892 jobno(thisjob), thisjob->state, state));
3893 thisjob->state = state;
3895 if (state == JOBSTOPPED) {
3896 set_curjob(thisjob, CUR_STOPPED);
3905 if (thisjob && thisjob == job) {
3909 len = sprint_status(s, status, 1);
3920 blocking_wait_with_raise_on_sig(struct job *job)
3922 pid_t pid = dowait(DOWAIT_BLOCK, job);
3923 if (pid <= 0 && pendingsig)
3924 raise_exception(EXSIG);
3930 showjob(FILE *out, struct job *jp, int mode)
3932 struct procstat *ps;
3933 struct procstat *psend;
3940 if (mode & SHOW_PGID) {
3941 /* just output process (group) id of pipeline */
3942 fprintf(out, "%d\n", ps->pid);
3946 col = fmtstr(s, 16, "[%d] ", jobno(jp));
3951 else if (curjob && jp == curjob->prev_job)
3954 if (mode & SHOW_PID)
3955 col += fmtstr(s + col, 16, "%d ", ps->pid);
3957 psend = ps + jp->nprocs;
3959 if (jp->state == JOBRUNNING) {
3960 strcpy(s + col, "Running");
3961 col += sizeof("Running") - 1;
3963 int status = psend[-1].status;
3964 if (jp->state == JOBSTOPPED)
3965 status = jp->stopstatus;
3966 col += sprint_status(s + col, status, 0);
3972 /* for each process */
3973 col = fmtstr(s, 48, " |\n%*c%d ", indent_col, ' ', ps->pid) - 3;
3975 fprintf(out, "%s%*c%s",
3976 s, 33 - col >= 0 ? 33 - col : 0, ' ', ps->cmd
3978 if (!(mode & SHOW_PID)) {
3982 if (++ps == psend) {
3983 outcslow('\n', out);
3990 if (jp->state == JOBDONE) {
3991 TRACE(("showjob: freeing job %d\n", jobno(jp)));
3997 * Print a list of jobs. If "change" is nonzero, only print jobs whose
3998 * statuses have changed since the last call to showjobs.
4001 showjobs(FILE *out, int mode)
4005 TRACE(("showjobs(%x) called\n", mode));
4007 /* Handle all finished jobs */
4008 while (dowait(DOWAIT_NONBLOCK, NULL) > 0)
4011 for (jp = curjob; jp; jp = jp->prev_job) {
4012 if (!(mode & SHOW_CHANGED) || jp->changed) {
4013 showjob(out, jp, mode);
4019 jobscmd(int argc UNUSED_PARAM, char **argv)
4024 while ((m = nextopt("lp"))) {
4034 showjob(stdout, getjob(*argv,0), mode);
4037 showjobs(stdout, mode);
4044 getstatus(struct job *job)
4049 status = job->ps[job->nprocs - 1].status;
4050 retval = WEXITSTATUS(status);
4051 if (!WIFEXITED(status)) {
4053 retval = WSTOPSIG(status);
4054 if (!WIFSTOPPED(status))
4057 /* XXX: limits number of signals */
4058 retval = WTERMSIG(status);
4060 if (retval == SIGINT)
4066 TRACE(("getstatus: job %d, nproc %d, status %x, retval %x\n",
4067 jobno(job), job->nprocs, status, retval));
4072 waitcmd(int argc UNUSED_PARAM, char **argv)
4081 raise_exception(EXSIG);
4088 /* wait for all jobs */
4092 if (!jp) /* no running procs */
4094 if (jp->state == JOBRUNNING)
4100 * "When bash is waiting for an asynchronous command via
4101 * the wait builtin, the reception of a signal for which a trap
4102 * has been set will cause the wait builtin to return immediately
4103 * with an exit status greater than 128, immediately after which
4104 * the trap is executed."
4105 * Do we do it that way? */
4106 blocking_wait_with_raise_on_sig(NULL);
4112 if (**argv != '%') {
4113 pid_t pid = number(*argv);
4118 if (job->ps[job->nprocs - 1].pid == pid)
4120 job = job->prev_job;
4123 job = getjob(*argv, 0);
4124 /* loop until process terminated or stopped */
4125 while (job->state == JOBRUNNING)
4126 blocking_wait_with_raise_on_sig(NULL);
4128 retval = getstatus(job);
4141 struct job *jp, *jq;
4143 len = njobs * sizeof(*jp);
4145 jp = ckrealloc(jq, len + 4 * sizeof(*jp));
4147 offset = (char *)jp - (char *)jq;
4149 /* Relocate pointers */
4152 jq = (struct job *)((char *)jq + l);
4156 #define joff(p) ((struct job *)((char *)(p) + l))
4157 #define jmove(p) (p) = (void *)((char *)(p) + offset)
4158 if (joff(jp)->ps == &jq->ps0)
4159 jmove(joff(jp)->ps);
4160 if (joff(jp)->prev_job)
4161 jmove(joff(jp)->prev_job);
4171 jp = (struct job *)((char *)jp + len);
4175 } while (--jq >= jp);
4180 * Return a new job structure.
4181 * Called with interrupts off.
4184 makejob(/*union node *node,*/ int nprocs)
4189 for (i = njobs, jp = jobtab; ; jp++) {
4196 if (jp->state != JOBDONE || !jp->waited)
4205 memset(jp, 0, sizeof(*jp));
4207 /* jp->jobctl is a bitfield.
4208 * "jp->jobctl |= jobctl" likely to give awful code */
4212 jp->prev_job = curjob;
4217 jp->ps = ckmalloc(nprocs * sizeof(struct procstat));
4219 TRACE(("makejob(%d) returns %%%d\n", nprocs,
4226 * Return a string identifying a command (to be printed by the
4229 static char *cmdnextc;
4232 cmdputs(const char *s)
4234 static const char vstype[VSTYPE + 1][3] = {
4235 "", "}", "-", "+", "?", "=",
4236 "%", "%%", "#", "##"
4237 USE_ASH_BASH_COMPAT(, ":", "/", "//")
4240 const char *p, *str;
4241 char c, cc[2] = " ";
4246 nextc = makestrspace((strlen(s) + 1) * 8, cmdnextc);
4248 while ((c = *p++) != 0) {
4256 if ((subtype & VSTYPE) == VSLENGTH)
4260 if (!(subtype & VSQUOTE) == !(quoted & 1))
4266 str = "\"}" + !(quoted & 1);
4273 case CTLBACKQ+CTLQUOTE:
4276 #if ENABLE_ASH_MATH_SUPPORT
4291 if ((subtype & VSTYPE) != VSNORMAL)
4293 str = vstype[subtype & VSTYPE];
4294 if (subtype & VSNUL)
4303 /* These can only happen inside quotes */
4316 while ((c = *str++)) {
4321 USTPUTC('"', nextc);
4327 /* cmdtxt() and cmdlist() call each other */
4328 static void cmdtxt(union node *n);
4331 cmdlist(union node *np, int sep)
4333 for (; np; np = np->narg.next) {
4337 if (sep && np->narg.next)
4343 cmdtxt(union node *n)
4346 struct nodelist *lp;
4357 lp = n->npipe.cmdlist;
4375 cmdtxt(n->nbinary.ch1);
4391 cmdtxt(n->nif.test);
4394 if (n->nif.elsepart) {
4397 n = n->nif.elsepart;
4413 cmdtxt(n->nbinary.ch1);
4423 cmdputs(n->nfor.var);
4425 cmdlist(n->nfor.args, 1);
4430 cmdputs(n->narg.text);
4434 cmdlist(n->ncmd.args, 1);
4435 cmdlist(n->ncmd.redirect, 0);
4448 cmdputs(n->ncase.expr->narg.text);
4450 for (np = n->ncase.cases; np; np = np->nclist.next) {
4451 cmdtxt(np->nclist.pattern);
4453 cmdtxt(np->nclist.body);
4467 #if ENABLE_ASH_BASH_COMPAT
4482 cmdputs(utoa(n->nfile.fd));
4484 if (n->type == NTOFD || n->type == NFROMFD) {
4485 cmdputs(utoa(n->ndup.dupfd));
4494 commandtext(union node *n)
4498 STARTSTACKSTR(cmdnextc);
4500 name = stackblock();
4501 TRACE(("commandtext: name %p, end %p\n\t\"%s\"\n",
4502 name, cmdnextc, cmdnextc));
4503 return ckstrdup(name);
4508 * Fork off a subshell. If we are doing job control, give the subshell its
4509 * own process group. Jp is a job structure that the job is to be added to.
4510 * N is the command that will be evaluated by the child. Both jp and n may
4511 * be NULL. The mode parameter can be one of the following:
4512 * FORK_FG - Fork off a foreground process.
4513 * FORK_BG - Fork off a background process.
4514 * FORK_NOJOB - Like FORK_FG, but don't give the process its own
4515 * process group even if job control is on.
4517 * When job control is turned off, background processes have their standard
4518 * input redirected to /dev/null (except for the second and later processes
4521 * Called with interrupts off.
4524 * Clear traps on a fork.
4531 for (tp = trap; tp < &trap[NSIG]; tp++) {
4532 if (*tp && **tp) { /* trap not NULL or "" (SIG_IGN) */
4537 setsignal(tp - trap);
4543 /* Lives far away from here, needed for forkchild */
4544 static void closescript(void);
4546 /* Called after fork(), in child */
4548 forkchild(struct job *jp, /*union node *n,*/ int mode)
4552 TRACE(("Child shell %d\n", getpid()));
4556 /* man bash: "Non-builtin commands run by bash have signal handlers
4557 * set to the values inherited by the shell from its parent".
4558 * Do we do it correctly? */
4563 /* do job control only in root shell */
4565 if (mode != FORK_NOJOB && jp->jobctl && !oldlvl) {
4568 if (jp->nprocs == 0)
4571 pgrp = jp->ps[0].pid;
4572 /* this can fail because we are doing it in the parent also */
4574 if (mode == FORK_FG)
4575 xtcsetpgrp(ttyfd, pgrp);
4580 if (mode == FORK_BG) {
4581 /* man bash: "When job control is not in effect,
4582 * asynchronous commands ignore SIGINT and SIGQUIT" */
4585 if (jp->nprocs == 0) {
4587 if (open(bb_dev_null, O_RDONLY) != 0)
4588 ash_msg_and_raise_error("can't open '%s'", bb_dev_null);
4592 if (iflag) { /* why if iflag only? */
4597 * "In all cases, bash ignores SIGQUIT. Non-builtin
4598 * commands run by bash have signal handlers
4599 * set to the values inherited by the shell
4601 * Take care of the second rule: */
4604 for (jp = curjob; jp; jp = jp->prev_job)
4609 /* Called after fork(), in parent */
4611 #define forkparent(jp, n, mode, pid) forkparent(jp, mode, pid)
4614 forkparent(struct job *jp, union node *n, int mode, pid_t pid)
4616 TRACE(("In parent shell: child = %d\n", pid));
4618 while (jobless && dowait(DOWAIT_NONBLOCK, NULL) > 0)
4624 if (mode != FORK_NOJOB && jp->jobctl) {
4627 if (jp->nprocs == 0)
4630 pgrp = jp->ps[0].pid;
4631 /* This can fail because we are doing it in the child also */
4635 if (mode == FORK_BG) {
4636 backgndpid = pid; /* set $! */
4637 set_curjob(jp, CUR_RUNNING);
4640 struct procstat *ps = &jp->ps[jp->nprocs++];
4645 if (doing_jobctl && n)
4646 ps->cmd = commandtext(n);
4652 forkshell(struct job *jp, union node *n, int mode)
4656 TRACE(("forkshell(%%%d, %p, %d) called\n", jobno(jp), n, mode));
4659 TRACE(("Fork failed, errno=%d", errno));
4662 ash_msg_and_raise_error("can't fork");
4665 forkchild(jp, /*n,*/ mode);
4667 forkparent(jp, n, mode, pid);
4672 * Wait for job to finish.
4674 * Under job control we have the problem that while a child process
4675 * is running interrupts generated by the user are sent to the child
4676 * but not to the shell. This means that an infinite loop started by
4677 * an interactive user may be hard to kill. With job control turned off,
4678 * an interactive user may place an interactive program inside a loop.
4679 * If the interactive program catches interrupts, the user doesn't want
4680 * these interrupts to also abort the loop. The approach we take here
4681 * is to have the shell ignore interrupt signals while waiting for a
4682 * foreground process to terminate, and then send itself an interrupt
4683 * signal if the child process was terminated by an interrupt signal.
4684 * Unfortunately, some programs want to do a bit of cleanup and then
4685 * exit on interrupt; unless these processes terminate themselves by
4686 * sending a signal to themselves (instead of calling exit) they will
4687 * confuse this approach.
4689 * Called with interrupts off.
4692 waitforjob(struct job *jp)
4696 TRACE(("waitforjob(%%%d) called\n", jobno(jp)));
4699 while (jp->state == JOBRUNNING) {
4700 /* In non-interactive shells, we _can_ get
4701 * a keyboard signal here and be EINTRed,
4702 * but we just loop back, waiting for command to complete.
4705 * "If bash is waiting for a command to complete and receives
4706 * a signal for which a trap has been set, the trap
4707 * will not be executed until the command completes."
4709 * Reality is that even if trap is not set, bash
4710 * will not act on the signal until command completes.
4711 * Try this. sleep5intoff.c:
4712 * #include <signal.h>
4713 * #include <unistd.h>
4716 * sigemptyset(&set);
4717 * sigaddset(&set, SIGINT);
4718 * sigaddset(&set, SIGQUIT);
4719 * sigprocmask(SIG_BLOCK, &set, NULL);
4723 * $ bash -c './sleep5intoff; echo hi'
4724 * ^C^C^C^C <--- pressing ^C once a second
4726 * $ bash -c './sleep5intoff; echo hi'
4727 * ^\^\^\^\hi <--- pressing ^\ (SIGQUIT)
4730 dowait(DOWAIT_BLOCK, jp);
4737 xtcsetpgrp(ttyfd, rootpid);
4739 * This is truly gross.
4740 * If we're doing job control, then we did a TIOCSPGRP which
4741 * caused us (the shell) to no longer be in the controlling
4742 * session -- so we wouldn't have seen any ^C/SIGINT. So, we
4743 * intuit from the subprocess exit status whether a SIGINT
4744 * occurred, and if so interrupt ourselves. Yuck. - mycroft
4746 if (jp->sigint) /* TODO: do the same with all signals */
4747 raise(SIGINT); /* ... by raise(jp->sig) instead? */
4749 if (jp->state == JOBDONE)
4756 * return 1 if there are stopped jobs, otherwise 0
4768 if (jp && jp->state == JOBSTOPPED) {
4769 out2str("You have stopped jobs.\n");
4778 /* ============ redir.c
4780 * Code for dealing with input/output redirection.
4783 #define EMPTY -2 /* marks an unused slot in redirtab */
4784 #define CLOSED -3 /* marks a slot of previously-closed fd */
4787 * Open a file in noclobber mode.
4788 * The code was copied from bash.
4791 noclobberopen(const char *fname)
4794 struct stat finfo, finfo2;
4797 * If the file exists and is a regular file, return an error
4800 r = stat(fname, &finfo);
4801 if (r == 0 && S_ISREG(finfo.st_mode)) {
4807 * If the file was not present (r != 0), make sure we open it
4808 * exclusively so that if it is created before we open it, our open
4809 * will fail. Make sure that we do not truncate an existing file.
4810 * Note that we don't turn on O_EXCL unless the stat failed -- if the
4811 * file was not a regular file, we leave O_EXCL off.
4814 return open(fname, O_WRONLY|O_CREAT|O_EXCL, 0666);
4815 fd = open(fname, O_WRONLY|O_CREAT, 0666);
4817 /* If the open failed, return the file descriptor right away. */
4822 * OK, the open succeeded, but the file may have been changed from a
4823 * non-regular file to a regular file between the stat and the open.
4824 * We are assuming that the O_EXCL open handles the case where FILENAME
4825 * did not exist and is symlinked to an existing file between the stat
4830 * If we can open it and fstat the file descriptor, and neither check
4831 * revealed that it was a regular file, and the file has not been
4832 * replaced, return the file descriptor.
4834 if (fstat(fd, &finfo2) == 0 && !S_ISREG(finfo2.st_mode)
4835 && finfo.st_dev == finfo2.st_dev && finfo.st_ino == finfo2.st_ino)
4838 /* The file has been replaced. badness. */
4845 * Handle here documents. Normally we fork off a process to write the
4846 * data to a pipe. If the document is short, we can stuff the data in
4847 * the pipe without forking.
4849 /* openhere needs this forward reference */
4850 static void expandhere(union node *arg, int fd);
4852 openhere(union node *redir)
4858 ash_msg_and_raise_error("pipe call failed");
4859 if (redir->type == NHERE) {
4860 len = strlen(redir->nhere.doc->narg.text);
4861 if (len <= PIPE_BUF) {
4862 full_write(pip[1], redir->nhere.doc->narg.text, len);
4866 if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) {
4869 ignoresig(SIGINT); //signal(SIGINT, SIG_IGN);
4870 ignoresig(SIGQUIT); //signal(SIGQUIT, SIG_IGN);
4871 ignoresig(SIGHUP); //signal(SIGHUP, SIG_IGN);
4872 ignoresig(SIGTSTP); //signal(SIGTSTP, SIG_IGN);
4873 signal(SIGPIPE, SIG_DFL);
4874 if (redir->type == NHERE)
4875 full_write(pip[1], redir->nhere.doc->narg.text, len);
4877 expandhere(redir->nhere.doc, pip[1]);
4878 _exit(EXIT_SUCCESS);
4886 openredirect(union node *redir)
4891 switch (redir->nfile.type) {
4893 fname = redir->nfile.expfname;
4894 f = open(fname, O_RDONLY);
4899 fname = redir->nfile.expfname;
4900 f = open(fname, O_RDWR|O_CREAT|O_TRUNC, 0666);
4905 #if ENABLE_ASH_BASH_COMPAT
4908 /* Take care of noclobber mode. */
4910 fname = redir->nfile.expfname;
4911 f = noclobberopen(fname);
4918 fname = redir->nfile.expfname;
4919 f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666);
4924 fname = redir->nfile.expfname;
4925 f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666);
4933 /* Fall through to eliminate warning. */
4934 /* Our single caller does this itself */
4941 f = openhere(redir);
4947 ash_msg_and_raise_error("can't create %s: %s", fname, errmsg(errno, "nonexistent directory"));
4949 ash_msg_and_raise_error("can't open %s: %s", fname, errmsg(errno, "no such file"));
4953 * Copy a file descriptor to be >= to. Returns -1
4954 * if the source file descriptor is closed, EMPTY if there are no unused
4955 * file descriptors left.
4957 /* 0x800..00: bit to set in "to" to request dup2 instead of fcntl(F_DUPFD).
4958 * old code was doing close(to) prior to copyfd() to achieve the same */
4960 COPYFD_EXACT = (int)~(INT_MAX),
4961 COPYFD_RESTORE = (int)((unsigned)COPYFD_EXACT >> 1),
4964 copyfd(int from, int to)
4968 if (to & COPYFD_EXACT) {
4969 to &= ~COPYFD_EXACT;
4971 newfd = dup2(from, to);
4973 newfd = fcntl(from, F_DUPFD, to);
4976 if (errno == EMFILE)
4978 /* Happens when source fd is not open: try "echo >&99" */
4979 ash_msg_and_raise_error("%d: %m", from);
4984 /* Struct def and variable are moved down to the first usage site */
4989 struct redirtab *next;
4992 struct two_fd_t two_fd[0];
4994 #define redirlist (G_var.redirlist)
4996 static int need_to_remember(struct redirtab *rp, int fd)
5000 if (!rp) /* remembering was not requested */
5003 for (i = 0; i < rp->pair_count; i++) {
5004 if (rp->two_fd[i].orig == fd) {
5005 /* already remembered */
5012 /* "hidden" fd is a fd used to read scripts, or a copy of such */
5013 static int is_hidden_fd(struct redirtab *rp, int fd)
5016 struct parsefile *pf;
5029 fd |= COPYFD_RESTORE;
5030 for (i = 0; i < rp->pair_count; i++) {
5031 if (rp->two_fd[i].copy == fd) {
5039 * Process a list of redirection commands. If the REDIR_PUSH flag is set,
5040 * old file descriptors are stashed away so that the redirection can be
5041 * undone by calling popredir. If the REDIR_BACKQ flag is set, then the
5042 * standard output, and the standard error if it becomes a duplicate of
5043 * stdout, is saved in memory.
5045 /* flags passed to redirect */
5046 #define REDIR_PUSH 01 /* save previous values of file descriptors */
5047 #define REDIR_SAVEFD2 03 /* set preverrout */
5049 redirect(union node *redir, int flags)
5051 struct redirtab *sv;
5056 int copied_fd2 = -1;
5066 if (flags & REDIR_PUSH) {
5067 union node *tmp = redir;
5070 #if ENABLE_ASH_BASH_COMPAT
5071 if (redir->nfile.type == NTO2)
5074 tmp = tmp->nfile.next;
5076 sv = ckmalloc(sizeof(*sv) + sv_pos * sizeof(sv->two_fd[0]));
5077 sv->next = redirlist;
5078 sv->pair_count = sv_pos;
5080 sv->nullredirs = g_nullredirs - 1;
5082 while (sv_pos > 0) {
5084 sv->two_fd[sv_pos].orig = sv->two_fd[sv_pos].copy = EMPTY;
5089 fd = redir->nfile.fd;
5090 if (redir->nfile.type == NTOFD || redir->nfile.type == NFROMFD) {
5091 int right_fd = redir->ndup.dupfd;
5092 /* redirect from/to same file descriptor? */
5095 /* echo >&10 and 10 is a fd opened to the sh script? */
5096 if (is_hidden_fd(sv, right_fd)) {
5097 errno = EBADF; /* as if it is closed */
5098 ash_msg_and_raise_error("%d: %m", right_fd);
5102 newfd = openredirect(redir); /* always >= 0 */
5104 /* Descriptor wasn't open before redirect.
5105 * Mark it for close in the future */
5106 if (need_to_remember(sv, fd)) {
5107 goto remember_to_close;
5112 #if ENABLE_ASH_BASH_COMPAT
5115 if (need_to_remember(sv, fd)) {
5116 /* Copy old descriptor */
5117 i = fcntl(fd, F_DUPFD, 10);
5118 /* You'd expect copy to be CLOEXECed. Currently these extra "saved" fds
5119 * are closed in popredir() in the child, preventing them from leaking
5120 * into child. (popredir() also cleans up the mess in case of failures)
5125 /* Strange error (e.g. "too many files" EMFILE?) */
5129 ash_msg_and_raise_error("%d: %m", fd);
5132 /* EBADF: it is not open - good, remember to close it */
5135 } else { /* fd is open, save its copy */
5136 /* "exec fd>&-" should not close fds
5137 * which point to script file(s).
5138 * Force them to be restored afterwards */
5139 if (is_hidden_fd(sv, fd))
5140 i |= COPYFD_RESTORE;
5144 sv->two_fd[sv_pos].orig = fd;
5145 sv->two_fd[sv_pos].copy = i;
5149 /* NTOFD/NFROMFD: copy redir->ndup.dupfd to fd */
5150 if (redir->ndup.dupfd < 0) { /* "fd>&-" */
5151 /* Don't want to trigger debugging */
5155 copyfd(redir->ndup.dupfd, fd | COPYFD_EXACT);
5157 } else if (fd != newfd) { /* move newfd to fd */
5158 copyfd(newfd, fd | COPYFD_EXACT);
5159 #if ENABLE_ASH_BASH_COMPAT
5160 if (!(redir->nfile.type == NTO2 && fd == 2))
5164 #if ENABLE_ASH_BASH_COMPAT
5165 if (redir->nfile.type == NTO2 && fd == 1) {
5166 /* We already redirected it to fd 1, now copy it to 2 */
5172 } while ((redir = redir->nfile.next) != NULL);
5175 if ((flags & REDIR_SAVEFD2) && copied_fd2 >= 0)
5176 preverrout_fd = copied_fd2;
5180 * Undo the effects of the last redirection.
5183 popredir(int drop, int restore)
5185 struct redirtab *rp;
5188 if (--g_nullredirs >= 0)
5192 for (i = 0; i < rp->pair_count; i++) {
5193 int fd = rp->two_fd[i].orig;
5194 int copy = rp->two_fd[i].copy;
5195 if (copy == CLOSED) {
5200 if (copy != EMPTY) {
5201 if (!drop || (restore && (copy & COPYFD_RESTORE))) {
5202 copy &= ~COPYFD_RESTORE;
5204 copyfd(copy, fd | COPYFD_EXACT);
5206 close(copy & ~COPYFD_RESTORE);
5209 redirlist = rp->next;
5210 g_nullredirs = rp->nullredirs;
5216 * Undo all redirections. Called on error or interrupt.
5220 * Discard all saved file descriptors.
5223 clearredir(int drop)
5229 popredir(drop, /*restore:*/ 0);
5234 redirectsafe(union node *redir, int flags)
5237 volatile int saveint;
5238 struct jmploc *volatile savehandler = exception_handler;
5239 struct jmploc jmploc;
5242 /* "echo 9>/dev/null; echo >&9; echo result: $?" - result should be 1, not 2! */
5243 err = setjmp(jmploc.loc); // huh?? was = setjmp(jmploc.loc) * 2;
5245 exception_handler = &jmploc;
5246 redirect(redir, flags);
5248 exception_handler = savehandler;
5249 if (err && exception_type != EXERROR)
5250 longjmp(exception_handler->loc, 1);
5251 RESTORE_INT(saveint);
5256 /* ============ Routines to expand arguments to commands
5258 * We have to deal with backquotes, shell variables, and file metacharacters.
5261 #if ENABLE_ASH_MATH_SUPPORT_64
5262 typedef int64_t arith_t;
5263 #define arith_t_type long long
5265 typedef long arith_t;
5266 #define arith_t_type long
5269 #if ENABLE_ASH_MATH_SUPPORT
5270 static arith_t dash_arith(const char *);
5271 static arith_t arith(const char *expr, int *perrcode);
5277 #define EXP_FULL 0x1 /* perform word splitting & file globbing */
5278 #define EXP_TILDE 0x2 /* do normal tilde expansion */
5279 #define EXP_VARTILDE 0x4 /* expand tildes in an assignment */
5280 #define EXP_REDIR 0x8 /* file glob for a redirection (1 match only) */
5281 #define EXP_CASE 0x10 /* keeps quotes around for CASE pattern */
5282 #define EXP_RECORD 0x20 /* need to record arguments for ifs breakup */
5283 #define EXP_VARTILDE2 0x40 /* expand tildes after colons only */
5284 #define EXP_WORD 0x80 /* expand word in parameter expansion */
5285 #define EXP_QWORD 0x100 /* expand word in quoted parameter expansion */
5289 #define RMESCAPE_ALLOC 0x1 /* Allocate a new string */
5290 #define RMESCAPE_GLOB 0x2 /* Add backslashes for glob */
5291 #define RMESCAPE_QUOTED 0x4 /* Remove CTLESC unless in quotes */
5292 #define RMESCAPE_GROW 0x8 /* Grow strings instead of stalloc */
5293 #define RMESCAPE_HEAP 0x10 /* Malloc strings instead of stalloc */
5296 * Structure specifying which parts of the string should be searched
5297 * for IFS characters.
5300 struct ifsregion *next; /* next region in list */
5301 int begoff; /* offset of start of region */
5302 int endoff; /* offset of end of region */
5303 int nulonly; /* search for nul bytes only */
5307 struct strlist *list;
5308 struct strlist **lastp;
5311 /* output of current string */
5312 static char *expdest;
5313 /* list of back quote expressions */
5314 static struct nodelist *argbackq;
5315 /* first struct in list of ifs regions */
5316 static struct ifsregion ifsfirst;
5317 /* last struct in list */
5318 static struct ifsregion *ifslastp;
5319 /* holds expanded arg list */
5320 static struct arglist exparg;
5330 expdest = makestrspace(32, expdest);
5331 #if ENABLE_ASH_MATH_SUPPORT_64
5332 len = fmtstr(expdest, 32, "%lld", (long long) num);
5334 len = fmtstr(expdest, 32, "%ld", num);
5336 STADJUST(len, expdest);
5341 esclen(const char *start, const char *p)
5345 while (p > start && *--p == CTLESC) {
5352 * Remove any CTLESC characters from a string.
5355 _rmescapes(char *str, int flag)
5357 static const char qchars[] ALIGN1 = { CTLESC, CTLQUOTEMARK, '\0' };
5364 p = strpbrk(str, qchars);
5370 if (flag & RMESCAPE_ALLOC) {
5371 size_t len = p - str;
5372 size_t fulllen = len + strlen(p) + 1;
5374 if (flag & RMESCAPE_GROW) {
5375 r = makestrspace(fulllen, expdest);
5376 } else if (flag & RMESCAPE_HEAP) {
5377 r = ckmalloc(fulllen);
5379 r = stalloc(fulllen);
5383 q = (char *)memcpy(q, str, len) + len;
5386 inquotes = (flag & RMESCAPE_QUOTED) ^ RMESCAPE_QUOTED;
5387 globbing = flag & RMESCAPE_GLOB;
5388 notescaped = globbing;
5390 if (*p == CTLQUOTEMARK) {
5391 inquotes = ~inquotes;
5393 notescaped = globbing;
5397 /* naked back slash */
5403 if (notescaped && inquotes && *p != '/') {
5407 notescaped = globbing;
5412 if (flag & RMESCAPE_GROW) {
5414 STADJUST(q - r + 1, expdest);
5418 #define rmescapes(p) _rmescapes((p), 0)
5420 #define pmatch(a, b) !fnmatch((a), (b), 0)
5423 * Prepare a pattern for a expmeta (internal glob(3)) call.
5425 * Returns an stalloced string.
5428 preglob(const char *pattern, int quoted, int flag)
5430 flag |= RMESCAPE_GLOB;
5432 flag |= RMESCAPE_QUOTED;
5434 return _rmescapes((char *)pattern, flag);
5438 * Put a string on the stack.
5441 memtodest(const char *p, size_t len, int syntax, int quotes)
5445 q = makestrspace(len * 2, q);
5448 int c = signed_char2int(*p++);
5451 if (quotes && (SIT(c, syntax) == CCTL || SIT(c, syntax) == CBACK))
5460 strtodest(const char *p, int syntax, int quotes)
5462 memtodest(p, strlen(p), syntax, quotes);
5466 * Record the fact that we have to scan this region of the
5467 * string for IFS characters.
5470 recordregion(int start, int end, int nulonly)
5472 struct ifsregion *ifsp;
5474 if (ifslastp == NULL) {
5478 ifsp = ckzalloc(sizeof(*ifsp));
5479 /*ifsp->next = NULL; - ckzalloc did it */
5480 ifslastp->next = ifsp;
5484 ifslastp->begoff = start;
5485 ifslastp->endoff = end;
5486 ifslastp->nulonly = nulonly;
5490 removerecordregions(int endoff)
5492 if (ifslastp == NULL)
5495 if (ifsfirst.endoff > endoff) {
5496 while (ifsfirst.next != NULL) {
5497 struct ifsregion *ifsp;
5499 ifsp = ifsfirst.next->next;
5500 free(ifsfirst.next);
5501 ifsfirst.next = ifsp;
5504 if (ifsfirst.begoff > endoff)
5507 ifslastp = &ifsfirst;
5508 ifsfirst.endoff = endoff;
5513 ifslastp = &ifsfirst;
5514 while (ifslastp->next && ifslastp->next->begoff < endoff)
5515 ifslastp=ifslastp->next;
5516 while (ifslastp->next != NULL) {
5517 struct ifsregion *ifsp;
5519 ifsp = ifslastp->next->next;
5520 free(ifslastp->next);
5521 ifslastp->next = ifsp;
5524 if (ifslastp->endoff > endoff)
5525 ifslastp->endoff = endoff;
5529 exptilde(char *startp, char *p, int flag)
5535 int quotes = flag & (EXP_FULL | EXP_CASE);
5540 while ((c = *++p) != '\0') {
5547 if (flag & EXP_VARTILDE)
5557 if (*name == '\0') {
5558 home = lookupvar(homestr);
5560 pw = getpwnam(name);
5565 if (!home || !*home)
5568 startloc = expdest - (char *)stackblock();
5569 strtodest(home, SQSYNTAX, quotes);
5570 recordregion(startloc, expdest - (char *)stackblock(), 0);
5578 * Execute a command inside back quotes. If it's a builtin command, we
5579 * want to save its output in a block obtained from malloc. Otherwise
5580 * we fork off a subprocess and get the output of the command via a pipe.
5581 * Should be called with interrupts off.
5583 struct backcmd { /* result of evalbackcmd */
5584 int fd; /* file descriptor to read from */
5585 int nleft; /* number of chars in buffer */
5586 char *buf; /* buffer */
5587 struct job *jp; /* job structure for command */
5590 /* These forward decls are needed to use "eval" code for backticks handling: */
5591 static uint8_t back_exitstatus; /* exit status of backquoted command */
5592 #define EV_EXIT 01 /* exit after evaluating tree */
5593 static void evaltree(union node *, int);
5596 evalbackcmd(union node *n, struct backcmd *result)
5607 saveherefd = herefd;
5615 ash_msg_and_raise_error("pipe call failed");
5616 jp = makejob(/*n,*/ 1);
5617 if (forkshell(jp, n, FORK_NOJOB) == 0) {
5622 copyfd(pip[1], 1 | COPYFD_EXACT);
5626 evaltree(n, EV_EXIT); /* actually evaltreenr... */
5630 result->fd = pip[0];
5633 herefd = saveherefd;
5635 TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n",
5636 result->fd, result->buf, result->nleft, result->jp));
5640 * Expand stuff in backwards quotes.
5643 expbackq(union node *cmd, int quoted, int quotes)
5651 int syntax = quoted ? DQSYNTAX : BASESYNTAX;
5652 struct stackmark smark;
5655 setstackmark(&smark);
5657 startloc = dest - (char *)stackblock();
5659 evalbackcmd(cmd, &in);
5660 popstackmark(&smark);
5667 memtodest(p, i, syntax, quotes);
5671 i = nonblock_safe_read(in.fd, buf, sizeof(buf));
5672 TRACE(("expbackq: read returns %d\n", i));
5681 back_exitstatus = waitforjob(in.jp);
5685 /* Eat all trailing newlines */
5687 for (; dest > (char *)stackblock() && dest[-1] == '\n';)
5692 recordregion(startloc, dest - (char *)stackblock(), 0);
5693 TRACE(("evalbackq: size=%d: \"%.*s\"\n",
5694 (dest - (char *)stackblock()) - startloc,
5695 (dest - (char *)stackblock()) - startloc,
5696 stackblock() + startloc));
5699 #if ENABLE_ASH_MATH_SUPPORT
5701 * Expand arithmetic expression. Backup to start of expression,
5702 * evaluate, place result in (backed up) result, adjust string position.
5715 * This routine is slightly over-complicated for
5716 * efficiency. Next we scan backwards looking for the
5717 * start of arithmetic.
5719 start = stackblock();
5726 while (*p != CTLARI) {
5730 ash_msg_and_raise_error("missing CTLARI (shouldn't happen)");
5735 esc = esclen(start, p);
5745 removerecordregions(begoff);
5754 len = cvtnum(dash_arith(p + 2));
5757 recordregion(begoff, begoff + len, 0);
5761 /* argstr needs it */
5762 static char *evalvar(char *p, int flag, struct strlist *var_str_list);
5765 * Perform variable and command substitution. If EXP_FULL is set, output CTLESC
5766 * characters to allow for further processing. Otherwise treat
5767 * $@ like $* since no splitting will be performed.
5769 * var_str_list (can be NULL) is a list of "VAR=val" strings which take precedence
5770 * over shell varables. Needed for "A=a B=$A; echo $B" case - we use it
5771 * for correct expansion of "B=$A" word.
5774 argstr(char *p, int flag, struct strlist *var_str_list)
5776 static const char spclchars[] ALIGN1 = {
5784 CTLBACKQ | CTLQUOTE,
5785 #if ENABLE_ASH_MATH_SUPPORT
5790 const char *reject = spclchars;
5792 int quotes = flag & (EXP_FULL | EXP_CASE); /* do CTLESC */
5793 int breakall = flag & EXP_WORD;
5798 if (!(flag & EXP_VARTILDE)) {
5800 } else if (flag & EXP_VARTILDE2) {
5805 if (flag & EXP_TILDE) {
5811 if (*q == CTLESC && (flag & EXP_QWORD))
5814 p = exptilde(p, q, flag);
5817 startloc = expdest - (char *)stackblock();
5819 length += strcspn(p + length, reject);
5821 if (c && (!(c & 0x80)
5822 #if ENABLE_ASH_MATH_SUPPORT
5826 /* c == '=' || c == ':' || c == CTLENDARI */
5831 expdest = stack_nputstr(p, length, expdest);
5832 newloc = expdest - (char *)stackblock();
5833 if (breakall && !inquotes && newloc > startloc) {
5834 recordregion(startloc, newloc, 0);
5845 if (flag & EXP_VARTILDE2) {
5849 flag |= EXP_VARTILDE2;
5854 * sort of a hack - expand tildes in variable
5855 * assignments (after the first '=' and after ':'s).
5864 case CTLENDVAR: /* ??? */
5867 /* "$@" syntax adherence hack */
5870 !memcmp(p, dolatstr, 4) &&
5871 (p[4] == CTLQUOTEMARK || (
5872 p[4] == CTLENDVAR &&
5873 p[5] == CTLQUOTEMARK
5876 p = evalvar(p + 1, flag, /* var_str_list: */ NULL) + 1;
5879 inquotes = !inquotes;
5892 p = evalvar(p, flag, var_str_list);
5896 case CTLBACKQ|CTLQUOTE:
5897 expbackq(argbackq->n, c, quotes);
5898 argbackq = argbackq->next;
5900 #if ENABLE_ASH_MATH_SUPPORT
5913 scanleft(char *startp, char *rmesc, char *rmescend UNUSED_PARAM, char *str, int quotes,
5916 // This commented out code was added by James Simmons <jsimmons@infradead.org>
5917 // as part of a larger change when he added support for ${var/a/b}.
5918 // However, it broke # and % operators:
5922 //echo ${var#ab} abcdcd abcdcd
5923 //echo ${var##ab} abcdcd abcdcd
5924 //echo ${var#a*b} abcdcd ababcdcd (!)
5925 //echo ${var##a*b} cdcd cdcd
5926 //echo ${var#?} babcdcd ababcdcd (!)
5927 //echo ${var##?} babcdcd babcdcd
5928 //echo ${var#*} ababcdcd babcdcd (!)
5930 //echo ${var%cd} ababcd ababcd
5931 //echo ${var%%cd} ababcd abab (!)
5932 //echo ${var%c*d} ababcd ababcd
5933 //echo ${var%%c*d} abab ababcdcd (!)
5934 //echo ${var%?} ababcdc ababcdc
5935 //echo ${var%%?} ababcdc ababcdcd (!)
5936 //echo ${var%*} ababcdcd ababcdcd
5939 // Commenting it back out helped. Remove it completely if it really
5942 char *loc, *loc2; //, *full;
5948 int match; // = strlen(str);
5949 const char *s = loc2;
5956 match = pmatch(str, s); // this line was deleted
5958 // // chop off end if its '*'
5959 // full = strrchr(str, '*');
5960 // if (full && full != str)
5963 // // If str starts with '*' replace with s.
5964 // if ((*str == '*') && strlen(s) >= match) {
5965 // full = xstrdup(s);
5966 // strncpy(full+strlen(s)-match+1, str+1, match-1);
5968 // full = xstrndup(str, match);
5969 // match = strncmp(s, full, strlen(full));
5973 if (match) // if (!match)
5975 if (quotes && *loc == CTLESC)
5984 scanright(char *startp, char *rmesc, char *rmescend, char *str, int quotes,
5991 for (loc = str - 1, loc2 = rmescend; loc >= startp; loc2--) {
5994 const char *s = loc2;
5999 match = pmatch(str, s);
6006 esc = esclen(startp, loc);
6017 static void varunset(const char *, const char *, const char *, int) NORETURN;
6019 varunset(const char *end, const char *var, const char *umsg, int varflags)
6025 msg = "parameter not set";
6027 if (*end == CTLENDVAR) {
6028 if (varflags & VSNUL)
6034 ash_msg_and_raise_error("%.*s: %s%s", end - var - 1, var, msg, tail);
6037 #if ENABLE_ASH_BASH_COMPAT
6039 parse_sub_pattern(char *arg, int inquotes)
6041 char *idx, *repl = NULL;
6050 /* Only the first '/' seen is our separator */
6057 if (!inquotes && c == '\\' && arg[1] == '\\')
6058 arg++; /* skip both \\, not just first one */
6065 #endif /* ENABLE_ASH_BASH_COMPAT */
6068 subevalvar(char *p, char *str, int strloc, int subtype,
6069 int startloc, int varflags, int quotes, struct strlist *var_str_list)
6071 struct nodelist *saveargbackq = argbackq;
6074 char *rmesc, *rmescend;
6075 USE_ASH_BASH_COMPAT(char *repl = NULL;)
6076 USE_ASH_BASH_COMPAT(char null = '\0';)
6077 USE_ASH_BASH_COMPAT(int pos, len, orig_len;)
6078 int saveherefd = herefd;
6079 int amount, workloc, resetloc;
6081 char *(*scan)(char*, char*, char*, char*, int, int);
6084 argstr(p, (subtype != VSASSIGN && subtype != VSQUESTION) ? EXP_CASE : 0,
6086 STPUTC('\0', expdest);
6087 herefd = saveherefd;
6088 argbackq = saveargbackq;
6089 startp = (char *)stackblock() + startloc;
6093 setvar(str, startp, 0);
6094 amount = startp - expdest;
6095 STADJUST(amount, expdest);
6098 #if ENABLE_ASH_BASH_COMPAT
6100 loc = str = stackblock() + strloc;
6101 // TODO: number() instead? It does error checking...
6103 len = str - startp - 1;
6105 /* *loc != '\0', guaranteed by parser */
6109 /* We must adjust the length by the number of escapes we find. */
6110 for (ptr = startp; ptr < (str - 1); ptr++) {
6111 if (*ptr == CTLESC) {
6119 if (*loc++ == ':') {
6120 // TODO: number() instead? It does error checking...
6124 while (*loc && *loc != ':')
6127 // TODO: number() instead? It does error checking...
6130 if (pos >= orig_len) {
6134 if (len > (orig_len - pos))
6135 len = orig_len - pos;
6137 for (str = startp; pos; str++, pos--) {
6138 if (quotes && *str == CTLESC)
6141 for (loc = startp; len; len--) {
6142 if (quotes && *str == CTLESC)
6147 amount = loc - expdest;
6148 STADJUST(amount, expdest);
6153 varunset(p, str, startp, varflags);
6156 resetloc = expdest - (char *)stackblock();
6158 /* We'll comeback here if we grow the stack while handling
6159 * a VSREPLACE or VSREPLACEALL, since our pointers into the
6160 * stack will need rebasing, and we'll need to remove our work
6163 USE_ASH_BASH_COMPAT(restart:)
6165 amount = expdest - ((char *)stackblock() + resetloc);
6166 STADJUST(-amount, expdest);
6167 startp = (char *)stackblock() + startloc;
6170 rmescend = (char *)stackblock() + strloc;
6172 rmesc = _rmescapes(startp, RMESCAPE_ALLOC | RMESCAPE_GROW);
6173 if (rmesc != startp) {
6175 startp = (char *)stackblock() + startloc;
6179 str = (char *)stackblock() + strloc;
6180 preglob(str, varflags & VSQUOTE, 0);
6181 workloc = expdest - (char *)stackblock();
6183 #if ENABLE_ASH_BASH_COMPAT
6184 if (subtype == VSREPLACE || subtype == VSREPLACEALL) {
6185 char *idx, *end, *restart_detect;
6188 repl = parse_sub_pattern(str, varflags & VSQUOTE);
6193 /* If there's no pattern to match, return the expansion unmolested */
6201 loc = scanright(idx, rmesc, rmescend, str, quotes, 1);
6203 /* No match, advance */
6204 restart_detect = stackblock();
6205 STPUTC(*idx, expdest);
6206 if (quotes && *idx == CTLESC) {
6209 STPUTC(*idx, expdest);
6211 if (stackblock() != restart_detect)
6219 if (subtype == VSREPLACEALL) {
6221 if (quotes && *idx == CTLESC)
6230 for (loc = repl; *loc; loc++) {
6231 restart_detect = stackblock();
6232 STPUTC(*loc, expdest);
6233 if (stackblock() != restart_detect)
6238 if (subtype == VSREPLACE) {
6240 restart_detect = stackblock();
6241 STPUTC(*idx, expdest);
6242 if (stackblock() != restart_detect)
6251 /* We've put the replaced text into a buffer at workloc, now
6252 * move it to the right place and adjust the stack.
6254 startp = stackblock() + startloc;
6255 STPUTC('\0', expdest);
6256 memmove(startp, stackblock() + workloc, len);
6257 startp[len++] = '\0';
6258 amount = expdest - ((char *)stackblock() + startloc + len - 1);
6259 STADJUST(-amount, expdest);
6262 #endif /* ENABLE_ASH_BASH_COMPAT */
6264 subtype -= VSTRIMRIGHT;
6266 if (subtype < 0 || subtype > 7)
6269 /* zero = subtype == VSTRIMLEFT || subtype == VSTRIMLEFTMAX */
6270 zero = subtype >> 1;
6271 /* VSTRIMLEFT/VSTRIMRIGHTMAX -> scanleft */
6272 scan = (subtype & 1) ^ zero ? scanleft : scanright;
6274 loc = scan(startp, rmesc, rmescend, str, quotes, zero);
6277 memmove(startp, loc, str - loc);
6278 loc = startp + (str - loc) - 1;
6281 amount = loc - expdest;
6282 STADJUST(amount, expdest);
6288 * Add the value of a specialized variable to the stack string.
6291 varvalue(char *name, int varflags, int flags, struct strlist *var_str_list)
6301 int quoted = varflags & VSQUOTE;
6302 int subtype = varflags & VSTYPE;
6303 int quotes = flags & (EXP_FULL | EXP_CASE);
6305 if (quoted && (flags & EXP_FULL))
6306 sep = 1 << CHAR_BIT;
6308 syntax = quoted ? DQSYNTAX : BASESYNTAX;
6317 num = shellparam.nparam;
6327 p = makestrspace(NOPTS, expdest);
6328 for (i = NOPTS - 1; i >= 0; i--) {
6330 USTPUTC(optletters(i), p);
6341 sep = ifsset() ? signed_char2int(ifsval()[0]) : ' ';
6342 if (quotes && (SIT(sep, syntax) == CCTL || SIT(sep, syntax) == CBACK))
6348 while ((p = *ap++)) {
6351 partlen = strlen(p);
6354 if (!(subtype == VSPLUS || subtype == VSLENGTH))
6355 memtodest(p, partlen, syntax, quotes);
6361 if (subtype == VSPLUS || subtype == VSLENGTH) {
6382 // TODO: number() instead? It does error checking...
6384 if (num < 0 || num > shellparam.nparam)
6386 p = num ? shellparam.p[num - 1] : arg0;
6389 /* NB: name has form "VAR=..." */
6391 /* "A=a B=$A" case: var_str_list is a list of "A=a" strings
6392 * which should be considered before we check variables. */
6394 unsigned name_len = (strchrnul(name, '=') - name) + 1;
6398 str = var_str_list->text;
6399 eq = strchr(str, '=');
6400 if (!eq) /* stop at first non-assignment */
6403 if (name_len == (unsigned)(eq - str)
6404 && strncmp(str, name, name_len) == 0) {
6406 /* goto value; - WRONG! */
6407 /* think "A=1 A=2 B=$A" */
6409 var_str_list = var_str_list->next;
6410 } while (var_str_list);
6414 p = lookupvar(name);
6420 if (!(subtype == VSPLUS || subtype == VSLENGTH))
6421 memtodest(p, len, syntax, quotes);
6425 if (subtype == VSPLUS || subtype == VSLENGTH)
6426 STADJUST(-len, expdest);
6431 * Expand a variable, and return a pointer to the next character in the
6435 evalvar(char *p, int flag, struct strlist *var_str_list)
6447 subtype = varflags & VSTYPE;
6448 quoted = varflags & VSQUOTE;
6450 easy = (!quoted || (*var == '@' && shellparam.nparam));
6451 startloc = expdest - (char *)stackblock();
6452 p = strchr(p, '=') + 1;
6455 varlen = varvalue(var, varflags, flag, var_str_list);
6456 if (varflags & VSNUL)
6459 if (subtype == VSPLUS) {
6460 varlen = -1 - varlen;
6464 if (subtype == VSMINUS) {
6468 p, flag | EXP_TILDE |
6469 (quoted ? EXP_QWORD : EXP_WORD),
6479 if (subtype == VSASSIGN || subtype == VSQUESTION) {
6481 if (subevalvar(p, var, /* strloc: */ 0,
6482 subtype, startloc, varflags,
6488 * Remove any recorded regions beyond
6491 removerecordregions(startloc);
6501 if (varlen < 0 && uflag)
6502 varunset(p, var, 0, 0);
6504 if (subtype == VSLENGTH) {
6505 cvtnum(varlen > 0 ? varlen : 0);
6509 if (subtype == VSNORMAL) {
6520 case VSTRIMRIGHTMAX:
6521 #if ENABLE_ASH_BASH_COMPAT
6534 * Terminate the string and start recording the pattern
6537 STPUTC('\0', expdest);
6538 patloc = expdest - (char *)stackblock();
6539 if (0 == subevalvar(p, /* str: */ NULL, patloc, subtype,
6541 /* quotes: */ flag & (EXP_FULL | EXP_CASE),
6544 int amount = expdest - (
6545 (char *)stackblock() + patloc - 1
6547 STADJUST(-amount, expdest);
6549 /* Remove any recorded regions beyond start of variable */
6550 removerecordregions(startloc);
6552 recordregion(startloc, expdest - (char *)stackblock(), quoted);
6556 if (subtype != VSNORMAL) { /* skip to end of alternative */
6562 else if (c == CTLBACKQ || c == (CTLBACKQ|CTLQUOTE)) {
6564 argbackq = argbackq->next;
6565 } else if (c == CTLVAR) {
6566 if ((*p++ & VSTYPE) != VSNORMAL)
6568 } else if (c == CTLENDVAR) {
6578 * Break the argument string into pieces based upon IFS and add the
6579 * strings to the argument list. The regions of the string to be
6580 * searched for IFS characters have been stored by recordregion.
6583 ifsbreakup(char *string, struct arglist *arglist)
6585 struct ifsregion *ifsp;
6590 const char *ifs, *realifs;
6595 if (ifslastp != NULL) {
6598 realifs = ifsset() ? ifsval() : defifs;
6601 p = string + ifsp->begoff;
6602 nulonly = ifsp->nulonly;
6603 ifs = nulonly ? nullstr : realifs;
6605 while (p < string + ifsp->endoff) {
6609 if (!strchr(ifs, *p)) {
6614 ifsspc = (strchr(defifs, *p) != NULL);
6615 /* Ignore IFS whitespace at start */
6616 if (q == start && ifsspc) {
6622 sp = stzalloc(sizeof(*sp));
6624 *arglist->lastp = sp;
6625 arglist->lastp = &sp->next;
6629 if (p >= string + ifsp->endoff) {
6635 if (strchr(ifs, *p) == NULL) {
6639 if (strchr(defifs, *p) == NULL) {
6654 } while (ifsp != NULL);
6663 sp = stzalloc(sizeof(*sp));
6665 *arglist->lastp = sp;
6666 arglist->lastp = &sp->next;
6672 struct ifsregion *p;
6677 struct ifsregion *ifsp;
6683 ifsfirst.next = NULL;
6688 * Add a file name to the list.
6691 addfname(const char *name)
6695 sp = stzalloc(sizeof(*sp));
6696 sp->text = ststrdup(name);
6698 exparg.lastp = &sp->next;
6701 static char *expdir;
6704 * Do metacharacter (i.e. *, ?, [...]) expansion.
6707 expmeta(char *enddir, char *name)
6722 for (p = name; *p; p++) {
6723 if (*p == '*' || *p == '?')
6725 else if (*p == '[') {
6732 if (*q == '/' || *q == '\0')
6739 } else if (*p == '\\')
6741 else if (*p == '/') {
6748 if (metaflag == 0) { /* we've reached the end of the file name */
6749 if (enddir != expdir)
6757 if (metaflag == 0 || lstat(expdir, &statb) >= 0)
6768 } while (p < start);
6770 if (enddir == expdir) {
6772 } else if (enddir == expdir + 1 && *expdir == '/') {
6781 if (enddir != expdir)
6783 if (*endname == 0) {
6795 while (!intpending && (dp = readdir(dirp)) != NULL) {
6796 if (dp->d_name[0] == '.' && !matchdot)
6798 if (pmatch(start, dp->d_name)) {
6800 strcpy(enddir, dp->d_name);
6803 for (p = enddir, cp = dp->d_name; (*p++ = *cp++) != '\0';)
6806 expmeta(p, endname);
6815 static struct strlist *
6816 msort(struct strlist *list, int len)
6818 struct strlist *p, *q = NULL;
6819 struct strlist **lpp;
6827 for (n = half; --n >= 0;) {
6831 q->next = NULL; /* terminate first half of list */
6832 q = msort(list, half); /* sort first half of list */
6833 p = msort(p, len - half); /* sort second half */
6836 #if ENABLE_LOCALE_SUPPORT
6837 if (strcoll(p->text, q->text) < 0)
6839 if (strcmp(p->text, q->text) < 0)
6863 * Sort the results of file name expansion. It calculates the number of
6864 * strings to sort and then calls msort (short for merge sort) to do the
6867 static struct strlist *
6868 expsort(struct strlist *str)
6874 for (sp = str; sp; sp = sp->next)
6876 return msort(str, len);
6880 expandmeta(struct strlist *str /*, int flag*/)
6882 static const char metachars[] ALIGN1 = {
6885 /* TODO - EXP_REDIR */
6888 struct strlist **savelastp;
6894 if (!strpbrk(str->text, metachars))
6896 savelastp = exparg.lastp;
6899 p = preglob(str->text, 0, RMESCAPE_ALLOC | RMESCAPE_HEAP);
6901 int i = strlen(str->text);
6902 expdir = ckmalloc(i < 2048 ? 2048 : i); /* XXX */
6910 if (exparg.lastp == savelastp) {
6915 *exparg.lastp = str;
6916 rmescapes(str->text);
6917 exparg.lastp = &str->next;
6919 *exparg.lastp = NULL;
6920 *savelastp = sp = expsort(*savelastp);
6921 while (sp->next != NULL)
6923 exparg.lastp = &sp->next;
6930 * Perform variable substitution and command substitution on an argument,
6931 * placing the resulting list of arguments in arglist. If EXP_FULL is true,
6932 * perform splitting and file name expansion. When arglist is NULL, perform
6933 * here document expansion.
6936 expandarg(union node *arg, struct arglist *arglist, int flag)
6941 argbackq = arg->narg.backquote;
6942 STARTSTACKSTR(expdest);
6943 ifsfirst.next = NULL;
6945 argstr(arg->narg.text, flag,
6946 /* var_str_list: */ arglist ? arglist->list : NULL);
6947 p = _STPUTC('\0', expdest);
6949 if (arglist == NULL) {
6950 return; /* here document expanded */
6952 p = grabstackstr(p);
6953 exparg.lastp = &exparg.list;
6957 if (flag & EXP_FULL) {
6958 ifsbreakup(p, &exparg);
6959 *exparg.lastp = NULL;
6960 exparg.lastp = &exparg.list;
6961 expandmeta(exparg.list /*, flag*/);
6963 if (flag & EXP_REDIR) /*XXX - for now, just remove escapes */
6965 sp = stzalloc(sizeof(*sp));
6968 exparg.lastp = &sp->next;
6972 *exparg.lastp = NULL;
6974 *arglist->lastp = exparg.list;
6975 arglist->lastp = exparg.lastp;
6980 * Expand shell variables and backquotes inside a here document.
6983 expandhere(union node *arg, int fd)
6986 expandarg(arg, (struct arglist *)NULL, 0);
6987 full_write(fd, stackblock(), expdest - (char *)stackblock());
6991 * Returns true if the pattern matches the string.
6994 patmatch(char *pattern, const char *string)
6996 return pmatch(preglob(pattern, 0, 0), string);
7000 * See if a pattern matches in a case statement.
7003 casematch(union node *pattern, char *val)
7005 struct stackmark smark;
7008 setstackmark(&smark);
7009 argbackq = pattern->narg.backquote;
7010 STARTSTACKSTR(expdest);
7012 argstr(pattern->narg.text, EXP_TILDE | EXP_CASE,
7013 /* var_str_list: */ NULL);
7014 STACKSTRNUL(expdest);
7015 result = patmatch(stackblock(), val);
7016 popstackmark(&smark);
7021 /* ============ find_command */
7025 int (*builtin)(int, char **);
7026 /* unsigned flags; */
7028 #define IS_BUILTIN_SPECIAL(b) ((b)->name[0] & 1)
7029 /* "regular" builtins always take precedence over commands,
7030 * regardless of PATH=....%builtin... position */
7031 #define IS_BUILTIN_REGULAR(b) ((b)->name[0] & 2)
7032 #define IS_BUILTIN_ASSIGN(b) ((b)->name[0] & 4)
7035 smallint cmdtype; /* CMDxxx */
7038 /* index >= 0 for commands without path (slashes) */
7039 /* (TODO: what exactly does the value mean? PATH position?) */
7040 /* index == -1 for commands with slashes */
7041 /* index == (-2 - applet_no) for NOFORK applets */
7042 const struct builtincmd *cmd;
7043 struct funcnode *func;
7046 /* values of cmdtype */
7047 #define CMDUNKNOWN -1 /* no entry in table for command */
7048 #define CMDNORMAL 0 /* command is an executable program */
7049 #define CMDFUNCTION 1 /* command is a shell function */
7050 #define CMDBUILTIN 2 /* command is a shell builtin */
7052 /* action to find_command() */
7053 #define DO_ERR 0x01 /* prints errors */
7054 #define DO_ABS 0x02 /* checks absolute paths */
7055 #define DO_NOFUNC 0x04 /* don't return shell functions, for command */
7056 #define DO_ALTPATH 0x08 /* using alternate path */
7057 #define DO_ALTBLTIN 0x20 /* %builtin in alt. path */
7059 static void find_command(char *, struct cmdentry *, int, const char *);
7062 /* ============ Hashing commands */
7065 * When commands are first encountered, they are entered in a hash table.
7066 * This ensures that a full path search will not have to be done for them
7067 * on each invocation.
7069 * We should investigate converting to a linear search, even though that
7070 * would make the command name "hash" a misnomer.
7074 struct tblentry *next; /* next entry in hash chain */
7075 union param param; /* definition of builtin function */
7076 smallint cmdtype; /* CMDxxx */
7077 char rehash; /* if set, cd done since entry created */
7078 char cmdname[1]; /* name of command */
7081 static struct tblentry **cmdtable;
7082 #define INIT_G_cmdtable() do { \
7083 cmdtable = xzalloc(CMDTABLESIZE * sizeof(cmdtable[0])); \
7086 static int builtinloc = -1; /* index in path of %builtin, or -1 */
7090 tryexec(USE_FEATURE_SH_STANDALONE(int applet_no,) char *cmd, char **argv, char **envp)
7094 #if ENABLE_FEATURE_SH_STANDALONE
7095 if (applet_no >= 0) {
7096 if (APPLET_IS_NOEXEC(applet_no)) {
7099 run_applet_no_and_exit(applet_no, argv);
7101 /* re-exec ourselves with the new arguments */
7102 execve(bb_busybox_exec_path, argv, envp);
7103 /* If they called chroot or otherwise made the binary no longer
7104 * executable, fall through */
7111 execve(cmd, argv, envp);
7112 } while (errno == EINTR);
7114 execve(cmd, argv, envp);
7120 if (errno == ENOEXEC) {
7124 for (ap = argv; *ap; ap++)
7126 ap = new = ckmalloc((ap - argv + 2) * sizeof(ap[0]));
7128 ap[0] = cmd = (char *)DEFAULT_SHELL;
7131 while ((*ap++ = *argv++) != NULL)
7140 * Exec a program. Never returns. If you change this routine, you may
7141 * have to change the find_command routine as well.
7143 static void shellexec(char **, const char *, int) NORETURN;
7145 shellexec(char **argv, const char *path, int idx)
7151 #if ENABLE_FEATURE_SH_STANDALONE
7155 clearredir(/*drop:*/ 1);
7156 envp = listvars(VEXPORT, VUNSET, 0);
7157 if (strchr(argv[0], '/') != NULL
7158 #if ENABLE_FEATURE_SH_STANDALONE
7159 || (applet_no = find_applet_by_name(argv[0])) >= 0
7162 tryexec(USE_FEATURE_SH_STANDALONE(applet_no,) argv[0], argv, envp);
7166 while ((cmdname = padvance(&path, argv[0])) != NULL) {
7167 if (--idx < 0 && pathopt == NULL) {
7168 tryexec(USE_FEATURE_SH_STANDALONE(-1,) cmdname, argv, envp);
7169 if (errno != ENOENT && errno != ENOTDIR)
7176 /* Map to POSIX errors */
7188 exitstatus = exerrno;
7189 TRACE(("shellexec failed for %s, errno %d, suppressint %d\n",
7190 argv[0], e, suppressint));
7191 ash_msg_and_raise(EXEXEC, "%s: %s", argv[0], errmsg(e, "not found"));
7196 printentry(struct tblentry *cmdp)
7202 idx = cmdp->param.index;
7205 name = padvance(&path, cmdp->cmdname);
7207 } while (--idx >= 0);
7208 out1fmt("%s%s\n", name, (cmdp->rehash ? "*" : nullstr));
7212 * Clear out command entries. The argument specifies the first entry in
7213 * PATH which has changed.
7216 clearcmdentry(int firstchange)
7218 struct tblentry **tblp;
7219 struct tblentry **pp;
7220 struct tblentry *cmdp;
7223 for (tblp = cmdtable; tblp < &cmdtable[CMDTABLESIZE]; tblp++) {
7225 while ((cmdp = *pp) != NULL) {
7226 if ((cmdp->cmdtype == CMDNORMAL &&
7227 cmdp->param.index >= firstchange)
7228 || (cmdp->cmdtype == CMDBUILTIN &&
7229 builtinloc >= firstchange)
7242 * Locate a command in the command hash table. If "add" is nonzero,
7243 * add the command to the table if it is not already present. The
7244 * variable "lastcmdentry" is set to point to the address of the link
7245 * pointing to the entry, so that delete_cmd_entry can delete the
7248 * Interrupts must be off if called with add != 0.
7250 static struct tblentry **lastcmdentry;
7252 static struct tblentry *
7253 cmdlookup(const char *name, int add)
7255 unsigned int hashval;
7257 struct tblentry *cmdp;
7258 struct tblentry **pp;
7261 hashval = (unsigned char)*p << 4;
7263 hashval += (unsigned char)*p++;
7265 pp = &cmdtable[hashval % CMDTABLESIZE];
7266 for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
7267 if (strcmp(cmdp->cmdname, name) == 0)
7271 if (add && cmdp == NULL) {
7272 cmdp = *pp = ckzalloc(sizeof(struct tblentry)
7274 /* + 1 - already done because
7275 * tblentry::cmdname is char[1] */);
7276 /*cmdp->next = NULL; - ckzalloc did it */
7277 cmdp->cmdtype = CMDUNKNOWN;
7278 strcpy(cmdp->cmdname, name);
7285 * Delete the command entry returned on the last lookup.
7288 delete_cmd_entry(void)
7290 struct tblentry *cmdp;
7293 cmdp = *lastcmdentry;
7294 *lastcmdentry = cmdp->next;
7295 if (cmdp->cmdtype == CMDFUNCTION)
7296 freefunc(cmdp->param.func);
7302 * Add a new command entry, replacing any existing command entry for
7303 * the same name - except special builtins.
7306 addcmdentry(char *name, struct cmdentry *entry)
7308 struct tblentry *cmdp;
7310 cmdp = cmdlookup(name, 1);
7311 if (cmdp->cmdtype == CMDFUNCTION) {
7312 freefunc(cmdp->param.func);
7314 cmdp->cmdtype = entry->cmdtype;
7315 cmdp->param = entry->u;
7320 hashcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
7322 struct tblentry **pp;
7323 struct tblentry *cmdp;
7325 struct cmdentry entry;
7328 if (nextopt("r") != '\0') {
7333 if (*argptr == NULL) {
7334 for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
7335 for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
7336 if (cmdp->cmdtype == CMDNORMAL)
7344 while ((name = *argptr) != NULL) {
7345 cmdp = cmdlookup(name, 0);
7347 && (cmdp->cmdtype == CMDNORMAL
7348 || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0))
7352 find_command(name, &entry, DO_ERR, pathval());
7353 if (entry.cmdtype == CMDUNKNOWN)
7361 * Called when a cd is done. Marks all commands so the next time they
7362 * are executed they will be rehashed.
7367 struct tblentry **pp;
7368 struct tblentry *cmdp;
7370 for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
7371 for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
7372 if (cmdp->cmdtype == CMDNORMAL
7373 || (cmdp->cmdtype == CMDBUILTIN
7374 && !IS_BUILTIN_REGULAR(cmdp->param.cmd)
7384 * Fix command hash table when PATH changed.
7385 * Called before PATH is changed. The argument is the new value of PATH;
7386 * pathval() still returns the old value at this point.
7387 * Called with interrupts off.
7390 changepath(const char *new)
7398 firstchange = 9999; /* assume no change */
7404 if ((*old == '\0' && *new == ':')
7405 || (*old == ':' && *new == '\0'))
7407 old = new; /* ignore subsequent differences */
7411 if (*new == '%' && idx_bltin < 0 && prefix(new + 1, "builtin"))
7417 if (builtinloc < 0 && idx_bltin >= 0)
7418 builtinloc = idx_bltin; /* zap builtins */
7419 if (builtinloc >= 0 && idx_bltin < 0)
7421 clearcmdentry(firstchange);
7422 builtinloc = idx_bltin;
7437 #define TENDBQUOTE 12
7454 typedef smallint token_id_t;
7456 /* first char is indicating which tokens mark the end of a list */
7457 static const char *const tokname_array[] = {
7471 #define KWDOFFSET 13
7472 /* the following are keywords */
7494 static char buf[16];
7497 //if (tok < TSEMI) return tokname_array[tok] + 1;
7498 //sprintf(buf, "\"%s\"", tokname_array[tok] + 1);
7503 sprintf(buf + (tok >= TSEMI), "%s%c",
7504 tokname_array[tok] + 1, (tok >= TSEMI ? '"' : 0));
7508 /* Wrapper around strcmp for qsort/bsearch/... */
7510 pstrcmp(const void *a, const void *b)
7512 return strcmp((char*) a, (*(char**) b) + 1);
7515 static const char *const *
7516 findkwd(const char *s)
7518 return bsearch(s, tokname_array + KWDOFFSET,
7519 ARRAY_SIZE(tokname_array) - KWDOFFSET,
7520 sizeof(tokname_array[0]), pstrcmp);
7524 * Locate and print what a word is...
7527 describe_command(char *command, int describe_command_verbose)
7529 struct cmdentry entry;
7530 struct tblentry *cmdp;
7531 #if ENABLE_ASH_ALIAS
7532 const struct alias *ap;
7534 const char *path = pathval();
7536 if (describe_command_verbose) {
7540 /* First look at the keywords */
7541 if (findkwd(command)) {
7542 out1str(describe_command_verbose ? " is a shell keyword" : command);
7546 #if ENABLE_ASH_ALIAS
7547 /* Then look at the aliases */
7548 ap = lookupalias(command, 0);
7550 if (!describe_command_verbose) {
7555 out1fmt(" is an alias for %s", ap->val);
7559 /* Then check if it is a tracked alias */
7560 cmdp = cmdlookup(command, 0);
7562 entry.cmdtype = cmdp->cmdtype;
7563 entry.u = cmdp->param;
7565 /* Finally use brute force */
7566 find_command(command, &entry, DO_ABS, path);
7569 switch (entry.cmdtype) {
7571 int j = entry.u.index;
7577 p = padvance(&path, command);
7581 if (describe_command_verbose) {
7583 (cmdp ? " a tracked alias for" : nullstr), p
7592 if (describe_command_verbose) {
7593 out1str(" is a shell function");
7600 if (describe_command_verbose) {
7601 out1fmt(" is a %sshell builtin",
7602 IS_BUILTIN_SPECIAL(entry.u.cmd) ?
7603 "special " : nullstr
7611 if (describe_command_verbose) {
7612 out1str(": not found\n");
7617 outstr("\n", stdout);
7622 typecmd(int argc UNUSED_PARAM, char **argv)
7628 /* type -p ... ? (we don't bother checking for 'p') */
7629 if (argv[1] && argv[1][0] == '-') {
7634 err |= describe_command(argv[i++], verbose);
7639 #if ENABLE_ASH_CMDCMD
7641 commandcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
7649 while ((c = nextopt("pvV")) != '\0')
7651 verify |= VERIFY_VERBOSE;
7653 verify |= VERIFY_BRIEF;
7658 /* Mimic bash: just "command -v" doesn't complain, it's a nop */
7659 if (verify && (*argptr != NULL)) {
7660 return describe_command(*argptr, verify - VERIFY_BRIEF);
7668 /* ============ eval.c */
7670 static int funcblocksize; /* size of structures in function */
7671 static int funcstringsize; /* size of strings in node */
7672 static void *funcblock; /* block to allocate function from */
7673 static char *funcstring; /* block to allocate strings from */
7675 /* flags in argument to evaltree */
7676 #define EV_EXIT 01 /* exit after evaluating tree */
7677 #define EV_TESTED 02 /* exit status is checked; ignore -e flag */
7678 #define EV_BACKCMD 04 /* command executing within back quotes */
7680 static const short nodesize[N_NUMBER] = {
7681 [NCMD ] = SHELL_ALIGN(sizeof(struct ncmd)),
7682 [NPIPE ] = SHELL_ALIGN(sizeof(struct npipe)),
7683 [NREDIR ] = SHELL_ALIGN(sizeof(struct nredir)),
7684 [NBACKGND ] = SHELL_ALIGN(sizeof(struct nredir)),
7685 [NSUBSHELL] = SHELL_ALIGN(sizeof(struct nredir)),
7686 [NAND ] = SHELL_ALIGN(sizeof(struct nbinary)),
7687 [NOR ] = SHELL_ALIGN(sizeof(struct nbinary)),
7688 [NSEMI ] = SHELL_ALIGN(sizeof(struct nbinary)),
7689 [NIF ] = SHELL_ALIGN(sizeof(struct nif)),
7690 [NWHILE ] = SHELL_ALIGN(sizeof(struct nbinary)),
7691 [NUNTIL ] = SHELL_ALIGN(sizeof(struct nbinary)),
7692 [NFOR ] = SHELL_ALIGN(sizeof(struct nfor)),
7693 [NCASE ] = SHELL_ALIGN(sizeof(struct ncase)),
7694 [NCLIST ] = SHELL_ALIGN(sizeof(struct nclist)),
7695 [NDEFUN ] = SHELL_ALIGN(sizeof(struct narg)),
7696 [NARG ] = SHELL_ALIGN(sizeof(struct narg)),
7697 [NTO ] = SHELL_ALIGN(sizeof(struct nfile)),
7698 #if ENABLE_ASH_BASH_COMPAT
7699 [NTO2 ] = SHELL_ALIGN(sizeof(struct nfile)),
7701 [NCLOBBER ] = SHELL_ALIGN(sizeof(struct nfile)),
7702 [NFROM ] = SHELL_ALIGN(sizeof(struct nfile)),
7703 [NFROMTO ] = SHELL_ALIGN(sizeof(struct nfile)),
7704 [NAPPEND ] = SHELL_ALIGN(sizeof(struct nfile)),
7705 [NTOFD ] = SHELL_ALIGN(sizeof(struct ndup)),
7706 [NFROMFD ] = SHELL_ALIGN(sizeof(struct ndup)),
7707 [NHERE ] = SHELL_ALIGN(sizeof(struct nhere)),
7708 [NXHERE ] = SHELL_ALIGN(sizeof(struct nhere)),
7709 [NNOT ] = SHELL_ALIGN(sizeof(struct nnot)),
7712 static void calcsize(union node *n);
7715 sizenodelist(struct nodelist *lp)
7718 funcblocksize += SHELL_ALIGN(sizeof(struct nodelist));
7725 calcsize(union node *n)
7729 funcblocksize += nodesize[n->type];
7732 calcsize(n->ncmd.redirect);
7733 calcsize(n->ncmd.args);
7734 calcsize(n->ncmd.assign);
7737 sizenodelist(n->npipe.cmdlist);
7742 calcsize(n->nredir.redirect);
7743 calcsize(n->nredir.n);
7750 calcsize(n->nbinary.ch2);
7751 calcsize(n->nbinary.ch1);
7754 calcsize(n->nif.elsepart);
7755 calcsize(n->nif.ifpart);
7756 calcsize(n->nif.test);
7759 funcstringsize += strlen(n->nfor.var) + 1;
7760 calcsize(n->nfor.body);
7761 calcsize(n->nfor.args);
7764 calcsize(n->ncase.cases);
7765 calcsize(n->ncase.expr);
7768 calcsize(n->nclist.body);
7769 calcsize(n->nclist.pattern);
7770 calcsize(n->nclist.next);
7774 sizenodelist(n->narg.backquote);
7775 funcstringsize += strlen(n->narg.text) + 1;
7776 calcsize(n->narg.next);
7779 #if ENABLE_ASH_BASH_COMPAT
7786 calcsize(n->nfile.fname);
7787 calcsize(n->nfile.next);
7791 calcsize(n->ndup.vname);
7792 calcsize(n->ndup.next);
7796 calcsize(n->nhere.doc);
7797 calcsize(n->nhere.next);
7800 calcsize(n->nnot.com);
7806 nodeckstrdup(char *s)
7808 char *rtn = funcstring;
7810 strcpy(funcstring, s);
7811 funcstring += strlen(s) + 1;
7815 static union node *copynode(union node *);
7817 static struct nodelist *
7818 copynodelist(struct nodelist *lp)
7820 struct nodelist *start;
7821 struct nodelist **lpp;
7826 funcblock = (char *) funcblock + SHELL_ALIGN(sizeof(struct nodelist));
7827 (*lpp)->n = copynode(lp->n);
7829 lpp = &(*lpp)->next;
7836 copynode(union node *n)
7843 funcblock = (char *) funcblock + nodesize[n->type];
7847 new->ncmd.redirect = copynode(n->ncmd.redirect);
7848 new->ncmd.args = copynode(n->ncmd.args);
7849 new->ncmd.assign = copynode(n->ncmd.assign);
7852 new->npipe.cmdlist = copynodelist(n->npipe.cmdlist);
7853 new->npipe.pipe_backgnd = n->npipe.pipe_backgnd;
7858 new->nredir.redirect = copynode(n->nredir.redirect);
7859 new->nredir.n = copynode(n->nredir.n);
7866 new->nbinary.ch2 = copynode(n->nbinary.ch2);
7867 new->nbinary.ch1 = copynode(n->nbinary.ch1);
7870 new->nif.elsepart = copynode(n->nif.elsepart);
7871 new->nif.ifpart = copynode(n->nif.ifpart);
7872 new->nif.test = copynode(n->nif.test);
7875 new->nfor.var = nodeckstrdup(n->nfor.var);
7876 new->nfor.body = copynode(n->nfor.body);
7877 new->nfor.args = copynode(n->nfor.args);
7880 new->ncase.cases = copynode(n->ncase.cases);
7881 new->ncase.expr = copynode(n->ncase.expr);
7884 new->nclist.body = copynode(n->nclist.body);
7885 new->nclist.pattern = copynode(n->nclist.pattern);
7886 new->nclist.next = copynode(n->nclist.next);
7890 new->narg.backquote = copynodelist(n->narg.backquote);
7891 new->narg.text = nodeckstrdup(n->narg.text);
7892 new->narg.next = copynode(n->narg.next);
7895 #if ENABLE_ASH_BASH_COMPAT
7902 new->nfile.fname = copynode(n->nfile.fname);
7903 new->nfile.fd = n->nfile.fd;
7904 new->nfile.next = copynode(n->nfile.next);
7908 new->ndup.vname = copynode(n->ndup.vname);
7909 new->ndup.dupfd = n->ndup.dupfd;
7910 new->ndup.fd = n->ndup.fd;
7911 new->ndup.next = copynode(n->ndup.next);
7915 new->nhere.doc = copynode(n->nhere.doc);
7916 new->nhere.fd = n->nhere.fd;
7917 new->nhere.next = copynode(n->nhere.next);
7920 new->nnot.com = copynode(n->nnot.com);
7923 new->type = n->type;
7928 * Make a copy of a parse tree.
7930 static struct funcnode *
7931 copyfunc(union node *n)
7936 funcblocksize = offsetof(struct funcnode, n);
7939 blocksize = funcblocksize;
7940 f = ckmalloc(blocksize + funcstringsize);
7941 funcblock = (char *) f + offsetof(struct funcnode, n);
7942 funcstring = (char *) f + blocksize;
7949 * Define a shell function.
7952 defun(char *name, union node *func)
7954 struct cmdentry entry;
7957 entry.cmdtype = CMDFUNCTION;
7958 entry.u.func = copyfunc(func);
7959 addcmdentry(name, &entry);
7963 /* Reasons for skipping commands (see comment on breakcmd routine) */
7964 #define SKIPBREAK (1 << 0)
7965 #define SKIPCONT (1 << 1)
7966 #define SKIPFUNC (1 << 2)
7967 #define SKIPFILE (1 << 3)
7968 #define SKIPEVAL (1 << 4)
7969 static smallint evalskip; /* set to SKIPxxx if we are skipping commands */
7970 static int skipcount; /* number of levels to skip */
7971 static int funcnest; /* depth of function calls */
7972 static int loopnest; /* current loop nesting level */
7974 /* Forward decl way out to parsing code - dotrap needs it */
7975 static int evalstring(char *s, int mask);
7977 /* Called to execute a trap.
7978 * Single callsite - at the end of evaltree().
7979 * If we return non-zero, exaltree raises EXEXIT exception.
7981 * Perhaps we should avoid entering new trap handlers
7982 * while we are executing a trap handler. [is it a TODO?]
7991 savestatus = exitstatus;
7995 TRACE(("dotrap entered\n"));
7996 for (sig = 1, g = gotsig; sig < NSIG; sig++, g++) {
8003 /* non-trapped SIGINT is handled separately by raise_interrupt,
8004 * don't upset it by resetting gotsig[SIGINT-1] */
8005 if (sig == SIGINT && !t)
8008 TRACE(("sig %d is active, will run handler '%s'\n", sig, t));
8012 want_exexit = evalstring(t, SKIPEVAL);
8013 exitstatus = savestatus;
8015 TRACE(("dotrap returns %d\n", want_exexit));
8020 TRACE(("dotrap returns 0\n"));
8024 /* forward declarations - evaluation is fairly recursive business... */
8025 static void evalloop(union node *, int);
8026 static void evalfor(union node *, int);
8027 static void evalcase(union node *, int);
8028 static void evalsubshell(union node *, int);
8029 static void expredir(union node *);
8030 static void evalpipe(union node *, int);
8031 static void evalcommand(union node *, int);
8032 static int evalbltin(const struct builtincmd *, int, char **);
8033 static void prehash(union node *);
8036 * Evaluate a parse tree. The value is left in the global variable
8040 evaltree(union node *n, int flags)
8042 struct jmploc *volatile savehandler = exception_handler;
8043 struct jmploc jmploc;
8045 void (*evalfn)(union node *, int);
8049 SAVE_INT(int_level);
8052 TRACE(("evaltree(NULL) called\n"));
8055 TRACE(("evaltree(%p: %d, %d) called\n", n, n->type, flags));
8057 exception_handler = &jmploc;
8059 int err = setjmp(jmploc.loc);
8061 /* if it was a signal, check for trap handlers */
8062 if (exception_type == EXSIG) {
8063 TRACE(("exception %d (EXSIG) in evaltree, err=%d\n",
8064 exception_type, err));
8067 /* continue on the way out */
8068 TRACE(("exception %d in evaltree, propagating err=%d\n",
8069 exception_type, err));
8070 exception_handler = savehandler;
8071 longjmp(exception_handler->loc, err);
8078 out1fmt("Node type = %d\n", n->type);
8083 evaltree(n->nnot.com, EV_TESTED);
8084 status = !exitstatus;
8087 expredir(n->nredir.redirect);
8088 status = redirectsafe(n->nredir.redirect, REDIR_PUSH);
8090 evaltree(n->nredir.n, flags & EV_TESTED);
8091 status = exitstatus;
8093 popredir(/*drop:*/ 0, /*restore:*/ 0 /* not sure */);
8096 evalfn = evalcommand;
8098 if (eflag && !(flags & EV_TESTED))
8110 evalfn = evalsubshell;
8123 #error NAND + 1 != NOR
8125 #if NOR + 1 != NSEMI
8126 #error NOR + 1 != NSEMI
8128 unsigned is_or = n->type - NAND;
8131 (flags | ((is_or >> 1) - 1)) & EV_TESTED
8133 if (!exitstatus == is_or)
8146 evaltree(n->nif.test, EV_TESTED);
8149 if (exitstatus == 0) {
8153 if (n->nif.elsepart) {
8154 n = n->nif.elsepart;
8159 defun(n->narg.text, n->narg.next);
8163 exitstatus = status;
8168 exception_handler = savehandler;
8170 if (checkexit & exitstatus)
8171 evalskip |= SKIPEVAL;
8172 else if (pendingsig && dotrap())
8175 if (flags & EV_EXIT) {
8177 raise_exception(EXEXIT);
8180 RESTORE_INT(int_level);
8181 TRACE(("leaving evaltree (no interrupts)\n"));
8184 #if !defined(__alpha__) || (defined(__GNUC__) && __GNUC__ >= 3)
8187 void evaltreenr(union node *, int) __attribute__ ((alias("evaltree"),__noreturn__));
8190 evalloop(union node *n, int flags)
8200 evaltree(n->nbinary.ch1, EV_TESTED);
8203 if (evalskip == SKIPCONT && --skipcount <= 0) {
8207 if (evalskip == SKIPBREAK && --skipcount <= 0)
8212 if (n->type != NWHILE)
8216 evaltree(n->nbinary.ch2, flags);
8217 status = exitstatus;
8222 exitstatus = status;
8226 evalfor(union node *n, int flags)
8228 struct arglist arglist;
8231 struct stackmark smark;
8233 setstackmark(&smark);
8234 arglist.list = NULL;
8235 arglist.lastp = &arglist.list;
8236 for (argp = n->nfor.args; argp; argp = argp->narg.next) {
8237 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE | EXP_RECORD);
8242 *arglist.lastp = NULL;
8247 for (sp = arglist.list; sp; sp = sp->next) {
8248 setvar(n->nfor.var, sp->text, 0);
8249 evaltree(n->nfor.body, flags);
8251 if (evalskip == SKIPCONT && --skipcount <= 0) {
8255 if (evalskip == SKIPBREAK && --skipcount <= 0)
8262 popstackmark(&smark);
8266 evalcase(union node *n, int flags)
8270 struct arglist arglist;
8271 struct stackmark smark;
8273 setstackmark(&smark);
8274 arglist.list = NULL;
8275 arglist.lastp = &arglist.list;
8276 expandarg(n->ncase.expr, &arglist, EXP_TILDE);
8278 for (cp = n->ncase.cases; cp && evalskip == 0; cp = cp->nclist.next) {
8279 for (patp = cp->nclist.pattern; patp; patp = patp->narg.next) {
8280 if (casematch(patp, arglist.list->text)) {
8281 if (evalskip == 0) {
8282 evaltree(cp->nclist.body, flags);
8289 popstackmark(&smark);
8293 * Kick off a subshell to evaluate a tree.
8296 evalsubshell(union node *n, int flags)
8299 int backgnd = (n->type == NBACKGND);
8302 expredir(n->nredir.redirect);
8303 if (!backgnd && flags & EV_EXIT && !trap[0])
8306 jp = makejob(/*n,*/ 1);
8307 if (forkshell(jp, n, backgnd) == 0) {
8311 flags &=~ EV_TESTED;
8313 redirect(n->nredir.redirect, 0);
8314 evaltreenr(n->nredir.n, flags);
8319 status = waitforjob(jp);
8320 exitstatus = status;
8325 * Compute the names of the files in a redirection list.
8327 static void fixredir(union node *, const char *, int);
8329 expredir(union node *n)
8333 for (redir = n; redir; redir = redir->nfile.next) {
8337 fn.lastp = &fn.list;
8338 switch (redir->type) {
8342 #if ENABLE_ASH_BASH_COMPAT
8347 expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
8348 #if ENABLE_ASH_BASH_COMPAT
8351 redir->nfile.expfname = fn.list->text;
8354 case NTOFD: /* >& */
8355 if (redir->ndup.vname) {
8356 expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE);
8357 if (fn.list == NULL)
8358 ash_msg_and_raise_error("redir error");
8359 #if ENABLE_ASH_BASH_COMPAT
8360 //FIXME: we used expandarg with different args!
8361 if (!isdigit_str9(fn.list->text)) {
8362 /* >&file, not >&fd */
8363 if (redir->nfile.fd != 1) /* 123>&file - BAD */
8364 ash_msg_and_raise_error("redir error");
8366 goto store_expfname;
8369 fixredir(redir, fn.list->text, 1);
8377 * Evaluate a pipeline. All the processes in the pipeline are children
8378 * of the process creating the pipeline. (This differs from some versions
8379 * of the shell, which make the last process in a pipeline the parent
8383 evalpipe(union node *n, int flags)
8386 struct nodelist *lp;
8391 TRACE(("evalpipe(0x%lx) called\n", (long)n));
8393 for (lp = n->npipe.cmdlist; lp; lp = lp->next)
8397 jp = makejob(/*n,*/ pipelen);
8399 for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
8403 if (pipe(pip) < 0) {
8405 ash_msg_and_raise_error("pipe call failed");
8408 if (forkshell(jp, lp->n, n->npipe.pipe_backgnd) == 0) {
8421 evaltreenr(lp->n, flags);
8427 /* Don't want to trigger debugging */
8431 if (n->npipe.pipe_backgnd == 0) {
8432 exitstatus = waitforjob(jp);
8433 TRACE(("evalpipe: job done exit status %d\n", exitstatus));
8439 * Controls whether the shell is interactive or not.
8442 setinteractive(int on)
8444 static smallint is_interactive;
8446 if (++on == is_interactive)
8448 is_interactive = on;
8452 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
8453 if (is_interactive > 1) {
8454 /* Looks like they want an interactive shell */
8455 static smallint did_banner;
8460 "%s built-in shell (ash)\n"
8461 "Enter 'help' for a list of built-in commands."
8476 setinteractive(iflag);
8478 #if ENABLE_FEATURE_EDITING_VI
8480 line_input_state->flags |= VI_MODE;
8482 line_input_state->flags &= ~VI_MODE;
8484 viflag = 0; /* forcibly keep the option off */
8488 static struct localvar *localvars;
8491 * Called after a function returns.
8492 * Interrupts must be off.
8497 struct localvar *lvp;
8500 while ((lvp = localvars) != NULL) {
8501 localvars = lvp->next;
8503 TRACE(("poplocalvar %s", vp ? vp->text : "-"));
8504 if (vp == NULL) { /* $- saved */
8505 memcpy(optlist, lvp->text, sizeof(optlist));
8506 free((char*)lvp->text);
8508 } else if ((lvp->flags & (VUNSET|VSTRFIXED)) == VUNSET) {
8512 (*vp->func)(strchrnul(lvp->text, '=') + 1);
8513 if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
8514 free((char*)vp->text);
8515 vp->flags = lvp->flags;
8516 vp->text = lvp->text;
8523 evalfun(struct funcnode *func, int argc, char **argv, int flags)
8525 volatile struct shparam saveparam;
8526 struct localvar *volatile savelocalvars;
8527 struct jmploc *volatile savehandler;
8528 struct jmploc jmploc;
8531 saveparam = shellparam;
8532 savelocalvars = localvars;
8533 e = setjmp(jmploc.loc);
8538 savehandler = exception_handler;
8539 exception_handler = &jmploc;
8541 shellparam.malloced = 0;
8545 shellparam.nparam = argc - 1;
8546 shellparam.p = argv + 1;
8547 #if ENABLE_ASH_GETOPTS
8548 shellparam.optind = 1;
8549 shellparam.optoff = -1;
8551 evaltree(&func->n, flags & EV_TESTED);
8557 localvars = savelocalvars;
8558 freeparam(&shellparam);
8559 shellparam = saveparam;
8560 exception_handler = savehandler;
8562 evalskip &= ~SKIPFUNC;
8566 #if ENABLE_ASH_CMDCMD
8568 parse_command_args(char **argv, const char **path)
8581 if (c == '-' && !*cp) {
8588 *path = bb_default_path;
8591 /* run 'typecmd' for other options */
8602 * Make a variable a local variable. When a variable is made local, it's
8603 * value and flags are saved in a localvar structure. The saved values
8604 * will be restored when the shell function returns. We handle the name
8605 * "-" as a special case.
8610 struct localvar *lvp;
8615 lvp = ckzalloc(sizeof(struct localvar));
8616 if (LONE_DASH(name)) {
8618 p = ckmalloc(sizeof(optlist));
8619 lvp->text = memcpy(p, optlist, sizeof(optlist));
8624 vpp = hashvar(name);
8625 vp = *findvar(vpp, name);
8626 eq = strchr(name, '=');
8629 setvareq(name, VSTRFIXED);
8631 setvar(name, NULL, VSTRFIXED);
8632 vp = *vpp; /* the new variable */
8633 lvp->flags = VUNSET;
8635 lvp->text = vp->text;
8636 lvp->flags = vp->flags;
8637 vp->flags |= VSTRFIXED|VTEXTFIXED;
8643 lvp->next = localvars;
8649 * The "local" command.
8652 localcmd(int argc UNUSED_PARAM, char **argv)
8657 while ((name = *argv++) != NULL) {
8664 falsecmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
8670 truecmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
8676 execcmd(int argc UNUSED_PARAM, char **argv)
8679 iflag = 0; /* exit on error */
8682 shellexec(argv + 1, pathval(), 0);
8688 * The return command.
8691 returncmd(int argc UNUSED_PARAM, char **argv)
8694 * If called outside a function, do what ksh does;
8695 * skip the rest of the file.
8697 evalskip = funcnest ? SKIPFUNC : SKIPFILE;
8698 return argv[1] ? number(argv[1]) : exitstatus;
8701 /* Forward declarations for builtintab[] */
8702 static int breakcmd(int, char **);
8703 static int dotcmd(int, char **);
8704 static int evalcmd(int, char **);
8705 static int exitcmd(int, char **);
8706 static int exportcmd(int, char **);
8707 #if ENABLE_ASH_GETOPTS
8708 static int getoptscmd(int, char **);
8710 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
8711 static int helpcmd(int, char **);
8713 #if ENABLE_ASH_MATH_SUPPORT
8714 static int letcmd(int, char **);
8716 static int readcmd(int, char **);
8717 static int setcmd(int, char **);
8718 static int shiftcmd(int, char **);
8719 static int timescmd(int, char **);
8720 static int trapcmd(int, char **);
8721 static int umaskcmd(int, char **);
8722 static int unsetcmd(int, char **);
8723 static int ulimitcmd(int, char **);
8725 #define BUILTIN_NOSPEC "0"
8726 #define BUILTIN_SPECIAL "1"
8727 #define BUILTIN_REGULAR "2"
8728 #define BUILTIN_SPEC_REG "3"
8729 #define BUILTIN_ASSIGN "4"
8730 #define BUILTIN_SPEC_ASSG "5"
8731 #define BUILTIN_REG_ASSG "6"
8732 #define BUILTIN_SPEC_REG_ASSG "7"
8734 /* We do not handle [[ expr ]] bashism bash-compatibly,
8735 * we make it a synonym of [ expr ].
8736 * Basically, word splitting and pathname expansion should NOT be performed
8738 * no word splitting: a="a b"; [[ $a = "a b" ]]; echo $? should print "0"
8739 * no pathname expansion: [[ /bin/m* = "/bin/m*" ]]; echo $? should print "0"
8740 * Additional operators:
8741 * || and && should work as -o and -a
8743 * Apart from the above, [[ expr ]] should work as [ expr ]
8746 #define echocmd echo_main
8747 #define printfcmd printf_main
8748 #define testcmd test_main
8750 /* Keep these in proper order since it is searched via bsearch() */
8751 static const struct builtincmd builtintab[] = {
8752 { BUILTIN_SPEC_REG ".", dotcmd },
8753 { BUILTIN_SPEC_REG ":", truecmd },
8754 #if ENABLE_ASH_BUILTIN_TEST
8755 { BUILTIN_REGULAR "[", testcmd },
8756 #if ENABLE_ASH_BASH_COMPAT
8757 { BUILTIN_REGULAR "[[", testcmd },
8760 #if ENABLE_ASH_ALIAS
8761 { BUILTIN_REG_ASSG "alias", aliascmd },
8764 { BUILTIN_REGULAR "bg", fg_bgcmd },
8766 { BUILTIN_SPEC_REG "break", breakcmd },
8767 { BUILTIN_REGULAR "cd", cdcmd },
8768 { BUILTIN_NOSPEC "chdir", cdcmd },
8769 #if ENABLE_ASH_CMDCMD
8770 { BUILTIN_REGULAR "command", commandcmd },
8772 { BUILTIN_SPEC_REG "continue", breakcmd },
8773 #if ENABLE_ASH_BUILTIN_ECHO
8774 { BUILTIN_REGULAR "echo", echocmd },
8776 { BUILTIN_SPEC_REG "eval", evalcmd },
8777 { BUILTIN_SPEC_REG "exec", execcmd },
8778 { BUILTIN_SPEC_REG "exit", exitcmd },
8779 { BUILTIN_SPEC_REG_ASSG "export", exportcmd },
8780 { BUILTIN_REGULAR "false", falsecmd },
8782 { BUILTIN_REGULAR "fg", fg_bgcmd },
8784 #if ENABLE_ASH_GETOPTS
8785 { BUILTIN_REGULAR "getopts", getoptscmd },
8787 { BUILTIN_NOSPEC "hash", hashcmd },
8788 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
8789 { BUILTIN_NOSPEC "help", helpcmd },
8792 { BUILTIN_REGULAR "jobs", jobscmd },
8793 { BUILTIN_REGULAR "kill", killcmd },
8795 #if ENABLE_ASH_MATH_SUPPORT
8796 { BUILTIN_NOSPEC "let", letcmd },
8798 { BUILTIN_ASSIGN "local", localcmd },
8799 #if ENABLE_ASH_BUILTIN_PRINTF
8800 { BUILTIN_REGULAR "printf", printfcmd },
8802 { BUILTIN_NOSPEC "pwd", pwdcmd },
8803 { BUILTIN_REGULAR "read", readcmd },
8804 { BUILTIN_SPEC_REG_ASSG "readonly", exportcmd },
8805 { BUILTIN_SPEC_REG "return", returncmd },
8806 { BUILTIN_SPEC_REG "set", setcmd },
8807 { BUILTIN_SPEC_REG "shift", shiftcmd },
8808 { BUILTIN_SPEC_REG "source", dotcmd },
8809 #if ENABLE_ASH_BUILTIN_TEST
8810 { BUILTIN_REGULAR "test", testcmd },
8812 { BUILTIN_SPEC_REG "times", timescmd },
8813 { BUILTIN_SPEC_REG "trap", trapcmd },
8814 { BUILTIN_REGULAR "true", truecmd },
8815 { BUILTIN_NOSPEC "type", typecmd },
8816 { BUILTIN_NOSPEC "ulimit", ulimitcmd },
8817 { BUILTIN_REGULAR "umask", umaskcmd },
8818 #if ENABLE_ASH_ALIAS
8819 { BUILTIN_REGULAR "unalias", unaliascmd },
8821 { BUILTIN_SPEC_REG "unset", unsetcmd },
8822 { BUILTIN_REGULAR "wait", waitcmd },
8825 /* Should match the above table! */
8826 #define COMMANDCMD (builtintab + \
8828 1 * ENABLE_ASH_BUILTIN_TEST + \
8829 1 * ENABLE_ASH_BUILTIN_TEST * ENABLE_ASH_BASH_COMPAT + \
8830 1 * ENABLE_ASH_ALIAS + \
8831 1 * ENABLE_ASH_JOB_CONTROL + \
8833 #define EXECCMD (builtintab + \
8835 1 * ENABLE_ASH_BUILTIN_TEST + \
8836 1 * ENABLE_ASH_BUILTIN_TEST * ENABLE_ASH_BASH_COMPAT + \
8837 1 * ENABLE_ASH_ALIAS + \
8838 1 * ENABLE_ASH_JOB_CONTROL + \
8840 1 * ENABLE_ASH_CMDCMD + \
8842 ENABLE_ASH_BUILTIN_ECHO + \
8846 * Search the table of builtin commands.
8848 static struct builtincmd *
8849 find_builtin(const char *name)
8851 struct builtincmd *bp;
8854 name, builtintab, ARRAY_SIZE(builtintab), sizeof(builtintab[0]),
8861 * Execute a simple command.
8864 isassignment(const char *p)
8866 const char *q = endofname(p);
8872 bltincmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
8874 /* Preserve exitstatus of a previous possible redirection
8875 * as POSIX mandates */
8876 return back_exitstatus;
8879 evalcommand(union node *cmd, int flags)
8881 static const struct builtincmd null_bltin = {
8882 "\0\0", bltincmd /* why three NULs? */
8884 struct stackmark smark;
8886 struct arglist arglist;
8887 struct arglist varlist;
8890 const struct strlist *sp;
8891 struct cmdentry cmdentry;
8898 struct builtincmd *bcmd;
8899 smallint cmd_is_exec;
8900 smallint pseudovarflag = 0;
8902 /* First expand the arguments. */
8903 TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
8904 setstackmark(&smark);
8905 back_exitstatus = 0;
8907 cmdentry.cmdtype = CMDBUILTIN;
8908 cmdentry.u.cmd = &null_bltin;
8909 varlist.lastp = &varlist.list;
8910 *varlist.lastp = NULL;
8911 arglist.lastp = &arglist.list;
8912 *arglist.lastp = NULL;
8915 if (cmd->ncmd.args) {
8916 bcmd = find_builtin(cmd->ncmd.args->narg.text);
8917 pseudovarflag = bcmd && IS_BUILTIN_ASSIGN(bcmd);
8920 for (argp = cmd->ncmd.args; argp; argp = argp->narg.next) {
8921 struct strlist **spp;
8923 spp = arglist.lastp;
8924 if (pseudovarflag && isassignment(argp->narg.text))
8925 expandarg(argp, &arglist, EXP_VARTILDE);
8927 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
8929 for (sp = *spp; sp; sp = sp->next)
8933 argv = nargv = stalloc(sizeof(char *) * (argc + 1));
8934 for (sp = arglist.list; sp; sp = sp->next) {
8935 TRACE(("evalcommand arg: %s\n", sp->text));
8936 *nargv++ = sp->text;
8941 if (iflag && funcnest == 0 && argc > 0)
8942 lastarg = nargv[-1];
8945 expredir(cmd->ncmd.redirect);
8946 status = redirectsafe(cmd->ncmd.redirect, REDIR_PUSH | REDIR_SAVEFD2);
8949 for (argp = cmd->ncmd.assign; argp; argp = argp->narg.next) {
8950 struct strlist **spp;
8953 spp = varlist.lastp;
8954 expandarg(argp, &varlist, EXP_VARTILDE);
8957 * Modify the command lookup path, if a PATH= assignment
8961 if (varequal(p, path))
8965 /* Print the command if xflag is set. */
8968 const char *p = " %s";
8971 fdprintf(preverrout_fd, p, expandstr(ps4val()));
8974 for (n = 0; n < 2; n++) {
8976 fdprintf(preverrout_fd, p, sp->text);
8984 safe_write(preverrout_fd, "\n", 1);
8990 /* Now locate the command. */
8992 const char *oldpath;
8993 int cmd_flag = DO_ERR;
8998 find_command(argv[0], &cmdentry, cmd_flag, path);
8999 if (cmdentry.cmdtype == CMDUNKNOWN) {
9005 /* implement bltin and command here */
9006 if (cmdentry.cmdtype != CMDBUILTIN)
9009 spclbltin = IS_BUILTIN_SPECIAL(cmdentry.u.cmd);
9010 if (cmdentry.u.cmd == EXECCMD)
9012 #if ENABLE_ASH_CMDCMD
9013 if (cmdentry.u.cmd == COMMANDCMD) {
9015 nargv = parse_command_args(argv, &path);
9018 argc -= nargv - argv;
9020 cmd_flag |= DO_NOFUNC;
9028 /* We have a redirection error. */
9030 raise_exception(EXERROR);
9032 exitstatus = status;
9036 /* Execute the command. */
9037 switch (cmdentry.cmdtype) {
9040 #if ENABLE_FEATURE_SH_NOFORK
9041 /* Hmmm... shouldn't it happen somewhere in forkshell() instead?
9042 * Why "fork off a child process if necessary" doesn't apply to NOFORK? */
9044 /* find_command() encodes applet_no as (-2 - applet_no) */
9045 int applet_no = (- cmdentry.u.index - 2);
9046 if (applet_no >= 0 && APPLET_IS_NOFORK(applet_no)) {
9047 listsetvar(varlist.list, VEXPORT|VSTACK);
9048 /* run <applet>_main() */
9049 exitstatus = run_nofork_applet(applet_no, argv);
9054 /* Fork off a child process if necessary. */
9055 if (!(flags & EV_EXIT) || trap[0]) {
9057 jp = makejob(/*cmd,*/ 1);
9058 if (forkshell(jp, cmd, FORK_FG) != 0) {
9059 exitstatus = waitforjob(jp);
9061 TRACE(("forked child exited with %d\n", exitstatus));
9066 listsetvar(varlist.list, VEXPORT|VSTACK);
9067 shellexec(argv, path, cmdentry.u.index);
9071 cmdenviron = varlist.list;
9073 struct strlist *list = cmdenviron;
9075 if (spclbltin > 0 || argc == 0) {
9077 if (cmd_is_exec && argc > 1)
9080 listsetvar(list, i);
9082 /* Tight loop with builtins only:
9083 * "while kill -0 $child; do true; done"
9084 * will never exit even if $child died, unless we do this
9085 * to reap the zombie and make kill detect that it's gone: */
9086 dowait(DOWAIT_NONBLOCK, NULL);
9088 if (evalbltin(cmdentry.u.cmd, argc, argv)) {
9090 int i = exception_type;
9095 exit_status = 128 + SIGINT;
9097 exit_status = 128 + pendingsig;
9098 exitstatus = exit_status;
9099 if (i == EXINT || spclbltin > 0) {
9101 longjmp(exception_handler->loc, 1);
9108 listsetvar(varlist.list, 0);
9109 /* See above for the rationale */
9110 dowait(DOWAIT_NONBLOCK, NULL);
9111 if (evalfun(cmdentry.u.func, argc, argv, flags))
9117 popredir(/*drop:*/ cmd_is_exec, /*restore:*/ cmd_is_exec);
9119 /* dsl: I think this is intended to be used to support
9120 * '_' in 'vi' command mode during line editing...
9121 * However I implemented that within libedit itself.
9123 setvar("_", lastarg, 0);
9125 popstackmark(&smark);
9129 evalbltin(const struct builtincmd *cmd, int argc, char **argv)
9131 char *volatile savecmdname;
9132 struct jmploc *volatile savehandler;
9133 struct jmploc jmploc;
9136 savecmdname = commandname;
9137 i = setjmp(jmploc.loc);
9140 savehandler = exception_handler;
9141 exception_handler = &jmploc;
9142 commandname = argv[0];
9144 optptr = NULL; /* initialize nextopt */
9145 exitstatus = (*cmd->builtin)(argc, argv);
9146 flush_stdout_stderr();
9148 exitstatus |= ferror(stdout);
9150 commandname = savecmdname;
9152 exception_handler = savehandler;
9158 goodname(const char *p)
9160 return !*endofname(p);
9165 * Search for a command. This is called before we fork so that the
9166 * location of the command will be available in the parent as well as
9167 * the child. The check for "goodname" is an overly conservative
9168 * check that the name will not be subject to expansion.
9171 prehash(union node *n)
9173 struct cmdentry entry;
9175 if (n->type == NCMD && n->ncmd.args && goodname(n->ncmd.args->narg.text))
9176 find_command(n->ncmd.args->narg.text, &entry, 0, pathval());
9180 /* ============ Builtin commands
9182 * Builtin commands whose functions are closely tied to evaluation
9183 * are implemented here.
9187 * Handle break and continue commands. Break, continue, and return are
9188 * all handled by setting the evalskip flag. The evaluation routines
9189 * above all check this flag, and if it is set they start skipping
9190 * commands rather than executing them. The variable skipcount is
9191 * the number of loops to break/continue, or the number of function
9192 * levels to return. (The latter is always 1.) It should probably
9193 * be an error to break out of more loops than exist, but it isn't
9194 * in the standard shell so we don't make it one here.
9197 breakcmd(int argc UNUSED_PARAM, char **argv)
9199 int n = argv[1] ? number(argv[1]) : 1;
9202 ash_msg_and_raise_error(illnum, argv[1]);
9206 evalskip = (**argv == 'c') ? SKIPCONT : SKIPBREAK;
9213 /* ============ input.c
9215 * This implements the input routines used by the parser.
9219 INPUT_PUSH_FILE = 1,
9220 INPUT_NOFILE_OK = 2,
9223 static smallint checkkwd;
9224 /* values of checkkwd variable */
9225 #define CHKALIAS 0x1
9230 * Push a string back onto the input at this current parsefile level.
9231 * We handle aliases this way.
9233 #if !ENABLE_ASH_ALIAS
9234 #define pushstring(s, ap) pushstring(s)
9237 pushstring(char *s, struct alias *ap)
9244 if (g_parsefile->strpush) {
9245 sp = ckzalloc(sizeof(*sp));
9246 sp->prev = g_parsefile->strpush;
9248 sp = &(g_parsefile->basestrpush);
9250 g_parsefile->strpush = sp;
9251 sp->prev_string = g_parsefile->next_to_pgetc;
9252 sp->prev_left_in_line = g_parsefile->left_in_line;
9253 #if ENABLE_ASH_ALIAS
9256 ap->flag |= ALIASINUSE;
9260 g_parsefile->next_to_pgetc = s;
9261 g_parsefile->left_in_line = len;
9268 struct strpush *sp = g_parsefile->strpush;
9271 #if ENABLE_ASH_ALIAS
9273 if (g_parsefile->next_to_pgetc[-1] == ' '
9274 || g_parsefile->next_to_pgetc[-1] == '\t'
9276 checkkwd |= CHKALIAS;
9278 if (sp->string != sp->ap->val) {
9281 sp->ap->flag &= ~ALIASINUSE;
9282 if (sp->ap->flag & ALIASDEAD) {
9283 unalias(sp->ap->name);
9287 g_parsefile->next_to_pgetc = sp->prev_string;
9288 g_parsefile->left_in_line = sp->prev_left_in_line;
9289 g_parsefile->strpush = sp->prev;
9290 if (sp != &(g_parsefile->basestrpush))
9295 //FIXME: BASH_COMPAT with "...&" does TWO pungetc():
9296 //it peeks whether it is &>, and then pushes back both chars.
9297 //This function needs to save last *next_to_pgetc to buf[0]
9298 //to make two pungetc() reliable. Currently,
9299 // pgetc (out of buf: does preadfd), pgetc, pungetc, pungetc won't work...
9304 char *buf = g_parsefile->buf;
9306 g_parsefile->next_to_pgetc = buf;
9307 #if ENABLE_FEATURE_EDITING
9309 if (!iflag || g_parsefile->fd != STDIN_FILENO)
9310 nr = nonblock_safe_read(g_parsefile->fd, buf, BUFSIZ - 1);
9312 #if ENABLE_FEATURE_TAB_COMPLETION
9313 line_input_state->path_lookup = pathval();
9315 nr = read_line_input(cmdedit_prompt, buf, BUFSIZ, line_input_state);
9317 /* Ctrl+C pressed */
9326 if (nr < 0 && errno == 0) {
9327 /* Ctrl+D pressed */
9332 nr = nonblock_safe_read(g_parsefile->fd, buf, BUFSIZ - 1);
9336 /* nonblock_safe_read() handles this problem */
9338 if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
9339 int flags = fcntl(0, F_GETFL);
9340 if (flags >= 0 && (flags & O_NONBLOCK)) {
9341 flags &= ~O_NONBLOCK;
9342 if (fcntl(0, F_SETFL, flags) >= 0) {
9343 out2str("sh: turning off NDELAY mode\n");
9354 * Refill the input buffer and return the next input character:
9356 * 1) If a string was pushed back on the input, pop it;
9357 * 2) If an EOF was pushed back (g_parsefile->left_in_line < -BIGNUM)
9358 * or we are reading from a string so we can't refill the buffer,
9360 * 3) If the is more stuff in this buffer, use it else call read to fill it.
9361 * 4) Process input up to the next newline, deleting nul characters.
9363 //#define pgetc_debug(...) bb_error_msg(__VA_ARGS__)
9364 #define pgetc_debug(...) ((void)0)
9366 * NB: due to SIT(c) internals (syntax_index_table[] vector),
9367 * pgetc() and related functions must return chars SIGN-EXTENDED into ints,
9368 * not zero-extended. Seems fragile to me. Affects only !USE_SIT_FUNCTION case,
9369 * so we can fix it by ditching !USE_SIT_FUNCTION if Unicode requires that.
9377 while (g_parsefile->strpush) {
9378 #if ENABLE_ASH_ALIAS
9379 if (g_parsefile->left_in_line == -1
9380 && g_parsefile->strpush->ap
9381 && g_parsefile->next_to_pgetc[-1] != ' '
9382 && g_parsefile->next_to_pgetc[-1] != '\t'
9384 pgetc_debug("preadbuffer PEOA");
9389 /* try "pgetc" now: */
9390 pgetc_debug("preadbuffer internal pgetc at %d:%p'%s'",
9391 g_parsefile->left_in_line,
9392 g_parsefile->next_to_pgetc,
9393 g_parsefile->next_to_pgetc);
9394 if (--g_parsefile->left_in_line >= 0)
9395 return (unsigned char)(*g_parsefile->next_to_pgetc++);
9397 /* on both branches above g_parsefile->left_in_line < 0.
9398 * "pgetc" needs refilling.
9401 /* -90 is our -BIGNUM. Below we use -99 to mark "EOF on read",
9402 * pungetc() may increment it a few times.
9403 * Assuming it won't increment it to less than -90.
9405 if (g_parsefile->left_in_line < -90 || g_parsefile->buf == NULL) {
9406 pgetc_debug("preadbuffer PEOF1");
9407 /* even in failure keep left_in_line and next_to_pgetc
9408 * in lock step, for correct multi-layer pungetc.
9409 * left_in_line was decremented before preadbuffer(),
9410 * must inc next_to_pgetc: */
9411 g_parsefile->next_to_pgetc++;
9415 more = g_parsefile->left_in_buffer;
9417 flush_stdout_stderr();
9421 /* don't try reading again */
9422 g_parsefile->left_in_line = -99;
9423 pgetc_debug("preadbuffer PEOF2");
9424 g_parsefile->next_to_pgetc++;
9429 /* Find out where's the end of line.
9430 * Set g_parsefile->left_in_line
9431 * and g_parsefile->left_in_buffer acordingly.
9432 * NUL chars are deleted.
9434 q = g_parsefile->next_to_pgetc;
9442 memmove(q, q + 1, more);
9446 g_parsefile->left_in_line = q - g_parsefile->next_to_pgetc - 1;
9452 g_parsefile->left_in_line = q - g_parsefile->next_to_pgetc - 1;
9453 if (g_parsefile->left_in_line < 0)
9458 g_parsefile->left_in_buffer = more;
9463 out2str(g_parsefile->next_to_pgetc);
9467 pgetc_debug("preadbuffer at %d:%p'%s'",
9468 g_parsefile->left_in_line,
9469 g_parsefile->next_to_pgetc,
9470 g_parsefile->next_to_pgetc);
9471 return signed_char2int(*g_parsefile->next_to_pgetc++);
9474 #define pgetc_as_macro() \
9475 (--g_parsefile->left_in_line >= 0 \
9476 ? signed_char2int(*g_parsefile->next_to_pgetc++) \
9483 pgetc_debug("pgetc_fast at %d:%p'%s'",
9484 g_parsefile->left_in_line,
9485 g_parsefile->next_to_pgetc,
9486 g_parsefile->next_to_pgetc);
9487 return pgetc_as_macro();
9490 #if ENABLE_ASH_OPTIMIZE_FOR_SIZE
9491 #define pgetc_fast() pgetc()
9493 #define pgetc_fast() pgetc_as_macro()
9497 * Same as pgetc(), but ignores PEOA.
9499 #if ENABLE_ASH_ALIAS
9505 pgetc_debug("pgetc_fast at %d:%p'%s'",
9506 g_parsefile->left_in_line,
9507 g_parsefile->next_to_pgetc,
9508 g_parsefile->next_to_pgetc);
9510 } while (c == PEOA);
9514 #define pgetc2() pgetc()
9518 * Read a line from the script.
9521 pfgets(char *line, int len)
9527 while (--nleft > 0) {
9543 * Undo the last call to pgetc. Only one character may be pushed back.
9544 * PEOF may be pushed back.
9549 g_parsefile->left_in_line++;
9550 g_parsefile->next_to_pgetc--;
9551 pgetc_debug("pushed back to %d:%p'%s'",
9552 g_parsefile->left_in_line,
9553 g_parsefile->next_to_pgetc,
9554 g_parsefile->next_to_pgetc);
9558 * To handle the "." command, a stack of input files is used. Pushfile
9559 * adds a new entry to the stack and popfile restores the previous level.
9564 struct parsefile *pf;
9566 pf = ckzalloc(sizeof(*pf));
9567 pf->prev = g_parsefile;
9569 /*pf->strpush = NULL; - ckzalloc did it */
9570 /*pf->basestrpush.prev = NULL;*/
9577 struct parsefile *pf = g_parsefile;
9585 g_parsefile = pf->prev;
9591 * Return to top level.
9596 while (g_parsefile != &basepf)
9601 * Close the file(s) that the shell is reading commands from. Called
9602 * after a fork is done.
9608 if (g_parsefile->fd > 0) {
9609 close(g_parsefile->fd);
9610 g_parsefile->fd = 0;
9615 * Like setinputfile, but takes an open file descriptor. Call this with
9619 setinputfd(int fd, int push)
9621 close_on_exec_on(fd);
9624 g_parsefile->buf = NULL;
9626 g_parsefile->fd = fd;
9627 if (g_parsefile->buf == NULL)
9628 g_parsefile->buf = ckmalloc(IBUFSIZ);
9629 g_parsefile->left_in_buffer = 0;
9630 g_parsefile->left_in_line = 0;
9631 g_parsefile->linno = 1;
9635 * Set the input to take input from a file. If push is set, push the
9636 * old input onto the stack first.
9639 setinputfile(const char *fname, int flags)
9645 fd = open(fname, O_RDONLY);
9647 if (flags & INPUT_NOFILE_OK)
9649 ash_msg_and_raise_error("can't open '%s'", fname);
9652 fd2 = copyfd(fd, 10);
9655 ash_msg_and_raise_error("out of file descriptors");
9658 setinputfd(fd, flags & INPUT_PUSH_FILE);
9665 * Like setinputfile, but takes input from a string.
9668 setinputstring(char *string)
9672 g_parsefile->next_to_pgetc = string;
9673 g_parsefile->left_in_line = strlen(string);
9674 g_parsefile->buf = NULL;
9675 g_parsefile->linno = 1;
9680 /* ============ mail.c
9682 * Routines to check for mail.
9687 #define MAXMBOXES 10
9689 /* times of mailboxes */
9690 static time_t mailtime[MAXMBOXES];
9691 /* Set if MAIL or MAILPATH is changed. */
9692 static smallint mail_var_path_changed;
9695 * Print appropriate message(s) if mail has arrived.
9696 * If mail_var_path_changed is set,
9697 * then the value of MAIL has mail_var_path_changed,
9698 * so we just update the values.
9707 struct stackmark smark;
9710 setstackmark(&smark);
9711 mpath = mpathset() ? mpathval() : mailval();
9712 for (mtp = mailtime; mtp < mailtime + MAXMBOXES; mtp++) {
9713 p = padvance(&mpath, nullstr);
9718 for (q = p; *q; q++)
9724 q[-1] = '\0'; /* delete trailing '/' */
9725 if (stat(p, &statb) < 0) {
9729 if (!mail_var_path_changed && statb.st_mtime != *mtp) {
9732 pathopt ? pathopt : "you have mail"
9735 *mtp = statb.st_mtime;
9737 mail_var_path_changed = 0;
9738 popstackmark(&smark);
9742 changemail(const char *val UNUSED_PARAM)
9744 mail_var_path_changed = 1;
9747 #endif /* ASH_MAIL */
9750 /* ============ ??? */
9753 * Set the shell parameters.
9756 setparam(char **argv)
9762 for (nparam = 0; argv[nparam]; nparam++)
9764 ap = newparam = ckmalloc((nparam + 1) * sizeof(*ap));
9766 *ap++ = ckstrdup(*argv++);
9769 freeparam(&shellparam);
9770 shellparam.malloced = 1;
9771 shellparam.nparam = nparam;
9772 shellparam.p = newparam;
9773 #if ENABLE_ASH_GETOPTS
9774 shellparam.optind = 1;
9775 shellparam.optoff = -1;
9780 * Process shell options. The global variable argptr contains a pointer
9781 * to the argument list; we advance it past the options.
9783 * SUSv3 section 2.8.1 "Consequences of Shell Errors" says:
9784 * For a non-interactive shell, an error condition encountered
9785 * by a special built-in ... shall cause the shell to write a diagnostic message
9786 * to standard error and exit as shown in the following table:
9787 * Error Special Built-In
9789 * Utility syntax error (option or operand error) Shall exit
9791 * However, in bug 1142 (http://busybox.net/bugs/view.php?id=1142)
9792 * we see that bash does not do that (set "finishes" with error code 1 instead,
9793 * and shell continues), and people rely on this behavior!
9795 * set -o barfoo 2>/dev/null
9798 * Oh well. Let's mimic that.
9801 plus_minus_o(char *name, int val)
9806 for (i = 0; i < NOPTS; i++) {
9807 if (strcmp(name, optnames(i)) == 0) {
9812 ash_msg("illegal option %co %s", val ? '-' : '+', name);
9815 for (i = 0; i < NOPTS; i++) {
9817 out1fmt("%-16s%s\n", optnames(i), optlist[i] ? "on" : "off");
9819 out1fmt("set %co %s\n", optlist[i] ? '-' : '+', optnames(i));
9825 setoption(int flag, int val)
9829 for (i = 0; i < NOPTS; i++) {
9830 if (optletters(i) == flag) {
9835 ash_msg_and_raise_error("illegal option %c%c", val ? '-' : '+', flag);
9839 options(int cmdline)
9847 while ((p = *argptr) != NULL) {
9849 if (c != '-' && c != '+')
9852 val = 0; /* val = 0 if c == '+' */
9855 if (p[0] == '\0' || LONE_DASH(p)) {
9857 /* "-" means turn off -x and -v */
9860 /* "--" means reset params */
9861 else if (*argptr == NULL)
9864 break; /* "-" or "--" terminates options */
9867 /* first char was + or - */
9868 while ((c = *p++) != '\0') {
9869 /* bash 3.2 indeed handles -c CMD and +c CMD the same */
9870 if (c == 'c' && cmdline) {
9871 minusc = p; /* command is after shell args */
9872 } else if (c == 'o') {
9873 if (plus_minus_o(*argptr, val)) {
9874 /* it already printed err message */
9875 return 1; /* error */
9879 } else if (cmdline && (c == 'l')) { /* -l or +l == --login */
9881 /* bash does not accept +-login, we also won't */
9882 } else if (cmdline && val && (c == '-')) { /* long options */
9883 if (strcmp(p, "login") == 0)
9895 * The shift builtin command.
9898 shiftcmd(int argc UNUSED_PARAM, char **argv)
9905 n = number(argv[1]);
9906 if (n > shellparam.nparam)
9907 n = 0; /* bash compat, was = shellparam.nparam; */
9909 shellparam.nparam -= n;
9910 for (ap1 = shellparam.p; --n >= 0; ap1++) {
9911 if (shellparam.malloced)
9915 while ((*ap2++ = *ap1++) != NULL)
9917 #if ENABLE_ASH_GETOPTS
9918 shellparam.optind = 1;
9919 shellparam.optoff = -1;
9926 * POSIX requires that 'set' (but not export or readonly) output the
9927 * variables in lexicographic order - by the locale's collating order (sigh).
9928 * Maybe we could keep them in an ordered balanced binary tree
9929 * instead of hashed lists.
9930 * For now just roll 'em through qsort for printing...
9933 showvars(const char *sep_prefix, int on, int off)
9938 ep = listvars(on, off, &epend);
9939 qsort(ep, epend - ep, sizeof(char *), vpcmp);
9941 sep = *sep_prefix ? " " : sep_prefix;
9943 for (; ep < epend; ep++) {
9947 p = strchrnul(*ep, '=');
9950 q = single_quote(++p);
9951 out1fmt("%s%s%.*s%s\n", sep_prefix, sep, (int)(p - *ep), *ep, q);
9957 * The set command builtin.
9960 setcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9965 return showvars(nullstr, 0, VUNSET);
9968 if (!options(0)) { /* if no parse error... */
9971 if (*argptr != NULL) {
9979 #if ENABLE_ASH_RANDOM_SUPPORT
9981 change_random(const char *value)
9983 /* Galois LFSR parameter */
9984 /* Taps at 32 31 29 1: */
9985 enum { MASK = 0x8000000b };
9986 /* Another example - taps at 32 31 30 10: */
9987 /* MASK = 0x00400007 */
9989 if (value == NULL) {
9990 /* "get", generate */
9993 /* LCG has period of 2^32 and alternating lowest bit */
9994 random_LCG = 1664525 * random_LCG + 1013904223;
9995 /* Galois LFSR has period of 2^32-1 = 3 * 5 * 17 * 257 * 65537 */
9996 t = (random_galois_LFSR << 1);
9997 if (random_galois_LFSR < 0) /* if we just shifted 1 out of msb... */
9999 random_galois_LFSR = t;
10000 /* Both are weak, combining them gives better randomness
10001 * and ~2^64 period. & 0x7fff is probably bash compat
10002 * for $RANDOM range. Combining with subtraction is
10003 * just for fun. + and ^ would work equally well. */
10004 t = (t - random_LCG) & 0x7fff;
10005 /* set without recursion */
10006 setvar(vrandom.text, utoa(t), VNOFUNC);
10007 vrandom.flags &= ~VNOFUNC;
10010 random_galois_LFSR = random_LCG = strtoul(value, (char **)NULL, 10);
10015 #if ENABLE_ASH_GETOPTS
10017 getopts(char *optstr, char *optvar, char **optfirst, int *param_optind, int *optoff)
10026 if (*param_optind < 1)
10028 optnext = optfirst + *param_optind - 1;
10030 if (*param_optind <= 1 || *optoff < 0 || (int)strlen(optnext[-1]) < *optoff)
10033 p = optnext[-1] + *optoff;
10034 if (p == NULL || *p == '\0') {
10035 /* Current word is done, advance */
10037 if (p == NULL || *p != '-' || *++p == '\0') {
10044 if (LONE_DASH(p)) /* check for "--" */
10049 for (q = optstr; *q != c;) {
10051 if (optstr[0] == ':') {
10054 err |= setvarsafe("OPTARG", s, 0);
10056 fprintf(stderr, "Illegal option -%c\n", c);
10057 unsetvar("OPTARG");
10067 if (*p == '\0' && (p = *optnext) == NULL) {
10068 if (optstr[0] == ':') {
10071 err |= setvarsafe("OPTARG", s, 0);
10074 fprintf(stderr, "No arg for -%c option\n", c);
10075 unsetvar("OPTARG");
10083 err |= setvarsafe("OPTARG", p, 0);
10086 err |= setvarsafe("OPTARG", nullstr, 0);
10088 *optoff = p ? p - *(optnext - 1) : -1;
10089 *param_optind = optnext - optfirst + 1;
10090 fmtstr(s, sizeof(s), "%d", *param_optind);
10091 err |= setvarsafe("OPTIND", s, VNOFUNC);
10094 err |= setvarsafe(optvar, s, 0);
10098 flush_stdout_stderr();
10099 raise_exception(EXERROR);
10105 * The getopts builtin. Shellparam.optnext points to the next argument
10106 * to be processed. Shellparam.optptr points to the next character to
10107 * be processed in the current argument. If shellparam.optnext is NULL,
10108 * then it's the first time getopts has been called.
10111 getoptscmd(int argc, char **argv)
10116 ash_msg_and_raise_error("usage: getopts optstring var [arg]");
10118 optbase = shellparam.p;
10119 if (shellparam.optind > shellparam.nparam + 1) {
10120 shellparam.optind = 1;
10121 shellparam.optoff = -1;
10124 optbase = &argv[3];
10125 if (shellparam.optind > argc - 2) {
10126 shellparam.optind = 1;
10127 shellparam.optoff = -1;
10131 return getopts(argv[1], argv[2], optbase, &shellparam.optind,
10132 &shellparam.optoff);
10134 #endif /* ASH_GETOPTS */
10137 /* ============ Shell parser */
10140 struct heredoc *next; /* next here document in list */
10141 union node *here; /* redirection node */
10142 char *eofmark; /* string indicating end of input */
10143 smallint striptabs; /* if set, strip leading tabs */
10146 static smallint tokpushback; /* last token pushed back */
10147 static smallint parsebackquote; /* nonzero if we are inside backquotes */
10148 static smallint quoteflag; /* set if (part of) last token was quoted */
10149 static token_id_t lasttoken; /* last token read (integer id Txxx) */
10150 static struct heredoc *heredoclist; /* list of here documents to read */
10151 static char *wordtext; /* text of last word returned by readtoken */
10152 static struct nodelist *backquotelist;
10153 static union node *redirnode;
10154 static struct heredoc *heredoc;
10156 * NEOF is returned by parsecmd when it encounters an end of file. It
10157 * must be distinct from NULL, so we use the address of a variable that
10158 * happens to be handy.
10160 #define NEOF ((union node *)&tokpushback)
10162 static void raise_error_syntax(const char *) NORETURN;
10164 raise_error_syntax(const char *msg)
10166 ash_msg_and_raise_error("syntax error: %s", msg);
10171 * Called when an unexpected token is read during the parse. The argument
10172 * is the token that is expected, or -1 if more than one type of token can
10173 * occur at this point.
10175 static void raise_error_unexpected_syntax(int) NORETURN;
10177 raise_error_unexpected_syntax(int token)
10182 l = sprintf(msg, "unexpected %s", tokname(lasttoken));
10184 sprintf(msg + l, " (expecting %s)", tokname(token));
10185 raise_error_syntax(msg);
10189 #define EOFMARKLEN 79
10191 /* parsing is heavily cross-recursive, need these forward decls */
10192 static union node *andor(void);
10193 static union node *pipeline(void);
10194 static union node *parse_command(void);
10195 static void parseheredoc(void);
10196 static char peektoken(void);
10197 static int readtoken(void);
10199 static union node *
10202 union node *n1, *n2, *n3;
10205 checkkwd = CHKNL | CHKKWD | CHKALIAS;
10206 if (nlflag == 2 && peektoken())
10212 if (tok == TBACKGND) {
10213 if (n2->type == NPIPE) {
10214 n2->npipe.pipe_backgnd = 1;
10216 if (n2->type != NREDIR) {
10217 n3 = stzalloc(sizeof(struct nredir));
10219 /*n3->nredir.redirect = NULL; - stzalloc did it */
10222 n2->type = NBACKGND;
10228 n3 = stzalloc(sizeof(struct nbinary));
10230 n3->nbinary.ch1 = n1;
10231 n3->nbinary.ch2 = n2;
10247 checkkwd = CHKNL | CHKKWD | CHKALIAS;
10255 pungetc(); /* push back EOF on input */
10259 raise_error_unexpected_syntax(-1);
10266 static union node *
10269 union node *n1, *n2, *n3;
10277 } else if (t == TOR) {
10283 checkkwd = CHKNL | CHKKWD | CHKALIAS;
10285 n3 = stzalloc(sizeof(struct nbinary));
10287 n3->nbinary.ch1 = n1;
10288 n3->nbinary.ch2 = n2;
10293 static union node *
10296 union node *n1, *n2, *pipenode;
10297 struct nodelist *lp, *prev;
10301 TRACE(("pipeline: entered\n"));
10302 if (readtoken() == TNOT) {
10304 checkkwd = CHKKWD | CHKALIAS;
10307 n1 = parse_command();
10308 if (readtoken() == TPIPE) {
10309 pipenode = stzalloc(sizeof(struct npipe));
10310 pipenode->type = NPIPE;
10311 /*pipenode->npipe.pipe_backgnd = 0; - stzalloc did it */
10312 lp = stzalloc(sizeof(struct nodelist));
10313 pipenode->npipe.cmdlist = lp;
10317 lp = stzalloc(sizeof(struct nodelist));
10318 checkkwd = CHKNL | CHKKWD | CHKALIAS;
10319 lp->n = parse_command();
10321 } while (readtoken() == TPIPE);
10327 n2 = stzalloc(sizeof(struct nnot));
10335 static union node *
10340 n = stzalloc(sizeof(struct narg));
10342 /*n->narg.next = NULL; - stzalloc did it */
10343 n->narg.text = wordtext;
10344 n->narg.backquote = backquotelist;
10349 fixredir(union node *n, const char *text, int err)
10353 TRACE(("Fix redir %s %d\n", text, err));
10355 n->ndup.vname = NULL;
10357 fd = bb_strtou(text, NULL, 10);
10358 if (!errno && fd >= 0)
10359 n->ndup.dupfd = fd;
10360 else if (LONE_DASH(text))
10361 n->ndup.dupfd = -1;
10364 raise_error_syntax("bad fd number");
10365 n->ndup.vname = makename();
10370 * Returns true if the text contains nothing to expand (no dollar signs
10374 noexpand(const char *text)
10380 while ((c = *p++) != '\0') {
10381 if (c == CTLQUOTEMARK)
10385 else if (SIT((signed char)c, BASESYNTAX) == CCTL)
10394 union node *n = redirnode;
10396 if (readtoken() != TWORD)
10397 raise_error_unexpected_syntax(-1);
10398 if (n->type == NHERE) {
10399 struct heredoc *here = heredoc;
10403 if (quoteflag == 0)
10405 TRACE(("Here document %d\n", n->type));
10406 if (!noexpand(wordtext) || (i = strlen(wordtext)) == 0 || i > EOFMARKLEN)
10407 raise_error_syntax("illegal eof marker for << redirection");
10408 rmescapes(wordtext);
10409 here->eofmark = wordtext;
10411 if (heredoclist == NULL)
10412 heredoclist = here;
10414 for (p = heredoclist; p->next; p = p->next)
10418 } else if (n->type == NTOFD || n->type == NFROMFD) {
10419 fixredir(n, wordtext, 0);
10421 n->nfile.fname = makename();
10425 static union node *
10428 union node *args, **app;
10429 union node *n = NULL;
10430 union node *vars, **vpp;
10431 union node **rpp, *redir;
10433 #if ENABLE_ASH_BASH_COMPAT
10434 smallint double_brackets_flag = 0;
10444 savecheckkwd = CHKALIAS;
10447 checkkwd = savecheckkwd;
10450 #if ENABLE_ASH_BASH_COMPAT
10451 case TAND: /* "&&" */
10452 case TOR: /* "||" */
10453 if (!double_brackets_flag) {
10457 wordtext = (char *) (t == TAND ? "-a" : "-o");
10460 n = stzalloc(sizeof(struct narg));
10462 /*n->narg.next = NULL; - stzalloc did it */
10463 n->narg.text = wordtext;
10464 #if ENABLE_ASH_BASH_COMPAT
10465 if (strcmp("[[", wordtext) == 0)
10466 double_brackets_flag = 1;
10467 else if (strcmp("]]", wordtext) == 0)
10468 double_brackets_flag = 0;
10470 n->narg.backquote = backquotelist;
10471 if (savecheckkwd && isassignment(wordtext)) {
10473 vpp = &n->narg.next;
10476 app = &n->narg.next;
10481 *rpp = n = redirnode;
10482 rpp = &n->nfile.next;
10483 parsefname(); /* read name of redirection file */
10486 if (args && app == &args->narg.next
10489 struct builtincmd *bcmd;
10492 /* We have a function */
10493 if (readtoken() != TRP)
10494 raise_error_unexpected_syntax(TRP);
10495 name = n->narg.text;
10496 if (!goodname(name)
10497 || ((bcmd = find_builtin(name)) && IS_BUILTIN_SPECIAL(bcmd))
10499 raise_error_syntax("bad function name");
10502 checkkwd = CHKNL | CHKKWD | CHKALIAS;
10503 n->narg.next = parse_command();
10516 n = stzalloc(sizeof(struct ncmd));
10518 n->ncmd.args = args;
10519 n->ncmd.assign = vars;
10520 n->ncmd.redirect = redir;
10524 static union node *
10525 parse_command(void)
10527 union node *n1, *n2;
10528 union node *ap, **app;
10529 union node *cp, **cpp;
10530 union node *redir, **rpp;
10537 switch (readtoken()) {
10539 raise_error_unexpected_syntax(-1);
10542 n1 = stzalloc(sizeof(struct nif));
10544 n1->nif.test = list(0);
10545 if (readtoken() != TTHEN)
10546 raise_error_unexpected_syntax(TTHEN);
10547 n1->nif.ifpart = list(0);
10549 while (readtoken() == TELIF) {
10550 n2->nif.elsepart = stzalloc(sizeof(struct nif));
10551 n2 = n2->nif.elsepart;
10553 n2->nif.test = list(0);
10554 if (readtoken() != TTHEN)
10555 raise_error_unexpected_syntax(TTHEN);
10556 n2->nif.ifpart = list(0);
10558 if (lasttoken == TELSE)
10559 n2->nif.elsepart = list(0);
10561 n2->nif.elsepart = NULL;
10569 n1 = stzalloc(sizeof(struct nbinary));
10570 n1->type = (lasttoken == TWHILE) ? NWHILE : NUNTIL;
10571 n1->nbinary.ch1 = list(0);
10574 TRACE(("expecting DO got %s %s\n", tokname(got),
10575 got == TWORD ? wordtext : ""));
10576 raise_error_unexpected_syntax(TDO);
10578 n1->nbinary.ch2 = list(0);
10583 if (readtoken() != TWORD || quoteflag || !goodname(wordtext))
10584 raise_error_syntax("bad for loop variable");
10585 n1 = stzalloc(sizeof(struct nfor));
10587 n1->nfor.var = wordtext;
10588 checkkwd = CHKKWD | CHKALIAS;
10589 if (readtoken() == TIN) {
10591 while (readtoken() == TWORD) {
10592 n2 = stzalloc(sizeof(struct narg));
10594 /*n2->narg.next = NULL; - stzalloc did it */
10595 n2->narg.text = wordtext;
10596 n2->narg.backquote = backquotelist;
10598 app = &n2->narg.next;
10601 n1->nfor.args = ap;
10602 if (lasttoken != TNL && lasttoken != TSEMI)
10603 raise_error_unexpected_syntax(-1);
10605 n2 = stzalloc(sizeof(struct narg));
10607 /*n2->narg.next = NULL; - stzalloc did it */
10608 n2->narg.text = (char *)dolatstr;
10609 /*n2->narg.backquote = NULL;*/
10610 n1->nfor.args = n2;
10612 * Newline or semicolon here is optional (but note
10613 * that the original Bourne shell only allowed NL).
10615 if (lasttoken != TNL && lasttoken != TSEMI)
10618 checkkwd = CHKNL | CHKKWD | CHKALIAS;
10619 if (readtoken() != TDO)
10620 raise_error_unexpected_syntax(TDO);
10621 n1->nfor.body = list(0);
10625 n1 = stzalloc(sizeof(struct ncase));
10627 if (readtoken() != TWORD)
10628 raise_error_unexpected_syntax(TWORD);
10629 n1->ncase.expr = n2 = stzalloc(sizeof(struct narg));
10631 /*n2->narg.next = NULL; - stzalloc did it */
10632 n2->narg.text = wordtext;
10633 n2->narg.backquote = backquotelist;
10635 checkkwd = CHKKWD | CHKALIAS;
10636 } while (readtoken() == TNL);
10637 if (lasttoken != TIN)
10638 raise_error_unexpected_syntax(TIN);
10639 cpp = &n1->ncase.cases;
10641 checkkwd = CHKNL | CHKKWD;
10643 while (t != TESAC) {
10644 if (lasttoken == TLP)
10646 *cpp = cp = stzalloc(sizeof(struct nclist));
10648 app = &cp->nclist.pattern;
10650 *app = ap = stzalloc(sizeof(struct narg));
10652 /*ap->narg.next = NULL; - stzalloc did it */
10653 ap->narg.text = wordtext;
10654 ap->narg.backquote = backquotelist;
10655 if (readtoken() != TPIPE)
10657 app = &ap->narg.next;
10660 //ap->narg.next = NULL;
10661 if (lasttoken != TRP)
10662 raise_error_unexpected_syntax(TRP);
10663 cp->nclist.body = list(2);
10665 cpp = &cp->nclist.next;
10667 checkkwd = CHKNL | CHKKWD;
10671 raise_error_unexpected_syntax(TENDCASE);
10678 n1 = stzalloc(sizeof(struct nredir));
10679 n1->type = NSUBSHELL;
10680 n1->nredir.n = list(0);
10681 /*n1->nredir.redirect = NULL; - stzalloc did it */
10691 return simplecmd();
10694 if (readtoken() != t)
10695 raise_error_unexpected_syntax(t);
10698 /* Now check for redirection which may follow command */
10699 checkkwd = CHKKWD | CHKALIAS;
10701 while (readtoken() == TREDIR) {
10702 *rpp = n2 = redirnode;
10703 rpp = &n2->nfile.next;
10709 if (n1->type != NSUBSHELL) {
10710 n2 = stzalloc(sizeof(struct nredir));
10715 n1->nredir.redirect = redir;
10720 #if ENABLE_ASH_BASH_COMPAT
10721 static int decode_dollar_squote(void)
10723 static const char C_escapes[] ALIGN1 = "nrbtfav""x\\01234567";
10729 p = strchr(C_escapes, c);
10734 if ((unsigned char)(c - '0') <= 7) { /* \ooo */
10738 } while ((unsigned char)(c - '0') <= 7 && --cnt);
10740 } else if (c == 'x') { /* \xHH */
10744 } while (isxdigit(c) && --cnt);
10746 if (cnt == 3) { /* \x but next char is "bad" */
10750 } else { /* simple seq like \\ or \t */
10755 c = bb_process_escape_sequence((void*)&p);
10756 } else { /* unrecognized "\z": print both chars unless ' or " */
10757 if (c != '\'' && c != '"') {
10759 c |= 0x100; /* "please encode \, then me" */
10767 * If eofmark is NULL, read a word or a redirection symbol. If eofmark
10768 * is not NULL, read a here document. In the latter case, eofmark is the
10769 * word which marks the end of the document and striptabs is true if
10770 * leading tabs should be stripped from the document. The argument firstc
10771 * is the first character of the input token or document.
10773 * Because C does not have internal subroutines, I have simulated them
10774 * using goto's to implement the subroutine linkage. The following macros
10775 * will run code that appears at the end of readtoken1.
10777 #define CHECKEND() {goto checkend; checkend_return:;}
10778 #define PARSEREDIR() {goto parseredir; parseredir_return:;}
10779 #define PARSESUB() {goto parsesub; parsesub_return:;}
10780 #define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
10781 #define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
10782 #define PARSEARITH() {goto parsearith; parsearith_return:;}
10784 readtoken1(int firstc, int syntax, char *eofmark, int striptabs)
10786 /* NB: syntax parameter fits into smallint */
10790 char line[EOFMARKLEN + 1];
10791 struct nodelist *bqlist;
10795 smallint prevsyntax; /* syntax before arithmetic */
10796 #if ENABLE_ASH_EXPAND_PRMT
10797 smallint pssyntax; /* we are expanding a prompt string */
10799 int varnest; /* levels of variables expansion */
10800 int arinest; /* levels of arithmetic expansion */
10801 int parenlevel; /* levels of parens in arithmetic */
10802 int dqvarnest; /* levels of variables expansion within double quotes */
10804 USE_ASH_BASH_COMPAT(smallint bash_dollar_squote = 0;)
10807 /* Avoid longjmp clobbering */
10813 (void) &parenlevel;
10816 (void) &prevsyntax;
10819 startlinno = g_parsefile->linno;
10824 #if ENABLE_ASH_EXPAND_PRMT
10825 pssyntax = (syntax == PSSYNTAX);
10829 dblquote = (syntax == DQSYNTAX);
10835 STARTSTACKSTR(out);
10837 /* For each line, until end of word */
10839 CHECKEND(); /* set c to PEOF if at end of here document */
10840 for (;;) { /* until end of line or end of word */
10841 CHECKSTRSPACE(4, out); /* permit 4 calls to USTPUTC */
10842 switch (SIT(c, syntax)) {
10843 case CNL: /* '\n' */
10844 if (syntax == BASESYNTAX)
10845 goto endword; /* exit outer loop */
10847 g_parsefile->linno++;
10851 goto loop; /* continue outer loop */
10856 if (eofmark == NULL || dblquote)
10857 USTPUTC(CTLESC, out);
10858 #if ENABLE_ASH_BASH_COMPAT
10859 if (c == '\\' && bash_dollar_squote) {
10860 c = decode_dollar_squote();
10862 USTPUTC('\\', out);
10863 c = (unsigned char)c;
10869 case CBACK: /* backslash */
10872 USTPUTC(CTLESC, out);
10873 USTPUTC('\\', out);
10875 } else if (c == '\n') {
10879 #if ENABLE_ASH_EXPAND_PRMT
10880 if (c == '$' && pssyntax) {
10881 USTPUTC(CTLESC, out);
10882 USTPUTC('\\', out);
10885 if (dblquote && c != '\\'
10886 && c != '`' && c != '$'
10887 && (c != '"' || eofmark != NULL)
10889 USTPUTC(CTLESC, out);
10890 USTPUTC('\\', out);
10892 if (SIT(c, SQSYNTAX) == CCTL)
10893 USTPUTC(CTLESC, out);
10901 if (eofmark == NULL) {
10902 USTPUTC(CTLQUOTEMARK, out);
10910 USE_ASH_BASH_COMPAT(bash_dollar_squote = 0;)
10911 if (eofmark != NULL && arinest == 0
10916 if (dqvarnest == 0) {
10917 syntax = BASESYNTAX;
10924 case CVAR: /* '$' */
10925 PARSESUB(); /* parse substitution */
10927 case CENDVAR: /* '}' */
10930 if (dqvarnest > 0) {
10933 USTPUTC(CTLENDVAR, out);
10938 #if ENABLE_ASH_MATH_SUPPORT
10939 case CLP: /* '(' in arithmetic */
10943 case CRP: /* ')' in arithmetic */
10944 if (parenlevel > 0) {
10948 if (pgetc() == ')') {
10949 if (--arinest == 0) {
10950 USTPUTC(CTLENDARI, out);
10951 syntax = prevsyntax;
10952 dblquote = (syntax == DQSYNTAX);
10957 * unbalanced parens
10958 * (don't 2nd guess - no error)
10966 case CBQUOTE: /* '`' */
10970 goto endword; /* exit outer loop */
10974 if (varnest == 0) {
10975 #if ENABLE_ASH_BASH_COMPAT
10977 if (pgetc() == '>')
10978 c = 0x100 + '>'; /* flag &> */
10982 goto endword; /* exit outer loop */
10984 #if ENABLE_ASH_ALIAS
10994 #if ENABLE_ASH_MATH_SUPPORT
10995 if (syntax == ARISYNTAX)
10996 raise_error_syntax("missing '))'");
10998 if (syntax != BASESYNTAX && !parsebackquote && eofmark == NULL)
10999 raise_error_syntax("unterminated quoted string");
11000 if (varnest != 0) {
11001 startlinno = g_parsefile->linno;
11003 raise_error_syntax("missing '}'");
11005 USTPUTC('\0', out);
11006 len = out - (char *)stackblock();
11007 out = stackblock();
11008 if (eofmark == NULL) {
11009 if ((c == '>' || c == '<' USE_ASH_BASH_COMPAT( || c == 0x100 + '>'))
11012 if (isdigit_str9(out)) {
11013 PARSEREDIR(); /* passed as params: out, c */
11014 lasttoken = TREDIR;
11017 /* else: non-number X seen, interpret it
11018 * as "NNNX>file" = "NNNX >file" */
11022 quoteflag = quotef;
11023 backquotelist = bqlist;
11024 grabstackblock(len);
11028 /* end of readtoken routine */
11031 * Check to see whether we are at the end of the here document. When this
11032 * is called, c is set to the first character of the next input line. If
11033 * we are at the end of the here document, this routine sets the c to PEOF.
11037 #if ENABLE_ASH_ALIAS
11043 while (c == '\t') {
11047 if (c == *eofmark) {
11048 if (pfgets(line, sizeof(line)) != NULL) {
11052 for (q = eofmark + 1; *q && *p == *q; p++, q++)
11054 if (*p == '\n' && *q == '\0') {
11056 g_parsefile->linno++;
11057 needprompt = doprompt;
11059 pushstring(line, NULL);
11064 goto checkend_return;
11068 * Parse a redirection operator. The variable "out" points to a string
11069 * specifying the fd to be redirected. The variable "c" contains the
11070 * first character of the redirection operator.
11073 /* out is already checked to be a valid number or "" */
11074 int fd = (*out == '\0' ? -1 : atoi(out));
11077 np = stzalloc(sizeof(struct nfile));
11082 np->type = NAPPEND;
11084 np->type = NCLOBBER;
11087 /* it also can be NTO2 (>&file), but we can't figure it out yet */
11093 #if ENABLE_ASH_BASH_COMPAT
11094 else if (c == 0x100 + '>') { /* this flags &> redirection */
11096 pgetc(); /* this is '>', no need to check */
11100 else { /* c == '<' */
11101 /*np->nfile.fd = 0; - stzalloc did it */
11105 if (sizeof(struct nfile) != sizeof(struct nhere)) {
11106 np = stzalloc(sizeof(struct nhere));
11107 /*np->nfile.fd = 0; - stzalloc did it */
11110 heredoc = stzalloc(sizeof(struct heredoc));
11111 heredoc->here = np;
11114 heredoc->striptabs = 1;
11116 /*heredoc->striptabs = 0; - stzalloc did it */
11122 np->type = NFROMFD;
11126 np->type = NFROMTO;
11138 goto parseredir_return;
11142 * Parse a substitution. At this point, we have read the dollar sign
11143 * and nothing else.
11146 /* is_special(c) evaluates to 1 for c in "!#$*-0123456789?@"; 0 otherwise
11147 * (assuming ascii char codes, as the original implementation did) */
11148 #define is_special(c) \
11149 (((unsigned)(c) - 33 < 32) \
11150 && ((0xc1ff920dU >> ((unsigned)(c) - 33)) & 1))
11156 static const char types[] ALIGN1 = "}-+?=";
11159 if (c <= PEOA_OR_PEOF
11160 || (c != '(' && c != '{' && !is_name(c) && !is_special(c))
11162 #if ENABLE_ASH_BASH_COMPAT
11164 bash_dollar_squote = 1;
11169 } else if (c == '(') { /* $(command) or $((arith)) */
11170 if (pgetc() == '(') {
11171 #if ENABLE_ASH_MATH_SUPPORT
11174 raise_error_syntax("you disabled math support for $((arith)) syntax");
11181 USTPUTC(CTLVAR, out);
11182 typeloc = out - (char *)stackblock();
11183 USTPUTC(VSNORMAL, out);
11184 subtype = VSNORMAL;
11192 subtype = VSLENGTH;
11196 if (c > PEOA_OR_PEOF && is_name(c)) {
11200 } while (c > PEOA_OR_PEOF && is_in_name(c));
11201 } else if (isdigit(c)) {
11205 } while (isdigit(c));
11206 } else if (is_special(c)) {
11211 raise_error_syntax("bad substitution");
11216 if (subtype == 0) {
11220 #if ENABLE_ASH_BASH_COMPAT
11221 if (c == ':' || c == '$' || isdigit(c)) {
11223 subtype = VSSUBSTR;
11230 p = strchr(types, c);
11233 subtype = p - types + VSNORMAL;
11238 subtype = c == '#' ? VSTRIMLEFT : VSTRIMRIGHT;
11246 #if ENABLE_ASH_BASH_COMPAT
11248 subtype = VSREPLACE;
11251 subtype++; /* VSREPLACEALL */
11260 if (dblquote || arinest)
11262 *((char *)stackblock() + typeloc) = subtype | flags;
11263 if (subtype != VSNORMAL) {
11265 if (dblquote || arinest) {
11270 goto parsesub_return;
11274 * Called to parse command substitutions. Newstyle is set if the command
11275 * is enclosed inside $(...); nlpp is a pointer to the head of the linked
11276 * list of commands (passed by reference), and savelen is the number of
11277 * characters on the top of the stack which must be preserved.
11280 struct nodelist **nlpp;
11283 char *volatile str;
11284 struct jmploc jmploc;
11285 struct jmploc *volatile savehandler;
11287 smallint saveprompt = 0;
11290 (void) &saveprompt;
11292 savepbq = parsebackquote;
11293 if (setjmp(jmploc.loc)) {
11295 parsebackquote = 0;
11296 exception_handler = savehandler;
11297 longjmp(exception_handler->loc, 1);
11301 savelen = out - (char *)stackblock();
11303 str = ckmalloc(savelen);
11304 memcpy(str, stackblock(), savelen);
11306 savehandler = exception_handler;
11307 exception_handler = &jmploc;
11310 /* We must read until the closing backquote, giving special
11311 treatment to some slashes, and then push the string and
11312 reread it as input, interpreting it normally. */
11319 STARTSTACKSTR(pout);
11332 g_parsefile->linno++;
11336 * If eating a newline, avoid putting
11337 * the newline into the new character
11338 * stream (via the STPUTC after the
11343 if (pc != '\\' && pc != '`' && pc != '$'
11344 && (!dblquote || pc != '"'))
11345 STPUTC('\\', pout);
11346 if (pc > PEOA_OR_PEOF) {
11352 #if ENABLE_ASH_ALIAS
11355 startlinno = g_parsefile->linno;
11356 raise_error_syntax("EOF in backquote substitution");
11359 g_parsefile->linno++;
11360 needprompt = doprompt;
11369 STPUTC('\0', pout);
11370 psavelen = pout - (char *)stackblock();
11371 if (psavelen > 0) {
11372 pstr = grabstackstr(pout);
11373 setinputstring(pstr);
11378 nlpp = &(*nlpp)->next;
11379 *nlpp = stzalloc(sizeof(**nlpp));
11380 /* (*nlpp)->next = NULL; - stzalloc did it */
11381 parsebackquote = oldstyle;
11384 saveprompt = doprompt;
11391 doprompt = saveprompt;
11392 else if (readtoken() != TRP)
11393 raise_error_unexpected_syntax(TRP);
11398 * Start reading from old file again, ignoring any pushed back
11399 * tokens left from the backquote parsing
11404 while (stackblocksize() <= savelen)
11406 STARTSTACKSTR(out);
11408 memcpy(out, str, savelen);
11409 STADJUST(savelen, out);
11415 parsebackquote = savepbq;
11416 exception_handler = savehandler;
11417 if (arinest || dblquote)
11418 USTPUTC(CTLBACKQ | CTLQUOTE, out);
11420 USTPUTC(CTLBACKQ, out);
11422 goto parsebackq_oldreturn;
11423 goto parsebackq_newreturn;
11426 #if ENABLE_ASH_MATH_SUPPORT
11428 * Parse an arithmetic expansion (indicate start of one and set state)
11431 if (++arinest == 1) {
11432 prevsyntax = syntax;
11433 syntax = ARISYNTAX;
11434 USTPUTC(CTLARI, out);
11441 * we collapse embedded arithmetic expansion to
11442 * parenthesis, which should be equivalent
11446 goto parsearith_return;
11450 } /* end of readtoken */
11453 * Read the next input token.
11454 * If the token is a word, we set backquotelist to the list of cmds in
11455 * backquotes. We set quoteflag to true if any part of the word was
11457 * If the token is TREDIR, then we set redirnode to a structure containing
11459 * In all cases, the variable startlinno is set to the number of the line
11460 * on which the token starts.
11462 * [Change comment: here documents and internal procedures]
11463 * [Readtoken shouldn't have any arguments. Perhaps we should make the
11464 * word parsing code into a separate routine. In this case, readtoken
11465 * doesn't need to have any internal procedures, but parseword does.
11466 * We could also make parseoperator in essence the main routine, and
11467 * have parseword (readtoken1?) handle both words and redirection.]
11469 #define NEW_xxreadtoken
11470 #ifdef NEW_xxreadtoken
11471 /* singles must be first! */
11472 static const char xxreadtoken_chars[7] ALIGN1 = {
11473 '\n', '(', ')', /* singles */
11474 '&', '|', ';', /* doubles */
11478 #define xxreadtoken_singles 3
11479 #define xxreadtoken_doubles 3
11481 static const char xxreadtoken_tokens[] ALIGN1 = {
11482 TNL, TLP, TRP, /* only single occurrence allowed */
11483 TBACKGND, TPIPE, TSEMI, /* if single occurrence */
11484 TEOF, /* corresponds to trailing nul */
11485 TAND, TOR, TENDCASE /* if double occurrence */
11500 startlinno = g_parsefile->linno;
11501 for (;;) { /* until token or start of word found */
11503 if (c == ' ' || c == '\t' USE_ASH_ALIAS( || c == PEOA))
11507 while ((c = pgetc()) != '\n' && c != PEOF)
11510 } else if (c == '\\') {
11511 if (pgetc() != '\n') {
11513 break; /* return readtoken1(...) */
11515 startlinno = ++g_parsefile->linno;
11521 p = xxreadtoken_chars + sizeof(xxreadtoken_chars) - 1;
11524 g_parsefile->linno++;
11525 needprompt = doprompt;
11528 p = strchr(xxreadtoken_chars, c);
11530 break; /* return readtoken1(...) */
11532 if ((int)(p - xxreadtoken_chars) >= xxreadtoken_singles) {
11534 if (cc == c) { /* double occurrence? */
11535 p += xxreadtoken_doubles + 1;
11538 #if ENABLE_ASH_BASH_COMPAT
11539 if (c == '&' && cc == '>') /* &> */
11540 break; /* return readtoken1(...) */
11545 lasttoken = xxreadtoken_tokens[p - xxreadtoken_chars];
11550 return readtoken1(c, BASESYNTAX, (char *) NULL, 0);
11552 #else /* old xxreadtoken */
11553 #define RETURN(token) return lasttoken = token
11566 startlinno = g_parsefile->linno;
11567 for (;;) { /* until token or start of word found */
11570 case ' ': case '\t':
11571 #if ENABLE_ASH_ALIAS
11576 while ((c = pgetc()) != '\n' && c != PEOF)
11581 if (pgetc() == '\n') {
11582 startlinno = ++g_parsefile->linno;
11590 g_parsefile->linno++;
11591 needprompt = doprompt;
11596 if (pgetc() == '&')
11601 if (pgetc() == '|')
11606 if (pgetc() == ';')
11619 return readtoken1(c, BASESYNTAX, (char *)NULL, 0);
11622 #endif /* old xxreadtoken */
11629 smallint alreadyseen = tokpushback;
11632 #if ENABLE_ASH_ALIAS
11641 if (checkkwd & CHKNL) {
11648 if (t != TWORD || quoteflag) {
11653 * check for keywords
11655 if (checkkwd & CHKKWD) {
11656 const char *const *pp;
11658 pp = findkwd(wordtext);
11660 lasttoken = t = pp - tokname_array;
11661 TRACE(("keyword %s recognized\n", tokname(t)));
11666 if (checkkwd & CHKALIAS) {
11667 #if ENABLE_ASH_ALIAS
11669 ap = lookupalias(wordtext, 1);
11672 pushstring(ap->val, ap);
11682 TRACE(("token %s %s\n", tokname(t), t == TWORD ? wordtext : ""));
11684 TRACE(("reread token %s %s\n", tokname(t), t == TWORD ? wordtext : ""));
11696 return tokname_array[t][0];
11700 * Read and parse a command. Returns NEOF on end of file. (NULL is a
11701 * valid parse tree indicating a blank line.)
11703 static union node *
11704 parsecmd(int interact)
11709 doprompt = interact;
11711 setprompt(doprompt);
11723 * Input any here documents.
11728 struct heredoc *here;
11731 here = heredoclist;
11732 heredoclist = NULL;
11738 readtoken1(pgetc(), here->here->type == NHERE? SQSYNTAX : DQSYNTAX,
11739 here->eofmark, here->striptabs);
11740 n = stzalloc(sizeof(struct narg));
11741 n->narg.type = NARG;
11742 /*n->narg.next = NULL; - stzalloc did it */
11743 n->narg.text = wordtext;
11744 n->narg.backquote = backquotelist;
11745 here->here->nhere.doc = n;
11752 * called by editline -- any expansions to the prompt should be added here.
11754 #if ENABLE_ASH_EXPAND_PRMT
11755 static const char *
11756 expandstr(const char *ps)
11760 /* XXX Fix (char *) cast. It _is_ a bug. ps is variable's value,
11761 * and token processing _can_ alter it (delete NULs etc). */
11762 setinputstring((char *)ps);
11763 readtoken1(pgetc(), PSSYNTAX, nullstr, 0);
11766 n.narg.type = NARG;
11767 n.narg.next = NULL;
11768 n.narg.text = wordtext;
11769 n.narg.backquote = backquotelist;
11771 expandarg(&n, NULL, 0);
11772 return stackblock();
11777 * Execute a command or commands contained in a string.
11780 evalstring(char *s, int mask)
11783 struct stackmark smark;
11787 setstackmark(&smark);
11790 while ((n = parsecmd(0)) != NEOF) {
11792 popstackmark(&smark);
11805 * The eval command.
11808 evalcmd(int argc UNUSED_PARAM, char **argv)
11817 STARTSTACKSTR(concat);
11819 concat = stack_putstr(p, concat);
11823 STPUTC(' ', concat);
11825 STPUTC('\0', concat);
11826 p = grabstackstr(concat);
11828 evalstring(p, ~SKIPEVAL);
11835 * Read and execute commands. "Top" is nonzero for the top level command
11836 * loop; it turns on prompting if the shell is interactive.
11842 struct stackmark smark;
11846 TRACE(("cmdloop(%d) called\n", top));
11850 setstackmark(&smark);
11853 showjobs(stderr, SHOW_CHANGED);
11856 if (iflag && top) {
11858 #if ENABLE_ASH_MAIL
11862 n = parsecmd(inter);
11863 /* showtree(n); DEBUG */
11865 if (!top || numeof >= 50)
11867 if (!stoppedjobs()) {
11870 out2str("\nUse \"exit\" to leave shell.\n");
11873 } else if (nflag == 0) {
11874 /* job_warning can only be 2,1,0. Here 2->1, 1/0->0 */
11879 popstackmark(&smark);
11884 return skip & SKIPEVAL;
11891 * Take commands from a file. To be compatible we should do a path
11892 * search for the file, which is necessary to find sub-commands.
11895 find_dot_file(char *name)
11898 const char *path = pathval();
11901 /* don't try this for absolute or relative paths */
11902 if (strchr(name, '/'))
11905 /* IIRC standards do not say whether . is to be searched.
11906 * And it is even smaller this way, making it unconditional for now:
11908 if (1) { /* ENABLE_ASH_BASH_COMPAT */
11913 while ((fullname = padvance(&path, name)) != NULL) {
11915 if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) {
11917 * Don't bother freeing here, since it will
11918 * be freed by the caller.
11922 stunalloc(fullname);
11925 /* not found in the PATH */
11926 ash_msg_and_raise_error("%s: not found", name);
11931 dotcmd(int argc, char **argv)
11933 struct strlist *sp;
11934 volatile struct shparam saveparam;
11937 for (sp = cmdenviron; sp; sp = sp->next)
11938 setvareq(ckstrdup(sp->text), VSTRFIXED | VTEXTFIXED);
11940 if (argv[1]) { /* That's what SVR2 does */
11941 char *fullname = find_dot_file(argv[1]);
11944 if (argc) { /* argc > 0, argv[0] != NULL */
11945 saveparam = shellparam;
11946 shellparam.malloced = 0;
11947 shellparam.nparam = argc;
11948 shellparam.p = argv;
11951 setinputfile(fullname, INPUT_PUSH_FILE);
11952 commandname = fullname;
11957 freeparam(&shellparam);
11958 shellparam = saveparam;
11960 status = exitstatus;
11966 exitcmd(int argc UNUSED_PARAM, char **argv)
11971 exitstatus = number(argv[1]);
11972 raise_exception(EXEXIT);
11977 * Read a file containing shell functions.
11980 readcmdfile(char *name)
11982 setinputfile(name, INPUT_PUSH_FILE);
11988 /* ============ find_command inplementation */
11991 * Resolve a command name. If you change this routine, you may have to
11992 * change the shellexec routine as well.
11995 find_command(char *name, struct cmdentry *entry, int act, const char *path)
11997 struct tblentry *cmdp;
12004 struct builtincmd *bcmd;
12006 /* If name contains a slash, don't use PATH or hash table */
12007 if (strchr(name, '/') != NULL) {
12008 entry->u.index = -1;
12009 if (act & DO_ABS) {
12010 while (stat(name, &statb) < 0) {
12012 if (errno == EINTR)
12015 entry->cmdtype = CMDUNKNOWN;
12019 entry->cmdtype = CMDNORMAL;
12023 /* #if ENABLE_FEATURE_SH_STANDALONE... moved after builtin check */
12025 updatetbl = (path == pathval());
12028 if (strstr(path, "%builtin") != NULL)
12029 act |= DO_ALTBLTIN;
12032 /* If name is in the table, check answer will be ok */
12033 cmdp = cmdlookup(name, 0);
12034 if (cmdp != NULL) {
12037 switch (cmdp->cmdtype) {
12055 } else if (cmdp->rehash == 0)
12056 /* if not invalidated by cd, we're done */
12060 /* If %builtin not in path, check for builtin next */
12061 bcmd = find_builtin(name);
12063 if (IS_BUILTIN_REGULAR(bcmd))
12064 goto builtin_success;
12065 if (act & DO_ALTPATH) {
12066 if (!(act & DO_ALTBLTIN))
12067 goto builtin_success;
12068 } else if (builtinloc <= 0) {
12069 goto builtin_success;
12073 #if ENABLE_FEATURE_SH_STANDALONE
12075 int applet_no = find_applet_by_name(name);
12076 if (applet_no >= 0) {
12077 entry->cmdtype = CMDNORMAL;
12078 entry->u.index = -2 - applet_no;
12084 /* We have to search path. */
12085 prev = -1; /* where to start */
12086 if (cmdp && cmdp->rehash) { /* doing a rehash */
12087 if (cmdp->cmdtype == CMDBUILTIN)
12090 prev = cmdp->param.index;
12096 while ((fullname = padvance(&path, name)) != NULL) {
12097 stunalloc(fullname);
12098 /* NB: code below will still use fullname
12099 * despite it being "unallocated" */
12102 if (prefix(pathopt, "builtin")) {
12104 goto builtin_success;
12107 if ((act & DO_NOFUNC)
12108 || !prefix(pathopt, "func")
12109 ) { /* ignore unimplemented options */
12113 /* if rehash, don't redo absolute path names */
12114 if (fullname[0] == '/' && idx <= prev) {
12117 TRACE(("searchexec \"%s\": no change\n", name));
12120 while (stat(fullname, &statb) < 0) {
12122 if (errno == EINTR)
12125 if (errno != ENOENT && errno != ENOTDIR)
12129 e = EACCES; /* if we fail, this will be the error */
12130 if (!S_ISREG(statb.st_mode))
12132 if (pathopt) { /* this is a %func directory */
12133 stalloc(strlen(fullname) + 1);
12134 /* NB: stalloc will return space pointed by fullname
12135 * (because we don't have any intervening allocations
12136 * between stunalloc above and this stalloc) */
12137 readcmdfile(fullname);
12138 cmdp = cmdlookup(name, 0);
12139 if (cmdp == NULL || cmdp->cmdtype != CMDFUNCTION)
12140 ash_msg_and_raise_error("%s not defined in %s", name, fullname);
12141 stunalloc(fullname);
12144 TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
12146 entry->cmdtype = CMDNORMAL;
12147 entry->u.index = idx;
12151 cmdp = cmdlookup(name, 1);
12152 cmdp->cmdtype = CMDNORMAL;
12153 cmdp->param.index = idx;
12158 /* We failed. If there was an entry for this command, delete it */
12159 if (cmdp && updatetbl)
12160 delete_cmd_entry();
12162 ash_msg("%s: %s", name, errmsg(e, "not found"));
12163 entry->cmdtype = CMDUNKNOWN;
12168 entry->cmdtype = CMDBUILTIN;
12169 entry->u.cmd = bcmd;
12173 cmdp = cmdlookup(name, 1);
12174 cmdp->cmdtype = CMDBUILTIN;
12175 cmdp->param.cmd = bcmd;
12179 entry->cmdtype = cmdp->cmdtype;
12180 entry->u = cmdp->param;
12184 /* ============ trap.c */
12187 * The trap builtin.
12190 trapcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
12199 for (signo = 0; signo < NSIG; signo++) {
12200 if (trap[signo] != NULL) {
12201 out1fmt("trap -- %s %s\n",
12202 single_quote(trap[signo]),
12203 get_signame(signo));
12212 signo = get_signum(*ap);
12214 ash_msg_and_raise_error("%s: bad trap", *ap);
12217 if (LONE_DASH(action))
12220 action = ckstrdup(action);
12223 trap[signo] = action;
12233 /* ============ Builtins */
12235 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
12237 * Lists available builtins
12240 helpcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
12245 out1fmt("\nBuilt-in commands:\n-------------------\n");
12246 for (col = 0, i = 0; i < ARRAY_SIZE(builtintab); i++) {
12247 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '),
12248 builtintab[i].name + 1);
12254 #if ENABLE_FEATURE_SH_STANDALONE
12256 const char *a = applet_names;
12258 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '), a);
12263 a += strlen(a) + 1;
12268 return EXIT_SUCCESS;
12270 #endif /* FEATURE_SH_EXTRA_QUIET */
12273 * The export and readonly commands.
12276 exportcmd(int argc UNUSED_PARAM, char **argv)
12282 int flag = argv[0][0] == 'r' ? VREADONLY : VEXPORT;
12284 if (nextopt("p") != 'p') {
12289 p = strchr(name, '=');
12293 vp = *findvar(hashvar(name), name);
12299 setvar(name, p, flag);
12300 } while ((name = *++aptr) != NULL);
12304 showvars(argv[0], flag, 0);
12309 * Delete a function if it exists.
12312 unsetfunc(const char *name)
12314 struct tblentry *cmdp;
12316 cmdp = cmdlookup(name, 0);
12317 if (cmdp!= NULL && cmdp->cmdtype == CMDFUNCTION)
12318 delete_cmd_entry();
12322 * The unset builtin command. We unset the function before we unset the
12323 * variable to allow a function to be unset when there is a readonly variable
12324 * with the same name.
12327 unsetcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
12334 while ((i = nextopt("vf")) != '\0') {
12338 for (ap = argptr; *ap; ap++) {
12354 #include <sys/times.h>
12356 static const unsigned char timescmd_str[] ALIGN1 = {
12357 ' ', offsetof(struct tms, tms_utime),
12358 '\n', offsetof(struct tms, tms_stime),
12359 ' ', offsetof(struct tms, tms_cutime),
12360 '\n', offsetof(struct tms, tms_cstime),
12365 timescmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
12367 long clk_tck, s, t;
12368 const unsigned char *p;
12371 clk_tck = sysconf(_SC_CLK_TCK);
12376 t = *(clock_t *)(((char *) &buf) + p[1]);
12378 out1fmt("%ldm%ld.%.3lds%c",
12380 ((t - s * clk_tck) * 1000) / clk_tck,
12382 } while (*(p += 2));
12387 #if ENABLE_ASH_MATH_SUPPORT
12389 dash_arith(const char *s)
12395 result = arith(s, &errcode);
12398 ash_msg_and_raise_error("exponent less than 0");
12400 ash_msg_and_raise_error("divide by zero");
12402 ash_msg_and_raise_error("expression recursion loop detected");
12403 raise_error_syntax(s);
12411 * The let builtin. partial stolen from GNU Bash, the Bourne Again SHell.
12412 * Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
12414 * Copyright (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
12417 letcmd(int argc UNUSED_PARAM, char **argv)
12423 ash_msg_and_raise_error("expression expected");
12425 i = dash_arith(*argv);
12430 #endif /* ASH_MATH_SUPPORT */
12433 /* ============ miscbltin.c
12435 * Miscellaneous builtins.
12440 #if defined(__GLIBC__) && __GLIBC__ == 2 && __GLIBC_MINOR__ < 1
12441 typedef enum __rlimit_resource rlim_t;
12445 * The read builtin. Options:
12446 * -r Do not interpret '\' specially
12447 * -s Turn off echo (tty only)
12448 * -n NCHARS Read NCHARS max
12449 * -p PROMPT Display PROMPT on stderr (if input is from tty)
12450 * -t SECONDS Timeout after SECONDS (tty or pipe only)
12451 * -u FD Read from given FD instead of fd 0
12452 * This uses unbuffered input, which may be avoidable in some cases.
12453 * TODO: bash also has:
12454 * -a ARRAY Read into array[0],[1],etc
12455 * -d DELIM End on DELIM char, not newline
12456 * -e Use line editing (tty only)
12459 readcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
12461 static const char *const arg_REPLY[] = { "REPLY", NULL };
12474 #if ENABLE_ASH_READ_NCHARS
12475 int nchars = 0; /* if != 0, -n is in effect */
12477 struct termios tty, old_tty;
12479 #if ENABLE_ASH_READ_TIMEOUT
12480 unsigned end_ms = 0;
12481 unsigned timeout = 0;
12486 while ((i = nextopt("p:u:r"
12487 USE_ASH_READ_TIMEOUT("t:")
12488 USE_ASH_READ_NCHARS("n:s")
12492 prompt = optionarg;
12494 #if ENABLE_ASH_READ_NCHARS
12496 nchars = bb_strtou(optionarg, NULL, 10);
12497 if (nchars < 0 || errno)
12498 ash_msg_and_raise_error("invalid count");
12499 /* nchars == 0: off (bash 3.2 does this too) */
12505 #if ENABLE_ASH_READ_TIMEOUT
12507 timeout = bb_strtou(optionarg, NULL, 10);
12508 if (errno || timeout > UINT_MAX / 2048)
12509 ash_msg_and_raise_error("invalid timeout");
12511 #if 0 /* even bash have no -t N.NNN support */
12512 ts.tv_sec = bb_strtou(optionarg, &p, 10);
12514 /* EINVAL means number is ok, but not terminated by NUL */
12515 if (*p == '.' && errno == EINVAL) {
12519 ts.tv_usec = bb_strtou(p, &p2, 10);
12521 ash_msg_and_raise_error("invalid timeout");
12523 /* normalize to usec */
12525 ash_msg_and_raise_error("invalid timeout");
12526 while (scale++ < 6)
12529 } else if (ts.tv_sec < 0 || errno) {
12530 ash_msg_and_raise_error("invalid timeout");
12532 if (!(ts.tv_sec | ts.tv_usec)) { /* both are 0? */
12533 ash_msg_and_raise_error("invalid timeout");
12542 fd = bb_strtou(optionarg, NULL, 10);
12543 if (fd < 0 || errno)
12544 ash_msg_and_raise_error("invalid file descriptor");
12550 if (prompt && isatty(fd)) {
12555 ap = (char**)arg_REPLY;
12556 ifs = bltinlookup("IFS");
12559 #if ENABLE_ASH_READ_NCHARS
12560 tcgetattr(fd, &tty);
12562 if (nchars || silent) {
12564 tty.c_lflag &= ~ICANON;
12565 tty.c_cc[VMIN] = nchars < 256 ? nchars : 255;
12568 tty.c_lflag &= ~(ECHO | ECHOK | ECHONL);
12570 /* if tcgetattr failed, tcsetattr will fail too.
12571 * Ignoring, it's harmless. */
12572 tcsetattr(fd, TCSANOW, &tty);
12579 #if ENABLE_ASH_READ_TIMEOUT
12580 if (timeout) /* NB: ensuring end_ms is nonzero */
12581 end_ms = ((unsigned)(monotonic_us() / 1000) + timeout) | 1;
12585 const char *is_ifs;
12587 #if ENABLE_ASH_READ_TIMEOUT
12589 struct pollfd pfd[1];
12591 pfd[0].events = POLLIN;
12592 timeout = end_ms - (unsigned)(monotonic_us() / 1000);
12593 if ((int)timeout <= 0 /* already late? */
12594 || safe_poll(pfd, 1, timeout) != 1 /* no? wait... */
12595 ) { /* timed out! */
12596 #if ENABLE_ASH_READ_NCHARS
12597 tcsetattr(fd, TCSANOW, &old_tty);
12603 if (nonblock_safe_read(fd, &c, 1) != 1) {
12615 if (!rflag && c == '\\') {
12621 /* $IFS splitting */
12622 /* http://www.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_05 */
12623 is_ifs = strchr(ifs, c);
12624 if (startword && is_ifs) {
12627 /* it is a non-space ifs char */
12629 if (startword == 1) /* first one? */
12630 continue; /* yes, it is not next word yet */
12633 if (ap[1] != NULL && is_ifs) {
12636 beg = stackblock();
12637 setvar(*ap, beg, 0);
12639 /* can we skip one non-space ifs char? (2: yes) */
12640 startword = isspace(c) ? 2 : 1;
12647 /* end of do {} while: */
12648 #if ENABLE_ASH_READ_NCHARS
12654 #if ENABLE_ASH_READ_NCHARS
12655 tcsetattr(fd, TCSANOW, &old_tty);
12659 /* Remove trailing space ifs chars */
12660 while ((char *)stackblock() <= --p && isspace(*p) && strchr(ifs, *p) != NULL)
12662 setvar(*ap, stackblock(), 0);
12663 while (*++ap != NULL)
12664 setvar(*ap, nullstr, 0);
12669 umaskcmd(int argc UNUSED_PARAM, char **argv)
12671 static const char permuser[3] ALIGN1 = "ugo";
12672 static const char permmode[3] ALIGN1 = "rwx";
12673 static const short permmask[] ALIGN2 = {
12674 S_IRUSR, S_IWUSR, S_IXUSR,
12675 S_IRGRP, S_IWGRP, S_IXGRP,
12676 S_IROTH, S_IWOTH, S_IXOTH
12682 int symbolic_mode = 0;
12684 while (nextopt("S") != '\0') {
12695 if (symbolic_mode) {
12699 for (i = 0; i < 3; i++) {
12702 *p++ = permuser[i];
12704 for (j = 0; j < 3; j++) {
12705 if ((mask & permmask[3 * i + j]) == 0) {
12706 *p++ = permmode[j];
12714 out1fmt("%.4o\n", mask);
12717 if (isdigit((unsigned char) *ap)) {
12720 if (*ap >= '8' || *ap < '0')
12721 ash_msg_and_raise_error(illnum, argv[1]);
12722 mask = (mask << 3) + (*ap - '0');
12723 } while (*++ap != '\0');
12726 mask = ~mask & 0777;
12727 if (!bb_parse_mode(ap, &mask)) {
12728 ash_msg_and_raise_error("illegal mode: %s", ap);
12730 umask(~mask & 0777);
12739 * This code, originally by Doug Gwyn, Doug Kingston, Eric Gisin, and
12740 * Michael Rendell was ripped from pdksh 5.0.8 and hacked for use with
12741 * ash by J.T. Conklin.
12747 uint8_t cmd; /* RLIMIT_xxx fit into it */
12748 uint8_t factor_shift; /* shift by to get rlim_{cur,max} values */
12752 static const struct limits limits_tbl[] = {
12754 { RLIMIT_CPU, 0, 't' },
12756 #ifdef RLIMIT_FSIZE
12757 { RLIMIT_FSIZE, 9, 'f' },
12760 { RLIMIT_DATA, 10, 'd' },
12762 #ifdef RLIMIT_STACK
12763 { RLIMIT_STACK, 10, 's' },
12766 { RLIMIT_CORE, 9, 'c' },
12769 { RLIMIT_RSS, 10, 'm' },
12771 #ifdef RLIMIT_MEMLOCK
12772 { RLIMIT_MEMLOCK, 10, 'l' },
12774 #ifdef RLIMIT_NPROC
12775 { RLIMIT_NPROC, 0, 'p' },
12777 #ifdef RLIMIT_NOFILE
12778 { RLIMIT_NOFILE, 0, 'n' },
12781 { RLIMIT_AS, 10, 'v' },
12783 #ifdef RLIMIT_LOCKS
12784 { RLIMIT_LOCKS, 0, 'w' },
12787 static const char limits_name[] =
12789 "time(seconds)" "\0"
12791 #ifdef RLIMIT_FSIZE
12792 "file(blocks)" "\0"
12797 #ifdef RLIMIT_STACK
12801 "coredump(blocks)" "\0"
12806 #ifdef RLIMIT_MEMLOCK
12807 "locked memory(kb)" "\0"
12809 #ifdef RLIMIT_NPROC
12812 #ifdef RLIMIT_NOFILE
12818 #ifdef RLIMIT_LOCKS
12823 enum limtype { SOFT = 0x1, HARD = 0x2 };
12826 printlim(enum limtype how, const struct rlimit *limit,
12827 const struct limits *l)
12831 val = limit->rlim_max;
12833 val = limit->rlim_cur;
12835 if (val == RLIM_INFINITY)
12836 out1fmt("unlimited\n");
12838 val >>= l->factor_shift;
12839 out1fmt("%lld\n", (long long) val);
12844 ulimitcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
12848 enum limtype how = SOFT | HARD;
12849 const struct limits *l;
12852 struct rlimit limit;
12855 while ((optc = nextopt("HSa"
12859 #ifdef RLIMIT_FSIZE
12865 #ifdef RLIMIT_STACK
12874 #ifdef RLIMIT_MEMLOCK
12877 #ifdef RLIMIT_NPROC
12880 #ifdef RLIMIT_NOFILE
12886 #ifdef RLIMIT_LOCKS
12904 for (l = limits_tbl; l->option != what; l++)
12907 set = *argptr ? 1 : 0;
12911 if (all || argptr[1])
12912 ash_msg_and_raise_error("too many arguments");
12913 if (strncmp(p, "unlimited\n", 9) == 0)
12914 val = RLIM_INFINITY;
12918 while ((c = *p++) >= '0' && c <= '9') {
12919 val = (val * 10) + (long)(c - '0');
12920 // val is actually 'unsigned long int' and can't get < 0
12921 if (val < (rlim_t) 0)
12925 ash_msg_and_raise_error("bad number");
12926 val <<= l->factor_shift;
12930 const char *lname = limits_name;
12931 for (l = limits_tbl; l != &limits_tbl[ARRAY_SIZE(limits_tbl)]; l++) {
12932 getrlimit(l->cmd, &limit);
12933 out1fmt("%-20s ", lname);
12934 lname += strlen(lname) + 1;
12935 printlim(how, &limit, l);
12940 getrlimit(l->cmd, &limit);
12943 limit.rlim_max = val;
12945 limit.rlim_cur = val;
12946 if (setrlimit(l->cmd, &limit) < 0)
12947 ash_msg_and_raise_error("error setting limit (%m)");
12949 printlim(how, &limit, l);
12955 /* ============ Math support */
12957 #if ENABLE_ASH_MATH_SUPPORT
12959 /* Copyright (c) 2001 Aaron Lehmann <aaronl@vitelus.com>
12961 Permission is hereby granted, free of charge, to any person obtaining
12962 a copy of this software and associated documentation files (the
12963 "Software"), to deal in the Software without restriction, including
12964 without limitation the rights to use, copy, modify, merge, publish,
12965 distribute, sublicense, and/or sell copies of the Software, and to
12966 permit persons to whom the Software is furnished to do so, subject to
12967 the following conditions:
12969 The above copyright notice and this permission notice shall be
12970 included in all copies or substantial portions of the Software.
12972 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
12973 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
12974 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
12975 IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
12976 CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
12977 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
12978 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
12981 /* This is my infix parser/evaluator. It is optimized for size, intended
12982 * as a replacement for yacc-based parsers. However, it may well be faster
12983 * than a comparable parser written in yacc. The supported operators are
12984 * listed in #defines below. Parens, order of operations, and error handling
12985 * are supported. This code is thread safe. The exact expression format should
12986 * be that which POSIX specifies for shells. */
12988 /* The code uses a simple two-stack algorithm. See
12989 * http://www.onthenet.com.au/~grahamis/int2008/week02/lect02.html
12990 * for a detailed explanation of the infix-to-postfix algorithm on which
12991 * this is based (this code differs in that it applies operators immediately
12992 * to the stack instead of adding them to a queue to end up with an
12995 /* To use the routine, call it with an expression string and error return
12999 * Aug 24, 2001 Manuel Novoa III
13001 * Reduced the generated code size by about 30% (i386) and fixed several bugs.
13003 * 1) In arith_apply():
13004 * a) Cached values of *numptr and &(numptr[-1]).
13005 * b) Removed redundant test for zero denominator.
13008 * a) Eliminated redundant code for processing operator tokens by moving
13009 * to a table-based implementation. Also folded handling of parens
13011 * b) Combined all 3 loops which called arith_apply to reduce generated
13012 * code size at the cost of speed.
13014 * 3) The following expressions were treated as valid by the original code:
13015 * 1() , 0! , 1 ( *3 ) .
13016 * These bugs have been fixed by internally enclosing the expression in
13017 * parens and then checking that all binary ops and right parens are
13018 * preceded by a valid expression (NUM_TOKEN).
13020 * Note: It may be desirable to replace Aaron's test for whitespace with
13021 * ctype's isspace() if it is used by another busybox applet or if additional
13022 * whitespace chars should be considered. Look below the "#include"s for a
13023 * precompiler test.
13027 * Aug 26, 2001 Manuel Novoa III
13029 * Return 0 for null expressions. Pointed out by Vladimir Oleynik.
13031 * Merge in Aaron's comments previously posted to the busybox list,
13032 * modified slightly to take account of my changes to the code.
13037 * (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
13039 * - allow access to variable,
13040 * used recursive find value indirection (c=2*2; a="c"; $((a+=2)) produce 6)
13041 * - realize assign syntax (VAR=expr, +=, *= etc)
13042 * - realize exponentiation (** operator)
13043 * - realize comma separated - expr, expr
13044 * - realise ++expr --expr expr++ expr--
13045 * - realise expr ? expr : expr (but, second expr calculate always)
13046 * - allow hexadecimal and octal numbers
13047 * - was restored loses XOR operator
13048 * - remove one goto label, added three ;-)
13049 * - protect $((num num)) as true zero expr (Manuel`s error)
13050 * - always use special isspace(), see comment from bash ;-)
13053 #define arith_isspace(arithval) \
13054 (arithval == ' ' || arithval == '\n' || arithval == '\t')
13056 typedef unsigned char operator;
13058 /* An operator's token id is a bit of a bitfield. The lower 5 bits are the
13059 * precedence, and 3 high bits are an ID unique across operators of that
13060 * precedence. The ID portion is so that multiple operators can have the
13061 * same precedence, ensuring that the leftmost one is evaluated first.
13062 * Consider * and /. */
13064 #define tok_decl(prec,id) (((id)<<5)|(prec))
13065 #define PREC(op) ((op) & 0x1F)
13067 #define TOK_LPAREN tok_decl(0,0)
13069 #define TOK_COMMA tok_decl(1,0)
13071 #define TOK_ASSIGN tok_decl(2,0)
13072 #define TOK_AND_ASSIGN tok_decl(2,1)
13073 #define TOK_OR_ASSIGN tok_decl(2,2)
13074 #define TOK_XOR_ASSIGN tok_decl(2,3)
13075 #define TOK_PLUS_ASSIGN tok_decl(2,4)
13076 #define TOK_MINUS_ASSIGN tok_decl(2,5)
13077 #define TOK_LSHIFT_ASSIGN tok_decl(2,6)
13078 #define TOK_RSHIFT_ASSIGN tok_decl(2,7)
13080 #define TOK_MUL_ASSIGN tok_decl(3,0)
13081 #define TOK_DIV_ASSIGN tok_decl(3,1)
13082 #define TOK_REM_ASSIGN tok_decl(3,2)
13084 /* all assign is right associativity and precedence eq, but (7+3)<<5 > 256 */
13085 #define convert_prec_is_assing(prec) do { if (prec == 3) prec = 2; } while (0)
13087 /* conditional is right associativity too */
13088 #define TOK_CONDITIONAL tok_decl(4,0)
13089 #define TOK_CONDITIONAL_SEP tok_decl(4,1)
13091 #define TOK_OR tok_decl(5,0)
13093 #define TOK_AND tok_decl(6,0)
13095 #define TOK_BOR tok_decl(7,0)
13097 #define TOK_BXOR tok_decl(8,0)
13099 #define TOK_BAND tok_decl(9,0)
13101 #define TOK_EQ tok_decl(10,0)
13102 #define TOK_NE tok_decl(10,1)
13104 #define TOK_LT tok_decl(11,0)
13105 #define TOK_GT tok_decl(11,1)
13106 #define TOK_GE tok_decl(11,2)
13107 #define TOK_LE tok_decl(11,3)
13109 #define TOK_LSHIFT tok_decl(12,0)
13110 #define TOK_RSHIFT tok_decl(12,1)
13112 #define TOK_ADD tok_decl(13,0)
13113 #define TOK_SUB tok_decl(13,1)
13115 #define TOK_MUL tok_decl(14,0)
13116 #define TOK_DIV tok_decl(14,1)
13117 #define TOK_REM tok_decl(14,2)
13119 /* exponent is right associativity */
13120 #define TOK_EXPONENT tok_decl(15,1)
13122 /* For now unary operators. */
13123 #define UNARYPREC 16
13124 #define TOK_BNOT tok_decl(UNARYPREC,0)
13125 #define TOK_NOT tok_decl(UNARYPREC,1)
13127 #define TOK_UMINUS tok_decl(UNARYPREC+1,0)
13128 #define TOK_UPLUS tok_decl(UNARYPREC+1,1)
13130 #define PREC_PRE (UNARYPREC+2)
13132 #define TOK_PRE_INC tok_decl(PREC_PRE, 0)
13133 #define TOK_PRE_DEC tok_decl(PREC_PRE, 1)
13135 #define PREC_POST (UNARYPREC+3)
13137 #define TOK_POST_INC tok_decl(PREC_POST, 0)
13138 #define TOK_POST_DEC tok_decl(PREC_POST, 1)
13140 #define SPEC_PREC (UNARYPREC+4)
13142 #define TOK_NUM tok_decl(SPEC_PREC, 0)
13143 #define TOK_RPAREN tok_decl(SPEC_PREC, 1)
13145 #define NUMPTR (*numstackptr)
13148 tok_have_assign(operator op)
13150 operator prec = PREC(op);
13152 convert_prec_is_assing(prec);
13153 return (prec == PREC(TOK_ASSIGN) ||
13154 prec == PREC_PRE || prec == PREC_POST);
13158 is_right_associativity(operator prec)
13160 return (prec == PREC(TOK_ASSIGN) || prec == PREC(TOK_EXPONENT)
13161 || prec == PREC(TOK_CONDITIONAL));
13166 arith_t contidional_second_val;
13167 char contidional_second_val_initialized;
13168 char *var; /* if NULL then is regular number,
13169 else is variable name */
13172 typedef struct chk_var_recursive_looped_t {
13174 struct chk_var_recursive_looped_t *next;
13175 } chk_var_recursive_looped_t;
13177 static chk_var_recursive_looped_t *prev_chk_var_recursive;
13180 arith_lookup_val(v_n_t *t)
13183 const char * p = lookupvar(t->var);
13188 /* recursive try as expression */
13189 chk_var_recursive_looped_t *cur;
13190 chk_var_recursive_looped_t cur_save;
13192 for (cur = prev_chk_var_recursive; cur; cur = cur->next) {
13193 if (strcmp(cur->var, t->var) == 0) {
13194 /* expression recursion loop detected */
13198 /* save current lookuped var name */
13199 cur = prev_chk_var_recursive;
13200 cur_save.var = t->var;
13201 cur_save.next = cur;
13202 prev_chk_var_recursive = &cur_save;
13204 t->val = arith (p, &errcode);
13205 /* restore previous ptr after recursiving */
13206 prev_chk_var_recursive = cur;
13209 /* allow undefined var as 0 */
13215 /* "applying" a token means performing it on the top elements on the integer
13216 * stack. For a unary operator it will only change the top element, but a
13217 * binary operator will pop two arguments and push a result */
13219 arith_apply(operator op, v_n_t *numstack, v_n_t **numstackptr)
13222 arith_t numptr_val, rez;
13223 int ret_arith_lookup_val;
13225 /* There is no operator that can work without arguments */
13226 if (NUMPTR == numstack) goto err;
13227 numptr_m1 = NUMPTR - 1;
13229 /* check operand is var with noninteger value */
13230 ret_arith_lookup_val = arith_lookup_val(numptr_m1);
13231 if (ret_arith_lookup_val)
13232 return ret_arith_lookup_val;
13234 rez = numptr_m1->val;
13235 if (op == TOK_UMINUS)
13237 else if (op == TOK_NOT)
13239 else if (op == TOK_BNOT)
13241 else if (op == TOK_POST_INC || op == TOK_PRE_INC)
13243 else if (op == TOK_POST_DEC || op == TOK_PRE_DEC)
13245 else if (op != TOK_UPLUS) {
13246 /* Binary operators */
13248 /* check and binary operators need two arguments */
13249 if (numptr_m1 == numstack) goto err;
13251 /* ... and they pop one */
13254 if (op == TOK_CONDITIONAL) {
13255 if (!numptr_m1->contidional_second_val_initialized) {
13256 /* protect $((expr1 ? expr2)) without ": expr" */
13259 rez = numptr_m1->contidional_second_val;
13260 } else if (numptr_m1->contidional_second_val_initialized) {
13261 /* protect $((expr1 : expr2)) without "expr ? " */
13264 numptr_m1 = NUMPTR - 1;
13265 if (op != TOK_ASSIGN) {
13266 /* check operand is var with noninteger value for not '=' */
13267 ret_arith_lookup_val = arith_lookup_val(numptr_m1);
13268 if (ret_arith_lookup_val)
13269 return ret_arith_lookup_val;
13271 if (op == TOK_CONDITIONAL) {
13272 numptr_m1->contidional_second_val = rez;
13274 rez = numptr_m1->val;
13275 if (op == TOK_BOR || op == TOK_OR_ASSIGN)
13277 else if (op == TOK_OR)
13278 rez = numptr_val || rez;
13279 else if (op == TOK_BAND || op == TOK_AND_ASSIGN)
13281 else if (op == TOK_BXOR || op == TOK_XOR_ASSIGN)
13283 else if (op == TOK_AND)
13284 rez = rez && numptr_val;
13285 else if (op == TOK_EQ)
13286 rez = (rez == numptr_val);
13287 else if (op == TOK_NE)
13288 rez = (rez != numptr_val);
13289 else if (op == TOK_GE)
13290 rez = (rez >= numptr_val);
13291 else if (op == TOK_RSHIFT || op == TOK_RSHIFT_ASSIGN)
13292 rez >>= numptr_val;
13293 else if (op == TOK_LSHIFT || op == TOK_LSHIFT_ASSIGN)
13294 rez <<= numptr_val;
13295 else if (op == TOK_GT)
13296 rez = (rez > numptr_val);
13297 else if (op == TOK_LT)
13298 rez = (rez < numptr_val);
13299 else if (op == TOK_LE)
13300 rez = (rez <= numptr_val);
13301 else if (op == TOK_MUL || op == TOK_MUL_ASSIGN)
13303 else if (op == TOK_ADD || op == TOK_PLUS_ASSIGN)
13305 else if (op == TOK_SUB || op == TOK_MINUS_ASSIGN)
13307 else if (op == TOK_ASSIGN || op == TOK_COMMA)
13309 else if (op == TOK_CONDITIONAL_SEP) {
13310 if (numptr_m1 == numstack) {
13311 /* protect $((expr : expr)) without "expr ? " */
13314 numptr_m1->contidional_second_val_initialized = op;
13315 numptr_m1->contidional_second_val = numptr_val;
13316 } else if (op == TOK_CONDITIONAL) {
13318 numptr_val : numptr_m1->contidional_second_val;
13319 } else if (op == TOK_EXPONENT) {
13320 if (numptr_val < 0)
13321 return -3; /* exponent less than 0 */
13326 while (numptr_val--)
13330 } else if (numptr_val==0) /* zero divisor check */
13332 else if (op == TOK_DIV || op == TOK_DIV_ASSIGN)
13334 else if (op == TOK_REM || op == TOK_REM_ASSIGN)
13337 if (tok_have_assign(op)) {
13338 char buf[sizeof(arith_t_type)*3 + 2];
13340 if (numptr_m1->var == NULL) {
13344 /* save to shell variable */
13345 #if ENABLE_ASH_MATH_SUPPORT_64
13346 snprintf(buf, sizeof(buf), "%lld", (arith_t_type) rez);
13348 snprintf(buf, sizeof(buf), "%ld", (arith_t_type) rez);
13350 setvar(numptr_m1->var, buf, 0);
13351 /* after saving, make previous value for v++ or v-- */
13352 if (op == TOK_POST_INC)
13354 else if (op == TOK_POST_DEC)
13357 numptr_m1->val = rez;
13358 /* protect geting var value, is number now */
13359 numptr_m1->var = NULL;
13365 /* longest must be first */
13366 static const char op_tokens[] ALIGN1 = {
13367 '<','<','=',0, TOK_LSHIFT_ASSIGN,
13368 '>','>','=',0, TOK_RSHIFT_ASSIGN,
13369 '<','<', 0, TOK_LSHIFT,
13370 '>','>', 0, TOK_RSHIFT,
13371 '|','|', 0, TOK_OR,
13372 '&','&', 0, TOK_AND,
13373 '!','=', 0, TOK_NE,
13374 '<','=', 0, TOK_LE,
13375 '>','=', 0, TOK_GE,
13376 '=','=', 0, TOK_EQ,
13377 '|','=', 0, TOK_OR_ASSIGN,
13378 '&','=', 0, TOK_AND_ASSIGN,
13379 '*','=', 0, TOK_MUL_ASSIGN,
13380 '/','=', 0, TOK_DIV_ASSIGN,
13381 '%','=', 0, TOK_REM_ASSIGN,
13382 '+','=', 0, TOK_PLUS_ASSIGN,
13383 '-','=', 0, TOK_MINUS_ASSIGN,
13384 '-','-', 0, TOK_POST_DEC,
13385 '^','=', 0, TOK_XOR_ASSIGN,
13386 '+','+', 0, TOK_POST_INC,
13387 '*','*', 0, TOK_EXPONENT,
13391 '=', 0, TOK_ASSIGN,
13403 '?', 0, TOK_CONDITIONAL,
13404 ':', 0, TOK_CONDITIONAL_SEP,
13405 ')', 0, TOK_RPAREN,
13406 '(', 0, TOK_LPAREN,
13410 #define endexpression (&op_tokens[sizeof(op_tokens)-7])
13413 arith(const char *expr, int *perrcode)
13415 char arithval; /* Current character under analysis */
13416 operator lasttok, op;
13418 operator *stack, *stackptr;
13419 const char *p = endexpression;
13421 v_n_t *numstack, *numstackptr;
13422 unsigned datasizes = strlen(expr) + 2;
13424 /* Stack of integers */
13425 /* The proof that there can be no more than strlen(startbuf)/2+1 integers
13426 * in any given correct or incorrect expression is left as an exercise to
13428 numstackptr = numstack = alloca((datasizes / 2) * sizeof(numstack[0]));
13429 /* Stack of operator tokens */
13430 stackptr = stack = alloca(datasizes * sizeof(stack[0]));
13432 *stackptr++ = lasttok = TOK_LPAREN; /* start off with a left paren */
13433 *perrcode = errcode = 0;
13437 if (arithval == 0) {
13438 if (p == endexpression) {
13439 /* Null expression. */
13443 /* This is only reached after all tokens have been extracted from the
13444 * input stream. If there are still tokens on the operator stack, they
13445 * are to be applied in order. At the end, there should be a final
13446 * result on the integer stack */
13448 if (expr != endexpression + 1) {
13449 /* If we haven't done so already, */
13450 /* append a closing right paren */
13451 expr = endexpression;
13452 /* and let the loop process it. */
13455 /* At this point, we're done with the expression. */
13456 if (numstackptr != numstack+1) {
13457 /* ... but if there isn't, it's bad */
13462 if (numstack->var) {
13463 /* expression is $((var)) only, lookup now */
13464 errcode = arith_lookup_val(numstack);
13467 *perrcode = errcode;
13468 return numstack->val;
13471 /* Continue processing the expression. */
13472 if (arith_isspace(arithval)) {
13473 /* Skip whitespace */
13476 p = endofname(expr);
13478 size_t var_name_size = (p-expr) + 1; /* trailing zero */
13480 numstackptr->var = alloca(var_name_size);
13481 safe_strncpy(numstackptr->var, expr, var_name_size);
13484 numstackptr->contidional_second_val_initialized = 0;
13489 if (isdigit(arithval)) {
13490 numstackptr->var = NULL;
13491 #if ENABLE_ASH_MATH_SUPPORT_64
13492 numstackptr->val = strtoll(expr, (char **) &expr, 0);
13494 numstackptr->val = strtol(expr, (char **) &expr, 0);
13498 for (p = op_tokens; ; p++) {
13502 /* strange operator not found */
13505 for (o = expr; *p && *o == *p; p++)
13512 /* skip tail uncompared token */
13515 /* skip zero delim */
13520 /* post grammar: a++ reduce to num */
13521 if (lasttok == TOK_POST_INC || lasttok == TOK_POST_DEC)
13524 /* Plus and minus are binary (not unary) _only_ if the last
13525 * token was as number, or a right paren (which pretends to be
13526 * a number, since it evaluates to one). Think about it.
13527 * It makes sense. */
13528 if (lasttok != TOK_NUM) {
13544 /* We don't want a unary operator to cause recursive descent on the
13545 * stack, because there can be many in a row and it could cause an
13546 * operator to be evaluated before its argument is pushed onto the
13547 * integer stack. */
13548 /* But for binary operators, "apply" everything on the operator
13549 * stack until we find an operator with a lesser priority than the
13550 * one we have just extracted. */
13551 /* Left paren is given the lowest priority so it will never be
13552 * "applied" in this way.
13553 * if associativity is right and priority eq, applied also skip
13556 if ((prec > 0 && prec < UNARYPREC) || prec == SPEC_PREC) {
13557 /* not left paren or unary */
13558 if (lasttok != TOK_NUM) {
13559 /* binary op must be preceded by a num */
13562 while (stackptr != stack) {
13563 if (op == TOK_RPAREN) {
13564 /* The algorithm employed here is simple: while we don't
13565 * hit an open paren nor the bottom of the stack, pop
13566 * tokens and apply them */
13567 if (stackptr[-1] == TOK_LPAREN) {
13569 /* Any operator directly after a */
13571 /* close paren should consider itself binary */
13575 operator prev_prec = PREC(stackptr[-1]);
13577 convert_prec_is_assing(prec);
13578 convert_prec_is_assing(prev_prec);
13579 if (prev_prec < prec)
13581 /* check right assoc */
13582 if (prev_prec == prec && is_right_associativity(prec))
13585 errcode = arith_apply(*--stackptr, numstack, &numstackptr);
13586 if (errcode) goto ret;
13588 if (op == TOK_RPAREN) {
13593 /* Push this operator to the stack and remember it. */
13594 *stackptr++ = lasttok = op;
13599 #endif /* ASH_MATH_SUPPORT */
13602 /* ============ main() and helpers */
13605 * Called to exit the shell.
13607 static void exitshell(void) NORETURN;
13615 status = exitstatus;
13616 TRACE(("pid %d, exitshell(%d)\n", getpid(), status));
13617 if (setjmp(loc.loc)) {
13618 if (exception_type == EXEXIT)
13619 /* dash bug: it just does _exit(exitstatus) here
13620 * but we have to do setjobctl(0) first!
13621 * (bug is still not fixed in dash-0.5.3 - if you run dash
13622 * under Midnight Commander, on exit from dash MC is backgrounded) */
13623 status = exitstatus;
13626 exception_handler = &loc;
13632 flush_stdout_stderr();
13642 /* from input.c: */
13643 basepf.next_to_pgetc = basepf.buf = basebuf;
13646 signal(SIGCHLD, SIG_DFL);
13651 char ppid[sizeof(int)*3 + 1];
13653 struct stat st1, st2;
13656 for (envp = environ; envp && *envp; envp++) {
13657 if (strchr(*envp, '=')) {
13658 setvareq(*envp, VEXPORT|VTEXTFIXED);
13662 snprintf(ppid, sizeof(ppid), "%u", (unsigned) getppid());
13663 setvar("PPID", ppid, 0);
13665 p = lookupvar("PWD");
13667 if (*p != '/' || stat(p, &st1) || stat(".", &st2)
13668 || st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino)
13675 * Process the shell command line arguments.
13678 procargs(char **argv)
13681 const char *xminusc;
13686 /* if (xargv[0]) - mmm, this is always true! */
13688 for (i = 0; i < NOPTS; i++)
13692 /* it already printed err message */
13693 raise_exception(EXERROR);
13697 if (*xargv == NULL) {
13699 ash_msg_and_raise_error(bb_msg_requires_arg, "-c");
13702 if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
13706 for (i = 0; i < NOPTS; i++)
13707 if (optlist[i] == 2)
13712 /* POSIX 1003.2: first arg after -c cmd is $0, remainder $1... */
13717 } else if (!sflag) {
13718 setinputfile(*xargv, 0);
13721 commandname = arg0;
13724 shellparam.p = xargv;
13725 #if ENABLE_ASH_GETOPTS
13726 shellparam.optind = 1;
13727 shellparam.optoff = -1;
13729 /* assert(shellparam.malloced == 0 && shellparam.nparam == 0); */
13731 shellparam.nparam++;
13738 * Read /etc/profile or .profile.
13741 read_profile(const char *name)
13745 if (setinputfile(name, INPUT_PUSH_FILE | INPUT_NOFILE_OK) < 0)
13754 * This routine is called when an error or an interrupt occurs in an
13755 * interactive shell and control is returned to the main command loop.
13763 /* from input.c: */
13764 g_parsefile->left_in_buffer = 0;
13765 g_parsefile->left_in_line = 0; /* clear input buffer */
13767 /* from parser.c: */
13770 /* from redir.c: */
13771 clearredir(/*drop:*/ 0);
13775 static short profile_buf[16384];
13776 extern int etext();
13780 * Main routine. We initialize things, parse the arguments, execute
13781 * profiles if we're a login shell, and then call cmdloop to execute
13782 * commands. The setjmp call sets up the location to jump to when an
13783 * exception occurs. When an exception occurs the variable "state"
13784 * is used to figure out how far we had gotten.
13786 int ash_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
13787 int ash_main(int argc UNUSED_PARAM, char **argv)
13790 volatile smallint state;
13791 struct jmploc jmploc;
13792 struct stackmark smark;
13794 /* Initialize global data */
13798 #if ENABLE_ASH_ALIAS
13804 monitor(4, etext, profile_buf, sizeof(profile_buf), 50);
13807 #if ENABLE_FEATURE_EDITING
13808 line_input_state = new_line_input_t(FOR_SHELL | WITH_PATH_LOOKUP);
13811 if (setjmp(jmploc.loc)) {
13817 e = exception_type;
13821 if (e == EXEXIT || s == 0 || iflag == 0 || shlvl)
13824 outcslow('\n', stderr);
13826 popstackmark(&smark);
13827 FORCE_INT_ON; /* enable interrupts */
13836 exception_handler = &jmploc;
13839 TRACE(("Shell args: "));
13840 trace_puts_args(argv);
13842 rootpid = getpid();
13844 #if ENABLE_ASH_RANDOM_SUPPORT
13845 /* Can use monotonic_ns() for better randomness but for now it is
13846 * not used anywhere else in busybox... so avoid bloat */
13847 random_galois_LFSR = random_LCG = rootpid + monotonic_us();
13850 setstackmark(&smark);
13853 #if ENABLE_FEATURE_EDITING_SAVEHISTORY
13855 const char *hp = lookupvar("HISTFILE");
13858 hp = lookupvar("HOME");
13860 char *defhp = concat_path_file(hp, ".ash_history");
13861 setvar("HISTFILE", defhp, 0);
13867 if (/* argv[0] && */ argv[0][0] == '-')
13871 read_profile("/etc/profile");
13874 read_profile(".profile");
13880 getuid() == geteuid() && getgid() == getegid() &&
13884 shinit = lookupvar("ENV");
13885 if (shinit != NULL && *shinit != '\0') {
13886 read_profile(shinit);
13892 /* evalstring pushes parsefile stack.
13893 * Ensure we don't falsely claim that 0 (stdin)
13894 * is one of stacked source fds.
13895 * Testcase: ash -c 'exec 1>&0' must not complain. */
13897 g_parsefile->fd = -1;
13898 evalstring(minusc, 0);
13901 if (sflag || minusc == NULL) {
13902 #if ENABLE_FEATURE_EDITING_SAVEHISTORY
13904 const char *hp = lookupvar("HISTFILE");
13906 line_input_state->hist_file = hp;
13909 state4: /* XXX ??? - why isn't this before the "if" statement */
13917 extern void _mcleanup(void);
13927 * Copyright (c) 1989, 1991, 1993, 1994
13928 * The Regents of the University of California. All rights reserved.
13930 * This code is derived from software contributed to Berkeley by
13931 * Kenneth Almquist.
13933 * Redistribution and use in source and binary forms, with or without
13934 * modification, are permitted provided that the following conditions
13936 * 1. Redistributions of source code must retain the above copyright
13937 * notice, this list of conditions and the following disclaimer.
13938 * 2. Redistributions in binary form must reproduce the above copyright
13939 * notice, this list of conditions and the following disclaimer in the
13940 * documentation and/or other materials provided with the distribution.
13941 * 3. Neither the name of the University nor the names of its contributors
13942 * may be used to endorse or promote products derived from this software
13943 * without specific prior written permission.
13945 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
13946 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
13947 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
13948 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
13949 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
13950 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
13951 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
13952 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
13953 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
13954 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF