1 /* vi: set sw=4 ts=4: */
3 * ash shell port for busybox
5 * Copyright (c) 1989, 1991, 1993, 1994
6 * The Regents of the University of California. All rights reserved.
8 * Copyright (c) 1997-2005 Herbert Xu <herbert@gondor.apana.org.au>
9 * was re-ported from NetBSD and debianized.
11 * This code is derived from software contributed to Berkeley by
14 * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
16 * Original BSD copyright notice is retained at the end of this file.
20 * rewrite arith.y to micro stack based cryptic algorithm by
21 * Copyright (c) 2001 Aaron Lehmann <aaronl@vitelus.com>
23 * Modified by Paul Mundt <lethal@linux-sh.org> (c) 2004 to support
26 * Modified by Vladimir Oleynik <dzo@simtreas.ru> (c) 2001-2005 to be
27 * used in busybox and size optimizations,
28 * rewrote arith (see notes to this), added locale support,
29 * rewrote dynamic variables.
33 * The follow should be set to reflect the type of system you have:
34 * JOBS -> 1 if you have Berkeley job control, 0 otherwise.
35 * define SYSV if you are running under System V.
36 * define DEBUG=1 to compile in debugging ('set -o debug' to turn on)
37 * define DEBUG=2 to compile in and turn on debugging.
39 * When debugging is on, debugging info will be written to ./trace and
40 * a quit signal will generate a core dump.
47 #define JOBS ENABLE_ASH_JOB_CONTROL
55 #include "busybox.h" /* for applet_names */
56 //TODO: pull in some .h and find out do we have SINGLE_APPLET_MAIN?
57 //#include "applet_tables.h" doesn't work
62 #if defined SINGLE_APPLET_MAIN
63 /* STANDALONE does not make sense, and won't compile */
64 #undef CONFIG_FEATURE_SH_STANDALONE
65 #undef ENABLE_FEATURE_SH_STANDALONE
66 #undef USE_FEATURE_SH_STANDALONE
67 #undef SKIP_FEATURE_SH_STANDALONE(...)
68 #define ENABLE_FEATURE_SH_STANDALONE 0
69 #define USE_FEATURE_SH_STANDALONE(...)
70 #define SKIP_FEATURE_SH_STANDALONE(...) __VA_ARGS__
74 #define PIPE_BUF 4096 /* amount of buffering in a pipe */
77 #if defined(__uClinux__)
78 #error "Do not even bother, ash will not run on uClinux"
82 /* ============ Hash table sizes. Configurable. */
86 #define CMDTABLESIZE 31 /* should be prime */
89 /* ============ Misc helpers */
91 #define xbarrier() do { __asm__ __volatile__ ("": : :"memory"); } while (0)
93 /* C99 say: "char" declaration may be signed or unsigned default */
94 #define signed_char2int(sc) ((int)((signed char)sc))
97 /* ============ Shell options */
99 static const char *const optletters_optnames[] = {
120 #define optletters(n) optletters_optnames[(n)][0]
121 #define optnames(n) (&optletters_optnames[(n)][1])
123 enum { NOPTS = ARRAY_SIZE(optletters_optnames) };
126 /* ============ Misc data */
128 static const char homestr[] ALIGN1 = "HOME";
129 static const char snlfmt[] ALIGN1 = "%s\n";
130 static const char illnum[] ALIGN1 = "Illegal number: %s";
133 * We enclose jmp_buf in a structure so that we can declare pointers to
134 * jump locations. The global variable handler contains the location to
135 * jump to when an exception occurs, and the global variable exception
136 * contains a code identifying the exception. To implement nested
137 * exception handlers, the user should save the value of handler on entry
138 * to an inner scope, set handler to point to a jmploc structure for the
139 * inner scope, and restore handler on exit from the scope.
145 struct globals_misc {
146 /* pid of main shell */
148 /* shell level: 0 for the main shell, 1 for its children, and so on */
150 #define rootshell (!shlvl)
151 char *minusc; /* argument to -c option */
153 char *curdir; // = nullstr; /* current working directory */
154 char *physdir; // = nullstr; /* physical working directory */
156 char *arg0; /* value of $0 */
158 struct jmploc *exception_handler;
160 // disabled by vda: cannot understand how it was supposed to work -
161 // cannot fix bugs. That's why you have to explain your non-trivial designs!
162 // /* do we generate EXSIG events */
163 // int exsig; /* counter */
164 volatile int suppressint; /* counter */
165 volatile /*sig_atomic_t*/ smallint intpending; /* 1 = got SIGINT */
166 /* last pending signal */
167 volatile /*sig_atomic_t*/ smallint pendingsig;
168 smallint exception; /* kind of exception (0..5) */
170 #define EXINT 0 /* SIGINT received */
171 #define EXERROR 1 /* a generic error */
172 #define EXSHELLPROC 2 /* execute a shell procedure */
173 #define EXEXEC 3 /* command execution failed */
174 #define EXEXIT 4 /* exit the shell */
175 #define EXSIG 5 /* trapped signal in wait(1) */
178 char nullstr[1]; /* zero length string */
181 #define eflag optlist[0]
182 #define fflag optlist[1]
183 #define Iflag optlist[2]
184 #define iflag optlist[3]
185 #define mflag optlist[4]
186 #define nflag optlist[5]
187 #define sflag optlist[6]
188 #define xflag optlist[7]
189 #define vflag optlist[8]
190 #define Cflag optlist[9]
191 #define aflag optlist[10]
192 #define bflag optlist[11]
193 #define uflag optlist[12]
194 #define viflag optlist[13]
196 #define nolog optlist[14]
197 #define debug optlist[15]
200 /* trap handler commands */
202 * Sigmode records the current value of the signal handlers for the various
203 * modes. A value of zero means that the current handler is not known.
204 * S_HARD_IGN indicates that the signal was ignored on entry to the shell,
206 char sigmode[NSIG - 1];
207 #define S_DFL 1 /* default signal handling (SIG_DFL) */
208 #define S_CATCH 2 /* signal is caught */
209 #define S_IGN 3 /* signal is ignored (SIG_IGN) */
210 #define S_HARD_IGN 4 /* signal is ignored permenantly */
211 #define S_RESET 5 /* temporary - to reset a hard ignored sig */
213 /* indicates specified signal received */
214 char gotsig[NSIG - 1]; /* offset by 1: "signal" 0 is meaningless */
217 /* Rarely referenced stuff */
218 #if ENABLE_ASH_RANDOM_SUPPORT
219 /* Random number generators */
220 int32_t random_galois_LFSR; /* Galois LFSR (fast but weak). signed! */
221 uint32_t random_LCG; /* LCG (fast but weak) */
223 pid_t backgndpid; /* pid of last background process */
224 smallint job_warning; /* user was warned about stopped jobs (can be 2, 1 or 0). */
226 extern struct globals_misc *const ash_ptr_to_globals_misc;
227 #define G_misc (*ash_ptr_to_globals_misc)
228 #define rootpid (G_misc.rootpid )
229 #define shlvl (G_misc.shlvl )
230 #define minusc (G_misc.minusc )
231 #define curdir (G_misc.curdir )
232 #define physdir (G_misc.physdir )
233 #define arg0 (G_misc.arg0 )
234 #define exception_handler (G_misc.exception_handler)
235 #define exception (G_misc.exception )
236 #define suppressint (G_misc.suppressint )
237 #define intpending (G_misc.intpending )
238 //#define exsig (G_misc.exsig )
239 #define pendingsig (G_misc.pendingsig )
240 #define isloginsh (G_misc.isloginsh )
241 #define nullstr (G_misc.nullstr )
242 #define optlist (G_misc.optlist )
243 #define sigmode (G_misc.sigmode )
244 #define gotsig (G_misc.gotsig )
245 #define trap (G_misc.trap )
246 #define random_galois_LFSR (G_misc.random_galois_LFSR)
247 #define random_LCG (G_misc.random_LCG )
248 #define backgndpid (G_misc.backgndpid )
249 #define job_warning (G_misc.job_warning)
250 #define INIT_G_misc() do { \
251 (*(struct globals_misc**)&ash_ptr_to_globals_misc) = xzalloc(sizeof(G_misc)); \
258 /* ============ Utility functions */
259 static int isdigit_str9(const char *str)
261 int maxlen = 9 + 1; /* max 9 digits: 999999999 */
262 while (--maxlen && isdigit(*str))
264 return (*str == '\0');
268 /* ============ Interrupts / exceptions */
270 * These macros allow the user to suspend the handling of interrupt signals
271 * over a period of time. This is similar to SIGHOLD or to sigblock, but
272 * much more efficient and portable. (But hacking the kernel is so much
273 * more fun than worrying about efficiency and portability. :-))
275 #define INT_OFF do { \
281 * Called to raise an exception. Since C doesn't include exceptions, we
282 * just do a longjmp to the exception handler. The type of exception is
283 * stored in the global variable "exception".
285 static void raise_exception(int) NORETURN;
287 raise_exception(int e)
290 if (exception_handler == NULL)
295 longjmp(exception_handler->loc, 1);
299 * Called from trap.c when a SIGINT is received. (If the user specifies
300 * that SIGINT is to be trapped or ignored using the trap builtin, then
301 * this routine is not called.) Suppressint is nonzero when interrupts
302 * are held using the INT_OFF macro. (The test for iflag is just
303 * defensive programming.)
305 static void raise_interrupt(void) NORETURN;
307 raise_interrupt(void)
312 /* Signal is not automatically unmasked after it is raised,
313 * do it ourself - unmask all signals */
314 sigprocmask_allsigs(SIG_UNBLOCK);
315 /* pendingsig = 0; - now done in onsig() */
318 if (gotsig[SIGINT - 1] && !trap[SIGINT]) {
319 if (!(rootshell && iflag)) {
320 /* Kill ourself with SIGINT */
321 signal(SIGINT, SIG_DFL);
330 #if ENABLE_ASH_OPTIMIZE_FOR_SIZE
334 if (--suppressint == 0 && intpending) {
338 #define INT_ON int_on()
346 #define FORCE_INT_ON force_int_on()
348 #define INT_ON do { \
350 if (--suppressint == 0 && intpending) \
353 #define FORCE_INT_ON do { \
359 #endif /* ASH_OPTIMIZE_FOR_SIZE */
361 #define SAVE_INT(v) ((v) = suppressint)
363 #define RESTORE_INT(v) do { \
366 if (suppressint == 0 && intpending) \
371 * Ignore a signal. Only one usage site - in forkchild()
376 if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) {
377 signal(signo, SIG_IGN);
379 sigmode[signo - 1] = S_HARD_IGN;
383 * Signal handler. Only one usage site - in setsignal()
388 gotsig[signo - 1] = 1;
391 if (/* exsig || */ (signo == SIGINT && !trap[SIGINT])) {
394 raise_interrupt(); /* does not return */
401 /* ============ Stdout/stderr output */
404 outstr(const char *p, FILE *file)
412 flush_stdout_stderr(void)
429 outcslow(int c, FILE *dest)
437 static int out1fmt(const char *, ...) __attribute__((__format__(__printf__,1,2)));
439 out1fmt(const char *fmt, ...)
446 r = vprintf(fmt, ap);
452 static int fmtstr(char *, size_t, const char *, ...) __attribute__((__format__(__printf__,3,4)));
454 fmtstr(char *outbuf, size_t length, const char *fmt, ...)
461 ret = vsnprintf(outbuf, length, fmt, ap);
468 out1str(const char *p)
474 out2str(const char *p)
481 /* ============ Parser structures */
483 /* control characters in argument strings */
484 #define CTLESC '\201' /* escape next character */
485 #define CTLVAR '\202' /* variable defn */
486 #define CTLENDVAR '\203'
487 #define CTLBACKQ '\204'
488 #define CTLQUOTE 01 /* ored with CTLBACKQ code if in quotes */
489 /* CTLBACKQ | CTLQUOTE == '\205' */
490 #define CTLARI '\206' /* arithmetic expression */
491 #define CTLENDARI '\207'
492 #define CTLQUOTEMARK '\210'
494 /* variable substitution byte (follows CTLVAR) */
495 #define VSTYPE 0x0f /* type of variable substitution */
496 #define VSNUL 0x10 /* colon--treat the empty string as unset */
497 #define VSQUOTE 0x80 /* inside double quotes--suppress splitting */
499 /* values of VSTYPE field */
500 #define VSNORMAL 0x1 /* normal variable: $var or ${var} */
501 #define VSMINUS 0x2 /* ${var-text} */
502 #define VSPLUS 0x3 /* ${var+text} */
503 #define VSQUESTION 0x4 /* ${var?message} */
504 #define VSASSIGN 0x5 /* ${var=text} */
505 #define VSTRIMRIGHT 0x6 /* ${var%pattern} */
506 #define VSTRIMRIGHTMAX 0x7 /* ${var%%pattern} */
507 #define VSTRIMLEFT 0x8 /* ${var#pattern} */
508 #define VSTRIMLEFTMAX 0x9 /* ${var##pattern} */
509 #define VSLENGTH 0xa /* ${#var} */
510 #if ENABLE_ASH_BASH_COMPAT
511 #define VSSUBSTR 0xc /* ${var:position:length} */
512 #define VSREPLACE 0xd /* ${var/pattern/replacement} */
513 #define VSREPLACEALL 0xe /* ${var//pattern/replacement} */
516 static const char dolatstr[] ALIGN1 = {
517 CTLVAR, VSNORMAL|VSQUOTE, '@', '=', '\0'
537 #if ENABLE_ASH_BASH_COMPAT
554 smallint type; /* Nxxxx */
557 union node *redirect;
562 smallint pipe_backgnd;
563 struct nodelist *cmdlist;
569 union node *redirect;
582 union node *elsepart;
609 struct nodelist *backquote;
612 /* nfile and ndup layout must match!
613 * NTOFD (>&fdnum) uses ndup structure, but we may discover mid-flight
614 * that it is actually NTO2 (>&file), and change its type.
631 char *_unused_expfname;
650 struct nredir nredir;
651 struct nbinary nbinary;
655 struct nclist nclist;
664 struct nodelist *next;
677 freefunc(struct funcnode *f)
679 if (f && --f->count < 0)
684 /* ============ Debugging output */
688 static FILE *tracefile;
691 trace_printf(const char *fmt, ...)
698 vfprintf(tracefile, fmt, va);
703 trace_vprintf(const char *fmt, va_list va)
707 vfprintf(tracefile, fmt, va);
711 trace_puts(const char *s)
719 trace_puts_quoted(char *s)
726 putc('"', tracefile);
727 for (p = s; *p; p++) {
729 case '\n': c = 'n'; goto backslash;
730 case '\t': c = 't'; goto backslash;
731 case '\r': c = 'r'; goto backslash;
732 case '"': c = '"'; goto backslash;
733 case '\\': c = '\\'; goto backslash;
734 case CTLESC: c = 'e'; goto backslash;
735 case CTLVAR: c = 'v'; goto backslash;
736 case CTLVAR+CTLQUOTE: c = 'V'; goto backslash;
737 case CTLBACKQ: c = 'q'; goto backslash;
738 case CTLBACKQ+CTLQUOTE: c = 'Q'; goto backslash;
740 putc('\\', tracefile);
744 if (*p >= ' ' && *p <= '~')
747 putc('\\', tracefile);
748 putc(*p >> 6 & 03, tracefile);
749 putc(*p >> 3 & 07, tracefile);
750 putc(*p & 07, tracefile);
755 putc('"', tracefile);
759 trace_puts_args(char **ap)
766 trace_puts_quoted(*ap);
768 putc('\n', tracefile);
771 putc(' ', tracefile);
786 /* leave open because libedit might be using it */
789 strcpy(s, "./trace");
791 if (!freopen(s, "a", tracefile)) {
792 fprintf(stderr, "Can't re-open %s\n", s);
797 tracefile = fopen(s, "a");
798 if (tracefile == NULL) {
799 fprintf(stderr, "Can't open %s\n", s);
805 flags = fcntl(fileno(tracefile), F_GETFL);
807 fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND);
809 setlinebuf(tracefile);
810 fputs("\nTracing started.\n", tracefile);
814 indent(int amount, char *pfx, FILE *fp)
818 for (i = 0; i < amount; i++) {
819 if (pfx && i == amount - 1)
825 /* little circular references here... */
826 static void shtree(union node *n, int ind, char *pfx, FILE *fp);
829 sharg(union node *arg, FILE *fp)
832 struct nodelist *bqlist;
835 if (arg->type != NARG) {
836 out1fmt("<node type %d>\n", arg->type);
839 bqlist = arg->narg.backquote;
840 for (p = arg->narg.text; *p; p++) {
849 if (subtype == VSLENGTH)
858 switch (subtype & VSTYPE) {
891 out1fmt("<subtype %d>", subtype);
898 case CTLBACKQ|CTLQUOTE:
901 shtree(bqlist->n, -1, NULL, fp);
912 shcmd(union node *cmd, FILE *fp)
920 for (np = cmd->ncmd.args; np; np = np->narg.next) {
926 for (np = cmd->ncmd.redirect; np; np = np->nfile.next) {
930 switch (np->nfile.type) {
931 case NTO: s = ">>"+1; dftfd = 1; break;
932 case NCLOBBER: s = ">|"; dftfd = 1; break;
933 case NAPPEND: s = ">>"; dftfd = 1; break;
934 #if ENABLE_ASH_BASH_COMPAT
937 case NTOFD: s = ">&"; dftfd = 1; break;
938 case NFROM: s = "<"; break;
939 case NFROMFD: s = "<&"; break;
940 case NFROMTO: s = "<>"; break;
941 default: s = "*error*"; break;
943 if (np->nfile.fd != dftfd)
944 fprintf(fp, "%d", np->nfile.fd);
946 if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) {
947 fprintf(fp, "%d", np->ndup.dupfd);
949 sharg(np->nfile.fname, fp);
956 shtree(union node *n, int ind, char *pfx, FILE *fp)
964 indent(ind, pfx, fp);
975 shtree(n->nbinary.ch1, ind, NULL, fp);
978 shtree(n->nbinary.ch2, ind, NULL, fp);
986 for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
991 if (n->npipe.pipe_backgnd)
997 fprintf(fp, "<node type %d>", n->type);
1005 showtree(union node *n)
1007 trace_puts("showtree called\n");
1008 shtree(n, 1, NULL, stdout);
1011 #define TRACE(param) trace_printf param
1012 #define TRACEV(param) trace_vprintf param
1016 #define TRACE(param)
1017 #define TRACEV(param)
1022 /* ============ Parser data */
1025 * ash_vmsg() needs parsefile->fd, hence parsefile definition is moved up.
1028 struct strlist *next;
1035 struct strpush *prev; /* preceding string on stack */
1037 int prev_left_in_line;
1038 #if ENABLE_ASH_ALIAS
1039 struct alias *ap; /* if push was associated with an alias */
1041 char *string; /* remember the string since it may change */
1045 struct parsefile *prev; /* preceding file on stack */
1046 int linno; /* current line */
1047 int fd; /* file descriptor (or -1 if string) */
1048 int left_in_line; /* number of chars left in this line */
1049 int left_in_buffer; /* number of chars left in this buffer past the line */
1050 char *next_to_pgetc; /* next char in buffer */
1051 char *buf; /* input buffer */
1052 struct strpush *strpush; /* for pushing strings at this level */
1053 struct strpush basestrpush; /* so pushing one is fast */
1056 static struct parsefile basepf; /* top level input file */
1057 static struct parsefile *g_parsefile = &basepf; /* current input file */
1058 static int startlinno; /* line # where last token started */
1059 static char *commandname; /* currently executing command */
1060 static struct strlist *cmdenviron; /* environment for builtin command */
1061 static uint8_t exitstatus; /* exit status of last command */
1064 /* ============ Message printing */
1067 ash_vmsg(const char *msg, va_list ap)
1069 fprintf(stderr, "%s: ", arg0);
1071 if (strcmp(arg0, commandname))
1072 fprintf(stderr, "%s: ", commandname);
1073 if (!iflag || g_parsefile->fd)
1074 fprintf(stderr, "line %d: ", startlinno);
1076 vfprintf(stderr, msg, ap);
1077 outcslow('\n', stderr);
1081 * Exverror is called to raise the error exception. If the second argument
1082 * is not NULL then error prints an error message using printf style
1083 * formatting. It then raises the error exception.
1085 static void ash_vmsg_and_raise(int, const char *, va_list) NORETURN;
1087 ash_vmsg_and_raise(int cond, const char *msg, va_list ap)
1091 TRACE(("ash_vmsg_and_raise(%d, \"", cond));
1093 TRACE(("\") pid=%d\n", getpid()));
1095 TRACE(("ash_vmsg_and_raise(%d, NULL) pid=%d\n", cond, getpid()));
1100 flush_stdout_stderr();
1101 raise_exception(cond);
1105 static void ash_msg_and_raise_error(const char *, ...) NORETURN;
1107 ash_msg_and_raise_error(const char *msg, ...)
1112 ash_vmsg_and_raise(EXERROR, msg, ap);
1117 static void ash_msg_and_raise(int, const char *, ...) NORETURN;
1119 ash_msg_and_raise(int cond, const char *msg, ...)
1124 ash_vmsg_and_raise(cond, msg, ap);
1130 * error/warning routines for external builtins
1133 ash_msg(const char *fmt, ...)
1143 * Return a string describing an error. The returned string may be a
1144 * pointer to a static buffer that will be overwritten on the next call.
1145 * Action describes the operation that got the error.
1148 errmsg(int e, const char *em)
1150 if (e == ENOENT || e == ENOTDIR) {
1157 /* ============ Memory allocation */
1160 * It appears that grabstackstr() will barf with such alignments
1161 * because stalloc() will return a string allocated in a new stackblock.
1163 #define SHELL_ALIGN(nbytes) (((nbytes) + SHELL_SIZE) & ~SHELL_SIZE)
1165 /* Most machines require the value returned from malloc to be aligned
1166 * in some way. The following macro will get this right
1167 * on many machines. */
1168 SHELL_SIZE = sizeof(union {int i; char *cp; double d; }) - 1,
1169 /* Minimum size of a block */
1170 MINSIZE = SHELL_ALIGN(504),
1173 struct stack_block {
1174 struct stack_block *prev;
1175 char space[MINSIZE];
1179 struct stack_block *stackp;
1182 struct stackmark *marknext;
1186 struct globals_memstack {
1187 struct stack_block *g_stackp; // = &stackbase;
1188 struct stackmark *markp;
1189 char *g_stacknxt; // = stackbase.space;
1190 char *sstrend; // = stackbase.space + MINSIZE;
1191 size_t g_stacknleft; // = MINSIZE;
1192 int herefd; // = -1;
1193 struct stack_block stackbase;
1195 extern struct globals_memstack *const ash_ptr_to_globals_memstack;
1196 #define G_memstack (*ash_ptr_to_globals_memstack)
1197 #define g_stackp (G_memstack.g_stackp )
1198 #define markp (G_memstack.markp )
1199 #define g_stacknxt (G_memstack.g_stacknxt )
1200 #define sstrend (G_memstack.sstrend )
1201 #define g_stacknleft (G_memstack.g_stacknleft)
1202 #define herefd (G_memstack.herefd )
1203 #define stackbase (G_memstack.stackbase )
1204 #define INIT_G_memstack() do { \
1205 (*(struct globals_memstack**)&ash_ptr_to_globals_memstack) = xzalloc(sizeof(G_memstack)); \
1207 g_stackp = &stackbase; \
1208 g_stacknxt = stackbase.space; \
1209 g_stacknleft = MINSIZE; \
1210 sstrend = stackbase.space + MINSIZE; \
1214 #define stackblock() ((void *)g_stacknxt)
1215 #define stackblocksize() g_stacknleft
1219 ckrealloc(void * p, size_t nbytes)
1221 p = realloc(p, nbytes);
1223 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1228 ckmalloc(size_t nbytes)
1230 return ckrealloc(NULL, nbytes);
1234 ckzalloc(size_t nbytes)
1236 return memset(ckmalloc(nbytes), 0, nbytes);
1240 * Make a copy of a string in safe storage.
1243 ckstrdup(const char *s)
1245 char *p = strdup(s);
1247 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1252 * Parse trees for commands are allocated in lifo order, so we use a stack
1253 * to make this more efficient, and also to avoid all sorts of exception
1254 * handling code to handle interrupts in the middle of a parse.
1256 * The size 504 was chosen because the Ultrix malloc handles that size
1260 stalloc(size_t nbytes)
1265 aligned = SHELL_ALIGN(nbytes);
1266 if (aligned > g_stacknleft) {
1269 struct stack_block *sp;
1271 blocksize = aligned;
1272 if (blocksize < MINSIZE)
1273 blocksize = MINSIZE;
1274 len = sizeof(struct stack_block) - MINSIZE + blocksize;
1275 if (len < blocksize)
1276 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1279 sp->prev = g_stackp;
1280 g_stacknxt = sp->space;
1281 g_stacknleft = blocksize;
1282 sstrend = g_stacknxt + blocksize;
1287 g_stacknxt += aligned;
1288 g_stacknleft -= aligned;
1293 stzalloc(size_t nbytes)
1295 return memset(stalloc(nbytes), 0, nbytes);
1302 if (!p || (g_stacknxt < (char *)p) || ((char *)p < g_stackp->space)) {
1303 write(STDERR_FILENO, "stunalloc\n", 10);
1307 g_stacknleft += g_stacknxt - (char *)p;
1312 * Like strdup but works with the ash stack.
1315 ststrdup(const char *p)
1317 size_t len = strlen(p) + 1;
1318 return memcpy(stalloc(len), p, len);
1322 setstackmark(struct stackmark *mark)
1324 mark->stackp = g_stackp;
1325 mark->stacknxt = g_stacknxt;
1326 mark->stacknleft = g_stacknleft;
1327 mark->marknext = markp;
1332 popstackmark(struct stackmark *mark)
1334 struct stack_block *sp;
1340 markp = mark->marknext;
1341 while (g_stackp != mark->stackp) {
1343 g_stackp = sp->prev;
1346 g_stacknxt = mark->stacknxt;
1347 g_stacknleft = mark->stacknleft;
1348 sstrend = mark->stacknxt + mark->stacknleft;
1353 * When the parser reads in a string, it wants to stick the string on the
1354 * stack and only adjust the stack pointer when it knows how big the
1355 * string is. Stackblock (defined in stack.h) returns a pointer to a block
1356 * of space on top of the stack and stackblocklen returns the length of
1357 * this block. Growstackblock will grow this space by at least one byte,
1358 * possibly moving it (like realloc). Grabstackblock actually allocates the
1359 * part of the block that has been used.
1362 growstackblock(void)
1366 newlen = g_stacknleft * 2;
1367 if (newlen < g_stacknleft)
1368 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1372 if (g_stacknxt == g_stackp->space && g_stackp != &stackbase) {
1373 struct stack_block *oldstackp;
1374 struct stackmark *xmark;
1375 struct stack_block *sp;
1376 struct stack_block *prevstackp;
1380 oldstackp = g_stackp;
1382 prevstackp = sp->prev;
1383 grosslen = newlen + sizeof(struct stack_block) - MINSIZE;
1384 sp = ckrealloc(sp, grosslen);
1385 sp->prev = prevstackp;
1387 g_stacknxt = sp->space;
1388 g_stacknleft = newlen;
1389 sstrend = sp->space + newlen;
1392 * Stack marks pointing to the start of the old block
1393 * must be relocated to point to the new block
1396 while (xmark != NULL && xmark->stackp == oldstackp) {
1397 xmark->stackp = g_stackp;
1398 xmark->stacknxt = g_stacknxt;
1399 xmark->stacknleft = g_stacknleft;
1400 xmark = xmark->marknext;
1404 char *oldspace = g_stacknxt;
1405 size_t oldlen = g_stacknleft;
1406 char *p = stalloc(newlen);
1408 /* free the space we just allocated */
1409 g_stacknxt = memcpy(p, oldspace, oldlen);
1410 g_stacknleft += newlen;
1415 grabstackblock(size_t len)
1417 len = SHELL_ALIGN(len);
1419 g_stacknleft -= len;
1423 * The following routines are somewhat easier to use than the above.
1424 * The user declares a variable of type STACKSTR, which may be declared
1425 * to be a register. The macro STARTSTACKSTR initializes things. Then
1426 * the user uses the macro STPUTC to add characters to the string. In
1427 * effect, STPUTC(c, p) is the same as *p++ = c except that the stack is
1428 * grown as necessary. When the user is done, she can just leave the
1429 * string there and refer to it using stackblock(). Or she can allocate
1430 * the space for it using grabstackstr(). If it is necessary to allow
1431 * someone else to use the stack temporarily and then continue to grow
1432 * the string, the user should use grabstack to allocate the space, and
1433 * then call ungrabstr(p) to return to the previous mode of operation.
1435 * USTPUTC is like STPUTC except that it doesn't check for overflow.
1436 * CHECKSTACKSPACE can be called before USTPUTC to ensure that there
1437 * is space for at least one character.
1442 size_t len = stackblocksize();
1443 if (herefd >= 0 && len >= 1024) {
1444 full_write(herefd, stackblock(), len);
1445 return stackblock();
1448 return (char *)stackblock() + len;
1452 * Called from CHECKSTRSPACE.
1455 makestrspace(size_t newlen, char *p)
1457 size_t len = p - g_stacknxt;
1458 size_t size = stackblocksize();
1463 size = stackblocksize();
1465 if (nleft >= newlen)
1469 return (char *)stackblock() + len;
1473 stack_nputstr(const char *s, size_t n, char *p)
1475 p = makestrspace(n, p);
1476 p = (char *)memcpy(p, s, n) + n;
1481 stack_putstr(const char *s, char *p)
1483 return stack_nputstr(s, strlen(s), p);
1487 _STPUTC(int c, char *p)
1495 #define STARTSTACKSTR(p) ((p) = stackblock())
1496 #define STPUTC(c, p) ((p) = _STPUTC((c), (p)))
1497 #define CHECKSTRSPACE(n, p) do { \
1500 size_t m = sstrend - q; \
1502 (p) = makestrspace(l, q); \
1504 #define USTPUTC(c, p) (*(p)++ = (c))
1505 #define STACKSTRNUL(p) do { \
1506 if ((p) == sstrend) \
1507 (p) = growstackstr(); \
1510 #define STUNPUTC(p) (--(p))
1511 #define STTOPC(p) ((p)[-1])
1512 #define STADJUST(amount, p) ((p) += (amount))
1514 #define grabstackstr(p) stalloc((char *)(p) - (char *)stackblock())
1515 #define ungrabstackstr(s, p) stunalloc(s)
1516 #define stackstrend() ((void *)sstrend)
1519 /* ============ String helpers */
1522 * prefix -- see if pfx is a prefix of string.
1525 prefix(const char *string, const char *pfx)
1528 if (*pfx++ != *string++)
1531 return (char *) string;
1535 * Check for a valid number. This should be elsewhere.
1538 is_number(const char *p)
1543 } while (*++p != '\0');
1548 * Convert a string of digits to an integer, printing an error message on
1552 number(const char *s)
1555 ash_msg_and_raise_error(illnum, s);
1560 * Produce a possibly single quoted string suitable as input to the shell.
1561 * The return string is allocated on the stack.
1564 single_quote(const char *s)
1574 len = strchrnul(s, '\'') - s;
1576 q = p = makestrspace(len + 3, p);
1579 q = (char *)memcpy(q, s, len) + len;
1585 len = strspn(s, "'");
1589 q = p = makestrspace(len + 3, p);
1592 q = (char *)memcpy(q, s, len) + len;
1601 return stackblock();
1605 /* ============ nextopt */
1607 static char **argptr; /* argument list for builtin commands */
1608 static char *optionarg; /* set by nextopt (like getopt) */
1609 static char *optptr; /* used by nextopt */
1612 * XXX - should get rid of. Have all builtins use getopt(3).
1613 * The library getopt must have the BSD extension static variable
1614 * "optreset", otherwise it can't be used within the shell safely.
1616 * Standard option processing (a la getopt) for builtin routines.
1617 * The only argument that is passed to nextopt is the option string;
1618 * the other arguments are unnecessary. It returns the character,
1619 * or '\0' on end of input.
1622 nextopt(const char *optstring)
1629 if (p == NULL || *p == '\0') {
1630 /* We ate entire "-param", take next one */
1636 if (*++p == '\0') /* just "-" ? */
1639 if (LONE_DASH(p)) /* "--" ? */
1641 /* p => next "-param" */
1643 /* p => some option char in the middle of a "-param" */
1645 for (q = optstring; *q != c;) {
1647 ash_msg_and_raise_error("illegal option -%c", c);
1655 ash_msg_and_raise_error("no arg for -%c option", c);
1665 /* ============ Shell variables */
1668 * The parsefile structure pointed to by the global variable parsefile
1669 * contains information about the current file being read.
1672 int nparam; /* # of positional parameters (without $0) */
1673 #if ENABLE_ASH_GETOPTS
1674 int optind; /* next parameter to be processed by getopts */
1675 int optoff; /* used by getopts */
1677 unsigned char malloced; /* if parameter list dynamically allocated */
1678 char **p; /* parameter list */
1682 * Free the list of positional parameters.
1685 freeparam(volatile struct shparam *param)
1687 if (param->malloced) {
1689 ap = ap1 = param->p;
1696 #if ENABLE_ASH_GETOPTS
1697 static void getoptsreset(const char *value);
1701 struct var *next; /* next entry in hash list */
1702 int flags; /* flags are defined above */
1703 const char *text; /* name=value */
1704 void (*func)(const char *); /* function to be called when */
1705 /* the variable gets set/unset */
1709 struct localvar *next; /* next local variable in list */
1710 struct var *vp; /* the variable that was made local */
1711 int flags; /* saved flags */
1712 const char *text; /* saved text */
1716 #define VEXPORT 0x01 /* variable is exported */
1717 #define VREADONLY 0x02 /* variable cannot be modified */
1718 #define VSTRFIXED 0x04 /* variable struct is statically allocated */
1719 #define VTEXTFIXED 0x08 /* text is statically allocated */
1720 #define VSTACK 0x10 /* text is allocated on the stack */
1721 #define VUNSET 0x20 /* the variable is not set */
1722 #define VNOFUNC 0x40 /* don't call the callback function */
1723 #define VNOSET 0x80 /* do not set variable - just readonly test */
1724 #define VNOSAVE 0x100 /* when text is on the heap before setvareq */
1725 #if ENABLE_ASH_RANDOM_SUPPORT
1726 # define VDYNAMIC 0x200 /* dynamic variable */
1732 static const char defifsvar[] ALIGN1 = "IFS= \t\n";
1733 #define defifs (defifsvar + 4)
1735 static const char defifs[] ALIGN1 = " \t\n";
1739 /* Need to be before varinit_data[] */
1740 #if ENABLE_LOCALE_SUPPORT
1742 change_lc_all(const char *value)
1744 if (value && *value != '\0')
1745 setlocale(LC_ALL, value);
1748 change_lc_ctype(const char *value)
1750 if (value && *value != '\0')
1751 setlocale(LC_CTYPE, value);
1755 static void chkmail(void);
1756 static void changemail(const char *);
1758 static void changepath(const char *);
1759 #if ENABLE_ASH_RANDOM_SUPPORT
1760 static void change_random(const char *);
1763 static const struct {
1766 void (*func)(const char *);
1767 } varinit_data[] = {
1769 { VSTRFIXED|VTEXTFIXED , defifsvar , NULL },
1771 { VSTRFIXED|VTEXTFIXED|VUNSET, "IFS\0" , NULL },
1774 { VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL\0" , changemail },
1775 { VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH\0", changemail },
1777 { VSTRFIXED|VTEXTFIXED , bb_PATH_root_path, changepath },
1778 { VSTRFIXED|VTEXTFIXED , "PS1=$ " , NULL },
1779 { VSTRFIXED|VTEXTFIXED , "PS2=> " , NULL },
1780 { VSTRFIXED|VTEXTFIXED , "PS4=+ " , NULL },
1781 #if ENABLE_ASH_GETOPTS
1782 { VSTRFIXED|VTEXTFIXED , "OPTIND=1" , getoptsreset },
1784 #if ENABLE_ASH_RANDOM_SUPPORT
1785 { VSTRFIXED|VTEXTFIXED|VUNSET|VDYNAMIC, "RANDOM\0", change_random },
1787 #if ENABLE_LOCALE_SUPPORT
1788 { VSTRFIXED|VTEXTFIXED|VUNSET, "LC_ALL\0" , change_lc_all },
1789 { VSTRFIXED|VTEXTFIXED|VUNSET, "LC_CTYPE\0", change_lc_ctype },
1791 #if ENABLE_FEATURE_EDITING_SAVEHISTORY
1792 { VSTRFIXED|VTEXTFIXED|VUNSET, "HISTFILE\0", NULL },
1798 struct globals_var {
1799 struct shparam shellparam; /* $@ current positional parameters */
1800 struct redirtab *redirlist;
1802 int preverrout_fd; /* save fd2 before print debug if xflag is set. */
1803 struct var *vartab[VTABSIZE];
1804 struct var varinit[ARRAY_SIZE(varinit_data)];
1806 extern struct globals_var *const ash_ptr_to_globals_var;
1807 #define G_var (*ash_ptr_to_globals_var)
1808 #define shellparam (G_var.shellparam )
1809 //#define redirlist (G_var.redirlist )
1810 #define g_nullredirs (G_var.g_nullredirs )
1811 #define preverrout_fd (G_var.preverrout_fd)
1812 #define vartab (G_var.vartab )
1813 #define varinit (G_var.varinit )
1814 #define INIT_G_var() do { \
1816 (*(struct globals_var**)&ash_ptr_to_globals_var) = xzalloc(sizeof(G_var)); \
1818 for (i = 0; i < ARRAY_SIZE(varinit_data); i++) { \
1819 varinit[i].flags = varinit_data[i].flags; \
1820 varinit[i].text = varinit_data[i].text; \
1821 varinit[i].func = varinit_data[i].func; \
1825 #define vifs varinit[0]
1827 # define vmail (&vifs)[1]
1828 # define vmpath (&vmail)[1]
1829 # define vpath (&vmpath)[1]
1831 # define vpath (&vifs)[1]
1833 #define vps1 (&vpath)[1]
1834 #define vps2 (&vps1)[1]
1835 #define vps4 (&vps2)[1]
1836 #if ENABLE_ASH_GETOPTS
1837 # define voptind (&vps4)[1]
1838 # if ENABLE_ASH_RANDOM_SUPPORT
1839 # define vrandom (&voptind)[1]
1842 # if ENABLE_ASH_RANDOM_SUPPORT
1843 # define vrandom (&vps4)[1]
1848 * The following macros access the values of the above variables.
1849 * They have to skip over the name. They return the null string
1850 * for unset variables.
1852 #define ifsval() (vifs.text + 4)
1853 #define ifsset() ((vifs.flags & VUNSET) == 0)
1855 # define mailval() (vmail.text + 5)
1856 # define mpathval() (vmpath.text + 9)
1857 # define mpathset() ((vmpath.flags & VUNSET) == 0)
1859 #define pathval() (vpath.text + 5)
1860 #define ps1val() (vps1.text + 4)
1861 #define ps2val() (vps2.text + 4)
1862 #define ps4val() (vps4.text + 4)
1863 #if ENABLE_ASH_GETOPTS
1864 # define optindval() (voptind.text + 7)
1868 #define is_name(c) ((c) == '_' || isalpha((unsigned char)(c)))
1869 #define is_in_name(c) ((c) == '_' || isalnum((unsigned char)(c)))
1871 #if ENABLE_ASH_GETOPTS
1873 getoptsreset(const char *value)
1875 shellparam.optind = number(value);
1876 shellparam.optoff = -1;
1881 * Return of a legal variable name (a letter or underscore followed by zero or
1882 * more letters, underscores, and digits).
1885 endofname(const char *name)
1893 if (!is_in_name(*p))
1900 * Compares two strings up to the first = or '\0'. The first
1901 * string must be terminated by '='; the second may be terminated by
1902 * either '=' or '\0'.
1905 varcmp(const char *p, const char *q)
1909 while ((c = *p) == (d = *q)) {
1924 varequal(const char *a, const char *b)
1926 return !varcmp(a, b);
1930 * Find the appropriate entry in the hash table from the name.
1932 static struct var **
1933 hashvar(const char *p)
1937 hashval = ((unsigned char) *p) << 4;
1938 while (*p && *p != '=')
1939 hashval += (unsigned char) *p++;
1940 return &vartab[hashval % VTABSIZE];
1944 vpcmp(const void *a, const void *b)
1946 return varcmp(*(const char **)a, *(const char **)b);
1950 * This routine initializes the builtin variables.
1960 * PS1 depends on uid
1962 #if ENABLE_FEATURE_EDITING && ENABLE_FEATURE_EDITING_FANCY_PROMPT
1963 vps1.text = "PS1=\\w \\$ ";
1966 vps1.text = "PS1=# ";
1969 end = vp + ARRAY_SIZE(varinit);
1971 vpp = hashvar(vp->text);
1974 } while (++vp < end);
1977 static struct var **
1978 findvar(struct var **vpp, const char *name)
1980 for (; *vpp; vpp = &(*vpp)->next) {
1981 if (varequal((*vpp)->text, name)) {
1989 * Find the value of a variable. Returns NULL if not set.
1992 lookupvar(const char *name)
1996 v = *findvar(hashvar(name), name);
1998 #if ENABLE_ASH_RANDOM_SUPPORT
2000 * Dynamic variables are implemented roughly the same way they are
2001 * in bash. Namely, they're "special" so long as they aren't unset.
2002 * As soon as they're unset, they're no longer dynamic, and dynamic
2003 * lookup will no longer happen at that point. -- PFM.
2005 if ((v->flags & VDYNAMIC))
2008 if (!(v->flags & VUNSET))
2009 return strchrnul(v->text, '=') + 1;
2015 * Search the environment of a builtin command.
2018 bltinlookup(const char *name)
2022 for (sp = cmdenviron; sp; sp = sp->next) {
2023 if (varequal(sp->text, name))
2024 return strchrnul(sp->text, '=') + 1;
2026 return lookupvar(name);
2030 * Same as setvar except that the variable and value are passed in
2031 * the first argument as name=value. Since the first argument will
2032 * be actually stored in the table, it should not be a string that
2034 * Called with interrupts off.
2037 setvareq(char *s, int flags)
2039 struct var *vp, **vpp;
2042 flags |= (VEXPORT & (((unsigned) (1 - aflag)) - 1));
2043 vp = *findvar(vpp, s);
2045 if ((vp->flags & (VREADONLY|VDYNAMIC)) == VREADONLY) {
2048 if (flags & VNOSAVE)
2051 ash_msg_and_raise_error("%.*s: is read only", strchrnul(n, '=') - n, n);
2057 if (vp->func && (flags & VNOFUNC) == 0)
2058 (*vp->func)(strchrnul(s, '=') + 1);
2060 if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
2061 free((char*)vp->text);
2063 flags |= vp->flags & ~(VTEXTFIXED|VSTACK|VNOSAVE|VUNSET);
2068 vp = ckzalloc(sizeof(*vp));
2070 /*vp->func = NULL; - ckzalloc did it */
2073 if (!(flags & (VTEXTFIXED|VSTACK|VNOSAVE)))
2080 * Set the value of a variable. The flags argument is ored with the
2081 * flags of the variable. If val is NULL, the variable is unset.
2084 setvar(const char *name, const char *val, int flags)
2091 q = endofname(name);
2092 p = strchrnul(q, '=');
2094 if (!namelen || p != q)
2095 ash_msg_and_raise_error("%.*s: bad variable name", namelen, name);
2100 vallen = strlen(val);
2103 nameeq = ckmalloc(namelen + vallen + 2);
2104 p = (char *)memcpy(nameeq, name, namelen) + namelen;
2107 p = (char *)memcpy(p, val, vallen) + vallen;
2110 setvareq(nameeq, flags | VNOSAVE);
2114 #if ENABLE_ASH_GETOPTS
2116 * Safe version of setvar, returns 1 on success 0 on failure.
2119 setvarsafe(const char *name, const char *val, int flags)
2122 volatile int saveint;
2123 struct jmploc *volatile savehandler = exception_handler;
2124 struct jmploc jmploc;
2127 if (setjmp(jmploc.loc))
2130 exception_handler = &jmploc;
2131 setvar(name, val, flags);
2134 exception_handler = savehandler;
2135 RESTORE_INT(saveint);
2141 * Unset the specified variable.
2144 unsetvar(const char *s)
2150 vpp = findvar(hashvar(s), s);
2154 int flags = vp->flags;
2157 if (flags & VREADONLY)
2159 #if ENABLE_ASH_RANDOM_SUPPORT
2160 vp->flags &= ~VDYNAMIC;
2164 if ((flags & VSTRFIXED) == 0) {
2166 if ((flags & (VTEXTFIXED|VSTACK)) == 0)
2167 free((char*)vp->text);
2173 vp->flags &= ~VEXPORT;
2183 * Process a linked list of variable assignments.
2186 listsetvar(struct strlist *list_set_var, int flags)
2188 struct strlist *lp = list_set_var;
2194 setvareq(lp->text, flags);
2201 * Generate a list of variables satisfying the given conditions.
2204 listvars(int on, int off, char ***end)
2215 for (vp = *vpp; vp; vp = vp->next) {
2216 if ((vp->flags & mask) == on) {
2217 if (ep == stackstrend())
2218 ep = growstackstr();
2219 *ep++ = (char *) vp->text;
2222 } while (++vpp < vartab + VTABSIZE);
2223 if (ep == stackstrend())
2224 ep = growstackstr();
2228 return grabstackstr(ep);
2232 /* ============ Path search helper
2234 * The variable path (passed by reference) should be set to the start
2235 * of the path before the first call; padvance will update
2236 * this value as it proceeds. Successive calls to padvance will return
2237 * the possible path expansions in sequence. If an option (indicated by
2238 * a percent sign) appears in the path entry then the global variable
2239 * pathopt will be set to point to it; otherwise pathopt will be set to
2242 static const char *pathopt; /* set by padvance */
2245 padvance(const char **path, const char *name)
2255 for (p = start; *p && *p != ':' && *p != '%'; p++)
2257 len = p - start + strlen(name) + 2; /* "2" is for '/' and '\0' */
2258 while (stackblocksize() < len)
2262 memcpy(q, start, p - start);
2270 while (*p && *p != ':')
2277 return stalloc(len);
2281 /* ============ Prompt */
2283 static smallint doprompt; /* if set, prompt the user */
2284 static smallint needprompt; /* true if interactive and at start of line */
2286 #if ENABLE_FEATURE_EDITING
2287 static line_input_t *line_input_state;
2288 static const char *cmdedit_prompt;
2290 putprompt(const char *s)
2292 if (ENABLE_ASH_EXPAND_PRMT) {
2293 free((char*)cmdedit_prompt);
2294 cmdedit_prompt = ckstrdup(s);
2301 putprompt(const char *s)
2307 #if ENABLE_ASH_EXPAND_PRMT
2308 /* expandstr() needs parsing machinery, so it is far away ahead... */
2309 static const char *expandstr(const char *ps);
2311 #define expandstr(s) s
2315 setprompt(int whichprompt)
2318 #if ENABLE_ASH_EXPAND_PRMT
2319 struct stackmark smark;
2324 switch (whichprompt) {
2334 #if ENABLE_ASH_EXPAND_PRMT
2335 setstackmark(&smark);
2336 stalloc(stackblocksize());
2338 putprompt(expandstr(prompt));
2339 #if ENABLE_ASH_EXPAND_PRMT
2340 popstackmark(&smark);
2345 /* ============ The cd and pwd commands */
2347 #define CD_PHYSICAL 1
2350 static int docd(const char *, int);
2359 while ((i = nextopt("LP"))) {
2361 flags ^= CD_PHYSICAL;
2370 * Update curdir (the name of the current directory) in response to a
2374 updatepwd(const char *dir)
2381 cdcomppath = ststrdup(dir);
2384 if (curdir == nullstr)
2386 new = stack_putstr(curdir, new);
2388 new = makestrspace(strlen(dir) + 2, new);
2389 lim = (char *)stackblock() + 1;
2393 if (new > lim && *lim == '/')
2398 if (dir[1] == '/' && dir[2] != '/') {
2404 p = strtok(cdcomppath, "/");
2408 if (p[1] == '.' && p[2] == '\0') {
2420 new = stack_putstr(p, new);
2428 return stackblock();
2432 * Find out what the current directory is. If we already know the current
2433 * directory, this routine returns immediately.
2438 char *dir = getcwd(NULL, 0); /* huh, using glibc extension? */
2439 return dir ? dir : nullstr;
2443 setpwd(const char *val, int setold)
2447 oldcur = dir = curdir;
2450 setvar("OLDPWD", oldcur, VEXPORT);
2453 if (physdir != nullstr) {
2454 if (physdir != oldcur)
2458 if (oldcur == val || !val) {
2464 dir = ckstrdup(val);
2465 if (oldcur != dir && oldcur != nullstr) {
2470 setvar("PWD", dir, VEXPORT);
2473 static void hashcd(void);
2476 * Actually do the chdir. We also call hashcd to let the routines in exec.c
2477 * know that the current directory has changed.
2480 docd(const char *dest, int flags)
2482 const char *dir = 0;
2485 TRACE(("docd(\"%s\", %d) called\n", dest, flags));
2488 if (!(flags & CD_PHYSICAL)) {
2489 dir = updatepwd(dest);
2504 cdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
2516 dest = bltinlookup(homestr);
2517 else if (LONE_DASH(dest)) {
2518 dest = bltinlookup("OLDPWD");
2540 path = bltinlookup("CDPATH");
2549 p = padvance(&path, dest);
2550 if (stat(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) {
2554 if (!docd(p, flags))
2559 ash_msg_and_raise_error("can't cd to %s", dest);
2562 if (flags & CD_PRINT)
2563 out1fmt(snlfmt, curdir);
2568 pwdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
2571 const char *dir = curdir;
2575 if (physdir == nullstr)
2579 out1fmt(snlfmt, dir);
2584 /* ============ ... */
2587 #define IBUFSIZ COMMON_BUFSIZE
2588 /* buffer for top level input file */
2589 #define basebuf bb_common_bufsiz1
2591 /* Syntax classes */
2592 #define CWORD 0 /* character is nothing special */
2593 #define CNL 1 /* newline character */
2594 #define CBACK 2 /* a backslash character */
2595 #define CSQUOTE 3 /* single quote */
2596 #define CDQUOTE 4 /* double quote */
2597 #define CENDQUOTE 5 /* a terminating quote */
2598 #define CBQUOTE 6 /* backwards single quote */
2599 #define CVAR 7 /* a dollar sign */
2600 #define CENDVAR 8 /* a '}' character */
2601 #define CLP 9 /* a left paren in arithmetic */
2602 #define CRP 10 /* a right paren in arithmetic */
2603 #define CENDFILE 11 /* end of file */
2604 #define CCTL 12 /* like CWORD, except it must be escaped */
2605 #define CSPCL 13 /* these terminate a word */
2606 #define CIGN 14 /* character should be ignored */
2608 #if ENABLE_ASH_ALIAS
2612 #define PEOA_OR_PEOF PEOA
2616 #define PEOA_OR_PEOF PEOF
2619 /* number syntax index */
2620 #define BASESYNTAX 0 /* not in quotes */
2621 #define DQSYNTAX 1 /* in double quotes */
2622 #define SQSYNTAX 2 /* in single quotes */
2623 #define ARISYNTAX 3 /* in arithmetic */
2624 #define PSSYNTAX 4 /* prompt */
2626 #if ENABLE_ASH_OPTIMIZE_FOR_SIZE
2627 #define USE_SIT_FUNCTION
2630 #if ENABLE_ASH_MATH_SUPPORT
2631 static const char S_I_T[][4] = {
2632 #if ENABLE_ASH_ALIAS
2633 { CSPCL, CIGN, CIGN, CIGN }, /* 0, PEOA */
2635 { CSPCL, CWORD, CWORD, CWORD }, /* 1, ' ' */
2636 { CNL, CNL, CNL, CNL }, /* 2, \n */
2637 { CWORD, CCTL, CCTL, CWORD }, /* 3, !*-/:=?[]~ */
2638 { CDQUOTE, CENDQUOTE, CWORD, CWORD }, /* 4, '"' */
2639 { CVAR, CVAR, CWORD, CVAR }, /* 5, $ */
2640 { CSQUOTE, CWORD, CENDQUOTE, CWORD }, /* 6, "'" */
2641 { CSPCL, CWORD, CWORD, CLP }, /* 7, ( */
2642 { CSPCL, CWORD, CWORD, CRP }, /* 8, ) */
2643 { CBACK, CBACK, CCTL, CBACK }, /* 9, \ */
2644 { CBQUOTE, CBQUOTE, CWORD, CBQUOTE }, /* 10, ` */
2645 { CENDVAR, CENDVAR, CWORD, CENDVAR }, /* 11, } */
2646 #ifndef USE_SIT_FUNCTION
2647 { CENDFILE, CENDFILE, CENDFILE, CENDFILE }, /* 12, PEOF */
2648 { CWORD, CWORD, CWORD, CWORD }, /* 13, 0-9A-Za-z */
2649 { CCTL, CCTL, CCTL, CCTL } /* 14, CTLESC ... */
2653 static const char S_I_T[][3] = {
2654 #if ENABLE_ASH_ALIAS
2655 { CSPCL, CIGN, CIGN }, /* 0, PEOA */
2657 { CSPCL, CWORD, CWORD }, /* 1, ' ' */
2658 { CNL, CNL, CNL }, /* 2, \n */
2659 { CWORD, CCTL, CCTL }, /* 3, !*-/:=?[]~ */
2660 { CDQUOTE, CENDQUOTE, CWORD }, /* 4, '"' */
2661 { CVAR, CVAR, CWORD }, /* 5, $ */
2662 { CSQUOTE, CWORD, CENDQUOTE }, /* 6, "'" */
2663 { CSPCL, CWORD, CWORD }, /* 7, ( */
2664 { CSPCL, CWORD, CWORD }, /* 8, ) */
2665 { CBACK, CBACK, CCTL }, /* 9, \ */
2666 { CBQUOTE, CBQUOTE, CWORD }, /* 10, ` */
2667 { CENDVAR, CENDVAR, CWORD }, /* 11, } */
2668 #ifndef USE_SIT_FUNCTION
2669 { CENDFILE, CENDFILE, CENDFILE }, /* 12, PEOF */
2670 { CWORD, CWORD, CWORD }, /* 13, 0-9A-Za-z */
2671 { CCTL, CCTL, CCTL } /* 14, CTLESC ... */
2674 #endif /* ASH_MATH_SUPPORT */
2676 #ifdef USE_SIT_FUNCTION
2679 SIT(int c, int syntax)
2681 static const char spec_symbls[] ALIGN1 = "\t\n !\"$&'()*-/:;<=>?[\\]`|}~";
2682 #if ENABLE_ASH_ALIAS
2683 static const char syntax_index_table[] ALIGN1 = {
2684 1, 2, 1, 3, 4, 5, 1, 6, /* "\t\n !\"$&'" */
2685 7, 8, 3, 3, 3, 3, 1, 1, /* "()*-/:;<" */
2686 3, 1, 3, 3, 9, 3, 10, 1, /* "=>?[\\]`|" */
2690 static const char syntax_index_table[] ALIGN1 = {
2691 0, 1, 0, 2, 3, 4, 0, 5, /* "\t\n !\"$&'" */
2692 6, 7, 2, 2, 2, 2, 0, 0, /* "()*-/:;<" */
2693 2, 0, 2, 2, 8, 2, 9, 0, /* "=>?[\\]`|" */
2700 if (c == PEOF) /* 2^8+2 */
2702 #if ENABLE_ASH_ALIAS
2703 if (c == PEOA) /* 2^8+1 */
2708 if ((unsigned char)c >= (unsigned char)(CTLESC)
2709 && (unsigned char)c <= (unsigned char)(CTLQUOTEMARK)
2713 s = strchrnul(spec_symbls, c);
2716 indx = syntax_index_table[s - spec_symbls];
2718 return S_I_T[indx][syntax];
2721 #else /* !USE_SIT_FUNCTION */
2723 #if ENABLE_ASH_ALIAS
2724 #define CSPCL_CIGN_CIGN_CIGN 0
2725 #define CSPCL_CWORD_CWORD_CWORD 1
2726 #define CNL_CNL_CNL_CNL 2
2727 #define CWORD_CCTL_CCTL_CWORD 3
2728 #define CDQUOTE_CENDQUOTE_CWORD_CWORD 4
2729 #define CVAR_CVAR_CWORD_CVAR 5
2730 #define CSQUOTE_CWORD_CENDQUOTE_CWORD 6
2731 #define CSPCL_CWORD_CWORD_CLP 7
2732 #define CSPCL_CWORD_CWORD_CRP 8
2733 #define CBACK_CBACK_CCTL_CBACK 9
2734 #define CBQUOTE_CBQUOTE_CWORD_CBQUOTE 10
2735 #define CENDVAR_CENDVAR_CWORD_CENDVAR 11
2736 #define CENDFILE_CENDFILE_CENDFILE_CENDFILE 12
2737 #define CWORD_CWORD_CWORD_CWORD 13
2738 #define CCTL_CCTL_CCTL_CCTL 14
2740 #define CSPCL_CWORD_CWORD_CWORD 0
2741 #define CNL_CNL_CNL_CNL 1
2742 #define CWORD_CCTL_CCTL_CWORD 2
2743 #define CDQUOTE_CENDQUOTE_CWORD_CWORD 3
2744 #define CVAR_CVAR_CWORD_CVAR 4
2745 #define CSQUOTE_CWORD_CENDQUOTE_CWORD 5
2746 #define CSPCL_CWORD_CWORD_CLP 6
2747 #define CSPCL_CWORD_CWORD_CRP 7
2748 #define CBACK_CBACK_CCTL_CBACK 8
2749 #define CBQUOTE_CBQUOTE_CWORD_CBQUOTE 9
2750 #define CENDVAR_CENDVAR_CWORD_CENDVAR 10
2751 #define CENDFILE_CENDFILE_CENDFILE_CENDFILE 11
2752 #define CWORD_CWORD_CWORD_CWORD 12
2753 #define CCTL_CCTL_CCTL_CCTL 13
2756 static const char syntax_index_table[258] = {
2757 /* BASESYNTAX_DQSYNTAX_SQSYNTAX_ARISYNTAX */
2758 /* 0 PEOF */ CENDFILE_CENDFILE_CENDFILE_CENDFILE,
2759 #if ENABLE_ASH_ALIAS
2760 /* 1 PEOA */ CSPCL_CIGN_CIGN_CIGN,
2762 /* 2 -128 0x80 */ CWORD_CWORD_CWORD_CWORD,
2763 /* 3 -127 CTLESC */ CCTL_CCTL_CCTL_CCTL,
2764 /* 4 -126 CTLVAR */ CCTL_CCTL_CCTL_CCTL,
2765 /* 5 -125 CTLENDVAR */ CCTL_CCTL_CCTL_CCTL,
2766 /* 6 -124 CTLBACKQ */ CCTL_CCTL_CCTL_CCTL,
2767 /* 7 -123 CTLQUOTE */ CCTL_CCTL_CCTL_CCTL,
2768 /* 8 -122 CTLARI */ CCTL_CCTL_CCTL_CCTL,
2769 /* 9 -121 CTLENDARI */ CCTL_CCTL_CCTL_CCTL,
2770 /* 10 -120 CTLQUOTEMARK */ CCTL_CCTL_CCTL_CCTL,
2771 /* 11 -119 */ CWORD_CWORD_CWORD_CWORD,
2772 /* 12 -118 */ CWORD_CWORD_CWORD_CWORD,
2773 /* 13 -117 */ CWORD_CWORD_CWORD_CWORD,
2774 /* 14 -116 */ CWORD_CWORD_CWORD_CWORD,
2775 /* 15 -115 */ CWORD_CWORD_CWORD_CWORD,
2776 /* 16 -114 */ CWORD_CWORD_CWORD_CWORD,
2777 /* 17 -113 */ CWORD_CWORD_CWORD_CWORD,
2778 /* 18 -112 */ CWORD_CWORD_CWORD_CWORD,
2779 /* 19 -111 */ CWORD_CWORD_CWORD_CWORD,
2780 /* 20 -110 */ CWORD_CWORD_CWORD_CWORD,
2781 /* 21 -109 */ CWORD_CWORD_CWORD_CWORD,
2782 /* 22 -108 */ CWORD_CWORD_CWORD_CWORD,
2783 /* 23 -107 */ CWORD_CWORD_CWORD_CWORD,
2784 /* 24 -106 */ CWORD_CWORD_CWORD_CWORD,
2785 /* 25 -105 */ CWORD_CWORD_CWORD_CWORD,
2786 /* 26 -104 */ CWORD_CWORD_CWORD_CWORD,
2787 /* 27 -103 */ CWORD_CWORD_CWORD_CWORD,
2788 /* 28 -102 */ CWORD_CWORD_CWORD_CWORD,
2789 /* 29 -101 */ CWORD_CWORD_CWORD_CWORD,
2790 /* 30 -100 */ CWORD_CWORD_CWORD_CWORD,
2791 /* 31 -99 */ CWORD_CWORD_CWORD_CWORD,
2792 /* 32 -98 */ CWORD_CWORD_CWORD_CWORD,
2793 /* 33 -97 */ CWORD_CWORD_CWORD_CWORD,
2794 /* 34 -96 */ CWORD_CWORD_CWORD_CWORD,
2795 /* 35 -95 */ CWORD_CWORD_CWORD_CWORD,
2796 /* 36 -94 */ CWORD_CWORD_CWORD_CWORD,
2797 /* 37 -93 */ CWORD_CWORD_CWORD_CWORD,
2798 /* 38 -92 */ CWORD_CWORD_CWORD_CWORD,
2799 /* 39 -91 */ CWORD_CWORD_CWORD_CWORD,
2800 /* 40 -90 */ CWORD_CWORD_CWORD_CWORD,
2801 /* 41 -89 */ CWORD_CWORD_CWORD_CWORD,
2802 /* 42 -88 */ CWORD_CWORD_CWORD_CWORD,
2803 /* 43 -87 */ CWORD_CWORD_CWORD_CWORD,
2804 /* 44 -86 */ CWORD_CWORD_CWORD_CWORD,
2805 /* 45 -85 */ CWORD_CWORD_CWORD_CWORD,
2806 /* 46 -84 */ CWORD_CWORD_CWORD_CWORD,
2807 /* 47 -83 */ CWORD_CWORD_CWORD_CWORD,
2808 /* 48 -82 */ CWORD_CWORD_CWORD_CWORD,
2809 /* 49 -81 */ CWORD_CWORD_CWORD_CWORD,
2810 /* 50 -80 */ CWORD_CWORD_CWORD_CWORD,
2811 /* 51 -79 */ CWORD_CWORD_CWORD_CWORD,
2812 /* 52 -78 */ CWORD_CWORD_CWORD_CWORD,
2813 /* 53 -77 */ CWORD_CWORD_CWORD_CWORD,
2814 /* 54 -76 */ CWORD_CWORD_CWORD_CWORD,
2815 /* 55 -75 */ CWORD_CWORD_CWORD_CWORD,
2816 /* 56 -74 */ CWORD_CWORD_CWORD_CWORD,
2817 /* 57 -73 */ CWORD_CWORD_CWORD_CWORD,
2818 /* 58 -72 */ CWORD_CWORD_CWORD_CWORD,
2819 /* 59 -71 */ CWORD_CWORD_CWORD_CWORD,
2820 /* 60 -70 */ CWORD_CWORD_CWORD_CWORD,
2821 /* 61 -69 */ CWORD_CWORD_CWORD_CWORD,
2822 /* 62 -68 */ CWORD_CWORD_CWORD_CWORD,
2823 /* 63 -67 */ CWORD_CWORD_CWORD_CWORD,
2824 /* 64 -66 */ CWORD_CWORD_CWORD_CWORD,
2825 /* 65 -65 */ CWORD_CWORD_CWORD_CWORD,
2826 /* 66 -64 */ CWORD_CWORD_CWORD_CWORD,
2827 /* 67 -63 */ CWORD_CWORD_CWORD_CWORD,
2828 /* 68 -62 */ CWORD_CWORD_CWORD_CWORD,
2829 /* 69 -61 */ CWORD_CWORD_CWORD_CWORD,
2830 /* 70 -60 */ CWORD_CWORD_CWORD_CWORD,
2831 /* 71 -59 */ CWORD_CWORD_CWORD_CWORD,
2832 /* 72 -58 */ CWORD_CWORD_CWORD_CWORD,
2833 /* 73 -57 */ CWORD_CWORD_CWORD_CWORD,
2834 /* 74 -56 */ CWORD_CWORD_CWORD_CWORD,
2835 /* 75 -55 */ CWORD_CWORD_CWORD_CWORD,
2836 /* 76 -54 */ CWORD_CWORD_CWORD_CWORD,
2837 /* 77 -53 */ CWORD_CWORD_CWORD_CWORD,
2838 /* 78 -52 */ CWORD_CWORD_CWORD_CWORD,
2839 /* 79 -51 */ CWORD_CWORD_CWORD_CWORD,
2840 /* 80 -50 */ CWORD_CWORD_CWORD_CWORD,
2841 /* 81 -49 */ CWORD_CWORD_CWORD_CWORD,
2842 /* 82 -48 */ CWORD_CWORD_CWORD_CWORD,
2843 /* 83 -47 */ CWORD_CWORD_CWORD_CWORD,
2844 /* 84 -46 */ CWORD_CWORD_CWORD_CWORD,
2845 /* 85 -45 */ CWORD_CWORD_CWORD_CWORD,
2846 /* 86 -44 */ CWORD_CWORD_CWORD_CWORD,
2847 /* 87 -43 */ CWORD_CWORD_CWORD_CWORD,
2848 /* 88 -42 */ CWORD_CWORD_CWORD_CWORD,
2849 /* 89 -41 */ CWORD_CWORD_CWORD_CWORD,
2850 /* 90 -40 */ CWORD_CWORD_CWORD_CWORD,
2851 /* 91 -39 */ CWORD_CWORD_CWORD_CWORD,
2852 /* 92 -38 */ CWORD_CWORD_CWORD_CWORD,
2853 /* 93 -37 */ CWORD_CWORD_CWORD_CWORD,
2854 /* 94 -36 */ CWORD_CWORD_CWORD_CWORD,
2855 /* 95 -35 */ CWORD_CWORD_CWORD_CWORD,
2856 /* 96 -34 */ CWORD_CWORD_CWORD_CWORD,
2857 /* 97 -33 */ CWORD_CWORD_CWORD_CWORD,
2858 /* 98 -32 */ CWORD_CWORD_CWORD_CWORD,
2859 /* 99 -31 */ CWORD_CWORD_CWORD_CWORD,
2860 /* 100 -30 */ CWORD_CWORD_CWORD_CWORD,
2861 /* 101 -29 */ CWORD_CWORD_CWORD_CWORD,
2862 /* 102 -28 */ CWORD_CWORD_CWORD_CWORD,
2863 /* 103 -27 */ CWORD_CWORD_CWORD_CWORD,
2864 /* 104 -26 */ CWORD_CWORD_CWORD_CWORD,
2865 /* 105 -25 */ CWORD_CWORD_CWORD_CWORD,
2866 /* 106 -24 */ CWORD_CWORD_CWORD_CWORD,
2867 /* 107 -23 */ CWORD_CWORD_CWORD_CWORD,
2868 /* 108 -22 */ CWORD_CWORD_CWORD_CWORD,
2869 /* 109 -21 */ CWORD_CWORD_CWORD_CWORD,
2870 /* 110 -20 */ CWORD_CWORD_CWORD_CWORD,
2871 /* 111 -19 */ CWORD_CWORD_CWORD_CWORD,
2872 /* 112 -18 */ CWORD_CWORD_CWORD_CWORD,
2873 /* 113 -17 */ CWORD_CWORD_CWORD_CWORD,
2874 /* 114 -16 */ CWORD_CWORD_CWORD_CWORD,
2875 /* 115 -15 */ CWORD_CWORD_CWORD_CWORD,
2876 /* 116 -14 */ CWORD_CWORD_CWORD_CWORD,
2877 /* 117 -13 */ CWORD_CWORD_CWORD_CWORD,
2878 /* 118 -12 */ CWORD_CWORD_CWORD_CWORD,
2879 /* 119 -11 */ CWORD_CWORD_CWORD_CWORD,
2880 /* 120 -10 */ CWORD_CWORD_CWORD_CWORD,
2881 /* 121 -9 */ CWORD_CWORD_CWORD_CWORD,
2882 /* 122 -8 */ CWORD_CWORD_CWORD_CWORD,
2883 /* 123 -7 */ CWORD_CWORD_CWORD_CWORD,
2884 /* 124 -6 */ CWORD_CWORD_CWORD_CWORD,
2885 /* 125 -5 */ CWORD_CWORD_CWORD_CWORD,
2886 /* 126 -4 */ CWORD_CWORD_CWORD_CWORD,
2887 /* 127 -3 */ CWORD_CWORD_CWORD_CWORD,
2888 /* 128 -2 */ CWORD_CWORD_CWORD_CWORD,
2889 /* 129 -1 */ CWORD_CWORD_CWORD_CWORD,
2890 /* 130 0 */ CWORD_CWORD_CWORD_CWORD,
2891 /* 131 1 */ CWORD_CWORD_CWORD_CWORD,
2892 /* 132 2 */ CWORD_CWORD_CWORD_CWORD,
2893 /* 133 3 */ CWORD_CWORD_CWORD_CWORD,
2894 /* 134 4 */ CWORD_CWORD_CWORD_CWORD,
2895 /* 135 5 */ CWORD_CWORD_CWORD_CWORD,
2896 /* 136 6 */ CWORD_CWORD_CWORD_CWORD,
2897 /* 137 7 */ CWORD_CWORD_CWORD_CWORD,
2898 /* 138 8 */ CWORD_CWORD_CWORD_CWORD,
2899 /* 139 9 "\t" */ CSPCL_CWORD_CWORD_CWORD,
2900 /* 140 10 "\n" */ CNL_CNL_CNL_CNL,
2901 /* 141 11 */ CWORD_CWORD_CWORD_CWORD,
2902 /* 142 12 */ CWORD_CWORD_CWORD_CWORD,
2903 /* 143 13 */ CWORD_CWORD_CWORD_CWORD,
2904 /* 144 14 */ CWORD_CWORD_CWORD_CWORD,
2905 /* 145 15 */ CWORD_CWORD_CWORD_CWORD,
2906 /* 146 16 */ CWORD_CWORD_CWORD_CWORD,
2907 /* 147 17 */ CWORD_CWORD_CWORD_CWORD,
2908 /* 148 18 */ CWORD_CWORD_CWORD_CWORD,
2909 /* 149 19 */ CWORD_CWORD_CWORD_CWORD,
2910 /* 150 20 */ CWORD_CWORD_CWORD_CWORD,
2911 /* 151 21 */ CWORD_CWORD_CWORD_CWORD,
2912 /* 152 22 */ CWORD_CWORD_CWORD_CWORD,
2913 /* 153 23 */ CWORD_CWORD_CWORD_CWORD,
2914 /* 154 24 */ CWORD_CWORD_CWORD_CWORD,
2915 /* 155 25 */ CWORD_CWORD_CWORD_CWORD,
2916 /* 156 26 */ CWORD_CWORD_CWORD_CWORD,
2917 /* 157 27 */ CWORD_CWORD_CWORD_CWORD,
2918 /* 158 28 */ CWORD_CWORD_CWORD_CWORD,
2919 /* 159 29 */ CWORD_CWORD_CWORD_CWORD,
2920 /* 160 30 */ CWORD_CWORD_CWORD_CWORD,
2921 /* 161 31 */ CWORD_CWORD_CWORD_CWORD,
2922 /* 162 32 " " */ CSPCL_CWORD_CWORD_CWORD,
2923 /* 163 33 "!" */ CWORD_CCTL_CCTL_CWORD,
2924 /* 164 34 """ */ CDQUOTE_CENDQUOTE_CWORD_CWORD,
2925 /* 165 35 "#" */ CWORD_CWORD_CWORD_CWORD,
2926 /* 166 36 "$" */ CVAR_CVAR_CWORD_CVAR,
2927 /* 167 37 "%" */ CWORD_CWORD_CWORD_CWORD,
2928 /* 168 38 "&" */ CSPCL_CWORD_CWORD_CWORD,
2929 /* 169 39 "'" */ CSQUOTE_CWORD_CENDQUOTE_CWORD,
2930 /* 170 40 "(" */ CSPCL_CWORD_CWORD_CLP,
2931 /* 171 41 ")" */ CSPCL_CWORD_CWORD_CRP,
2932 /* 172 42 "*" */ CWORD_CCTL_CCTL_CWORD,
2933 /* 173 43 "+" */ CWORD_CWORD_CWORD_CWORD,
2934 /* 174 44 "," */ CWORD_CWORD_CWORD_CWORD,
2935 /* 175 45 "-" */ CWORD_CCTL_CCTL_CWORD,
2936 /* 176 46 "." */ CWORD_CWORD_CWORD_CWORD,
2937 /* 177 47 "/" */ CWORD_CCTL_CCTL_CWORD,
2938 /* 178 48 "0" */ CWORD_CWORD_CWORD_CWORD,
2939 /* 179 49 "1" */ CWORD_CWORD_CWORD_CWORD,
2940 /* 180 50 "2" */ CWORD_CWORD_CWORD_CWORD,
2941 /* 181 51 "3" */ CWORD_CWORD_CWORD_CWORD,
2942 /* 182 52 "4" */ CWORD_CWORD_CWORD_CWORD,
2943 /* 183 53 "5" */ CWORD_CWORD_CWORD_CWORD,
2944 /* 184 54 "6" */ CWORD_CWORD_CWORD_CWORD,
2945 /* 185 55 "7" */ CWORD_CWORD_CWORD_CWORD,
2946 /* 186 56 "8" */ CWORD_CWORD_CWORD_CWORD,
2947 /* 187 57 "9" */ CWORD_CWORD_CWORD_CWORD,
2948 /* 188 58 ":" */ CWORD_CCTL_CCTL_CWORD,
2949 /* 189 59 ";" */ CSPCL_CWORD_CWORD_CWORD,
2950 /* 190 60 "<" */ CSPCL_CWORD_CWORD_CWORD,
2951 /* 191 61 "=" */ CWORD_CCTL_CCTL_CWORD,
2952 /* 192 62 ">" */ CSPCL_CWORD_CWORD_CWORD,
2953 /* 193 63 "?" */ CWORD_CCTL_CCTL_CWORD,
2954 /* 194 64 "@" */ CWORD_CWORD_CWORD_CWORD,
2955 /* 195 65 "A" */ CWORD_CWORD_CWORD_CWORD,
2956 /* 196 66 "B" */ CWORD_CWORD_CWORD_CWORD,
2957 /* 197 67 "C" */ CWORD_CWORD_CWORD_CWORD,
2958 /* 198 68 "D" */ CWORD_CWORD_CWORD_CWORD,
2959 /* 199 69 "E" */ CWORD_CWORD_CWORD_CWORD,
2960 /* 200 70 "F" */ CWORD_CWORD_CWORD_CWORD,
2961 /* 201 71 "G" */ CWORD_CWORD_CWORD_CWORD,
2962 /* 202 72 "H" */ CWORD_CWORD_CWORD_CWORD,
2963 /* 203 73 "I" */ CWORD_CWORD_CWORD_CWORD,
2964 /* 204 74 "J" */ CWORD_CWORD_CWORD_CWORD,
2965 /* 205 75 "K" */ CWORD_CWORD_CWORD_CWORD,
2966 /* 206 76 "L" */ CWORD_CWORD_CWORD_CWORD,
2967 /* 207 77 "M" */ CWORD_CWORD_CWORD_CWORD,
2968 /* 208 78 "N" */ CWORD_CWORD_CWORD_CWORD,
2969 /* 209 79 "O" */ CWORD_CWORD_CWORD_CWORD,
2970 /* 210 80 "P" */ CWORD_CWORD_CWORD_CWORD,
2971 /* 211 81 "Q" */ CWORD_CWORD_CWORD_CWORD,
2972 /* 212 82 "R" */ CWORD_CWORD_CWORD_CWORD,
2973 /* 213 83 "S" */ CWORD_CWORD_CWORD_CWORD,
2974 /* 214 84 "T" */ CWORD_CWORD_CWORD_CWORD,
2975 /* 215 85 "U" */ CWORD_CWORD_CWORD_CWORD,
2976 /* 216 86 "V" */ CWORD_CWORD_CWORD_CWORD,
2977 /* 217 87 "W" */ CWORD_CWORD_CWORD_CWORD,
2978 /* 218 88 "X" */ CWORD_CWORD_CWORD_CWORD,
2979 /* 219 89 "Y" */ CWORD_CWORD_CWORD_CWORD,
2980 /* 220 90 "Z" */ CWORD_CWORD_CWORD_CWORD,
2981 /* 221 91 "[" */ CWORD_CCTL_CCTL_CWORD,
2982 /* 222 92 "\" */ CBACK_CBACK_CCTL_CBACK,
2983 /* 223 93 "]" */ CWORD_CCTL_CCTL_CWORD,
2984 /* 224 94 "^" */ CWORD_CWORD_CWORD_CWORD,
2985 /* 225 95 "_" */ CWORD_CWORD_CWORD_CWORD,
2986 /* 226 96 "`" */ CBQUOTE_CBQUOTE_CWORD_CBQUOTE,
2987 /* 227 97 "a" */ CWORD_CWORD_CWORD_CWORD,
2988 /* 228 98 "b" */ CWORD_CWORD_CWORD_CWORD,
2989 /* 229 99 "c" */ CWORD_CWORD_CWORD_CWORD,
2990 /* 230 100 "d" */ CWORD_CWORD_CWORD_CWORD,
2991 /* 231 101 "e" */ CWORD_CWORD_CWORD_CWORD,
2992 /* 232 102 "f" */ CWORD_CWORD_CWORD_CWORD,
2993 /* 233 103 "g" */ CWORD_CWORD_CWORD_CWORD,
2994 /* 234 104 "h" */ CWORD_CWORD_CWORD_CWORD,
2995 /* 235 105 "i" */ CWORD_CWORD_CWORD_CWORD,
2996 /* 236 106 "j" */ CWORD_CWORD_CWORD_CWORD,
2997 /* 237 107 "k" */ CWORD_CWORD_CWORD_CWORD,
2998 /* 238 108 "l" */ CWORD_CWORD_CWORD_CWORD,
2999 /* 239 109 "m" */ CWORD_CWORD_CWORD_CWORD,
3000 /* 240 110 "n" */ CWORD_CWORD_CWORD_CWORD,
3001 /* 241 111 "o" */ CWORD_CWORD_CWORD_CWORD,
3002 /* 242 112 "p" */ CWORD_CWORD_CWORD_CWORD,
3003 /* 243 113 "q" */ CWORD_CWORD_CWORD_CWORD,
3004 /* 244 114 "r" */ CWORD_CWORD_CWORD_CWORD,
3005 /* 245 115 "s" */ CWORD_CWORD_CWORD_CWORD,
3006 /* 246 116 "t" */ CWORD_CWORD_CWORD_CWORD,
3007 /* 247 117 "u" */ CWORD_CWORD_CWORD_CWORD,
3008 /* 248 118 "v" */ CWORD_CWORD_CWORD_CWORD,
3009 /* 249 119 "w" */ CWORD_CWORD_CWORD_CWORD,
3010 /* 250 120 "x" */ CWORD_CWORD_CWORD_CWORD,
3011 /* 251 121 "y" */ CWORD_CWORD_CWORD_CWORD,
3012 /* 252 122 "z" */ CWORD_CWORD_CWORD_CWORD,
3013 /* 253 123 "{" */ CWORD_CWORD_CWORD_CWORD,
3014 /* 254 124 "|" */ CSPCL_CWORD_CWORD_CWORD,
3015 /* 255 125 "}" */ CENDVAR_CENDVAR_CWORD_CENDVAR,
3016 /* 256 126 "~" */ CWORD_CCTL_CCTL_CWORD,
3017 /* 257 127 */ CWORD_CWORD_CWORD_CWORD,
3020 #define SIT(c, syntax) (S_I_T[(int)syntax_index_table[((int)c)+SYNBASE]][syntax])
3022 #endif /* USE_SIT_FUNCTION */
3025 /* ============ Alias handling */
3027 #if ENABLE_ASH_ALIAS
3029 #define ALIASINUSE 1
3040 static struct alias **atab; // [ATABSIZE];
3041 #define INIT_G_alias() do { \
3042 atab = xzalloc(ATABSIZE * sizeof(atab[0])); \
3046 static struct alias **
3047 __lookupalias(const char *name) {
3048 unsigned int hashval;
3055 ch = (unsigned char)*p;
3059 ch = (unsigned char)*++p;
3061 app = &atab[hashval % ATABSIZE];
3063 for (; *app; app = &(*app)->next) {
3064 if (strcmp(name, (*app)->name) == 0) {
3072 static struct alias *
3073 lookupalias(const char *name, int check)
3075 struct alias *ap = *__lookupalias(name);
3077 if (check && ap && (ap->flag & ALIASINUSE))
3082 static struct alias *
3083 freealias(struct alias *ap)
3087 if (ap->flag & ALIASINUSE) {
3088 ap->flag |= ALIASDEAD;
3100 setalias(const char *name, const char *val)
3102 struct alias *ap, **app;
3104 app = __lookupalias(name);
3108 if (!(ap->flag & ALIASINUSE)) {
3111 ap->val = ckstrdup(val);
3112 ap->flag &= ~ALIASDEAD;
3115 ap = ckzalloc(sizeof(struct alias));
3116 ap->name = ckstrdup(name);
3117 ap->val = ckstrdup(val);
3118 /*ap->flag = 0; - ckzalloc did it */
3119 /*ap->next = NULL;*/
3126 unalias(const char *name)
3130 app = __lookupalias(name);
3134 *app = freealias(*app);
3145 struct alias *ap, **app;
3149 for (i = 0; i < ATABSIZE; i++) {
3151 for (ap = *app; ap; ap = *app) {
3152 *app = freealias(*app);
3162 printalias(const struct alias *ap)
3164 out1fmt("%s=%s\n", ap->name, single_quote(ap->val));
3168 * TODO - sort output
3171 aliascmd(int argc UNUSED_PARAM, char **argv)
3180 for (i = 0; i < ATABSIZE; i++) {
3181 for (ap = atab[i]; ap; ap = ap->next) {
3187 while ((n = *++argv) != NULL) {
3188 v = strchr(n+1, '=');
3189 if (v == NULL) { /* n+1: funny ksh stuff */
3190 ap = *__lookupalias(n);
3192 fprintf(stderr, "%s: %s not found\n", "alias", n);
3206 unaliascmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
3210 while ((i = nextopt("a")) != '\0') {
3216 for (i = 0; *argptr; argptr++) {
3217 if (unalias(*argptr)) {
3218 fprintf(stderr, "%s: %s not found\n", "unalias", *argptr);
3226 #endif /* ASH_ALIAS */
3229 /* ============ jobs.c */
3231 /* Mode argument to forkshell. Don't change FORK_FG or FORK_BG. */
3234 #define FORK_NOJOB 2
3236 /* mode flags for showjob(s) */
3237 #define SHOW_PGID 0x01 /* only show pgid - for jobs -p */
3238 #define SHOW_PID 0x04 /* include process pid */
3239 #define SHOW_CHANGED 0x08 /* only jobs whose state has changed */
3242 * A job structure contains information about a job. A job is either a
3243 * single process or a set of processes contained in a pipeline. In the
3244 * latter case, pidlist will be non-NULL, and will point to a -1 terminated
3249 pid_t pid; /* process id */
3250 int status; /* last process status from wait() */
3251 char *cmd; /* text of command being run */
3255 struct procstat ps0; /* status of process */
3256 struct procstat *ps; /* status or processes when more than one */
3258 int stopstatus; /* status of a stopped job */
3261 nprocs: 16, /* number of processes */
3263 #define JOBRUNNING 0 /* at least one proc running */
3264 #define JOBSTOPPED 1 /* all procs are stopped */
3265 #define JOBDONE 2 /* all procs are completed */
3267 sigint: 1, /* job was killed by SIGINT */
3268 jobctl: 1, /* job running under job control */
3270 waited: 1, /* true if this entry has been waited for */
3271 used: 1, /* true if this entry is in used */
3272 changed: 1; /* true if status has changed */
3273 struct job *prev_job; /* previous job */
3276 static struct job *makejob(/*union node *,*/ int);
3278 #define forkshell(job, node, mode) forkshell(job, mode)
3280 static int forkshell(struct job *, union node *, int);
3281 static int waitforjob(struct job *);
3284 enum { doing_jobctl = 0 };
3285 #define setjobctl(on) do {} while (0)
3287 static smallint doing_jobctl; //references:8
3288 static void setjobctl(int);
3292 * Set the signal handler for the specified signal. The routine figures
3293 * out what it should be set to.
3296 setsignal(int signo)
3300 struct sigaction act;
3306 else if (*t != '\0')
3308 if (rootshell && action == S_DFL) {
3311 if (iflag || minusc || sflag == 0)
3334 t = &sigmode[signo - 1];
3338 * current setting unknown
3340 if (sigaction(signo, NULL, &act) == -1) {
3342 * Pretend it worked; maybe we should give a warning
3343 * here, but other shells don't. We don't alter
3344 * sigmode, so that we retry every time.
3348 tsig = S_RESET; /* force to be set */
3349 if (act.sa_handler == SIG_IGN) {
3352 && (signo == SIGTSTP || signo == SIGTTIN || signo == SIGTTOU)
3354 tsig = S_IGN; /* don't hard ignore these */
3358 if (tsig == S_HARD_IGN || tsig == action)
3360 act.sa_handler = SIG_DFL;
3363 act.sa_handler = onsig;
3366 act.sa_handler = SIG_IGN;
3371 sigfillset(&act.sa_mask);
3372 sigaction_set(signo, &act);
3375 /* mode flags for set_curjob */
3376 #define CUR_DELETE 2
3377 #define CUR_RUNNING 1
3378 #define CUR_STOPPED 0
3380 /* mode flags for dowait */
3381 #define DOWAIT_NONBLOCK WNOHANG
3382 #define DOWAIT_BLOCK 0
3385 /* pgrp of shell on invocation */
3386 static int initialpgrp; //references:2
3387 static int ttyfd = -1; //5
3390 static struct job *jobtab; //5
3392 static unsigned njobs; //4
3394 static struct job *curjob; //lots
3395 /* number of presumed living untracked jobs */
3396 static int jobless; //4
3399 set_curjob(struct job *jp, unsigned mode)
3402 struct job **jpp, **curp;
3404 /* first remove from list */
3405 jpp = curp = &curjob;
3410 jpp = &jp1->prev_job;
3412 *jpp = jp1->prev_job;
3414 /* Then re-insert in correct position */
3422 /* job being deleted */
3425 /* newly created job or backgrounded job,
3426 put after all stopped jobs. */
3430 if (!jp1 || jp1->state != JOBSTOPPED)
3433 jpp = &jp1->prev_job;
3439 /* newly stopped job - becomes curjob */
3440 jp->prev_job = *jpp;
3448 jobno(const struct job *jp)
3450 return jp - jobtab + 1;
3455 * Convert a job name to a job structure.
3458 #define getjob(name, getctl) getjob(name)
3461 getjob(const char *name, int getctl)
3465 const char *err_msg = "No such job: %s";
3469 char *(*match)(const char *, const char *);
3484 if (c == '+' || c == '%') {
3486 err_msg = "No current job";
3492 err_msg = "No previous job";
3501 // TODO: number() instead? It does error checking...
3504 jp = jobtab + num - 1;
3521 if (match(jp->ps[0].cmd, p)) {
3525 err_msg = "%s: ambiguous";
3532 err_msg = "job %s not created under job control";
3533 if (getctl && jp->jobctl == 0)
3538 ash_msg_and_raise_error(err_msg, name);
3542 * Mark a job structure as unused.
3545 freejob(struct job *jp)
3547 struct procstat *ps;
3551 for (i = jp->nprocs, ps = jp->ps; --i >= 0; ps++) {
3552 if (ps->cmd != nullstr)
3555 if (jp->ps != &jp->ps0)
3558 set_curjob(jp, CUR_DELETE);
3564 xtcsetpgrp(int fd, pid_t pgrp)
3566 if (tcsetpgrp(fd, pgrp))
3567 ash_msg_and_raise_error("can't set tty process group (%m)");
3571 * Turn job control on and off.
3573 * Note: This code assumes that the third arg to ioctl is a character
3574 * pointer, which is true on Berkeley systems but not System V. Since
3575 * System V doesn't have job control yet, this isn't a problem now.
3577 * Called with interrupts off.
3585 if (on == doing_jobctl || rootshell == 0)
3589 ofd = fd = open(_PATH_TTY, O_RDWR);
3591 /* BTW, bash will try to open(ttyname(0)) if open("/dev/tty") fails.
3592 * That sometimes helps to acquire controlling tty.
3593 * Obviously, a workaround for bugs when someone
3594 * failed to provide a controlling tty to bash! :) */
3600 fd = fcntl(fd, F_DUPFD, 10);
3605 /* fd is a tty at this point */
3606 close_on_exec_on(fd);
3607 do { /* while we are in the background */
3608 pgrp = tcgetpgrp(fd);
3611 ash_msg("can't access tty; job control turned off");
3615 if (pgrp == getpgrp())
3626 xtcsetpgrp(fd, pgrp);
3628 /* turning job control off */
3631 /* was xtcsetpgrp, but this can make exiting ash
3632 * loop forever if pty is already deleted */
3633 tcsetpgrp(fd, pgrp);
3648 killcmd(int argc, char **argv)
3651 if (argv[1] && strcmp(argv[1], "-l") != 0) {
3653 if (argv[i][0] == '%') {
3654 struct job *jp = getjob(argv[i], 0);
3655 unsigned pid = jp->ps[0].pid;
3656 /* Enough space for ' -NNN<nul>' */
3657 argv[i] = alloca(sizeof(int)*3 + 3);
3658 /* kill_main has matching code to expect
3659 * leading space. Needed to not confuse
3660 * negative pids with "kill -SIGNAL_NO" syntax */
3661 sprintf(argv[i], " -%u", pid);
3663 } while (argv[++i]);
3665 return kill_main(argc, argv);
3669 showpipe(struct job *jp, FILE *out)
3671 struct procstat *sp;
3672 struct procstat *spend;
3674 spend = jp->ps + jp->nprocs;
3675 for (sp = jp->ps + 1; sp < spend; sp++)
3676 fprintf(out, " | %s", sp->cmd);
3677 outcslow('\n', out);
3678 flush_stdout_stderr();
3683 restartjob(struct job *jp, int mode)
3685 struct procstat *ps;
3691 if (jp->state == JOBDONE)
3693 jp->state = JOBRUNNING;
3695 if (mode == FORK_FG)
3696 xtcsetpgrp(ttyfd, pgid);
3697 killpg(pgid, SIGCONT);
3701 if (WIFSTOPPED(ps->status)) {
3707 status = (mode == FORK_FG) ? waitforjob(jp) : 0;
3713 fg_bgcmd(int argc UNUSED_PARAM, char **argv)
3720 mode = (**argv == 'f') ? FORK_FG : FORK_BG;
3725 jp = getjob(*argv, 1);
3726 if (mode == FORK_BG) {
3727 set_curjob(jp, CUR_RUNNING);
3728 fprintf(out, "[%d] ", jobno(jp));
3730 outstr(jp->ps->cmd, out);
3732 retval = restartjob(jp, mode);
3733 } while (*argv && *++argv);
3739 sprint_status(char *s, int status, int sigonly)
3745 if (!WIFEXITED(status)) {
3747 if (WIFSTOPPED(status))
3748 st = WSTOPSIG(status);
3751 st = WTERMSIG(status);
3753 if (st == SIGINT || st == SIGPIPE)
3756 if (WIFSTOPPED(status))
3761 col = fmtstr(s, 32, strsignal(st));
3762 if (WCOREDUMP(status)) {
3763 col += fmtstr(s + col, 16, " (core dumped)");
3765 } else if (!sigonly) {
3766 st = WEXITSTATUS(status);
3768 col = fmtstr(s, 16, "Done(%d)", st);
3770 col = fmtstr(s, 16, "Done");
3777 dowait(int wait_flags, struct job *job)
3782 struct job *thisjob;
3785 TRACE(("dowait(0x%x) called\n", wait_flags));
3787 /* Do a wait system call. If job control is compiled in, we accept
3788 * stopped processes. wait_flags may have WNOHANG, preventing blocking.
3789 * NB: _not_ safe_waitpid, we need to detect EINTR */
3790 pid = waitpid(-1, &status,
3791 (doing_jobctl ? (wait_flags | WUNTRACED) : wait_flags));
3792 TRACE(("wait returns pid=%d, status=0x%x\n", pid, status));
3795 /* If we were doing blocking wait and (probably) got EINTR,
3796 * check for pending sigs received while waiting.
3797 * (NB: can be moved into callers if needed) */
3798 if (wait_flags == DOWAIT_BLOCK && pendingsig)
3799 raise_exception(EXSIG);
3804 for (jp = curjob; jp; jp = jp->prev_job) {
3805 struct procstat *sp;
3806 struct procstat *spend;
3807 if (jp->state == JOBDONE)
3810 spend = jp->ps + jp->nprocs;
3813 if (sp->pid == pid) {
3814 TRACE(("Job %d: changing status of proc %d "
3815 "from 0x%x to 0x%x\n",
3816 jobno(jp), pid, sp->status, status));
3817 sp->status = status;
3820 if (sp->status == -1)
3823 if (state == JOBRUNNING)
3825 if (WIFSTOPPED(sp->status)) {
3826 jp->stopstatus = sp->status;
3830 } while (++sp < spend);
3835 if (!WIFSTOPPED(status))
3841 if (state != JOBRUNNING) {
3842 thisjob->changed = 1;
3844 if (thisjob->state != state) {
3845 TRACE(("Job %d: changing state from %d to %d\n",
3846 jobno(thisjob), thisjob->state, state));
3847 thisjob->state = state;
3849 if (state == JOBSTOPPED) {
3850 set_curjob(thisjob, CUR_STOPPED);
3859 if (thisjob && thisjob == job) {
3863 len = sprint_status(s, status, 1);
3875 showjob(FILE *out, struct job *jp, int mode)
3877 struct procstat *ps;
3878 struct procstat *psend;
3885 if (mode & SHOW_PGID) {
3886 /* just output process (group) id of pipeline */
3887 fprintf(out, "%d\n", ps->pid);
3891 col = fmtstr(s, 16, "[%d] ", jobno(jp));
3896 else if (curjob && jp == curjob->prev_job)
3899 if (mode & SHOW_PID)
3900 col += fmtstr(s + col, 16, "%d ", ps->pid);
3902 psend = ps + jp->nprocs;
3904 if (jp->state == JOBRUNNING) {
3905 strcpy(s + col, "Running");
3906 col += sizeof("Running") - 1;
3908 int status = psend[-1].status;
3909 if (jp->state == JOBSTOPPED)
3910 status = jp->stopstatus;
3911 col += sprint_status(s + col, status, 0);
3917 /* for each process */
3918 col = fmtstr(s, 48, " |\n%*c%d ", indent_col, ' ', ps->pid) - 3;
3920 fprintf(out, "%s%*c%s",
3921 s, 33 - col >= 0 ? 33 - col : 0, ' ', ps->cmd
3923 if (!(mode & SHOW_PID)) {
3927 if (++ps == psend) {
3928 outcslow('\n', out);
3935 if (jp->state == JOBDONE) {
3936 TRACE(("showjob: freeing job %d\n", jobno(jp)));
3942 * Print a list of jobs. If "change" is nonzero, only print jobs whose
3943 * statuses have changed since the last call to showjobs.
3946 showjobs(FILE *out, int mode)
3950 TRACE(("showjobs(%x) called\n", mode));
3952 /* If not even one job changed, there is nothing to do */
3953 while (dowait(DOWAIT_NONBLOCK, NULL) > 0)
3956 for (jp = curjob; jp; jp = jp->prev_job) {
3957 if (!(mode & SHOW_CHANGED) || jp->changed) {
3958 showjob(out, jp, mode);
3964 jobscmd(int argc UNUSED_PARAM, char **argv)
3969 while ((m = nextopt("lp"))) {
3979 showjob(stdout, getjob(*argv,0), mode);
3982 showjobs(stdout, mode);
3989 getstatus(struct job *job)
3994 status = job->ps[job->nprocs - 1].status;
3995 retval = WEXITSTATUS(status);
3996 if (!WIFEXITED(status)) {
3998 retval = WSTOPSIG(status);
3999 if (!WIFSTOPPED(status))
4002 /* XXX: limits number of signals */
4003 retval = WTERMSIG(status);
4005 if (retval == SIGINT)
4011 TRACE(("getstatus: job %d, nproc %d, status %x, retval %x\n",
4012 jobno(job), job->nprocs, status, retval));
4017 waitcmd(int argc UNUSED_PARAM, char **argv)
4026 raise_exception(EXSIG);
4033 /* wait for all jobs */
4037 if (!jp) /* no running procs */
4039 if (jp->state == JOBRUNNING)
4044 dowait(DOWAIT_BLOCK, NULL);
4050 if (**argv != '%') {
4051 pid_t pid = number(*argv);
4056 if (job->ps[job->nprocs - 1].pid == pid)
4058 job = job->prev_job;
4061 job = getjob(*argv, 0);
4062 /* loop until process terminated or stopped */
4063 while (job->state == JOBRUNNING)
4064 dowait(DOWAIT_BLOCK, NULL);
4066 retval = getstatus(job);
4080 struct job *jp, *jq;
4082 len = njobs * sizeof(*jp);
4084 jp = ckrealloc(jq, len + 4 * sizeof(*jp));
4086 offset = (char *)jp - (char *)jq;
4088 /* Relocate pointers */
4091 jq = (struct job *)((char *)jq + l);
4095 #define joff(p) ((struct job *)((char *)(p) + l))
4096 #define jmove(p) (p) = (void *)((char *)(p) + offset)
4097 if (joff(jp)->ps == &jq->ps0)
4098 jmove(joff(jp)->ps);
4099 if (joff(jp)->prev_job)
4100 jmove(joff(jp)->prev_job);
4110 jp = (struct job *)((char *)jp + len);
4114 } while (--jq >= jp);
4119 * Return a new job structure.
4120 * Called with interrupts off.
4123 makejob(/*union node *node,*/ int nprocs)
4128 for (i = njobs, jp = jobtab; ; jp++) {
4135 if (jp->state != JOBDONE || !jp->waited)
4144 memset(jp, 0, sizeof(*jp));
4146 /* jp->jobctl is a bitfield.
4147 * "jp->jobctl |= jobctl" likely to give awful code */
4151 jp->prev_job = curjob;
4156 jp->ps = ckmalloc(nprocs * sizeof(struct procstat));
4158 TRACE(("makejob(%d) returns %%%d\n", nprocs,
4165 * Return a string identifying a command (to be printed by the
4168 static char *cmdnextc;
4171 cmdputs(const char *s)
4173 static const char vstype[VSTYPE + 1][3] = {
4174 "", "}", "-", "+", "?", "=",
4175 "%", "%%", "#", "##"
4176 USE_ASH_BASH_COMPAT(, ":", "/", "//")
4179 const char *p, *str;
4180 char c, cc[2] = " ";
4185 nextc = makestrspace((strlen(s) + 1) * 8, cmdnextc);
4187 while ((c = *p++) != 0) {
4195 if ((subtype & VSTYPE) == VSLENGTH)
4199 if (!(subtype & VSQUOTE) == !(quoted & 1))
4205 str = "\"}" + !(quoted & 1);
4212 case CTLBACKQ+CTLQUOTE:
4215 #if ENABLE_ASH_MATH_SUPPORT
4230 if ((subtype & VSTYPE) != VSNORMAL)
4232 str = vstype[subtype & VSTYPE];
4233 if (subtype & VSNUL)
4242 /* These can only happen inside quotes */
4255 while ((c = *str++)) {
4260 USTPUTC('"', nextc);
4266 /* cmdtxt() and cmdlist() call each other */
4267 static void cmdtxt(union node *n);
4270 cmdlist(union node *np, int sep)
4272 for (; np; np = np->narg.next) {
4276 if (sep && np->narg.next)
4282 cmdtxt(union node *n)
4285 struct nodelist *lp;
4296 lp = n->npipe.cmdlist;
4314 cmdtxt(n->nbinary.ch1);
4330 cmdtxt(n->nif.test);
4333 if (n->nif.elsepart) {
4336 n = n->nif.elsepart;
4352 cmdtxt(n->nbinary.ch1);
4362 cmdputs(n->nfor.var);
4364 cmdlist(n->nfor.args, 1);
4369 cmdputs(n->narg.text);
4373 cmdlist(n->ncmd.args, 1);
4374 cmdlist(n->ncmd.redirect, 0);
4387 cmdputs(n->ncase.expr->narg.text);
4389 for (np = n->ncase.cases; np; np = np->nclist.next) {
4390 cmdtxt(np->nclist.pattern);
4392 cmdtxt(np->nclist.body);
4406 #if ENABLE_ASH_BASH_COMPAT
4421 cmdputs(utoa(n->nfile.fd));
4423 if (n->type == NTOFD || n->type == NFROMFD) {
4424 cmdputs(utoa(n->ndup.dupfd));
4433 commandtext(union node *n)
4437 STARTSTACKSTR(cmdnextc);
4439 name = stackblock();
4440 TRACE(("commandtext: name %p, end %p\n\t\"%s\"\n",
4441 name, cmdnextc, cmdnextc));
4442 return ckstrdup(name);
4447 * Fork off a subshell. If we are doing job control, give the subshell its
4448 * own process group. Jp is a job structure that the job is to be added to.
4449 * N is the command that will be evaluated by the child. Both jp and n may
4450 * be NULL. The mode parameter can be one of the following:
4451 * FORK_FG - Fork off a foreground process.
4452 * FORK_BG - Fork off a background process.
4453 * FORK_NOJOB - Like FORK_FG, but don't give the process its own
4454 * process group even if job control is on.
4456 * When job control is turned off, background processes have their standard
4457 * input redirected to /dev/null (except for the second and later processes
4460 * Called with interrupts off.
4463 * Clear traps on a fork.
4470 for (tp = trap; tp < &trap[NSIG]; tp++) {
4471 if (*tp && **tp) { /* trap not NULL or "" (SIG_IGN) */
4476 setsignal(tp - trap);
4482 /* Lives far away from here, needed for forkchild */
4483 static void closescript(void);
4485 /* Called after fork(), in child */
4487 forkchild(struct job *jp, /*union node *n,*/ int mode)
4491 TRACE(("Child shell %d\n", getpid()));
4498 /* do job control only in root shell */
4500 if (mode != FORK_NOJOB && jp->jobctl && !oldlvl) {
4503 if (jp->nprocs == 0)
4506 pgrp = jp->ps[0].pid;
4507 /* This can fail because we are doing it in the parent also */
4508 (void)setpgid(0, pgrp);
4509 if (mode == FORK_FG)
4510 xtcsetpgrp(ttyfd, pgrp);
4515 if (mode == FORK_BG) {
4518 if (jp->nprocs == 0) {
4520 if (open(bb_dev_null, O_RDONLY) != 0)
4521 ash_msg_and_raise_error("can't open %s", bb_dev_null);
4524 if (!oldlvl && iflag) {
4529 for (jp = curjob; jp; jp = jp->prev_job)
4534 /* Called after fork(), in parent */
4536 #define forkparent(jp, n, mode, pid) forkparent(jp, mode, pid)
4539 forkparent(struct job *jp, union node *n, int mode, pid_t pid)
4541 TRACE(("In parent shell: child = %d\n", pid));
4543 while (jobless && dowait(DOWAIT_NONBLOCK, NULL) > 0)
4549 if (mode != FORK_NOJOB && jp->jobctl) {
4552 if (jp->nprocs == 0)
4555 pgrp = jp->ps[0].pid;
4556 /* This can fail because we are doing it in the child also */
4560 if (mode == FORK_BG) {
4561 backgndpid = pid; /* set $! */
4562 set_curjob(jp, CUR_RUNNING);
4565 struct procstat *ps = &jp->ps[jp->nprocs++];
4570 if (doing_jobctl && n)
4571 ps->cmd = commandtext(n);
4577 forkshell(struct job *jp, union node *n, int mode)
4581 TRACE(("forkshell(%%%d, %p, %d) called\n", jobno(jp), n, mode));
4584 TRACE(("Fork failed, errno=%d", errno));
4587 ash_msg_and_raise_error("can't fork");
4590 forkchild(jp, /*n,*/ mode);
4592 forkparent(jp, n, mode, pid);
4597 * Wait for job to finish.
4599 * Under job control we have the problem that while a child process is
4600 * running interrupts generated by the user are sent to the child but not
4601 * to the shell. This means that an infinite loop started by an inter-
4602 * active user may be hard to kill. With job control turned off, an
4603 * interactive user may place an interactive program inside a loop. If
4604 * the interactive program catches interrupts, the user doesn't want
4605 * these interrupts to also abort the loop. The approach we take here
4606 * is to have the shell ignore interrupt signals while waiting for a
4607 * foreground process to terminate, and then send itself an interrupt
4608 * signal if the child process was terminated by an interrupt signal.
4609 * Unfortunately, some programs want to do a bit of cleanup and then
4610 * exit on interrupt; unless these processes terminate themselves by
4611 * sending a signal to themselves (instead of calling exit) they will
4612 * confuse this approach.
4614 * Called with interrupts off.
4617 waitforjob(struct job *jp)
4621 TRACE(("waitforjob(%%%d) called\n", jobno(jp)));
4622 while (jp->state == JOBRUNNING) {
4623 dowait(DOWAIT_BLOCK, jp);
4628 xtcsetpgrp(ttyfd, rootpid);
4630 * This is truly gross.
4631 * If we're doing job control, then we did a TIOCSPGRP which
4632 * caused us (the shell) to no longer be in the controlling
4633 * session -- so we wouldn't have seen any ^C/SIGINT. So, we
4634 * intuit from the subprocess exit status whether a SIGINT
4635 * occurred, and if so interrupt ourselves. Yuck. - mycroft
4637 if (jp->sigint) /* TODO: do the same with all signals */
4638 raise(SIGINT); /* ... by raise(jp->sig) instead? */
4640 if (jp->state == JOBDONE)
4647 * return 1 if there are stopped jobs, otherwise 0
4659 if (jp && jp->state == JOBSTOPPED) {
4660 out2str("You have stopped jobs.\n");
4669 /* ============ redir.c
4671 * Code for dealing with input/output redirection.
4674 #define EMPTY -2 /* marks an unused slot in redirtab */
4675 #define CLOSED -3 /* marks a slot of previously-closed fd */
4678 * Open a file in noclobber mode.
4679 * The code was copied from bash.
4682 noclobberopen(const char *fname)
4685 struct stat finfo, finfo2;
4688 * If the file exists and is a regular file, return an error
4691 r = stat(fname, &finfo);
4692 if (r == 0 && S_ISREG(finfo.st_mode)) {
4698 * If the file was not present (r != 0), make sure we open it
4699 * exclusively so that if it is created before we open it, our open
4700 * will fail. Make sure that we do not truncate an existing file.
4701 * Note that we don't turn on O_EXCL unless the stat failed -- if the
4702 * file was not a regular file, we leave O_EXCL off.
4705 return open(fname, O_WRONLY|O_CREAT|O_EXCL, 0666);
4706 fd = open(fname, O_WRONLY|O_CREAT, 0666);
4708 /* If the open failed, return the file descriptor right away. */
4713 * OK, the open succeeded, but the file may have been changed from a
4714 * non-regular file to a regular file between the stat and the open.
4715 * We are assuming that the O_EXCL open handles the case where FILENAME
4716 * did not exist and is symlinked to an existing file between the stat
4721 * If we can open it and fstat the file descriptor, and neither check
4722 * revealed that it was a regular file, and the file has not been
4723 * replaced, return the file descriptor.
4725 if (fstat(fd, &finfo2) == 0 && !S_ISREG(finfo2.st_mode)
4726 && finfo.st_dev == finfo2.st_dev && finfo.st_ino == finfo2.st_ino)
4729 /* The file has been replaced. badness. */
4736 * Handle here documents. Normally we fork off a process to write the
4737 * data to a pipe. If the document is short, we can stuff the data in
4738 * the pipe without forking.
4740 /* openhere needs this forward reference */
4741 static void expandhere(union node *arg, int fd);
4743 openhere(union node *redir)
4749 ash_msg_and_raise_error("pipe call failed");
4750 if (redir->type == NHERE) {
4751 len = strlen(redir->nhere.doc->narg.text);
4752 if (len <= PIPE_BUF) {
4753 full_write(pip[1], redir->nhere.doc->narg.text, len);
4757 if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) {
4760 signal(SIGINT, SIG_IGN);
4761 signal(SIGQUIT, SIG_IGN);
4762 signal(SIGHUP, SIG_IGN);
4764 signal(SIGTSTP, SIG_IGN);
4766 signal(SIGPIPE, SIG_DFL);
4767 if (redir->type == NHERE)
4768 full_write(pip[1], redir->nhere.doc->narg.text, len);
4770 expandhere(redir->nhere.doc, pip[1]);
4771 _exit(EXIT_SUCCESS);
4779 openredirect(union node *redir)
4784 switch (redir->nfile.type) {
4786 fname = redir->nfile.expfname;
4787 f = open(fname, O_RDONLY);
4792 fname = redir->nfile.expfname;
4793 f = open(fname, O_RDWR|O_CREAT|O_TRUNC, 0666);
4798 #if ENABLE_ASH_BASH_COMPAT
4801 /* Take care of noclobber mode. */
4803 fname = redir->nfile.expfname;
4804 f = noclobberopen(fname);
4811 fname = redir->nfile.expfname;
4812 f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666);
4817 fname = redir->nfile.expfname;
4818 f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666);
4826 /* Fall through to eliminate warning. */
4827 /* Our single caller does this itself */
4834 f = openhere(redir);
4840 ash_msg_and_raise_error("can't create %s: %s", fname, errmsg(errno, "nonexistent directory"));
4842 ash_msg_and_raise_error("can't open %s: %s", fname, errmsg(errno, "no such file"));
4846 * Copy a file descriptor to be >= to. Returns -1
4847 * if the source file descriptor is closed, EMPTY if there are no unused
4848 * file descriptors left.
4850 /* 0x800..00: bit to set in "to" to request dup2 instead of fcntl(F_DUPFD).
4851 * old code was doing close(to) prior to copyfd() to achieve the same */
4853 COPYFD_EXACT = (int)~(INT_MAX),
4854 COPYFD_RESTORE = (int)((unsigned)COPYFD_EXACT >> 1),
4857 copyfd(int from, int to)
4861 if (to & COPYFD_EXACT) {
4862 to &= ~COPYFD_EXACT;
4864 newfd = dup2(from, to);
4866 newfd = fcntl(from, F_DUPFD, to);
4869 if (errno == EMFILE)
4871 /* Happens when source fd is not open: try "echo >&99" */
4872 ash_msg_and_raise_error("%d: %m", from);
4877 /* Struct def and variable are moved down to the first usage site */
4882 struct redirtab *next;
4885 struct two_fd_t two_fd[0];
4887 #define redirlist (G_var.redirlist)
4889 static int need_to_remember(struct redirtab *rp, int fd)
4893 if (!rp) /* remembering was not requested */
4896 for (i = 0; i < rp->pair_count; i++) {
4897 if (rp->two_fd[i].orig == fd) {
4898 /* already remembered */
4905 /* "hidden" fd is a fd used to read scripts, or a copy of such */
4906 static int is_hidden_fd(struct redirtab *rp, int fd)
4909 struct parsefile *pf;
4922 fd |= COPYFD_RESTORE;
4923 for (i = 0; i < rp->pair_count; i++) {
4924 if (rp->two_fd[i].copy == fd) {
4932 * Process a list of redirection commands. If the REDIR_PUSH flag is set,
4933 * old file descriptors are stashed away so that the redirection can be
4934 * undone by calling popredir. If the REDIR_BACKQ flag is set, then the
4935 * standard output, and the standard error if it becomes a duplicate of
4936 * stdout, is saved in memory.
4938 /* flags passed to redirect */
4939 #define REDIR_PUSH 01 /* save previous values of file descriptors */
4940 #define REDIR_SAVEFD2 03 /* set preverrout */
4942 redirect(union node *redir, int flags)
4944 struct redirtab *sv;
4949 int copied_fd2 = -1;
4959 if (flags & REDIR_PUSH) {
4960 union node *tmp = redir;
4963 #if ENABLE_ASH_BASH_COMPAT
4964 if (redir->nfile.type == NTO2)
4967 tmp = tmp->nfile.next;
4969 sv = ckmalloc(sizeof(*sv) + sv_pos * sizeof(sv->two_fd[0]));
4970 sv->next = redirlist;
4971 sv->pair_count = sv_pos;
4973 sv->nullredirs = g_nullredirs - 1;
4975 while (sv_pos > 0) {
4977 sv->two_fd[sv_pos].orig = sv->two_fd[sv_pos].copy = EMPTY;
4982 fd = redir->nfile.fd;
4983 if (redir->nfile.type == NTOFD || redir->nfile.type == NFROMFD) {
4984 int right_fd = redir->ndup.dupfd;
4985 /* redirect from/to same file descriptor? */
4988 /* echo >&10 and 10 is a fd opened to the sh script? */
4989 if (is_hidden_fd(sv, right_fd)) {
4990 errno = EBADF; /* as if it is closed */
4991 ash_msg_and_raise_error("%d: %m", right_fd);
4995 newfd = openredirect(redir); /* always >= 0 */
4997 /* Descriptor wasn't open before redirect.
4998 * Mark it for close in the future */
4999 if (need_to_remember(sv, fd)) {
5000 goto remember_to_close;
5005 #if ENABLE_ASH_BASH_COMPAT
5008 if (need_to_remember(sv, fd)) {
5009 /* Copy old descriptor */
5010 i = fcntl(fd, F_DUPFD, 10);
5011 /* You'd expect copy to be CLOEXECed. Currently these extra "saved" fds
5012 * are closed in popredir() in the child, preventing them from leaking
5013 * into child. (popredir() also cleans up the mess in case of failures)
5018 /* Strange error (e.g. "too many files" EMFILE?) */
5022 ash_msg_and_raise_error("%d: %m", fd);
5025 /* EBADF: it is not open - good, remember to close it */
5028 } else { /* fd is open, save its copy */
5029 /* "exec fd>&-" should not close fds
5030 * which point to script file(s).
5031 * Force them to be restored afterwards */
5032 if (is_hidden_fd(sv, fd))
5033 i |= COPYFD_RESTORE;
5037 sv->two_fd[sv_pos].orig = fd;
5038 sv->two_fd[sv_pos].copy = i;
5042 /* NTOFD/NFROMFD: copy redir->ndup.dupfd to fd */
5043 if (redir->ndup.dupfd < 0) { /* "fd>&-" */
5046 copyfd(redir->ndup.dupfd, fd | COPYFD_EXACT);
5048 } else if (fd != newfd) { /* move newfd to fd */
5049 copyfd(newfd, fd | COPYFD_EXACT);
5050 #if ENABLE_ASH_BASH_COMPAT
5051 if (!(redir->nfile.type == NTO2 && fd == 2))
5055 #if ENABLE_ASH_BASH_COMPAT
5056 if (redir->nfile.type == NTO2 && fd == 1) {
5057 /* We already redirected it to fd 1, now copy it to 2 */
5063 } while ((redir = redir->nfile.next) != NULL);
5066 if ((flags & REDIR_SAVEFD2) && copied_fd2 >= 0)
5067 preverrout_fd = copied_fd2;
5071 * Undo the effects of the last redirection.
5074 popredir(int drop, int restore)
5076 struct redirtab *rp;
5079 if (--g_nullredirs >= 0)
5083 for (i = 0; i < rp->pair_count; i++) {
5084 int fd = rp->two_fd[i].orig;
5085 int copy = rp->two_fd[i].copy;
5086 if (copy == CLOSED) {
5091 if (copy != EMPTY) {
5092 if (!drop || (restore && (copy & COPYFD_RESTORE))) {
5093 copy &= ~COPYFD_RESTORE;
5095 copyfd(copy, fd | COPYFD_EXACT);
5100 redirlist = rp->next;
5101 g_nullredirs = rp->nullredirs;
5107 * Undo all redirections. Called on error or interrupt.
5111 * Discard all saved file descriptors.
5114 clearredir(int drop)
5120 popredir(drop, /*restore:*/ 0);
5125 redirectsafe(union node *redir, int flags)
5128 volatile int saveint;
5129 struct jmploc *volatile savehandler = exception_handler;
5130 struct jmploc jmploc;
5133 /* "echo 9>/dev/null; echo >&9; echo result: $?" - result should be 1, not 2! */
5134 err = setjmp(jmploc.loc); // huh?? was = setjmp(jmploc.loc) * 2;
5136 exception_handler = &jmploc;
5137 redirect(redir, flags);
5139 exception_handler = savehandler;
5140 if (err && exception != EXERROR)
5141 longjmp(exception_handler->loc, 1);
5142 RESTORE_INT(saveint);
5147 /* ============ Routines to expand arguments to commands
5149 * We have to deal with backquotes, shell variables, and file metacharacters.
5152 #if ENABLE_ASH_MATH_SUPPORT_64
5153 typedef int64_t arith_t;
5154 #define arith_t_type long long
5156 typedef long arith_t;
5157 #define arith_t_type long
5160 #if ENABLE_ASH_MATH_SUPPORT
5161 static arith_t dash_arith(const char *);
5162 static arith_t arith(const char *expr, int *perrcode);
5168 #define EXP_FULL 0x1 /* perform word splitting & file globbing */
5169 #define EXP_TILDE 0x2 /* do normal tilde expansion */
5170 #define EXP_VARTILDE 0x4 /* expand tildes in an assignment */
5171 #define EXP_REDIR 0x8 /* file glob for a redirection (1 match only) */
5172 #define EXP_CASE 0x10 /* keeps quotes around for CASE pattern */
5173 #define EXP_RECORD 0x20 /* need to record arguments for ifs breakup */
5174 #define EXP_VARTILDE2 0x40 /* expand tildes after colons only */
5175 #define EXP_WORD 0x80 /* expand word in parameter expansion */
5176 #define EXP_QWORD 0x100 /* expand word in quoted parameter expansion */
5180 #define RMESCAPE_ALLOC 0x1 /* Allocate a new string */
5181 #define RMESCAPE_GLOB 0x2 /* Add backslashes for glob */
5182 #define RMESCAPE_QUOTED 0x4 /* Remove CTLESC unless in quotes */
5183 #define RMESCAPE_GROW 0x8 /* Grow strings instead of stalloc */
5184 #define RMESCAPE_HEAP 0x10 /* Malloc strings instead of stalloc */
5187 * Structure specifying which parts of the string should be searched
5188 * for IFS characters.
5191 struct ifsregion *next; /* next region in list */
5192 int begoff; /* offset of start of region */
5193 int endoff; /* offset of end of region */
5194 int nulonly; /* search for nul bytes only */
5198 struct strlist *list;
5199 struct strlist **lastp;
5202 /* output of current string */
5203 static char *expdest;
5204 /* list of back quote expressions */
5205 static struct nodelist *argbackq;
5206 /* first struct in list of ifs regions */
5207 static struct ifsregion ifsfirst;
5208 /* last struct in list */
5209 static struct ifsregion *ifslastp;
5210 /* holds expanded arg list */
5211 static struct arglist exparg;
5221 expdest = makestrspace(32, expdest);
5222 #if ENABLE_ASH_MATH_SUPPORT_64
5223 len = fmtstr(expdest, 32, "%lld", (long long) num);
5225 len = fmtstr(expdest, 32, "%ld", num);
5227 STADJUST(len, expdest);
5232 esclen(const char *start, const char *p)
5236 while (p > start && *--p == CTLESC) {
5243 * Remove any CTLESC characters from a string.
5246 _rmescapes(char *str, int flag)
5248 static const char qchars[] ALIGN1 = { CTLESC, CTLQUOTEMARK, '\0' };
5255 p = strpbrk(str, qchars);
5261 if (flag & RMESCAPE_ALLOC) {
5262 size_t len = p - str;
5263 size_t fulllen = len + strlen(p) + 1;
5265 if (flag & RMESCAPE_GROW) {
5266 r = makestrspace(fulllen, expdest);
5267 } else if (flag & RMESCAPE_HEAP) {
5268 r = ckmalloc(fulllen);
5270 r = stalloc(fulllen);
5274 q = (char *)memcpy(q, str, len) + len;
5277 inquotes = (flag & RMESCAPE_QUOTED) ^ RMESCAPE_QUOTED;
5278 globbing = flag & RMESCAPE_GLOB;
5279 notescaped = globbing;
5281 if (*p == CTLQUOTEMARK) {
5282 inquotes = ~inquotes;
5284 notescaped = globbing;
5288 /* naked back slash */
5294 if (notescaped && inquotes && *p != '/') {
5298 notescaped = globbing;
5303 if (flag & RMESCAPE_GROW) {
5305 STADJUST(q - r + 1, expdest);
5309 #define rmescapes(p) _rmescapes((p), 0)
5311 #define pmatch(a, b) !fnmatch((a), (b), 0)
5314 * Prepare a pattern for a expmeta (internal glob(3)) call.
5316 * Returns an stalloced string.
5319 preglob(const char *pattern, int quoted, int flag)
5321 flag |= RMESCAPE_GLOB;
5323 flag |= RMESCAPE_QUOTED;
5325 return _rmescapes((char *)pattern, flag);
5329 * Put a string on the stack.
5332 memtodest(const char *p, size_t len, int syntax, int quotes)
5336 q = makestrspace(len * 2, q);
5339 int c = signed_char2int(*p++);
5342 if (quotes && (SIT(c, syntax) == CCTL || SIT(c, syntax) == CBACK))
5351 strtodest(const char *p, int syntax, int quotes)
5353 memtodest(p, strlen(p), syntax, quotes);
5357 * Record the fact that we have to scan this region of the
5358 * string for IFS characters.
5361 recordregion(int start, int end, int nulonly)
5363 struct ifsregion *ifsp;
5365 if (ifslastp == NULL) {
5369 ifsp = ckzalloc(sizeof(*ifsp));
5370 /*ifsp->next = NULL; - ckzalloc did it */
5371 ifslastp->next = ifsp;
5375 ifslastp->begoff = start;
5376 ifslastp->endoff = end;
5377 ifslastp->nulonly = nulonly;
5381 removerecordregions(int endoff)
5383 if (ifslastp == NULL)
5386 if (ifsfirst.endoff > endoff) {
5387 while (ifsfirst.next != NULL) {
5388 struct ifsregion *ifsp;
5390 ifsp = ifsfirst.next->next;
5391 free(ifsfirst.next);
5392 ifsfirst.next = ifsp;
5395 if (ifsfirst.begoff > endoff)
5398 ifslastp = &ifsfirst;
5399 ifsfirst.endoff = endoff;
5404 ifslastp = &ifsfirst;
5405 while (ifslastp->next && ifslastp->next->begoff < endoff)
5406 ifslastp=ifslastp->next;
5407 while (ifslastp->next != NULL) {
5408 struct ifsregion *ifsp;
5410 ifsp = ifslastp->next->next;
5411 free(ifslastp->next);
5412 ifslastp->next = ifsp;
5415 if (ifslastp->endoff > endoff)
5416 ifslastp->endoff = endoff;
5420 exptilde(char *startp, char *p, int flag)
5426 int quotes = flag & (EXP_FULL | EXP_CASE);
5431 while ((c = *++p) != '\0') {
5438 if (flag & EXP_VARTILDE)
5448 if (*name == '\0') {
5449 home = lookupvar(homestr);
5451 pw = getpwnam(name);
5456 if (!home || !*home)
5459 startloc = expdest - (char *)stackblock();
5460 strtodest(home, SQSYNTAX, quotes);
5461 recordregion(startloc, expdest - (char *)stackblock(), 0);
5469 * Execute a command inside back quotes. If it's a builtin command, we
5470 * want to save its output in a block obtained from malloc. Otherwise
5471 * we fork off a subprocess and get the output of the command via a pipe.
5472 * Should be called with interrupts off.
5474 struct backcmd { /* result of evalbackcmd */
5475 int fd; /* file descriptor to read from */
5476 int nleft; /* number of chars in buffer */
5477 char *buf; /* buffer */
5478 struct job *jp; /* job structure for command */
5481 /* These forward decls are needed to use "eval" code for backticks handling: */
5482 static uint8_t back_exitstatus; /* exit status of backquoted command */
5483 #define EV_EXIT 01 /* exit after evaluating tree */
5484 static void evaltree(union node *, int);
5487 evalbackcmd(union node *n, struct backcmd *result)
5499 saveherefd = herefd;
5507 ash_msg_and_raise_error("pipe call failed");
5508 jp = makejob(/*n,*/ 1);
5509 if (forkshell(jp, n, FORK_NOJOB) == 0) {
5514 copyfd(pip[1], 1 | COPYFD_EXACT);
5518 evaltree(n, EV_EXIT); /* actually evaltreenr... */
5522 result->fd = pip[0];
5525 herefd = saveherefd;
5527 TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n",
5528 result->fd, result->buf, result->nleft, result->jp));
5532 * Expand stuff in backwards quotes.
5535 expbackq(union node *cmd, int quoted, int quotes)
5543 int syntax = quoted ? DQSYNTAX : BASESYNTAX;
5544 struct stackmark smark;
5547 setstackmark(&smark);
5549 startloc = dest - (char *)stackblock();
5551 evalbackcmd(cmd, &in);
5552 popstackmark(&smark);
5559 memtodest(p, i, syntax, quotes);
5563 i = nonblock_safe_read(in.fd, buf, sizeof(buf));
5564 TRACE(("expbackq: read returns %d\n", i));
5573 back_exitstatus = waitforjob(in.jp);
5577 /* Eat all trailing newlines */
5579 for (; dest > (char *)stackblock() && dest[-1] == '\n';)
5584 recordregion(startloc, dest - (char *)stackblock(), 0);
5585 TRACE(("evalbackq: size=%d: \"%.*s\"\n",
5586 (dest - (char *)stackblock()) - startloc,
5587 (dest - (char *)stackblock()) - startloc,
5588 stackblock() + startloc));
5591 #if ENABLE_ASH_MATH_SUPPORT
5593 * Expand arithmetic expression. Backup to start of expression,
5594 * evaluate, place result in (backed up) result, adjust string position.
5607 * This routine is slightly over-complicated for
5608 * efficiency. Next we scan backwards looking for the
5609 * start of arithmetic.
5611 start = stackblock();
5618 while (*p != CTLARI) {
5622 ash_msg_and_raise_error("missing CTLARI (shouldn't happen)");
5627 esc = esclen(start, p);
5637 removerecordregions(begoff);
5646 len = cvtnum(dash_arith(p + 2));
5649 recordregion(begoff, begoff + len, 0);
5653 /* argstr needs it */
5654 static char *evalvar(char *p, int flag, struct strlist *var_str_list);
5657 * Perform variable and command substitution. If EXP_FULL is set, output CTLESC
5658 * characters to allow for further processing. Otherwise treat
5659 * $@ like $* since no splitting will be performed.
5661 * var_str_list (can be NULL) is a list of "VAR=val" strings which take precedence
5662 * over shell varables. Needed for "A=a B=$A; echo $B" case - we use it
5663 * for correct expansion of "B=$A" word.
5666 argstr(char *p, int flag, struct strlist *var_str_list)
5668 static const char spclchars[] ALIGN1 = {
5676 CTLBACKQ | CTLQUOTE,
5677 #if ENABLE_ASH_MATH_SUPPORT
5682 const char *reject = spclchars;
5684 int quotes = flag & (EXP_FULL | EXP_CASE); /* do CTLESC */
5685 int breakall = flag & EXP_WORD;
5690 if (!(flag & EXP_VARTILDE)) {
5692 } else if (flag & EXP_VARTILDE2) {
5697 if (flag & EXP_TILDE) {
5703 if (*q == CTLESC && (flag & EXP_QWORD))
5706 p = exptilde(p, q, flag);
5709 startloc = expdest - (char *)stackblock();
5711 length += strcspn(p + length, reject);
5713 if (c && (!(c & 0x80)
5714 #if ENABLE_ASH_MATH_SUPPORT
5718 /* c == '=' || c == ':' || c == CTLENDARI */
5723 expdest = stack_nputstr(p, length, expdest);
5724 newloc = expdest - (char *)stackblock();
5725 if (breakall && !inquotes && newloc > startloc) {
5726 recordregion(startloc, newloc, 0);
5737 if (flag & EXP_VARTILDE2) {
5741 flag |= EXP_VARTILDE2;
5746 * sort of a hack - expand tildes in variable
5747 * assignments (after the first '=' and after ':'s).
5756 case CTLENDVAR: /* ??? */
5759 /* "$@" syntax adherence hack */
5762 !memcmp(p, dolatstr, 4) &&
5763 (p[4] == CTLQUOTEMARK || (
5764 p[4] == CTLENDVAR &&
5765 p[5] == CTLQUOTEMARK
5768 p = evalvar(p + 1, flag, /* var_str_list: */ NULL) + 1;
5771 inquotes = !inquotes;
5784 p = evalvar(p, flag, var_str_list);
5788 case CTLBACKQ|CTLQUOTE:
5789 expbackq(argbackq->n, c, quotes);
5790 argbackq = argbackq->next;
5792 #if ENABLE_ASH_MATH_SUPPORT
5805 scanleft(char *startp, char *rmesc, char *rmescend UNUSED_PARAM, char *str, int quotes,
5808 // This commented out code was added by James Simmons <jsimmons@infradead.org>
5809 // as part of a larger change when he added support for ${var/a/b}.
5810 // However, it broke # and % operators:
5814 //echo ${var#ab} abcdcd abcdcd
5815 //echo ${var##ab} abcdcd abcdcd
5816 //echo ${var#a*b} abcdcd ababcdcd (!)
5817 //echo ${var##a*b} cdcd cdcd
5818 //echo ${var#?} babcdcd ababcdcd (!)
5819 //echo ${var##?} babcdcd babcdcd
5820 //echo ${var#*} ababcdcd babcdcd (!)
5822 //echo ${var%cd} ababcd ababcd
5823 //echo ${var%%cd} ababcd abab (!)
5824 //echo ${var%c*d} ababcd ababcd
5825 //echo ${var%%c*d} abab ababcdcd (!)
5826 //echo ${var%?} ababcdc ababcdc
5827 //echo ${var%%?} ababcdc ababcdcd (!)
5828 //echo ${var%*} ababcdcd ababcdcd
5831 // Commenting it back out helped. Remove it completely if it really
5834 char *loc, *loc2; //, *full;
5840 int match; // = strlen(str);
5841 const char *s = loc2;
5848 match = pmatch(str, s); // this line was deleted
5850 // // chop off end if its '*'
5851 // full = strrchr(str, '*');
5852 // if (full && full != str)
5855 // // If str starts with '*' replace with s.
5856 // if ((*str == '*') && strlen(s) >= match) {
5857 // full = xstrdup(s);
5858 // strncpy(full+strlen(s)-match+1, str+1, match-1);
5860 // full = xstrndup(str, match);
5861 // match = strncmp(s, full, strlen(full));
5865 if (match) // if (!match)
5867 if (quotes && *loc == CTLESC)
5876 scanright(char *startp, char *rmesc, char *rmescend, char *str, int quotes,
5883 for (loc = str - 1, loc2 = rmescend; loc >= startp; loc2--) {
5886 const char *s = loc2;
5891 match = pmatch(str, s);
5898 esc = esclen(startp, loc);
5909 static void varunset(const char *, const char *, const char *, int) NORETURN;
5911 varunset(const char *end, const char *var, const char *umsg, int varflags)
5917 msg = "parameter not set";
5919 if (*end == CTLENDVAR) {
5920 if (varflags & VSNUL)
5925 ash_msg_and_raise_error("%.*s: %s%s", end - var - 1, var, msg, tail);
5928 #if ENABLE_ASH_BASH_COMPAT
5930 parse_sub_pattern(char *arg, int inquotes)
5932 char *idx, *repl = NULL;
5941 /* Only the first '/' seen is our separator */
5948 if (!inquotes && c == '\\' && arg[1] == '\\')
5949 arg++; /* skip both \\, not just first one */
5956 #endif /* ENABLE_ASH_BASH_COMPAT */
5959 subevalvar(char *p, char *str, int strloc, int subtype,
5960 int startloc, int varflags, int quotes, struct strlist *var_str_list)
5962 struct nodelist *saveargbackq = argbackq;
5965 char *rmesc, *rmescend;
5966 USE_ASH_BASH_COMPAT(char *repl = NULL;)
5967 USE_ASH_BASH_COMPAT(char null = '\0';)
5968 USE_ASH_BASH_COMPAT(int pos, len, orig_len;)
5969 int saveherefd = herefd;
5970 int amount, workloc, resetloc;
5972 char *(*scan)(char*, char*, char*, char*, int, int);
5975 argstr(p, (subtype != VSASSIGN && subtype != VSQUESTION) ? EXP_CASE : 0,
5977 STPUTC('\0', expdest);
5978 herefd = saveherefd;
5979 argbackq = saveargbackq;
5980 startp = (char *)stackblock() + startloc;
5984 setvar(str, startp, 0);
5985 amount = startp - expdest;
5986 STADJUST(amount, expdest);
5989 #if ENABLE_ASH_BASH_COMPAT
5991 loc = str = stackblock() + strloc;
5992 // TODO: number() instead? It does error checking...
5994 len = str - startp - 1;
5996 /* *loc != '\0', guaranteed by parser */
6000 /* We must adjust the length by the number of escapes we find. */
6001 for (ptr = startp; ptr < (str - 1); ptr++) {
6002 if (*ptr == CTLESC) {
6010 if (*loc++ == ':') {
6011 // TODO: number() instead? It does error checking...
6015 while (*loc && *loc != ':')
6018 // TODO: number() instead? It does error checking...
6021 if (pos >= orig_len) {
6025 if (len > (orig_len - pos))
6026 len = orig_len - pos;
6028 for (str = startp; pos; str++, pos--) {
6029 if (quotes && *str == CTLESC)
6032 for (loc = startp; len; len--) {
6033 if (quotes && *str == CTLESC)
6038 amount = loc - expdest;
6039 STADJUST(amount, expdest);
6044 varunset(p, str, startp, varflags);
6047 resetloc = expdest - (char *)stackblock();
6049 /* We'll comeback here if we grow the stack while handling
6050 * a VSREPLACE or VSREPLACEALL, since our pointers into the
6051 * stack will need rebasing, and we'll need to remove our work
6054 USE_ASH_BASH_COMPAT(restart:)
6056 amount = expdest - ((char *)stackblock() + resetloc);
6057 STADJUST(-amount, expdest);
6058 startp = (char *)stackblock() + startloc;
6061 rmescend = (char *)stackblock() + strloc;
6063 rmesc = _rmescapes(startp, RMESCAPE_ALLOC | RMESCAPE_GROW);
6064 if (rmesc != startp) {
6066 startp = (char *)stackblock() + startloc;
6070 str = (char *)stackblock() + strloc;
6071 preglob(str, varflags & VSQUOTE, 0);
6072 workloc = expdest - (char *)stackblock();
6074 #if ENABLE_ASH_BASH_COMPAT
6075 if (subtype == VSREPLACE || subtype == VSREPLACEALL) {
6076 char *idx, *end, *restart_detect;
6079 repl = parse_sub_pattern(str, varflags & VSQUOTE);
6084 /* If there's no pattern to match, return the expansion unmolested */
6092 loc = scanright(idx, rmesc, rmescend, str, quotes, 1);
6094 /* No match, advance */
6095 restart_detect = stackblock();
6096 STPUTC(*idx, expdest);
6097 if (quotes && *idx == CTLESC) {
6100 STPUTC(*idx, expdest);
6102 if (stackblock() != restart_detect)
6110 if (subtype == VSREPLACEALL) {
6112 if (quotes && *idx == CTLESC)
6120 for (loc = repl; *loc; loc++) {
6121 restart_detect = stackblock();
6122 STPUTC(*loc, expdest);
6123 if (stackblock() != restart_detect)
6128 if (subtype == VSREPLACE) {
6130 restart_detect = stackblock();
6131 STPUTC(*idx, expdest);
6132 if (stackblock() != restart_detect)
6141 /* We've put the replaced text into a buffer at workloc, now
6142 * move it to the right place and adjust the stack.
6144 startp = stackblock() + startloc;
6145 STPUTC('\0', expdest);
6146 memmove(startp, stackblock() + workloc, len);
6147 startp[len++] = '\0';
6148 amount = expdest - ((char *)stackblock() + startloc + len - 1);
6149 STADJUST(-amount, expdest);
6152 #endif /* ENABLE_ASH_BASH_COMPAT */
6154 subtype -= VSTRIMRIGHT;
6156 if (subtype < 0 || subtype > 7)
6159 /* zero = subtype == VSTRIMLEFT || subtype == VSTRIMLEFTMAX */
6160 zero = subtype >> 1;
6161 /* VSTRIMLEFT/VSTRIMRIGHTMAX -> scanleft */
6162 scan = (subtype & 1) ^ zero ? scanleft : scanright;
6164 loc = scan(startp, rmesc, rmescend, str, quotes, zero);
6167 memmove(startp, loc, str - loc);
6168 loc = startp + (str - loc) - 1;
6171 amount = loc - expdest;
6172 STADJUST(amount, expdest);
6178 * Add the value of a specialized variable to the stack string.
6181 varvalue(char *name, int varflags, int flags, struct strlist *var_str_list)
6191 int quoted = varflags & VSQUOTE;
6192 int subtype = varflags & VSTYPE;
6193 int quotes = flags & (EXP_FULL | EXP_CASE);
6195 if (quoted && (flags & EXP_FULL))
6196 sep = 1 << CHAR_BIT;
6198 syntax = quoted ? DQSYNTAX : BASESYNTAX;
6207 num = shellparam.nparam;
6217 p = makestrspace(NOPTS, expdest);
6218 for (i = NOPTS - 1; i >= 0; i--) {
6220 USTPUTC(optletters(i), p);
6231 sep = ifsset() ? signed_char2int(ifsval()[0]) : ' ';
6232 if (quotes && (SIT(sep, syntax) == CCTL || SIT(sep, syntax) == CBACK))
6238 while ((p = *ap++)) {
6241 partlen = strlen(p);
6244 if (!(subtype == VSPLUS || subtype == VSLENGTH))
6245 memtodest(p, partlen, syntax, quotes);
6251 if (subtype == VSPLUS || subtype == VSLENGTH) {
6272 // TODO: number() instead? It does error checking...
6274 if (num < 0 || num > shellparam.nparam)
6276 p = num ? shellparam.p[num - 1] : arg0;
6279 /* NB: name has form "VAR=..." */
6281 /* "A=a B=$A" case: var_str_list is a list of "A=a" strings
6282 * which should be considered before we check variables. */
6284 unsigned name_len = (strchrnul(name, '=') - name) + 1;
6288 str = var_str_list->text;
6289 eq = strchr(str, '=');
6290 if (!eq) /* stop at first non-assignment */
6293 if (name_len == (unsigned)(eq - str)
6294 && strncmp(str, name, name_len) == 0) {
6296 /* goto value; - WRONG! */
6297 /* think "A=1 A=2 B=$A" */
6299 var_str_list = var_str_list->next;
6300 } while (var_str_list);
6304 p = lookupvar(name);
6310 if (!(subtype == VSPLUS || subtype == VSLENGTH))
6311 memtodest(p, len, syntax, quotes);
6315 if (subtype == VSPLUS || subtype == VSLENGTH)
6316 STADJUST(-len, expdest);
6321 * Expand a variable, and return a pointer to the next character in the
6325 evalvar(char *p, int flag, struct strlist *var_str_list)
6337 subtype = varflags & VSTYPE;
6338 quoted = varflags & VSQUOTE;
6340 easy = (!quoted || (*var == '@' && shellparam.nparam));
6341 startloc = expdest - (char *)stackblock();
6342 p = strchr(p, '=') + 1;
6345 varlen = varvalue(var, varflags, flag, var_str_list);
6346 if (varflags & VSNUL)
6349 if (subtype == VSPLUS) {
6350 varlen = -1 - varlen;
6354 if (subtype == VSMINUS) {
6358 p, flag | EXP_TILDE |
6359 (quoted ? EXP_QWORD : EXP_WORD),
6369 if (subtype == VSASSIGN || subtype == VSQUESTION) {
6371 if (subevalvar(p, var, /* strloc: */ 0,
6372 subtype, startloc, varflags,
6378 * Remove any recorded regions beyond
6381 removerecordregions(startloc);
6391 if (varlen < 0 && uflag)
6392 varunset(p, var, 0, 0);
6394 if (subtype == VSLENGTH) {
6395 cvtnum(varlen > 0 ? varlen : 0);
6399 if (subtype == VSNORMAL) {
6410 case VSTRIMRIGHTMAX:
6411 #if ENABLE_ASH_BASH_COMPAT
6424 * Terminate the string and start recording the pattern
6427 STPUTC('\0', expdest);
6428 patloc = expdest - (char *)stackblock();
6429 if (0 == subevalvar(p, /* str: */ NULL, patloc, subtype,
6431 /* quotes: */ flag & (EXP_FULL | EXP_CASE),
6434 int amount = expdest - (
6435 (char *)stackblock() + patloc - 1
6437 STADJUST(-amount, expdest);
6439 /* Remove any recorded regions beyond start of variable */
6440 removerecordregions(startloc);
6442 recordregion(startloc, expdest - (char *)stackblock(), quoted);
6446 if (subtype != VSNORMAL) { /* skip to end of alternative */
6452 else if (c == CTLBACKQ || c == (CTLBACKQ|CTLQUOTE)) {
6454 argbackq = argbackq->next;
6455 } else if (c == CTLVAR) {
6456 if ((*p++ & VSTYPE) != VSNORMAL)
6458 } else if (c == CTLENDVAR) {
6468 * Break the argument string into pieces based upon IFS and add the
6469 * strings to the argument list. The regions of the string to be
6470 * searched for IFS characters have been stored by recordregion.
6473 ifsbreakup(char *string, struct arglist *arglist)
6475 struct ifsregion *ifsp;
6480 const char *ifs, *realifs;
6485 if (ifslastp != NULL) {
6488 realifs = ifsset() ? ifsval() : defifs;
6491 p = string + ifsp->begoff;
6492 nulonly = ifsp->nulonly;
6493 ifs = nulonly ? nullstr : realifs;
6495 while (p < string + ifsp->endoff) {
6499 if (!strchr(ifs, *p)) {
6504 ifsspc = (strchr(defifs, *p) != NULL);
6505 /* Ignore IFS whitespace at start */
6506 if (q == start && ifsspc) {
6512 sp = stzalloc(sizeof(*sp));
6514 *arglist->lastp = sp;
6515 arglist->lastp = &sp->next;
6519 if (p >= string + ifsp->endoff) {
6525 if (strchr(ifs, *p) == NULL) {
6529 if (strchr(defifs, *p) == NULL) {
6544 } while (ifsp != NULL);
6553 sp = stzalloc(sizeof(*sp));
6555 *arglist->lastp = sp;
6556 arglist->lastp = &sp->next;
6562 struct ifsregion *p;
6567 struct ifsregion *ifsp;
6573 ifsfirst.next = NULL;
6578 * Add a file name to the list.
6581 addfname(const char *name)
6585 sp = stzalloc(sizeof(*sp));
6586 sp->text = ststrdup(name);
6588 exparg.lastp = &sp->next;
6591 static char *expdir;
6594 * Do metacharacter (i.e. *, ?, [...]) expansion.
6597 expmeta(char *enddir, char *name)
6612 for (p = name; *p; p++) {
6613 if (*p == '*' || *p == '?')
6615 else if (*p == '[') {
6622 if (*q == '/' || *q == '\0')
6629 } else if (*p == '\\')
6631 else if (*p == '/') {
6638 if (metaflag == 0) { /* we've reached the end of the file name */
6639 if (enddir != expdir)
6647 if (metaflag == 0 || lstat(expdir, &statb) >= 0)
6658 } while (p < start);
6660 if (enddir == expdir) {
6662 } else if (enddir == expdir + 1 && *expdir == '/') {
6671 if (enddir != expdir)
6673 if (*endname == 0) {
6685 while (!intpending && (dp = readdir(dirp)) != NULL) {
6686 if (dp->d_name[0] == '.' && !matchdot)
6688 if (pmatch(start, dp->d_name)) {
6690 strcpy(enddir, dp->d_name);
6693 for (p = enddir, cp = dp->d_name; (*p++ = *cp++) != '\0';)
6696 expmeta(p, endname);
6705 static struct strlist *
6706 msort(struct strlist *list, int len)
6708 struct strlist *p, *q = NULL;
6709 struct strlist **lpp;
6717 for (n = half; --n >= 0;) {
6721 q->next = NULL; /* terminate first half of list */
6722 q = msort(list, half); /* sort first half of list */
6723 p = msort(p, len - half); /* sort second half */
6726 #if ENABLE_LOCALE_SUPPORT
6727 if (strcoll(p->text, q->text) < 0)
6729 if (strcmp(p->text, q->text) < 0)
6753 * Sort the results of file name expansion. It calculates the number of
6754 * strings to sort and then calls msort (short for merge sort) to do the
6757 static struct strlist *
6758 expsort(struct strlist *str)
6764 for (sp = str; sp; sp = sp->next)
6766 return msort(str, len);
6770 expandmeta(struct strlist *str /*, int flag*/)
6772 static const char metachars[] ALIGN1 = {
6775 /* TODO - EXP_REDIR */
6778 struct strlist **savelastp;
6784 if (!strpbrk(str->text, metachars))
6786 savelastp = exparg.lastp;
6789 p = preglob(str->text, 0, RMESCAPE_ALLOC | RMESCAPE_HEAP);
6791 int i = strlen(str->text);
6792 expdir = ckmalloc(i < 2048 ? 2048 : i); /* XXX */
6800 if (exparg.lastp == savelastp) {
6805 *exparg.lastp = str;
6806 rmescapes(str->text);
6807 exparg.lastp = &str->next;
6809 *exparg.lastp = NULL;
6810 *savelastp = sp = expsort(*savelastp);
6811 while (sp->next != NULL)
6813 exparg.lastp = &sp->next;
6820 * Perform variable substitution and command substitution on an argument,
6821 * placing the resulting list of arguments in arglist. If EXP_FULL is true,
6822 * perform splitting and file name expansion. When arglist is NULL, perform
6823 * here document expansion.
6826 expandarg(union node *arg, struct arglist *arglist, int flag)
6831 argbackq = arg->narg.backquote;
6832 STARTSTACKSTR(expdest);
6833 ifsfirst.next = NULL;
6835 argstr(arg->narg.text, flag,
6836 /* var_str_list: */ arglist ? arglist->list : NULL);
6837 p = _STPUTC('\0', expdest);
6839 if (arglist == NULL) {
6840 return; /* here document expanded */
6842 p = grabstackstr(p);
6843 exparg.lastp = &exparg.list;
6847 if (flag & EXP_FULL) {
6848 ifsbreakup(p, &exparg);
6849 *exparg.lastp = NULL;
6850 exparg.lastp = &exparg.list;
6851 expandmeta(exparg.list /*, flag*/);
6853 if (flag & EXP_REDIR) /*XXX - for now, just remove escapes */
6855 sp = stzalloc(sizeof(*sp));
6858 exparg.lastp = &sp->next;
6862 *exparg.lastp = NULL;
6864 *arglist->lastp = exparg.list;
6865 arglist->lastp = exparg.lastp;
6870 * Expand shell variables and backquotes inside a here document.
6873 expandhere(union node *arg, int fd)
6876 expandarg(arg, (struct arglist *)NULL, 0);
6877 full_write(fd, stackblock(), expdest - (char *)stackblock());
6881 * Returns true if the pattern matches the string.
6884 patmatch(char *pattern, const char *string)
6886 return pmatch(preglob(pattern, 0, 0), string);
6890 * See if a pattern matches in a case statement.
6893 casematch(union node *pattern, char *val)
6895 struct stackmark smark;
6898 setstackmark(&smark);
6899 argbackq = pattern->narg.backquote;
6900 STARTSTACKSTR(expdest);
6902 argstr(pattern->narg.text, EXP_TILDE | EXP_CASE,
6903 /* var_str_list: */ NULL);
6904 STACKSTRNUL(expdest);
6905 result = patmatch(stackblock(), val);
6906 popstackmark(&smark);
6911 /* ============ find_command */
6915 int (*builtin)(int, char **);
6916 /* unsigned flags; */
6918 #define IS_BUILTIN_SPECIAL(b) ((b)->name[0] & 1)
6919 /* "regular" builtins always take precedence over commands,
6920 * regardless of PATH=....%builtin... position */
6921 #define IS_BUILTIN_REGULAR(b) ((b)->name[0] & 2)
6922 #define IS_BUILTIN_ASSIGN(b) ((b)->name[0] & 4)
6925 smallint cmdtype; /* CMDxxx */
6928 /* index >= 0 for commands without path (slashes) */
6929 /* (TODO: what exactly does the value mean? PATH position?) */
6930 /* index == -1 for commands with slashes */
6931 /* index == (-2 - applet_no) for NOFORK applets */
6932 const struct builtincmd *cmd;
6933 struct funcnode *func;
6936 /* values of cmdtype */
6937 #define CMDUNKNOWN -1 /* no entry in table for command */
6938 #define CMDNORMAL 0 /* command is an executable program */
6939 #define CMDFUNCTION 1 /* command is a shell function */
6940 #define CMDBUILTIN 2 /* command is a shell builtin */
6942 /* action to find_command() */
6943 #define DO_ERR 0x01 /* prints errors */
6944 #define DO_ABS 0x02 /* checks absolute paths */
6945 #define DO_NOFUNC 0x04 /* don't return shell functions, for command */
6946 #define DO_ALTPATH 0x08 /* using alternate path */
6947 #define DO_ALTBLTIN 0x20 /* %builtin in alt. path */
6949 static void find_command(char *, struct cmdentry *, int, const char *);
6952 /* ============ Hashing commands */
6955 * When commands are first encountered, they are entered in a hash table.
6956 * This ensures that a full path search will not have to be done for them
6957 * on each invocation.
6959 * We should investigate converting to a linear search, even though that
6960 * would make the command name "hash" a misnomer.
6964 struct tblentry *next; /* next entry in hash chain */
6965 union param param; /* definition of builtin function */
6966 smallint cmdtype; /* CMDxxx */
6967 char rehash; /* if set, cd done since entry created */
6968 char cmdname[1]; /* name of command */
6971 static struct tblentry **cmdtable;
6972 #define INIT_G_cmdtable() do { \
6973 cmdtable = xzalloc(CMDTABLESIZE * sizeof(cmdtable[0])); \
6976 static int builtinloc = -1; /* index in path of %builtin, or -1 */
6980 tryexec(USE_FEATURE_SH_STANDALONE(int applet_no,) char *cmd, char **argv, char **envp)
6984 #if ENABLE_FEATURE_SH_STANDALONE
6985 if (applet_no >= 0) {
6986 if (APPLET_IS_NOEXEC(applet_no)) {
6989 run_applet_no_and_exit(applet_no, argv);
6991 /* re-exec ourselves with the new arguments */
6992 execve(bb_busybox_exec_path, argv, envp);
6993 /* If they called chroot or otherwise made the binary no longer
6994 * executable, fall through */
7001 execve(cmd, argv, envp);
7002 } while (errno == EINTR);
7004 execve(cmd, argv, envp);
7010 if (errno == ENOEXEC) {
7014 for (ap = argv; *ap; ap++)
7016 ap = new = ckmalloc((ap - argv + 2) * sizeof(ap[0]));
7018 ap[0] = cmd = (char *)DEFAULT_SHELL;
7021 while ((*ap++ = *argv++) != NULL)
7030 * Exec a program. Never returns. If you change this routine, you may
7031 * have to change the find_command routine as well.
7033 static void shellexec(char **, const char *, int) NORETURN;
7035 shellexec(char **argv, const char *path, int idx)
7041 #if ENABLE_FEATURE_SH_STANDALONE
7045 clearredir(/*drop:*/ 1);
7046 envp = listvars(VEXPORT, VUNSET, 0);
7047 if (strchr(argv[0], '/') != NULL
7048 #if ENABLE_FEATURE_SH_STANDALONE
7049 || (applet_no = find_applet_by_name(argv[0])) >= 0
7052 tryexec(USE_FEATURE_SH_STANDALONE(applet_no,) argv[0], argv, envp);
7056 while ((cmdname = padvance(&path, argv[0])) != NULL) {
7057 if (--idx < 0 && pathopt == NULL) {
7058 tryexec(USE_FEATURE_SH_STANDALONE(-1,) cmdname, argv, envp);
7059 if (errno != ENOENT && errno != ENOTDIR)
7066 /* Map to POSIX errors */
7078 exitstatus = exerrno;
7079 TRACE(("shellexec failed for %s, errno %d, suppressint %d\n",
7080 argv[0], e, suppressint));
7081 ash_msg_and_raise(EXEXEC, "%s: %s", argv[0], errmsg(e, "not found"));
7086 printentry(struct tblentry *cmdp)
7092 idx = cmdp->param.index;
7095 name = padvance(&path, cmdp->cmdname);
7097 } while (--idx >= 0);
7098 out1fmt("%s%s\n", name, (cmdp->rehash ? "*" : nullstr));
7102 * Clear out command entries. The argument specifies the first entry in
7103 * PATH which has changed.
7106 clearcmdentry(int firstchange)
7108 struct tblentry **tblp;
7109 struct tblentry **pp;
7110 struct tblentry *cmdp;
7113 for (tblp = cmdtable; tblp < &cmdtable[CMDTABLESIZE]; tblp++) {
7115 while ((cmdp = *pp) != NULL) {
7116 if ((cmdp->cmdtype == CMDNORMAL &&
7117 cmdp->param.index >= firstchange)
7118 || (cmdp->cmdtype == CMDBUILTIN &&
7119 builtinloc >= firstchange)
7132 * Locate a command in the command hash table. If "add" is nonzero,
7133 * add the command to the table if it is not already present. The
7134 * variable "lastcmdentry" is set to point to the address of the link
7135 * pointing to the entry, so that delete_cmd_entry can delete the
7138 * Interrupts must be off if called with add != 0.
7140 static struct tblentry **lastcmdentry;
7142 static struct tblentry *
7143 cmdlookup(const char *name, int add)
7145 unsigned int hashval;
7147 struct tblentry *cmdp;
7148 struct tblentry **pp;
7151 hashval = (unsigned char)*p << 4;
7153 hashval += (unsigned char)*p++;
7155 pp = &cmdtable[hashval % CMDTABLESIZE];
7156 for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
7157 if (strcmp(cmdp->cmdname, name) == 0)
7161 if (add && cmdp == NULL) {
7162 cmdp = *pp = ckzalloc(sizeof(struct tblentry)
7164 /* + 1 - already done because
7165 * tblentry::cmdname is char[1] */);
7166 /*cmdp->next = NULL; - ckzalloc did it */
7167 cmdp->cmdtype = CMDUNKNOWN;
7168 strcpy(cmdp->cmdname, name);
7175 * Delete the command entry returned on the last lookup.
7178 delete_cmd_entry(void)
7180 struct tblentry *cmdp;
7183 cmdp = *lastcmdentry;
7184 *lastcmdentry = cmdp->next;
7185 if (cmdp->cmdtype == CMDFUNCTION)
7186 freefunc(cmdp->param.func);
7192 * Add a new command entry, replacing any existing command entry for
7193 * the same name - except special builtins.
7196 addcmdentry(char *name, struct cmdentry *entry)
7198 struct tblentry *cmdp;
7200 cmdp = cmdlookup(name, 1);
7201 if (cmdp->cmdtype == CMDFUNCTION) {
7202 freefunc(cmdp->param.func);
7204 cmdp->cmdtype = entry->cmdtype;
7205 cmdp->param = entry->u;
7210 hashcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
7212 struct tblentry **pp;
7213 struct tblentry *cmdp;
7215 struct cmdentry entry;
7218 if (nextopt("r") != '\0') {
7223 if (*argptr == NULL) {
7224 for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
7225 for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
7226 if (cmdp->cmdtype == CMDNORMAL)
7234 while ((name = *argptr) != NULL) {
7235 cmdp = cmdlookup(name, 0);
7237 && (cmdp->cmdtype == CMDNORMAL
7238 || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0))
7242 find_command(name, &entry, DO_ERR, pathval());
7243 if (entry.cmdtype == CMDUNKNOWN)
7251 * Called when a cd is done. Marks all commands so the next time they
7252 * are executed they will be rehashed.
7257 struct tblentry **pp;
7258 struct tblentry *cmdp;
7260 for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
7261 for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
7262 if (cmdp->cmdtype == CMDNORMAL
7263 || (cmdp->cmdtype == CMDBUILTIN
7264 && !IS_BUILTIN_REGULAR(cmdp->param.cmd)
7274 * Fix command hash table when PATH changed.
7275 * Called before PATH is changed. The argument is the new value of PATH;
7276 * pathval() still returns the old value at this point.
7277 * Called with interrupts off.
7280 changepath(const char *new)
7288 firstchange = 9999; /* assume no change */
7294 if ((*old == '\0' && *new == ':')
7295 || (*old == ':' && *new == '\0'))
7297 old = new; /* ignore subsequent differences */
7301 if (*new == '%' && idx_bltin < 0 && prefix(new + 1, "builtin"))
7307 if (builtinloc < 0 && idx_bltin >= 0)
7308 builtinloc = idx_bltin; /* zap builtins */
7309 if (builtinloc >= 0 && idx_bltin < 0)
7311 clearcmdentry(firstchange);
7312 builtinloc = idx_bltin;
7327 #define TENDBQUOTE 12
7344 typedef smallint token_id_t;
7346 /* first char is indicating which tokens mark the end of a list */
7347 static const char *const tokname_array[] = {
7361 #define KWDOFFSET 13
7362 /* the following are keywords */
7384 static char buf[16];
7387 //if (tok < TSEMI) return tokname_array[tok] + 1;
7388 //sprintf(buf, "\"%s\"", tokname_array[tok] + 1);
7393 sprintf(buf + (tok >= TSEMI), "%s%c",
7394 tokname_array[tok] + 1, (tok >= TSEMI ? '"' : 0));
7398 /* Wrapper around strcmp for qsort/bsearch/... */
7400 pstrcmp(const void *a, const void *b)
7402 return strcmp((char*) a, (*(char**) b) + 1);
7405 static const char *const *
7406 findkwd(const char *s)
7408 return bsearch(s, tokname_array + KWDOFFSET,
7409 ARRAY_SIZE(tokname_array) - KWDOFFSET,
7410 sizeof(tokname_array[0]), pstrcmp);
7414 * Locate and print what a word is...
7417 describe_command(char *command, int describe_command_verbose)
7419 struct cmdentry entry;
7420 struct tblentry *cmdp;
7421 #if ENABLE_ASH_ALIAS
7422 const struct alias *ap;
7424 const char *path = pathval();
7426 if (describe_command_verbose) {
7430 /* First look at the keywords */
7431 if (findkwd(command)) {
7432 out1str(describe_command_verbose ? " is a shell keyword" : command);
7436 #if ENABLE_ASH_ALIAS
7437 /* Then look at the aliases */
7438 ap = lookupalias(command, 0);
7440 if (!describe_command_verbose) {
7445 out1fmt(" is an alias for %s", ap->val);
7449 /* Then check if it is a tracked alias */
7450 cmdp = cmdlookup(command, 0);
7452 entry.cmdtype = cmdp->cmdtype;
7453 entry.u = cmdp->param;
7455 /* Finally use brute force */
7456 find_command(command, &entry, DO_ABS, path);
7459 switch (entry.cmdtype) {
7461 int j = entry.u.index;
7467 p = padvance(&path, command);
7471 if (describe_command_verbose) {
7473 (cmdp ? " a tracked alias for" : nullstr), p
7482 if (describe_command_verbose) {
7483 out1str(" is a shell function");
7490 if (describe_command_verbose) {
7491 out1fmt(" is a %sshell builtin",
7492 IS_BUILTIN_SPECIAL(entry.u.cmd) ?
7493 "special " : nullstr
7501 if (describe_command_verbose) {
7502 out1str(": not found\n");
7507 outstr("\n", stdout);
7512 typecmd(int argc UNUSED_PARAM, char **argv)
7518 /* type -p ... ? (we don't bother checking for 'p') */
7519 if (argv[1] && argv[1][0] == '-') {
7524 err |= describe_command(argv[i++], verbose);
7529 #if ENABLE_ASH_CMDCMD
7531 commandcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
7539 while ((c = nextopt("pvV")) != '\0')
7541 verify |= VERIFY_VERBOSE;
7543 verify |= VERIFY_BRIEF;
7548 /* Mimic bash: just "command -v" doesn't complain, it's a nop */
7549 if (verify && (*argptr != NULL)) {
7550 return describe_command(*argptr, verify - VERIFY_BRIEF);
7558 /* ============ eval.c */
7560 static int funcblocksize; /* size of structures in function */
7561 static int funcstringsize; /* size of strings in node */
7562 static void *funcblock; /* block to allocate function from */
7563 static char *funcstring; /* block to allocate strings from */
7565 /* flags in argument to evaltree */
7566 #define EV_EXIT 01 /* exit after evaluating tree */
7567 #define EV_TESTED 02 /* exit status is checked; ignore -e flag */
7568 #define EV_BACKCMD 04 /* command executing within back quotes */
7570 static const short nodesize[N_NUMBER] = {
7571 [NCMD ] = SHELL_ALIGN(sizeof(struct ncmd)),
7572 [NPIPE ] = SHELL_ALIGN(sizeof(struct npipe)),
7573 [NREDIR ] = SHELL_ALIGN(sizeof(struct nredir)),
7574 [NBACKGND ] = SHELL_ALIGN(sizeof(struct nredir)),
7575 [NSUBSHELL] = SHELL_ALIGN(sizeof(struct nredir)),
7576 [NAND ] = SHELL_ALIGN(sizeof(struct nbinary)),
7577 [NOR ] = SHELL_ALIGN(sizeof(struct nbinary)),
7578 [NSEMI ] = SHELL_ALIGN(sizeof(struct nbinary)),
7579 [NIF ] = SHELL_ALIGN(sizeof(struct nif)),
7580 [NWHILE ] = SHELL_ALIGN(sizeof(struct nbinary)),
7581 [NUNTIL ] = SHELL_ALIGN(sizeof(struct nbinary)),
7582 [NFOR ] = SHELL_ALIGN(sizeof(struct nfor)),
7583 [NCASE ] = SHELL_ALIGN(sizeof(struct ncase)),
7584 [NCLIST ] = SHELL_ALIGN(sizeof(struct nclist)),
7585 [NDEFUN ] = SHELL_ALIGN(sizeof(struct narg)),
7586 [NARG ] = SHELL_ALIGN(sizeof(struct narg)),
7587 [NTO ] = SHELL_ALIGN(sizeof(struct nfile)),
7588 #if ENABLE_ASH_BASH_COMPAT
7589 [NTO2 ] = SHELL_ALIGN(sizeof(struct nfile)),
7591 [NCLOBBER ] = SHELL_ALIGN(sizeof(struct nfile)),
7592 [NFROM ] = SHELL_ALIGN(sizeof(struct nfile)),
7593 [NFROMTO ] = SHELL_ALIGN(sizeof(struct nfile)),
7594 [NAPPEND ] = SHELL_ALIGN(sizeof(struct nfile)),
7595 [NTOFD ] = SHELL_ALIGN(sizeof(struct ndup)),
7596 [NFROMFD ] = SHELL_ALIGN(sizeof(struct ndup)),
7597 [NHERE ] = SHELL_ALIGN(sizeof(struct nhere)),
7598 [NXHERE ] = SHELL_ALIGN(sizeof(struct nhere)),
7599 [NNOT ] = SHELL_ALIGN(sizeof(struct nnot)),
7602 static void calcsize(union node *n);
7605 sizenodelist(struct nodelist *lp)
7608 funcblocksize += SHELL_ALIGN(sizeof(struct nodelist));
7615 calcsize(union node *n)
7619 funcblocksize += nodesize[n->type];
7622 calcsize(n->ncmd.redirect);
7623 calcsize(n->ncmd.args);
7624 calcsize(n->ncmd.assign);
7627 sizenodelist(n->npipe.cmdlist);
7632 calcsize(n->nredir.redirect);
7633 calcsize(n->nredir.n);
7640 calcsize(n->nbinary.ch2);
7641 calcsize(n->nbinary.ch1);
7644 calcsize(n->nif.elsepart);
7645 calcsize(n->nif.ifpart);
7646 calcsize(n->nif.test);
7649 funcstringsize += strlen(n->nfor.var) + 1;
7650 calcsize(n->nfor.body);
7651 calcsize(n->nfor.args);
7654 calcsize(n->ncase.cases);
7655 calcsize(n->ncase.expr);
7658 calcsize(n->nclist.body);
7659 calcsize(n->nclist.pattern);
7660 calcsize(n->nclist.next);
7664 sizenodelist(n->narg.backquote);
7665 funcstringsize += strlen(n->narg.text) + 1;
7666 calcsize(n->narg.next);
7669 #if ENABLE_ASH_BASH_COMPAT
7676 calcsize(n->nfile.fname);
7677 calcsize(n->nfile.next);
7681 calcsize(n->ndup.vname);
7682 calcsize(n->ndup.next);
7686 calcsize(n->nhere.doc);
7687 calcsize(n->nhere.next);
7690 calcsize(n->nnot.com);
7696 nodeckstrdup(char *s)
7698 char *rtn = funcstring;
7700 strcpy(funcstring, s);
7701 funcstring += strlen(s) + 1;
7705 static union node *copynode(union node *);
7707 static struct nodelist *
7708 copynodelist(struct nodelist *lp)
7710 struct nodelist *start;
7711 struct nodelist **lpp;
7716 funcblock = (char *) funcblock + SHELL_ALIGN(sizeof(struct nodelist));
7717 (*lpp)->n = copynode(lp->n);
7719 lpp = &(*lpp)->next;
7726 copynode(union node *n)
7733 funcblock = (char *) funcblock + nodesize[n->type];
7737 new->ncmd.redirect = copynode(n->ncmd.redirect);
7738 new->ncmd.args = copynode(n->ncmd.args);
7739 new->ncmd.assign = copynode(n->ncmd.assign);
7742 new->npipe.cmdlist = copynodelist(n->npipe.cmdlist);
7743 new->npipe.pipe_backgnd = n->npipe.pipe_backgnd;
7748 new->nredir.redirect = copynode(n->nredir.redirect);
7749 new->nredir.n = copynode(n->nredir.n);
7756 new->nbinary.ch2 = copynode(n->nbinary.ch2);
7757 new->nbinary.ch1 = copynode(n->nbinary.ch1);
7760 new->nif.elsepart = copynode(n->nif.elsepart);
7761 new->nif.ifpart = copynode(n->nif.ifpart);
7762 new->nif.test = copynode(n->nif.test);
7765 new->nfor.var = nodeckstrdup(n->nfor.var);
7766 new->nfor.body = copynode(n->nfor.body);
7767 new->nfor.args = copynode(n->nfor.args);
7770 new->ncase.cases = copynode(n->ncase.cases);
7771 new->ncase.expr = copynode(n->ncase.expr);
7774 new->nclist.body = copynode(n->nclist.body);
7775 new->nclist.pattern = copynode(n->nclist.pattern);
7776 new->nclist.next = copynode(n->nclist.next);
7780 new->narg.backquote = copynodelist(n->narg.backquote);
7781 new->narg.text = nodeckstrdup(n->narg.text);
7782 new->narg.next = copynode(n->narg.next);
7785 #if ENABLE_ASH_BASH_COMPAT
7792 new->nfile.fname = copynode(n->nfile.fname);
7793 new->nfile.fd = n->nfile.fd;
7794 new->nfile.next = copynode(n->nfile.next);
7798 new->ndup.vname = copynode(n->ndup.vname);
7799 new->ndup.dupfd = n->ndup.dupfd;
7800 new->ndup.fd = n->ndup.fd;
7801 new->ndup.next = copynode(n->ndup.next);
7805 new->nhere.doc = copynode(n->nhere.doc);
7806 new->nhere.fd = n->nhere.fd;
7807 new->nhere.next = copynode(n->nhere.next);
7810 new->nnot.com = copynode(n->nnot.com);
7813 new->type = n->type;
7818 * Make a copy of a parse tree.
7820 static struct funcnode *
7821 copyfunc(union node *n)
7826 funcblocksize = offsetof(struct funcnode, n);
7829 blocksize = funcblocksize;
7830 f = ckmalloc(blocksize + funcstringsize);
7831 funcblock = (char *) f + offsetof(struct funcnode, n);
7832 funcstring = (char *) f + blocksize;
7839 * Define a shell function.
7842 defun(char *name, union node *func)
7844 struct cmdentry entry;
7847 entry.cmdtype = CMDFUNCTION;
7848 entry.u.func = copyfunc(func);
7849 addcmdentry(name, &entry);
7853 static int evalskip; /* set if we are skipping commands */
7854 /* reasons for skipping commands (see comment on breakcmd routine) */
7855 #define SKIPBREAK (1 << 0)
7856 #define SKIPCONT (1 << 1)
7857 #define SKIPFUNC (1 << 2)
7858 #define SKIPFILE (1 << 3)
7859 #define SKIPEVAL (1 << 4)
7860 static int skipcount; /* number of levels to skip */
7861 static int funcnest; /* depth of function calls */
7862 static int loopnest; /* current loop nesting level */
7864 /* forward decl way out to parsing code - dotrap needs it */
7865 static int evalstring(char *s, int mask);
7868 * Called to execute a trap. Perhaps we should avoid entering new trap
7869 * handlers while we are executing a trap handler.
7880 savestatus = exitstatus;
7884 for (i = 1, q = gotsig; i < NSIG; i++, q++) {
7892 skip = evalstring(p, SKIPEVAL);
7893 exitstatus = savestatus;
7901 /* forward declarations - evaluation is fairly recursive business... */
7902 static void evalloop(union node *, int);
7903 static void evalfor(union node *, int);
7904 static void evalcase(union node *, int);
7905 static void evalsubshell(union node *, int);
7906 static void expredir(union node *);
7907 static void evalpipe(union node *, int);
7908 static void evalcommand(union node *, int);
7909 static int evalbltin(const struct builtincmd *, int, char **);
7910 static void prehash(union node *);
7913 * Evaluate a parse tree. The value is left in the global variable
7917 evaltree(union node *n, int flags)
7920 struct jmploc *volatile savehandler = exception_handler;
7921 struct jmploc jmploc;
7923 void (*evalfn)(union node *, int);
7927 TRACE(("evaltree(NULL) called\n"));
7930 TRACE(("pid %d, evaltree(%p: %d, %d) called\n",
7931 getpid(), n, n->type, flags));
7933 exception_handler = &jmploc;
7935 int err = setjmp(jmploc.loc);
7937 /* if it was a signal, check for trap handlers */
7938 if (exception == EXSIG)
7940 /* continue on the way out */
7941 exception_handler = savehandler;
7942 longjmp(exception_handler->loc, err);
7949 out1fmt("Node type = %d\n", n->type);
7954 evaltree(n->nnot.com, EV_TESTED);
7955 status = !exitstatus;
7958 expredir(n->nredir.redirect);
7959 status = redirectsafe(n->nredir.redirect, REDIR_PUSH);
7961 evaltree(n->nredir.n, flags & EV_TESTED);
7962 status = exitstatus;
7964 popredir(/*drop:*/ 0, /*restore:*/ 0 /* not sure */);
7967 evalfn = evalcommand;
7969 if (eflag && !(flags & EV_TESTED))
7981 evalfn = evalsubshell;
7994 #error NAND + 1 != NOR
7996 #if NOR + 1 != NSEMI
7997 #error NOR + 1 != NSEMI
7999 unsigned is_or = n->type - NAND;
8002 (flags | ((is_or >> 1) - 1)) & EV_TESTED
8004 if (!exitstatus == is_or)
8017 evaltree(n->nif.test, EV_TESTED);
8020 if (exitstatus == 0) {
8023 } else if (n->nif.elsepart) {
8024 n = n->nif.elsepart;
8029 defun(n->narg.text, n->narg.next);
8033 exitstatus = status;
8038 exception_handler = savehandler;
8040 if (checkexit & exitstatus)
8041 evalskip |= SKIPEVAL;
8042 else if (pendingsig && dotrap())
8045 if (flags & EV_EXIT) {
8047 raise_exception(EXEXIT);
8051 #if !defined(__alpha__) || (defined(__GNUC__) && __GNUC__ >= 3)
8054 void evaltreenr(union node *, int) __attribute__ ((alias("evaltree"),__noreturn__));
8057 evalloop(union node *n, int flags)
8067 evaltree(n->nbinary.ch1, EV_TESTED);
8070 if (evalskip == SKIPCONT && --skipcount <= 0) {
8074 if (evalskip == SKIPBREAK && --skipcount <= 0)
8079 if (n->type != NWHILE)
8083 evaltree(n->nbinary.ch2, flags);
8084 status = exitstatus;
8089 exitstatus = status;
8093 evalfor(union node *n, int flags)
8095 struct arglist arglist;
8098 struct stackmark smark;
8100 setstackmark(&smark);
8101 arglist.list = NULL;
8102 arglist.lastp = &arglist.list;
8103 for (argp = n->nfor.args; argp; argp = argp->narg.next) {
8104 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE | EXP_RECORD);
8109 *arglist.lastp = NULL;
8114 for (sp = arglist.list; sp; sp = sp->next) {
8115 setvar(n->nfor.var, sp->text, 0);
8116 evaltree(n->nfor.body, flags);
8118 if (evalskip == SKIPCONT && --skipcount <= 0) {
8122 if (evalskip == SKIPBREAK && --skipcount <= 0)
8129 popstackmark(&smark);
8133 evalcase(union node *n, int flags)
8137 struct arglist arglist;
8138 struct stackmark smark;
8140 setstackmark(&smark);
8141 arglist.list = NULL;
8142 arglist.lastp = &arglist.list;
8143 expandarg(n->ncase.expr, &arglist, EXP_TILDE);
8145 for (cp = n->ncase.cases; cp && evalskip == 0; cp = cp->nclist.next) {
8146 for (patp = cp->nclist.pattern; patp; patp = patp->narg.next) {
8147 if (casematch(patp, arglist.list->text)) {
8148 if (evalskip == 0) {
8149 evaltree(cp->nclist.body, flags);
8156 popstackmark(&smark);
8160 * Kick off a subshell to evaluate a tree.
8163 evalsubshell(union node *n, int flags)
8166 int backgnd = (n->type == NBACKGND);
8169 expredir(n->nredir.redirect);
8170 if (!backgnd && flags & EV_EXIT && !trap[0])
8173 jp = makejob(/*n,*/ 1);
8174 if (forkshell(jp, n, backgnd) == 0) {
8178 flags &=~ EV_TESTED;
8180 redirect(n->nredir.redirect, 0);
8181 evaltreenr(n->nredir.n, flags);
8186 status = waitforjob(jp);
8187 exitstatus = status;
8192 * Compute the names of the files in a redirection list.
8194 static void fixredir(union node *, const char *, int);
8196 expredir(union node *n)
8200 for (redir = n; redir; redir = redir->nfile.next) {
8204 fn.lastp = &fn.list;
8205 switch (redir->type) {
8209 #if ENABLE_ASH_BASH_COMPAT
8214 expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
8215 #if ENABLE_ASH_BASH_COMPAT
8218 redir->nfile.expfname = fn.list->text;
8221 case NTOFD: /* >& */
8222 if (redir->ndup.vname) {
8223 expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE);
8224 if (fn.list == NULL)
8225 ash_msg_and_raise_error("redir error");
8226 #if ENABLE_ASH_BASH_COMPAT
8227 //FIXME: we used expandarg with different args!
8228 if (!isdigit_str9(fn.list->text)) {
8229 /* >&file, not >&fd */
8230 if (redir->nfile.fd != 1) /* 123>&file - BAD */
8231 ash_msg_and_raise_error("redir error");
8233 goto store_expfname;
8236 fixredir(redir, fn.list->text, 1);
8244 * Evaluate a pipeline. All the processes in the pipeline are children
8245 * of the process creating the pipeline. (This differs from some versions
8246 * of the shell, which make the last process in a pipeline the parent
8250 evalpipe(union node *n, int flags)
8253 struct nodelist *lp;
8258 TRACE(("evalpipe(0x%lx) called\n", (long)n));
8260 for (lp = n->npipe.cmdlist; lp; lp = lp->next)
8264 jp = makejob(/*n,*/ pipelen);
8266 for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
8270 if (pipe(pip) < 0) {
8272 ash_msg_and_raise_error("pipe call failed");
8275 if (forkshell(jp, lp->n, n->npipe.pipe_backgnd) == 0) {
8288 evaltreenr(lp->n, flags);
8296 if (n->npipe.pipe_backgnd == 0) {
8297 exitstatus = waitforjob(jp);
8298 TRACE(("evalpipe: job done exit status %d\n", exitstatus));
8304 * Controls whether the shell is interactive or not.
8307 setinteractive(int on)
8309 static smallint is_interactive;
8311 if (++on == is_interactive)
8313 is_interactive = on;
8317 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
8318 if (is_interactive > 1) {
8319 /* Looks like they want an interactive shell */
8320 static smallint did_banner;
8325 "%s built-in shell (ash)\n"
8326 "Enter 'help' for a list of built-in commands."
8341 setinteractive(iflag);
8343 #if ENABLE_FEATURE_EDITING_VI
8345 line_input_state->flags |= VI_MODE;
8347 line_input_state->flags &= ~VI_MODE;
8349 viflag = 0; /* forcibly keep the option off */
8353 static struct localvar *localvars;
8356 * Called after a function returns.
8357 * Interrupts must be off.
8362 struct localvar *lvp;
8365 while ((lvp = localvars) != NULL) {
8366 localvars = lvp->next;
8368 TRACE(("poplocalvar %s", vp ? vp->text : "-"));
8369 if (vp == NULL) { /* $- saved */
8370 memcpy(optlist, lvp->text, sizeof(optlist));
8371 free((char*)lvp->text);
8373 } else if ((lvp->flags & (VUNSET|VSTRFIXED)) == VUNSET) {
8377 (*vp->func)(strchrnul(lvp->text, '=') + 1);
8378 if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
8379 free((char*)vp->text);
8380 vp->flags = lvp->flags;
8381 vp->text = lvp->text;
8388 evalfun(struct funcnode *func, int argc, char **argv, int flags)
8390 volatile struct shparam saveparam;
8391 struct localvar *volatile savelocalvars;
8392 struct jmploc *volatile savehandler;
8393 struct jmploc jmploc;
8396 saveparam = shellparam;
8397 savelocalvars = localvars;
8398 e = setjmp(jmploc.loc);
8403 savehandler = exception_handler;
8404 exception_handler = &jmploc;
8406 shellparam.malloced = 0;
8410 shellparam.nparam = argc - 1;
8411 shellparam.p = argv + 1;
8412 #if ENABLE_ASH_GETOPTS
8413 shellparam.optind = 1;
8414 shellparam.optoff = -1;
8416 evaltree(&func->n, flags & EV_TESTED);
8422 localvars = savelocalvars;
8423 freeparam(&shellparam);
8424 shellparam = saveparam;
8425 exception_handler = savehandler;
8427 evalskip &= ~SKIPFUNC;
8431 #if ENABLE_ASH_CMDCMD
8433 parse_command_args(char **argv, const char **path)
8446 if (c == '-' && !*cp) {
8453 *path = bb_default_path;
8456 /* run 'typecmd' for other options */
8467 * Make a variable a local variable. When a variable is made local, it's
8468 * value and flags are saved in a localvar structure. The saved values
8469 * will be restored when the shell function returns. We handle the name
8470 * "-" as a special case.
8475 struct localvar *lvp;
8480 lvp = ckzalloc(sizeof(struct localvar));
8481 if (LONE_DASH(name)) {
8483 p = ckmalloc(sizeof(optlist));
8484 lvp->text = memcpy(p, optlist, sizeof(optlist));
8489 vpp = hashvar(name);
8490 vp = *findvar(vpp, name);
8491 eq = strchr(name, '=');
8494 setvareq(name, VSTRFIXED);
8496 setvar(name, NULL, VSTRFIXED);
8497 vp = *vpp; /* the new variable */
8498 lvp->flags = VUNSET;
8500 lvp->text = vp->text;
8501 lvp->flags = vp->flags;
8502 vp->flags |= VSTRFIXED|VTEXTFIXED;
8508 lvp->next = localvars;
8514 * The "local" command.
8517 localcmd(int argc UNUSED_PARAM, char **argv)
8522 while ((name = *argv++) != NULL) {
8529 falsecmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
8535 truecmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
8541 execcmd(int argc UNUSED_PARAM, char **argv)
8544 iflag = 0; /* exit on error */
8547 shellexec(argv + 1, pathval(), 0);
8553 * The return command.
8556 returncmd(int argc UNUSED_PARAM, char **argv)
8559 * If called outside a function, do what ksh does;
8560 * skip the rest of the file.
8562 evalskip = funcnest ? SKIPFUNC : SKIPFILE;
8563 return argv[1] ? number(argv[1]) : exitstatus;
8566 /* Forward declarations for builtintab[] */
8567 static int breakcmd(int, char **);
8568 static int dotcmd(int, char **);
8569 static int evalcmd(int, char **);
8570 static int exitcmd(int, char **);
8571 static int exportcmd(int, char **);
8572 #if ENABLE_ASH_GETOPTS
8573 static int getoptscmd(int, char **);
8575 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
8576 static int helpcmd(int, char **);
8578 #if ENABLE_ASH_MATH_SUPPORT
8579 static int letcmd(int, char **);
8581 static int readcmd(int, char **);
8582 static int setcmd(int, char **);
8583 static int shiftcmd(int, char **);
8584 static int timescmd(int, char **);
8585 static int trapcmd(int, char **);
8586 static int umaskcmd(int, char **);
8587 static int unsetcmd(int, char **);
8588 static int ulimitcmd(int, char **);
8590 #define BUILTIN_NOSPEC "0"
8591 #define BUILTIN_SPECIAL "1"
8592 #define BUILTIN_REGULAR "2"
8593 #define BUILTIN_SPEC_REG "3"
8594 #define BUILTIN_ASSIGN "4"
8595 #define BUILTIN_SPEC_ASSG "5"
8596 #define BUILTIN_REG_ASSG "6"
8597 #define BUILTIN_SPEC_REG_ASSG "7"
8599 /* We do not handle [[ expr ]] bashism bash-compatibly,
8600 * we make it a synonym of [ expr ].
8601 * Basically, word splitting and pathname expansion should NOT be performed
8603 * no word splitting: a="a b"; [[ $a = "a b" ]]; echo $? should print "0"
8604 * no pathname expansion: [[ /bin/m* = "/bin/m*" ]]; echo $? should print "0"
8605 * Additional operators:
8606 * || and && should work as -o and -a
8608 * Apart from the above, [[ expr ]] should work as [ expr ]
8611 #define echocmd echo_main
8612 #define printfcmd printf_main
8613 #define testcmd test_main
8615 /* Keep these in proper order since it is searched via bsearch() */
8616 static const struct builtincmd builtintab[] = {
8617 { BUILTIN_SPEC_REG ".", dotcmd },
8618 { BUILTIN_SPEC_REG ":", truecmd },
8619 #if ENABLE_ASH_BUILTIN_TEST
8620 { BUILTIN_REGULAR "[", testcmd },
8621 #if ENABLE_ASH_BASH_COMPAT
8622 { BUILTIN_REGULAR "[[", testcmd },
8625 #if ENABLE_ASH_ALIAS
8626 { BUILTIN_REG_ASSG "alias", aliascmd },
8629 { BUILTIN_REGULAR "bg", fg_bgcmd },
8631 { BUILTIN_SPEC_REG "break", breakcmd },
8632 { BUILTIN_REGULAR "cd", cdcmd },
8633 { BUILTIN_NOSPEC "chdir", cdcmd },
8634 #if ENABLE_ASH_CMDCMD
8635 { BUILTIN_REGULAR "command", commandcmd },
8637 { BUILTIN_SPEC_REG "continue", breakcmd },
8638 #if ENABLE_ASH_BUILTIN_ECHO
8639 { BUILTIN_REGULAR "echo", echocmd },
8641 { BUILTIN_SPEC_REG "eval", evalcmd },
8642 { BUILTIN_SPEC_REG "exec", execcmd },
8643 { BUILTIN_SPEC_REG "exit", exitcmd },
8644 { BUILTIN_SPEC_REG_ASSG "export", exportcmd },
8645 { BUILTIN_REGULAR "false", falsecmd },
8647 { BUILTIN_REGULAR "fg", fg_bgcmd },
8649 #if ENABLE_ASH_GETOPTS
8650 { BUILTIN_REGULAR "getopts", getoptscmd },
8652 { BUILTIN_NOSPEC "hash", hashcmd },
8653 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
8654 { BUILTIN_NOSPEC "help", helpcmd },
8657 { BUILTIN_REGULAR "jobs", jobscmd },
8658 { BUILTIN_REGULAR "kill", killcmd },
8660 #if ENABLE_ASH_MATH_SUPPORT
8661 { BUILTIN_NOSPEC "let", letcmd },
8663 { BUILTIN_ASSIGN "local", localcmd },
8664 #if ENABLE_ASH_BUILTIN_PRINTF
8665 { BUILTIN_REGULAR "printf", printfcmd },
8667 { BUILTIN_NOSPEC "pwd", pwdcmd },
8668 { BUILTIN_REGULAR "read", readcmd },
8669 { BUILTIN_SPEC_REG_ASSG "readonly", exportcmd },
8670 { BUILTIN_SPEC_REG "return", returncmd },
8671 { BUILTIN_SPEC_REG "set", setcmd },
8672 { BUILTIN_SPEC_REG "shift", shiftcmd },
8673 { BUILTIN_SPEC_REG "source", dotcmd },
8674 #if ENABLE_ASH_BUILTIN_TEST
8675 { BUILTIN_REGULAR "test", testcmd },
8677 { BUILTIN_SPEC_REG "times", timescmd },
8678 { BUILTIN_SPEC_REG "trap", trapcmd },
8679 { BUILTIN_REGULAR "true", truecmd },
8680 { BUILTIN_NOSPEC "type", typecmd },
8681 { BUILTIN_NOSPEC "ulimit", ulimitcmd },
8682 { BUILTIN_REGULAR "umask", umaskcmd },
8683 #if ENABLE_ASH_ALIAS
8684 { BUILTIN_REGULAR "unalias", unaliascmd },
8686 { BUILTIN_SPEC_REG "unset", unsetcmd },
8687 { BUILTIN_REGULAR "wait", waitcmd },
8690 /* Should match the above table! */
8691 #define COMMANDCMD (builtintab + \
8693 1 * ENABLE_ASH_BUILTIN_TEST + \
8694 1 * ENABLE_ASH_BUILTIN_TEST * ENABLE_ASH_BASH_COMPAT + \
8695 1 * ENABLE_ASH_ALIAS + \
8696 1 * ENABLE_ASH_JOB_CONTROL + \
8698 #define EXECCMD (builtintab + \
8700 1 * ENABLE_ASH_BUILTIN_TEST + \
8701 1 * ENABLE_ASH_BUILTIN_TEST * ENABLE_ASH_BASH_COMPAT + \
8702 1 * ENABLE_ASH_ALIAS + \
8703 1 * ENABLE_ASH_JOB_CONTROL + \
8705 1 * ENABLE_ASH_CMDCMD + \
8707 ENABLE_ASH_BUILTIN_ECHO + \
8711 * Search the table of builtin commands.
8713 static struct builtincmd *
8714 find_builtin(const char *name)
8716 struct builtincmd *bp;
8719 name, builtintab, ARRAY_SIZE(builtintab), sizeof(builtintab[0]),
8726 * Execute a simple command.
8729 isassignment(const char *p)
8731 const char *q = endofname(p);
8737 bltincmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
8739 /* Preserve exitstatus of a previous possible redirection
8740 * as POSIX mandates */
8741 return back_exitstatus;
8744 evalcommand(union node *cmd, int flags)
8746 static const struct builtincmd null_bltin = {
8747 "\0\0", bltincmd /* why three NULs? */
8749 struct stackmark smark;
8751 struct arglist arglist;
8752 struct arglist varlist;
8755 const struct strlist *sp;
8756 struct cmdentry cmdentry;
8763 struct builtincmd *bcmd;
8764 smallint cmd_is_exec;
8765 smallint pseudovarflag = 0;
8767 /* First expand the arguments. */
8768 TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
8769 setstackmark(&smark);
8770 back_exitstatus = 0;
8772 cmdentry.cmdtype = CMDBUILTIN;
8773 cmdentry.u.cmd = &null_bltin;
8774 varlist.lastp = &varlist.list;
8775 *varlist.lastp = NULL;
8776 arglist.lastp = &arglist.list;
8777 *arglist.lastp = NULL;
8780 if (cmd->ncmd.args) {
8781 bcmd = find_builtin(cmd->ncmd.args->narg.text);
8782 pseudovarflag = bcmd && IS_BUILTIN_ASSIGN(bcmd);
8785 for (argp = cmd->ncmd.args; argp; argp = argp->narg.next) {
8786 struct strlist **spp;
8788 spp = arglist.lastp;
8789 if (pseudovarflag && isassignment(argp->narg.text))
8790 expandarg(argp, &arglist, EXP_VARTILDE);
8792 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
8794 for (sp = *spp; sp; sp = sp->next)
8798 argv = nargv = stalloc(sizeof(char *) * (argc + 1));
8799 for (sp = arglist.list; sp; sp = sp->next) {
8800 TRACE(("evalcommand arg: %s\n", sp->text));
8801 *nargv++ = sp->text;
8806 if (iflag && funcnest == 0 && argc > 0)
8807 lastarg = nargv[-1];
8810 expredir(cmd->ncmd.redirect);
8811 status = redirectsafe(cmd->ncmd.redirect, REDIR_PUSH | REDIR_SAVEFD2);
8814 for (argp = cmd->ncmd.assign; argp; argp = argp->narg.next) {
8815 struct strlist **spp;
8818 spp = varlist.lastp;
8819 expandarg(argp, &varlist, EXP_VARTILDE);
8822 * Modify the command lookup path, if a PATH= assignment
8826 if (varequal(p, path))
8830 /* Print the command if xflag is set. */
8833 const char *p = " %s";
8836 fdprintf(preverrout_fd, p, expandstr(ps4val()));
8839 for (n = 0; n < 2; n++) {
8841 fdprintf(preverrout_fd, p, sp->text);
8849 safe_write(preverrout_fd, "\n", 1);
8855 /* Now locate the command. */
8857 const char *oldpath;
8858 int cmd_flag = DO_ERR;
8863 find_command(argv[0], &cmdentry, cmd_flag, path);
8864 if (cmdentry.cmdtype == CMDUNKNOWN) {
8870 /* implement bltin and command here */
8871 if (cmdentry.cmdtype != CMDBUILTIN)
8874 spclbltin = IS_BUILTIN_SPECIAL(cmdentry.u.cmd);
8875 if (cmdentry.u.cmd == EXECCMD)
8877 #if ENABLE_ASH_CMDCMD
8878 if (cmdentry.u.cmd == COMMANDCMD) {
8880 nargv = parse_command_args(argv, &path);
8883 argc -= nargv - argv;
8885 cmd_flag |= DO_NOFUNC;
8893 /* We have a redirection error. */
8895 raise_exception(EXERROR);
8897 exitstatus = status;
8901 /* Execute the command. */
8902 switch (cmdentry.cmdtype) {
8905 #if ENABLE_FEATURE_SH_NOFORK
8906 /* Hmmm... shouldn't it happen somewhere in forkshell() instead?
8907 * Why "fork off a child process if necessary" doesn't apply to NOFORK? */
8909 /* find_command() encodes applet_no as (-2 - applet_no) */
8910 int applet_no = (- cmdentry.u.index - 2);
8911 if (applet_no >= 0 && APPLET_IS_NOFORK(applet_no)) {
8912 listsetvar(varlist.list, VEXPORT|VSTACK);
8913 /* run <applet>_main() */
8914 exitstatus = run_nofork_applet(applet_no, argv);
8919 /* Fork off a child process if necessary. */
8920 if (!(flags & EV_EXIT) || trap[0]) {
8922 jp = makejob(/*cmd,*/ 1);
8923 if (forkshell(jp, cmd, FORK_FG) != 0) {
8924 exitstatus = waitforjob(jp);
8930 listsetvar(varlist.list, VEXPORT|VSTACK);
8931 shellexec(argv, path, cmdentry.u.index);
8935 cmdenviron = varlist.list;
8937 struct strlist *list = cmdenviron;
8939 if (spclbltin > 0 || argc == 0) {
8941 if (cmd_is_exec && argc > 1)
8944 listsetvar(list, i);
8946 /* Tight loop with builtins only:
8947 * "while kill -0 $child; do true; done"
8948 * will never exit even if $child died, unless we do this
8949 * to reap the zombie and make kill detect that it's gone: */
8950 dowait(DOWAIT_NONBLOCK, NULL);
8952 if (evalbltin(cmdentry.u.cmd, argc, argv)) {
8959 exit_status = 128 + SIGINT;
8961 exit_status = 128 + pendingsig;
8962 exitstatus = exit_status;
8963 if (i == EXINT || spclbltin > 0) {
8965 longjmp(exception_handler->loc, 1);
8972 listsetvar(varlist.list, 0);
8973 /* See above for the rationale */
8974 dowait(DOWAIT_NONBLOCK, NULL);
8975 if (evalfun(cmdentry.u.func, argc, argv, flags))
8981 popredir(/*drop:*/ cmd_is_exec, /*restore:*/ cmd_is_exec);
8983 /* dsl: I think this is intended to be used to support
8984 * '_' in 'vi' command mode during line editing...
8985 * However I implemented that within libedit itself.
8987 setvar("_", lastarg, 0);
8989 popstackmark(&smark);
8993 evalbltin(const struct builtincmd *cmd, int argc, char **argv)
8995 char *volatile savecmdname;
8996 struct jmploc *volatile savehandler;
8997 struct jmploc jmploc;
9000 savecmdname = commandname;
9001 i = setjmp(jmploc.loc);
9004 savehandler = exception_handler;
9005 exception_handler = &jmploc;
9006 commandname = argv[0];
9008 optptr = NULL; /* initialize nextopt */
9009 exitstatus = (*cmd->builtin)(argc, argv);
9010 flush_stdout_stderr();
9012 exitstatus |= ferror(stdout);
9014 commandname = savecmdname;
9016 exception_handler = savehandler;
9022 goodname(const char *p)
9024 return !*endofname(p);
9029 * Search for a command. This is called before we fork so that the
9030 * location of the command will be available in the parent as well as
9031 * the child. The check for "goodname" is an overly conservative
9032 * check that the name will not be subject to expansion.
9035 prehash(union node *n)
9037 struct cmdentry entry;
9039 if (n->type == NCMD && n->ncmd.args && goodname(n->ncmd.args->narg.text))
9040 find_command(n->ncmd.args->narg.text, &entry, 0, pathval());
9044 /* ============ Builtin commands
9046 * Builtin commands whose functions are closely tied to evaluation
9047 * are implemented here.
9051 * Handle break and continue commands. Break, continue, and return are
9052 * all handled by setting the evalskip flag. The evaluation routines
9053 * above all check this flag, and if it is set they start skipping
9054 * commands rather than executing them. The variable skipcount is
9055 * the number of loops to break/continue, or the number of function
9056 * levels to return. (The latter is always 1.) It should probably
9057 * be an error to break out of more loops than exist, but it isn't
9058 * in the standard shell so we don't make it one here.
9061 breakcmd(int argc UNUSED_PARAM, char **argv)
9063 int n = argv[1] ? number(argv[1]) : 1;
9066 ash_msg_and_raise_error(illnum, argv[1]);
9070 evalskip = (**argv == 'c') ? SKIPCONT : SKIPBREAK;
9077 /* ============ input.c
9079 * This implements the input routines used by the parser.
9083 INPUT_PUSH_FILE = 1,
9084 INPUT_NOFILE_OK = 2,
9087 static smallint checkkwd;
9088 /* values of checkkwd variable */
9089 #define CHKALIAS 0x1
9094 * Push a string back onto the input at this current parsefile level.
9095 * We handle aliases this way.
9097 #if !ENABLE_ASH_ALIAS
9098 #define pushstring(s, ap) pushstring(s)
9101 pushstring(char *s, struct alias *ap)
9108 if (g_parsefile->strpush) {
9109 sp = ckzalloc(sizeof(*sp));
9110 sp->prev = g_parsefile->strpush;
9112 sp = &(g_parsefile->basestrpush);
9114 g_parsefile->strpush = sp;
9115 sp->prev_string = g_parsefile->next_to_pgetc;
9116 sp->prev_left_in_line = g_parsefile->left_in_line;
9117 #if ENABLE_ASH_ALIAS
9120 ap->flag |= ALIASINUSE;
9124 g_parsefile->next_to_pgetc = s;
9125 g_parsefile->left_in_line = len;
9132 struct strpush *sp = g_parsefile->strpush;
9135 #if ENABLE_ASH_ALIAS
9137 if (g_parsefile->next_to_pgetc[-1] == ' '
9138 || g_parsefile->next_to_pgetc[-1] == '\t'
9140 checkkwd |= CHKALIAS;
9142 if (sp->string != sp->ap->val) {
9145 sp->ap->flag &= ~ALIASINUSE;
9146 if (sp->ap->flag & ALIASDEAD) {
9147 unalias(sp->ap->name);
9151 g_parsefile->next_to_pgetc = sp->prev_string;
9152 g_parsefile->left_in_line = sp->prev_left_in_line;
9153 g_parsefile->strpush = sp->prev;
9154 if (sp != &(g_parsefile->basestrpush))
9159 //FIXME: BASH_COMPAT with "...&" does TWO pungetc():
9160 //it peeks whether it is &>, and then pushes back both chars.
9161 //This function needs to save last *next_to_pgetc to buf[0]
9162 //to make two pungetc() reliable. Currently,
9163 // pgetc (out of buf: does preadfd), pgetc, pungetc, pungetc won't work...
9168 char *buf = g_parsefile->buf;
9170 g_parsefile->next_to_pgetc = buf;
9171 #if ENABLE_FEATURE_EDITING
9173 if (!iflag || g_parsefile->fd != STDIN_FILENO)
9174 nr = nonblock_safe_read(g_parsefile->fd, buf, BUFSIZ - 1);
9176 #if ENABLE_FEATURE_TAB_COMPLETION
9177 line_input_state->path_lookup = pathval();
9179 nr = read_line_input(cmdedit_prompt, buf, BUFSIZ, line_input_state);
9181 /* Ctrl+C pressed */
9190 if (nr < 0 && errno == 0) {
9191 /* Ctrl+D pressed */
9196 nr = nonblock_safe_read(g_parsefile->fd, buf, BUFSIZ - 1);
9200 /* nonblock_safe_read() handles this problem */
9202 if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
9203 int flags = fcntl(0, F_GETFL);
9204 if (flags >= 0 && (flags & O_NONBLOCK)) {
9205 flags &= ~O_NONBLOCK;
9206 if (fcntl(0, F_SETFL, flags) >= 0) {
9207 out2str("sh: turning off NDELAY mode\n");
9218 * Refill the input buffer and return the next input character:
9220 * 1) If a string was pushed back on the input, pop it;
9221 * 2) If an EOF was pushed back (g_parsefile->left_in_line < -BIGNUM)
9222 * or we are reading from a string so we can't refill the buffer,
9224 * 3) If the is more stuff in this buffer, use it else call read to fill it.
9225 * 4) Process input up to the next newline, deleting nul characters.
9227 //#define pgetc_debug(...) bb_error_msg(__VA_ARGS__)
9228 #define pgetc_debug(...) ((void)0)
9235 while (g_parsefile->strpush) {
9236 #if ENABLE_ASH_ALIAS
9237 if (g_parsefile->left_in_line == -1
9238 && g_parsefile->strpush->ap
9239 && g_parsefile->next_to_pgetc[-1] != ' '
9240 && g_parsefile->next_to_pgetc[-1] != '\t'
9242 pgetc_debug("preadbuffer PEOA");
9247 /* try "pgetc" now: */
9248 pgetc_debug("preadbuffer internal pgetc at %d:%p'%s'",
9249 g_parsefile->left_in_line,
9250 g_parsefile->next_to_pgetc,
9251 g_parsefile->next_to_pgetc);
9252 if (--g_parsefile->left_in_line >= 0)
9253 return (unsigned char)(*g_parsefile->next_to_pgetc++);
9255 /* on both branches above g_parsefile->left_in_line < 0.
9256 * "pgetc" needs refilling.
9259 /* -90 is our -BIGNUM. Below we use -99 to mark "EOF on read",
9260 * pungetc() may increment it a few times.
9261 * Assuming it won't increment it to less than -90.
9263 if (g_parsefile->left_in_line < -90 || g_parsefile->buf == NULL) {
9264 pgetc_debug("preadbuffer PEOF1");
9265 /* even in failure keep left_in_line and next_to_pgetc
9266 * in lock step, for correct multi-layer pungetc.
9267 * left_in_line was decremented before preadbuffer(),
9268 * must inc next_to_pgetc: */
9269 g_parsefile->next_to_pgetc++;
9273 more = g_parsefile->left_in_buffer;
9275 flush_stdout_stderr();
9279 /* don't try reading again */
9280 g_parsefile->left_in_line = -99;
9281 pgetc_debug("preadbuffer PEOF2");
9282 g_parsefile->next_to_pgetc++;
9287 /* Find out where's the end of line.
9288 * Set g_parsefile->left_in_line
9289 * and g_parsefile->left_in_buffer acordingly.
9290 * NUL chars are deleted.
9292 q = g_parsefile->next_to_pgetc;
9300 memmove(q, q + 1, more);
9304 g_parsefile->left_in_line = q - g_parsefile->next_to_pgetc - 1;
9310 g_parsefile->left_in_line = q - g_parsefile->next_to_pgetc - 1;
9311 if (g_parsefile->left_in_line < 0)
9316 g_parsefile->left_in_buffer = more;
9321 out2str(g_parsefile->next_to_pgetc);
9325 pgetc_debug("preadbuffer at %d:%p'%s'",
9326 g_parsefile->left_in_line,
9327 g_parsefile->next_to_pgetc,
9328 g_parsefile->next_to_pgetc);
9329 return (unsigned char)(*g_parsefile->next_to_pgetc++);
9332 #define pgetc_as_macro() \
9333 (--g_parsefile->left_in_line >= 0 \
9334 ? (unsigned char)(*g_parsefile->next_to_pgetc++) \
9341 pgetc_debug("pgetc_fast at %d:%p'%s'",
9342 g_parsefile->left_in_line,
9343 g_parsefile->next_to_pgetc,
9344 g_parsefile->next_to_pgetc);
9345 return pgetc_as_macro();
9348 #if ENABLE_ASH_OPTIMIZE_FOR_SIZE
9349 #define pgetc_fast() pgetc()
9351 #define pgetc_fast() pgetc_as_macro()
9355 * Same as pgetc(), but ignores PEOA.
9357 #if ENABLE_ASH_ALIAS
9363 pgetc_debug("pgetc_fast at %d:%p'%s'",
9364 g_parsefile->left_in_line,
9365 g_parsefile->next_to_pgetc,
9366 g_parsefile->next_to_pgetc);
9368 } while (c == PEOA);
9372 #define pgetc2() pgetc()
9376 * Read a line from the script.
9379 pfgets(char *line, int len)
9385 while (--nleft > 0) {
9401 * Undo the last call to pgetc. Only one character may be pushed back.
9402 * PEOF may be pushed back.
9407 g_parsefile->left_in_line++;
9408 g_parsefile->next_to_pgetc--;
9409 pgetc_debug("pushed back to %d:%p'%s'",
9410 g_parsefile->left_in_line,
9411 g_parsefile->next_to_pgetc,
9412 g_parsefile->next_to_pgetc);
9416 * To handle the "." command, a stack of input files is used. Pushfile
9417 * adds a new entry to the stack and popfile restores the previous level.
9422 struct parsefile *pf;
9424 pf = ckzalloc(sizeof(*pf));
9425 pf->prev = g_parsefile;
9427 /*pf->strpush = NULL; - ckzalloc did it */
9428 /*pf->basestrpush.prev = NULL;*/
9435 struct parsefile *pf = g_parsefile;
9443 g_parsefile = pf->prev;
9449 * Return to top level.
9454 while (g_parsefile != &basepf)
9459 * Close the file(s) that the shell is reading commands from. Called
9460 * after a fork is done.
9466 if (g_parsefile->fd > 0) {
9467 close(g_parsefile->fd);
9468 g_parsefile->fd = 0;
9473 * Like setinputfile, but takes an open file descriptor. Call this with
9477 setinputfd(int fd, int push)
9479 close_on_exec_on(fd);
9482 g_parsefile->buf = NULL;
9484 g_parsefile->fd = fd;
9485 if (g_parsefile->buf == NULL)
9486 g_parsefile->buf = ckmalloc(IBUFSIZ);
9487 g_parsefile->left_in_buffer = 0;
9488 g_parsefile->left_in_line = 0;
9489 g_parsefile->linno = 1;
9493 * Set the input to take input from a file. If push is set, push the
9494 * old input onto the stack first.
9497 setinputfile(const char *fname, int flags)
9503 fd = open(fname, O_RDONLY);
9505 if (flags & INPUT_NOFILE_OK)
9507 ash_msg_and_raise_error("can't open %s", fname);
9510 fd2 = copyfd(fd, 10);
9513 ash_msg_and_raise_error("out of file descriptors");
9516 setinputfd(fd, flags & INPUT_PUSH_FILE);
9523 * Like setinputfile, but takes input from a string.
9526 setinputstring(char *string)
9530 g_parsefile->next_to_pgetc = string;
9531 g_parsefile->left_in_line = strlen(string);
9532 g_parsefile->buf = NULL;
9533 g_parsefile->linno = 1;
9538 /* ============ mail.c
9540 * Routines to check for mail.
9545 #define MAXMBOXES 10
9547 /* times of mailboxes */
9548 static time_t mailtime[MAXMBOXES];
9549 /* Set if MAIL or MAILPATH is changed. */
9550 static smallint mail_var_path_changed;
9553 * Print appropriate message(s) if mail has arrived.
9554 * If mail_var_path_changed is set,
9555 * then the value of MAIL has mail_var_path_changed,
9556 * so we just update the values.
9565 struct stackmark smark;
9568 setstackmark(&smark);
9569 mpath = mpathset() ? mpathval() : mailval();
9570 for (mtp = mailtime; mtp < mailtime + MAXMBOXES; mtp++) {
9571 p = padvance(&mpath, nullstr);
9576 for (q = p; *q; q++)
9582 q[-1] = '\0'; /* delete trailing '/' */
9583 if (stat(p, &statb) < 0) {
9587 if (!mail_var_path_changed && statb.st_mtime != *mtp) {
9590 pathopt ? pathopt : "you have mail"
9593 *mtp = statb.st_mtime;
9595 mail_var_path_changed = 0;
9596 popstackmark(&smark);
9600 changemail(const char *val UNUSED_PARAM)
9602 mail_var_path_changed = 1;
9605 #endif /* ASH_MAIL */
9608 /* ============ ??? */
9611 * Set the shell parameters.
9614 setparam(char **argv)
9620 for (nparam = 0; argv[nparam]; nparam++)
9622 ap = newparam = ckmalloc((nparam + 1) * sizeof(*ap));
9624 *ap++ = ckstrdup(*argv++);
9627 freeparam(&shellparam);
9628 shellparam.malloced = 1;
9629 shellparam.nparam = nparam;
9630 shellparam.p = newparam;
9631 #if ENABLE_ASH_GETOPTS
9632 shellparam.optind = 1;
9633 shellparam.optoff = -1;
9638 * Process shell options. The global variable argptr contains a pointer
9639 * to the argument list; we advance it past the options.
9641 * SUSv3 section 2.8.1 "Consequences of Shell Errors" says:
9642 * For a non-interactive shell, an error condition encountered
9643 * by a special built-in ... shall cause the shell to write a diagnostic message
9644 * to standard error and exit as shown in the following table:
9645 * Error Special Built-In
9647 * Utility syntax error (option or operand error) Shall exit
9649 * However, in bug 1142 (http://busybox.net/bugs/view.php?id=1142)
9650 * we see that bash does not do that (set "finishes" with error code 1 instead,
9651 * and shell continues), and people rely on this behavior!
9653 * set -o barfoo 2>/dev/null
9656 * Oh well. Let's mimic that.
9659 plus_minus_o(char *name, int val)
9664 for (i = 0; i < NOPTS; i++) {
9665 if (strcmp(name, optnames(i)) == 0) {
9670 ash_msg("illegal option %co %s", val ? '-' : '+', name);
9673 for (i = 0; i < NOPTS; i++) {
9675 out1fmt("%-16s%s\n", optnames(i), optlist[i] ? "on" : "off");
9677 out1fmt("set %co %s\n", optlist[i] ? '-' : '+', optnames(i));
9683 setoption(int flag, int val)
9687 for (i = 0; i < NOPTS; i++) {
9688 if (optletters(i) == flag) {
9693 ash_msg_and_raise_error("illegal option %c%c", val ? '-' : '+', flag);
9697 options(int cmdline)
9705 while ((p = *argptr) != NULL) {
9707 if (c != '-' && c != '+')
9710 val = 0; /* val = 0 if c == '+' */
9713 if (p[0] == '\0' || LONE_DASH(p)) {
9715 /* "-" means turn off -x and -v */
9718 /* "--" means reset params */
9719 else if (*argptr == NULL)
9722 break; /* "-" or "--" terminates options */
9725 /* first char was + or - */
9726 while ((c = *p++) != '\0') {
9727 /* bash 3.2 indeed handles -c CMD and +c CMD the same */
9728 if (c == 'c' && cmdline) {
9729 minusc = p; /* command is after shell args */
9730 } else if (c == 'o') {
9731 if (plus_minus_o(*argptr, val)) {
9732 /* it already printed err message */
9733 return 1; /* error */
9737 } else if (cmdline && (c == 'l')) { /* -l or +l == --login */
9739 /* bash does not accept +-login, we also won't */
9740 } else if (cmdline && val && (c == '-')) { /* long options */
9741 if (strcmp(p, "login") == 0)
9753 * The shift builtin command.
9756 shiftcmd(int argc UNUSED_PARAM, char **argv)
9763 n = number(argv[1]);
9764 if (n > shellparam.nparam)
9765 n = 0; /* bash compat, was = shellparam.nparam; */
9767 shellparam.nparam -= n;
9768 for (ap1 = shellparam.p; --n >= 0; ap1++) {
9769 if (shellparam.malloced)
9773 while ((*ap2++ = *ap1++) != NULL)
9775 #if ENABLE_ASH_GETOPTS
9776 shellparam.optind = 1;
9777 shellparam.optoff = -1;
9784 * POSIX requires that 'set' (but not export or readonly) output the
9785 * variables in lexicographic order - by the locale's collating order (sigh).
9786 * Maybe we could keep them in an ordered balanced binary tree
9787 * instead of hashed lists.
9788 * For now just roll 'em through qsort for printing...
9791 showvars(const char *sep_prefix, int on, int off)
9796 ep = listvars(on, off, &epend);
9797 qsort(ep, epend - ep, sizeof(char *), vpcmp);
9799 sep = *sep_prefix ? " " : sep_prefix;
9801 for (; ep < epend; ep++) {
9805 p = strchrnul(*ep, '=');
9808 q = single_quote(++p);
9809 out1fmt("%s%s%.*s%s\n", sep_prefix, sep, (int)(p - *ep), *ep, q);
9815 * The set command builtin.
9818 setcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9823 return showvars(nullstr, 0, VUNSET);
9826 if (!options(0)) { /* if no parse error... */
9829 if (*argptr != NULL) {
9837 #if ENABLE_ASH_RANDOM_SUPPORT
9839 change_random(const char *value)
9841 /* Galois LFSR parameter */
9842 /* Taps at 32 31 29 1: */
9843 enum { MASK = 0x8000000b };
9844 /* Another example - taps at 32 31 30 10: */
9845 /* MASK = 0x00400007 */
9847 if (value == NULL) {
9848 /* "get", generate */
9851 /* LCG has period of 2^32 and alternating lowest bit */
9852 random_LCG = 1664525 * random_LCG + 1013904223;
9853 /* Galois LFSR has period of 2^32-1 = 3 * 5 * 17 * 257 * 65537 */
9854 t = (random_galois_LFSR << 1);
9855 if (random_galois_LFSR < 0) /* if we just shifted 1 out of msb... */
9857 random_galois_LFSR = t;
9858 /* Both are weak, combining them gives better randomness
9859 * and ~2^64 period. & 0x7fff is probably bash compat
9860 * for $RANDOM range. Combining with subtraction is
9861 * just for fun. + and ^ would work equally well. */
9862 t = (t - random_LCG) & 0x7fff;
9863 /* set without recursion */
9864 setvar(vrandom.text, utoa(t), VNOFUNC);
9865 vrandom.flags &= ~VNOFUNC;
9868 random_galois_LFSR = random_LCG = strtoul(value, (char **)NULL, 10);
9873 #if ENABLE_ASH_GETOPTS
9875 getopts(char *optstr, char *optvar, char **optfirst, int *param_optind, int *optoff)
9884 if (*param_optind < 1)
9886 optnext = optfirst + *param_optind - 1;
9888 if (*param_optind <= 1 || *optoff < 0 || (int)strlen(optnext[-1]) < *optoff)
9891 p = optnext[-1] + *optoff;
9892 if (p == NULL || *p == '\0') {
9893 /* Current word is done, advance */
9895 if (p == NULL || *p != '-' || *++p == '\0') {
9902 if (LONE_DASH(p)) /* check for "--" */
9907 for (q = optstr; *q != c;) {
9909 if (optstr[0] == ':') {
9912 err |= setvarsafe("OPTARG", s, 0);
9914 fprintf(stderr, "Illegal option -%c\n", c);
9925 if (*p == '\0' && (p = *optnext) == NULL) {
9926 if (optstr[0] == ':') {
9929 err |= setvarsafe("OPTARG", s, 0);
9932 fprintf(stderr, "No arg for -%c option\n", c);
9941 err |= setvarsafe("OPTARG", p, 0);
9944 err |= setvarsafe("OPTARG", nullstr, 0);
9946 *optoff = p ? p - *(optnext - 1) : -1;
9947 *param_optind = optnext - optfirst + 1;
9948 fmtstr(s, sizeof(s), "%d", *param_optind);
9949 err |= setvarsafe("OPTIND", s, VNOFUNC);
9952 err |= setvarsafe(optvar, s, 0);
9956 flush_stdout_stderr();
9957 raise_exception(EXERROR);
9963 * The getopts builtin. Shellparam.optnext points to the next argument
9964 * to be processed. Shellparam.optptr points to the next character to
9965 * be processed in the current argument. If shellparam.optnext is NULL,
9966 * then it's the first time getopts has been called.
9969 getoptscmd(int argc, char **argv)
9974 ash_msg_and_raise_error("usage: getopts optstring var [arg]");
9976 optbase = shellparam.p;
9977 if (shellparam.optind > shellparam.nparam + 1) {
9978 shellparam.optind = 1;
9979 shellparam.optoff = -1;
9983 if (shellparam.optind > argc - 2) {
9984 shellparam.optind = 1;
9985 shellparam.optoff = -1;
9989 return getopts(argv[1], argv[2], optbase, &shellparam.optind,
9990 &shellparam.optoff);
9992 #endif /* ASH_GETOPTS */
9995 /* ============ Shell parser */
9998 struct heredoc *next; /* next here document in list */
9999 union node *here; /* redirection node */
10000 char *eofmark; /* string indicating end of input */
10001 smallint striptabs; /* if set, strip leading tabs */
10004 static smallint tokpushback; /* last token pushed back */
10005 static smallint parsebackquote; /* nonzero if we are inside backquotes */
10006 static smallint quoteflag; /* set if (part of) last token was quoted */
10007 static token_id_t lasttoken; /* last token read (integer id Txxx) */
10008 static struct heredoc *heredoclist; /* list of here documents to read */
10009 static char *wordtext; /* text of last word returned by readtoken */
10010 static struct nodelist *backquotelist;
10011 static union node *redirnode;
10012 static struct heredoc *heredoc;
10014 * NEOF is returned by parsecmd when it encounters an end of file. It
10015 * must be distinct from NULL, so we use the address of a variable that
10016 * happens to be handy.
10018 #define NEOF ((union node *)&tokpushback)
10020 static void raise_error_syntax(const char *) NORETURN;
10022 raise_error_syntax(const char *msg)
10024 ash_msg_and_raise_error("syntax error: %s", msg);
10029 * Called when an unexpected token is read during the parse. The argument
10030 * is the token that is expected, or -1 if more than one type of token can
10031 * occur at this point.
10033 static void raise_error_unexpected_syntax(int) NORETURN;
10035 raise_error_unexpected_syntax(int token)
10040 l = sprintf(msg, "unexpected %s", tokname(lasttoken));
10042 sprintf(msg + l, " (expecting %s)", tokname(token));
10043 raise_error_syntax(msg);
10047 #define EOFMARKLEN 79
10049 /* parsing is heavily cross-recursive, need these forward decls */
10050 static union node *andor(void);
10051 static union node *pipeline(void);
10052 static union node *parse_command(void);
10053 static void parseheredoc(void);
10054 static char peektoken(void);
10055 static int readtoken(void);
10057 static union node *
10060 union node *n1, *n2, *n3;
10063 checkkwd = CHKNL | CHKKWD | CHKALIAS;
10064 if (nlflag == 2 && peektoken())
10070 if (tok == TBACKGND) {
10071 if (n2->type == NPIPE) {
10072 n2->npipe.pipe_backgnd = 1;
10074 if (n2->type != NREDIR) {
10075 n3 = stzalloc(sizeof(struct nredir));
10077 /*n3->nredir.redirect = NULL; - stzalloc did it */
10080 n2->type = NBACKGND;
10086 n3 = stzalloc(sizeof(struct nbinary));
10088 n3->nbinary.ch1 = n1;
10089 n3->nbinary.ch2 = n2;
10105 checkkwd = CHKNL | CHKKWD | CHKALIAS;
10113 pungetc(); /* push back EOF on input */
10117 raise_error_unexpected_syntax(-1);
10124 static union node *
10127 union node *n1, *n2, *n3;
10135 } else if (t == TOR) {
10141 checkkwd = CHKNL | CHKKWD | CHKALIAS;
10143 n3 = stzalloc(sizeof(struct nbinary));
10145 n3->nbinary.ch1 = n1;
10146 n3->nbinary.ch2 = n2;
10151 static union node *
10154 union node *n1, *n2, *pipenode;
10155 struct nodelist *lp, *prev;
10159 TRACE(("pipeline: entered\n"));
10160 if (readtoken() == TNOT) {
10162 checkkwd = CHKKWD | CHKALIAS;
10165 n1 = parse_command();
10166 if (readtoken() == TPIPE) {
10167 pipenode = stzalloc(sizeof(struct npipe));
10168 pipenode->type = NPIPE;
10169 /*pipenode->npipe.pipe_backgnd = 0; - stzalloc did it */
10170 lp = stzalloc(sizeof(struct nodelist));
10171 pipenode->npipe.cmdlist = lp;
10175 lp = stzalloc(sizeof(struct nodelist));
10176 checkkwd = CHKNL | CHKKWD | CHKALIAS;
10177 lp->n = parse_command();
10179 } while (readtoken() == TPIPE);
10185 n2 = stzalloc(sizeof(struct nnot));
10193 static union node *
10198 n = stzalloc(sizeof(struct narg));
10200 /*n->narg.next = NULL; - stzalloc did it */
10201 n->narg.text = wordtext;
10202 n->narg.backquote = backquotelist;
10207 fixredir(union node *n, const char *text, int err)
10211 TRACE(("Fix redir %s %d\n", text, err));
10213 n->ndup.vname = NULL;
10215 fd = bb_strtou(text, NULL, 10);
10216 if (!errno && fd >= 0)
10217 n->ndup.dupfd = fd;
10218 else if (LONE_DASH(text))
10219 n->ndup.dupfd = -1;
10222 raise_error_syntax("bad fd number");
10223 n->ndup.vname = makename();
10228 * Returns true if the text contains nothing to expand (no dollar signs
10232 noexpand(char *text)
10238 while ((c = *p++) != '\0') {
10239 if (c == CTLQUOTEMARK)
10243 else if (SIT(c, BASESYNTAX) == CCTL)
10252 union node *n = redirnode;
10254 if (readtoken() != TWORD)
10255 raise_error_unexpected_syntax(-1);
10256 if (n->type == NHERE) {
10257 struct heredoc *here = heredoc;
10261 if (quoteflag == 0)
10263 TRACE(("Here document %d\n", n->type));
10264 if (!noexpand(wordtext) || (i = strlen(wordtext)) == 0 || i > EOFMARKLEN)
10265 raise_error_syntax("illegal eof marker for << redirection");
10266 rmescapes(wordtext);
10267 here->eofmark = wordtext;
10269 if (heredoclist == NULL)
10270 heredoclist = here;
10272 for (p = heredoclist; p->next; p = p->next)
10276 } else if (n->type == NTOFD || n->type == NFROMFD) {
10277 fixredir(n, wordtext, 0);
10279 n->nfile.fname = makename();
10283 static union node *
10286 union node *args, **app;
10287 union node *n = NULL;
10288 union node *vars, **vpp;
10289 union node **rpp, *redir;
10291 #if ENABLE_ASH_BASH_COMPAT
10292 smallint double_brackets_flag = 0;
10302 savecheckkwd = CHKALIAS;
10305 checkkwd = savecheckkwd;
10308 #if ENABLE_ASH_BASH_COMPAT
10309 case TAND: /* "&&" */
10310 case TOR: /* "||" */
10311 if (!double_brackets_flag) {
10315 wordtext = (char *) (t == TAND ? "-a" : "-o");
10318 n = stzalloc(sizeof(struct narg));
10320 /*n->narg.next = NULL; - stzalloc did it */
10321 n->narg.text = wordtext;
10322 #if ENABLE_ASH_BASH_COMPAT
10323 if (strcmp("[[", wordtext) == 0)
10324 double_brackets_flag = 1;
10325 else if (strcmp("]]", wordtext) == 0)
10326 double_brackets_flag = 0;
10328 n->narg.backquote = backquotelist;
10329 if (savecheckkwd && isassignment(wordtext)) {
10331 vpp = &n->narg.next;
10334 app = &n->narg.next;
10339 *rpp = n = redirnode;
10340 rpp = &n->nfile.next;
10341 parsefname(); /* read name of redirection file */
10344 if (args && app == &args->narg.next
10347 struct builtincmd *bcmd;
10350 /* We have a function */
10351 if (readtoken() != TRP)
10352 raise_error_unexpected_syntax(TRP);
10353 name = n->narg.text;
10354 if (!goodname(name)
10355 || ((bcmd = find_builtin(name)) && IS_BUILTIN_SPECIAL(bcmd))
10357 raise_error_syntax("bad function name");
10360 checkkwd = CHKNL | CHKKWD | CHKALIAS;
10361 n->narg.next = parse_command();
10374 n = stzalloc(sizeof(struct ncmd));
10376 n->ncmd.args = args;
10377 n->ncmd.assign = vars;
10378 n->ncmd.redirect = redir;
10382 static union node *
10383 parse_command(void)
10385 union node *n1, *n2;
10386 union node *ap, **app;
10387 union node *cp, **cpp;
10388 union node *redir, **rpp;
10395 switch (readtoken()) {
10397 raise_error_unexpected_syntax(-1);
10400 n1 = stzalloc(sizeof(struct nif));
10402 n1->nif.test = list(0);
10403 if (readtoken() != TTHEN)
10404 raise_error_unexpected_syntax(TTHEN);
10405 n1->nif.ifpart = list(0);
10407 while (readtoken() == TELIF) {
10408 n2->nif.elsepart = stzalloc(sizeof(struct nif));
10409 n2 = n2->nif.elsepart;
10411 n2->nif.test = list(0);
10412 if (readtoken() != TTHEN)
10413 raise_error_unexpected_syntax(TTHEN);
10414 n2->nif.ifpart = list(0);
10416 if (lasttoken == TELSE)
10417 n2->nif.elsepart = list(0);
10419 n2->nif.elsepart = NULL;
10427 n1 = stzalloc(sizeof(struct nbinary));
10428 n1->type = (lasttoken == TWHILE) ? NWHILE : NUNTIL;
10429 n1->nbinary.ch1 = list(0);
10432 TRACE(("expecting DO got %s %s\n", tokname(got),
10433 got == TWORD ? wordtext : ""));
10434 raise_error_unexpected_syntax(TDO);
10436 n1->nbinary.ch2 = list(0);
10441 if (readtoken() != TWORD || quoteflag || !goodname(wordtext))
10442 raise_error_syntax("bad for loop variable");
10443 n1 = stzalloc(sizeof(struct nfor));
10445 n1->nfor.var = wordtext;
10446 checkkwd = CHKKWD | CHKALIAS;
10447 if (readtoken() == TIN) {
10449 while (readtoken() == TWORD) {
10450 n2 = stzalloc(sizeof(struct narg));
10452 /*n2->narg.next = NULL; - stzalloc did it */
10453 n2->narg.text = wordtext;
10454 n2->narg.backquote = backquotelist;
10456 app = &n2->narg.next;
10459 n1->nfor.args = ap;
10460 if (lasttoken != TNL && lasttoken != TSEMI)
10461 raise_error_unexpected_syntax(-1);
10463 n2 = stzalloc(sizeof(struct narg));
10465 /*n2->narg.next = NULL; - stzalloc did it */
10466 n2->narg.text = (char *)dolatstr;
10467 /*n2->narg.backquote = NULL;*/
10468 n1->nfor.args = n2;
10470 * Newline or semicolon here is optional (but note
10471 * that the original Bourne shell only allowed NL).
10473 if (lasttoken != TNL && lasttoken != TSEMI)
10476 checkkwd = CHKNL | CHKKWD | CHKALIAS;
10477 if (readtoken() != TDO)
10478 raise_error_unexpected_syntax(TDO);
10479 n1->nfor.body = list(0);
10483 n1 = stzalloc(sizeof(struct ncase));
10485 if (readtoken() != TWORD)
10486 raise_error_unexpected_syntax(TWORD);
10487 n1->ncase.expr = n2 = stzalloc(sizeof(struct narg));
10489 /*n2->narg.next = NULL; - stzalloc did it */
10490 n2->narg.text = wordtext;
10491 n2->narg.backquote = backquotelist;
10493 checkkwd = CHKKWD | CHKALIAS;
10494 } while (readtoken() == TNL);
10495 if (lasttoken != TIN)
10496 raise_error_unexpected_syntax(TIN);
10497 cpp = &n1->ncase.cases;
10499 checkkwd = CHKNL | CHKKWD;
10501 while (t != TESAC) {
10502 if (lasttoken == TLP)
10504 *cpp = cp = stzalloc(sizeof(struct nclist));
10506 app = &cp->nclist.pattern;
10508 *app = ap = stzalloc(sizeof(struct narg));
10510 /*ap->narg.next = NULL; - stzalloc did it */
10511 ap->narg.text = wordtext;
10512 ap->narg.backquote = backquotelist;
10513 if (readtoken() != TPIPE)
10515 app = &ap->narg.next;
10518 //ap->narg.next = NULL;
10519 if (lasttoken != TRP)
10520 raise_error_unexpected_syntax(TRP);
10521 cp->nclist.body = list(2);
10523 cpp = &cp->nclist.next;
10525 checkkwd = CHKNL | CHKKWD;
10529 raise_error_unexpected_syntax(TENDCASE);
10536 n1 = stzalloc(sizeof(struct nredir));
10537 n1->type = NSUBSHELL;
10538 n1->nredir.n = list(0);
10539 /*n1->nredir.redirect = NULL; - stzalloc did it */
10549 return simplecmd();
10552 if (readtoken() != t)
10553 raise_error_unexpected_syntax(t);
10556 /* Now check for redirection which may follow command */
10557 checkkwd = CHKKWD | CHKALIAS;
10559 while (readtoken() == TREDIR) {
10560 *rpp = n2 = redirnode;
10561 rpp = &n2->nfile.next;
10567 if (n1->type != NSUBSHELL) {
10568 n2 = stzalloc(sizeof(struct nredir));
10573 n1->nredir.redirect = redir;
10578 #if ENABLE_ASH_BASH_COMPAT
10579 static int decode_dollar_squote(void)
10581 static const char C_escapes[] ALIGN1 = "nrbtfav""x\\01234567";
10587 p = strchr(C_escapes, c);
10592 if ((unsigned char)(c - '0') <= 7) { /* \ooo */
10596 } while ((unsigned char)(c - '0') <= 7 && --cnt);
10598 } else if (c == 'x') { /* \xHH */
10602 } while (isxdigit(c) && --cnt);
10604 if (cnt == 3) { /* \x but next char is "bad" */
10608 } else { /* simple seq like \\ or \t */
10613 c = bb_process_escape_sequence((void*)&p);
10614 } else { /* unrecognized "\z": print both chars unless ' or " */
10615 if (c != '\'' && c != '"') {
10617 c |= 0x100; /* "please encode \, then me" */
10625 * If eofmark is NULL, read a word or a redirection symbol. If eofmark
10626 * is not NULL, read a here document. In the latter case, eofmark is the
10627 * word which marks the end of the document and striptabs is true if
10628 * leading tabs should be stripped from the document. The argument firstc
10629 * is the first character of the input token or document.
10631 * Because C does not have internal subroutines, I have simulated them
10632 * using goto's to implement the subroutine linkage. The following macros
10633 * will run code that appears at the end of readtoken1.
10635 #define CHECKEND() {goto checkend; checkend_return:;}
10636 #define PARSEREDIR() {goto parseredir; parseredir_return:;}
10637 #define PARSESUB() {goto parsesub; parsesub_return:;}
10638 #define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
10639 #define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
10640 #define PARSEARITH() {goto parsearith; parsearith_return:;}
10642 readtoken1(int firstc, int syntax, char *eofmark, int striptabs)
10644 /* NB: syntax parameter fits into smallint */
10648 char line[EOFMARKLEN + 1];
10649 struct nodelist *bqlist;
10653 smallint prevsyntax; /* syntax before arithmetic */
10654 #if ENABLE_ASH_EXPAND_PRMT
10655 smallint pssyntax; /* we are expanding a prompt string */
10657 int varnest; /* levels of variables expansion */
10658 int arinest; /* levels of arithmetic expansion */
10659 int parenlevel; /* levels of parens in arithmetic */
10660 int dqvarnest; /* levels of variables expansion within double quotes */
10662 USE_ASH_BASH_COMPAT(smallint bash_dollar_squote = 0;)
10665 /* Avoid longjmp clobbering */
10671 (void) &parenlevel;
10674 (void) &prevsyntax;
10677 startlinno = g_parsefile->linno;
10682 #if ENABLE_ASH_EXPAND_PRMT
10683 pssyntax = (syntax == PSSYNTAX);
10687 dblquote = (syntax == DQSYNTAX);
10693 STARTSTACKSTR(out);
10695 /* For each line, until end of word */
10697 CHECKEND(); /* set c to PEOF if at end of here document */
10698 for (;;) { /* until end of line or end of word */
10699 CHECKSTRSPACE(4, out); /* permit 4 calls to USTPUTC */
10700 switch (SIT(c, syntax)) {
10701 case CNL: /* '\n' */
10702 if (syntax == BASESYNTAX)
10703 goto endword; /* exit outer loop */
10705 g_parsefile->linno++;
10709 goto loop; /* continue outer loop */
10714 if (eofmark == NULL || dblquote)
10715 USTPUTC(CTLESC, out);
10716 #if ENABLE_ASH_BASH_COMPAT
10717 if (c == '\\' && bash_dollar_squote) {
10718 c = decode_dollar_squote();
10720 USTPUTC('\\', out);
10721 c = (unsigned char)c;
10727 case CBACK: /* backslash */
10730 USTPUTC(CTLESC, out);
10731 USTPUTC('\\', out);
10733 } else if (c == '\n') {
10737 #if ENABLE_ASH_EXPAND_PRMT
10738 if (c == '$' && pssyntax) {
10739 USTPUTC(CTLESC, out);
10740 USTPUTC('\\', out);
10743 if (dblquote && c != '\\'
10744 && c != '`' && c != '$'
10745 && (c != '"' || eofmark != NULL)
10747 USTPUTC(CTLESC, out);
10748 USTPUTC('\\', out);
10750 if (SIT(c, SQSYNTAX) == CCTL)
10751 USTPUTC(CTLESC, out);
10759 if (eofmark == NULL) {
10760 USTPUTC(CTLQUOTEMARK, out);
10768 USE_ASH_BASH_COMPAT(bash_dollar_squote = 0;)
10769 if (eofmark != NULL && arinest == 0
10774 if (dqvarnest == 0) {
10775 syntax = BASESYNTAX;
10782 case CVAR: /* '$' */
10783 PARSESUB(); /* parse substitution */
10785 case CENDVAR: /* '}' */
10788 if (dqvarnest > 0) {
10791 USTPUTC(CTLENDVAR, out);
10796 #if ENABLE_ASH_MATH_SUPPORT
10797 case CLP: /* '(' in arithmetic */
10801 case CRP: /* ')' in arithmetic */
10802 if (parenlevel > 0) {
10806 if (pgetc() == ')') {
10807 if (--arinest == 0) {
10808 USTPUTC(CTLENDARI, out);
10809 syntax = prevsyntax;
10810 dblquote = (syntax == DQSYNTAX);
10815 * unbalanced parens
10816 * (don't 2nd guess - no error)
10824 case CBQUOTE: /* '`' */
10828 goto endword; /* exit outer loop */
10832 if (varnest == 0) {
10833 #if ENABLE_ASH_BASH_COMPAT
10835 if (pgetc() == '>')
10836 c = 0x100 + '>'; /* flag &> */
10840 goto endword; /* exit outer loop */
10842 #if ENABLE_ASH_ALIAS
10852 #if ENABLE_ASH_MATH_SUPPORT
10853 if (syntax == ARISYNTAX)
10854 raise_error_syntax("missing '))'");
10856 if (syntax != BASESYNTAX && !parsebackquote && eofmark == NULL)
10857 raise_error_syntax("unterminated quoted string");
10858 if (varnest != 0) {
10859 startlinno = g_parsefile->linno;
10861 raise_error_syntax("missing '}'");
10863 USTPUTC('\0', out);
10864 len = out - (char *)stackblock();
10865 out = stackblock();
10866 if (eofmark == NULL) {
10867 if ((c == '>' || c == '<' USE_ASH_BASH_COMPAT( || c == 0x100 + '>'))
10870 if (isdigit_str9(out)) {
10871 PARSEREDIR(); /* passed as params: out, c */
10872 lasttoken = TREDIR;
10875 /* else: non-number X seen, interpret it
10876 * as "NNNX>file" = "NNNX >file" */
10880 quoteflag = quotef;
10881 backquotelist = bqlist;
10882 grabstackblock(len);
10886 /* end of readtoken routine */
10889 * Check to see whether we are at the end of the here document. When this
10890 * is called, c is set to the first character of the next input line. If
10891 * we are at the end of the here document, this routine sets the c to PEOF.
10895 #if ENABLE_ASH_ALIAS
10901 while (c == '\t') {
10905 if (c == *eofmark) {
10906 if (pfgets(line, sizeof(line)) != NULL) {
10910 for (q = eofmark + 1; *q && *p == *q; p++, q++)
10912 if (*p == '\n' && *q == '\0') {
10914 g_parsefile->linno++;
10915 needprompt = doprompt;
10917 pushstring(line, NULL);
10922 goto checkend_return;
10926 * Parse a redirection operator. The variable "out" points to a string
10927 * specifying the fd to be redirected. The variable "c" contains the
10928 * first character of the redirection operator.
10931 /* out is already checked to be a valid number or "" */
10932 int fd = (*out == '\0' ? -1 : atoi(out));
10935 np = stzalloc(sizeof(struct nfile));
10940 np->type = NAPPEND;
10942 np->type = NCLOBBER;
10945 /* it also can be NTO2 (>&file), but we can't figure it out yet */
10951 #if ENABLE_ASH_BASH_COMPAT
10952 else if (c == 0x100 + '>') { /* this flags &> redirection */
10954 pgetc(); /* this is '>', no need to check */
10958 else { /* c == '<' */
10959 /*np->nfile.fd = 0; - stzalloc did it */
10963 if (sizeof(struct nfile) != sizeof(struct nhere)) {
10964 np = stzalloc(sizeof(struct nhere));
10965 /*np->nfile.fd = 0; - stzalloc did it */
10968 heredoc = stzalloc(sizeof(struct heredoc));
10969 heredoc->here = np;
10972 heredoc->striptabs = 1;
10974 /*heredoc->striptabs = 0; - stzalloc did it */
10980 np->type = NFROMFD;
10984 np->type = NFROMTO;
10996 goto parseredir_return;
11000 * Parse a substitution. At this point, we have read the dollar sign
11001 * and nothing else.
11004 /* is_special(c) evaluates to 1 for c in "!#$*-0123456789?@"; 0 otherwise
11005 * (assuming ascii char codes, as the original implementation did) */
11006 #define is_special(c) \
11007 (((unsigned)(c) - 33 < 32) \
11008 && ((0xc1ff920dU >> ((unsigned)(c) - 33)) & 1))
11014 static const char types[] ALIGN1 = "}-+?=";
11017 if (c <= PEOA_OR_PEOF
11018 || (c != '(' && c != '{' && !is_name(c) && !is_special(c))
11020 #if ENABLE_ASH_BASH_COMPAT
11022 bash_dollar_squote = 1;
11027 } else if (c == '(') { /* $(command) or $((arith)) */
11028 if (pgetc() == '(') {
11029 #if ENABLE_ASH_MATH_SUPPORT
11032 raise_error_syntax("you disabled math support for $((arith)) syntax");
11039 USTPUTC(CTLVAR, out);
11040 typeloc = out - (char *)stackblock();
11041 USTPUTC(VSNORMAL, out);
11042 subtype = VSNORMAL;
11050 subtype = VSLENGTH;
11054 if (c > PEOA_OR_PEOF && is_name(c)) {
11058 } while (c > PEOA_OR_PEOF && is_in_name(c));
11059 } else if (isdigit(c)) {
11063 } while (isdigit(c));
11064 } else if (is_special(c)) {
11069 raise_error_syntax("bad substitution");
11074 if (subtype == 0) {
11078 #if ENABLE_ASH_BASH_COMPAT
11079 if (c == ':' || c == '$' || isdigit(c)) {
11081 subtype = VSSUBSTR;
11088 p = strchr(types, c);
11091 subtype = p - types + VSNORMAL;
11096 subtype = c == '#' ? VSTRIMLEFT : VSTRIMRIGHT;
11104 #if ENABLE_ASH_BASH_COMPAT
11106 subtype = VSREPLACE;
11109 subtype++; /* VSREPLACEALL */
11118 if (dblquote || arinest)
11120 *((char *)stackblock() + typeloc) = subtype | flags;
11121 if (subtype != VSNORMAL) {
11123 if (dblquote || arinest) {
11128 goto parsesub_return;
11132 * Called to parse command substitutions. Newstyle is set if the command
11133 * is enclosed inside $(...); nlpp is a pointer to the head of the linked
11134 * list of commands (passed by reference), and savelen is the number of
11135 * characters on the top of the stack which must be preserved.
11138 struct nodelist **nlpp;
11141 char *volatile str;
11142 struct jmploc jmploc;
11143 struct jmploc *volatile savehandler;
11145 smallint saveprompt = 0;
11148 (void) &saveprompt;
11150 savepbq = parsebackquote;
11151 if (setjmp(jmploc.loc)) {
11153 parsebackquote = 0;
11154 exception_handler = savehandler;
11155 longjmp(exception_handler->loc, 1);
11159 savelen = out - (char *)stackblock();
11161 str = ckmalloc(savelen);
11162 memcpy(str, stackblock(), savelen);
11164 savehandler = exception_handler;
11165 exception_handler = &jmploc;
11168 /* We must read until the closing backquote, giving special
11169 treatment to some slashes, and then push the string and
11170 reread it as input, interpreting it normally. */
11177 STARTSTACKSTR(pout);
11190 g_parsefile->linno++;
11194 * If eating a newline, avoid putting
11195 * the newline into the new character
11196 * stream (via the STPUTC after the
11201 if (pc != '\\' && pc != '`' && pc != '$'
11202 && (!dblquote || pc != '"'))
11203 STPUTC('\\', pout);
11204 if (pc > PEOA_OR_PEOF) {
11210 #if ENABLE_ASH_ALIAS
11213 startlinno = g_parsefile->linno;
11214 raise_error_syntax("EOF in backquote substitution");
11217 g_parsefile->linno++;
11218 needprompt = doprompt;
11227 STPUTC('\0', pout);
11228 psavelen = pout - (char *)stackblock();
11229 if (psavelen > 0) {
11230 pstr = grabstackstr(pout);
11231 setinputstring(pstr);
11236 nlpp = &(*nlpp)->next;
11237 *nlpp = stzalloc(sizeof(**nlpp));
11238 /* (*nlpp)->next = NULL; - stzalloc did it */
11239 parsebackquote = oldstyle;
11242 saveprompt = doprompt;
11249 doprompt = saveprompt;
11250 else if (readtoken() != TRP)
11251 raise_error_unexpected_syntax(TRP);
11256 * Start reading from old file again, ignoring any pushed back
11257 * tokens left from the backquote parsing
11262 while (stackblocksize() <= savelen)
11264 STARTSTACKSTR(out);
11266 memcpy(out, str, savelen);
11267 STADJUST(savelen, out);
11273 parsebackquote = savepbq;
11274 exception_handler = savehandler;
11275 if (arinest || dblquote)
11276 USTPUTC(CTLBACKQ | CTLQUOTE, out);
11278 USTPUTC(CTLBACKQ, out);
11280 goto parsebackq_oldreturn;
11281 goto parsebackq_newreturn;
11284 #if ENABLE_ASH_MATH_SUPPORT
11286 * Parse an arithmetic expansion (indicate start of one and set state)
11289 if (++arinest == 1) {
11290 prevsyntax = syntax;
11291 syntax = ARISYNTAX;
11292 USTPUTC(CTLARI, out);
11299 * we collapse embedded arithmetic expansion to
11300 * parenthesis, which should be equivalent
11304 goto parsearith_return;
11308 } /* end of readtoken */
11311 * Read the next input token.
11312 * If the token is a word, we set backquotelist to the list of cmds in
11313 * backquotes. We set quoteflag to true if any part of the word was
11315 * If the token is TREDIR, then we set redirnode to a structure containing
11317 * In all cases, the variable startlinno is set to the number of the line
11318 * on which the token starts.
11320 * [Change comment: here documents and internal procedures]
11321 * [Readtoken shouldn't have any arguments. Perhaps we should make the
11322 * word parsing code into a separate routine. In this case, readtoken
11323 * doesn't need to have any internal procedures, but parseword does.
11324 * We could also make parseoperator in essence the main routine, and
11325 * have parseword (readtoken1?) handle both words and redirection.]
11327 #define NEW_xxreadtoken
11328 #ifdef NEW_xxreadtoken
11329 /* singles must be first! */
11330 static const char xxreadtoken_chars[7] ALIGN1 = {
11331 '\n', '(', ')', /* singles */
11332 '&', '|', ';', /* doubles */
11336 #define xxreadtoken_singles 3
11337 #define xxreadtoken_doubles 3
11339 static const char xxreadtoken_tokens[] ALIGN1 = {
11340 TNL, TLP, TRP, /* only single occurrence allowed */
11341 TBACKGND, TPIPE, TSEMI, /* if single occurrence */
11342 TEOF, /* corresponds to trailing nul */
11343 TAND, TOR, TENDCASE /* if double occurrence */
11358 startlinno = g_parsefile->linno;
11359 for (;;) { /* until token or start of word found */
11361 if (c == ' ' || c == '\t' USE_ASH_ALIAS( || c == PEOA))
11365 while ((c = pgetc()) != '\n' && c != PEOF)
11368 } else if (c == '\\') {
11369 if (pgetc() != '\n') {
11371 break; /* return readtoken1(...) */
11373 startlinno = ++g_parsefile->linno;
11379 p = xxreadtoken_chars + sizeof(xxreadtoken_chars) - 1;
11382 g_parsefile->linno++;
11383 needprompt = doprompt;
11386 p = strchr(xxreadtoken_chars, c);
11388 break; /* return readtoken1(...) */
11390 if ((int)(p - xxreadtoken_chars) >= xxreadtoken_singles) {
11392 if (cc == c) { /* double occurrence? */
11393 p += xxreadtoken_doubles + 1;
11396 #if ENABLE_ASH_BASH_COMPAT
11397 if (c == '&' && cc == '>') /* &> */
11398 break; /* return readtoken1(...) */
11403 lasttoken = xxreadtoken_tokens[p - xxreadtoken_chars];
11408 return readtoken1(c, BASESYNTAX, (char *) NULL, 0);
11410 #else /* old xxreadtoken */
11411 #define RETURN(token) return lasttoken = token
11424 startlinno = g_parsefile->linno;
11425 for (;;) { /* until token or start of word found */
11428 case ' ': case '\t':
11429 #if ENABLE_ASH_ALIAS
11434 while ((c = pgetc()) != '\n' && c != PEOF)
11439 if (pgetc() == '\n') {
11440 startlinno = ++g_parsefile->linno;
11448 g_parsefile->linno++;
11449 needprompt = doprompt;
11454 if (pgetc() == '&')
11459 if (pgetc() == '|')
11464 if (pgetc() == ';')
11477 return readtoken1(c, BASESYNTAX, (char *)NULL, 0);
11480 #endif /* old xxreadtoken */
11487 smallint alreadyseen = tokpushback;
11490 #if ENABLE_ASH_ALIAS
11499 if (checkkwd & CHKNL) {
11506 if (t != TWORD || quoteflag) {
11511 * check for keywords
11513 if (checkkwd & CHKKWD) {
11514 const char *const *pp;
11516 pp = findkwd(wordtext);
11518 lasttoken = t = pp - tokname_array;
11519 TRACE(("keyword %s recognized\n", tokname(t)));
11524 if (checkkwd & CHKALIAS) {
11525 #if ENABLE_ASH_ALIAS
11527 ap = lookupalias(wordtext, 1);
11530 pushstring(ap->val, ap);
11540 TRACE(("token %s %s\n", tokname(t), t == TWORD ? wordtext : ""));
11542 TRACE(("reread token %s %s\n", tokname(t), t == TWORD ? wordtext : ""));
11554 return tokname_array[t][0];
11558 * Read and parse a command. Returns NEOF on end of file. (NULL is a
11559 * valid parse tree indicating a blank line.)
11561 static union node *
11562 parsecmd(int interact)
11567 doprompt = interact;
11569 setprompt(doprompt);
11581 * Input any here documents.
11586 struct heredoc *here;
11589 here = heredoclist;
11590 heredoclist = NULL;
11596 readtoken1(pgetc(), here->here->type == NHERE? SQSYNTAX : DQSYNTAX,
11597 here->eofmark, here->striptabs);
11598 n = stzalloc(sizeof(struct narg));
11599 n->narg.type = NARG;
11600 /*n->narg.next = NULL; - stzalloc did it */
11601 n->narg.text = wordtext;
11602 n->narg.backquote = backquotelist;
11603 here->here->nhere.doc = n;
11610 * called by editline -- any expansions to the prompt should be added here.
11612 #if ENABLE_ASH_EXPAND_PRMT
11613 static const char *
11614 expandstr(const char *ps)
11618 /* XXX Fix (char *) cast. */
11619 setinputstring((char *)ps);
11620 readtoken1(pgetc(), PSSYNTAX, nullstr, 0);
11623 n.narg.type = NARG;
11624 n.narg.next = NULL;
11625 n.narg.text = wordtext;
11626 n.narg.backquote = backquotelist;
11628 expandarg(&n, NULL, 0);
11629 return stackblock();
11634 * Execute a command or commands contained in a string.
11637 evalstring(char *s, int mask)
11640 struct stackmark smark;
11644 setstackmark(&smark);
11647 while ((n = parsecmd(0)) != NEOF) {
11649 popstackmark(&smark);
11662 * The eval command.
11665 evalcmd(int argc UNUSED_PARAM, char **argv)
11674 STARTSTACKSTR(concat);
11676 concat = stack_putstr(p, concat);
11680 STPUTC(' ', concat);
11682 STPUTC('\0', concat);
11683 p = grabstackstr(concat);
11685 evalstring(p, ~SKIPEVAL);
11692 * Read and execute commands. "Top" is nonzero for the top level command
11693 * loop; it turns on prompting if the shell is interactive.
11699 struct stackmark smark;
11703 TRACE(("cmdloop(%d) called\n", top));
11707 setstackmark(&smark);
11710 showjobs(stderr, SHOW_CHANGED);
11713 if (iflag && top) {
11715 #if ENABLE_ASH_MAIL
11719 n = parsecmd(inter);
11720 /* showtree(n); DEBUG */
11722 if (!top || numeof >= 50)
11724 if (!stoppedjobs()) {
11727 out2str("\nUse \"exit\" to leave shell.\n");
11730 } else if (nflag == 0) {
11731 /* job_warning can only be 2,1,0. Here 2->1, 1/0->0 */
11736 popstackmark(&smark);
11741 return skip & SKIPEVAL;
11748 * Take commands from a file. To be compatible we should do a path
11749 * search for the file, which is necessary to find sub-commands.
11752 find_dot_file(char *name)
11755 const char *path = pathval();
11758 /* don't try this for absolute or relative paths */
11759 if (strchr(name, '/'))
11762 while ((fullname = padvance(&path, name)) != NULL) {
11763 if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) {
11765 * Don't bother freeing here, since it will
11766 * be freed by the caller.
11770 stunalloc(fullname);
11773 /* not found in the PATH */
11774 ash_msg_and_raise_error("%s: not found", name);
11779 dotcmd(int argc, char **argv)
11781 struct strlist *sp;
11782 volatile struct shparam saveparam;
11785 for (sp = cmdenviron; sp; sp = sp->next)
11786 setvareq(ckstrdup(sp->text), VSTRFIXED | VTEXTFIXED);
11788 if (argv[1]) { /* That's what SVR2 does */
11789 char *fullname = find_dot_file(argv[1]);
11792 if (argc) { /* argc > 0, argv[0] != NULL */
11793 saveparam = shellparam;
11794 shellparam.malloced = 0;
11795 shellparam.nparam = argc;
11796 shellparam.p = argv;
11799 setinputfile(fullname, INPUT_PUSH_FILE);
11800 commandname = fullname;
11805 freeparam(&shellparam);
11806 shellparam = saveparam;
11808 status = exitstatus;
11814 exitcmd(int argc UNUSED_PARAM, char **argv)
11819 exitstatus = number(argv[1]);
11820 raise_exception(EXEXIT);
11825 * Read a file containing shell functions.
11828 readcmdfile(char *name)
11830 setinputfile(name, INPUT_PUSH_FILE);
11836 /* ============ find_command inplementation */
11839 * Resolve a command name. If you change this routine, you may have to
11840 * change the shellexec routine as well.
11843 find_command(char *name, struct cmdentry *entry, int act, const char *path)
11845 struct tblentry *cmdp;
11852 struct builtincmd *bcmd;
11854 /* If name contains a slash, don't use PATH or hash table */
11855 if (strchr(name, '/') != NULL) {
11856 entry->u.index = -1;
11857 if (act & DO_ABS) {
11858 while (stat(name, &statb) < 0) {
11860 if (errno == EINTR)
11863 entry->cmdtype = CMDUNKNOWN;
11867 entry->cmdtype = CMDNORMAL;
11871 /* #if ENABLE_FEATURE_SH_STANDALONE... moved after builtin check */
11873 updatetbl = (path == pathval());
11876 if (strstr(path, "%builtin") != NULL)
11877 act |= DO_ALTBLTIN;
11880 /* If name is in the table, check answer will be ok */
11881 cmdp = cmdlookup(name, 0);
11882 if (cmdp != NULL) {
11885 switch (cmdp->cmdtype) {
11903 } else if (cmdp->rehash == 0)
11904 /* if not invalidated by cd, we're done */
11908 /* If %builtin not in path, check for builtin next */
11909 bcmd = find_builtin(name);
11911 if (IS_BUILTIN_REGULAR(bcmd))
11912 goto builtin_success;
11913 if (act & DO_ALTPATH) {
11914 if (!(act & DO_ALTBLTIN))
11915 goto builtin_success;
11916 } else if (builtinloc <= 0) {
11917 goto builtin_success;
11921 #if ENABLE_FEATURE_SH_STANDALONE
11923 int applet_no = find_applet_by_name(name);
11924 if (applet_no >= 0) {
11925 entry->cmdtype = CMDNORMAL;
11926 entry->u.index = -2 - applet_no;
11932 /* We have to search path. */
11933 prev = -1; /* where to start */
11934 if (cmdp && cmdp->rehash) { /* doing a rehash */
11935 if (cmdp->cmdtype == CMDBUILTIN)
11938 prev = cmdp->param.index;
11944 while ((fullname = padvance(&path, name)) != NULL) {
11945 stunalloc(fullname);
11946 /* NB: code below will still use fullname
11947 * despite it being "unallocated" */
11950 if (prefix(pathopt, "builtin")) {
11952 goto builtin_success;
11955 if ((act & DO_NOFUNC)
11956 || !prefix(pathopt, "func")
11957 ) { /* ignore unimplemented options */
11961 /* if rehash, don't redo absolute path names */
11962 if (fullname[0] == '/' && idx <= prev) {
11965 TRACE(("searchexec \"%s\": no change\n", name));
11968 while (stat(fullname, &statb) < 0) {
11970 if (errno == EINTR)
11973 if (errno != ENOENT && errno != ENOTDIR)
11977 e = EACCES; /* if we fail, this will be the error */
11978 if (!S_ISREG(statb.st_mode))
11980 if (pathopt) { /* this is a %func directory */
11981 stalloc(strlen(fullname) + 1);
11982 /* NB: stalloc will return space pointed by fullname
11983 * (because we don't have any intervening allocations
11984 * between stunalloc above and this stalloc) */
11985 readcmdfile(fullname);
11986 cmdp = cmdlookup(name, 0);
11987 if (cmdp == NULL || cmdp->cmdtype != CMDFUNCTION)
11988 ash_msg_and_raise_error("%s not defined in %s", name, fullname);
11989 stunalloc(fullname);
11992 TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
11994 entry->cmdtype = CMDNORMAL;
11995 entry->u.index = idx;
11999 cmdp = cmdlookup(name, 1);
12000 cmdp->cmdtype = CMDNORMAL;
12001 cmdp->param.index = idx;
12006 /* We failed. If there was an entry for this command, delete it */
12007 if (cmdp && updatetbl)
12008 delete_cmd_entry();
12010 ash_msg("%s: %s", name, errmsg(e, "not found"));
12011 entry->cmdtype = CMDUNKNOWN;
12016 entry->cmdtype = CMDBUILTIN;
12017 entry->u.cmd = bcmd;
12021 cmdp = cmdlookup(name, 1);
12022 cmdp->cmdtype = CMDBUILTIN;
12023 cmdp->param.cmd = bcmd;
12027 entry->cmdtype = cmdp->cmdtype;
12028 entry->u = cmdp->param;
12032 /* ============ trap.c */
12035 * The trap builtin.
12038 trapcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
12047 for (signo = 0; signo < NSIG; signo++) {
12048 if (trap[signo] != NULL) {
12049 out1fmt("trap -- %s %s\n",
12050 single_quote(trap[signo]),
12051 get_signame(signo));
12060 signo = get_signum(*ap);
12062 ash_msg_and_raise_error("%s: bad trap", *ap);
12065 if (LONE_DASH(action))
12068 action = ckstrdup(action);
12071 trap[signo] = action;
12081 /* ============ Builtins */
12083 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
12085 * Lists available builtins
12088 helpcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
12093 out1fmt("\nBuilt-in commands:\n-------------------\n");
12094 for (col = 0, i = 0; i < ARRAY_SIZE(builtintab); i++) {
12095 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '),
12096 builtintab[i].name + 1);
12102 #if ENABLE_FEATURE_SH_STANDALONE
12104 const char *a = applet_names;
12106 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '), a);
12111 a += strlen(a) + 1;
12116 return EXIT_SUCCESS;
12118 #endif /* FEATURE_SH_EXTRA_QUIET */
12121 * The export and readonly commands.
12124 exportcmd(int argc UNUSED_PARAM, char **argv)
12130 int flag = argv[0][0] == 'r' ? VREADONLY : VEXPORT;
12132 if (nextopt("p") != 'p') {
12137 p = strchr(name, '=');
12141 vp = *findvar(hashvar(name), name);
12147 setvar(name, p, flag);
12148 } while ((name = *++aptr) != NULL);
12152 showvars(argv[0], flag, 0);
12157 * Delete a function if it exists.
12160 unsetfunc(const char *name)
12162 struct tblentry *cmdp;
12164 cmdp = cmdlookup(name, 0);
12165 if (cmdp!= NULL && cmdp->cmdtype == CMDFUNCTION)
12166 delete_cmd_entry();
12170 * The unset builtin command. We unset the function before we unset the
12171 * variable to allow a function to be unset when there is a readonly variable
12172 * with the same name.
12175 unsetcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
12182 while ((i = nextopt("vf")) != '\0') {
12186 for (ap = argptr; *ap; ap++) {
12202 #include <sys/times.h>
12204 static const unsigned char timescmd_str[] ALIGN1 = {
12205 ' ', offsetof(struct tms, tms_utime),
12206 '\n', offsetof(struct tms, tms_stime),
12207 ' ', offsetof(struct tms, tms_cutime),
12208 '\n', offsetof(struct tms, tms_cstime),
12213 timescmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
12215 long clk_tck, s, t;
12216 const unsigned char *p;
12219 clk_tck = sysconf(_SC_CLK_TCK);
12224 t = *(clock_t *)(((char *) &buf) + p[1]);
12226 out1fmt("%ldm%ld.%.3lds%c",
12228 ((t - s * clk_tck) * 1000) / clk_tck,
12230 } while (*(p += 2));
12235 #if ENABLE_ASH_MATH_SUPPORT
12237 dash_arith(const char *s)
12243 result = arith(s, &errcode);
12246 ash_msg_and_raise_error("exponent less than 0");
12248 ash_msg_and_raise_error("divide by zero");
12250 ash_msg_and_raise_error("expression recursion loop detected");
12251 raise_error_syntax(s);
12259 * The let builtin. partial stolen from GNU Bash, the Bourne Again SHell.
12260 * Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
12262 * Copyright (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
12265 letcmd(int argc UNUSED_PARAM, char **argv)
12271 ash_msg_and_raise_error("expression expected");
12273 i = dash_arith(*argv);
12278 #endif /* ASH_MATH_SUPPORT */
12281 /* ============ miscbltin.c
12283 * Miscellaneous builtins.
12288 #if defined(__GLIBC__) && __GLIBC__ == 2 && __GLIBC_MINOR__ < 1
12289 typedef enum __rlimit_resource rlim_t;
12293 * The read builtin. Options:
12294 * -r Do not interpret '\' specially
12295 * -s Turn off echo (tty only)
12296 * -n NCHARS Read NCHARS max
12297 * -p PROMPT Display PROMPT on stderr (if input is from tty)
12298 * -t SECONDS Timeout after SECONDS (tty or pipe only)
12299 * -u FD Read from given FD instead of fd 0
12300 * This uses unbuffered input, which may be avoidable in some cases.
12301 * TODO: bash also has:
12302 * -a ARRAY Read into array[0],[1],etc
12303 * -d DELIM End on DELIM char, not newline
12304 * -e Use line editing (tty only)
12307 readcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
12309 static const char *const arg_REPLY[] = { "REPLY", NULL };
12322 #if ENABLE_ASH_READ_NCHARS
12323 int nchars = 0; /* if != 0, -n is in effect */
12325 struct termios tty, old_tty;
12327 #if ENABLE_ASH_READ_TIMEOUT
12328 unsigned end_ms = 0;
12329 unsigned timeout = 0;
12334 while ((i = nextopt("p:u:r"
12335 USE_ASH_READ_TIMEOUT("t:")
12336 USE_ASH_READ_NCHARS("n:s")
12340 prompt = optionarg;
12342 #if ENABLE_ASH_READ_NCHARS
12344 nchars = bb_strtou(optionarg, NULL, 10);
12345 if (nchars < 0 || errno)
12346 ash_msg_and_raise_error("invalid count");
12347 /* nchars == 0: off (bash 3.2 does this too) */
12353 #if ENABLE_ASH_READ_TIMEOUT
12355 timeout = bb_strtou(optionarg, NULL, 10);
12356 if (errno || timeout > UINT_MAX / 2048)
12357 ash_msg_and_raise_error("invalid timeout");
12359 #if 0 /* even bash have no -t N.NNN support */
12360 ts.tv_sec = bb_strtou(optionarg, &p, 10);
12362 /* EINVAL means number is ok, but not terminated by NUL */
12363 if (*p == '.' && errno == EINVAL) {
12367 ts.tv_usec = bb_strtou(p, &p2, 10);
12369 ash_msg_and_raise_error("invalid timeout");
12371 /* normalize to usec */
12373 ash_msg_and_raise_error("invalid timeout");
12374 while (scale++ < 6)
12377 } else if (ts.tv_sec < 0 || errno) {
12378 ash_msg_and_raise_error("invalid timeout");
12380 if (!(ts.tv_sec | ts.tv_usec)) { /* both are 0? */
12381 ash_msg_and_raise_error("invalid timeout");
12390 fd = bb_strtou(optionarg, NULL, 10);
12391 if (fd < 0 || errno)
12392 ash_msg_and_raise_error("invalid file descriptor");
12398 if (prompt && isatty(fd)) {
12403 ap = (char**)arg_REPLY;
12404 ifs = bltinlookup("IFS");
12407 #if ENABLE_ASH_READ_NCHARS
12408 tcgetattr(fd, &tty);
12410 if (nchars || silent) {
12412 tty.c_lflag &= ~ICANON;
12413 tty.c_cc[VMIN] = nchars < 256 ? nchars : 255;
12416 tty.c_lflag &= ~(ECHO | ECHOK | ECHONL);
12418 /* if tcgetattr failed, tcsetattr will fail too.
12419 * Ignoring, it's harmless. */
12420 tcsetattr(fd, TCSANOW, &tty);
12427 #if ENABLE_ASH_READ_TIMEOUT
12428 if (timeout) /* NB: ensuring end_ms is nonzero */
12429 end_ms = ((unsigned)(monotonic_us() / 1000) + timeout) | 1;
12433 #if ENABLE_ASH_READ_TIMEOUT
12435 struct pollfd pfd[1];
12437 pfd[0].events = POLLIN;
12438 timeout = end_ms - (unsigned)(monotonic_us() / 1000);
12439 if ((int)timeout <= 0 /* already late? */
12440 || safe_poll(pfd, 1, timeout) != 1 /* no? wait... */
12441 ) { /* timed out! */
12442 #if ENABLE_ASH_READ_NCHARS
12443 tcsetattr(fd, TCSANOW, &old_tty);
12449 if (nonblock_safe_read(fd, &c, 1) != 1) {
12461 if (!rflag && c == '\\') {
12467 if (startword && *ifs == ' ' && strchr(ifs, c)) {
12471 if (ap[1] != NULL && strchr(ifs, c) != NULL) {
12473 setvar(*ap, stackblock(), 0);
12482 /* end of do {} while: */
12483 #if ENABLE_ASH_READ_NCHARS
12489 #if ENABLE_ASH_READ_NCHARS
12490 tcsetattr(fd, TCSANOW, &old_tty);
12494 /* Remove trailing blanks */
12495 while ((char *)stackblock() <= --p && strchr(ifs, *p) != NULL)
12497 setvar(*ap, stackblock(), 0);
12498 while (*++ap != NULL)
12499 setvar(*ap, nullstr, 0);
12504 umaskcmd(int argc UNUSED_PARAM, char **argv)
12506 static const char permuser[3] ALIGN1 = "ugo";
12507 static const char permmode[3] ALIGN1 = "rwx";
12508 static const short permmask[] ALIGN2 = {
12509 S_IRUSR, S_IWUSR, S_IXUSR,
12510 S_IRGRP, S_IWGRP, S_IXGRP,
12511 S_IROTH, S_IWOTH, S_IXOTH
12517 int symbolic_mode = 0;
12519 while (nextopt("S") != '\0') {
12530 if (symbolic_mode) {
12534 for (i = 0; i < 3; i++) {
12537 *p++ = permuser[i];
12539 for (j = 0; j < 3; j++) {
12540 if ((mask & permmask[3 * i + j]) == 0) {
12541 *p++ = permmode[j];
12549 out1fmt("%.4o\n", mask);
12552 if (isdigit((unsigned char) *ap)) {
12555 if (*ap >= '8' || *ap < '0')
12556 ash_msg_and_raise_error(illnum, argv[1]);
12557 mask = (mask << 3) + (*ap - '0');
12558 } while (*++ap != '\0');
12561 mask = ~mask & 0777;
12562 if (!bb_parse_mode(ap, &mask)) {
12563 ash_msg_and_raise_error("illegal mode: %s", ap);
12565 umask(~mask & 0777);
12574 * This code, originally by Doug Gwyn, Doug Kingston, Eric Gisin, and
12575 * Michael Rendell was ripped from pdksh 5.0.8 and hacked for use with
12576 * ash by J.T. Conklin.
12582 uint8_t cmd; /* RLIMIT_xxx fit into it */
12583 uint8_t factor_shift; /* shift by to get rlim_{cur,max} values */
12587 static const struct limits limits_tbl[] = {
12589 { RLIMIT_CPU, 0, 't' },
12591 #ifdef RLIMIT_FSIZE
12592 { RLIMIT_FSIZE, 9, 'f' },
12595 { RLIMIT_DATA, 10, 'd' },
12597 #ifdef RLIMIT_STACK
12598 { RLIMIT_STACK, 10, 's' },
12601 { RLIMIT_CORE, 9, 'c' },
12604 { RLIMIT_RSS, 10, 'm' },
12606 #ifdef RLIMIT_MEMLOCK
12607 { RLIMIT_MEMLOCK, 10, 'l' },
12609 #ifdef RLIMIT_NPROC
12610 { RLIMIT_NPROC, 0, 'p' },
12612 #ifdef RLIMIT_NOFILE
12613 { RLIMIT_NOFILE, 0, 'n' },
12616 { RLIMIT_AS, 10, 'v' },
12618 #ifdef RLIMIT_LOCKS
12619 { RLIMIT_LOCKS, 0, 'w' },
12622 static const char limits_name[] =
12624 "time(seconds)" "\0"
12626 #ifdef RLIMIT_FSIZE
12627 "file(blocks)" "\0"
12632 #ifdef RLIMIT_STACK
12636 "coredump(blocks)" "\0"
12641 #ifdef RLIMIT_MEMLOCK
12642 "locked memory(kb)" "\0"
12644 #ifdef RLIMIT_NPROC
12647 #ifdef RLIMIT_NOFILE
12653 #ifdef RLIMIT_LOCKS
12658 enum limtype { SOFT = 0x1, HARD = 0x2 };
12661 printlim(enum limtype how, const struct rlimit *limit,
12662 const struct limits *l)
12666 val = limit->rlim_max;
12668 val = limit->rlim_cur;
12670 if (val == RLIM_INFINITY)
12671 out1fmt("unlimited\n");
12673 val >>= l->factor_shift;
12674 out1fmt("%lld\n", (long long) val);
12679 ulimitcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
12683 enum limtype how = SOFT | HARD;
12684 const struct limits *l;
12687 struct rlimit limit;
12690 while ((optc = nextopt("HSa"
12694 #ifdef RLIMIT_FSIZE
12700 #ifdef RLIMIT_STACK
12709 #ifdef RLIMIT_MEMLOCK
12712 #ifdef RLIMIT_NPROC
12715 #ifdef RLIMIT_NOFILE
12721 #ifdef RLIMIT_LOCKS
12739 for (l = limits_tbl; l->option != what; l++)
12742 set = *argptr ? 1 : 0;
12746 if (all || argptr[1])
12747 ash_msg_and_raise_error("too many arguments");
12748 if (strncmp(p, "unlimited\n", 9) == 0)
12749 val = RLIM_INFINITY;
12753 while ((c = *p++) >= '0' && c <= '9') {
12754 val = (val * 10) + (long)(c - '0');
12755 // val is actually 'unsigned long int' and can't get < 0
12756 if (val < (rlim_t) 0)
12760 ash_msg_and_raise_error("bad number");
12761 val <<= l->factor_shift;
12765 const char *lname = limits_name;
12766 for (l = limits_tbl; l != &limits_tbl[ARRAY_SIZE(limits_tbl)]; l++) {
12767 getrlimit(l->cmd, &limit);
12768 out1fmt("%-20s ", lname);
12769 lname += strlen(lname) + 1;
12770 printlim(how, &limit, l);
12775 getrlimit(l->cmd, &limit);
12778 limit.rlim_max = val;
12780 limit.rlim_cur = val;
12781 if (setrlimit(l->cmd, &limit) < 0)
12782 ash_msg_and_raise_error("error setting limit (%m)");
12784 printlim(how, &limit, l);
12790 /* ============ Math support */
12792 #if ENABLE_ASH_MATH_SUPPORT
12794 /* Copyright (c) 2001 Aaron Lehmann <aaronl@vitelus.com>
12796 Permission is hereby granted, free of charge, to any person obtaining
12797 a copy of this software and associated documentation files (the
12798 "Software"), to deal in the Software without restriction, including
12799 without limitation the rights to use, copy, modify, merge, publish,
12800 distribute, sublicense, and/or sell copies of the Software, and to
12801 permit persons to whom the Software is furnished to do so, subject to
12802 the following conditions:
12804 The above copyright notice and this permission notice shall be
12805 included in all copies or substantial portions of the Software.
12807 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
12808 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
12809 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
12810 IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
12811 CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
12812 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
12813 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
12816 /* This is my infix parser/evaluator. It is optimized for size, intended
12817 * as a replacement for yacc-based parsers. However, it may well be faster
12818 * than a comparable parser written in yacc. The supported operators are
12819 * listed in #defines below. Parens, order of operations, and error handling
12820 * are supported. This code is thread safe. The exact expression format should
12821 * be that which POSIX specifies for shells. */
12823 /* The code uses a simple two-stack algorithm. See
12824 * http://www.onthenet.com.au/~grahamis/int2008/week02/lect02.html
12825 * for a detailed explanation of the infix-to-postfix algorithm on which
12826 * this is based (this code differs in that it applies operators immediately
12827 * to the stack instead of adding them to a queue to end up with an
12830 /* To use the routine, call it with an expression string and error return
12834 * Aug 24, 2001 Manuel Novoa III
12836 * Reduced the generated code size by about 30% (i386) and fixed several bugs.
12838 * 1) In arith_apply():
12839 * a) Cached values of *numptr and &(numptr[-1]).
12840 * b) Removed redundant test for zero denominator.
12843 * a) Eliminated redundant code for processing operator tokens by moving
12844 * to a table-based implementation. Also folded handling of parens
12846 * b) Combined all 3 loops which called arith_apply to reduce generated
12847 * code size at the cost of speed.
12849 * 3) The following expressions were treated as valid by the original code:
12850 * 1() , 0! , 1 ( *3 ) .
12851 * These bugs have been fixed by internally enclosing the expression in
12852 * parens and then checking that all binary ops and right parens are
12853 * preceded by a valid expression (NUM_TOKEN).
12855 * Note: It may be desirable to replace Aaron's test for whitespace with
12856 * ctype's isspace() if it is used by another busybox applet or if additional
12857 * whitespace chars should be considered. Look below the "#include"s for a
12858 * precompiler test.
12862 * Aug 26, 2001 Manuel Novoa III
12864 * Return 0 for null expressions. Pointed out by Vladimir Oleynik.
12866 * Merge in Aaron's comments previously posted to the busybox list,
12867 * modified slightly to take account of my changes to the code.
12872 * (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
12874 * - allow access to variable,
12875 * used recursive find value indirection (c=2*2; a="c"; $((a+=2)) produce 6)
12876 * - realize assign syntax (VAR=expr, +=, *= etc)
12877 * - realize exponentiation (** operator)
12878 * - realize comma separated - expr, expr
12879 * - realise ++expr --expr expr++ expr--
12880 * - realise expr ? expr : expr (but, second expr calculate always)
12881 * - allow hexadecimal and octal numbers
12882 * - was restored loses XOR operator
12883 * - remove one goto label, added three ;-)
12884 * - protect $((num num)) as true zero expr (Manuel`s error)
12885 * - always use special isspace(), see comment from bash ;-)
12888 #define arith_isspace(arithval) \
12889 (arithval == ' ' || arithval == '\n' || arithval == '\t')
12891 typedef unsigned char operator;
12893 /* An operator's token id is a bit of a bitfield. The lower 5 bits are the
12894 * precedence, and 3 high bits are an ID unique across operators of that
12895 * precedence. The ID portion is so that multiple operators can have the
12896 * same precedence, ensuring that the leftmost one is evaluated first.
12897 * Consider * and /. */
12899 #define tok_decl(prec,id) (((id)<<5)|(prec))
12900 #define PREC(op) ((op) & 0x1F)
12902 #define TOK_LPAREN tok_decl(0,0)
12904 #define TOK_COMMA tok_decl(1,0)
12906 #define TOK_ASSIGN tok_decl(2,0)
12907 #define TOK_AND_ASSIGN tok_decl(2,1)
12908 #define TOK_OR_ASSIGN tok_decl(2,2)
12909 #define TOK_XOR_ASSIGN tok_decl(2,3)
12910 #define TOK_PLUS_ASSIGN tok_decl(2,4)
12911 #define TOK_MINUS_ASSIGN tok_decl(2,5)
12912 #define TOK_LSHIFT_ASSIGN tok_decl(2,6)
12913 #define TOK_RSHIFT_ASSIGN tok_decl(2,7)
12915 #define TOK_MUL_ASSIGN tok_decl(3,0)
12916 #define TOK_DIV_ASSIGN tok_decl(3,1)
12917 #define TOK_REM_ASSIGN tok_decl(3,2)
12919 /* all assign is right associativity and precedence eq, but (7+3)<<5 > 256 */
12920 #define convert_prec_is_assing(prec) do { if (prec == 3) prec = 2; } while (0)
12922 /* conditional is right associativity too */
12923 #define TOK_CONDITIONAL tok_decl(4,0)
12924 #define TOK_CONDITIONAL_SEP tok_decl(4,1)
12926 #define TOK_OR tok_decl(5,0)
12928 #define TOK_AND tok_decl(6,0)
12930 #define TOK_BOR tok_decl(7,0)
12932 #define TOK_BXOR tok_decl(8,0)
12934 #define TOK_BAND tok_decl(9,0)
12936 #define TOK_EQ tok_decl(10,0)
12937 #define TOK_NE tok_decl(10,1)
12939 #define TOK_LT tok_decl(11,0)
12940 #define TOK_GT tok_decl(11,1)
12941 #define TOK_GE tok_decl(11,2)
12942 #define TOK_LE tok_decl(11,3)
12944 #define TOK_LSHIFT tok_decl(12,0)
12945 #define TOK_RSHIFT tok_decl(12,1)
12947 #define TOK_ADD tok_decl(13,0)
12948 #define TOK_SUB tok_decl(13,1)
12950 #define TOK_MUL tok_decl(14,0)
12951 #define TOK_DIV tok_decl(14,1)
12952 #define TOK_REM tok_decl(14,2)
12954 /* exponent is right associativity */
12955 #define TOK_EXPONENT tok_decl(15,1)
12957 /* For now unary operators. */
12958 #define UNARYPREC 16
12959 #define TOK_BNOT tok_decl(UNARYPREC,0)
12960 #define TOK_NOT tok_decl(UNARYPREC,1)
12962 #define TOK_UMINUS tok_decl(UNARYPREC+1,0)
12963 #define TOK_UPLUS tok_decl(UNARYPREC+1,1)
12965 #define PREC_PRE (UNARYPREC+2)
12967 #define TOK_PRE_INC tok_decl(PREC_PRE, 0)
12968 #define TOK_PRE_DEC tok_decl(PREC_PRE, 1)
12970 #define PREC_POST (UNARYPREC+3)
12972 #define TOK_POST_INC tok_decl(PREC_POST, 0)
12973 #define TOK_POST_DEC tok_decl(PREC_POST, 1)
12975 #define SPEC_PREC (UNARYPREC+4)
12977 #define TOK_NUM tok_decl(SPEC_PREC, 0)
12978 #define TOK_RPAREN tok_decl(SPEC_PREC, 1)
12980 #define NUMPTR (*numstackptr)
12983 tok_have_assign(operator op)
12985 operator prec = PREC(op);
12987 convert_prec_is_assing(prec);
12988 return (prec == PREC(TOK_ASSIGN) ||
12989 prec == PREC_PRE || prec == PREC_POST);
12993 is_right_associativity(operator prec)
12995 return (prec == PREC(TOK_ASSIGN) || prec == PREC(TOK_EXPONENT)
12996 || prec == PREC(TOK_CONDITIONAL));
13001 arith_t contidional_second_val;
13002 char contidional_second_val_initialized;
13003 char *var; /* if NULL then is regular number,
13004 else is variable name */
13007 typedef struct chk_var_recursive_looped_t {
13009 struct chk_var_recursive_looped_t *next;
13010 } chk_var_recursive_looped_t;
13012 static chk_var_recursive_looped_t *prev_chk_var_recursive;
13015 arith_lookup_val(v_n_t *t)
13018 const char * p = lookupvar(t->var);
13023 /* recursive try as expression */
13024 chk_var_recursive_looped_t *cur;
13025 chk_var_recursive_looped_t cur_save;
13027 for (cur = prev_chk_var_recursive; cur; cur = cur->next) {
13028 if (strcmp(cur->var, t->var) == 0) {
13029 /* expression recursion loop detected */
13033 /* save current lookuped var name */
13034 cur = prev_chk_var_recursive;
13035 cur_save.var = t->var;
13036 cur_save.next = cur;
13037 prev_chk_var_recursive = &cur_save;
13039 t->val = arith (p, &errcode);
13040 /* restore previous ptr after recursiving */
13041 prev_chk_var_recursive = cur;
13044 /* allow undefined var as 0 */
13050 /* "applying" a token means performing it on the top elements on the integer
13051 * stack. For a unary operator it will only change the top element, but a
13052 * binary operator will pop two arguments and push a result */
13054 arith_apply(operator op, v_n_t *numstack, v_n_t **numstackptr)
13057 arith_t numptr_val, rez;
13058 int ret_arith_lookup_val;
13060 /* There is no operator that can work without arguments */
13061 if (NUMPTR == numstack) goto err;
13062 numptr_m1 = NUMPTR - 1;
13064 /* check operand is var with noninteger value */
13065 ret_arith_lookup_val = arith_lookup_val(numptr_m1);
13066 if (ret_arith_lookup_val)
13067 return ret_arith_lookup_val;
13069 rez = numptr_m1->val;
13070 if (op == TOK_UMINUS)
13072 else if (op == TOK_NOT)
13074 else if (op == TOK_BNOT)
13076 else if (op == TOK_POST_INC || op == TOK_PRE_INC)
13078 else if (op == TOK_POST_DEC || op == TOK_PRE_DEC)
13080 else if (op != TOK_UPLUS) {
13081 /* Binary operators */
13083 /* check and binary operators need two arguments */
13084 if (numptr_m1 == numstack) goto err;
13086 /* ... and they pop one */
13089 if (op == TOK_CONDITIONAL) {
13090 if (!numptr_m1->contidional_second_val_initialized) {
13091 /* protect $((expr1 ? expr2)) without ": expr" */
13094 rez = numptr_m1->contidional_second_val;
13095 } else if (numptr_m1->contidional_second_val_initialized) {
13096 /* protect $((expr1 : expr2)) without "expr ? " */
13099 numptr_m1 = NUMPTR - 1;
13100 if (op != TOK_ASSIGN) {
13101 /* check operand is var with noninteger value for not '=' */
13102 ret_arith_lookup_val = arith_lookup_val(numptr_m1);
13103 if (ret_arith_lookup_val)
13104 return ret_arith_lookup_val;
13106 if (op == TOK_CONDITIONAL) {
13107 numptr_m1->contidional_second_val = rez;
13109 rez = numptr_m1->val;
13110 if (op == TOK_BOR || op == TOK_OR_ASSIGN)
13112 else if (op == TOK_OR)
13113 rez = numptr_val || rez;
13114 else if (op == TOK_BAND || op == TOK_AND_ASSIGN)
13116 else if (op == TOK_BXOR || op == TOK_XOR_ASSIGN)
13118 else if (op == TOK_AND)
13119 rez = rez && numptr_val;
13120 else if (op == TOK_EQ)
13121 rez = (rez == numptr_val);
13122 else if (op == TOK_NE)
13123 rez = (rez != numptr_val);
13124 else if (op == TOK_GE)
13125 rez = (rez >= numptr_val);
13126 else if (op == TOK_RSHIFT || op == TOK_RSHIFT_ASSIGN)
13127 rez >>= numptr_val;
13128 else if (op == TOK_LSHIFT || op == TOK_LSHIFT_ASSIGN)
13129 rez <<= numptr_val;
13130 else if (op == TOK_GT)
13131 rez = (rez > numptr_val);
13132 else if (op == TOK_LT)
13133 rez = (rez < numptr_val);
13134 else if (op == TOK_LE)
13135 rez = (rez <= numptr_val);
13136 else if (op == TOK_MUL || op == TOK_MUL_ASSIGN)
13138 else if (op == TOK_ADD || op == TOK_PLUS_ASSIGN)
13140 else if (op == TOK_SUB || op == TOK_MINUS_ASSIGN)
13142 else if (op == TOK_ASSIGN || op == TOK_COMMA)
13144 else if (op == TOK_CONDITIONAL_SEP) {
13145 if (numptr_m1 == numstack) {
13146 /* protect $((expr : expr)) without "expr ? " */
13149 numptr_m1->contidional_second_val_initialized = op;
13150 numptr_m1->contidional_second_val = numptr_val;
13151 } else if (op == TOK_CONDITIONAL) {
13153 numptr_val : numptr_m1->contidional_second_val;
13154 } else if (op == TOK_EXPONENT) {
13155 if (numptr_val < 0)
13156 return -3; /* exponent less than 0 */
13161 while (numptr_val--)
13165 } else if (numptr_val==0) /* zero divisor check */
13167 else if (op == TOK_DIV || op == TOK_DIV_ASSIGN)
13169 else if (op == TOK_REM || op == TOK_REM_ASSIGN)
13172 if (tok_have_assign(op)) {
13173 char buf[sizeof(arith_t_type)*3 + 2];
13175 if (numptr_m1->var == NULL) {
13179 /* save to shell variable */
13180 #if ENABLE_ASH_MATH_SUPPORT_64
13181 snprintf(buf, sizeof(buf), "%lld", (arith_t_type) rez);
13183 snprintf(buf, sizeof(buf), "%ld", (arith_t_type) rez);
13185 setvar(numptr_m1->var, buf, 0);
13186 /* after saving, make previous value for v++ or v-- */
13187 if (op == TOK_POST_INC)
13189 else if (op == TOK_POST_DEC)
13192 numptr_m1->val = rez;
13193 /* protect geting var value, is number now */
13194 numptr_m1->var = NULL;
13200 /* longest must be first */
13201 static const char op_tokens[] ALIGN1 = {
13202 '<','<','=',0, TOK_LSHIFT_ASSIGN,
13203 '>','>','=',0, TOK_RSHIFT_ASSIGN,
13204 '<','<', 0, TOK_LSHIFT,
13205 '>','>', 0, TOK_RSHIFT,
13206 '|','|', 0, TOK_OR,
13207 '&','&', 0, TOK_AND,
13208 '!','=', 0, TOK_NE,
13209 '<','=', 0, TOK_LE,
13210 '>','=', 0, TOK_GE,
13211 '=','=', 0, TOK_EQ,
13212 '|','=', 0, TOK_OR_ASSIGN,
13213 '&','=', 0, TOK_AND_ASSIGN,
13214 '*','=', 0, TOK_MUL_ASSIGN,
13215 '/','=', 0, TOK_DIV_ASSIGN,
13216 '%','=', 0, TOK_REM_ASSIGN,
13217 '+','=', 0, TOK_PLUS_ASSIGN,
13218 '-','=', 0, TOK_MINUS_ASSIGN,
13219 '-','-', 0, TOK_POST_DEC,
13220 '^','=', 0, TOK_XOR_ASSIGN,
13221 '+','+', 0, TOK_POST_INC,
13222 '*','*', 0, TOK_EXPONENT,
13226 '=', 0, TOK_ASSIGN,
13238 '?', 0, TOK_CONDITIONAL,
13239 ':', 0, TOK_CONDITIONAL_SEP,
13240 ')', 0, TOK_RPAREN,
13241 '(', 0, TOK_LPAREN,
13245 #define endexpression (&op_tokens[sizeof(op_tokens)-7])
13248 arith(const char *expr, int *perrcode)
13250 char arithval; /* Current character under analysis */
13251 operator lasttok, op;
13253 operator *stack, *stackptr;
13254 const char *p = endexpression;
13256 v_n_t *numstack, *numstackptr;
13257 unsigned datasizes = strlen(expr) + 2;
13259 /* Stack of integers */
13260 /* The proof that there can be no more than strlen(startbuf)/2+1 integers
13261 * in any given correct or incorrect expression is left as an exercise to
13263 numstackptr = numstack = alloca((datasizes / 2) * sizeof(numstack[0]));
13264 /* Stack of operator tokens */
13265 stackptr = stack = alloca(datasizes * sizeof(stack[0]));
13267 *stackptr++ = lasttok = TOK_LPAREN; /* start off with a left paren */
13268 *perrcode = errcode = 0;
13272 if (arithval == 0) {
13273 if (p == endexpression) {
13274 /* Null expression. */
13278 /* This is only reached after all tokens have been extracted from the
13279 * input stream. If there are still tokens on the operator stack, they
13280 * are to be applied in order. At the end, there should be a final
13281 * result on the integer stack */
13283 if (expr != endexpression + 1) {
13284 /* If we haven't done so already, */
13285 /* append a closing right paren */
13286 expr = endexpression;
13287 /* and let the loop process it. */
13290 /* At this point, we're done with the expression. */
13291 if (numstackptr != numstack+1) {
13292 /* ... but if there isn't, it's bad */
13297 if (numstack->var) {
13298 /* expression is $((var)) only, lookup now */
13299 errcode = arith_lookup_val(numstack);
13302 *perrcode = errcode;
13303 return numstack->val;
13306 /* Continue processing the expression. */
13307 if (arith_isspace(arithval)) {
13308 /* Skip whitespace */
13311 p = endofname(expr);
13313 size_t var_name_size = (p-expr) + 1; /* trailing zero */
13315 numstackptr->var = alloca(var_name_size);
13316 safe_strncpy(numstackptr->var, expr, var_name_size);
13319 numstackptr->contidional_second_val_initialized = 0;
13324 if (isdigit(arithval)) {
13325 numstackptr->var = NULL;
13326 #if ENABLE_ASH_MATH_SUPPORT_64
13327 numstackptr->val = strtoll(expr, (char **) &expr, 0);
13329 numstackptr->val = strtol(expr, (char **) &expr, 0);
13333 for (p = op_tokens; ; p++) {
13337 /* strange operator not found */
13340 for (o = expr; *p && *o == *p; p++)
13347 /* skip tail uncompared token */
13350 /* skip zero delim */
13355 /* post grammar: a++ reduce to num */
13356 if (lasttok == TOK_POST_INC || lasttok == TOK_POST_DEC)
13359 /* Plus and minus are binary (not unary) _only_ if the last
13360 * token was as number, or a right paren (which pretends to be
13361 * a number, since it evaluates to one). Think about it.
13362 * It makes sense. */
13363 if (lasttok != TOK_NUM) {
13379 /* We don't want a unary operator to cause recursive descent on the
13380 * stack, because there can be many in a row and it could cause an
13381 * operator to be evaluated before its argument is pushed onto the
13382 * integer stack. */
13383 /* But for binary operators, "apply" everything on the operator
13384 * stack until we find an operator with a lesser priority than the
13385 * one we have just extracted. */
13386 /* Left paren is given the lowest priority so it will never be
13387 * "applied" in this way.
13388 * if associativity is right and priority eq, applied also skip
13391 if ((prec > 0 && prec < UNARYPREC) || prec == SPEC_PREC) {
13392 /* not left paren or unary */
13393 if (lasttok != TOK_NUM) {
13394 /* binary op must be preceded by a num */
13397 while (stackptr != stack) {
13398 if (op == TOK_RPAREN) {
13399 /* The algorithm employed here is simple: while we don't
13400 * hit an open paren nor the bottom of the stack, pop
13401 * tokens and apply them */
13402 if (stackptr[-1] == TOK_LPAREN) {
13404 /* Any operator directly after a */
13406 /* close paren should consider itself binary */
13410 operator prev_prec = PREC(stackptr[-1]);
13412 convert_prec_is_assing(prec);
13413 convert_prec_is_assing(prev_prec);
13414 if (prev_prec < prec)
13416 /* check right assoc */
13417 if (prev_prec == prec && is_right_associativity(prec))
13420 errcode = arith_apply(*--stackptr, numstack, &numstackptr);
13421 if (errcode) goto ret;
13423 if (op == TOK_RPAREN) {
13428 /* Push this operator to the stack and remember it. */
13429 *stackptr++ = lasttok = op;
13434 #endif /* ASH_MATH_SUPPORT */
13437 /* ============ main() and helpers */
13440 * Called to exit the shell.
13442 static void exitshell(void) NORETURN;
13450 status = exitstatus;
13451 TRACE(("pid %d, exitshell(%d)\n", getpid(), status));
13452 if (setjmp(loc.loc)) {
13453 if (exception == EXEXIT)
13454 /* dash bug: it just does _exit(exitstatus) here
13455 * but we have to do setjobctl(0) first!
13456 * (bug is still not fixed in dash-0.5.3 - if you run dash
13457 * under Midnight Commander, on exit from dash MC is backgrounded) */
13458 status = exitstatus;
13461 exception_handler = &loc;
13467 flush_stdout_stderr();
13477 /* from input.c: */
13478 basepf.next_to_pgetc = basepf.buf = basebuf;
13481 signal(SIGCHLD, SIG_DFL);
13486 char ppid[sizeof(int)*3 + 1];
13488 struct stat st1, st2;
13491 for (envp = environ; envp && *envp; envp++) {
13492 if (strchr(*envp, '=')) {
13493 setvareq(*envp, VEXPORT|VTEXTFIXED);
13497 snprintf(ppid, sizeof(ppid), "%u", (unsigned) getppid());
13498 setvar("PPID", ppid, 0);
13500 p = lookupvar("PWD");
13502 if (*p != '/' || stat(p, &st1) || stat(".", &st2)
13503 || st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino)
13510 * Process the shell command line arguments.
13513 procargs(char **argv)
13516 const char *xminusc;
13521 /* if (xargv[0]) - mmm, this is always true! */
13523 for (i = 0; i < NOPTS; i++)
13527 /* it already printed err message */
13528 raise_exception(EXERROR);
13532 if (*xargv == NULL) {
13534 ash_msg_and_raise_error(bb_msg_requires_arg, "-c");
13537 if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
13541 for (i = 0; i < NOPTS; i++)
13542 if (optlist[i] == 2)
13547 /* POSIX 1003.2: first arg after -c cmd is $0, remainder $1... */
13552 } else if (!sflag) {
13553 setinputfile(*xargv, 0);
13556 commandname = arg0;
13559 shellparam.p = xargv;
13560 #if ENABLE_ASH_GETOPTS
13561 shellparam.optind = 1;
13562 shellparam.optoff = -1;
13564 /* assert(shellparam.malloced == 0 && shellparam.nparam == 0); */
13566 shellparam.nparam++;
13573 * Read /etc/profile or .profile.
13576 read_profile(const char *name)
13580 if (setinputfile(name, INPUT_PUSH_FILE | INPUT_NOFILE_OK) < 0)
13589 * This routine is called when an error or an interrupt occurs in an
13590 * interactive shell and control is returned to the main command loop.
13598 /* from input.c: */
13599 g_parsefile->left_in_buffer = 0;
13600 g_parsefile->left_in_line = 0; /* clear input buffer */
13602 /* from parser.c: */
13605 /* from redir.c: */
13606 clearredir(/*drop:*/ 0);
13610 static short profile_buf[16384];
13611 extern int etext();
13615 * Main routine. We initialize things, parse the arguments, execute
13616 * profiles if we're a login shell, and then call cmdloop to execute
13617 * commands. The setjmp call sets up the location to jump to when an
13618 * exception occurs. When an exception occurs the variable "state"
13619 * is used to figure out how far we had gotten.
13621 int ash_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
13622 int ash_main(int argc UNUSED_PARAM, char **argv)
13625 volatile int state;
13626 struct jmploc jmploc;
13627 struct stackmark smark;
13629 /* Initialize global data */
13633 #if ENABLE_ASH_ALIAS
13639 monitor(4, etext, profile_buf, sizeof(profile_buf), 50);
13642 #if ENABLE_FEATURE_EDITING
13643 line_input_state = new_line_input_t(FOR_SHELL | WITH_PATH_LOOKUP);
13646 if (setjmp(jmploc.loc)) {
13656 if (e == EXEXIT || s == 0 || iflag == 0 || shlvl)
13660 outcslow('\n', stderr);
13662 popstackmark(&smark);
13663 FORCE_INT_ON; /* enable interrupts */
13672 exception_handler = &jmploc;
13675 trace_puts("Shell args: ");
13676 trace_puts_args(argv);
13678 rootpid = getpid();
13680 #if ENABLE_ASH_RANDOM_SUPPORT
13681 /* Can use monotonic_ns() for better randomness but for now it is
13682 * not used anywhere else in busybox... so avoid bloat */
13683 random_galois_LFSR = random_LCG = rootpid + monotonic_us();
13686 setstackmark(&smark);
13689 #if ENABLE_FEATURE_EDITING_SAVEHISTORY
13691 const char *hp = lookupvar("HISTFILE");
13694 hp = lookupvar("HOME");
13696 char *defhp = concat_path_file(hp, ".ash_history");
13697 setvar("HISTFILE", defhp, 0);
13703 if (argv[0] && argv[0][0] == '-')
13707 read_profile("/etc/profile");
13710 read_profile(".profile");
13716 getuid() == geteuid() && getgid() == getegid() &&
13720 shinit = lookupvar("ENV");
13721 if (shinit != NULL && *shinit != '\0') {
13722 read_profile(shinit);
13728 evalstring(minusc, 0);
13730 if (sflag || minusc == NULL) {
13731 #if ENABLE_FEATURE_EDITING_SAVEHISTORY
13733 const char *hp = lookupvar("HISTFILE");
13736 line_input_state->hist_file = hp;
13739 state4: /* XXX ??? - why isn't this before the "if" statement */
13747 extern void _mcleanup(void);
13756 const char *applet_name = "debug stuff usage";
13757 int main(int argc, char **argv)
13759 return ash_main(argc, argv);
13765 * Copyright (c) 1989, 1991, 1993, 1994
13766 * The Regents of the University of California. All rights reserved.
13768 * This code is derived from software contributed to Berkeley by
13769 * Kenneth Almquist.
13771 * Redistribution and use in source and binary forms, with or without
13772 * modification, are permitted provided that the following conditions
13774 * 1. Redistributions of source code must retain the above copyright
13775 * notice, this list of conditions and the following disclaimer.
13776 * 2. Redistributions in binary form must reproduce the above copyright
13777 * notice, this list of conditions and the following disclaimer in the
13778 * documentation and/or other materials provided with the distribution.
13779 * 3. Neither the name of the University nor the names of its contributors
13780 * may be used to endorse or promote products derived from this software
13781 * without specific prior written permission.
13783 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
13784 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
13785 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
13786 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
13787 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
13788 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
13789 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
13790 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
13791 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
13792 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF