1 /* vi: set sw=4 ts=4: */
3 * ash shell port for busybox
5 * This code is derived from software contributed to Berkeley by
8 * Original BSD copyright notice is retained at the end of this file.
10 * Copyright (c) 1989, 1991, 1993, 1994
11 * The Regents of the University of California. All rights reserved.
13 * Copyright (c) 1997-2005 Herbert Xu <herbert@gondor.apana.org.au>
14 * was re-ported from NetBSD and debianized.
16 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
18 //config:config SHELL_ASH
19 //config: bool #hidden option
20 //config: depends on !NOMMU
23 //config: bool "ash (80 kb)"
25 //config: depends on !NOMMU
26 //config: select SHELL_ASH
28 //config: The most complete and most pedantically correct shell included with
29 //config: busybox. This shell is actually a derivative of the Debian 'dash'
30 //config: shell (by Herbert Xu), which was created by porting the 'ash' shell
31 //config: (written by Kenneth Almquist) from NetBSD.
33 //config:# ash options
34 //config:# note: Don't remove !NOMMU part in the next line; it would break
35 //config:# menuconfig's indenting.
36 //config:if !NOMMU && (SHELL_ASH || ASH || SH_IS_ASH || BASH_IS_ASH)
38 //config:config ASH_OPTIMIZE_FOR_SIZE
39 //config: bool "Optimize for size instead of speed"
41 //config: depends on SHELL_ASH
43 //config:config ASH_INTERNAL_GLOB
44 //config: bool "Use internal glob() implementation"
45 //config: default y # Y is bigger, but because of uclibc glob() bug, let Y be default for now
46 //config: depends on SHELL_ASH
48 //config: Do not use glob() function from libc, use internal implementation.
49 //config: Use this if you are getting "glob.h: No such file or directory"
50 //config: or similar build errors.
51 //config: Note that as of now (2017-01), uclibc and musl glob() both have bugs
52 //config: which would break ash if you select N here.
54 //config:config ASH_BASH_COMPAT
55 //config: bool "bash-compatible extensions"
57 //config: depends on SHELL_ASH
59 //config:config ASH_BASH_SOURCE_CURDIR
60 //config: bool "'source' and '.' builtins search current directory after $PATH"
61 //config: default n # do not encourage non-standard behavior
62 //config: depends on ASH_BASH_COMPAT
64 //config: This is not compliant with standards. Avoid if possible.
66 //config:config ASH_BASH_NOT_FOUND_HOOK
67 //config: bool "command_not_found_handle hook support"
69 //config: depends on ASH_BASH_COMPAT
71 //config: Enable support for the 'command_not_found_handle' hook function,
72 //config: from GNU bash, which allows for alternative command not found
75 //config:config ASH_JOB_CONTROL
76 //config: bool "Job control"
78 //config: depends on SHELL_ASH
80 //config:config ASH_ALIAS
81 //config: bool "Alias support"
83 //config: depends on SHELL_ASH
85 //config:config ASH_RANDOM_SUPPORT
86 //config: bool "Pseudorandom generator and $RANDOM variable"
88 //config: depends on SHELL_ASH
90 //config: Enable pseudorandom generator and dynamic variable "$RANDOM".
91 //config: Each read of "$RANDOM" will generate a new pseudorandom value.
92 //config: You can reset the generator by using a specified start value.
93 //config: After "unset RANDOM" the generator will switch off and this
94 //config: variable will no longer have special treatment.
96 //config:config ASH_EXPAND_PRMT
97 //config: bool "Expand prompt string"
99 //config: depends on SHELL_ASH
101 //config: $PS# may contain volatile content, such as backquote commands.
102 //config: This option recreates the prompt string from the environment
103 //config: variable each time it is displayed.
105 //config:config ASH_IDLE_TIMEOUT
106 //config: bool "Idle timeout variable $TMOUT"
108 //config: depends on SHELL_ASH
110 //config: Enable bash-like auto-logout after $TMOUT seconds of idle time.
112 //config:config ASH_MAIL
113 //config: bool "Check for new mail in interactive shell"
115 //config: depends on SHELL_ASH
117 //config: Enable "check for new mail" function:
118 //config: if set, $MAIL file and $MAILPATH list of files
119 //config: are checked for mtime changes, and "you have mail"
120 //config: message is printed if change is detected.
122 //config:config ASH_ECHO
123 //config: bool "echo builtin"
125 //config: depends on SHELL_ASH
127 //config:config ASH_PRINTF
128 //config: bool "printf builtin"
130 //config: depends on SHELL_ASH
132 //config:config ASH_TEST
133 //config: bool "test builtin"
135 //config: depends on SHELL_ASH
138 ////config:config ASH_SLEEP
139 ////config: bool "sleep builtin"
140 ////config: default y
141 ////config: depends on SHELL_ASH
143 //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
144 //Disabled for now. Has a few annoying problems:
145 // * sleepcmd() -> sleep_main(), the parsing of bad arguments exits the shell.
146 // * sleep_for_duration() in sleep_main() has to be interruptible for
147 // ^C traps to work, which may be a problem for other users
148 // of sleep_for_duration().
149 // * BUT, if sleep_for_duration() is interruptible, then SIGCHLD interrupts it
150 // as well (try "/bin/sleep 1 & sleep 10").
151 // * sleep_main() must not allocate anything as ^C in ash longjmp's.
152 // (currently, allocations are only on error paths, in message printing).
154 //config:config ASH_HELP
155 //config: bool "help builtin"
157 //config: depends on SHELL_ASH
159 //config:config ASH_GETOPTS
160 //config: bool "getopts builtin"
162 //config: depends on SHELL_ASH
164 //config:config ASH_CMDCMD
165 //config: bool "command builtin"
167 //config: depends on SHELL_ASH
169 //config: Enable support for the 'command' builtin, which allows
170 //config: you to run the specified command or builtin,
171 //config: even when there is a function with the same name.
173 //config:endif # ash options
175 //applet:IF_ASH(APPLET(ash, BB_DIR_BIN, BB_SUID_DROP))
176 // APPLET_ODDNAME:name main location suid_type help
177 //applet:IF_SH_IS_ASH( APPLET_ODDNAME(sh, ash, BB_DIR_BIN, BB_SUID_DROP, ash))
178 //applet:IF_BASH_IS_ASH(APPLET_ODDNAME(bash, ash, BB_DIR_BIN, BB_SUID_DROP, ash))
180 //kbuild:lib-$(CONFIG_SHELL_ASH) += ash.o ash_ptr_hack.o shell_common.o
181 //kbuild:lib-$(CONFIG_ASH_RANDOM_SUPPORT) += random.o
184 * DEBUG=1 to compile in debugging ('set -o debug' turns on)
185 * DEBUG=2 to compile in and turn on debugging.
186 * When debugging is on ("set -o debug" was executed, or DEBUG=2),
187 * debugging info is written to ./trace, quit signal generates core dump.
190 /* Tweak debug output verbosity here */
194 #define DEBUG_INTONOFF 0
198 #define JOBS ENABLE_ASH_JOB_CONTROL
201 #include <sys/times.h>
202 #include <sys/utsname.h> /* for setting $HOSTNAME */
203 #include "busybox.h" /* for applet_names */
204 #if ENABLE_FEATURE_SH_EMBEDDED_SCRIPTS
205 # include "embedded_scripts.h"
207 # define NUM_SCRIPTS 0
210 /* So far, all bash compat is controlled by one config option */
211 /* Separate defines document which part of code implements what */
212 /* function keyword */
213 #define BASH_FUNCTION ENABLE_ASH_BASH_COMPAT
214 #define IF_BASH_FUNCTION IF_ASH_BASH_COMPAT
216 #define BASH_REDIR_OUTPUT ENABLE_ASH_BASH_COMPAT
217 #define IF_BASH_REDIR_OUTPUT IF_ASH_BASH_COMPAT
219 #define BASH_DOLLAR_SQUOTE ENABLE_ASH_BASH_COMPAT
220 #define IF_BASH_DOLLAR_SQUOTE IF_ASH_BASH_COMPAT
221 #define BASH_PATTERN_SUBST ENABLE_ASH_BASH_COMPAT
222 #define IF_BASH_PATTERN_SUBST IF_ASH_BASH_COMPAT
223 #define BASH_SUBSTR ENABLE_ASH_BASH_COMPAT
224 #define IF_BASH_SUBSTR IF_ASH_BASH_COMPAT
225 /* BASH_TEST2: [[ EXPR ]]
226 * Status of [[ support:
227 * && and || work as they should
228 * = is glob match operator, not equality operator: STR = GLOB
230 * =~ is regex match operator: STR =~ REGEX
232 * singleword+noglob expansion:
233 * v='a b'; [[ $v = 'a b' ]]; echo 0:$?
234 * [[ /bin/n* ]]; echo 0:$?
235 * quoting needs to be considered (-f is an operator, "-f" and ""-f are not; etc)
236 * ( ) < > should not have special meaning (IOW: should not require quoting)
237 * in word = GLOB, quoting should be significant on char-by-char basis: a*cd"*"
239 #define BASH_TEST2 (ENABLE_ASH_BASH_COMPAT * ENABLE_ASH_TEST)
240 #define BASH_SOURCE ENABLE_ASH_BASH_COMPAT
241 #define BASH_PIPEFAIL ENABLE_ASH_BASH_COMPAT
242 #define BASH_HOSTNAME_VAR ENABLE_ASH_BASH_COMPAT
243 #define BASH_EPOCH_VARS ENABLE_ASH_BASH_COMPAT
244 #define BASH_SHLVL_VAR ENABLE_ASH_BASH_COMPAT
245 #define BASH_XTRACEFD ENABLE_ASH_BASH_COMPAT
246 #define BASH_READ_D ENABLE_ASH_BASH_COMPAT
247 #define IF_BASH_READ_D IF_ASH_BASH_COMPAT
248 #define BASH_WAIT_N ENABLE_ASH_BASH_COMPAT
249 /* <(...) and >(...) */
251 # define BASH_PROCESS_SUBST ENABLE_ASH_BASH_COMPAT
252 # define IF_BASH_PROCESS_SUBST IF_ASH_BASH_COMPAT
254 # define BASH_PROCESS_SUBST 0
255 # define IF_BASH_PROCESS_SUBST(...)
258 #if defined(__ANDROID_API__) && __ANDROID_API__ <= 24
259 /* Bionic at least up to version 24 has no glob() */
260 # undef ENABLE_ASH_INTERNAL_GLOB
261 # define ENABLE_ASH_INTERNAL_GLOB 1
264 #if !ENABLE_ASH_INTERNAL_GLOB && defined(__UCLIBC__)
265 # error uClibc glob() is buggy, use ASH_INTERNAL_GLOB.
266 # error The bug is: for "$PWD"/<pattern> ash will escape e.g. dashes in "$PWD"
267 # error with backslash, even ones which do not need to be: "/a-b" -> "/a\-b"
268 # error glob() should unbackslash them and match. uClibc does not unbackslash,
269 # error fails to match dirname, subsequently not expanding <pattern> in it.
271 // if (glob("/etc/polkit\\-1", 0, NULL, &pglob)) - this returns 0 on uclibc, no bug
272 // if (glob("/etc/polkit\\-1/*", 0, NULL, &pglob)) printf("uclibc bug!\n");
275 #if !ENABLE_ASH_INTERNAL_GLOB
280 #include "shell_common.h"
281 #if ENABLE_FEATURE_SH_MATH
284 typedef long arith_t
;
285 # define ARITH_FMT "%ld"
287 #if ENABLE_ASH_RANDOM_SUPPORT
290 # define CLEAR_RANDOM_T(rnd) ((void)0)
293 #include "NUM_APPLETS.h"
295 /* STANDALONE does not make sense, and won't compile */
296 # undef CONFIG_FEATURE_SH_STANDALONE
297 # undef ENABLE_FEATURE_SH_STANDALONE
298 # undef IF_FEATURE_SH_STANDALONE
299 # undef IF_NOT_FEATURE_SH_STANDALONE
300 # define ENABLE_FEATURE_SH_STANDALONE 0
301 # define IF_FEATURE_SH_STANDALONE(...)
302 # define IF_NOT_FEATURE_SH_STANDALONE(...) __VA_ARGS__
305 #ifndef F_DUPFD_CLOEXEC
306 # define F_DUPFD_CLOEXEC F_DUPFD
312 # define PIPE_BUF 4096 /* amount of buffering in a pipe */
316 # define unlikely(cond) (cond)
320 # error "Do not even bother, ash will not run on NOMMU machine"
323 /* ============ Hash table sizes. Configurable. */
327 #define CMDTABLESIZE 31 /* should be prime */
330 /* ============ Shell options */
332 /* If you add/change options hare, update --help text too */
333 static const char *const optletters_optnames
[] ALIGN_PTR
= {
336 /* bash has '-o ignoreeof', but no short synonym -I for it */
337 /* (in bash, set -I disables invisible variables (what's that?)) */
339 /* The below allowed this invocation:
340 * ash -c 'set -i; echo $-; sleep 5; echo $-'
341 * to be ^C-ed and get to interactive ash prompt.
342 * bash does not support such "set -i".
343 * In our code, this is denoted by empty long name:
346 /* (removing "i" altogether would remove it from "$-", not good) */
349 /* Ditto: bash has no "set -s", "set -c" */
368 //bash 4.4.23 also has these opts (with these defaults):
376 //interactive-comments on
383 #define optletters(n) optletters_optnames[n][0]
384 #define optnames(n) (optletters_optnames[n] + 1)
386 enum { NOPTS
= ARRAY_SIZE(optletters_optnames
) };
389 /* ============ Misc data */
391 #define msg_illnum "Illegal number: %s"
394 * We enclose jmp_buf in a structure so that we can declare pointers to
395 * jump locations. The global variable handler contains the location to
396 * jump to when an exception occurs, and the global variable exception_type
397 * contains a code identifying the exception. To implement nested
398 * exception handlers, the user should save the value of handler on entry
399 * to an inner scope, set handler to point to a jmploc structure for the
400 * inner scope, and restore handler on exit from the scope.
406 struct globals_misc
{
407 uint8_t exitstatus
; /* exit status of last command */
408 uint8_t back_exitstatus
;/* exit status of backquoted command */
409 smallint job_warning
; /* user was warned about stopped jobs (can be 2, 1 or 0). */
410 smallint inps4
; /* Prevent PS4 nesting. */
411 int savestatus
; /* exit status of last command outside traps */
412 int rootpid
; /* pid of main shell */
413 /* shell level: 0 for the main shell, 1 for its children, and so on */
415 #define rootshell (!shlvl)
418 char *minusc
; /* argument to -c option */
420 char *curdir
; // = nullstr; /* current working directory */
421 char *physdir
; // = nullstr; /* physical working directory */
423 char *arg0
; /* value of $0 */
425 struct jmploc
*exception_handler
;
427 /*volatile*/ int suppress_int
; /* counter */
428 /* ^^^^^^^ removed "volatile" since on x86, gcc turns suppress_int++
429 * into ridiculous 3-insn sequence otherwise.
430 * We don't change suppress_int asyncronously (in a signal handler),
431 * but we do read it async.
433 volatile /*sig_atomic_t*/ smallint pending_int
; /* 1 = got SIGINT */
434 volatile /*sig_atomic_t*/ smallint got_sigchld
; /* 1 = got SIGCHLD */
435 volatile /*sig_atomic_t*/ smallint pending_sig
; /* last pending signal */
436 smallint exception_type
; /* kind of exception: */
437 #define EXINT 0 /* SIGINT received */
438 #define EXERROR 1 /* a generic error */
439 #define EXEND 3 /* exit the shell */
440 #define EXEXIT 4 /* exit the shell via exitcmd */
442 char nullstr
[1]; /* zero length string */
445 #define eflag optlist[0]
446 #define fflag optlist[1]
447 #define Iflag optlist[2]
448 #define iflag optlist[3]
449 #define mflag optlist[4]
450 #define nflag optlist[5]
451 #define sflag optlist[6]
452 #define cflag optlist[7]
453 #define xflag optlist[8]
454 #define vflag optlist[9]
455 #define Cflag optlist[10]
456 #define aflag optlist[11]
457 #define bflag optlist[12]
458 #define uflag optlist[13]
459 #define Eflag optlist[14]
460 #define viflag optlist[15]
462 # define pipefail optlist[16]
467 # define nolog optlist[16 + BASH_PIPEFAIL]
468 # define debug optlist[17 + BASH_PIPEFAIL]
471 /* trap handler commands */
473 * Sigmode records the current value of the signal handlers for the various
474 * modes. A value of zero means that the current handler is not known.
475 * S_HARD_IGN indicates that the signal was ignored on entry to the shell.
477 char sigmode
[NSIG
- 1];
478 #define S_DFL 1 /* default signal handling (SIG_DFL) */
479 #define S_CATCH 2 /* signal is caught */
480 #define S_IGN 3 /* signal is ignored (SIG_IGN) */
481 #define S_HARD_IGN 4 /* signal is ignored permanently (it was SIG_IGN on entry to shell) */
483 /* indicates specified signal received */
484 uint8_t gotsig
[NSIG
- 1]; /* offset by 1: "signal" 0 is meaningless */
485 uint8_t may_have_traps
; /* 0: definitely no traps are set, 1: some traps may be set */
486 char *trap
[NSIG
+ 1];
487 /* trap[0] is EXIT trap, trap[NTRAP_ERR] is ERR trap, other trap[i] are signal traps */
488 #define NTRAP_ERR NSIG
489 #define NTRAP_LAST NSIG
491 char **trap_ptr
; /* used only by "trap hack" */
493 /* Rarely referenced stuff */
494 #if ENABLE_ASH_RANDOM_SUPPORT
497 pid_t backgndpid
; /* pid of last background process */
499 extern struct globals_misc
*BB_GLOBAL_CONST ash_ptr_to_globals_misc
;
500 #define G_misc (*ash_ptr_to_globals_misc)
501 #define exitstatus (G_misc.exitstatus )
502 #define back_exitstatus (G_misc.back_exitstatus )
503 #define job_warning (G_misc.job_warning)
504 #define inps4 (G_misc.inps4 )
505 #define savestatus (G_misc.savestatus )
506 #define rootpid (G_misc.rootpid )
507 #define shlvl (G_misc.shlvl )
508 #define errlinno (G_misc.errlinno )
509 #define minusc (G_misc.minusc )
510 #define curdir (G_misc.curdir )
511 #define physdir (G_misc.physdir )
512 #define arg0 (G_misc.arg0 )
513 #define exception_handler (G_misc.exception_handler)
514 #define exception_type (G_misc.exception_type )
515 #define suppress_int (G_misc.suppress_int )
516 #define pending_int (G_misc.pending_int )
517 #define got_sigchld (G_misc.got_sigchld )
518 #define pending_sig (G_misc.pending_sig )
519 #define nullstr (G_misc.nullstr )
520 #define optlist (G_misc.optlist )
521 #define sigmode (G_misc.sigmode )
522 #define gotsig (G_misc.gotsig )
523 #define may_have_traps (G_misc.may_have_traps )
524 #define trap (G_misc.trap )
525 #define trap_ptr (G_misc.trap_ptr )
526 #define random_gen (G_misc.random_gen )
527 #define backgndpid (G_misc.backgndpid )
528 #define INIT_G_misc() do { \
529 XZALLOC_CONST_PTR(&ash_ptr_to_globals_misc, sizeof(G_misc)); \
537 /* ============ DEBUG */
539 static void trace_printf(const char *fmt
, ...);
540 static void trace_vprintf(const char *fmt
, va_list va
);
541 # define TRACE(param) trace_printf param
542 # define TRACEV(param) trace_vprintf param
543 # define close(fd) do { \
545 if (close(dfd) < 0) \
546 bb_error_msg("bug on %d: closing %d(0x%x)", \
547 __LINE__, dfd, dfd); \
550 # define TRACE(param)
551 # define TRACEV(param)
555 /* ============ Utility functions */
556 #define is_name(c) ((c) == '_' || isalpha((unsigned char)(c)))
557 #define is_in_name(c) ((c) == '_' || isalnum((unsigned char)(c)))
560 isdigit_str9(const char *str
)
562 int maxlen
= 9 + 1; /* max 9 digits: 999999999 */
563 while (--maxlen
&& isdigit(*str
))
565 return (*str
== '\0');
569 var_end(const char *var
)
578 /* ============ Parser data */
581 * ash_vmsg() needs parsefile->fd, hence parsefile definition is moved up.
584 struct strlist
*next
;
591 struct strpush
*prev
; /* preceding string on stack */
593 int prev_left_in_line
;
595 struct alias
*ap
; /* if push was associated with an alias */
597 char *string
; /* remember the string since it may change */
599 /* Delay freeing so we can stop nested aliases. */
600 struct strpush
*spfree
;
602 /* Remember last two characters for pungetc. */
605 /* Number of outstanding calls to pungetc. */
610 * The parsefile structure pointed to by the global variable parsefile
611 * contains information about the current file being read.
614 struct parsefile
*prev
; /* preceding file on stack */
615 int linno
; /* current line */
616 int pf_fd
; /* file descriptor (or -1 if string) */
617 int left_in_line
; /* number of chars left in this line */
618 int left_in_buffer
; /* number of chars left in this buffer past the line */
619 char *next_to_pgetc
; /* next char in buffer */
620 char *buf
; /* input buffer */
621 struct strpush
*strpush
; /* for pushing strings at this level */
622 struct strpush basestrpush
; /* so pushing one is fast */
624 /* Delay freeing so we can stop nested aliases. */
625 struct strpush
*spfree
;
627 /* Remember last two characters for pungetc. */
630 /* Number of outstanding calls to pungetc. */
634 static struct parsefile basepf
; /* top level input file */
635 static struct parsefile
*g_parsefile
= &basepf
; /* current input file */
636 static char *commandname
; /* currently executing command */
639 /* ============ Interrupts / exceptions */
641 static void exitshell(void) NORETURN
;
644 * These macros allow the user to suspend the handling of interrupt signals
645 * over a period of time. This is similar to SIGHOLD or to sigblock, but
646 * much more efficient and portable. (But hacking the kernel is so much
647 * more fun than worrying about efficiency and portability. :-))
650 # define INT_OFF do { \
651 TRACE(("%s:%d INT_OFF(%d)\n", __func__, __LINE__, suppress_int)); \
656 # define INT_OFF do { \
663 * Called to raise an exception. Since C doesn't include exceptions, we
664 * just do a longjmp to the exception handler. The type of exception is
665 * stored in the global variable "exception_type".
667 static void raise_exception(int) NORETURN
;
669 raise_exception(int e
)
672 if (exception_handler
== NULL
)
677 longjmp(exception_handler
->loc
, 1);
680 #define raise_exception(e) do { \
681 TRACE(("raising exception %d on line %d\n", (e), __LINE__)); \
682 raise_exception(e); \
687 * Called when a SIGINT is received. (If the user specifies
688 * that SIGINT is to be trapped or ignored using the trap builtin, then
689 * this routine is not called.) suppress_int is nonzero when interrupts
690 * are held using the INT_OFF macro. (The test for iflag is just
691 * defensive programming.)
693 static void raise_interrupt(void) NORETURN
;
695 raise_interrupt(void)
698 /* Signal is not automatically unmasked after it is raised,
699 * do it ourself - unmask all signals */
700 sigprocmask_allsigs(SIG_UNBLOCK
);
701 /* pending_sig = 0; - now done in signal_handler() */
703 if (!(rootshell
&& iflag
)) {
704 /* Kill ourself with SIGINT */
705 signal(SIGINT
, SIG_DFL
);
708 /* bash: ^C even on empty command line sets $? */
709 exitstatus
= SIGINT
+ 128;
710 raise_exception(EXINT
);
714 #define raise_interrupt() do { \
715 TRACE(("raising interrupt on line %d\n", __LINE__)); \
720 static IF_NOT_ASH_OPTIMIZE_FOR_SIZE(inline) void
724 if (--suppress_int
== 0 && pending_int
)
725 raise_interrupt(); /* does not return */
729 # define INT_ON do { \
730 TRACE(("%s:%d INT_ON(%d)\n", __func__, __LINE__, suppress_int-1)); \
734 # define INT_ON int_on()
736 static IF_NOT_ASH_OPTIMIZE_FOR_SIZE(inline) void
742 raise_interrupt(); /* does not return */
745 #define FORCE_INT_ON force_int_on()
747 #define SAVE_INT(v) ((v) = suppress_int)
749 #define RESTORE_INT(v) do { \
751 suppress_int = (v); \
752 if (suppress_int == 0 && pending_int) \
753 raise_interrupt(); /* does not return */ \
758 /* ============ Stdout/stderr output */
761 outstr(const char *p
, FILE *file
)
769 flush_stdout_stderr(void)
776 /* Was called outcslow(c,FILE*), but c was always '\n' */
778 newline_and_flush(FILE *dest
)
786 static int out1fmt(const char *, ...) __attribute__((__format__(__printf__
,1,2)));
788 out1fmt(const char *fmt
, ...)
795 r
= vprintf(fmt
, ap
);
801 static int fmtstr(char *, size_t, const char *, ...) __attribute__((__format__(__printf__
,3,4)));
803 fmtstr(char *outbuf
, size_t length
, const char *fmt
, ...)
810 ret
= vsnprintf(outbuf
, length
, fmt
, ap
);
813 return ret
> (int)length
? length
: ret
;
817 out1str(const char *p
)
823 out2str(const char *p
)
826 flush_stdout_stderr();
830 /* ============ Parser structures */
832 /* control characters in argument strings */
833 #define CTL_FIRST CTLESC
834 #define CTLESC ((unsigned char)'\201') /* escape next character */
835 #define CTLVAR ((unsigned char)'\202') /* variable defn */
836 #define CTLENDVAR ((unsigned char)'\203')
837 #define CTLBACKQ ((unsigned char)'\204')
838 #define CTLARI ((unsigned char)'\206') /* arithmetic expression */
839 #define CTLENDARI ((unsigned char)'\207')
840 #define CTLQUOTEMARK ((unsigned char)'\210')
841 #define CTL_LAST CTLQUOTEMARK
842 #if BASH_PROCESS_SUBST
843 # define CTLTOPROC ((unsigned char)'\211')
844 # define CTLFROMPROC ((unsigned char)'\212')
846 # define CTL_LAST CTLFROMPROC
849 /* variable substitution byte (follows CTLVAR) */
850 #define VSTYPE 0x0f /* type of variable substitution */
851 #define VSNUL 0x10 /* colon--treat the empty string as unset */
853 /* values of VSTYPE field */
854 #define VSNORMAL 0x1 /* normal variable: $var or ${var} */
855 #define VSMINUS 0x2 /* ${var-text} */
856 #define VSPLUS 0x3 /* ${var+text} */
857 #define VSQUESTION 0x4 /* ${var?message} */
858 #define VSASSIGN 0x5 /* ${var=text} */
859 #define VSTRIMRIGHT 0x6 /* ${var%pattern} */
860 #define VSTRIMRIGHTMAX 0x7 /* ${var%%pattern} */
861 #define VSTRIMLEFT 0x8 /* ${var#pattern} */
862 #define VSTRIMLEFTMAX 0x9 /* ${var##pattern} */
863 #define VSLENGTH 0xa /* ${#var} */
865 #define VSSUBSTR 0xc /* ${var:position:length} */
867 #if BASH_PATTERN_SUBST
868 #define VSREPLACE 0xd /* ${var/pattern/replacement} */
869 #define VSREPLACEALL 0xe /* ${var//pattern/replacement} */
872 static const char dolatstr
[] ALIGN1
= {
873 CTLQUOTEMARK
, CTLVAR
, VSNORMAL
, '@', '=', CTLQUOTEMARK
, '\0'
875 #define DOLATSTRLEN 6
894 #if BASH_REDIR_OUTPUT
911 smallint type
; /* Nxxxx */
915 union node
*redirect
;
920 smallint pipe_backgnd
;
921 struct nodelist
*cmdlist
;
928 union node
*redirect
;
941 union node
*elsepart
;
977 struct nodelist
*backquote
;
980 /* nfile and ndup layout must match!
981 * NTOFD (>&fdnum) uses ndup structure, but we may discover mid-flight
982 * that it is actually NTO2 (>&file), and change its type.
999 char *_unused_expfname
;
1018 struct nredir nredir
;
1019 struct nbinary nbinary
;
1023 struct nclist nclist
;
1024 struct ndefun ndefun
;
1033 * NODE_EOF is returned by parsecmd when it encounters an end of file.
1034 * It must be distinct from NULL.
1036 #define NODE_EOF ((union node *) -1L)
1039 struct nodelist
*next
;
1049 * Free a parse tree.
1052 freefunc(struct funcnode
*f
)
1054 if (f
&& --f
->count
< 0)
1059 /* ============ Debugging output */
1063 static FILE *tracefile
;
1066 trace_printf(const char *fmt
, ...)
1073 fprintf(tracefile
, "%u ", (int) time(NULL
));
1075 fprintf(tracefile
, "[%u] ", (int) getpid());
1077 fprintf(tracefile
, "pending s:%d i:%d(supp:%d) ", pending_sig
, pending_int
, suppress_int
);
1079 vfprintf(tracefile
, fmt
, va
);
1084 trace_vprintf(const char *fmt
, va_list va
)
1088 vfprintf(tracefile
, fmt
, va
);
1089 fprintf(tracefile
, "\n");
1093 trace_puts(const char *s
)
1097 fputs(s
, tracefile
);
1101 trace_puts_quoted(char *s
)
1108 putc('"', tracefile
);
1109 for (p
= s
; *p
; p
++) {
1110 switch ((unsigned char)*p
) {
1111 case '\n': c
= 'n'; goto backslash
;
1112 case '\t': c
= 't'; goto backslash
;
1113 case '\r': c
= 'r'; goto backslash
;
1114 case '\"': c
= '\"'; goto backslash
;
1115 case '\\': c
= '\\'; goto backslash
;
1116 case CTLESC
: c
= 'e'; goto backslash
;
1117 case CTLVAR
: c
= 'v'; goto backslash
;
1118 case CTLBACKQ
: c
= 'q'; goto backslash
;
1119 #if BASH_PROCESS_SUBST
1120 case CTLTOPROC
: c
= 'p'; goto backslash
;
1121 case CTLFROMPROC
: c
= 'P'; goto backslash
;
1124 putc('\\', tracefile
);
1128 if (*p
>= ' ' && *p
<= '~')
1129 putc(*p
, tracefile
);
1131 putc('\\', tracefile
);
1132 putc((*p
>> 6) & 03, tracefile
);
1133 putc((*p
>> 3) & 07, tracefile
);
1134 putc(*p
& 07, tracefile
);
1139 putc('"', tracefile
);
1143 trace_puts_args(char **ap
)
1150 trace_puts_quoted(*ap
);
1152 putc('\n', tracefile
);
1155 putc(' ', tracefile
);
1170 /* leave open because libedit might be using it */
1173 strcpy(s
, "./trace");
1175 if (!freopen(s
, "a", tracefile
)) {
1176 fprintf(stderr
, "Can't re-open %s\n", s
);
1181 tracefile
= fopen(s
, "a");
1182 if (tracefile
== NULL
) {
1183 fprintf(stderr
, "Can't open %s\n", s
);
1189 flags
= fcntl(fileno(tracefile
), F_GETFL
);
1191 fcntl(fileno(tracefile
), F_SETFL
, flags
| O_APPEND
);
1193 setlinebuf(tracefile
);
1194 fputs("\nTracing started.\n", tracefile
);
1198 indent(int amount
, char *pfx
, FILE *fp
)
1202 for (i
= 0; i
< amount
; i
++) {
1203 if (pfx
&& i
== amount
- 1)
1209 /* little circular references here... */
1210 static void shtree(union node
*n
, int ind
, char *pfx
, FILE *fp
);
1213 sharg(union node
*arg
, FILE *fp
)
1216 struct nodelist
*bqlist
;
1217 unsigned char subtype
;
1219 if (arg
->type
!= NARG
) {
1220 out1fmt("<node type %d>\n", arg
->type
);
1223 bqlist
= arg
->narg
.backquote
;
1224 for (p
= arg
->narg
.text
; *p
; p
++) {
1225 switch ((unsigned char)*p
) {
1234 if (subtype
== VSLENGTH
)
1242 if (subtype
& VSNUL
)
1245 switch (subtype
& VSTYPE
) {
1271 case VSTRIMRIGHTMAX
:
1278 out1fmt("<subtype %d>", subtype
);
1284 #if BASH_PROCESS_SUBST
1294 IF_BASH_PROCESS_SUBST(backq
:)
1296 shtree(bqlist
->n
, -1, NULL
, fp
);
1307 shcmd(union node
*cmd
, FILE *fp
)
1315 for (np
= cmd
->ncmd
.args
; np
; np
= np
->narg
.next
) {
1321 for (np
= cmd
->ncmd
.redirect
; np
; np
= np
->nfile
.next
) {
1325 switch (np
->nfile
.type
) {
1326 case NTO
: s
= ">>"+1; dftfd
= 1; break;
1327 case NCLOBBER
: s
= ">|"; dftfd
= 1; break;
1328 case NAPPEND
: s
= ">>"; dftfd
= 1; break;
1329 #if BASH_REDIR_OUTPUT
1332 case NTOFD
: s
= ">&"; dftfd
= 1; break;
1333 case NFROM
: s
= "<"; break;
1334 case NFROMFD
: s
= "<&"; break;
1335 case NFROMTO
: s
= "<>"; break;
1336 default: s
= "*error*"; break;
1338 if (np
->nfile
.fd
!= dftfd
)
1339 fprintf(fp
, "%d", np
->nfile
.fd
);
1341 if (np
->nfile
.type
== NTOFD
|| np
->nfile
.type
== NFROMFD
) {
1342 fprintf(fp
, "%d", np
->ndup
.dupfd
);
1344 sharg(np
->nfile
.fname
, fp
);
1351 shtree(union node
*n
, int ind
, char *pfx
, FILE *fp
)
1353 struct nodelist
*lp
;
1359 indent(ind
, pfx
, fp
);
1361 if (n
== NODE_EOF
) {
1376 shtree(n
->nbinary
.ch1
, ind
, NULL
, fp
);
1379 shtree(n
->nbinary
.ch2
, ind
, NULL
, fp
);
1387 for (lp
= n
->npipe
.cmdlist
; lp
; lp
= lp
->next
) {
1388 shtree(lp
->n
, 0, NULL
, fp
);
1392 if (n
->npipe
.pipe_backgnd
)
1398 fprintf(fp
, "<node type %d>", n
->type
);
1406 showtree(union node
*n
)
1408 trace_puts("showtree called\n");
1409 shtree(n
, 1, NULL
, stderr
);
1415 /* ============ Message printing */
1418 ash_vmsg(const char *msg
, va_list ap
)
1420 fprintf(stderr
, "%s: ", arg0
);
1422 if (strcmp(arg0
, commandname
))
1423 fprintf(stderr
, "%s: ", commandname
);
1424 if (!iflag
|| g_parsefile
->pf_fd
> 0)
1425 fprintf(stderr
, "line %d: ", errlinno
);
1427 vfprintf(stderr
, msg
, ap
);
1428 newline_and_flush(stderr
);
1432 * Exverror is called to raise the error exception. If the second argument
1433 * is not NULL then error prints an error message using printf style
1434 * formatting. It then raises the error exception.
1436 static void ash_vmsg_and_raise(int, const char *, va_list) NORETURN
;
1438 ash_vmsg_and_raise(int cond
, const char *msg
, va_list ap
)
1442 TRACE(("ash_vmsg_and_raise(%d):", cond
));
1445 TRACE(("ash_vmsg_and_raise(%d):NULL\n", cond
));
1450 flush_stdout_stderr();
1451 raise_exception(cond
);
1455 static void ash_msg_and_raise_error(const char *, ...) NORETURN
;
1457 ash_msg_and_raise_error(const char *msg
, ...)
1464 ash_vmsg_and_raise(EXERROR
, msg
, ap
);
1470 * 'fmt' must be a string literal.
1472 #define ash_msg_and_raise_perror(fmt, ...) ash_msg_and_raise_error(fmt ": "STRERROR_FMT, ##__VA_ARGS__ STRERROR_ERRNO)
1474 static void raise_error_syntax(const char *) NORETURN
;
1476 raise_error_syntax(const char *msg
)
1478 errlinno
= g_parsefile
->linno
;
1479 ash_msg_and_raise_error("syntax error: %s", msg
);
1483 static void ash_msg_and_raise(int, const char *, ...) NORETURN
;
1485 ash_msg_and_raise(int cond
, const char *msg
, ...)
1490 ash_vmsg_and_raise(cond
, msg
, ap
);
1496 * error/warning routines for external builtins
1499 ash_msg(const char *fmt
, ...)
1509 * Return a string describing an error. The returned string may be a
1510 * pointer to a static buffer that will be overwritten on the next call.
1511 * Action describes the operation that got the error.
1514 errmsg(int e
, const char *em
)
1516 if (e
== ENOENT
|| e
== ENOTDIR
) {
1523 /* ============ Memory allocation */
1526 /* I consider these wrappers nearly useless:
1527 * ok, they return you to nearest exception handler, but
1528 * how much memory do you leak in the process, making
1529 * memory starvation worse?
1532 ckrealloc(void * p
, size_t nbytes
)
1534 p
= realloc(p
, nbytes
);
1536 ash_msg_and_raise_error(bb_msg_memory_exhausted
);
1541 ckmalloc(size_t nbytes
)
1543 return ckrealloc(NULL
, nbytes
);
1547 ckzalloc(size_t nbytes
)
1549 return memset(ckmalloc(nbytes
), 0, nbytes
);
1553 ckstrdup(const char *s
)
1555 char *p
= strdup(s
);
1557 ash_msg_and_raise_error(bb_msg_memory_exhausted
);
1561 /* Using bbox equivalents. They exit if out of memory */
1562 # define ckrealloc xrealloc
1563 # define ckmalloc xmalloc
1564 # define ckzalloc xzalloc
1565 # define ckstrdup xstrdup
1569 * It appears that grabstackstr() will barf with such alignments
1570 * because stalloc() will return a string allocated in a new stackblock.
1572 #define SHELL_ALIGN(nbytes) (((nbytes) + SHELL_SIZE) & ~SHELL_SIZE)
1574 /* Most machines require the value returned from malloc to be aligned
1575 * in some way. The following macro will get this right
1576 * on many machines. */
1577 SHELL_SIZE
= sizeof(union { int i
; char *cp
; double d
; }) - 1,
1578 /* Minimum size of a block */
1579 MINSIZE
= SHELL_ALIGN(504),
1582 struct stack_block
{
1583 struct stack_block
*prev
;
1584 char space
[MINSIZE
];
1588 struct stack_block
*stackp
;
1594 struct globals_memstack
{
1595 struct stack_block
*g_stackp
; // = &stackbase;
1596 char *g_stacknxt
; // = stackbase.space;
1597 char *sstrend
; // = stackbase.space + MINSIZE;
1598 size_t g_stacknleft
; // = MINSIZE;
1599 struct stack_block stackbase
;
1601 extern struct globals_memstack
*BB_GLOBAL_CONST ash_ptr_to_globals_memstack
;
1602 #define G_memstack (*ash_ptr_to_globals_memstack)
1603 #define g_stackp (G_memstack.g_stackp )
1604 #define g_stacknxt (G_memstack.g_stacknxt )
1605 #define sstrend (G_memstack.sstrend )
1606 #define g_stacknleft (G_memstack.g_stacknleft)
1607 #define stackbase (G_memstack.stackbase )
1608 #define INIT_G_memstack() do { \
1609 XZALLOC_CONST_PTR(&ash_ptr_to_globals_memstack, sizeof(G_memstack)); \
1610 g_stackp = &stackbase; \
1611 g_stacknxt = stackbase.space; \
1612 g_stacknleft = MINSIZE; \
1613 sstrend = stackbase.space + MINSIZE; \
1617 #define stackblock() ((void *)g_stacknxt)
1618 #define stackblocksize() g_stacknleft
1621 * Parse trees for commands are allocated in lifo order, so we use a stack
1622 * to make this more efficient, and also to avoid all sorts of exception
1623 * handling code to handle interrupts in the middle of a parse.
1625 * The size 504 was chosen because the Ultrix malloc handles that size
1629 stalloc(size_t nbytes
)
1634 aligned
= SHELL_ALIGN(nbytes
);
1635 if (aligned
> g_stacknleft
) {
1638 struct stack_block
*sp
;
1640 blocksize
= aligned
;
1641 if (blocksize
< MINSIZE
)
1642 blocksize
= MINSIZE
;
1643 len
= sizeof(struct stack_block
) - MINSIZE
+ blocksize
;
1644 if (len
< blocksize
)
1645 ash_msg_and_raise_error(bb_msg_memory_exhausted
);
1648 sp
->prev
= g_stackp
;
1649 g_stacknxt
= sp
->space
;
1650 g_stacknleft
= blocksize
;
1651 sstrend
= g_stacknxt
+ blocksize
;
1656 g_stacknxt
+= aligned
;
1657 g_stacknleft
-= aligned
;
1662 stzalloc(size_t nbytes
)
1664 return memset(stalloc(nbytes
), 0, nbytes
);
1671 if (!p
|| (g_stacknxt
< (char *)p
) || ((char *)p
< g_stackp
->space
)) {
1672 write(STDERR_FILENO
, "stunalloc\n", 10);
1676 g_stacknleft
+= g_stacknxt
- (char *)p
;
1681 * Like strdup but works with the ash stack.
1684 sstrdup(const char *p
)
1686 size_t len
= strlen(p
) + 1;
1687 return memcpy(stalloc(len
), p
, len
);
1690 static ALWAYS_INLINE
void
1691 grabstackblock(size_t len
)
1697 pushstackmark(struct stackmark
*mark
, size_t len
)
1699 mark
->stackp
= g_stackp
;
1700 mark
->stacknxt
= g_stacknxt
;
1701 mark
->stacknleft
= g_stacknleft
;
1702 grabstackblock(len
);
1706 setstackmark(struct stackmark
*mark
)
1708 pushstackmark(mark
, g_stacknxt
== g_stackp
->space
&& g_stackp
!= &stackbase
);
1712 popstackmark(struct stackmark
*mark
)
1714 struct stack_block
*sp
;
1720 while (g_stackp
!= mark
->stackp
) {
1722 g_stackp
= sp
->prev
;
1725 g_stacknxt
= mark
->stacknxt
;
1726 g_stacknleft
= mark
->stacknleft
;
1727 sstrend
= mark
->stacknxt
+ mark
->stacknleft
;
1732 * When the parser reads in a string, it wants to stick the string on the
1733 * stack and only adjust the stack pointer when it knows how big the
1734 * string is. Stackblock (defined in stack.h) returns a pointer to a block
1735 * of space on top of the stack and stackblocklen returns the length of
1736 * this block. Growstackblock will grow this space by at least one byte,
1737 * possibly moving it (like realloc). Grabstackblock actually allocates the
1738 * part of the block that has been used.
1741 growstackblock(size_t min
)
1745 newlen
= g_stacknleft
* 2;
1746 if (newlen
< g_stacknleft
)
1747 ash_msg_and_raise_error(bb_msg_memory_exhausted
);
1748 min
= SHELL_ALIGN(min
| 128);
1752 if (g_stacknxt
== g_stackp
->space
&& g_stackp
!= &stackbase
) {
1753 struct stack_block
*sp
;
1754 struct stack_block
*prevstackp
;
1759 prevstackp
= sp
->prev
;
1760 grosslen
= newlen
+ sizeof(struct stack_block
) - MINSIZE
;
1761 sp
= ckrealloc(sp
, grosslen
);
1762 sp
->prev
= prevstackp
;
1764 g_stacknxt
= sp
->space
;
1765 g_stacknleft
= newlen
;
1766 sstrend
= sp
->space
+ newlen
;
1769 char *oldspace
= g_stacknxt
;
1770 size_t oldlen
= g_stacknleft
;
1771 char *p
= stalloc(newlen
);
1773 /* free the space we just allocated */
1774 g_stacknxt
= memcpy(p
, oldspace
, oldlen
);
1775 g_stacknleft
+= newlen
;
1780 * The following routines are somewhat easier to use than the above.
1781 * The user declares a variable of type STACKSTR, which may be declared
1782 * to be a register. The macro STARTSTACKSTR initializes things. Then
1783 * the user uses the macro STPUTC to add characters to the string. In
1784 * effect, STPUTC(c, p) is the same as *p++ = c except that the stack is
1785 * grown as necessary. When the user is done, she can just leave the
1786 * string there and refer to it using stackblock(). Or she can allocate
1787 * the space for it using grabstackstr(). If it is necessary to allow
1788 * someone else to use the stack temporarily and then continue to grow
1789 * the string, the user should use grabstack to allocate the space, and
1790 * then call ungrabstr(p) to return to the previous mode of operation.
1792 * USTPUTC is like STPUTC except that it doesn't check for overflow.
1793 * CHECKSTACKSPACE can be called before USTPUTC to ensure that there
1794 * is space for at least one character.
1799 size_t len
= stackblocksize();
1801 return (char *)stackblock() + len
;
1805 growstackto(size_t len
)
1807 if (stackblocksize() < len
)
1808 growstackblock(len
);
1809 return stackblock();
1813 * Called from CHECKSTRSPACE.
1816 makestrspace(size_t newlen
, char *p
)
1818 size_t len
= p
- g_stacknxt
;
1820 return growstackto(len
+ newlen
) + len
;
1824 stnputs(const char *s
, size_t n
, char *p
)
1826 p
= makestrspace(n
, p
);
1827 p
= (char *)mempcpy(p
, s
, n
);
1832 stack_putstr(const char *s
, char *p
)
1834 return stnputs(s
, strlen(s
), p
);
1838 _STPUTC(int c
, char *p
)
1846 #define STARTSTACKSTR(p) ((p) = stackblock())
1847 #define STPUTC(c, p) ((p) = _STPUTC((c), (p)))
1848 #define CHECKSTRSPACE(n, p) do { \
1851 size_t m = sstrend - q; \
1853 (p) = makestrspace(l, q); \
1855 #define USTPUTC(c, p) (*(p)++ = (c))
1856 #define STACKSTRNUL(p) do { \
1857 if ((p) == sstrend) \
1858 (p) = growstackstr(); \
1861 #define STUNPUTC(p) (--(p))
1862 #define STTOPC(p) ((p)[-1])
1863 #define STADJUST(amount, p) ((p) += (amount))
1865 #define grabstackstr(p) stalloc((char *)(p) - (char *)stackblock())
1866 #define ungrabstackstr(s, p) stunalloc(s)
1867 #define stackstrend() ((void *)sstrend)
1870 /* ============ String helpers */
1873 * prefix -- see if pfx is a prefix of string.
1875 static ALWAYS_INLINE
char *
1876 prefix(const char *string
, const char *pfx
)
1878 return is_prefixed_with(string
, pfx
);
1879 #if 0 /* dash implementation: */
1881 if (*pfx
++ != *string
++)
1884 return (char *) string
;
1888 * Check for a valid number. This should be elsewhere.
1891 is_number(const char *p
)
1896 } while (*++p
!= '\0');
1901 * Convert a string of digits to an integer, printing an error message on
1905 number(const char *s
)
1908 ash_msg_and_raise_error(msg_illnum
, s
);
1913 * Produce a single quoted string suitable as input to the shell.
1914 * The return string is allocated on the stack.
1917 single_quote(const char *s
)
1927 len
= strchrnul(s
, '\'') - s
;
1929 q
= p
= makestrspace(len
+ 3, p
);
1932 q
= (char *)mempcpy(q
, s
, len
);
1941 do len
++; while (*++s
== '\'');
1943 q
= p
= makestrspace(len
+ 3, p
);
1946 q
= (char *)mempcpy(q
, s
- len
, len
);
1954 return stackblock();
1958 * Produce a possibly single quoted string suitable as input to the shell.
1959 * If quoting was done, the return string is allocated on the stack,
1960 * otherwise a pointer to the original string is returned.
1963 maybe_single_quote(const char *s
)
1968 /* Assuming ACSII */
1969 /* quote ctrl_chars space !"#$%&'()* */
1973 if (*p
>= ';' && *p
<= '?')
1982 /* quote {|}~ DEL and high bytes */
1985 /* Not quoting these: +,-./ 0-9 :@ A-Z ]^_ a-z */
1986 /* TODO: maybe avoid quoting % */
1992 return single_quote(s
);
1996 /* ============ nextopt */
1998 static char **argptr
; /* argument list for builtin commands */
1999 static char *optionarg
; /* set by nextopt (like getopt) */
2000 static char *optptr
; /* used by nextopt */
2003 * XXX - should get rid of. Have all builtins use getopt(3).
2004 * The library getopt must have the BSD extension static variable
2005 * "optreset", otherwise it can't be used within the shell safely.
2007 * Standard option processing (a la getopt) for builtin routines.
2008 * The only argument that is passed to nextopt is the option string;
2009 * the other arguments are unnecessary. It returns the character,
2010 * or '\0' on end of input.
2013 nextopt(const char *optstring
)
2020 if (p
== NULL
|| *p
== '\0') {
2021 /* We ate entire "-param", take next one */
2027 if (*++p
== '\0') /* just "-" ? */
2030 if (LONE_DASH(p
)) /* "--" ? */
2032 /* p => next "-param" */
2034 /* p => some option char in the middle of a "-param" */
2036 for (q
= optstring
; *q
!= c
;) {
2038 ash_msg_and_raise_error("illegal option -%c", c
);
2046 ash_msg_and_raise_error("no arg for -%c option", c
);
2056 /* ============ Shell variables */
2059 int nparam
; /* # of positional parameters (without $0) */
2060 #if ENABLE_ASH_GETOPTS
2061 int optind
; /* next parameter to be processed by getopts */
2062 int optoff
; /* used by getopts */
2064 unsigned char malloced
; /* if parameter list dynamically allocated */
2065 char **p
; /* parameter list */
2069 * Free the list of positional parameters.
2072 freeparam(volatile struct shparam
*param
)
2074 if (param
->malloced
) {
2076 ap
= ap1
= param
->p
;
2083 #if ENABLE_ASH_GETOPTS
2084 static void FAST_FUNC
getoptsreset(const char *value
);
2088 struct var
*next
; /* next entry in hash list */
2089 int flags
; /* flags are defined above */
2090 const char *var_text
; /* name=value */
2091 void (*var_func
)(const char *) FAST_FUNC
; /* function to be called when */
2092 /* the variable gets set/unset */
2096 struct localvar
*next
; /* next local variable in list */
2097 struct var
*vp
; /* the variable that was made local */
2098 int flags
; /* saved flags */
2099 const char *text
; /* saved text */
2103 #define VEXPORT 0x01 /* variable is exported */
2104 #define VREADONLY 0x02 /* variable cannot be modified */
2105 #define VSTRFIXED 0x04 /* variable struct is statically allocated */
2106 #define VTEXTFIXED 0x08 /* text is statically allocated */
2107 #define VSTACK 0x10 /* text is allocated on the stack */
2108 #define VUNSET 0x20 /* the variable is not set */
2109 #define VNOFUNC 0x40 /* don't call the callback function */
2110 #define VNOSET 0x80 /* do not set variable - just readonly test */
2111 #define VNOSAVE 0x100 /* when text is on the heap before setvareq */
2112 #if ENABLE_ASH_RANDOM_SUPPORT || BASH_EPOCH_VARS
2113 # define VDYNAMIC 0x200 /* dynamic variable */
2119 /* Need to be before varinit_data[] */
2120 #if ENABLE_LOCALE_SUPPORT
2121 static void FAST_FUNC
2122 change_lc_all(const char *value
)
2124 if (value
&& *value
!= '\0')
2125 setlocale(LC_ALL
, value
);
2127 static void FAST_FUNC
2128 change_lc_ctype(const char *value
)
2130 if (value
&& *value
!= '\0')
2131 setlocale(LC_CTYPE
, value
);
2135 static void changemail(const char *var_value
) FAST_FUNC
;
2137 static void changepath(const char *) FAST_FUNC
;
2138 #if ENABLE_ASH_RANDOM_SUPPORT
2139 static void change_random(const char *) FAST_FUNC
;
2142 static void change_seconds(const char *) FAST_FUNC
;
2143 static void change_realtime(const char *) FAST_FUNC
;
2146 static const struct {
2148 const char *var_text
;
2149 void (*var_func
)(const char *) FAST_FUNC
;
2150 } varinit_data
[] ALIGN_PTR
= {
2152 * Note: VEXPORT would not work correctly here for NOFORK applets:
2153 * some environment strings may be constant.
2155 { VSTRFIXED
|VTEXTFIXED
, defifsvar
, NULL
},
2157 { VSTRFIXED
|VTEXTFIXED
|VUNSET
, "MAIL" , changemail
},
2158 { VSTRFIXED
|VTEXTFIXED
|VUNSET
, "MAILPATH" , changemail
},
2160 { VSTRFIXED
|VTEXTFIXED
, bb_PATH_root_path
, changepath
},
2161 { VSTRFIXED
|VTEXTFIXED
, "PS1=$ " , NULL
},
2162 { VSTRFIXED
|VTEXTFIXED
, "PS2=> " , NULL
},
2163 { VSTRFIXED
|VTEXTFIXED
, "PS4=+ " , NULL
},
2164 #if ENABLE_ASH_GETOPTS
2165 { VSTRFIXED
|VTEXTFIXED
, defoptindvar
, getoptsreset
},
2167 { VSTRFIXED
|VTEXTFIXED
, NULL
/* inited to linenovar */, NULL
},
2168 { VSTRFIXED
|VTEXTFIXED
, NULL
/* inited to funcnamevar */, NULL
},
2169 #if ENABLE_ASH_RANDOM_SUPPORT
2170 { VSTRFIXED
|VTEXTFIXED
|VUNSET
|VDYNAMIC
, "RANDOM", change_random
},
2173 { VSTRFIXED
|VTEXTFIXED
|VUNSET
|VDYNAMIC
, "EPOCHSECONDS", change_seconds
},
2174 { VSTRFIXED
|VTEXTFIXED
|VUNSET
|VDYNAMIC
, "EPOCHREALTIME", change_realtime
},
2176 #if ENABLE_LOCALE_SUPPORT
2177 { VSTRFIXED
|VTEXTFIXED
|VUNSET
, "LC_ALL" , change_lc_all
},
2178 { VSTRFIXED
|VTEXTFIXED
|VUNSET
, "LC_CTYPE" , change_lc_ctype
},
2180 #if ENABLE_FEATURE_EDITING_SAVEHISTORY
2181 { VSTRFIXED
|VTEXTFIXED
|VUNSET
, "HISTFILE" , NULL
},
2187 struct globals_var
{
2188 struct shparam shellparam
; /* $@ current positional parameters */
2189 struct redirtab
*redirlist
;
2190 int preverrout_fd
; /* stderr fd: usually 2, unless redirect moved it */
2191 struct var
*vartab
[VTABSIZE
];
2192 struct var varinit
[ARRAY_SIZE(varinit_data
)];
2194 char linenovar
[sizeof("LINENO=") + sizeof(int)*3];
2195 char funcnamevar
[sizeof("FUNCNAME=") + 64];
2197 unsigned trap_depth
;
2198 bool in_trap_ERR
; /* ERR cannot recurse, no need to be a counter */
2200 extern struct globals_var
*BB_GLOBAL_CONST ash_ptr_to_globals_var
;
2201 #define G_var (*ash_ptr_to_globals_var)
2202 #define shellparam (G_var.shellparam )
2203 //#define redirlist (G_var.redirlist )
2204 #define preverrout_fd (G_var.preverrout_fd)
2205 #define vartab (G_var.vartab )
2206 #define varinit (G_var.varinit )
2207 #define lineno (G_var.lineno )
2208 #define linenovar (G_var.linenovar )
2209 #define funcnamevar (G_var.funcnamevar )
2210 #define funcname (G_var.funcname )
2211 #define trap_depth (G_var.trap_depth )
2212 #define in_trap_ERR (G_var.in_trap_ERR )
2213 #define vifs varinit[0]
2215 # define vmail varinit[1]
2216 # define vmpath varinit[2]
2218 #define VAR_OFFSET1 (ENABLE_ASH_MAIL*2)
2219 #define vpath varinit[VAR_OFFSET1 + 1]
2220 #define vps1 varinit[VAR_OFFSET1 + 2]
2221 #define vps2 varinit[VAR_OFFSET1 + 3]
2222 #define vps4 varinit[VAR_OFFSET1 + 4]
2223 #if ENABLE_ASH_GETOPTS
2224 # define voptind varinit[VAR_OFFSET1 + 5]
2226 #define VAR_OFFSET2 (VAR_OFFSET1 + ENABLE_ASH_GETOPTS)
2227 #define vlineno varinit[VAR_OFFSET2 + 5]
2228 #define vfuncname varinit[VAR_OFFSET2 + 6]
2229 #if ENABLE_ASH_RANDOM_SUPPORT
2230 # define vrandom varinit[VAR_OFFSET2 + 7]
2232 #define VAR_OFFSET3 (VAR_OFFSET2 + ENABLE_ASH_RANDOM_SUPPORT)
2234 # define vepochs varinit[VAR_OFFSET3 + 7]
2235 # define vepochr varinit[VAR_OFFSET3 + 8]
2237 #define INIT_G_var() do { \
2239 XZALLOC_CONST_PTR(&ash_ptr_to_globals_var, sizeof(G_var)); \
2240 for (i = 0; i < ARRAY_SIZE(varinit_data); i++) { \
2241 varinit[i].flags = varinit_data[i].flags; \
2242 varinit[i].var_text = varinit_data[i].var_text; \
2243 varinit[i].var_func = varinit_data[i].var_func; \
2245 strcpy(linenovar, "LINENO="); \
2246 vlineno.var_text = linenovar; \
2247 strcpy(funcnamevar, "FUNCNAME="); \
2248 vfuncname.var_text = funcnamevar; \
2252 * The following macros access the values of the above variables.
2253 * They have to skip over the name. They return the null string
2254 * for unset variables.
2256 #define ifsval() (vifs.var_text + 4)
2257 #define ifsset() ((vifs.flags & VUNSET) == 0)
2259 # define mailval() (vmail.var_text + 5)
2260 # define mpathval() (vmpath.var_text + 9)
2261 # define mpathset() ((vmpath.flags & VUNSET) == 0)
2263 #define pathval() (vpath.var_text + 5)
2264 #define ps1val() (vps1.var_text + 4)
2265 #define ps2val() (vps2.var_text + 4)
2266 #define ps4val() (vps4.var_text + 4)
2267 #if ENABLE_ASH_GETOPTS
2268 # define optindval() (voptind.var_text + 7)
2271 #if ENABLE_ASH_GETOPTS
2272 static void FAST_FUNC
2273 getoptsreset(const char *value
)
2275 shellparam
.optind
= 1;
2276 if (is_number(value
))
2277 shellparam
.optind
= number(value
) ?: 1;
2278 shellparam
.optoff
= -1;
2283 * Find the appropriate entry in the hash table from the name.
2285 static struct var
**
2286 hashvar(const char *p
)
2290 hashval
= ((unsigned char) *p
) << 4;
2291 while (*p
&& *p
!= '=')
2292 hashval
+= (unsigned char) *p
++;
2293 return &vartab
[hashval
% VTABSIZE
];
2297 vpcmp(const void *a
, const void *b
)
2299 return varcmp(*(const char **)a
, *(const char **)b
);
2303 * This routine initializes the builtin variables.
2313 * PS1 depends on uid
2315 #if ENABLE_FEATURE_EDITING && ENABLE_FEATURE_EDITING_FANCY_PROMPT
2316 vps1
.var_text
= "PS1=\\w \\$ ";
2319 vps1
.var_text
= "PS1=# ";
2322 end
= vp
+ ARRAY_SIZE(varinit
);
2324 vpp
= hashvar(vp
->var_text
);
2327 } while (++vp
< end
);
2330 static struct var
**
2331 findvar(struct var
**vpp
, const char *name
)
2333 for (; *vpp
; vpp
= &(*vpp
)->next
) {
2334 if (varcmp((*vpp
)->var_text
, name
) == 0) {
2342 * Find the value of a variable. Returns NULL if not set.
2344 static const char* FAST_FUNC
2345 lookupvar(const char *name
)
2349 v
= *findvar(hashvar(name
), name
);
2351 #if ENABLE_ASH_RANDOM_SUPPORT || BASH_EPOCH_VARS
2353 * Dynamic variables are implemented roughly the same way they are
2354 * in bash. Namely, they're "special" so long as they aren't unset.
2355 * As soon as they're unset, they're no longer dynamic, and dynamic
2356 * lookup will no longer happen at that point. -- PFM.
2358 if (v
->flags
& VDYNAMIC
)
2361 if (!(v
->flags
& VUNSET
)) {
2362 if (v
->var_text
== linenovar
) {
2363 fmtstr(linenovar
+7, sizeof(linenovar
)-7, "%d", lineno
);
2365 if (v
->var_text
== funcnamevar
) {
2366 safe_strncpy(funcnamevar
+9, funcname
? funcname
: "", sizeof(funcnamevar
)-9);
2368 return var_end(v
->var_text
);
2374 #if ENABLE_UNICODE_SUPPORT
2376 reinit_unicode_for_ash(void)
2378 /* Unicode support should be activated even if LANG is set
2379 * _during_ shell execution, not only if it was set when
2380 * shell was started. Therefore, re-check LANG every time:
2382 if (ENABLE_FEATURE_CHECK_UNICODE_IN_ENV
2383 || ENABLE_UNICODE_USING_LOCALE
2385 const char *s
= lookupvar("LC_ALL");
2386 if (!s
) s
= lookupvar("LC_CTYPE");
2387 if (!s
) s
= lookupvar("LANG");
2392 # define reinit_unicode_for_ash() ((void)0)
2396 * Search the environment of a builtin command.
2398 static ALWAYS_INLINE
const char *
2399 bltinlookup(const char *name
)
2401 return lookupvar(name
);
2405 * Same as setvar except that the variable and value are passed in
2406 * the first argument as name=value. Since the first argument will
2407 * be actually stored in the table, it should not be a string that
2409 * Called with interrupts off.
2412 setvareq(char *s
, int flags
)
2414 struct var
*vp
, **vpp
;
2417 flags
|= (VEXPORT
& (((unsigned) (1 - aflag
)) - 1));
2418 vpp
= findvar(vpp
, s
);
2421 if ((vp
->flags
& (VREADONLY
|VDYNAMIC
)) == VREADONLY
) {
2424 if (flags
& VNOSAVE
)
2428 ash_msg_and_raise_error("%.*s: is read only", strchrnul(n
, '=') - n
, n
);
2434 if (vp
->var_func
&& !(flags
& VNOFUNC
))
2435 vp
->var_func(var_end(s
));
2437 if (!(vp
->flags
& (VTEXTFIXED
|VSTACK
)))
2438 free((char*)vp
->var_text
);
2440 if (((flags
& (VEXPORT
|VREADONLY
|VSTRFIXED
|VUNSET
)) | (vp
->flags
& VSTRFIXED
)) == VUNSET
) {
2444 if ((flags
& (VTEXTFIXED
|VSTACK
|VNOSAVE
)) == VNOSAVE
)
2449 flags
|= vp
->flags
& ~(VTEXTFIXED
|VSTACK
|VNOSAVE
|VUNSET
);
2450 #if ENABLE_ASH_RANDOM_SUPPORT || BASH_EPOCH_VARS
2455 /* variable s is not found */
2458 if ((flags
& (VEXPORT
|VREADONLY
|VSTRFIXED
|VUNSET
)) == VUNSET
)
2460 vp
= ckzalloc(sizeof(*vp
));
2462 /*vp->func = NULL; - ckzalloc did it */
2465 if (!(flags
& (VTEXTFIXED
|VSTACK
|VNOSAVE
)))
2475 * Set the value of a variable. The flags argument is ored with the
2476 * flags of the variable. If val is NULL, the variable is unset.
2479 setvar(const char *name
, const char *val
, int flags
)
2488 q
= endofname(name
);
2489 p
= strchrnul(q
, '=');
2491 if (!namelen
|| p
!= q
)
2492 ash_msg_and_raise_error("%.*s: bad variable name", namelen
, name
);
2497 vallen
= strlen(val
);
2501 nameeq
= ckzalloc(namelen
+ vallen
+ 2);
2502 p
= mempcpy(nameeq
, name
, namelen
);
2507 vp
= setvareq(nameeq
, flags
| VNOSAVE
);
2513 static void FAST_FUNC
2514 setvar0(const char *name
, const char *val
)
2516 setvar(name
, val
, 0);
2520 * Unset the specified variable.
2523 unsetvar(const char *s
)
2529 * Generate a list of variables satisfying the given conditions.
2531 #if !ENABLE_FEATURE_SH_NOFORK
2532 # define listvars(on, off, lp, end) listvars(on, off, end)
2535 listvars(int on
, int off
, struct strlist
*lp
, char ***end
)
2546 for (vp
= *vpp
; vp
; vp
= vp
->next
) {
2547 if ((vp
->flags
& mask
) == on
) {
2548 #if ENABLE_FEATURE_SH_NOFORK
2549 /* If variable with the same name is both
2550 * exported and temporarily set for a command:
2553 * then "ZVAR=6" will be both in vartab and
2554 * lp lists. Do not pass it twice to printenv.
2556 struct strlist
*lp1
= lp
;
2558 if (strcmp(lp1
->text
, vp
->var_text
) == 0)
2563 if (ep
== stackstrend())
2564 ep
= growstackstr();
2565 *ep
++ = (char*)vp
->var_text
;
2566 #if ENABLE_FEATURE_SH_NOFORK
2571 } while (++vpp
< vartab
+ VTABSIZE
);
2573 #if ENABLE_FEATURE_SH_NOFORK
2575 if (ep
== stackstrend())
2576 ep
= growstackstr();
2582 if (ep
== stackstrend())
2583 ep
= growstackstr();
2587 return grabstackstr(ep
);
2591 /* ============ Path search helper */
2593 legal_pathopt(const char *opt
, const char *term
, int magic
)
2601 opt
= prefix(opt
, "builtin") ?: prefix(opt
, "func");
2605 opt
+= strcspn(opt
, term
);
2609 if (opt
&& *opt
== '%')
2616 * The variable path (passed by reference) should be set to the start
2617 * of the path before the first call; padvance will update
2618 * this value as it proceeds. Successive calls to padvance will return
2619 * the possible path expansions in sequence. If an option (indicated by
2620 * a percent sign) appears in the path entry then the global variable
2621 * pathopt will be set to point to it; otherwise pathopt will be set to
2624 * If magic is 0 then pathopt recognition will be disabled. If magic is
2625 * 1 we shall recognise %builtin/%func. Otherwise we shall accept any
2628 static const char *pathopt
; /* set by padvance */
2631 padvance_magic(const char **path
, const char *name
, int magic
)
2633 const char *term
= "%:";
2634 const char *lpathopt
;
2647 if (*start
== '%' && (p
= legal_pathopt(start
+ 1, term
, magic
))) {
2648 lpathopt
= start
+ 1;
2653 len
= strcspn(start
, term
);
2657 size_t extra
= strchrnul(p
, ':') - p
;
2659 if (legal_pathopt(p
+ 1, term
, magic
))
2668 *path
= *p
== ':' ? p
+ 1 : NULL
;
2670 /* "2" is for '/' and '\0' */
2671 qlen
= len
+ strlen(name
) + 2;
2672 q
= growstackto(qlen
);
2675 q
= mempcpy(q
, start
, len
);
2684 padvance(const char **path
, const char *name
)
2686 return padvance_magic(path
, name
, 1);
2690 /* ============ Prompt */
2692 static smallint doprompt
; /* if set, prompt the user */
2693 static smallint needprompt
; /* true if interactive and at start of line */
2695 #if ENABLE_FEATURE_EDITING
2696 static line_input_t
*line_input_state
;
2697 static const char *cmdedit_prompt
;
2699 putprompt(const char *s
)
2701 if (ENABLE_ASH_EXPAND_PRMT
) {
2702 free((char*)cmdedit_prompt
);
2703 cmdedit_prompt
= ckstrdup(s
);
2710 putprompt(const char *s
)
2716 /* expandstr() needs parsing machinery, so it is far away ahead... */
2717 static const char *expandstr(const char *ps
, int syntax_type
);
2718 /* Values for syntax param */
2719 #define BASESYNTAX 0 /* not in quotes */
2720 #define DQSYNTAX 1 /* in double quotes */
2721 #define SQSYNTAX 2 /* in single quotes */
2722 #define ARISYNTAX 3 /* in arithmetic */
2723 #if ENABLE_ASH_EXPAND_PRMT
2724 # define PSSYNTAX 4 /* prompt. never passed to SIT() */
2726 /* PSSYNTAX expansion is identical to DQSYNTAX, except keeping '\$' as '\$' */
2729 * called by editline -- any expansions to the prompt should be added here.
2732 setprompt_if(smallint do_set
, int whichprompt
)
2735 IF_ASH_EXPAND_PRMT(struct stackmark smark
;)
2742 switch (whichprompt
) {
2752 #if ENABLE_ASH_EXPAND_PRMT
2753 pushstackmark(&smark
, stackblocksize());
2754 putprompt(expandstr(prompt
, PSSYNTAX
));
2755 popstackmark(&smark
);
2762 /* ============ The cd and pwd commands */
2764 #define CD_PHYSICAL 1
2774 while ((i
= nextopt("LP")) != '\0') {
2776 flags
^= CD_PHYSICAL
;
2785 * Update curdir (the name of the current directory) in response to a
2789 updatepwd(const char *dir
)
2796 cdcomppath
= sstrdup(dir
);
2799 if (curdir
== nullstr
)
2801 new = stack_putstr(curdir
, new);
2803 new = makestrspace(strlen(dir
) + 2, new);
2804 lim
= (char *)stackblock() + 1;
2808 if (new > lim
&& *lim
== '/')
2813 if (dir
[1] == '/' && dir
[2] != '/') {
2819 p
= strtok_r(cdcomppath
, "/", &cdcomppath
);
2823 if (p
[1] == '.' && p
[2] == '\0') {
2835 new = stack_putstr(p
, new);
2838 p
= strtok_r(NULL
, "/", &cdcomppath
);
2843 return stackblock();
2847 * Find out what the current directory is. If we already know the current
2848 * directory, this routine returns immediately.
2853 char *dir
= getcwd(NULL
, 0); /* huh, using glibc extension? */
2854 return dir
? dir
: nullstr
;
2858 setpwd(const char *val
, int setold
)
2862 oldcur
= dir
= curdir
;
2865 setvar("OLDPWD", oldcur
, VEXPORT
);
2868 if (physdir
!= nullstr
) {
2869 if (physdir
!= oldcur
)
2873 if (oldcur
== val
|| !val
) {
2879 dir
= ckstrdup(val
);
2880 if (oldcur
!= dir
&& oldcur
!= nullstr
) {
2885 setvar("PWD", dir
, VEXPORT
);
2888 static void hashcd(void);
2891 * Actually do the chdir. We also call hashcd to let other routines
2892 * know that the current directory has changed.
2895 docd(const char *dest
, int flags
)
2897 const char *dir
= NULL
;
2900 TRACE(("docd(\"%s\", %d) called\n", dest
, flags
));
2903 if (!(flags
& CD_PHYSICAL
)) {
2904 dir
= updatepwd(dest
);
2918 static int FAST_FUNC
2919 cdcmd(int argc UNUSED_PARAM
, char **argv UNUSED_PARAM
)
2932 dest
= bltinlookup("HOME");
2933 else if (LONE_DASH(dest
)) {
2934 dest
= bltinlookup("OLDPWD");
2956 path
= bltinlookup("CDPATH");
2957 while (p
= path
, (len
= padvance_magic(&path
, dest
, 0)) >= 0) {
2961 if (stat(p
, &statb
) >= 0 && S_ISDIR(statb
.st_mode
)) {
2965 if (!docd(p
, flags
))
2976 ash_msg_and_raise_perror("can't cd to %s", dest
);
2979 if (flags
& CD_PRINT
)
2980 out1fmt("%s\n", curdir
);
2984 static int FAST_FUNC
2985 pwdcmd(int argc UNUSED_PARAM
, char **argv UNUSED_PARAM
)
2988 const char *dir
= curdir
;
2992 if (physdir
== nullstr
)
2996 out1fmt("%s\n", dir
);
3001 /* ============ ... */
3004 #define IBUFSIZ (ENABLE_FEATURE_EDITING ? CONFIG_FEATURE_EDITING_MAX_LEN : 1024)
3006 /* Syntax classes */
3007 #define CWORD 0 /* character is nothing special */
3008 #define CNL 1 /* newline character */
3009 #define CBACK 2 /* a backslash character */
3010 #define CSQUOTE 3 /* single quote */
3011 #define CDQUOTE 4 /* double quote */
3012 #define CENDQUOTE 5 /* a terminating quote */
3013 #define CBQUOTE 6 /* backwards single quote */
3014 #define CVAR 7 /* a dollar sign */
3015 #define CENDVAR 8 /* a '}' character */
3016 #define CLP 9 /* a left paren in arithmetic */
3017 #define CRP 10 /* a right paren in arithmetic */
3018 #define CENDFILE 11 /* end of file */
3019 #define CCTL 12 /* like CWORD, except it must be escaped */
3020 #define CSPCL 13 /* these terminate a word */
3024 #define USE_SIT_FUNCTION ENABLE_ASH_OPTIMIZE_FOR_SIZE
3026 #if ENABLE_FEATURE_SH_MATH
3027 # define SIT_ITEM(a,b,c,d) (a | (b << 4) | (c << 8) | (d << 12))
3029 # define SIT_ITEM(a,b,c,d) (a | (b << 4) | (c << 8))
3031 static const uint16_t S_I_T
[] ALIGN2
= {
3032 SIT_ITEM(CSPCL
, CWORD
, CWORD
, CWORD
), /* 0, ' ' */
3033 SIT_ITEM(CNL
, CNL
, CNL
, CNL
), /* 1, \n */
3034 SIT_ITEM(CWORD
, CCTL
, CCTL
, CWORD
), /* 2, !*-/:=?[]~ */
3035 SIT_ITEM(CDQUOTE
, CENDQUOTE
, CWORD
, CWORD
), /* 3, '"' */
3036 SIT_ITEM(CVAR
, CVAR
, CWORD
, CVAR
), /* 4, $ */
3037 SIT_ITEM(CSQUOTE
, CWORD
, CENDQUOTE
, CWORD
), /* 5, "'" */
3038 SIT_ITEM(CSPCL
, CWORD
, CWORD
, CLP
), /* 6, ( */
3039 SIT_ITEM(CSPCL
, CWORD
, CWORD
, CRP
), /* 7, ) */
3040 SIT_ITEM(CBACK
, CBACK
, CCTL
, CBACK
), /* 8, \ */
3041 SIT_ITEM(CBQUOTE
, CBQUOTE
, CWORD
, CBQUOTE
), /* 9, ` */
3042 SIT_ITEM(CENDVAR
, CENDVAR
, CWORD
, CENDVAR
), /* 10, } */
3043 #if !USE_SIT_FUNCTION
3044 SIT_ITEM(CENDFILE
, CENDFILE
, CENDFILE
, CENDFILE
),/* 11, PEOF */
3045 SIT_ITEM(CWORD
, CWORD
, CWORD
, CWORD
), /* 12, 0-9A-Za-z */
3046 SIT_ITEM(CCTL
, CCTL
, CCTL
, CCTL
) /* 13, CTLESC ... */
3050 /* Constants below must match table above */
3052 CSPCL_CWORD_CWORD_CWORD
, /* 0 */
3053 CNL_CNL_CNL_CNL
, /* 1 */
3054 CWORD_CCTL_CCTL_CWORD
, /* 2 */
3055 CDQUOTE_CENDQUOTE_CWORD_CWORD
, /* 3 */
3056 CVAR_CVAR_CWORD_CVAR
, /* 4 */
3057 CSQUOTE_CWORD_CENDQUOTE_CWORD
, /* 5 */
3058 CSPCL_CWORD_CWORD_CLP
, /* 6 */
3059 CSPCL_CWORD_CWORD_CRP
, /* 7 */
3060 CBACK_CBACK_CCTL_CBACK
, /* 8 */
3061 CBQUOTE_CBQUOTE_CWORD_CBQUOTE
, /* 9 */
3062 CENDVAR_CENDVAR_CWORD_CENDVAR
, /* 10 */
3063 CENDFILE_CENDFILE_CENDFILE_CENDFILE
, /* 11 */
3064 CWORD_CWORD_CWORD_CWORD
, /* 12 */
3065 CCTL_CCTL_CCTL_CCTL
, /* 13 */
3068 /* c in SIT(c, syntax) must be an *unsigned char* or PEOF,
3069 * caller must ensure proper cast on it if c is *char_ptr!
3071 #if USE_SIT_FUNCTION
3074 SIT(int c
, int syntax
)
3076 /* Used to also have '/' in this string: "\t\n !\"$&'()*-/:;<=>?[\\]`|}~" */
3077 static const char spec_symbls
[] ALIGN1
= "\t\n !\"$&'()*-:;<=>?[\\]`|}~";
3079 * This causes '/' to be prepended with CTLESC in dquoted string,
3080 * making "./file"* treated incorrectly because we feed
3081 * ".\/file*" string to glob(), confusing it (see expandmeta func).
3082 * The "homegrown" glob implementation is okay with that,
3083 * but glibc one isn't. With '/' always treated as CWORD,
3086 static const uint8_t syntax_index_table
[] ALIGN1
= {
3087 0, 1, 0, 2, 3, 4, 0, 5, /* "\t\n !\"$&'" */
3088 6, 7, 2, 2,/*2,*/2, 0, 0, /* "()*-/:;<" */
3089 2, 0, 2, 2, 8, 2, 9, 0, /* "=>?[\\]`|" */
3097 /* Cast is purely for paranoia here,
3098 * just in case someone passed signed char to us */
3099 if ((unsigned char)c
>= CTL_FIRST
3100 && (unsigned char)c
<= CTL_LAST
3104 s
= strchrnul(spec_symbls
, c
);
3107 indx
= syntax_index_table
[s
- spec_symbls
];
3108 return (S_I_T
[indx
] >> (syntax
*4)) & 0xf;
3111 #else /* !USE_SIT_FUNCTION */
3113 static const uint8_t syntax_index_table
[] ALIGN1
= {
3114 /* BASESYNTAX_DQSYNTAX_SQSYNTAX_ARISYNTAX */
3115 /* 0 */ CWORD_CWORD_CWORD_CWORD
,
3116 /* 1 */ CWORD_CWORD_CWORD_CWORD
,
3117 /* 2 */ CWORD_CWORD_CWORD_CWORD
,
3118 /* 3 */ CWORD_CWORD_CWORD_CWORD
,
3119 /* 4 */ CWORD_CWORD_CWORD_CWORD
,
3120 /* 5 */ CWORD_CWORD_CWORD_CWORD
,
3121 /* 6 */ CWORD_CWORD_CWORD_CWORD
,
3122 /* 7 */ CWORD_CWORD_CWORD_CWORD
,
3123 /* 8 */ CWORD_CWORD_CWORD_CWORD
,
3124 /* 9 "\t" */ CSPCL_CWORD_CWORD_CWORD
,
3125 /* 10 "\n" */ CNL_CNL_CNL_CNL
,
3126 /* 11 */ CWORD_CWORD_CWORD_CWORD
,
3127 /* 12 */ CWORD_CWORD_CWORD_CWORD
,
3128 /* 13 */ CWORD_CWORD_CWORD_CWORD
,
3129 /* 14 */ CWORD_CWORD_CWORD_CWORD
,
3130 /* 15 */ CWORD_CWORD_CWORD_CWORD
,
3131 /* 16 */ CWORD_CWORD_CWORD_CWORD
,
3132 /* 17 */ CWORD_CWORD_CWORD_CWORD
,
3133 /* 18 */ CWORD_CWORD_CWORD_CWORD
,
3134 /* 19 */ CWORD_CWORD_CWORD_CWORD
,
3135 /* 20 */ CWORD_CWORD_CWORD_CWORD
,
3136 /* 21 */ CWORD_CWORD_CWORD_CWORD
,
3137 /* 22 */ CWORD_CWORD_CWORD_CWORD
,
3138 /* 23 */ CWORD_CWORD_CWORD_CWORD
,
3139 /* 24 */ CWORD_CWORD_CWORD_CWORD
,
3140 /* 25 */ CWORD_CWORD_CWORD_CWORD
,
3141 /* 26 */ CWORD_CWORD_CWORD_CWORD
,
3142 /* 27 */ CWORD_CWORD_CWORD_CWORD
,
3143 /* 28 */ CWORD_CWORD_CWORD_CWORD
,
3144 /* 29 */ CWORD_CWORD_CWORD_CWORD
,
3145 /* 30 */ CWORD_CWORD_CWORD_CWORD
,
3146 /* 31 */ CWORD_CWORD_CWORD_CWORD
,
3147 /* 32 " " */ CSPCL_CWORD_CWORD_CWORD
,
3148 /* 33 "!" */ CWORD_CCTL_CCTL_CWORD
,
3149 /* 34 """ */ CDQUOTE_CENDQUOTE_CWORD_CWORD
,
3150 /* 35 "#" */ CWORD_CWORD_CWORD_CWORD
,
3151 /* 36 "$" */ CVAR_CVAR_CWORD_CVAR
,
3152 /* 37 "%" */ CWORD_CWORD_CWORD_CWORD
,
3153 /* 38 "&" */ CSPCL_CWORD_CWORD_CWORD
,
3154 /* 39 "'" */ CSQUOTE_CWORD_CENDQUOTE_CWORD
,
3155 /* 40 "(" */ CSPCL_CWORD_CWORD_CLP
,
3156 /* 41 ")" */ CSPCL_CWORD_CWORD_CRP
,
3157 /* 42 "*" */ CWORD_CCTL_CCTL_CWORD
,
3158 /* 43 "+" */ CWORD_CWORD_CWORD_CWORD
,
3159 /* 44 "," */ CWORD_CWORD_CWORD_CWORD
,
3160 /* 45 "-" */ CWORD_CCTL_CCTL_CWORD
,
3161 /* 46 "." */ CWORD_CWORD_CWORD_CWORD
,
3162 /* "/" was CWORD_CCTL_CCTL_CWORD, see comment in SIT() function why this is changed: */
3163 /* 47 "/" */ CWORD_CWORD_CWORD_CWORD
,
3164 /* 48 "0" */ CWORD_CWORD_CWORD_CWORD
,
3165 /* 49 "1" */ CWORD_CWORD_CWORD_CWORD
,
3166 /* 50 "2" */ CWORD_CWORD_CWORD_CWORD
,
3167 /* 51 "3" */ CWORD_CWORD_CWORD_CWORD
,
3168 /* 52 "4" */ CWORD_CWORD_CWORD_CWORD
,
3169 /* 53 "5" */ CWORD_CWORD_CWORD_CWORD
,
3170 /* 54 "6" */ CWORD_CWORD_CWORD_CWORD
,
3171 /* 55 "7" */ CWORD_CWORD_CWORD_CWORD
,
3172 /* 56 "8" */ CWORD_CWORD_CWORD_CWORD
,
3173 /* 57 "9" */ CWORD_CWORD_CWORD_CWORD
,
3174 /* 58 ":" */ CWORD_CCTL_CCTL_CWORD
,
3175 /* 59 ";" */ CSPCL_CWORD_CWORD_CWORD
,
3176 /* 60 "<" */ CSPCL_CWORD_CWORD_CWORD
,
3177 /* 61 "=" */ CWORD_CCTL_CCTL_CWORD
,
3178 /* 62 ">" */ CSPCL_CWORD_CWORD_CWORD
,
3179 /* 63 "?" */ CWORD_CCTL_CCTL_CWORD
,
3180 /* 64 "@" */ CWORD_CWORD_CWORD_CWORD
,
3181 /* 65 "A" */ CWORD_CWORD_CWORD_CWORD
,
3182 /* 66 "B" */ CWORD_CWORD_CWORD_CWORD
,
3183 /* 67 "C" */ CWORD_CWORD_CWORD_CWORD
,
3184 /* 68 "D" */ CWORD_CWORD_CWORD_CWORD
,
3185 /* 69 "E" */ CWORD_CWORD_CWORD_CWORD
,
3186 /* 70 "F" */ CWORD_CWORD_CWORD_CWORD
,
3187 /* 71 "G" */ CWORD_CWORD_CWORD_CWORD
,
3188 /* 72 "H" */ CWORD_CWORD_CWORD_CWORD
,
3189 /* 73 "I" */ CWORD_CWORD_CWORD_CWORD
,
3190 /* 74 "J" */ CWORD_CWORD_CWORD_CWORD
,
3191 /* 75 "K" */ CWORD_CWORD_CWORD_CWORD
,
3192 /* 76 "L" */ CWORD_CWORD_CWORD_CWORD
,
3193 /* 77 "M" */ CWORD_CWORD_CWORD_CWORD
,
3194 /* 78 "N" */ CWORD_CWORD_CWORD_CWORD
,
3195 /* 79 "O" */ CWORD_CWORD_CWORD_CWORD
,
3196 /* 80 "P" */ CWORD_CWORD_CWORD_CWORD
,
3197 /* 81 "Q" */ CWORD_CWORD_CWORD_CWORD
,
3198 /* 82 "R" */ CWORD_CWORD_CWORD_CWORD
,
3199 /* 83 "S" */ CWORD_CWORD_CWORD_CWORD
,
3200 /* 84 "T" */ CWORD_CWORD_CWORD_CWORD
,
3201 /* 85 "U" */ CWORD_CWORD_CWORD_CWORD
,
3202 /* 86 "V" */ CWORD_CWORD_CWORD_CWORD
,
3203 /* 87 "W" */ CWORD_CWORD_CWORD_CWORD
,
3204 /* 88 "X" */ CWORD_CWORD_CWORD_CWORD
,
3205 /* 89 "Y" */ CWORD_CWORD_CWORD_CWORD
,
3206 /* 90 "Z" */ CWORD_CWORD_CWORD_CWORD
,
3207 /* 91 "[" */ CWORD_CCTL_CCTL_CWORD
,
3208 /* 92 "\" */ CBACK_CBACK_CCTL_CBACK
,
3209 /* 93 "]" */ CWORD_CCTL_CCTL_CWORD
,
3210 /* 94 "^" */ CWORD_CWORD_CWORD_CWORD
,
3211 /* 95 "_" */ CWORD_CWORD_CWORD_CWORD
,
3212 /* 96 "`" */ CBQUOTE_CBQUOTE_CWORD_CBQUOTE
,
3213 /* 97 "a" */ CWORD_CWORD_CWORD_CWORD
,
3214 /* 98 "b" */ CWORD_CWORD_CWORD_CWORD
,
3215 /* 99 "c" */ CWORD_CWORD_CWORD_CWORD
,
3216 /* 100 "d" */ CWORD_CWORD_CWORD_CWORD
,
3217 /* 101 "e" */ CWORD_CWORD_CWORD_CWORD
,
3218 /* 102 "f" */ CWORD_CWORD_CWORD_CWORD
,
3219 /* 103 "g" */ CWORD_CWORD_CWORD_CWORD
,
3220 /* 104 "h" */ CWORD_CWORD_CWORD_CWORD
,
3221 /* 105 "i" */ CWORD_CWORD_CWORD_CWORD
,
3222 /* 106 "j" */ CWORD_CWORD_CWORD_CWORD
,
3223 /* 107 "k" */ CWORD_CWORD_CWORD_CWORD
,
3224 /* 108 "l" */ CWORD_CWORD_CWORD_CWORD
,
3225 /* 109 "m" */ CWORD_CWORD_CWORD_CWORD
,
3226 /* 110 "n" */ CWORD_CWORD_CWORD_CWORD
,
3227 /* 111 "o" */ CWORD_CWORD_CWORD_CWORD
,
3228 /* 112 "p" */ CWORD_CWORD_CWORD_CWORD
,
3229 /* 113 "q" */ CWORD_CWORD_CWORD_CWORD
,
3230 /* 114 "r" */ CWORD_CWORD_CWORD_CWORD
,
3231 /* 115 "s" */ CWORD_CWORD_CWORD_CWORD
,
3232 /* 116 "t" */ CWORD_CWORD_CWORD_CWORD
,
3233 /* 117 "u" */ CWORD_CWORD_CWORD_CWORD
,
3234 /* 118 "v" */ CWORD_CWORD_CWORD_CWORD
,
3235 /* 119 "w" */ CWORD_CWORD_CWORD_CWORD
,
3236 /* 120 "x" */ CWORD_CWORD_CWORD_CWORD
,
3237 /* 121 "y" */ CWORD_CWORD_CWORD_CWORD
,
3238 /* 122 "z" */ CWORD_CWORD_CWORD_CWORD
,
3239 /* 123 "{" */ CWORD_CWORD_CWORD_CWORD
,
3240 /* 124 "|" */ CSPCL_CWORD_CWORD_CWORD
,
3241 /* 125 "}" */ CENDVAR_CENDVAR_CWORD_CENDVAR
,
3242 /* 126 "~" */ CWORD_CCTL_CCTL_CWORD
,
3243 /* 127 del */ CWORD_CWORD_CWORD_CWORD
,
3244 /* 128 0x80 */ CWORD_CWORD_CWORD_CWORD
,
3245 /* 129 CTLESC */ CCTL_CCTL_CCTL_CCTL
,
3246 /* 130 CTLVAR */ CCTL_CCTL_CCTL_CCTL
,
3247 /* 131 CTLENDVAR */ CCTL_CCTL_CCTL_CCTL
,
3248 /* 132 CTLBACKQ */ CCTL_CCTL_CCTL_CCTL
,
3249 /* 133 CTLQUOTE */ CCTL_CCTL_CCTL_CCTL
,
3250 /* 134 CTLARI */ CCTL_CCTL_CCTL_CCTL
,
3251 /* 135 CTLENDARI */ CCTL_CCTL_CCTL_CCTL
,
3252 /* 136 CTLQUOTEMARK */ CCTL_CCTL_CCTL_CCTL
,
3253 #if BASH_PROCESS_SUBST
3254 /* 137 CTLTOPROC */ CCTL_CCTL_CCTL_CCTL
,
3255 /* 138 CTLFROMPROC */ CCTL_CCTL_CCTL_CCTL
,
3257 /* 137 */ CWORD_CWORD_CWORD_CWORD
,
3258 /* 138 */ CWORD_CWORD_CWORD_CWORD
,
3260 /* 139 */ CWORD_CWORD_CWORD_CWORD
,
3261 /* 140 */ CWORD_CWORD_CWORD_CWORD
,
3262 /* 141 */ CWORD_CWORD_CWORD_CWORD
,
3263 /* 142 */ CWORD_CWORD_CWORD_CWORD
,
3264 /* 143 */ CWORD_CWORD_CWORD_CWORD
,
3265 /* 144 */ CWORD_CWORD_CWORD_CWORD
,
3266 /* 145 */ CWORD_CWORD_CWORD_CWORD
,
3267 /* 146 */ CWORD_CWORD_CWORD_CWORD
,
3268 /* 147 */ CWORD_CWORD_CWORD_CWORD
,
3269 /* 148 */ CWORD_CWORD_CWORD_CWORD
,
3270 /* 149 */ CWORD_CWORD_CWORD_CWORD
,
3271 /* 150 */ CWORD_CWORD_CWORD_CWORD
,
3272 /* 151 */ CWORD_CWORD_CWORD_CWORD
,
3273 /* 152 */ CWORD_CWORD_CWORD_CWORD
,
3274 /* 153 */ CWORD_CWORD_CWORD_CWORD
,
3275 /* 154 */ CWORD_CWORD_CWORD_CWORD
,
3276 /* 155 */ CWORD_CWORD_CWORD_CWORD
,
3277 /* 156 */ CWORD_CWORD_CWORD_CWORD
,
3278 /* 157 */ CWORD_CWORD_CWORD_CWORD
,
3279 /* 158 */ CWORD_CWORD_CWORD_CWORD
,
3280 /* 159 */ CWORD_CWORD_CWORD_CWORD
,
3281 /* 160 */ CWORD_CWORD_CWORD_CWORD
,
3282 /* 161 */ CWORD_CWORD_CWORD_CWORD
,
3283 /* 162 */ CWORD_CWORD_CWORD_CWORD
,
3284 /* 163 */ CWORD_CWORD_CWORD_CWORD
,
3285 /* 164 */ CWORD_CWORD_CWORD_CWORD
,
3286 /* 165 */ CWORD_CWORD_CWORD_CWORD
,
3287 /* 166 */ CWORD_CWORD_CWORD_CWORD
,
3288 /* 167 */ CWORD_CWORD_CWORD_CWORD
,
3289 /* 168 */ CWORD_CWORD_CWORD_CWORD
,
3290 /* 169 */ CWORD_CWORD_CWORD_CWORD
,
3291 /* 170 */ CWORD_CWORD_CWORD_CWORD
,
3292 /* 171 */ CWORD_CWORD_CWORD_CWORD
,
3293 /* 172 */ CWORD_CWORD_CWORD_CWORD
,
3294 /* 173 */ CWORD_CWORD_CWORD_CWORD
,
3295 /* 174 */ CWORD_CWORD_CWORD_CWORD
,
3296 /* 175 */ CWORD_CWORD_CWORD_CWORD
,
3297 /* 176 */ CWORD_CWORD_CWORD_CWORD
,
3298 /* 177 */ CWORD_CWORD_CWORD_CWORD
,
3299 /* 178 */ CWORD_CWORD_CWORD_CWORD
,
3300 /* 179 */ CWORD_CWORD_CWORD_CWORD
,
3301 /* 180 */ CWORD_CWORD_CWORD_CWORD
,
3302 /* 181 */ CWORD_CWORD_CWORD_CWORD
,
3303 /* 182 */ CWORD_CWORD_CWORD_CWORD
,
3304 /* 183 */ CWORD_CWORD_CWORD_CWORD
,
3305 /* 184 */ CWORD_CWORD_CWORD_CWORD
,
3306 /* 185 */ CWORD_CWORD_CWORD_CWORD
,
3307 /* 186 */ CWORD_CWORD_CWORD_CWORD
,
3308 /* 187 */ CWORD_CWORD_CWORD_CWORD
,
3309 /* 188 */ CWORD_CWORD_CWORD_CWORD
,
3310 /* 189 */ CWORD_CWORD_CWORD_CWORD
,
3311 /* 190 */ CWORD_CWORD_CWORD_CWORD
,
3312 /* 191 */ CWORD_CWORD_CWORD_CWORD
,
3313 /* 192 */ CWORD_CWORD_CWORD_CWORD
,
3314 /* 193 */ CWORD_CWORD_CWORD_CWORD
,
3315 /* 194 */ CWORD_CWORD_CWORD_CWORD
,
3316 /* 195 */ CWORD_CWORD_CWORD_CWORD
,
3317 /* 196 */ CWORD_CWORD_CWORD_CWORD
,
3318 /* 197 */ CWORD_CWORD_CWORD_CWORD
,
3319 /* 198 */ CWORD_CWORD_CWORD_CWORD
,
3320 /* 199 */ CWORD_CWORD_CWORD_CWORD
,
3321 /* 200 */ CWORD_CWORD_CWORD_CWORD
,
3322 /* 201 */ CWORD_CWORD_CWORD_CWORD
,
3323 /* 202 */ CWORD_CWORD_CWORD_CWORD
,
3324 /* 203 */ CWORD_CWORD_CWORD_CWORD
,
3325 /* 204 */ CWORD_CWORD_CWORD_CWORD
,
3326 /* 205 */ CWORD_CWORD_CWORD_CWORD
,
3327 /* 206 */ CWORD_CWORD_CWORD_CWORD
,
3328 /* 207 */ CWORD_CWORD_CWORD_CWORD
,
3329 /* 208 */ CWORD_CWORD_CWORD_CWORD
,
3330 /* 209 */ CWORD_CWORD_CWORD_CWORD
,
3331 /* 210 */ CWORD_CWORD_CWORD_CWORD
,
3332 /* 211 */ CWORD_CWORD_CWORD_CWORD
,
3333 /* 212 */ CWORD_CWORD_CWORD_CWORD
,
3334 /* 213 */ CWORD_CWORD_CWORD_CWORD
,
3335 /* 214 */ CWORD_CWORD_CWORD_CWORD
,
3336 /* 215 */ CWORD_CWORD_CWORD_CWORD
,
3337 /* 216 */ CWORD_CWORD_CWORD_CWORD
,
3338 /* 217 */ CWORD_CWORD_CWORD_CWORD
,
3339 /* 218 */ CWORD_CWORD_CWORD_CWORD
,
3340 /* 219 */ CWORD_CWORD_CWORD_CWORD
,
3341 /* 220 */ CWORD_CWORD_CWORD_CWORD
,
3342 /* 221 */ CWORD_CWORD_CWORD_CWORD
,
3343 /* 222 */ CWORD_CWORD_CWORD_CWORD
,
3344 /* 223 */ CWORD_CWORD_CWORD_CWORD
,
3345 /* 224 */ CWORD_CWORD_CWORD_CWORD
,
3346 /* 225 */ CWORD_CWORD_CWORD_CWORD
,
3347 /* 226 */ CWORD_CWORD_CWORD_CWORD
,
3348 /* 227 */ CWORD_CWORD_CWORD_CWORD
,
3349 /* 228 */ CWORD_CWORD_CWORD_CWORD
,
3350 /* 229 */ CWORD_CWORD_CWORD_CWORD
,
3351 /* 230 */ CWORD_CWORD_CWORD_CWORD
,
3352 /* 231 */ CWORD_CWORD_CWORD_CWORD
,
3353 /* 232 */ CWORD_CWORD_CWORD_CWORD
,
3354 /* 233 */ CWORD_CWORD_CWORD_CWORD
,
3355 /* 234 */ CWORD_CWORD_CWORD_CWORD
,
3356 /* 235 */ CWORD_CWORD_CWORD_CWORD
,
3357 /* 236 */ CWORD_CWORD_CWORD_CWORD
,
3358 /* 237 */ CWORD_CWORD_CWORD_CWORD
,
3359 /* 238 */ CWORD_CWORD_CWORD_CWORD
,
3360 /* 239 */ CWORD_CWORD_CWORD_CWORD
,
3361 /* 230 */ CWORD_CWORD_CWORD_CWORD
,
3362 /* 241 */ CWORD_CWORD_CWORD_CWORD
,
3363 /* 242 */ CWORD_CWORD_CWORD_CWORD
,
3364 /* 243 */ CWORD_CWORD_CWORD_CWORD
,
3365 /* 244 */ CWORD_CWORD_CWORD_CWORD
,
3366 /* 245 */ CWORD_CWORD_CWORD_CWORD
,
3367 /* 246 */ CWORD_CWORD_CWORD_CWORD
,
3368 /* 247 */ CWORD_CWORD_CWORD_CWORD
,
3369 /* 248 */ CWORD_CWORD_CWORD_CWORD
,
3370 /* 249 */ CWORD_CWORD_CWORD_CWORD
,
3371 /* 250 */ CWORD_CWORD_CWORD_CWORD
,
3372 /* 251 */ CWORD_CWORD_CWORD_CWORD
,
3373 /* 252 */ CWORD_CWORD_CWORD_CWORD
,
3374 /* 253 */ CWORD_CWORD_CWORD_CWORD
,
3375 /* 254 */ CWORD_CWORD_CWORD_CWORD
,
3376 /* 255 */ CWORD_CWORD_CWORD_CWORD
,
3377 /* PEOF */ CENDFILE_CENDFILE_CENDFILE_CENDFILE
,
3381 # define SIT(c, syntax) ((S_I_T[syntax_index_table[c]] >> ((syntax)*4)) & 0xf)
3382 #else /* debug version, caught one signed char bug */
3383 # define SIT(c, syntax) \
3385 if ((c) < 0 || (c) > (PEOF + ENABLE_ASH_ALIAS)) \
3386 bb_error_msg_and_die("line:%d c:%d", __LINE__, (c)); \
3387 if ((syntax) < 0 || (syntax) > (2 + ENABLE_FEATURE_SH_MATH)) \
3388 bb_error_msg_and_die("line:%d c:%d", __LINE__, (c)); \
3389 ((S_I_T[syntax_index_table[c]] >> ((syntax)*4)) & 0xf); \
3393 #endif /* !USE_SIT_FUNCTION */
3396 /* ============ Alias handling */
3398 #if ENABLE_ASH_ALIAS
3400 #define ALIASINUSE 1
3411 static struct alias
**atab
; // [ATABSIZE];
3412 #define INIT_G_alias() do { \
3413 atab = xzalloc(ATABSIZE * sizeof(atab[0])); \
3417 static struct alias
**
3418 __lookupalias(const char *name
)
3420 unsigned int hashval
;
3427 ch
= (unsigned char)*p
;
3431 ch
= (unsigned char)*++p
;
3433 app
= &atab
[hashval
% ATABSIZE
];
3435 for (; *app
; app
= &(*app
)->next
) {
3436 if (strcmp(name
, (*app
)->name
) == 0) {
3444 static struct alias
*
3445 lookupalias(const char *name
, int check
)
3447 struct alias
*ap
= *__lookupalias(name
);
3449 if (check
&& ap
&& (ap
->flag
& ALIASINUSE
))
3454 static struct alias
*
3455 freealias(struct alias
*ap
)
3459 if (ap
->flag
& ALIASINUSE
) {
3460 ap
->flag
|= ALIASDEAD
;
3472 setalias(const char *name
, const char *val
)
3474 struct alias
*ap
, **app
;
3476 app
= __lookupalias(name
);
3480 if (!(ap
->flag
& ALIASINUSE
)) {
3483 ap
->val
= ckstrdup(val
);
3484 ap
->flag
&= ~ALIASDEAD
;
3487 ap
= ckzalloc(sizeof(struct alias
));
3488 ap
->name
= ckstrdup(name
);
3489 ap
->val
= ckstrdup(val
);
3490 /*ap->flag = 0; - ckzalloc did it */
3491 /*ap->next = NULL;*/
3498 unalias(const char *name
)
3502 app
= __lookupalias(name
);
3506 *app
= freealias(*app
);
3517 struct alias
*ap
, **app
;
3521 for (i
= 0; i
< ATABSIZE
; i
++) {
3523 for (ap
= *app
; ap
; ap
= *app
) {
3524 *app
= freealias(*app
);
3534 printalias(const struct alias
*ap
)
3536 out1fmt("%s=%s\n", ap
->name
, single_quote(ap
->val
));
3540 * TODO - sort output
3542 static int FAST_FUNC
3543 aliascmd(int argc UNUSED_PARAM
, char **argv
)
3552 for (i
= 0; i
< ATABSIZE
; i
++) {
3553 for (ap
= atab
[i
]; ap
; ap
= ap
->next
) {
3559 while ((n
= *++argv
) != NULL
) {
3560 v
= strchr(n
+1, '=');
3561 if (v
== NULL
) { /* n+1: funny ksh stuff */
3562 ap
= *__lookupalias(n
);
3564 fprintf(stderr
, "%s: %s not found\n", "alias", n
);
3577 static int FAST_FUNC
3578 unaliascmd(int argc UNUSED_PARAM
, char **argv UNUSED_PARAM
)
3582 while (nextopt("a") != '\0') {
3586 for (i
= 0; *argptr
; argptr
++) {
3587 if (unalias(*argptr
)) {
3588 fprintf(stderr
, "%s: %s not found\n", "unalias", *argptr
);
3596 #endif /* ASH_ALIAS */
3599 /* Mode argument to forkshell. Don't change FORK_FG or FORK_BG. */
3602 #define FORK_NOJOB 2
3604 /* mode flags for showjob(s) */
3605 #define SHOW_ONLY_PGID 0x01 /* show only pgid (jobs -p) */
3606 #define SHOW_PIDS 0x02 /* show individual pids, not just one line per job */
3607 #define SHOW_CHANGED 0x04 /* only jobs whose state has changed */
3608 #define SHOW_STDERR 0x08 /* print to stderr (else stdout) */
3611 * A job structure contains information about a job. A job is either a
3612 * single process or a set of processes contained in a pipeline. In the
3613 * latter case, pidlist will be non-NULL, and will point to a -1 terminated
3617 pid_t ps_pid
; /* process id */
3618 int ps_status
; /* last process status from wait() */
3619 char *ps_cmd
; /* text of command being run */
3623 struct procstat ps0
; /* status of process */
3624 struct procstat
*ps
; /* status of processes when more than one */
3626 int stopstatus
; /* status of a stopped job */
3628 unsigned nprocs
; /* number of processes */
3630 #define JOBRUNNING 0 /* at least one proc running */
3631 #define JOBSTOPPED 1 /* all procs are stopped */
3632 #define JOBDONE 2 /* all procs are completed */
3636 sigint
: 1, /* job was killed by SIGINT */
3637 jobctl
: 1, /* job running under job control */
3639 waited
: 1, /* true if this entry has been waited for */
3640 used
: 1, /* true if this entry is in used */
3641 changed
: 1; /* true if status has changed */
3642 struct job
*prev_job
; /* previous job */
3645 static struct job
*makejob(/*union node *,*/ int);
3646 static int forkshell(struct job
*, union node
*, int);
3647 static int waitforjob(struct job
*);
3650 enum { doing_jobctl
= 0 };
3651 #define setjobctl(on) do {} while (0)
3653 static smallint doing_jobctl
; //references:8
3654 static void setjobctl(int);
3661 ignoresig(int signo
)
3663 /* Avoid unnecessary system calls. Is it already SIG_IGNed? */
3664 if (sigmode
[signo
- 1] != S_IGN
&& sigmode
[signo
- 1] != S_HARD_IGN
) {
3665 /* No, need to do it */
3666 signal(signo
, SIG_IGN
);
3668 sigmode
[signo
- 1] = S_HARD_IGN
;
3672 * Only one usage site - in setsignal()
3675 signal_handler(int signo
)
3677 if (signo
== SIGCHLD
) {
3682 #if ENABLE_FEATURE_EDITING
3683 bb_got_signal
= signo
; /* for read_line_input: "we got a signal" */
3685 gotsig
[signo
- 1] = 1;
3686 pending_sig
= signo
;
3688 if (signo
== SIGINT
&& !trap
[SIGINT
]) {
3689 if (!suppress_int
) {
3691 raise_interrupt(); /* does not return */
3698 * Set the signal handler for the specified signal. The routine figures
3699 * out what it should be set to.
3702 setsignal(int signo
)
3705 char cur_act
, new_act
;
3706 struct sigaction act
;
3710 if (t
!= NULL
) { /* trap for this sig is set */
3712 if (t
[0] == '\0') /* trap is "": ignore this sig */
3716 if (rootshell
&& new_act
== S_DFL
) {
3719 if (iflag
|| minusc
|| sflag
== 0)
3728 * "In all cases, bash ignores SIGQUIT. Non-builtin
3729 * commands run by bash have signal handlers
3730 * set to the values inherited by the shell
3731 * from its parent". */
3747 /* if !rootshell, we reset SIGQUIT to DFL,
3748 * whereas we have to restore it to what shell got on entry.
3749 * This is handled by the fact that if signal was IGNored on entry,
3750 * then cur_act is S_HARD_IGN and we never change its sigaction
3754 if (signo
== SIGCHLD
)
3757 t
= &sigmode
[signo
- 1];
3760 /* current setting is not yet known */
3761 if (sigaction(signo
, NULL
, &act
)) {
3762 /* pretend it worked; maybe we should give a warning,
3763 * but other shells don't. We don't alter sigmode,
3764 * so we retry every time.
3765 * btw, in Linux it never fails. --vda */
3768 if (act
.sa_handler
== SIG_IGN
) {
3769 cur_act
= S_HARD_IGN
;
3771 && (signo
== SIGTSTP
|| signo
== SIGTTIN
|| signo
== SIGTTOU
)
3773 cur_act
= S_IGN
; /* don't hard ignore these */
3776 if (act
.sa_handler
== SIG_DFL
&& new_act
== S_DFL
) {
3777 /* installing SIG_DFL over SIG_DFL is a no-op */
3778 /* saves one sigaction call in each "sh -c SCRIPT" invocation */
3783 if (cur_act
== S_HARD_IGN
|| cur_act
== new_act
)
3788 act
.sa_handler
= SIG_DFL
;
3791 act
.sa_handler
= signal_handler
;
3794 act
.sa_handler
= SIG_IGN
;
3797 /* flags and mask matter only if !DFL and !IGN, but we do it
3798 * for all cases for more deterministic behavior:
3800 act
.sa_flags
= 0; //TODO: why not SA_RESTART?
3801 sigfillset(&act
.sa_mask
);
3803 sigaction_set(signo
, &act
);
3806 /* mode flags for set_curjob */
3807 #define CUR_DELETE 2
3808 #define CUR_RUNNING 1
3809 #define CUR_STOPPED 0
3812 /* pgrp of shell on invocation */
3813 static int initialpgrp
; //references:2
3814 static int ttyfd
= -1; //5
3817 static struct job
*jobtab
; //5
3819 static unsigned njobs
; //4
3821 static struct job
*curjob
; //lots
3824 /* Bash has a feature: it restores termios after a successful wait for
3825 * a foreground job which had at least one stopped or sigkilled member.
3826 * The probable rationale is that SIGSTOP and SIGKILL can preclude task from
3827 * properly restoring tty state. Should we do this too?
3828 * A reproducer: ^Z an interactive python:
3831 * Python 2.7.12 (...)
3833 * { python leaves tty in -icanon -echo state. We do survive that... }
3834 * [1]+ Stopped python
3835 * { ...however, next program (python #2) does not survive it well: }
3837 * Python 2.7.12 (...)
3838 * >>> Traceback (most recent call last):
3839 * { above, I typed "qwerty<CR>", but -echo state is still in effect }
3840 * File "<stdin>", line 1, in <module>
3841 * NameError: name 'qwerty' is not defined
3843 * The implementation below is modeled on bash code and seems to work.
3844 * However, I'm not sure we should do this. For one: what if I'd fg
3845 * the stopped python instead? It'll be confused by "restored" tty state.
3847 static struct termios shell_tty_info
;
3851 if (rootshell
&& ttyfd
>= 0)
3852 tcgetattr(ttyfd
, &shell_tty_info
);
3857 /* if (rootshell) - caller ensures this */
3859 tcsetattr(ttyfd
, TCSADRAIN
, &shell_tty_info
);
3862 job_signal_status(struct job
*jp
)
3866 struct procstat
*ps
= jp
->ps
;
3867 for (i
= 0; i
< jp
->nprocs
; i
++) {
3868 status
= ps
[i
].ps_status
;
3869 if (WIFSIGNALED(status
) || WIFSTOPPED(status
))
3875 restore_tty_if_stopped_or_signaled(struct job
*jp
)
3877 //TODO: check what happens if we come from waitforjob() in expbackq()
3879 int s
= job_signal_status(jp
);
3880 if (s
) /* WIFSIGNALED(s) || WIFSTOPPED(s) */
3885 # define get_tty_state() ((void)0)
3886 # define restore_tty_if_stopped_or_signaled(jp) ((void)0)
3890 set_curjob(struct job
*jp
, unsigned mode
)
3893 struct job
**jpp
, **curp
;
3895 /* first remove from list */
3896 jpp
= curp
= &curjob
;
3901 jpp
= &jp1
->prev_job
;
3903 *jpp
= jp1
->prev_job
;
3905 /* Then re-insert in correct position */
3913 /* job being deleted */
3916 /* newly created job or backgrounded job,
3917 * put after all stopped jobs.
3922 if (!jp1
|| jp1
->state
!= JOBSTOPPED
)
3925 jpp
= &jp1
->prev_job
;
3931 /* newly stopped job - becomes curjob */
3932 jp
->prev_job
= *jpp
;
3940 jobno(const struct job
*jp
)
3942 return jp
- jobtab
+ 1;
3947 * Convert a job name to a job structure.
3950 #define getjob(name, getctl) getjob(name)
3953 getjob(const char *name
, int getctl
)
3957 const char *err_msg
= "%s: no such job";
3975 if (c
== '+' || c
== '%') {
3977 err_msg
= "No current job";
3983 err_msg
= "No previous job";
3993 if (num
> 0 && num
<= njobs
) {
3994 jp
= jobtab
+ num
- 1;
4004 ? strstr(jp
->ps
[0].ps_cmd
, p
+ 1)
4005 : prefix(jp
->ps
[0].ps_cmd
, p
)
4010 err_msg
= "%s: ambiguous";
4020 err_msg
= "job %s not created under job control";
4021 if (getctl
&& jp
->jobctl
== 0)
4026 ash_msg_and_raise_error(err_msg
, name
);
4030 * Mark a job structure as unused.
4033 freejob(struct job
*jp
)
4035 struct procstat
*ps
;
4039 for (i
= jp
->nprocs
, ps
= jp
->ps
; --i
>= 0; ps
++) {
4040 if (ps
->ps_cmd
!= nullstr
)
4043 if (jp
->ps
!= &jp
->ps0
)
4046 set_curjob(jp
, CUR_DELETE
);
4052 xtcsetpgrp(int fd
, pid_t pgrp
)
4054 if (tcsetpgrp(fd
, pgrp
))
4055 ash_msg_and_raise_perror("can't set tty process group");
4059 * Turn job control on and off.
4061 * Note: This code assumes that the third arg to ioctl is a character
4062 * pointer, which is true on Berkeley systems but not System V. Since
4063 * System V doesn't have job control yet, this isn't a problem now.
4065 * Called with interrupts off.
4073 if (on
== doing_jobctl
|| rootshell
== 0)
4077 ofd
= fd
= open(_PATH_TTY
, O_RDWR
);
4079 /* BTW, bash will try to open(ttyname(0)) if open("/dev/tty") fails.
4080 * That sometimes helps to acquire controlling tty.
4081 * Obviously, a workaround for bugs when someone
4082 * failed to provide a controlling tty to bash! :) */
4088 /* fd is a tty at this point */
4089 fd
= fcntl(fd
, F_DUPFD_CLOEXEC
, 10);
4090 if (ofd
>= 0) /* if it is "/dev/tty", close. If 0/1/2, don't */
4093 goto out
; /* F_DUPFD failed */
4094 if (F_DUPFD_CLOEXEC
== F_DUPFD
) /* if old libc (w/o F_DUPFD_CLOEXEC) */
4095 close_on_exec_on(fd
);
4096 while (1) { /* while we are in the background */
4097 pgrp
= tcgetpgrp(fd
);
4100 ash_msg("can't access tty; job control turned off");
4104 if (pgrp
== getpgrp())
4115 xtcsetpgrp(fd
, pgrp
);
4117 /* turning job control off */
4120 /* was xtcsetpgrp, but this can make exiting ash
4121 * loop forever if pty is already deleted */
4122 tcsetpgrp(fd
, pgrp
);
4136 static int FAST_FUNC
4137 killcmd(int argc
, char **argv
)
4139 if (argv
[1] && strcmp(argv
[1], "-l") != 0) {
4142 if (argv
[i
][0] == '%') {
4144 * "kill %N" - job kill
4145 * Converting to pgrp / pid kill
4151 jp
= getjob(argv
[i
], 0);
4153 * In jobs started under job control, we signal
4154 * entire process group by kill -PGRP_ID.
4155 * This happens, f.e., in interactive shell.
4157 * Otherwise, we signal each child via
4158 * kill PID1 PID2 PID3.
4160 * sh -c 'sleep 1|sleep 1 & kill %1'
4161 * sh -c 'true|sleep 2 & sleep 1; kill %1'
4162 * sh -c 'true|sleep 1 & sleep 2; kill %1'
4164 n
= jp
->nprocs
; /* can't be 0 (I hope) */
4167 dst
= alloca(n
* sizeof(int)*4);
4169 for (j
= 0; j
< n
; j
++) {
4170 struct procstat
*ps
= &jp
->ps
[j
];
4171 /* Skip non-running and not-stopped members
4172 * (i.e. dead members) of the job
4174 if (ps
->ps_status
!= -1 && !WIFSTOPPED(ps
->ps_status
))
4177 * kill_main has matching code to expect
4178 * leading space. Needed to not confuse
4179 * negative pids with "kill -SIGNAL_NO" syntax
4181 dst
+= sprintf(dst
, jp
->jobctl
? " -%u" : " %u", (int)ps
->ps_pid
);
4185 } while (argv
[++i
]);
4187 return kill_main(argc
, argv
);
4191 showpipe(struct job
*jp
/*, FILE *out*/)
4193 struct procstat
*ps
;
4194 struct procstat
*psend
;
4196 psend
= jp
->ps
+ jp
->nprocs
;
4197 for (ps
= jp
->ps
+ 1; ps
< psend
; ps
++)
4198 printf(" | %s", ps
->ps_cmd
);
4199 newline_and_flush(stdout
);
4200 flush_stdout_stderr();
4205 restartjob(struct job
*jp
, int mode
)
4207 struct procstat
*ps
;
4213 if (jp
->state
== JOBDONE
)
4215 jp
->state
= JOBRUNNING
;
4216 pgid
= jp
->ps
[0].ps_pid
;
4217 if (mode
== FORK_FG
) {
4219 xtcsetpgrp(ttyfd
, pgid
);
4221 killpg(pgid
, SIGCONT
);
4225 if (WIFSTOPPED(ps
->ps_status
)) {
4231 status
= (mode
== FORK_FG
) ? waitforjob(jp
) : 0;
4236 static int FAST_FUNC
4237 fg_bgcmd(int argc UNUSED_PARAM
, char **argv
)
4243 mode
= (**argv
== 'f') ? FORK_FG
: FORK_BG
;
4247 jp
= getjob(*argv
, 1);
4248 if (mode
== FORK_BG
) {
4249 set_curjob(jp
, CUR_RUNNING
);
4250 printf("[%d] ", jobno(jp
));
4252 out1str(jp
->ps
[0].ps_cmd
);
4253 showpipe(jp
/*, stdout*/);
4254 retval
= restartjob(jp
, mode
);
4255 } while (*argv
&& *++argv
);
4261 sprint_status48(char *os
, int status
, int sigonly
)
4266 if (!WIFEXITED(status
)) {
4268 if (WIFSTOPPED(status
))
4269 st
= WSTOPSIG(status
);
4272 st
= WTERMSIG(status
);
4274 if (st
== SIGINT
|| st
== SIGPIPE
)
4277 if (WIFSTOPPED(status
))
4282 s
= stpncpy(s
, strsignal(st
), 32);
4283 if (WCOREDUMP(status
)) {
4284 s
= stpcpy(s
, " (core dumped)");
4286 } else if (!sigonly
) {
4287 st
= WEXITSTATUS(status
);
4288 s
+= fmtstr(s
, 16, (st
? "Done(%d)" : "Done"), st
);
4294 #define DOWAIT_NONBLOCK 0
4295 #define DOWAIT_BLOCK 1
4296 #define DOWAIT_BLOCK_OR_SIG 2
4298 # define DOWAIT_JOBSTATUS 0x10 /* OR this to get job's exitstatus instead of pid */
4302 waitproc(int block
, int *status
)
4305 int flags
= block
== DOWAIT_BLOCK
? 0 : WNOHANG
;
4316 err
= waitpid(-1, status
, flags
);
4317 while (err
< 0 && errno
== EINTR
);
4319 if (err
|| (err
= -!block
))
4322 sigfillset(&oldmask
);
4323 sigprocmask2(SIG_SETMASK
, &oldmask
); /* mask is updated */
4324 while (!got_sigchld
&& !pending_sig
)
4325 sigsuspend(&oldmask
);
4326 sigprocmask(SIG_SETMASK
, &oldmask
, NULL
);
4327 //simpler, but unsafe: a signal can set pending_sig after check, but before pause():
4328 //while (!got_sigchld && !pending_sig)
4331 } while (got_sigchld
);
4337 waitone(int block
, struct job
*job
)
4342 struct job
*thisjob
= NULL
;
4344 bool want_jobexitstatus
= (block
& DOWAIT_JOBSTATUS
);
4345 block
= (block
& ~DOWAIT_JOBSTATUS
);
4348 TRACE(("dowait(0x%x) called\n", block
));
4350 /* It's wrong to call waitpid() outside of INT_OFF region:
4351 * signal can arrive just after syscall return and handler can
4352 * longjmp away, losing stop/exit notification processing.
4353 * Thus, for "jobs" builtin, and for waiting for a fg job,
4354 * we call waitpid() (blocking or non-blocking) inside INT_OFF.
4356 * However, for "wait" builtin it is wrong to simply call waitpid()
4357 * in INT_OFF region: "wait" needs to wait for any running job
4358 * to change state, but should exit on any trap too.
4359 * In INT_OFF region, a signal just before syscall entry can set
4360 * pending_sig variables, but we can't check them, and we would
4361 * either enter a sleeping waitpid() (BUG), or need to busy-loop.
4363 * Because of this, we run inside INT_OFF, but use a special routine
4364 * which combines waitpid() and sigsuspend().
4365 * This is the reason why we need to have a handler for SIGCHLD:
4366 * SIG_DFL handler does not wake sigsuspend().
4369 pid
= waitproc(block
, &status
);
4370 TRACE(("wait returns pid %d, status=%d\n", pid
, status
));
4374 for (jp
= curjob
; jp
; jp
= jp
->prev_job
) {
4376 struct procstat
*ps
;
4377 struct procstat
*psend
;
4378 if (jp
->state
== JOBDONE
)
4382 psend
= ps
+ jp
->nprocs
;
4384 if (ps
->ps_pid
== pid
) {
4385 TRACE(("Job %d: changing status of proc %d "
4386 "from 0x%x to 0x%x\n",
4387 jobno(jp
), pid
, ps
->ps_status
, status
));
4388 ps
->ps_status
= status
;
4391 if (ps
->ps_status
== -1)
4392 jobstate
= JOBRUNNING
;
4394 if (jobstate
== JOBRUNNING
)
4396 if (WIFSTOPPED(ps
->ps_status
)) {
4397 jp
->stopstatus
= ps
->ps_status
;
4398 jobstate
= JOBSTOPPED
;
4401 } while (++ps
< psend
);
4405 /* Found the job where one of its processes changed its state.
4406 * Is there at least one live and running process in this job? */
4407 if (jobstate
!= JOBRUNNING
) {
4408 /* No. All live processes in the job are stopped
4409 * (JOBSTOPPED) or there are no live processes (JOBDONE)
4411 thisjob
->changed
= 1;
4412 if (thisjob
->state
!= jobstate
) {
4413 TRACE(("Job %d: changing state from %d to %d\n",
4414 jobno(thisjob
), thisjob
->state
, jobstate
));
4415 thisjob
->state
= jobstate
;
4417 if (jobstate
== JOBSTOPPED
)
4418 set_curjob(thisjob
, CUR_STOPPED
);
4424 /* The process wasn't found in job list */
4429 if (want_jobexitstatus
) {
4431 if (thisjob
&& thisjob
->state
== JOBDONE
)
4432 pid
= thisjob
->ps
[thisjob
->nprocs
- 1].ps_status
;
4435 if (thisjob
&& thisjob
== job
) {
4439 len
= sprint_status48(s
, status
, 1);
4450 dowait(int block
, struct job
*jp
)
4452 smallint gotchld
= *(volatile smallint
*)&got_sigchld
;
4456 if (jp
&& jp
->state
!= JOBRUNNING
)
4457 block
= DOWAIT_NONBLOCK
;
4459 if (block
== DOWAIT_NONBLOCK
&& !gotchld
)
4465 pid
= waitone(block
, jp
);
4468 if (!pid
|| (jp
&& jp
->state
!= JOBRUNNING
))
4469 block
= DOWAIT_NONBLOCK
;
4477 showjob(struct job
*jp
, int mode
)
4479 struct procstat
*ps
;
4480 struct procstat
*psend
;
4483 char s
[16 + 16 + 48];
4484 FILE *out
= (mode
& SHOW_STDERR
? stderr
: stdout
);
4488 if (mode
& SHOW_ONLY_PGID
) { /* jobs -p */
4489 /* just output process (group) id of pipeline */
4490 fprintf(out
, "%d\n", ps
->ps_pid
);
4494 col
= fmtstr(s
, 16, "[%d] ", jobno(jp
));
4499 else if (curjob
&& jp
== curjob
->prev_job
)
4502 if (mode
& SHOW_PIDS
)
4503 col
+= fmtstr(s
+ col
, 16, "%d ", ps
->ps_pid
);
4505 psend
= ps
+ jp
->nprocs
;
4507 if (jp
->state
== JOBRUNNING
) {
4508 strcpy(s
+ col
, "Running");
4509 col
+= sizeof("Running") - 1;
4511 int status
= psend
[-1].ps_status
;
4512 if (jp
->state
== JOBSTOPPED
)
4513 status
= jp
->stopstatus
;
4514 col
+= sprint_status48(s
+ col
, status
, 0);
4516 /* By now, "[JOBID]* [maybe PID] STATUS" is printed */
4518 /* This loop either prints "<cmd1> | <cmd2> | <cmd3>" line
4519 * or prints several "PID | <cmdN>" lines,
4520 * depending on SHOW_PIDS bit.
4521 * We do not print status of individual processes
4522 * between PID and <cmdN>. bash does it, but not very well:
4523 * first line shows overall job status, not process status,
4524 * making it impossible to know 1st process status.
4528 /* for each process */
4531 if (mode
& SHOW_PIDS
)
4532 col
= fmtstr(s
, 48, "\n%*c%d ", indent_col
, ' ', ps
->ps_pid
) - 1;
4534 fprintf(out
, "%s%*c%s%s",
4536 33 - col
>= 0 ? 33 - col
: 0, ' ',
4537 ps
== jp
->ps
? "" : "| ",
4540 } while (++ps
!= psend
);
4541 newline_and_flush(out
);
4545 if (jp
->state
== JOBDONE
) {
4546 TRACE(("showjob: freeing job %d\n", jobno(jp
)));
4552 * Print a list of jobs. If "change" is nonzero, only print jobs whose
4553 * statuses have changed since the last call to showjobs.
4560 TRACE(("showjobs(0x%x) called\n", mode
));
4562 /* Handle all finished jobs */
4563 dowait(DOWAIT_NONBLOCK
, NULL
);
4565 for (jp
= curjob
; jp
; jp
= jp
->prev_job
) {
4566 if (!(mode
& SHOW_CHANGED
) || jp
->changed
) {
4572 static int FAST_FUNC
4573 jobscmd(int argc UNUSED_PARAM
, char **argv
)
4578 while ((m
= nextopt("lp")) != '\0') {
4582 mode
|= SHOW_ONLY_PGID
;
4588 showjob(getjob(*argv
, 0), mode
);
4598 /* Called only on finished or stopped jobs (no members are running) */
4600 getstatus(struct job
*job
)
4604 struct procstat
*ps
;
4606 /* Fetch last member's status */
4607 ps
= job
->ps
+ job
->nprocs
- 1;
4608 status
= ps
->ps_status
;
4610 /* "set -o pipefail" mode: use last _nonzero_ status */
4611 while (status
== 0 && --ps
>= job
->ps
)
4612 status
= ps
->ps_status
;
4615 retval
= WEXITSTATUS(status
);
4616 if (!WIFEXITED(status
)) {
4618 retval
= WSTOPSIG(status
);
4619 if (!WIFSTOPPED(status
))
4622 /* XXX: limits number of signals */
4623 retval
= WTERMSIG(status
);
4625 if (retval
== SIGINT
)
4631 TRACE(("getstatus: job %d, nproc %d, status 0x%x, retval 0x%x\n",
4632 jobno(job
), job
->nprocs
, status
, retval
));
4636 static int FAST_FUNC
4637 waitcmd(int argc UNUSED_PARAM
, char **argv
)
4644 char one
= nextopt("n");
4652 /* wait for all jobs / one job if -n */
4657 /* exitcode of "wait -n" with nothing to wait for is 127, not 0 */
4661 if (!jp
) /* no running procs */
4663 if (jp
->state
== JOBRUNNING
)
4669 * "When bash is waiting for an asynchronous command via
4670 * the wait builtin, the reception of a signal for which a trap
4671 * has been set will cause the wait builtin to return immediately
4672 * with an exit status greater than 128, immediately after which
4673 * the trap is executed."
4676 status
= dowait(DOWAIT_BLOCK_OR_SIG
| DOWAIT_JOBSTATUS
, NULL
);
4678 dowait(DOWAIT_BLOCK_OR_SIG
, NULL
);
4680 /* if child sends us a signal *and immediately exits*,
4681 * dowait() returns pid > 0. Check this case,
4682 * not "if (dowait() < 0)"!
4688 /* wait -n waits for one _job_, not one _process_.
4689 * date; sleep 3 & sleep 2 | sleep 1 & wait -n; date
4690 * should wait for 2 seconds. Not 1 or 3.
4692 if (status
!= -1 && !WIFSTOPPED(status
)) {
4693 retval
= WEXITSTATUS(status
);
4694 if (WIFSIGNALED(status
))
4695 retval
= 128 | WTERMSIG(status
);
4705 if (**argv
!= '%') {
4706 pid_t pid
= number(*argv
);
4711 if (job
->ps
[job
->nprocs
- 1].ps_pid
== pid
)
4713 job
= job
->prev_job
;
4716 job
= getjob(*argv
, 0);
4718 /* loop until process terminated or stopped */
4719 dowait(DOWAIT_BLOCK_OR_SIG
, job
);
4723 retval
= getstatus(job
);
4730 retval
= 128 | pending_sig
;
4739 struct job
*jp
, *jq
;
4741 len
= njobs
* sizeof(*jp
);
4743 jp
= ckrealloc(jq
, len
+ 4 * sizeof(*jp
));
4745 offset
= (char *)jp
- (char *)jq
;
4747 /* Relocate pointers */
4750 jq
= (struct job
*)((char *)jq
+ l
);
4754 #define joff(p) ((struct job *)((char *)(p) + l))
4755 #define jmove(p) (p) = (void *)((char *)(p) + offset)
4756 if (joff(jp
)->ps
== &jq
->ps0
)
4757 jmove(joff(jp
)->ps
);
4758 if (joff(jp
)->prev_job
)
4759 jmove(joff(jp
)->prev_job
);
4769 jp
= (struct job
*)((char *)jp
+ len
);
4773 } while (--jq
>= jp
);
4778 * Return a new job structure.
4779 * Called with interrupts off.
4782 makejob(/*union node *node,*/ int nprocs
)
4787 for (i
= njobs
, jp
= jobtab
; ; jp
++) {
4794 if (jp
->state
!= JOBDONE
|| !jp
->waited
)
4803 memset(jp
, 0, sizeof(*jp
));
4805 /* jp->jobctl is a bitfield.
4806 * "jp->jobctl |= doing_jobctl" likely to give awful code */
4810 jp
->prev_job
= curjob
;
4815 jp
->ps
= ckmalloc(nprocs
* sizeof(struct procstat
));
4817 TRACE(("makejob(%d) returns %%%d\n", nprocs
,
4824 * Return a string identifying a command (to be printed by the
4827 static char *cmdnextc
;
4830 cmdputs(const char *s
)
4832 static const char vstype
[VSTYPE
+ 1][3] ALIGN1
= {
4833 "", "}", "-", "+", "?", "=",
4834 "%", "%%", "#", "##"
4835 IF_BASH_SUBSTR(, ":")
4836 IF_BASH_PATTERN_SUBST(, "/", "//")
4839 const char *p
, *str
;
4843 unsigned char subtype
= 0;
4847 nextc
= makestrspace((strlen(s
) + 1) * 8, cmdnextc
);
4849 while ((c
= *p
++) != '\0') {
4857 if ((subtype
& VSTYPE
) == VSLENGTH
)
4864 str
+= !(quoted
& 1);
4868 #if BASH_PROCESS_SUBST
4886 #if ENABLE_FEATURE_SH_MATH
4901 if ((subtype
& VSTYPE
) != VSNORMAL
)
4903 str
= vstype
[subtype
& VSTYPE
];
4904 if (subtype
& VSNUL
)
4913 /* These can only happen inside quotes */
4919 // [1]+ Done true ${\$} <<=== BUG: ${\$} is not a valid way to write $$ (${$} would be ok)
4930 while ((c
= *str
++) != '\0') {
4933 } /* while *p++ not NUL */
4936 USTPUTC('"', nextc
);
4942 /* cmdtxt() and cmdlist() call each other */
4943 static void cmdtxt(union node
*n
);
4946 cmdlist(union node
*np
, int sep
)
4948 for (; np
; np
= np
->narg
.next
) {
4952 if (sep
&& np
->narg
.next
)
4958 cmdtxt(union node
*n
)
4961 struct nodelist
*lp
;
4972 lp
= n
->npipe
.cmdlist
;
4990 cmdtxt(n
->nbinary
.ch1
);
5006 cmdtxt(n
->nif
.test
);
5008 if (n
->nif
.elsepart
) {
5009 cmdtxt(n
->nif
.ifpart
);
5011 n
= n
->nif
.elsepart
;
5029 cmdtxt(n
->nbinary
.ch1
);
5039 cmdputs(n
->nfor
.var
);
5041 cmdlist(n
->nfor
.args
, 1);
5046 cmdputs(n
->ndefun
.text
);
5050 cmdlist(n
->ncmd
.args
, 1);
5051 cmdlist(n
->ncmd
.redirect
, 0);
5064 cmdputs(n
->ncase
.expr
->narg
.text
);
5066 for (np
= n
->ncase
.cases
; np
; np
= np
->nclist
.next
) {
5067 cmdtxt(np
->nclist
.pattern
);
5069 cmdtxt(np
->nclist
.body
);
5083 #if BASH_REDIR_OUTPUT
5098 cmdputs(utoa(n
->nfile
.fd
));
5100 if (n
->type
== NTOFD
|| n
->type
== NFROMFD
) {
5101 if (n
->ndup
.dupfd
>= 0)
5102 cmdputs(utoa(n
->ndup
.dupfd
));
5113 commandtext(union node
*n
)
5117 STARTSTACKSTR(cmdnextc
);
5119 name
= stackblock();
5120 TRACE(("commandtext: name %p, end %p\n", name
, cmdnextc
));
5121 return ckstrdup(name
);
5126 * Fork off a subshell. If we are doing job control, give the subshell its
5127 * own process group. Jp is a job structure that the job is to be added to.
5128 * N is the command that will be evaluated by the child. Both jp and n may
5129 * be NULL. The mode parameter can be one of the following:
5130 * FORK_FG - Fork off a foreground process.
5131 * FORK_BG - Fork off a background process.
5132 * FORK_NOJOB - Like FORK_FG, but don't give the process its own
5133 * process group even if job control is on.
5135 * When job control is turned off, background processes have their standard
5136 * input redirected to /dev/null (except for the second and later processes
5139 * Called with interrupts off.
5142 * Clear traps on a fork.
5150 for (tp
= trap
; tp
<= &trap
[NTRAP_LAST
]; tp
++) {
5151 if (*tp
&& **tp
) { /* trap not NULL or "" (SIG_IGN) */
5152 if (trap_ptr
== trap
)
5154 /* else: it "belongs" to trap_ptr vector, don't free */
5156 if ((tp
- trap
) != 0 && (tp
- trap
) < NSIG
)
5157 setsignal(tp
- trap
);
5164 /* Lives far away from here, needed for forkchild */
5165 static void closescript(void);
5167 /* Called after fork(), in child */
5168 /* jp and n are NULL when called by openhere() for heredoc support */
5169 static NOINLINE
void
5170 forkchild(struct job
*jp
, union node
*n
, int mode
)
5174 TRACE(("Child shell %d\n", getpid()));
5178 /* man bash: "Non-builtin commands run by bash have signal handlers
5179 * set to the values inherited by the shell from its parent".
5180 * Do we do it correctly? */
5184 if (n
&& n
->type
== NCMD
/* is it single cmd? */
5185 /* && n->ncmd.args->type == NARG - always true? */
5186 && n
->ncmd
.args
&& strcmp(n
->ncmd
.args
->narg
.text
, "trap") == 0
5187 && n
->ncmd
.args
->narg
.next
== NULL
/* "trap" with no arguments */
5188 /* && n->ncmd.args->narg.backquote == NULL - do we need to check this? */
5190 TRACE(("Trap hack\n"));
5191 /* Awful hack for `trap` or $(trap).
5193 * http://www.opengroup.org/onlinepubs/009695399/utilities/trap.html
5194 * contains an example where "trap" is executed in a subshell:
5196 * save_traps=$(trap)
5198 * eval "$save_traps"
5200 * Standard does not say that "trap" in subshell shall print
5201 * parent shell's traps. It only says that its output
5202 * must have suitable form, but then, in the above example
5203 * (which is not supposed to be normative), it implies that.
5205 * bash (and probably other shell) does implement it
5206 * (traps are reset to defaults, but "trap" still shows them),
5207 * but as a result, "trap" logic is hopelessly messed up:
5210 * trap -- 'echo Ho' SIGWINCH <--- we have a handler
5211 * # (trap) <--- trap is in subshell - no output (correct, traps are reset)
5212 * # true | trap <--- trap is in subshell - no output (ditto)
5213 * # echo `true | trap` <--- in subshell - output (but traps are reset!)
5214 * trap -- 'echo Ho' SIGWINCH
5215 * # echo `(trap)` <--- in subshell in subshell - output
5216 * trap -- 'echo Ho' SIGWINCH
5217 * # echo `true | (trap)` <--- in subshell in subshell in subshell - output!
5218 * trap -- 'echo Ho' SIGWINCH
5220 * The rules when to forget and when to not forget traps
5221 * get really complex and nonsensical.
5223 * Our solution: ONLY bare $(trap) or `trap` is special.
5225 /* Save trap handler strings for trap builtin to print */
5226 trap_ptr
= xmemdup(trap
, sizeof(trap
));
5227 /* Fall through into clearing traps */
5231 /* do job control only in root shell */
5233 if (mode
!= FORK_NOJOB
&& jp
->jobctl
&& oldlvl
== 0) {
5236 if (jp
->nprocs
== 0)
5239 pgrp
= jp
->ps
[0].ps_pid
;
5240 /* this can fail because we are doing it in the parent also */
5242 if (mode
== FORK_FG
)
5243 xtcsetpgrp(ttyfd
, pgrp
);
5248 if (mode
== FORK_BG
) {
5249 /* man bash: "When job control is not in effect,
5250 * asynchronous commands ignore SIGINT and SIGQUIT" */
5253 if (jp
->nprocs
== 0) {
5255 if (open(bb_dev_null
, O_RDONLY
) != 0)
5256 ash_msg_and_raise_perror("can't open '%s'", bb_dev_null
);
5260 if (iflag
) { /* why if iflag only? */
5265 * "In all cases, bash ignores SIGQUIT. Non-builtin
5266 * commands run by bash have signal handlers
5267 * set to the values inherited by the shell
5269 * Take care of the second rule: */
5273 if (n
&& n
->type
== NCMD
5274 && n
->ncmd
.args
&& strcmp(n
->ncmd
.args
->narg
.text
, "jobs") == 0
5276 TRACE(("Job hack\n"));
5277 /* "jobs": we do not want to clear job list for it,
5278 * instead we remove only _its_ own_ job from job list
5280 * This makes "jobs .... | cat" more useful.
5287 for (jp
= curjob
; jp
; jp
= jp
->prev_job
)
5291 /* Called after fork(), in parent */
5293 #define forkparent(jp, n, mode, pid) forkparent(jp, mode, pid)
5296 forkparent(struct job
*jp
, union node
*n
, int mode
, pid_t pid
)
5298 TRACE(("In parent shell: child = %d\n", pid
));
5299 if (!jp
) /* jp is NULL when called by openhere() for heredoc support */
5302 if (mode
!= FORK_NOJOB
&& jp
->jobctl
) {
5305 if (jp
->nprocs
== 0)
5308 pgrp
= jp
->ps
[0].ps_pid
;
5309 /* This can fail because we are doing it in the child also */
5313 if (mode
== FORK_BG
) {
5314 backgndpid
= pid
; /* set $! */
5315 set_curjob(jp
, CUR_RUNNING
);
5318 struct procstat
*ps
= &jp
->ps
[jp
->nprocs
++];
5321 ps
->ps_cmd
= nullstr
;
5323 if (doing_jobctl
&& n
)
5324 ps
->ps_cmd
= commandtext(n
);
5329 /* jp and n are NULL when called by openhere() for heredoc support */
5331 forkshell(struct job
*jp
, union node
*n
, int mode
)
5335 TRACE(("forkshell(%%%d, %p, %d) called\n", jobno(jp
), n
, mode
));
5338 TRACE(("Fork failed, errno=%d", errno
));
5341 ash_msg_and_raise_perror("can't fork");
5344 CLEAR_RANDOM_T(&random_gen
); /* or else $RANDOM repeats in child */
5345 forkchild(jp
, n
, mode
);
5347 forkparent(jp
, n
, mode
, pid
);
5353 * Wait for job to finish.
5355 * Under job control we have the problem that while a child process
5356 * is running interrupts generated by the user are sent to the child
5357 * but not to the shell. This means that an infinite loop started by
5358 * an interactive user may be hard to kill. With job control turned off,
5359 * an interactive user may place an interactive program inside a loop.
5360 * If the interactive program catches interrupts, the user doesn't want
5361 * these interrupts to also abort the loop. The approach we take here
5362 * is to have the shell ignore interrupt signals while waiting for a
5363 * foreground process to terminate, and then send itself an interrupt
5364 * signal if the child process was terminated by an interrupt signal.
5365 * Unfortunately, some programs want to do a bit of cleanup and then
5366 * exit on interrupt; unless these processes terminate themselves by
5367 * sending a signal to themselves (instead of calling exit) they will
5368 * confuse this approach.
5370 * Called with interrupts off.
5373 waitforjob(struct job
*jp
)
5377 TRACE(("waitforjob(%%%d) called\n", jp
? jobno(jp
) : 0));
5379 /* In non-interactive shells, we _can_ get
5380 * a keyboard signal here and be EINTRed, but we just loop
5381 * inside dowait(), waiting for command to complete.
5384 * "If bash is waiting for a command to complete and receives
5385 * a signal for which a trap has been set, the trap
5386 * will not be executed until the command completes."
5388 * Reality is that even if trap is not set, bash
5389 * will not act on the signal until command completes.
5390 * Try this. sleep5intoff.c:
5391 * #include <signal.h>
5392 * #include <unistd.h>
5395 * sigemptyset(&set);
5396 * sigaddset(&set, SIGINT);
5397 * sigaddset(&set, SIGQUIT);
5398 * sigprocmask(SIG_BLOCK, &set, NULL);
5402 * $ bash -c './sleep5intoff; echo hi'
5403 * ^C^C^C^C <--- pressing ^C once a second
5405 * $ bash -c './sleep5intoff; echo hi'
5406 * ^\^\^\^\hi <--- pressing ^\ (SIGQUIT)
5409 dowait(jp
? DOWAIT_BLOCK
: DOWAIT_NONBLOCK
, jp
);
5416 xtcsetpgrp(ttyfd
, rootpid
);
5417 restore_tty_if_stopped_or_signaled(jp
);
5420 * This is truly gross.
5421 * If we're doing job control, then we did a TIOCSPGRP which
5422 * caused us (the shell) to no longer be in the controlling
5423 * session -- so we wouldn't have seen any ^C/SIGINT. So, we
5424 * intuit from the subprocess exit status whether a SIGINT
5425 * occurred, and if so interrupt ourselves. Yuck. - mycroft
5427 if (jp
->sigint
) /* TODO: do the same with all signals */
5428 raise(SIGINT
); /* ... by raise(jp->sig) instead? */
5430 if (jp
->state
== JOBDONE
)
5437 * return 1 if there are stopped jobs, otherwise 0
5446 if (!iflag
|| job_warning
)
5449 if (jp
&& jp
->state
== JOBSTOPPED
) {
5450 out2str("You have stopped jobs.\n");
5460 * Code for dealing with input/output redirection.
5465 #define EMPTY -2 /* marks an unused slot in redirtab */
5466 #define CLOSED -1 /* marks a slot of previously-closed fd */
5469 * Handle here documents. Normally we fork off a process to write the
5470 * data to a pipe. If the document is short, we can stuff the data in
5471 * the pipe without forking.
5473 /* openhere needs this forward reference */
5474 static void expandhere(union node
*arg
);
5476 openhere(union node
*redir
)
5483 ash_msg_and_raise_perror("can't create pipe");
5485 p
= redir
->nhere
.doc
->narg
.text
;
5486 if (redir
->type
== NXHERE
) {
5487 expandhere(redir
->nhere
.doc
);
5492 if (len
<= PIPE_BUF
) {
5493 xwrite(pip
[1], p
, len
);
5497 if (forkshell((struct job
*)NULL
, (union node
*)NULL
, FORK_NOJOB
) == 0) {
5500 ignoresig(SIGINT
); //signal(SIGINT, SIG_IGN);
5501 ignoresig(SIGQUIT
); //signal(SIGQUIT, SIG_IGN);
5502 ignoresig(SIGHUP
); //signal(SIGHUP, SIG_IGN);
5503 ignoresig(SIGTSTP
); //signal(SIGTSTP, SIG_IGN);
5504 signal(SIGPIPE
, SIG_DFL
);
5505 xwrite(pip
[1], p
, len
);
5514 openredirect(union node
*redir
)
5520 switch (redir
->nfile
.type
) {
5521 /* Can't happen, our single caller does this itself */
5527 return openhere(redir
);
5530 /* For N[X]HERE, reading redir->nfile.expfname would touch beyond
5531 * allocated space. Do it only when we know it is safe.
5533 fname
= redir
->nfile
.expfname
;
5535 switch (redir
->nfile
.type
) {
5541 f
= open(fname
, O_RDONLY
);
5546 f
= open(fname
, O_RDWR
|O_CREAT
, 0666);
5551 #if BASH_REDIR_OUTPUT
5554 /* Take care of noclobber mode. */
5556 if (stat(fname
, &sb
) < 0) {
5557 f
= open(fname
, O_WRONLY
|O_CREAT
|O_EXCL
, 0666);
5560 } else if (!S_ISREG(sb
.st_mode
)) {
5561 f
= open(fname
, O_WRONLY
, 0666);
5564 if (!fstat(f
, &sb
) && S_ISREG(sb
.st_mode
)) {
5577 f
= open(fname
, O_WRONLY
|O_CREAT
|O_TRUNC
, 0666);
5582 f
= open(fname
, O_WRONLY
|O_CREAT
|O_APPEND
, 0666);
5590 ash_msg_and_raise_error("can't create %s: %s", fname
, errmsg(errno
, "nonexistent directory"));
5592 ash_msg_and_raise_error("can't open %s: %s", fname
, errmsg(errno
, "no such file"));
5596 * Copy a file descriptor to be >= 10. Throws exception on error.
5604 newfd
= fcntl(from
, F_DUPFD_CLOEXEC
, 10);
5605 err
= newfd
< 0 ? errno
: 0;
5608 ash_msg_and_raise_perror("%d", from
);
5610 if (F_DUPFD_CLOEXEC
== F_DUPFD
)
5611 close_on_exec_on(newfd
);
5617 dup2_or_raise(int from
, int to
)
5621 newfd
= (from
!= to
) ? dup2(from
, to
) : to
;
5623 /* Happens when source fd is not open: try "echo >&99" */
5624 ash_msg_and_raise_perror("%d", from
);
5629 dup_CLOEXEC(int fd
, int avoid_fd
)
5633 newfd
= fcntl(fd
, F_DUPFD_CLOEXEC
, avoid_fd
+ 1);
5635 if (F_DUPFD_CLOEXEC
== F_DUPFD
) /* if old libc (w/o F_DUPFD_CLOEXEC) */
5636 close_on_exec_on(newfd
);
5637 } else { /* newfd < 0 */
5646 xdup_CLOEXEC_and_close(int fd
, int avoid_fd
)
5650 newfd
= fcntl(fd
, F_DUPFD_CLOEXEC
, avoid_fd
+ 1);
5656 /* fd was not open? */
5659 ash_msg_and_raise_perror("%d", newfd
);
5661 if (F_DUPFD_CLOEXEC
== F_DUPFD
)
5662 close_on_exec_on(newfd
);
5667 /* Struct def and variable are moved down to the first usage site */
5673 struct redirtab
*next
;
5675 struct squirrel two_fd
[];
5677 #define redirlist (G_var.redirlist)
5680 add_squirrel_closed(struct redirtab
*sq
, int fd
)
5687 for (i
= 0; sq
->two_fd
[i
].orig_fd
!= EMPTY
; i
++) {
5688 /* If we collide with an already moved fd... */
5689 if (fd
== sq
->two_fd
[i
].orig_fd
) {
5691 * "echo 3>FILE 3>&- 3>FILE"
5692 * "echo 3>&- 3>FILE"
5693 * No need for last redirect to insert
5694 * another "need to close 3" indicator.
5696 TRACE(("redirect_fd %d: already moved or closed\n", fd
));
5700 TRACE(("redirect_fd %d: previous fd was closed\n", fd
));
5701 sq
->two_fd
[i
].orig_fd
= fd
;
5702 sq
->two_fd
[i
].moved_to
= CLOSED
;
5706 save_fd_on_redirect(int fd
, int avoid_fd
, struct redirtab
*sq
)
5710 if (avoid_fd
< 9) /* the important case here is that it can be -1 */
5715 /* Testcase: "ls -l /proc/$$/fd 10>&-" should work */
5716 ttyfd
= xdup_CLOEXEC_and_close(ttyfd
, avoid_fd
);
5717 TRACE(("redirect_fd %d: matches ttyfd, moving it to %d\n", fd
, ttyfd
));
5718 return 1; /* "we closed fd" */
5721 /* Are we called from redirect(0)? E.g. redirect
5722 * in a forked child. No need to save fds,
5723 * we aren't going to use them anymore, ok to trash.
5728 /* If this one of script's fds? */
5730 struct parsefile
*pf
= g_parsefile
;
5732 /* We skip fd == 0 case because of the following:
5733 * $ ash # running ash interactively
5735 * and in script.sh: "exec 9>&0".
5736 * Even though top-level pf_fd _is_ 0,
5737 * it's still ok to use it: "read" builtin uses it,
5738 * why should we cripple "exec" builtin?
5740 if (fd
== pf
->pf_fd
) {
5741 pf
->pf_fd
= xdup_CLOEXEC_and_close(fd
, avoid_fd
);
5742 return 1; /* "we closed fd" */
5748 /* Check whether it collides with any open fds (e.g. stdio), save fds as needed */
5750 /* First: do we collide with some already moved fds? */
5751 for (i
= 0; sq
->two_fd
[i
].orig_fd
!= EMPTY
; i
++) {
5752 /* If we collide with an already moved fd... */
5753 if (fd
== sq
->two_fd
[i
].moved_to
) {
5754 new_fd
= dup_CLOEXEC(fd
, avoid_fd
);
5755 sq
->two_fd
[i
].moved_to
= new_fd
;
5756 TRACE(("redirect_fd %d: already busy, moving to %d\n", fd
, new_fd
));
5757 if (new_fd
< 0) /* what? */
5759 return 0; /* "we did not close fd" */
5761 if (fd
== sq
->two_fd
[i
].orig_fd
) {
5762 /* Example: echo Hello >/dev/null 1>&2 */
5763 TRACE(("redirect_fd %d: already moved\n", fd
));
5764 return 0; /* "we did not close fd" */
5768 /* If this fd is open, we move and remember it; if it's closed, new_fd = CLOSED (-1) */
5769 new_fd
= dup_CLOEXEC(fd
, avoid_fd
);
5770 TRACE(("redirect_fd %d: previous fd is moved to %d (-1 if it was closed)\n", fd
, new_fd
));
5774 /* new_fd = CLOSED; - already is -1 */
5776 sq
->two_fd
[i
].moved_to
= new_fd
;
5777 sq
->two_fd
[i
].orig_fd
= fd
;
5779 /* if we move stderr, let "set -x" code know */
5780 if (fd
== preverrout_fd
)
5781 preverrout_fd
= new_fd
;
5783 return 0; /* "we did not close fd" */
5787 internally_opened_fd(int fd
, struct redirtab
*sq
)
5794 /* If this one of script's fds? */
5796 struct parsefile
*pf
= g_parsefile
;
5798 if (fd
== pf
->pf_fd
)
5804 if (sq
) for (i
= 0; i
< sq
->pair_count
&& sq
->two_fd
[i
].orig_fd
!= EMPTY
; i
++) {
5805 if (fd
== sq
->two_fd
[i
].moved_to
)
5812 * Process a list of redirection commands. If the REDIR_PUSH flag is set,
5813 * old file descriptors are stashed away so that the redirection can be
5814 * undone by calling popredir.
5816 /* flags passed to redirect */
5817 #define REDIR_PUSH 01 /* save previous values of file descriptors */
5819 redirect(union node
*redir
, int flags
)
5821 struct redirtab
*sv
;
5828 if (flags
& REDIR_PUSH
)
5836 fd
= redir
->nfile
.fd
;
5837 if (redir
->nfile
.type
== NTOFD
|| redir
->nfile
.type
== NFROMFD
) {
5838 //bb_error_msg("doing %d > %d", fd, newfd);
5839 newfd
= redir
->ndup
.dupfd
;
5842 newfd
= openredirect(redir
); /* always >= 0 */
5844 /* open() gave us precisely the fd we wanted.
5845 * This means that this fd was not busy
5846 * (not opened to anywhere).
5847 * Remember to close it on restore:
5849 add_squirrel_closed(sv
, fd
);
5858 /* if "N>FILE": move newfd to fd */
5859 /* if "N>&M": dup newfd to fd */
5860 /* if "N>&-": close fd (newfd is -1) */
5862 IF_BASH_REDIR_OUTPUT(redirect_more
:)
5864 closed
= save_fd_on_redirect(fd
, /*avoid:*/ newfd
, sv
);
5866 /* "N>&-" means "close me" */
5868 /* ^^^ optimization: saving may already
5869 * have closed it. If not... */
5873 /* if newfd is a script fd or saved fd, simulate EBADF */
5874 if (internally_opened_fd(newfd
, sv
)) {
5876 ash_msg_and_raise_perror("%d", newfd
);
5878 dup2_or_raise(newfd
, fd
);
5879 if (close_fd
>= 0) /* "N>FILE" or ">&FILE" or heredoc? */
5881 #if BASH_REDIR_OUTPUT
5882 if (redir
->nfile
.type
== NTO2
&& fd
== 1) {
5883 /* ">&FILE". we already redirected to 1, now copy 1 to 2 */
5891 } while ((redir
= redir
->nfile
.next
) != NULL
);
5894 //dash:#define REDIR_SAVEFD2 03 /* set preverrout */
5895 #define REDIR_SAVEFD2 0
5896 // dash has a bug: since REDIR_SAVEFD2=3 and REDIR_PUSH=1, this test
5897 // triggers for pure REDIR_PUSH too. Thus, this is done almost always,
5898 // not only for calls with flags containing REDIR_SAVEFD2.
5899 // We do this unconditionally (see save_fd_on_redirect()).
5900 //if ((flags & REDIR_SAVEFD2) && copied_fd2 >= 0)
5901 // preverrout_fd = copied_fd2;
5905 redirectsafe(union node
*redir
, int flags
)
5908 volatile int saveint
;
5909 struct jmploc
*volatile savehandler
= exception_handler
;
5910 struct jmploc jmploc
;
5913 /* "echo 9>/dev/null; echo >&9; echo result: $?" - result should be 1, not 2! */
5914 err
= setjmp(jmploc
.loc
); /* was = setjmp(jmploc.loc) * 2; */
5916 exception_handler
= &jmploc
;
5917 redirect(redir
, flags
);
5919 exception_handler
= savehandler
;
5920 if (err
&& exception_type
!= EXERROR
)
5921 longjmp(exception_handler
->loc
, 1);
5922 RESTORE_INT(saveint
);
5926 #if BASH_PROCESS_SUBST
5930 struct redirtab
*sv
;
5932 sv
= ckzalloc(sizeof(*sv
) + sizeof(sv
->two_fd
[0]));
5934 sv
->two_fd
[0].orig_fd
= fd
;
5935 sv
->two_fd
[0].moved_to
= CLOSED
;
5936 sv
->next
= redirlist
;
5941 static struct redirtab
*
5942 pushredir(union node
*redir
)
5944 struct redirtab
*sv
;
5953 #if BASH_REDIR_OUTPUT
5954 if (redir
->nfile
.type
== NTO2
)
5957 redir
= redir
->nfile
.next
;
5960 sv
= ckzalloc(sizeof(*sv
) + i
* sizeof(sv
->two_fd
[0]));
5963 sv
->two_fd
[i
].orig_fd
= sv
->two_fd
[i
].moved_to
= EMPTY
;
5964 sv
->next
= redirlist
;
5970 * Undo the effects of the last redirection.
5975 struct redirtab
*rp
;
5978 if (redirlist
== NULL
)
5982 for (i
= 0; i
< rp
->pair_count
; i
++) {
5983 int fd
= rp
->two_fd
[i
].orig_fd
;
5984 int copy
= rp
->two_fd
[i
].moved_to
;
5985 if (copy
== CLOSED
) {
5990 if (copy
!= EMPTY
) {
5993 dup2_or_raise(copy
, fd
);
5998 redirlist
= rp
->next
;
6004 unwindredir(struct redirtab
*stop
)
6006 while (redirlist
!= stop
)
6007 popredir(/*drop:*/ 0);
6011 /* ============ Routines to expand arguments to commands
6013 * We have to deal with backquotes, shell variables, and file metacharacters.
6016 #if ENABLE_FEATURE_SH_MATH
6018 ash_arith(const char *s
)
6020 arith_state_t math_state
;
6023 math_state
.lookupvar
= lookupvar
;
6024 math_state
.setvar
= setvar0
;
6025 //math_state.endofname = endofname;
6028 result
= arith(&math_state
, s
);
6029 if (math_state
.errmsg
)
6030 ash_msg_and_raise_error(math_state
.errmsg
);
6037 # if ENABLE_FEATURE_SH_MATH
6038 static int substr_atoi(const char *s
)
6040 arith_t t
= ash_arith(s
);
6041 if (sizeof(t
) > sizeof(int)) {
6042 /* clamp very large or very large negative nums for ${v:N:M}:
6043 * else "${v:0:0x100000001}" would work as "${v:0:1}"
6053 # define substr_atoi(s) number(s)
6060 #define EXP_FULL 0x1 /* perform word splitting & file globbing */
6061 #define EXP_TILDE 0x2 /* do normal tilde expansion */
6062 #define EXP_VARTILDE 0x4 /* expand tildes in an assignment */
6063 #define EXP_REDIR 0x8 /* file glob for a redirection (1 match only) */
6064 /* ^^^^^^^^^^^^^^ this is meant to support constructs such as "cmd >file*.txt"
6065 * POSIX says for this case:
6066 * Pathname expansion shall not be performed on the word by a
6067 * non-interactive shell; an interactive shell may perform it, but shall
6068 * do so only when the expansion would result in one word.
6069 * Currently, our code complies to the above rule by never globbing
6070 * redirection filenames.
6071 * Bash performs globbing, unless it is non-interactive and in POSIX mode.
6072 * (this means that on a typical Linux distro, bash almost always
6073 * performs globbing, and thus diverges from what we do).
6075 #define EXP_CASE 0x10 /* keeps quotes around for CASE pattern */
6076 #define EXP_VARTILDE2 0x20 /* expand tildes after colons only */
6077 #define EXP_WORD 0x40 /* expand word in parameter expansion */
6078 #define EXP_QUOTED 0x100 /* expand word in double quotes */
6079 #define EXP_KEEPNUL 0x200 /* do not skip NUL characters */
6080 #define EXP_DISCARD 0x400 /* discard result of expansion */
6085 #define RMESCAPE_ALLOC 0x1 /* Allocate a new string */
6086 #define RMESCAPE_GLOB 0x2 /* Add backslashes for glob */
6087 #define RMESCAPE_GROW 0x8 /* Grow strings instead of stalloc */
6088 #define RMESCAPE_HEAP 0x10 /* Malloc strings instead of stalloc */
6090 /* Add CTLESC when necessary. */
6091 #define QUOTES_ESC (EXP_FULL | EXP_CASE)
6094 * Structure specifying which parts of the string should be searched
6095 * for IFS characters.
6098 struct ifsregion
*next
; /* next region in list */
6099 int begoff
; /* offset of start of region */
6100 int endoff
; /* offset of end of region */
6101 int nulonly
; /* search for nul bytes only */
6105 struct strlist
*list
;
6106 struct strlist
**lastp
;
6109 /* output of current string */
6110 static char *expdest
;
6111 /* list of back quote expressions */
6112 static struct nodelist
*argbackq
;
6113 /* first struct in list of ifs regions */
6114 static struct ifsregion ifsfirst
;
6115 /* last struct in list */
6116 static struct ifsregion
*ifslastp
;
6117 /* holds expanded arg list */
6118 static struct arglist exparg
;
6121 * Break the argument string into pieces based upon IFS and add the
6122 * strings to the argument list. The regions of the string to be
6123 * searched for IFS characters have been stored by recordregion.
6126 ifsbreakup(char *string
, struct arglist
*arglist
)
6128 struct ifsregion
*ifsp
;
6133 const char *ifs
, *realifs
;
6138 if (ifslastp
!= NULL
) {
6141 realifs
= ifsset() ? ifsval() : defifs
;
6146 p
= string
+ ifsp
->begoff
;
6148 nulonly
= ifsp
->nulonly
;
6149 ifs
= nulonly
? nullstr
: realifs
;
6151 while (p
< string
+ ifsp
->endoff
) {
6153 if ((unsigned char)*p
== CTLESC
)
6155 if (!strchr(ifs
, *p
)) {
6159 if (!(afternul
|| nulonly
))
6160 ifsspc
= (strchr(defifs
, *p
) != NULL
);
6161 /* Ignore IFS whitespace at start */
6162 if (q
== start
&& ifsspc
) {
6168 sp
= stzalloc(sizeof(*sp
));
6170 *arglist
->lastp
= sp
;
6171 arglist
->lastp
= &sp
->next
;
6175 if (p
>= string
+ ifsp
->endoff
) {
6179 if ((unsigned char)*p
== CTLESC
)
6181 if (strchr(ifs
, *p
) == NULL
) {
6185 if (strchr(defifs
, *p
) == NULL
) {
6200 } while (ifsp
!= NULL
);
6209 sp
= stzalloc(sizeof(*sp
));
6211 *arglist
->lastp
= sp
;
6212 arglist
->lastp
= &sp
->next
;
6218 struct ifsregion
*p
= ifsfirst
.next
;
6225 struct ifsregion
*ifsp
;
6230 ifsfirst
.next
= NULL
;
6237 esclen(const char *start
, const char *p
)
6241 while (p
> start
&& (unsigned char)*--p
== CTLESC
) {
6248 * Remove any CTLESC characters from a string.
6250 #if !BASH_PATTERN_SUBST
6251 #define rmescapes(str, flag, slash_position) \
6252 rmescapes(str, flag)
6255 rmescapes(char *str
, int flag
, int *slash_position
)
6257 static const char qchars
[] ALIGN1
= {
6258 IF_BASH_PATTERN_SUBST('/',) CTLESC
, CTLQUOTEMARK
, '\0' };
6261 unsigned protect_against_glob
;
6264 p
= strpbrk(str
, qchars
IF_BASH_PATTERN_SUBST(+ !slash_position
));
6270 if (flag
& RMESCAPE_ALLOC
) {
6271 size_t len
= p
- str
;
6272 size_t fulllen
= len
+ strlen(p
) + 1;
6274 if (flag
& RMESCAPE_GROW
) {
6275 int strloc
= str
- (char *)stackblock();
6276 r
= makestrspace(fulllen
, expdest
);
6277 /* p and str may be invalidated by makestrspace */
6278 str
= (char *)stackblock() + strloc
;
6280 } else if (flag
& RMESCAPE_HEAP
) {
6281 r
= ckmalloc(fulllen
);
6283 r
= stalloc(fulllen
);
6287 q
= (char *)mempcpy(q
, str
, len
);
6291 globbing
= flag
& RMESCAPE_GLOB
;
6292 protect_against_glob
= globbing
;
6294 if ((unsigned char)*p
== CTLQUOTEMARK
) {
6295 // Note: protect_against_glob only affect whether
6296 // CTLESC,<ch> gets converted to <ch> or to \<ch>
6298 protect_against_glob
= globbing
;
6302 /* naked back slash */
6303 protect_against_glob
= 0;
6306 if ((unsigned char)*p
== CTLESC
) {
6310 ash_msg_and_raise_error("CTLESC at EOL (shouldn't happen)");
6312 if (protect_against_glob
) {
6314 * We used to trust glob() and fnmatch() to eat
6315 * superfluous escapes (\z where z has no
6316 * special meaning anyway). But this causes
6317 * bugs such as string of one greek letter rho
6318 * (unicode-encoded as two bytes "cf,81")
6319 * getting encoded as "cf,CTLESC,81"
6320 * and here, converted to "cf,\,81" -
6321 * which does not go well with some flavors
6322 * of fnmatch() in unicode locales
6323 * (for example, glibc <= 2.22).
6325 * Lets add "\" only on the chars which need it.
6326 * Testcases for less obvious chars are shown.
6331 || *p
== '\\' /* case '\' in \\ ) echo ok;; *) echo WRONG;; esac */
6332 || *p
== ']' /* case ']' in [a\]] ) echo ok;; *) echo WRONG;; esac */
6333 || *p
== '-' /* case '-' in [a\-c]) echo ok;; *) echo WRONG;; esac */
6334 || *p
== '!' /* case '!' in [\!] ) echo ok;; *) echo WRONG;; esac */
6335 /* Some libc support [^negate], that's why "^" also needs love */
6336 || *p
== '^' /* case '^' in [\^] ) echo ok;; *) echo WRONG;; esac */
6342 #if BASH_PATTERN_SUBST
6343 else if (slash_position
&& p
== str
+ *slash_position
) {
6344 /* stop handling globbing */
6346 *slash_position
= q
- r
;
6347 slash_position
= NULL
;
6350 protect_against_glob
= globbing
;
6355 if (flag
& RMESCAPE_GROW
) {
6357 STADJUST(q
- r
+ 1, expdest
);
6361 #define pmatch(a, b) !fnmatch((a), (b), 0)
6364 * Prepare a pattern for a expmeta (internal glob(3)) call.
6366 * Returns an stalloced string.
6369 preglob(const char *pattern
, int flag
)
6371 return rmescapes((char *)pattern
, flag
| RMESCAPE_GLOB
, NULL
);
6375 * Put a string on the stack.
6378 memtodest(const char *p
, size_t len
, int flags
)
6380 int syntax
= flags
& EXP_QUOTED
? DQSYNTAX
: BASESYNTAX
;
6387 q
= makestrspace(len
* 2, expdest
);
6391 unsigned char c
= *p
++;
6393 if (flags
& QUOTES_ESC
) {
6394 int n
= SIT(c
, syntax
);
6396 || ((flags
& EXP_QUOTED
) && n
== CBACK
)
6401 } else if (!(flags
& EXP_KEEPNUL
))
6411 strtodest(const char *p
, int flags
)
6413 size_t len
= strlen(p
);
6414 memtodest(p
, len
, flags
);
6420 * cvtnum() is used even if math support is off (to prepare $? values and such).
6423 cvtnum(arith_t num
, int flags
)
6425 /* 32-bit and wider ints require buffer size of bytes*3 (or less) */
6426 /* If narrower: worst case, 1-byte ints: need 5 bytes: "-127<NUL>" */
6427 int len
= (sizeof(arith_t
) >= 4) ? sizeof(arith_t
) * 3 : sizeof(arith_t
) * 3 + 2;
6430 len
= fmtstr(buf
, len
, ARITH_FMT
, num
);
6431 return memtodest(buf
, len
, flags
);
6435 * Record the fact that we have to scan this region of the
6436 * string for IFS characters.
6439 recordregion(int start
, int end
, int nulonly
)
6441 struct ifsregion
*ifsp
;
6443 if (ifslastp
== NULL
) {
6447 ifsp
= ckzalloc(sizeof(*ifsp
));
6448 /*ifsp->next = NULL; - ckzalloc did it */
6449 ifslastp
->next
= ifsp
;
6453 ifslastp
->begoff
= start
;
6454 ifslastp
->endoff
= end
;
6455 ifslastp
->nulonly
= nulonly
;
6459 removerecordregions(int endoff
)
6461 if (ifslastp
== NULL
)
6464 if (ifsfirst
.endoff
> endoff
) {
6465 while (ifsfirst
.next
) {
6466 struct ifsregion
*ifsp
;
6468 ifsp
= ifsfirst
.next
->next
;
6469 free(ifsfirst
.next
);
6470 ifsfirst
.next
= ifsp
;
6473 if (ifsfirst
.begoff
> endoff
) {
6476 ifslastp
= &ifsfirst
;
6477 ifsfirst
.endoff
= endoff
;
6482 ifslastp
= &ifsfirst
;
6483 while (ifslastp
->next
&& ifslastp
->next
->begoff
< endoff
)
6484 ifslastp
= ifslastp
->next
;
6485 while (ifslastp
->next
) {
6486 struct ifsregion
*ifsp
;
6488 ifsp
= ifslastp
->next
->next
;
6489 free(ifslastp
->next
);
6490 ifslastp
->next
= ifsp
;
6493 if (ifslastp
->endoff
> endoff
)
6494 ifslastp
->endoff
= endoff
;
6498 exptilde(char *startp
, int flag
)
6509 while ((c
= *++p
) != '\0') {
6516 if (flag
& EXP_VARTILDE
)
6525 if (flag
& EXP_DISCARD
)
6528 if (*name
== '\0') {
6529 home
= lookupvar("HOME");
6531 pw
= getpwnam(name
);
6532 home
= pw
? pw
->pw_dir
: NULL
;
6537 strtodest(home
, flag
| EXP_QUOTED
);
6545 * Execute a command inside back quotes. If it's a builtin command, we
6546 * want to save its output in a block obtained from malloc. Otherwise
6547 * we fork off a subprocess and get the output of the command via a pipe.
6548 * Should be called with interrupts off.
6550 struct backcmd
{ /* result of evalbackcmd */
6551 int fd
; /* file descriptor to read from */
6552 int nleft
; /* number of chars in buffer */
6553 char *buf
; /* buffer */
6554 struct job
*jp
; /* job structure for command */
6557 /* These forward decls are needed to use "eval" code for backticks handling: */
6558 /* flags in argument to evaltree */
6559 #define EV_EXIT 01 /* exit after evaluating tree */
6560 #define EV_TESTED 02 /* exit status is checked; ignore -e flag */
6561 static int evaltree(union node
*, int);
6563 /* An evaltree() which is known to never return.
6564 * Used to use an alias:
6565 * static int evaltreenr(union node *, int) __attribute__((alias("evaltree"),__noreturn__));
6566 * but clang was reported to "transfer" noreturn-ness to evaltree() as well.
6568 static ALWAYS_INLINE NORETURN
void
6569 evaltreenr(union node
*n
, int flags
)
6572 bb_unreachable(abort());
6576 static void FAST_FUNC
6577 evalbackcmd(union node
*n
, struct backcmd
*result
6578 IF_BASH_PROCESS_SUBST(, int ctl
))
6582 #if BASH_PROCESS_SUBST
6583 /* determine end of pipe used by parent (ip) and child (ic) */
6584 const int ip
= (ctl
== CTLTOPROC
);
6585 const int ic
= !(ctl
== CTLTOPROC
);
6587 const int ctl
= CTLBACKQ
;
6601 ash_msg_and_raise_perror("can't create pipe");
6602 /* process substitution uses NULL job, like openhere() */
6603 jp
= (ctl
== CTLBACKQ
) ? makejob(/*n,*/ 1) : NULL
;
6604 if (forkshell(jp
, n
, FORK_NOJOB
) == 0) {
6608 /* ic is index of child end of pipe *and* fd to connect it to */
6609 if (pip
[ic
] != ic
) {
6611 dup2_or_raise(pip
[ic
], ic
);
6614 /* TODO: eflag clearing makes the following not abort:
6615 * ash -c 'set -e; z=$(false;echo foo); echo $z'
6616 * which is what bash does (unless it is in POSIX mode).
6617 * dash deleted "eflag = 0" line in the commit
6618 * Date: Mon, 28 Jun 2010 17:11:58 +1000
6619 * [EVAL] Don't clear eflag in evalbackcmd
6620 * For now, preserve bash-like behavior, it seems to be somewhat more useful:
6624 evaltreenr(n
, EV_EXIT
);
6628 #if BASH_PROCESS_SUBST
6629 if (ctl
!= CTLBACKQ
) {
6630 int fd
= fcntl(pip
[ip
], F_DUPFD
, 64);
6639 result
->fd
= pip
[ip
];
6643 TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n",
6644 result
->fd
, result
->buf
, result
->nleft
, result
->jp
));
6648 * Expand stuff in backwards quotes.
6651 expbackq(union node
*cmd
, int flag
IF_BASH_PROCESS_SUBST(, int ctl
))
6653 #if !BASH_PROCESS_SUBST
6654 const int ctl
= CTLBACKQ
;
6662 struct stackmark smark
;
6664 if (flag
& EXP_DISCARD
)
6668 startloc
= expdest
- (char *)stackblock();
6669 pushstackmark(&smark
, startloc
);
6670 evalbackcmd(cmd
, &in
IF_BASH_PROCESS_SUBST(, ctl
));
6671 popstackmark(&smark
);
6673 if (ctl
!= CTLBACKQ
) {
6674 sprintf(buf
, DEV_FD_PREFIX
"%d", in
.fd
);
6675 strtodest(buf
, BASESYNTAX
);
6684 memtodest(p
, i
, flag
);
6688 i
= nonblock_immune_read(in
.fd
, buf
, sizeof(buf
));
6689 TRACE(("expbackq: read returns %d\n", i
));
6698 back_exitstatus
= waitforjob(in
.jp
);
6703 /* Eat all trailing newlines */
6705 for (; dest
> ((char *)stackblock() + startloc
) && dest
[-1] == '\n';)
6709 if (!(flag
& EXP_QUOTED
))
6710 recordregion(startloc
, dest
- (char *)stackblock(), 0);
6711 TRACE(("evalbackq: size:%d:'%.*s'\n",
6712 (int)((dest
- (char *)stackblock()) - startloc
),
6713 (int)((dest
- (char *)stackblock()) - startloc
),
6714 stackblock() + startloc
));
6717 argbackq
= argbackq
->next
;
6720 /* expari needs it */
6721 static char *argstr(char *p
, int flag
);
6723 #if ENABLE_FEATURE_SH_MATH
6725 * Expand arithmetic expression. Backup to start of expression,
6726 * evaluate, place result in (backed up) result, adjust string position.
6729 expari(char *start
, int flag
)
6731 struct stackmark sm
;
6739 begoff
= expdest
- p
;
6740 p
= argstr(start
, flag
& EXP_DISCARD
);
6742 if (flag
& EXP_DISCARD
)
6745 start
= stackblock();
6746 endoff
= expdest
- start
;
6748 STADJUST(start
- expdest
, expdest
);
6750 removerecordregions(begoff
);
6752 if (flag
& QUOTES_ESC
)
6753 rmescapes(start
, 0, NULL
);
6755 pushstackmark(&sm
, endoff
);
6756 result
= ash_arith(start
);
6759 len
= cvtnum(result
, flag
);
6761 if (!(flag
& EXP_QUOTED
))
6762 recordregion(begoff
, begoff
+ len
, 0);
6769 /* argstr needs it */
6770 static char *evalvar(char *p
, int flags
);
6773 * Perform variable and command substitution. If EXP_FULL is set, output CTLESC
6774 * characters to allow for further processing. Otherwise treat
6775 * $@ like $* since no splitting will be performed.
6778 argstr(char *p
, int flag
)
6780 static const char spclchars
[] ALIGN1
= {
6788 #if BASH_PROCESS_SUBST
6792 #if ENABLE_FEATURE_SH_MATH
6798 const char *reject
= spclchars
;
6799 int breakall
= (flag
& (EXP_WORD
| EXP_QUOTED
)) == EXP_WORD
;
6804 reject
+= !!(flag
& EXP_VARTILDE2
);
6805 reject
+= flag
& EXP_VARTILDE
? 0 : 2;
6808 if (flag
& EXP_TILDE
) {
6812 p
= exptilde(p
, flag
);
6815 startloc
= expdest
- (char *)stackblock();
6820 length
+= strcspn(p
+ length
, reject
);
6824 IF_FEATURE_SH_MATH(|| c
== CTLENDARI
)
6828 * c == '=' || c == ':' || c == '\0' ||
6829 * c == CTLENDARI || c == CTLENDVAR
6832 /* c == '\0' || c == CTLENDARI || c == CTLENDVAR */
6833 end
= !!((c
- 1) & 0x80);
6835 if (length
> 0 && !(flag
& EXP_DISCARD
)) {
6839 q
= stnputs(p
, length
, expdest
);
6841 expdest
= q
- (flag
& EXP_WORD
? end
: 0);
6842 newloc
= q
- (char *)stackblock() - end
;
6843 if (breakall
&& !inquotes
&& newloc
> startloc
) {
6844 recordregion(startloc
, newloc
, 0);
6856 flag
|= EXP_VARTILDE2
;
6861 * sort of a hack - expand tildes in variable
6862 * assignments (after the first '=' and after ':'s).
6869 /* "$@" syntax adherence hack */
6870 if (!inquotes
&& !memcmp(p
, dolatstr
+ 1, DOLATSTRLEN
- 1)) {
6871 p
= evalvar(p
+ 1, flag
| EXP_QUOTED
) + 1;
6874 inquotes
^= EXP_QUOTED
;
6876 if (flag
& QUOTES_ESC
) {
6887 TRACE(("argstr: evalvar('%s')\n", p
));
6888 p
= evalvar(p
, flag
| inquotes
);
6889 TRACE(("argstr: evalvar:'%s'\n", (char *)stackblock()));
6891 #if BASH_PROCESS_SUBST
6896 expbackq(argbackq
->n
, flag
| inquotes
IF_BASH_PROCESS_SUBST(, c
));
6898 #if ENABLE_FEATURE_SH_MATH
6900 p
= expari(p
, flag
| inquotes
);
6909 scanleft(char *startp
, char *rmesc
, char *rmescend UNUSED_PARAM
,
6910 char *pattern
, int quotes
, int zero
)
6919 const char *s
= loc2
;
6926 match
= pmatch(pattern
, s
);
6931 if (quotes
&& (unsigned char)*loc
== CTLESC
)
6940 scanright(char *startp
, char *rmesc
, char *rmescend
,
6941 char *pattern
, int quotes
, int match_at_start
)
6943 #if !ENABLE_ASH_OPTIMIZE_FOR_SIZE
6944 int try2optimize
= match_at_start
;
6950 /* If we called by "${v/pattern/repl}" or "${v//pattern/repl}":
6951 * startp="escaped_value_of_v" rmesc="raw_value_of_v"
6952 * rmescend=""(ptr to NUL in rmesc) pattern="pattern" quotes=match_at_start=1
6954 * loc starts at NUL at the end of startp, loc2 starts at the end of rmesc,
6955 * and on each iteration they go back two/one char until they reach the beginning.
6956 * We try to match "raw_value_of_v", "raw_value_of_", "raw_value_of" etc.
6957 * If one of these matches, return pointer past last matched char in startp.
6959 /* TODO: document in what other circumstances we are called. */
6961 for (loc
= pattern
- 1, loc2
= rmescend
; loc
>= startp
; loc2
--) {
6964 const char *s
= loc2
;
6965 if (match_at_start
) {
6969 match
= pmatch(pattern
, s
);
6970 //bb_error_msg("pmatch(pattern:'%s',s:'%s'):%d", pattern, s, match);
6974 #if !ENABLE_ASH_OPTIMIZE_FOR_SIZE
6976 /* Maybe we can optimize this:
6977 * if pattern ends with unescaped *, we can avoid checking
6978 * shorter strings: if "foo*" doesn't match "raw_value_of_v",
6979 * it won't match truncated "raw_value_of_" strings too.
6981 unsigned plen
= strlen(pattern
);
6982 /* Does it end with "*"? */
6983 if (plen
!= 0 && pattern
[--plen
] == '*') {
6984 /* "xxxx*" is not escaped */
6985 /* "xxx\*" is escaped */
6986 /* "xx\\*" is not escaped */
6987 /* "x\\\*" is escaped */
6989 while (plen
!= 0 && pattern
[--plen
] == '\\')
6992 break; /* ends with unescaped "*" */
7000 esc
= esclen(startp
, loc
);
7011 static void varunset(const char *, const char *, const char *, int) NORETURN
;
7013 varunset(const char *end
, const char *var
, const char *umsg
, int varflags
)
7019 msg
= "parameter not set";
7021 if ((unsigned char)*end
== CTLENDVAR
) {
7022 if (varflags
& VSNUL
)
7029 ash_msg_and_raise_error("%.*s: %s%s", (int)(end
- var
- 1), var
, msg
, tail
);
7033 subevalvar(char *start
, char *str
, int strloc
,
7034 int startloc
, int varflags
, int flag
)
7036 int subtype
= varflags
& VSTYPE
;
7037 int quotes
= flag
& QUOTES_ESC
;
7040 char *rmesc
, *rmescend
;
7044 IF_BASH_PATTERN_SUBST(int workloc
;)
7045 IF_BASH_PATTERN_SUBST(int slash_pos
;)
7046 IF_BASH_PATTERN_SUBST(char *repl
;)
7048 char *(*scan
)(char*, char*, char*, char*, int, int);
7051 //bb_error_msg("subevalvar(start:'%s',str:'%s',strloc:%d,startloc:%d,varflags:%x,quotes:%d)",
7052 // start, str, strloc, startloc, varflags, quotes);
7054 #if BASH_PATTERN_SUBST
7055 /* For "${v/pattern/repl}", we must find the delimiter _before_
7056 * argstr() call expands possible variable references in pattern:
7057 * think about "v=a; a=a/; echo ${v/$a/r}" case.
7060 if (subtype
== VSREPLACE
|| subtype
== VSREPLACEALL
) {
7061 /* Find '/' and replace with NUL */
7063 /* The pattern can't be empty.
7064 * IOW: if the first char after "${v//" is a slash,
7065 * it does not terminate the pattern - it's the first char of the pattern:
7066 * v=/dev/ram; echo ${v////-} prints -dev-ram (pattern is "/")
7067 * v=/dev/ram; echo ${v///r/-} prints /dev-am (pattern is "/r")
7072 if (*repl
== '\0') {
7076 /* Skip over quoted 'str'. Example: ${var/'/'} - second / is not a separator */
7077 if ((unsigned char)*repl
== CTLQUOTEMARK
) {
7078 while ((unsigned char)*++repl
!= CTLQUOTEMARK
)
7085 if ((unsigned char)*repl
== CTLENDVAR
) { /* ${v/pattern} (no trailing /, no repl) */
7089 /* Handle escaped slashes, e.g. "${v/\//_}" (they are CTLESC'ed by this point) */
7090 if ((unsigned char)*repl
== CTLESC
&& repl
[1])
7096 argstr_flags
= (flag
& EXP_DISCARD
) | EXP_TILDE
;
7099 && subtype
!= VSSUBSTR
7102 /* EXP_CASE keeps CTLESC's */
7103 argstr_flags
|= EXP_CASE
;
7105 p
= argstr(start
, argstr_flags
);
7107 //bb_error_msg("str0:'%s'", (char *)stackblock() + strloc);
7108 #if BASH_PATTERN_SUBST
7111 slash_pos
= expdest
- ((char *)stackblock() + strloc
);
7112 if (!(flag
& EXP_DISCARD
))
7113 STPUTC('/', expdest
);
7114 //bb_error_msg("repl+1:'%s'", repl + 1);
7115 p
= argstr(repl
+ 1, (flag
& EXP_DISCARD
) | EXP_TILDE
); /* EXP_TILDE: echo "${v/x/~}" expands ~ ! */
7119 if (flag
& EXP_DISCARD
)
7122 startp
= (char *)stackblock() + startloc
;
7123 //bb_error_msg("str1:'%s'", (char *)stackblock() + strloc);
7127 setvar0(str
, startp
);
7133 varunset(start
, str
, startp
, varflags
);
7138 int pos
, len
, orig_len
;
7142 loc
= vstr
= stackblock() + strloc
;
7144 /* Read POS in ${var:POS:LEN} */
7145 colon
= strchr(loc
, ':');
7146 if (colon
) *colon
= '\0';
7147 pos
= substr_atoi(loc
);
7148 if (colon
) *colon
= ':';
7150 /* Read LEN in ${var:POS:LEN} */
7151 len
= vstr
- startp
- 1;
7152 /* *loc != '\0', guaranteed by parser */
7155 /* Adjust the length by the number of escapes */
7156 for (ptr
= startp
; ptr
< (vstr
- 1); ptr
++) {
7157 if ((unsigned char)*ptr
== CTLESC
) {
7164 if (*loc
++ == ':') {
7166 len
= substr_atoi(loc
);
7168 /* Skip POS in ${var:POS:LEN} */
7170 while (*loc
&& *loc
!= ':')
7173 len
= substr_atoi(loc
);
7176 /* ${VAR:$((-n)):l} starts n chars from the end */
7177 pos
= orig_len
+ pos
;
7179 if ((unsigned)pos
>= orig_len
) {
7180 /* apart from obvious ${VAR:999999:l},
7181 * covers ${VAR:$((-9999999)):l} - result is ""
7188 /* ${VAR:N:-M} sets LEN to strlen()-M */
7189 len
= (orig_len
- pos
) + len
;
7191 if ((unsigned)len
> (orig_len
- pos
))
7192 len
= orig_len
- pos
;
7195 /* want: loc = mempcpy(startp, startp + pos, len)
7196 * but it does not allow overlapping arguments */
7198 while (--len
>= 0) {
7203 for (vstr
= startp
; pos
!= 0; pos
--) {
7204 if ((unsigned char)*vstr
== CTLESC
)
7208 for (loc
= startp
; len
!= 0; len
--) {
7209 if ((unsigned char)*vstr
== CTLESC
)
7217 #endif /* BASH_SUBSTR */
7220 resetloc
= expdest
- (char *)stackblock();
7222 #if BASH_PATTERN_SUBST
7225 /* We'll comeback here if we grow the stack while handling
7226 * a VSREPLACE or VSREPLACEALL, since our pointers into the
7227 * stack will need rebasing, and we'll need to remove our work
7233 amount
= expdest
- ((char *)stackblock() + resetloc
);
7234 STADJUST(-amount
, expdest
);
7235 startp
= (char *)stackblock() + startloc
;
7238 rmescend
= (char *)stackblock() + strloc
;
7239 //bb_error_msg("str7:'%s'", rmescend);
7241 //TODO: how to handle slash_pos here if string changes (shortens?)
7242 rmesc
= rmescapes(startp
, RMESCAPE_ALLOC
| RMESCAPE_GROW
, NULL
);
7243 if (rmesc
!= startp
) {
7245 startp
= (char *)stackblock() + startloc
;
7249 str
= (char *)stackblock() + strloc
;
7251 * Example: v='a\bc'; echo ${v/\\b/_\\_\z_}
7252 * The result is a_\_z_c (not a\_\_z_c)!
7254 * The search pattern and replace string treat backslashes differently!
7255 * "&slash_pos" causes rmescapes() to work differently on the pattern
7256 * and string. It's only used on the first call.
7258 //bb_error_msg("str8:'%s' slash_pos:%d", str, slash_pos);
7259 rmescapes(str
, RMESCAPE_GLOB
,
7260 repl
? NULL
: (slash_pos
< 0 ? NULL
: &slash_pos
)
7263 #if BASH_PATTERN_SUBST
7264 workloc
= expdest
- (char *)stackblock();
7265 if (subtype
== VSREPLACE
|| subtype
== VSREPLACEALL
) {
7266 size_t no_meta_len
, first_escaped
;
7271 //bb_error_msg("str9:'%s' slash_pos:%d", str, slash_pos);
7273 if (slash_pos
>= 0) {
7274 repl
= str
+ slash_pos
;
7278 //bb_error_msg("str:'%s' repl:'%s'", str, repl);
7280 /* If there's no pattern to match, return the expansion unmolested */
7284 first_escaped
= (str
[0] == '\\' && str
[1]);
7285 /* "first_escaped" trick allows to treat e.g. "\*no_glob_chars"
7286 * as literal too (as it is semi-common, and easy to accomodate
7287 * by just using str + 1).
7289 no_meta_len
= strpbrk(str
+ first_escaped
* 2, "*?[\\") ? 0 : strlen(str
);
7293 while (idx
<= end
) {
7295 if (no_meta_len
== 0) {
7296 /* pattern has meta chars, have to glob */
7297 loc
= scanright(idx
, rmesc
, rmescend
, str
, quotes
, /*match_at_start:*/ 1);
7299 /* Testcase for very slow replace (performs about 22k replaces):
7300 * x=::::::::::::::::::::::
7301 * x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;echo ${#x}
7303 * To test "first_escaped" logic, replace : with *.
7305 if (strncmp(rmesc
, str
+ first_escaped
, no_meta_len
- first_escaped
) != 0)
7309 loc
+= no_meta_len
- first_escaped
;
7311 size_t n
= no_meta_len
- first_escaped
;
7313 if ((unsigned char)*loc
== CTLESC
)
7319 //bb_error_msg("scanright('%s'):'%s'", str, loc);
7321 char *restart_detect
;
7323 /* No match, advance */
7324 restart_detect
= stackblock();
7328 STPUTC(*idx
, expdest
);
7329 if (stackblock() != restart_detect
)
7331 if (quotes
&& (unsigned char)*idx
== CTLESC
) {
7334 STPUTC(*idx
, expdest
);
7335 if (stackblock() != restart_detect
)
7341 /* continue; - prone to quadratic behavior, smarter code: */
7342 if (str
[0] == '*') {
7343 /* Pattern is "*foo". If "*foo" does not match "long_string",
7344 * it would never match "ong_string" etc, no point in trying.
7351 if (subtype
== VSREPLACEALL
) {
7353 if (quotes
&& (unsigned char)*idx
== CTLESC
)
7362 /* The STPUTC invocations above may resize and move the
7363 * stack via realloc(3). Since repl is a pointer into the
7364 * stack, we need to reconstruct it relative to stackblock().
7367 repl
= (char *)stackblock() + strloc
+ slash_pos
+ 1;
7369 //bb_error_msg("repl:'%s'", repl);
7370 for (loc
= (char*)repl
; *loc
; loc
++) {
7371 char *restart_detect
= stackblock();
7372 if (quotes
&& *loc
== '\\') {
7373 STPUTC(CTLESC
, expdest
);
7374 if (stackblock() != restart_detect
)
7378 STPUTC(*loc
, expdest
);
7379 if (stackblock() != restart_detect
)
7384 if (subtype
== VSREPLACE
) {
7385 //bb_error_msg("tail:'%s', quotes:%x", idx, quotes);
7387 char *restart_detect
= stackblock();
7388 STPUTC(*idx
, expdest
);
7389 if (stackblock() != restart_detect
)
7398 /* We've put the replaced text into a buffer at workloc, now
7399 * move it to the right place and adjust the stack.
7401 STPUTC('\0', expdest
);
7402 startp
= (char *)stackblock() + startloc
;
7403 memmove(startp
, (char *)stackblock() + workloc
, len
+ 1);
7404 //bb_error_msg("startp:'%s'", startp);
7408 #endif /* BASH_PATTERN_SUBST */
7410 subtype
-= VSTRIMRIGHT
;
7412 if (subtype
< 0 || subtype
> 7)
7415 /* zero = (subtype == VSTRIMLEFT || subtype == VSTRIMLEFTMAX) */
7416 zero
= subtype
>> 1;
7417 /* VSTRIMLEFT/VSTRIMRIGHTMAX -> scanleft */
7418 scan
= (subtype
& 1) ^ zero
? scanleft
: scanright
;
7420 loc
= scan(startp
, rmesc
, rmescend
, str
, quotes
, zero
);
7423 memmove(startp
, loc
, str
- loc
);
7424 loc
= startp
+ (str
- loc
) - 1;
7431 amount
= loc
- expdest
;
7432 STADJUST(amount
, expdest
);
7433 #if BASH_PATTERN_SUBST
7436 /* Remove any recorded regions beyond start of variable */
7437 removerecordregions(startloc
);
7443 * Add the value of a specialized variable to the stack string.
7444 * name parameter (examples):
7445 * ash -c 'echo $1' name:'1='
7446 * ash -c 'echo $qwe' name:'qwe='
7447 * ash -c 'echo $$' name:'$='
7448 * ash -c 'echo ${$}' name:'$='
7449 * ash -c 'echo ${$##q}' name:'$=q'
7450 * ash -c 'echo ${#$}' name:'$='
7451 * note: examples with bad shell syntax:
7452 * ash -c 'echo ${#$1}' name:'$=1'
7453 * ash -c 'echo ${#1#}' name:'1=#'
7455 static NOINLINE ssize_t
7456 varvalue(char *name
, int varflags
, int flags
, int quoted
)
7463 int subtype
= varflags
& VSTYPE
;
7464 int discard
= (subtype
== VSPLUS
|| subtype
== VSLENGTH
) | (flags
& EXP_DISCARD
);
7471 raise_error_syntax("bad substitution");
7474 flags
|= EXP_KEEPNUL
;
7475 flags
&= discard
? ~QUOTES_ESC
: ~0;
7476 sep
= (flags
& EXP_FULL
) << CHAR_BIT
;
7486 num
= shellparam
.nparam
;
7493 len
= cvtnum(num
, flags
);
7494 goto check_1char_name
;
7496 expdest
= makestrspace(NOPTS
, expdest
);
7497 for (i
= NOPTS
- 1; i
>= 0; i
--) {
7498 if (optlist
[i
] && optletters(i
)) {
7499 USTPUTC(optletters(i
), expdest
);
7505 /* handles cases similar to ${#$1} */
7506 if (name
[2] != '\0')
7507 raise_error_syntax("bad substitution");
7519 /* We will set c to 0 or ~0 depending on whether
7520 * we're doing field splitting. We won't do field
7521 * splitting if either we're quoted or sep is zero.
7523 * Instead of testing (quoted || !sep) the following
7524 * trick optimises away any branches by using the
7525 * fact that EXP_QUOTED (which is the only bit that
7526 * can be set in quoted) is the same as EXP_FULL <<
7527 * CHAR_BIT (which is the only bit that can be set
7530 #if EXP_QUOTED >> CHAR_BIT != EXP_FULL
7531 #error The following two lines expect EXP_QUOTED == EXP_FULL << CHAR_BIT
7533 c
= !((quoted
| ~sep
) & EXP_QUOTED
) - 1;
7535 sep
|= ifsset() ? (unsigned char)(c
& ifsval()[0]) : ' ';
7541 while ((p
= *ap
++) != NULL
) {
7542 len
+= strtodest(p
, flags
);
7546 memtodest(&sepc
, 1, flags
);
7561 num
= atoi(name
); /* number(name) fails on ${N#str} etc */
7562 if (num
< 0 || num
> shellparam
.nparam
)
7564 p
= num
? shellparam
.p
[num
- 1] : arg0
;
7567 /* NB: name has form "VAR=..." */
7568 p
= lookupvar(name
);
7573 len
= strtodest(p
, flags
);
7574 #if ENABLE_UNICODE_SUPPORT
7575 if (subtype
== VSLENGTH
&& len
> 0) {
7576 reinit_unicode_for_ash();
7577 if (unicode_status
== UNICODE_ON
) {
7578 STADJUST(-len
, expdest
);
7580 len
= unicode_strlen(p
);
7588 STADJUST(-len
, expdest
);
7594 * Expand a variable, and return a pointer to the next character in the
7598 evalvar(char *p
, int flag
)
7609 varflags
= (unsigned char) *p
++;
7610 subtype
= varflags
& VSTYPE
;
7612 quoted
= flag
& EXP_QUOTED
;
7614 startloc
= expdest
- (char *)stackblock();
7615 p
= strchr(p
, '=') + 1; //TODO: use var_end(p)?
7618 varlen
= varvalue(var
, varflags
, flag
, quoted
);
7619 if (varflags
& VSNUL
)
7622 discard
= varlen
< 0 ? EXP_DISCARD
: 0;
7626 discard
^= EXP_DISCARD
;
7630 p
= argstr(p
, flag
| EXP_TILDE
| EXP_WORD
| (discard
^ EXP_DISCARD
));
7635 p
= subevalvar(p
, var
, 0, startloc
, varflags
,
7636 (flag
& ~QUOTES_ESC
) | (discard
^ EXP_DISCARD
));
7638 if ((flag
| ~discard
) & EXP_DISCARD
)
7646 if ((discard
& ~flag
) && uflag
)
7647 varunset(p
, var
, 0, 0);
7649 if (subtype
== VSLENGTH
) {
7651 if (flag
& EXP_DISCARD
)
7653 cvtnum(varlen
> 0 ? varlen
: 0, flag
);
7657 if (subtype
== VSNORMAL
)
7665 case VSTRIMRIGHTMAX
:
7669 #if BASH_PATTERN_SUBST
7680 if (!(flag
& EXP_DISCARD
)) {
7682 * Terminate the string and start recording the pattern
7685 STPUTC('\0', expdest
);
7688 patloc
= expdest
- (char *)stackblock();
7689 p
= subevalvar(p
, NULL
, patloc
, startloc
, varflags
, flag
);
7692 if ((flag
| discard
) & EXP_DISCARD
)
7697 quoted
= *var
== '@' && shellparam
.nparam
;
7701 recordregion(startloc
, expdest
- (char *)stackblock(), quoted
);
7706 * Add a file name to the list.
7709 addfname(const char *name
)
7713 sp
= stzalloc(sizeof(*sp
));
7714 sp
->text
= sstrdup(name
);
7716 exparg
.lastp
= &sp
->next
;
7719 /* Avoid glob() (and thus, stat() et al) for words like "echo" */
7721 hasmeta(const char *p
)
7723 static const char chars
[] ALIGN1
= {
7724 '*', '?', '[', '\\', CTLQUOTEMARK
, CTLESC
, 0
7728 p
= strpbrk(p
, chars
);
7731 switch ((unsigned char)*p
) {
7735 if ((unsigned char)*p
== CTLQUOTEMARK
)
7737 if ((unsigned char)*p
== CTLESC
)
7739 if (*p
== '\0') /* huh? */
7750 if (!strchr(p
+ 1, ']')) {
7751 /* It's not a properly closed [] pattern,
7752 * but other metas may follow. Continue checking.
7753 * my[file* _is_ globbed by bash
7754 * and matches filenames like "my[file1".
7770 /* If we want to use glob() from libc... */
7771 #if !ENABLE_ASH_INTERNAL_GLOB
7773 /* Add the result of glob() to the list */
7775 addglob(const glob_t
*pglob
)
7777 char **p
= pglob
->gl_pathv
;
7784 expandmeta(struct strlist
*str
/*, int flag*/)
7786 /* TODO - EXP_REDIR */
7796 if (!hasmeta(str
->text
))
7800 p
= preglob(str
->text
, RMESCAPE_ALLOC
| RMESCAPE_HEAP
);
7801 // GLOB_NOMAGIC (GNU): if no *?[ chars in pattern, return it even if no match
7802 // GLOB_NOCHECK: if no match, return unchanged pattern (sans \* escapes?)
7804 // glibc 2.24.90 glob(GLOB_NOMAGIC) does not remove backslashes used for escaping:
7805 // if you pass it "file\?", it returns "file\?", not "file?", if no match.
7806 // Which means you need to unescape the string, right? Not so fast:
7807 // if there _is_ a file named "file\?" (with backslash), it is returned
7808 // as "file\?" too (whichever pattern you used to find it, say, "file*").
7809 // You DON'T KNOW by looking at the result whether you need to unescape it.
7811 // Worse, globbing of "file\?" in a directory with two files, "file?" and "file\?",
7812 // returns "file\?" - which is WRONG: "file\?" pattern matches "file?" file.
7813 // Without GLOB_NOMAGIC, this works correctly ("file?" is returned as a match).
7814 // With GLOB_NOMAGIC | GLOB_NOCHECK, this also works correctly.
7815 // i = glob(p, GLOB_NOMAGIC | GLOB_NOCHECK, NULL, &pglob);
7816 // i = glob(p, GLOB_NOMAGIC, NULL, &pglob);
7817 i
= glob(p
, 0, NULL
, &pglob
);
7818 //bb_error_msg("glob('%s'):%d '%s'...", p, i, pglob.gl_pathv ? pglob.gl_pathv[0] : "-");
7823 #if 0 // glibc 2.24.90 bug? Patterns like "*/file", when match, don't set GLOB_MAGCHAR
7824 /* GLOB_MAGCHAR is set if *?[ chars were seen (GNU) */
7825 if (!(pglob
.gl_flags
& GLOB_MAGCHAR
))
7837 *exparg
.lastp
= str
;
7838 rmescapes(str
->text
, 0, NULL
);
7839 exparg
.lastp
= &str
->next
;
7841 default: /* GLOB_NOSPACE */
7844 ash_msg_and_raise_error(bb_msg_memory_exhausted
);
7851 /* ENABLE_ASH_INTERNAL_GLOB: Homegrown globbing code. (dash also has both, uses homegrown one.) */
7854 * Do metacharacter (i.e. *, ?, [...]) expansion.
7856 typedef struct exp_t
{
7861 expmeta(exp_t
*exp
, char *name
, unsigned name_len
, unsigned expdir_len
)
7863 #define expdir exp->dir
7864 #define expdir_max exp->dir_max
7865 char *enddir
= expdir
+ expdir_len
;
7880 for (p
= name
; esc
= 0, *p
; p
+= esc
+ 1) {
7881 if (*p
== '*' || *p
== '?')
7883 else if (*p
== '[') {
7890 if (*q
== '/' || *q
== '\0')
7898 if (*p
== '\\' && p
[1])
7900 if (p
[esc
] == '/') {
7903 start
= p
+ esc
+ 1;
7907 if (metaflag
== 0) { /* we've reached the end of the file name */
7912 if (*p
== '\\' && p
[1])
7916 if (lstat(expdir
, &statb
) == 0)
7924 if (*p
== '\\' && p
[1])
7927 } while (p
< start
);
7931 expdir_len
= enddir
- cp
;
7937 if (*endname
== 0) {
7944 name_len
-= endname
- name
;
7951 while (!pending_int
&& (dp
= readdir(dirp
)) != NULL
) {
7952 if (dp
->d_name
[0] == '.' && !matchdot
)
7954 if (pmatch(start
, dp
->d_name
)) {
7956 strcpy(enddir
, dp
->d_name
);
7962 p
= stpcpy(enddir
, dp
->d_name
);
7965 offset
= p
- expdir
+ 1;
7966 len
= offset
+ name_len
+ NAME_MAX
;
7967 if (len
> expdir_max
) {
7969 expdir
= ckrealloc(expdir
, len
);
7973 expmeta(exp
, endname
, name_len
, offset
);
7974 enddir
= expdir
+ expdir_len
;
7980 endname
[-esc
- 1] = esc
? '\\' : '/';
7985 static struct strlist
*
7986 msort(struct strlist
*list
, int len
)
7988 struct strlist
*p
, *q
= NULL
;
7989 struct strlist
**lpp
;
7997 for (n
= half
; --n
>= 0;) {
8001 q
->next
= NULL
; /* terminate first half of list */
8002 q
= msort(list
, half
); /* sort first half of list */
8003 p
= msort(p
, len
- half
); /* sort second half */
8006 #if ENABLE_LOCALE_SUPPORT
8007 if (strcoll(p
->text
, q
->text
) < 0)
8009 if (strcmp(p
->text
, q
->text
) < 0)
8033 * Sort the results of file name expansion. It calculates the number of
8034 * strings to sort and then calls msort (short for merge sort) to do the
8037 static struct strlist
*
8038 expsort(struct strlist
*str
)
8044 for (sp
= str
; sp
; sp
= sp
->next
)
8046 return msort(str
, len
);
8050 expandmeta(struct strlist
*str
/*, int flag*/)
8052 /* TODO - EXP_REDIR */
8056 struct strlist
**savelastp
;
8063 if (!hasmeta(str
->text
))
8065 savelastp
= exparg
.lastp
;
8068 p
= preglob(str
->text
, RMESCAPE_ALLOC
| RMESCAPE_HEAP
);
8070 exp
.dir_max
= len
+ PATH_MAX
;
8071 exp
.dir
= ckmalloc(exp
.dir_max
);
8073 expmeta(&exp
, p
, len
, 0);
8078 if (exparg
.lastp
== savelastp
) {
8083 *exparg
.lastp
= str
;
8084 rmescapes(str
->text
, 0, NULL
);
8085 exparg
.lastp
= &str
->next
;
8087 *exparg
.lastp
= NULL
;
8088 *savelastp
= sp
= expsort(*savelastp
);
8089 while (sp
->next
!= NULL
)
8091 exparg
.lastp
= &sp
->next
;
8096 #endif /* ENABLE_ASH_INTERNAL_GLOB */
8099 * Perform variable substitution and command substitution on an argument,
8100 * placing the resulting list of arguments in arglist. If EXP_FULL is true,
8101 * perform splitting and file name expansion. When arglist is NULL, perform
8102 * here document expansion.
8105 expandarg(union node
*arg
, struct arglist
*arglist
, int flag
)
8110 argbackq
= arg
->narg
.backquote
;
8111 STARTSTACKSTR(expdest
);
8112 TRACE(("expandarg: argstr('%s',flags:%x)\n", arg
->narg
.text
, flag
));
8113 argstr(arg
->narg
.text
, flag
);
8114 if (arglist
== NULL
) {
8115 /* here document expanded */
8118 p
= grabstackstr(expdest
);
8119 TRACE(("expandarg: p:'%s'\n", p
));
8120 exparg
.lastp
= &exparg
.list
;
8124 if (flag
& EXP_FULL
) {
8125 ifsbreakup(p
, &exparg
);
8126 *exparg
.lastp
= NULL
;
8127 exparg
.lastp
= &exparg
.list
;
8128 expandmeta(exparg
.list
/*, flag*/);
8130 sp
= stzalloc(sizeof(*sp
));
8133 exparg
.lastp
= &sp
->next
;
8135 *exparg
.lastp
= NULL
;
8137 *arglist
->lastp
= exparg
.list
;
8138 arglist
->lastp
= exparg
.lastp
;
8146 * Expand shell variables and backquotes inside a here document.
8149 expandhere(union node
*arg
)
8151 expandarg(arg
, (struct arglist
*)NULL
, EXP_QUOTED
);
8155 * Returns true if the pattern matches the string.
8158 patmatch(char *pattern
, const char *string
)
8160 char *p
= preglob(pattern
, 0);
8161 int r
= pmatch(p
, string
);
8162 //bb_error_msg("!fnmatch(pattern:'%s',str:'%s',0):%d", p, string, r);
8167 * See if a pattern matches in a case statement.
8170 casematch(union node
*pattern
, char *val
)
8172 struct stackmark smark
;
8175 setstackmark(&smark
);
8176 argbackq
= pattern
->narg
.backquote
;
8177 STARTSTACKSTR(expdest
);
8178 argstr(pattern
->narg
.text
, EXP_TILDE
| EXP_CASE
);
8180 result
= patmatch(stackblock(), val
);
8181 popstackmark(&smark
);
8186 /* ============ find_command */
8190 int (*builtin
)(int, char **) FAST_FUNC
;
8191 /* unsigned flags; */
8193 #define IS_BUILTIN_SPECIAL(b) ((b)->name[0] & 1)
8194 /* "regular" builtins always take precedence over commands,
8195 * regardless of PATH=....%builtin... position */
8196 #define IS_BUILTIN_REGULAR(b) ((b)->name[0] & 2)
8197 #define IS_BUILTIN_ASSIGN(b) ((b)->name[0] & 4)
8200 smallint cmdtype
; /* CMDxxx */
8203 /* index >= 0 for commands without path (slashes) */
8204 /* (TODO: what exactly does the value mean? PATH position?) */
8205 /* index == -1 for commands with slashes */
8206 /* index == (-2 - applet_no) for NOFORK applets */
8207 const struct builtincmd
*cmd
;
8208 struct funcnode
*func
;
8211 /* values of cmdtype */
8212 #define CMDUNKNOWN -1 /* no entry in table for command */
8213 #define CMDNORMAL 0 /* command is an executable program */
8214 #define CMDFUNCTION 1 /* command is a shell function */
8215 #define CMDBUILTIN 2 /* command is a shell builtin */
8217 /* action to find_command() */
8218 #define DO_ERR 0x01 /* prints errors */
8219 #define DO_ABS 0x02 /* checks absolute paths */
8220 #define DO_NOFUNC 0x04 /* don't return shell functions, for command */
8221 #define DO_ALTPATH 0x08 /* using alternate path */
8222 #define DO_REGBLTIN 0x10 /* regular built-ins and functions only */
8224 static void find_command(char *, struct cmdentry
*, int, const char *);
8227 /* ============ Hashing commands */
8230 * When commands are first encountered, they are entered in a hash table.
8231 * This ensures that a full path search will not have to be done for them
8232 * on each invocation.
8234 * We should investigate converting to a linear search, even though that
8235 * would make the command name "hash" a misnomer.
8239 struct tblentry
*next
; /* next entry in hash chain */
8240 union param param
; /* definition of builtin function */
8241 smallint cmdtype
; /* CMDxxx */
8242 char rehash
; /* if set, cd done since entry created */
8243 char cmdname
[1]; /* name of command */
8246 static struct tblentry
**cmdtable
;
8247 #define INIT_G_cmdtable() do { \
8248 cmdtable = xzalloc(CMDTABLESIZE * sizeof(cmdtable[0])); \
8251 static int builtinloc
= -1; /* index in path of %builtin, or -1 */
8255 tryexec(IF_FEATURE_SH_STANDALONE(int applet_no
,) const char *cmd
, char **argv
, char **envp
)
8257 #if ENABLE_FEATURE_SH_STANDALONE
8258 if (applet_no
>= 0) {
8259 if (APPLET_IS_NOEXEC(applet_no
)) {
8263 popredir(/*drop:*/ 1);
8264 run_noexec_applet_and_exit(applet_no
, cmd
, argv
);
8266 /* re-exec ourselves with the new arguments */
8267 execve(bb_busybox_exec_path
, argv
, envp
);
8268 /* If they called chroot or otherwise made the binary no longer
8269 * executable, fall through */
8276 execve(cmd
, argv
, envp
);
8277 } while (errno
== EINTR
);
8279 execve(cmd
, argv
, envp
);
8282 if (cmd
!= bb_busybox_exec_path
&& errno
== ENOEXEC
) {
8283 /* Run "cmd" as a shell script:
8284 * http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html
8285 * "If the execve() function fails with ENOEXEC, the shell
8286 * shall execute a command equivalent to having a shell invoked
8287 * with the command name as its first operand,
8288 * with any remaining arguments passed to the new shell"
8290 * That is, do not use $SHELL, user's shell, or /bin/sh;
8291 * just call ourselves.
8293 * Note that bash reads ~80 chars of the file, and if it sees
8294 * a zero byte before it sees newline, it doesn't try to
8295 * interpret it, but fails with "cannot execute binary file"
8296 * message and exit code 126. For one, this prevents attempts
8297 * to interpret foreign ELF binaries as shell scripts.
8299 argv
[0] = (char*) cmd
;
8300 cmd
= bb_busybox_exec_path
;
8301 /* NB: this is only possible because all callers of shellexec()
8302 * ensure that the argv[-1] slot exists!
8305 argv
[0] = (char*) "ash";
8311 * Exec a program. Never returns. If you change this routine, you may
8312 * have to change the find_command routine as well.
8313 * argv[-1] must exist and be writable! See tryexec() for why.
8315 static void shellexec(char *prog
, char **argv
, const char *path
, int idx
) NORETURN
;
8316 static void shellexec(char *prog
, char **argv
, const char *path
, int idx
)
8322 int applet_no
= -1; /* used only by FEATURE_SH_STANDALONE */
8324 envp
= listvars(VEXPORT
, VUNSET
, /*strlist:*/ NULL
, /*end:*/ NULL
);
8325 if (strchr(prog
, '/') != NULL
8326 #if ENABLE_FEATURE_SH_STANDALONE
8327 || (applet_no
= find_applet_by_name(prog
)) >= 0
8330 tryexec(IF_FEATURE_SH_STANDALONE(applet_no
,) prog
, argv
, envp
);
8331 if (applet_no
>= 0) {
8332 /* We tried execing ourself, but it didn't work.
8333 * Maybe /proc/self/exe doesn't exist?
8342 while (padvance(&path
, argv
[0]) >= 0) {
8343 cmdname
= stackblock();
8344 if (--idx
< 0 && pathopt
== NULL
) {
8345 tryexec(IF_FEATURE_SH_STANDALONE(-1,) cmdname
, argv
, envp
);
8346 if (errno
!= ENOENT
&& errno
!= ENOTDIR
)
8352 /* Map to POSIX errors */
8364 exitstatus
= exerrno
;
8365 TRACE(("shellexec failed for %s, errno %d, suppress_int %d\n",
8366 prog
, e
, suppress_int
));
8367 ash_msg_and_raise(EXEND
, "%s: %s", prog
, errmsg(e
, "not found"));
8372 printentry(struct tblentry
*cmdp
)
8378 idx
= cmdp
->param
.index
;
8381 padvance(&path
, cmdp
->cmdname
);
8382 } while (--idx
>= 0);
8383 name
= stackblock();
8384 out1fmt("%s%s\n", name
, (cmdp
->rehash
? "*" : nullstr
));
8388 * Clear out command entries.
8393 struct tblentry
**tblp
;
8394 struct tblentry
**pp
;
8395 struct tblentry
*cmdp
;
8398 for (tblp
= cmdtable
; tblp
< &cmdtable
[CMDTABLESIZE
]; tblp
++) {
8400 while ((cmdp
= *pp
) != NULL
) {
8401 if (cmdp
->cmdtype
== CMDNORMAL
8402 || (cmdp
->cmdtype
== CMDBUILTIN
8403 && !IS_BUILTIN_REGULAR(cmdp
->param
.cmd
)
8418 * Locate a command in the command hash table. If "add" is nonzero,
8419 * add the command to the table if it is not already present. The
8420 * variable "lastcmdentry" is set to point to the address of the link
8421 * pointing to the entry, so that delete_cmd_entry can delete the
8424 * Interrupts must be off if called with add != 0.
8426 static struct tblentry
**lastcmdentry
;
8428 static struct tblentry
*
8429 cmdlookup(const char *name
, int add
)
8431 unsigned int hashval
;
8433 struct tblentry
*cmdp
;
8434 struct tblentry
**pp
;
8437 hashval
= (unsigned char)*p
<< 4;
8439 hashval
+= (unsigned char)*p
++;
8441 pp
= &cmdtable
[hashval
% CMDTABLESIZE
];
8442 for (cmdp
= *pp
; cmdp
; cmdp
= cmdp
->next
) {
8443 if (strcmp(cmdp
->cmdname
, name
) == 0)
8447 if (add
&& cmdp
== NULL
) {
8448 cmdp
= *pp
= ckzalloc(sizeof(struct tblentry
)
8450 /* + 1 - already done because
8451 * tblentry::cmdname is char[1] */);
8452 /*cmdp->next = NULL; - ckzalloc did it */
8453 cmdp
->cmdtype
= CMDUNKNOWN
;
8454 strcpy(cmdp
->cmdname
, name
);
8461 * Delete the command entry returned on the last lookup.
8464 delete_cmd_entry(void)
8466 struct tblentry
*cmdp
;
8469 cmdp
= *lastcmdentry
;
8470 *lastcmdentry
= cmdp
->next
;
8471 if (cmdp
->cmdtype
== CMDFUNCTION
)
8472 freefunc(cmdp
->param
.func
);
8478 * Add a new command entry, replacing any existing command entry for
8479 * the same name - except special builtins.
8482 addcmdentry(char *name
, struct cmdentry
*entry
)
8484 struct tblentry
*cmdp
;
8486 cmdp
= cmdlookup(name
, 1);
8487 if (cmdp
->cmdtype
== CMDFUNCTION
) {
8488 freefunc(cmdp
->param
.func
);
8490 cmdp
->cmdtype
= entry
->cmdtype
;
8491 cmdp
->param
= entry
->u
;
8495 static int FAST_FUNC
8496 hashcmd(int argc UNUSED_PARAM
, char **argv UNUSED_PARAM
)
8498 struct tblentry
**pp
;
8499 struct tblentry
*cmdp
;
8501 struct cmdentry entry
;
8504 if (nextopt("r") != '\0') {
8509 if (*argptr
== NULL
) {
8510 for (pp
= cmdtable
; pp
< &cmdtable
[CMDTABLESIZE
]; pp
++) {
8511 for (cmdp
= *pp
; cmdp
; cmdp
= cmdp
->next
) {
8512 if (cmdp
->cmdtype
== CMDNORMAL
)
8520 while ((name
= *argptr
) != NULL
) {
8521 cmdp
= cmdlookup(name
, 0);
8523 && (cmdp
->cmdtype
== CMDNORMAL
8524 || (cmdp
->cmdtype
== CMDBUILTIN
8525 && !IS_BUILTIN_REGULAR(cmdp
->param
.cmd
)
8532 find_command(name
, &entry
, DO_ERR
, pathval());
8533 if (entry
.cmdtype
== CMDUNKNOWN
)
8541 * Called when a cd is done. Marks all commands so the next time they
8542 * are executed they will be rehashed.
8547 struct tblentry
**pp
;
8548 struct tblentry
*cmdp
;
8550 for (pp
= cmdtable
; pp
< &cmdtable
[CMDTABLESIZE
]; pp
++) {
8551 for (cmdp
= *pp
; cmdp
; cmdp
= cmdp
->next
) {
8552 if (cmdp
->cmdtype
== CMDNORMAL
8553 || (cmdp
->cmdtype
== CMDBUILTIN
8554 && !IS_BUILTIN_REGULAR(cmdp
->param
.cmd
)
8564 * Fix command hash table when PATH changed.
8565 * Called before PATH is changed. The argument is the new value of PATH;
8566 * pathval() still returns the old value at this point.
8567 * Called with interrupts off.
8569 static void FAST_FUNC
8570 changepath(const char *newval
)
8580 if (*new == '%' && prefix(new + 1, "builtin")) {
8584 new = strchr(new, ':');
8627 typedef smallint token_id_t
;
8629 /* Nth bit indicates if token marks the end of a list */
8632 /* 0 */ | (1u << TEOF
)
8633 /* 1 */ | (0u << TNL
)
8634 /* 2 */ | (0u << TREDIR
)
8635 /* 3 */ | (0u << TWORD
)
8636 /* 4 */ | (0u << TSEMI
)
8637 /* 5 */ | (0u << TBACKGND
)
8638 /* 6 */ | (0u << TAND
)
8639 /* 7 */ | (0u << TOR
)
8640 /* 8 */ | (0u << TPIPE
)
8641 /* 9 */ | (0u << TLP
)
8642 /* 10 */ | (1u << TRP
)
8643 /* 11 */ | (1u << TENDCASE
)
8644 /* 12 */ | (1u << TENDBQUOTE
)
8645 /* 13 */ | (0u << TNOT
)
8646 /* 14 */ | (0u << TCASE
)
8647 /* 15 */ | (1u << TDO
)
8648 /* 16 */ | (1u << TDONE
)
8649 /* 17 */ | (1u << TELIF
)
8650 /* 18 */ | (1u << TELSE
)
8651 /* 19 */ | (1u << TESAC
)
8652 /* 20 */ | (1u << TFI
)
8653 /* 21 */ | (0u << TFOR
)
8655 /* 22 */ | (0u << TFUNCTION
)
8657 /* 23 */ | (0u << TIF
)
8658 /* 24 */ | (0u << TIN
)
8659 /* 25 */ | (1u << TTHEN
)
8660 /* 26 */ | (0u << TUNTIL
)
8661 /* 27 */ | (0u << TWHILE
)
8662 /* 28 */ | (0u << TBEGIN
)
8663 /* 29 */ | (1u << TEND
)
8664 , /* thus far 29 bits used */
8667 static const char *const tokname_array
[] ALIGN_PTR
= {
8681 #define KWDOFFSET 13
8682 /* the following are keywords */
8704 /* Wrapper around strcmp for qsort/bsearch/... */
8706 pstrcmp(const void *a
, const void *b
)
8708 return strcmp((char*)a
, *(char**)b
);
8711 static const char *const *
8712 findkwd(const char *s
)
8714 return bsearch(s
, tokname_array
+ KWDOFFSET
,
8715 ARRAY_SIZE(tokname_array
) - KWDOFFSET
,
8716 sizeof(tokname_array
[0]), pstrcmp
);
8720 * Locate and print what a word is...
8723 describe_command(char *command
, const char *path
, int describe_command_verbose
)
8725 struct cmdentry entry
;
8726 #if ENABLE_ASH_ALIAS
8727 const struct alias
*ap
;
8730 if (describe_command_verbose
) {
8734 /* First look at the keywords */
8735 if (findkwd(command
)) {
8736 out1str(describe_command_verbose
? " is a shell keyword" : command
);
8740 #if ENABLE_ASH_ALIAS
8741 /* Then look at the aliases */
8742 ap
= lookupalias(command
, 0);
8744 if (!describe_command_verbose
) {
8749 out1fmt(" is an alias for %s", ap
->val
);
8754 path
= path
? path
: pathval();
8755 find_command(command
, &entry
, DO_ABS
, path
);
8757 switch (entry
.cmdtype
) {
8759 int j
= entry
.u
.index
;
8765 padvance(&path
, command
);
8769 if (describe_command_verbose
) {
8770 out1fmt(" is %s", p
);
8778 if (describe_command_verbose
) {
8779 /*out1str(" is a shell function");*/
8780 out1str(" is a function"); /* bash says this */
8787 if (describe_command_verbose
) {
8788 out1fmt(" is a %sshell builtin",
8789 IS_BUILTIN_SPECIAL(entry
.u
.cmd
) ?
8790 "special " : nullstr
8798 if (describe_command_verbose
) {
8799 out1str(": not found\n");
8808 static int FAST_FUNC
8809 typecmd(int argc UNUSED_PARAM
, char **argv
)
8815 /* type -p ... ? (we don't bother checking for 'p') */
8816 if (argv
[1] && argv
[1][0] == '-') {
8821 err
|= describe_command(argv
[i
++], NULL
, verbose
);
8826 static struct strlist
*
8827 fill_arglist(struct arglist
*arglist
, union node
**argpp
)
8829 struct strlist
**lastp
= arglist
->lastp
;
8832 while ((argp
= *argpp
) != NULL
) {
8833 expandarg(argp
, arglist
, EXP_FULL
| EXP_TILDE
);
8834 *argpp
= argp
->narg
.next
;
8842 #if ENABLE_ASH_CMDCMD
8843 /* Is it "command [-p] PROG ARGS" bltin, no other opts? Return ptr to "PROG" if yes */
8845 parse_command_args(struct arglist
*arglist
, union node
**argpp
, const char **path
)
8847 struct strlist
*sp
= arglist
->list
;
8851 sp
= sp
->next
? sp
->next
: fill_arglist(arglist
, argpp
);
8860 if (c
== '-' && !*cp
) {
8861 if (!sp
->next
&& !fill_arglist(arglist
, argpp
))
8869 *path
= bb_default_path
;
8872 /* run 'typecmd' for other options */
8883 static int FAST_FUNC
8884 commandcmd(int argc UNUSED_PARAM
, char **argv UNUSED_PARAM
)
8892 const char *path
= NULL
;
8894 /* "command [-p] PROG ARGS" (that is, without -V or -v)
8895 * never reaches this function.
8898 while ((c
= nextopt("pvV")) != '\0')
8900 verify
|= VERIFY_VERBOSE
;
8902 /*verify |= VERIFY_BRIEF*/;
8908 path
= bb_default_path
;
8910 /* Mimic bash: just "command -v" doesn't complain, it's a nop */
8912 if (/*verify && */ cmd
)
8913 return describe_command(cmd
, path
, verify
/* - VERIFY_BRIEF*/);
8920 /*static int funcblocksize; // size of structures in function */
8921 /*static int funcstringsize; // size of strings in node */
8922 static void *funcblock
; /* block to allocate function from */
8923 static char *funcstring_end
; /* end of block to allocate strings from */
8925 static const uint8_t nodesize
[N_NUMBER
] ALIGN1
= {
8926 [NCMD
] = SHELL_ALIGN(sizeof(struct ncmd
)),
8927 [NPIPE
] = SHELL_ALIGN(sizeof(struct npipe
)),
8928 [NREDIR
] = SHELL_ALIGN(sizeof(struct nredir
)),
8929 [NBACKGND
] = SHELL_ALIGN(sizeof(struct nredir
)),
8930 [NSUBSHELL
] = SHELL_ALIGN(sizeof(struct nredir
)),
8931 [NAND
] = SHELL_ALIGN(sizeof(struct nbinary
)),
8932 [NOR
] = SHELL_ALIGN(sizeof(struct nbinary
)),
8933 [NSEMI
] = SHELL_ALIGN(sizeof(struct nbinary
)),
8934 [NIF
] = SHELL_ALIGN(sizeof(struct nif
)),
8935 [NWHILE
] = SHELL_ALIGN(sizeof(struct nbinary
)),
8936 [NUNTIL
] = SHELL_ALIGN(sizeof(struct nbinary
)),
8937 [NFOR
] = SHELL_ALIGN(sizeof(struct nfor
)),
8938 [NCASE
] = SHELL_ALIGN(sizeof(struct ncase
)),
8939 [NCLIST
] = SHELL_ALIGN(sizeof(struct nclist
)),
8940 [NDEFUN
] = SHELL_ALIGN(sizeof(struct narg
)),
8941 [NARG
] = SHELL_ALIGN(sizeof(struct narg
)),
8942 [NTO
] = SHELL_ALIGN(sizeof(struct nfile
)),
8943 #if BASH_REDIR_OUTPUT
8944 [NTO2
] = SHELL_ALIGN(sizeof(struct nfile
)),
8946 [NCLOBBER
] = SHELL_ALIGN(sizeof(struct nfile
)),
8947 [NFROM
] = SHELL_ALIGN(sizeof(struct nfile
)),
8948 [NFROMTO
] = SHELL_ALIGN(sizeof(struct nfile
)),
8949 [NAPPEND
] = SHELL_ALIGN(sizeof(struct nfile
)),
8950 [NTOFD
] = SHELL_ALIGN(sizeof(struct ndup
)),
8951 [NFROMFD
] = SHELL_ALIGN(sizeof(struct ndup
)),
8952 [NHERE
] = SHELL_ALIGN(sizeof(struct nhere
)),
8953 [NXHERE
] = SHELL_ALIGN(sizeof(struct nhere
)),
8954 [NNOT
] = SHELL_ALIGN(sizeof(struct nnot
)),
8957 static int calcsize(int funcblocksize
, union node
*n
);
8960 sizenodelist(int funcblocksize
, struct nodelist
*lp
)
8963 funcblocksize
+= SHELL_ALIGN(sizeof(struct nodelist
));
8964 funcblocksize
= calcsize(funcblocksize
, lp
->n
);
8967 return funcblocksize
;
8971 calcsize(int funcblocksize
, union node
*n
)
8974 return funcblocksize
;
8975 funcblocksize
+= nodesize
[n
->type
];
8978 funcblocksize
= calcsize(funcblocksize
, n
->ncmd
.redirect
);
8979 funcblocksize
= calcsize(funcblocksize
, n
->ncmd
.args
);
8980 funcblocksize
= calcsize(funcblocksize
, n
->ncmd
.assign
);
8983 funcblocksize
= sizenodelist(funcblocksize
, n
->npipe
.cmdlist
);
8988 funcblocksize
= calcsize(funcblocksize
, n
->nredir
.redirect
);
8989 funcblocksize
= calcsize(funcblocksize
, n
->nredir
.n
);
8996 funcblocksize
= calcsize(funcblocksize
, n
->nbinary
.ch2
);
8997 funcblocksize
= calcsize(funcblocksize
, n
->nbinary
.ch1
);
9000 funcblocksize
= calcsize(funcblocksize
, n
->nif
.elsepart
);
9001 funcblocksize
= calcsize(funcblocksize
, n
->nif
.ifpart
);
9002 funcblocksize
= calcsize(funcblocksize
, n
->nif
.test
);
9005 funcblocksize
+= SHELL_ALIGN(strlen(n
->nfor
.var
) + 1); /* was funcstringsize += ... */
9006 funcblocksize
= calcsize(funcblocksize
, n
->nfor
.body
);
9007 funcblocksize
= calcsize(funcblocksize
, n
->nfor
.args
);
9010 funcblocksize
= calcsize(funcblocksize
, n
->ncase
.cases
);
9011 funcblocksize
= calcsize(funcblocksize
, n
->ncase
.expr
);
9014 funcblocksize
= calcsize(funcblocksize
, n
->nclist
.body
);
9015 funcblocksize
= calcsize(funcblocksize
, n
->nclist
.pattern
);
9016 funcblocksize
= calcsize(funcblocksize
, n
->nclist
.next
);
9019 funcblocksize
= calcsize(funcblocksize
, n
->ndefun
.body
);
9020 funcblocksize
+= SHELL_ALIGN(strlen(n
->ndefun
.text
) + 1);
9023 funcblocksize
= sizenodelist(funcblocksize
, n
->narg
.backquote
);
9024 funcblocksize
+= SHELL_ALIGN(strlen(n
->narg
.text
) + 1); /* was funcstringsize += ... */
9025 funcblocksize
= calcsize(funcblocksize
, n
->narg
.next
);
9028 #if BASH_REDIR_OUTPUT
9035 funcblocksize
= calcsize(funcblocksize
, n
->nfile
.fname
);
9036 funcblocksize
= calcsize(funcblocksize
, n
->nfile
.next
);
9040 funcblocksize
= calcsize(funcblocksize
, n
->ndup
.vname
);
9041 funcblocksize
= calcsize(funcblocksize
, n
->ndup
.next
);
9045 funcblocksize
= calcsize(funcblocksize
, n
->nhere
.doc
);
9046 funcblocksize
= calcsize(funcblocksize
, n
->nhere
.next
);
9049 funcblocksize
= calcsize(funcblocksize
, n
->nnot
.com
);
9052 return funcblocksize
;
9056 nodeckstrdup(char *s
)
9058 funcstring_end
-= SHELL_ALIGN(strlen(s
) + 1);
9059 return strcpy(funcstring_end
, s
);
9062 static union node
*copynode(union node
*);
9064 static struct nodelist
*
9065 copynodelist(struct nodelist
*lp
)
9067 struct nodelist
*start
;
9068 struct nodelist
**lpp
;
9073 funcblock
= (char *) funcblock
+ SHELL_ALIGN(sizeof(struct nodelist
));
9074 (*lpp
)->n
= copynode(lp
->n
);
9076 lpp
= &(*lpp
)->next
;
9083 copynode(union node
*n
)
9090 funcblock
= (char *) funcblock
+ nodesize
[n
->type
];
9094 new->ncmd
.redirect
= copynode(n
->ncmd
.redirect
);
9095 new->ncmd
.args
= copynode(n
->ncmd
.args
);
9096 new->ncmd
.assign
= copynode(n
->ncmd
.assign
);
9097 new->ncmd
.linno
= n
->ncmd
.linno
;
9100 new->npipe
.cmdlist
= copynodelist(n
->npipe
.cmdlist
);
9101 new->npipe
.pipe_backgnd
= n
->npipe
.pipe_backgnd
;
9106 new->nredir
.redirect
= copynode(n
->nredir
.redirect
);
9107 new->nredir
.n
= copynode(n
->nredir
.n
);
9108 new->nredir
.linno
= n
->nredir
.linno
;
9115 new->nbinary
.ch2
= copynode(n
->nbinary
.ch2
);
9116 new->nbinary
.ch1
= copynode(n
->nbinary
.ch1
);
9119 new->nif
.elsepart
= copynode(n
->nif
.elsepart
);
9120 new->nif
.ifpart
= copynode(n
->nif
.ifpart
);
9121 new->nif
.test
= copynode(n
->nif
.test
);
9124 new->nfor
.var
= nodeckstrdup(n
->nfor
.var
);
9125 new->nfor
.body
= copynode(n
->nfor
.body
);
9126 new->nfor
.args
= copynode(n
->nfor
.args
);
9127 new->nfor
.linno
= n
->nfor
.linno
;
9130 new->ncase
.cases
= copynode(n
->ncase
.cases
);
9131 new->ncase
.expr
= copynode(n
->ncase
.expr
);
9132 new->ncase
.linno
= n
->ncase
.linno
;
9135 new->nclist
.body
= copynode(n
->nclist
.body
);
9136 new->nclist
.pattern
= copynode(n
->nclist
.pattern
);
9137 new->nclist
.next
= copynode(n
->nclist
.next
);
9140 new->ndefun
.body
= copynode(n
->ndefun
.body
);
9141 new->ndefun
.text
= nodeckstrdup(n
->ndefun
.text
);
9142 new->ndefun
.linno
= n
->ndefun
.linno
;
9145 new->narg
.backquote
= copynodelist(n
->narg
.backquote
);
9146 new->narg
.text
= nodeckstrdup(n
->narg
.text
);
9147 new->narg
.next
= copynode(n
->narg
.next
);
9150 #if BASH_REDIR_OUTPUT
9157 new->nfile
.fname
= copynode(n
->nfile
.fname
);
9158 new->nfile
.fd
= n
->nfile
.fd
;
9159 new->nfile
.next
= copynode(n
->nfile
.next
);
9163 new->ndup
.vname
= copynode(n
->ndup
.vname
);
9164 new->ndup
.dupfd
= n
->ndup
.dupfd
;
9165 new->ndup
.fd
= n
->ndup
.fd
;
9166 new->ndup
.next
= copynode(n
->ndup
.next
);
9170 new->nhere
.doc
= copynode(n
->nhere
.doc
);
9171 new->nhere
.fd
= n
->nhere
.fd
;
9172 new->nhere
.next
= copynode(n
->nhere
.next
);
9175 new->nnot
.com
= copynode(n
->nnot
.com
);
9178 new->type
= n
->type
;
9183 * Make a copy of a parse tree.
9185 static struct funcnode
*
9186 copyfunc(union node
*n
)
9191 /*funcstringsize = 0;*/
9192 blocksize
= offsetof(struct funcnode
, n
) + calcsize(0, n
);
9193 f
= ckzalloc(blocksize
/* + funcstringsize */);
9194 funcblock
= (char *) f
+ offsetof(struct funcnode
, n
);
9195 funcstring_end
= (char *) f
+ blocksize
;
9197 /* f->count = 0; - ckzalloc did it */
9202 * Define a shell function.
9205 defun(union node
*func
)
9207 struct cmdentry entry
;
9210 entry
.cmdtype
= CMDFUNCTION
;
9211 entry
.u
.func
= copyfunc(func
);
9212 addcmdentry(func
->ndefun
.text
, &entry
);
9216 /* Reasons for skipping commands (see comment on breakcmd routine) */
9217 #define SKIPBREAK (1 << 0)
9218 #define SKIPCONT (1 << 1)
9219 #define SKIPFUNC (1 << 2)
9220 #define SKIPFUNCDEF (1 << 3)
9221 static smallint evalskip
; /* set to SKIPxxx if we are skipping commands */
9222 static int skipcount
; /* number of levels to skip */
9223 static int loopnest
; /* current loop nesting level */
9224 static int funcline
; /* starting line number of current function, or 0 if not in a function */
9226 /* Forward decl way out to parsing code - dotrap needs it */
9227 static int evalstring(char *s
, int flags
);
9229 /* Called to execute a trap.
9230 * Single callsite - at the end of evaltree().
9231 * If we return non-zero, evaltree raises EXEXIT exception.
9233 * Perhaps we should avoid entering new trap handlers
9234 * while we are executing a trap handler. [is it a TODO?]
9241 int status
, last_status
;
9246 status
= savestatus
;
9247 last_status
= status
;
9249 status
= exitstatus
;
9250 savestatus
= status
;
9255 TRACE(("dotrap entered\n"));
9256 for (sig
= 1, g
= gotsig
; sig
< NSIG
; sig
++, g
++) {
9268 /* non-trapped SIGINT is handled separately by raise_interrupt,
9269 * don't upset it by resetting gotsig[SIGINT-1] */
9270 if (sig
== SIGINT
&& !p
)
9273 TRACE(("sig %d is active, will run handler '%s'\n", sig
, p
));
9280 if (evalskip
!= SKIPFUNC
)
9281 exitstatus
= status
;
9284 savestatus
= last_status
;
9285 TRACE(("dotrap returns\n"));
9288 /* forward declarations - evaluation is fairly recursive business... */
9289 static int evalloop(union node
*, int);
9290 static int evalfor(union node
*, int);
9291 static int evalcase(union node
*, int);
9292 static int evalsubshell(union node
*, int);
9293 static void expredir(union node
*);
9294 static int evalpipe(union node
*, int);
9295 static int evalcommand(union node
*, int);
9296 static int evalbltin(const struct builtincmd
*, int, char **, int);
9297 static void prehash(union node
*);
9300 * Evaluate a parse tree. The value is left in the global variable
9304 evaltree(union node
*n
, int flags
)
9307 int (*evalfn
)(union node
*, int);
9308 struct stackmark smark
;
9311 setstackmark(&smark
);
9317 TRACE(("evaltree(NULL) called\n"));
9320 TRACE(("evaltree(%p: %d, %d) called\n", n
, n
->type
, flags
));
9327 out1fmt("Node type = %d\n", n
->type
);
9332 status
= !evaltree(n
->nnot
.com
, EV_TESTED
);
9335 errlinno
= lineno
= n
->nredir
.linno
;
9336 expredir(n
->nredir
.redirect
);
9337 pushredir(n
->nredir
.redirect
);
9338 status
= redirectsafe(n
->nredir
.redirect
, REDIR_PUSH
);
9340 status
= evaltree(n
->nredir
.n
, flags
& EV_TESTED
);
9342 if (n
->nredir
.redirect
)
9343 popredir(/*drop:*/ 0);
9346 evalfn
= evalcommand
;
9348 checkexit
= ~flags
& EV_TESTED
;
9359 evalfn
= evalsubshell
;
9371 #error NAND + 1 != NOR
9373 #if NOR + 1 != NSEMI
9374 #error NOR + 1 != NSEMI
9376 unsigned is_or
= n
->type
- NAND
;
9379 (flags
| ((is_or
>> 1) - 1)) & EV_TESTED
9381 if ((!status
) == is_or
|| evalskip
)
9387 status
= evalfn(n
, flags
);
9391 status
= evaltree(n
->nif
.test
, EV_TESTED
);
9397 } else if (n
->nif
.elsepart
) {
9398 n
= n
->nif
.elsepart
;
9405 /* Not necessary. To test it:
9406 * "false; f() { qwerty; }; echo $?" should print 0.
9410 exitstatus
= status
;
9414 /* Order of checks below is important:
9415 * signal handlers trigger before exit caused by "set -e".
9419 if (checkexit
&& status
) {
9420 if (trap
[NTRAP_ERR
] && !in_trap_ERR
) {
9422 struct jmploc
*volatile savehandler
= exception_handler
;
9423 struct jmploc jmploc
;
9427 err
= setjmp(jmploc
.loc
);
9429 exception_handler
= &jmploc
;
9430 savestatus
= exitstatus
;
9431 evalstring(trap
[NTRAP_ERR
], 0);
9436 exception_handler
= savehandler
;
9437 if (err
&& exception_type
!= EXERROR
)
9438 longjmp(exception_handler
->loc
, 1);
9440 exitstatus
= savestatus
;
9445 if (flags
& EV_EXIT
) {
9447 raise_exception(EXEND
); /* does not return */
9450 popstackmark(&smark
);
9451 TRACE(("leaving evaltree (no interrupts)\n"));
9458 int skip
= evalskip
;
9465 if (--skipcount
<= 0) {
9476 evalloop(union node
*n
, int flags
)
9487 i
= evaltree(n
->nbinary
.ch1
, EV_TESTED
);
9489 if (skip
== SKIPFUNC
)
9493 if (n
->type
!= NWHILE
)
9497 status
= evaltree(n
->nbinary
.ch2
, flags
);
9499 } while (!(skip
& ~SKIPCONT
));
9506 evalfor(union node
*n
, int flags
)
9508 struct arglist arglist
;
9513 errlinno
= lineno
= n
->ncase
.linno
;
9515 arglist
.list
= NULL
;
9516 arglist
.lastp
= &arglist
.list
;
9517 for (argp
= n
->nfor
.args
; argp
; argp
= argp
->narg
.next
) {
9518 expandarg(argp
, &arglist
, EXP_FULL
| EXP_TILDE
);
9520 *arglist
.lastp
= NULL
;
9524 for (sp
= arglist
.list
; sp
; sp
= sp
->next
) {
9525 setvar0(n
->nfor
.var
, sp
->text
);
9526 status
= evaltree(n
->nfor
.body
, flags
);
9527 if (skiploop() & ~SKIPCONT
)
9536 evalcase(union node
*n
, int flags
)
9540 struct arglist arglist
;
9543 errlinno
= lineno
= n
->ncase
.linno
;
9545 arglist
.list
= NULL
;
9546 arglist
.lastp
= &arglist
.list
;
9547 expandarg(n
->ncase
.expr
, &arglist
, EXP_TILDE
);
9548 for (cp
= n
->ncase
.cases
; cp
&& evalskip
== 0; cp
= cp
->nclist
.next
) {
9549 for (patp
= cp
->nclist
.pattern
; patp
; patp
= patp
->narg
.next
) {
9550 if (casematch(patp
, arglist
.list
->text
)) {
9551 /* Ensure body is non-empty as otherwise
9552 * EV_EXIT may prevent us from setting the
9555 if (evalskip
== 0 && cp
->nclist
.body
) {
9556 status
= evaltree(cp
->nclist
.body
, flags
);
9567 * Kick off a subshell to evaluate a tree.
9570 evalsubshell(union node
*n
, int flags
)
9573 int backgnd
= (n
->type
== NBACKGND
); /* FORK_BG(1) if yes, else FORK_FG(0) */
9576 errlinno
= lineno
= n
->nredir
.linno
;
9578 expredir(n
->nredir
.redirect
);
9579 if (!backgnd
&& (flags
& EV_EXIT
) && !may_have_traps
)
9582 if (backgnd
== FORK_FG
)
9584 jp
= makejob(/*n,*/ 1);
9585 if (forkshell(jp
, n
, backgnd
) == 0) {
9590 flags
&= ~EV_TESTED
;
9592 redirect(n
->nredir
.redirect
, 0);
9593 evaltreenr(n
->nredir
.n
, flags
);
9598 if (backgnd
== FORK_FG
)
9599 status
= waitforjob(jp
);
9605 * Compute the names of the files in a redirection list.
9607 static void fixredir(union node
*, const char *, int);
9609 expredir(union node
*n
)
9613 for (redir
= n
; redir
; redir
= redir
->nfile
.next
) {
9617 fn
.lastp
= &fn
.list
;
9618 switch (redir
->type
) {
9622 #if BASH_REDIR_OUTPUT
9627 expandarg(redir
->nfile
.fname
, &fn
, EXP_TILDE
| EXP_REDIR
);
9628 TRACE(("expredir expanded to '%s'\n", fn
.list
->text
));
9629 #if BASH_REDIR_OUTPUT
9633 // By the design of stack allocator, the loop of this kind:
9634 // while true; do while true; do break; done </dev/null; done
9635 // will look like a memory leak: ash plans to free expfname's
9636 // of "/dev/null" as soon as it finishes running the loop
9637 // (in this case, never).
9638 // This "fix" is wrong:
9639 if (redir
->nfile
.expfname
)
9640 stunalloc(redir
->nfile
.expfname
);
9641 // It results in corrupted state of stacked allocations.
9643 redir
->nfile
.expfname
= fn
.list
->text
;
9646 case NTOFD
: /* >& */
9647 if (redir
->ndup
.vname
) {
9648 expandarg(redir
->ndup
.vname
, &fn
, EXP_TILDE
| EXP_REDIR
);
9649 if (fn
.list
== NULL
)
9650 ash_msg_and_raise_error("redir error");
9651 #if BASH_REDIR_OUTPUT
9652 if (!isdigit_str9(fn
.list
->text
)) {
9653 /* >&file, not >&fd */
9654 if (redir
->nfile
.fd
!= 1) /* 123>&file - BAD */
9655 ash_msg_and_raise_error("redir error");
9657 goto store_expfname
;
9660 fixredir(redir
, fn
.list
->text
, 1);
9668 * Evaluate a pipeline. All the processes in the pipeline are children
9669 * of the process creating the pipeline. (This differs from some versions
9670 * of the shell, which make the last process in a pipeline the parent
9674 evalpipe(union node
*n
, int flags
)
9677 struct nodelist
*lp
;
9683 TRACE(("evalpipe(0x%lx) called\n", (long)n
));
9685 for (lp
= n
->npipe
.cmdlist
; lp
; lp
= lp
->next
)
9689 if (n
->npipe
.pipe_backgnd
== 0)
9691 jp
= makejob(/*n,*/ pipelen
);
9693 for (lp
= n
->npipe
.cmdlist
; lp
; lp
= lp
->next
) {
9697 if (pipe(pip
) < 0) {
9699 ash_msg_and_raise_perror("can't create pipe");
9702 if (forkshell(jp
, lp
->n
, n
->npipe
.pipe_backgnd
) == 0) {
9716 evaltreenr(lp
->n
, flags
);
9723 /* Don't want to trigger debugging */
9727 if (n
->npipe
.pipe_backgnd
== 0) {
9728 status
= waitforjob(jp
);
9729 TRACE(("evalpipe: job done exit status %d\n", status
));
9736 /* setinteractive needs this forward reference */
9737 #if ENABLE_FEATURE_TAB_COMPLETION
9738 static const char *ash_command_name(int i
) FAST_FUNC
;
9742 * Controls whether the shell is interactive or not.
9745 setinteractive(int on
)
9747 static smallint is_interactive
;
9749 if (++on
== is_interactive
)
9751 is_interactive
= on
;
9755 if (is_interactive
> 1) {
9756 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
9757 /* Looks like they want an interactive shell */
9758 static smallint did_banner
;
9761 /* note: ash and hush share this string */
9762 out1fmt("\n\n%s %s\n"
9763 IF_ASH_HELP("Enter 'help' for a list of built-in commands.\n")
9766 "built-in shell (ash)"
9771 #if ENABLE_FEATURE_EDITING
9772 if (!line_input_state
) {
9773 line_input_state
= new_line_input_t(FOR_SHELL
| WITH_PATH_LOOKUP
);
9774 # if ENABLE_FEATURE_TAB_COMPLETION
9775 line_input_state
->get_exe_name
= ash_command_name
;
9777 # if EDITING_HAS_sh_get_var
9778 line_input_state
->sh_get_var
= lookupvar
;
9791 setinteractive(iflag
);
9793 #if ENABLE_FEATURE_EDITING_VI
9794 if (line_input_state
) {
9796 line_input_state
->flags
|= VI_MODE
;
9798 line_input_state
->flags
&= ~VI_MODE
;
9801 viflag
= 0; /* forcibly keep the option off */
9805 struct localvar_list
{
9806 struct localvar_list
*next
;
9807 struct localvar
*lv
;
9810 static struct localvar_list
*localvar_stack
;
9813 * Called after a function returns.
9814 * Interrupts must be off.
9817 poplocalvars(int keep
)
9819 struct localvar_list
*ll
;
9820 struct localvar
*lvp
, *next
;
9824 ll
= localvar_stack
;
9825 localvar_stack
= ll
->next
;
9830 while ((lvp
= next
) != NULL
) {
9833 TRACE(("poplocalvar %s\n", vp
? vp
->var_text
: "-"));
9835 int bits
= VSTRFIXED
;
9837 if (lvp
->flags
!= VUNSET
) {
9838 if (vp
->var_text
== lvp
->text
)
9840 else if (!(lvp
->flags
& (VTEXTFIXED
|VSTACK
)))
9841 free((char*)lvp
->text
);
9845 vp
->flags
|= (lvp
->flags
& bits
);
9848 (VEXPORT
|VREADONLY
|VSTRFIXED
|VUNSET
)) == VUNSET
)
9849 unsetvar(vp
->var_text
);
9850 } else if (vp
== NULL
) { /* $- saved */
9851 memcpy(optlist
, lvp
->text
, sizeof(optlist
));
9852 free((char*)lvp
->text
);
9854 } else if (lvp
->flags
== VUNSET
) {
9855 vp
->flags
&= ~(VSTRFIXED
|VREADONLY
);
9856 unsetvar(vp
->var_text
);
9859 vp
->var_func(var_end(lvp
->text
));
9860 if ((vp
->flags
& (VTEXTFIXED
|VSTACK
)) == 0)
9861 free((char*)vp
->var_text
);
9862 vp
->flags
= lvp
->flags
;
9863 vp
->var_text
= lvp
->text
;
9871 * Create a new localvar environment.
9873 static struct localvar_list
*
9874 pushlocalvars(int push
)
9876 struct localvar_list
*ll
;
9877 struct localvar_list
*top
;
9879 top
= localvar_stack
;
9884 ll
= ckzalloc(sizeof(*ll
));
9885 /*ll->lv = NULL; - zalloc did it */
9887 localvar_stack
= ll
;
9894 unwindlocalvars(struct localvar_list
*stop
)
9896 while (localvar_stack
!= stop
)
9901 evalfun(struct funcnode
*func
, int argc
, char **argv
, int flags
)
9903 volatile struct shparam saveparam
;
9904 struct jmploc
*volatile savehandler
;
9905 struct jmploc jmploc
;
9910 char *savetrap
= NULL
;
9913 savetrap
= trap
[NTRAP_ERR
];
9914 trap
[NTRAP_ERR
] = NULL
;
9916 savelineno
= lineno
;
9917 saveparam
= shellparam
;
9918 savefuncline
= funcline
;
9919 savefuncname
= funcname
;
9920 savehandler
= exception_handler
;
9921 e
= setjmp(jmploc
.loc
);
9926 exception_handler
= &jmploc
;
9927 shellparam
.malloced
= 0;
9929 funcname
= func
->n
.ndefun
.text
;
9930 funcline
= func
->n
.ndefun
.linno
;
9932 shellparam
.nparam
= argc
- 1;
9933 shellparam
.p
= argv
+ 1;
9934 #if ENABLE_ASH_GETOPTS
9935 shellparam
.optind
= 1;
9936 shellparam
.optoff
= -1;
9938 evaltree(func
->n
.ndefun
.body
, flags
& EV_TESTED
);
9941 funcname
= savefuncname
;
9943 if (!trap
[NTRAP_ERR
])
9944 trap
[NTRAP_ERR
] = savetrap
;
9948 funcline
= savefuncline
;
9949 lineno
= savelineno
;
9951 freeparam(&shellparam
);
9952 shellparam
= saveparam
;
9953 exception_handler
= savehandler
;
9955 evalskip
&= ~(SKIPFUNC
| SKIPFUNCDEF
);
9960 * Make a variable a local variable. When a variable is made local, it's
9961 * value and flags are saved in a localvar structure. The saved values
9962 * will be restored when the shell function returns. We handle the name
9963 * "-" as a special case: it makes changes to "set +-options" local
9964 * (options will be restored on return from the function).
9967 mklocal(char *name
, int flags
)
9969 struct localvar
*lvp
;
9972 char *eq
= strchr(name
, '=');
9975 /* Cater for duplicate "local". Examples:
9976 * x=0; f() { local x=1; echo $x; local x; echo $x; }; f; echo $x
9977 * x=0; f() { local x=1; echo $x; local x=2; echo $x; }; f; echo $x
9979 lvp
= localvar_stack
->lv
;
9981 if (lvp
->vp
&& varcmp(lvp
->vp
->var_text
, name
) == 0) {
9985 * it's a duplicate "local VAR" declaration, do nothing
9992 lvp
= ckzalloc(sizeof(*lvp
));
9993 if (LONE_DASH(name
)) {
9995 p
= ckmalloc(sizeof(optlist
));
9996 lvp
->text
= memcpy(p
, optlist
, sizeof(optlist
));
9999 vpp
= hashvar(name
);
10000 vp
= *findvar(vpp
, name
);
10002 /* variable did not exist yet */
10004 vp
= setvareq(name
, VSTRFIXED
| flags
);
10006 vp
= setvar(name
, NULL
, VSTRFIXED
| flags
);
10007 lvp
->flags
= VUNSET
;
10009 lvp
->text
= vp
->var_text
;
10010 lvp
->flags
= vp
->flags
;
10011 /* make sure neither "struct var" nor string gets freed
10012 * during (un)setting:
10014 vp
->flags
|= VSTRFIXED
|VTEXTFIXED
;
10016 setvareq(name
, flags
);
10018 /* "local VAR" unsets VAR: */
10023 lvp
->next
= localvar_stack
->lv
;
10024 localvar_stack
->lv
= lvp
;
10030 * The "local" command.
10032 static int FAST_FUNC
10033 localcmd(int argc UNUSED_PARAM
, char **argv
)
10037 if (!localvar_stack
)
10038 ash_msg_and_raise_error("not in a function");
10041 while ((name
= *argv
++) != NULL
) {
10047 static int FAST_FUNC
10048 falsecmd(int argc UNUSED_PARAM
, char **argv UNUSED_PARAM
)
10053 static int FAST_FUNC
10054 truecmd(int argc UNUSED_PARAM
, char **argv UNUSED_PARAM
)
10059 static int FAST_FUNC
10060 execcmd(int argc UNUSED_PARAM
, char **argv
)
10063 while (nextopt("a:") != '\0')
10064 /* nextopt() sets optionarg to "-a ARGV0" */;
10070 iflag
= 0; /* exit on error */
10073 /* We should set up signals for "exec CMD"
10074 * the same way as for "CMD" without "exec".
10075 * But optschanged->setinteractive->setsignal
10076 * still thought we are a root shell. Therefore, for example,
10077 * SIGQUIT is still set to IGN. Fix it:
10080 setsignal(SIGQUIT
);
10081 /*setsignal(SIGTERM); - unnecessary because of iflag=0 */
10082 /*setsignal(SIGTSTP); - unnecessary because of mflag=0 */
10083 /*setsignal(SIGTTOU); - unnecessary because of mflag=0 */
10087 argv
[0] = optionarg
;
10088 shellexec(prog
, argv
, pathval(), 0);
10095 * The return command.
10097 static int FAST_FUNC
10098 returncmd(int argc UNUSED_PARAM
, char **argv
)
10104 * If called outside a function, do what ksh does;
10105 * skip the rest of the file.
10109 status
= number(argv
[1]);
10111 skip
= SKIPFUNCDEF
;
10112 status
= exitstatus
;
10119 /* Forward declarations for builtintab[] */
10120 static int breakcmd(int, char **) FAST_FUNC
;
10121 static int dotcmd(int, char **) FAST_FUNC
;
10122 static int evalcmd(int, char **, int) FAST_FUNC
;
10123 static int exitcmd(int, char **) FAST_FUNC
;
10124 static int exportcmd(int, char **) FAST_FUNC
;
10125 #if ENABLE_ASH_GETOPTS
10126 static int getoptscmd(int, char **) FAST_FUNC
;
10128 #if ENABLE_ASH_HELP
10129 static int helpcmd(int, char **) FAST_FUNC
;
10132 static int historycmd(int, char **) FAST_FUNC
;
10134 #if ENABLE_FEATURE_SH_MATH
10135 static int letcmd(int, char **) FAST_FUNC
;
10137 static int readcmd(int, char **) FAST_FUNC
;
10138 static int setcmd(int, char **) FAST_FUNC
;
10139 static int shiftcmd(int, char **) FAST_FUNC
;
10140 static int timescmd(int, char **) FAST_FUNC
;
10141 static int trapcmd(int, char **) FAST_FUNC
;
10142 static int umaskcmd(int, char **) FAST_FUNC
;
10143 static int unsetcmd(int, char **) FAST_FUNC
;
10144 static int ulimitcmd(int, char **) FAST_FUNC
;
10146 #define BUILTIN_NOSPEC "0"
10147 #define BUILTIN_SPECIAL "1"
10148 #define BUILTIN_REGULAR "2"
10149 #define BUILTIN_SPEC_REG "3"
10150 #define BUILTIN_ASSIGN "4"
10151 #define BUILTIN_SPEC_ASSG "5"
10152 #define BUILTIN_REG_ASSG "6"
10153 #define BUILTIN_SPEC_REG_ASSG "7"
10155 /* Stubs for calling non-FAST_FUNC's */
10156 #if ENABLE_ASH_ECHO
10157 static int FAST_FUNC
echocmd(int argc
, char **argv
) { return echo_main(argc
, argv
); }
10159 #if ENABLE_ASH_PRINTF
10160 static int FAST_FUNC
printfcmd(int argc
, char **argv
) { return printf_main(argc
, argv
); }
10162 #if ENABLE_ASH_TEST || BASH_TEST2
10163 static int FAST_FUNC
testcmd(int argc
, char **argv
) { return test_main(argc
, argv
); }
10165 #if ENABLE_ASH_SLEEP
10166 static int FAST_FUNC
sleepcmd(int argc
, char **argv
) { return sleep_main(argc
, argv
); }
10169 /* Keep these in proper order since it is searched via bsearch() */
10170 static const struct builtincmd builtintab
[] = {
10171 { BUILTIN_SPEC_REG
"." , dotcmd
},
10172 { BUILTIN_SPEC_REG
":" , truecmd
},
10173 #if ENABLE_ASH_TEST
10174 { BUILTIN_REGULAR
"[" , testcmd
},
10177 { BUILTIN_REGULAR
"[[" , testcmd
},
10179 #if ENABLE_ASH_ALIAS
10180 { BUILTIN_REG_ASSG
"alias" , aliascmd
},
10183 { BUILTIN_REGULAR
"bg" , fg_bgcmd
},
10185 { BUILTIN_SPEC_REG
"break" , breakcmd
},
10186 { BUILTIN_REGULAR
"cd" , cdcmd
},
10187 { BUILTIN_NOSPEC
"chdir" , cdcmd
},
10188 #if ENABLE_ASH_CMDCMD
10189 { BUILTIN_REGULAR
"command" , commandcmd
},
10191 { BUILTIN_SPEC_REG
"continue", breakcmd
},
10192 #if ENABLE_ASH_ECHO
10193 { BUILTIN_REGULAR
"echo" , echocmd
},
10195 { BUILTIN_SPEC_REG
"eval" , NULL
}, /*evalcmd() has a differing prototype*/
10196 { BUILTIN_SPEC_REG
"exec" , execcmd
},
10197 { BUILTIN_SPEC_REG
"exit" , exitcmd
},
10198 { BUILTIN_SPEC_REG_ASSG
"export" , exportcmd
},
10199 { BUILTIN_REGULAR
"false" , falsecmd
},
10201 { BUILTIN_REGULAR
"fg" , fg_bgcmd
},
10203 #if ENABLE_ASH_GETOPTS
10204 { BUILTIN_REGULAR
"getopts" , getoptscmd
},
10206 { BUILTIN_REGULAR
"hash" , hashcmd
},
10207 #if ENABLE_ASH_HELP
10208 { BUILTIN_NOSPEC
"help" , helpcmd
},
10211 { BUILTIN_NOSPEC
"history" , historycmd
},
10214 { BUILTIN_REGULAR
"jobs" , jobscmd
},
10215 { BUILTIN_REGULAR
"kill" , killcmd
},
10217 #if ENABLE_FEATURE_SH_MATH
10218 { BUILTIN_NOSPEC
"let" , letcmd
},
10220 { BUILTIN_SPEC_REG_ASSG
"local" , localcmd
},
10221 #if ENABLE_ASH_PRINTF
10222 { BUILTIN_REGULAR
"printf" , printfcmd
},
10224 { BUILTIN_REGULAR
"pwd" , pwdcmd
},
10225 { BUILTIN_REGULAR
"read" , readcmd
},
10226 { BUILTIN_SPEC_REG_ASSG
"readonly", exportcmd
},
10227 { BUILTIN_SPEC_REG
"return" , returncmd
},
10228 { BUILTIN_SPEC_REG
"set" , setcmd
},
10229 { BUILTIN_SPEC_REG
"shift" , shiftcmd
},
10230 #if ENABLE_ASH_SLEEP
10231 { BUILTIN_REGULAR
"sleep" , sleepcmd
},
10234 { BUILTIN_SPEC_REG
"source" , dotcmd
},
10236 #if ENABLE_ASH_TEST
10237 { BUILTIN_REGULAR
"test" , testcmd
},
10239 { BUILTIN_SPEC_REG
"times" , timescmd
},
10240 { BUILTIN_SPEC_REG
"trap" , trapcmd
},
10241 { BUILTIN_REGULAR
"true" , truecmd
},
10242 { BUILTIN_REGULAR
"type" , typecmd
},
10243 { BUILTIN_REGULAR
"ulimit" , ulimitcmd
},
10244 { BUILTIN_REGULAR
"umask" , umaskcmd
},
10245 #if ENABLE_ASH_ALIAS
10246 { BUILTIN_REGULAR
"unalias" , unaliascmd
},
10248 { BUILTIN_SPEC_REG
"unset" , unsetcmd
},
10249 { BUILTIN_REGULAR
"wait" , waitcmd
},
10252 /* Should match the above table! */
10253 #define COMMANDCMD (builtintab + \
10255 /* [ */ 1 * ENABLE_ASH_TEST + \
10256 /* [[ */ 1 * BASH_TEST2 + \
10257 /* alias */ 1 * ENABLE_ASH_ALIAS + \
10258 /* bg */ 1 * ENABLE_ASH_JOB_CONTROL + \
10259 /* break cd cddir */ 3)
10260 #define EVALCMD (COMMANDCMD + \
10261 /* command */ 1 * ENABLE_ASH_CMDCMD + \
10262 /* continue */ 1 + \
10263 /* echo */ 1 * ENABLE_ASH_ECHO + \
10265 #define EXECCMD (EVALCMD + \
10269 * Search the table of builtin commands.
10272 pstrcmp1(const void *a
, const void *b
)
10274 return strcmp((char*)a
, *(char**)b
+ 1);
10276 static struct builtincmd
*
10277 find_builtin(const char *name
)
10279 struct builtincmd
*bp
;
10282 name
, builtintab
, ARRAY_SIZE(builtintab
), sizeof(builtintab
[0]),
10288 #if ENABLE_FEATURE_TAB_COMPLETION
10289 static const char * FAST_FUNC
10290 ash_command_name(int i
)
10294 if (/*i >= 0 &&*/ i
< ARRAY_SIZE(builtintab
))
10295 return builtintab
[i
].name
+ 1;
10296 i
-= ARRAY_SIZE(builtintab
);
10298 for (n
= 0; n
< CMDTABLESIZE
; n
++) {
10299 struct tblentry
*cmdp
;
10300 for (cmdp
= cmdtable
[n
]; cmdp
; cmdp
= cmdp
->next
) {
10301 if (cmdp
->cmdtype
== CMDFUNCTION
&& --i
< 0)
10302 return cmdp
->cmdname
;
10306 # if ENABLE_ASH_ALIAS
10307 for (n
= 0; n
< ATABSIZE
; n
++) {
10309 for (ap
= atab
[n
]; ap
; ap
= ap
->next
) {
10321 * Execute a simple command.
10323 static void unwindfiles(struct parsefile
*stop
);
10325 isassignment(const char *p
)
10327 const char *q
= endofname(p
);
10332 static int FAST_FUNC
10333 bltincmd(int argc UNUSED_PARAM
, char **argv UNUSED_PARAM
)
10335 /* Preserve exitstatus of a previous possible redirection
10336 * as POSIX mandates */
10337 return back_exitstatus
;
10340 evalcommand(union node
*cmd
, int flags
)
10342 static const struct builtincmd null_bltin
= {
10343 BUILTIN_REGULAR
"", bltincmd
10345 struct localvar_list
*localvar_stop
;
10346 struct parsefile
*file_stop
;
10347 struct redirtab
*redir_stop
;
10349 struct arglist arglist
;
10350 struct arglist varlist
;
10353 struct strlist
*osp
;
10354 const struct strlist
*sp
;
10355 struct cmdentry cmdentry
;
10363 smallint cmd_is_exec
;
10367 errlinno
= lineno
= cmd
->ncmd
.linno
;
10369 /* First expand the arguments. */
10370 TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd
, flags
));
10371 #if BASH_PROCESS_SUBST
10372 redir_stop
= redirlist
;
10374 file_stop
= g_parsefile
;
10375 back_exitstatus
= 0;
10377 cmdentry
.cmdtype
= CMDBUILTIN
;
10378 cmdentry
.u
.cmd
= &null_bltin
;
10379 varlist
.lastp
= &varlist
.list
;
10380 *varlist
.lastp
= NULL
;
10381 arglist
.lastp
= &arglist
.list
;
10382 *arglist
.lastp
= NULL
;
10392 argp
= cmd
->ncmd
.args
;
10393 osp
= fill_arglist(&arglist
, &argp
);
10395 int pseudovarflag
= 0;
10398 find_command(arglist
.list
->text
, &cmdentry
,
10399 cmd_flag
| DO_REGBLTIN
, pathval());
10403 /* implement bltin and command here */
10404 if (cmdentry
.cmdtype
!= CMDBUILTIN
)
10407 pseudovarflag
= IS_BUILTIN_ASSIGN(cmdentry
.u
.cmd
);
10408 if (spclbltin
< 0) {
10409 spclbltin
= IS_BUILTIN_SPECIAL(cmdentry
.u
.cmd
);
10410 vlocal
= !spclbltin
;
10412 cmd_is_exec
= cmdentry
.u
.cmd
== EXECCMD
;
10413 #if ENABLE_ASH_CMDCMD
10414 if (cmdentry
.u
.cmd
!= COMMANDCMD
)
10417 cmd_flag
= parse_command_args(&arglist
, &argp
, &path
);
10423 for (; argp
; argp
= argp
->narg
.next
)
10424 expandarg(argp
, &arglist
,
10426 isassignment(argp
->narg
.text
) ?
10427 EXP_VARTILDE
: EXP_FULL
| EXP_TILDE
);
10429 for (sp
= arglist
.list
; sp
; sp
= sp
->next
)
10432 if (cmd_is_exec
&& argc
> 1)
10436 localvar_stop
= pushlocalvars(vlocal
);
10438 /* Reserve one extra spot at the front for shellexec. */
10439 nargv
= stalloc(sizeof(char *) * (argc
+ 2));
10441 for (sp
= arglist
.list
; sp
; sp
= sp
->next
) {
10442 TRACE(("evalcommand arg: %s\n", sp
->text
));
10443 *nargv
++ = sp
->text
;
10448 if (iflag
&& funcline
== 0 && argc
> 0)
10449 lastarg
= nargv
[-1];
10451 expredir(cmd
->ncmd
.redirect
);
10452 #if !BASH_PROCESS_SUBST
10453 redir_stop
= pushredir(cmd
->ncmd
.redirect
);
10455 pushredir(cmd
->ncmd
.redirect
);
10458 if (BASH_XTRACEFD
&& xflag
) {
10459 /* NB: bash closes fd == $BASH_XTRACEFD when it is changed.
10460 * we do not emulate this. We only use its value.
10462 const char *xtracefd
= lookupvar("BASH_XTRACEFD");
10463 if (xtracefd
&& is_number(xtracefd
))
10464 preverrout_fd
= atoi(xtracefd
);
10467 status
= redirectsafe(cmd
->ncmd
.redirect
, REDIR_PUSH
| REDIR_SAVEFD2
);
10471 exitstatus
= status
;
10473 /* We have a redirection error. */
10475 raise_exception(EXERROR
); /* does not return */
10480 for (argp
= cmd
->ncmd
.assign
; argp
; argp
= argp
->narg
.next
) {
10481 struct strlist
**spp
;
10483 spp
= varlist
.lastp
;
10484 expandarg(argp
, &varlist
, EXP_VARTILDE
);
10487 mklocal((*spp
)->text
, VEXPORT
);
10489 setvareq((*spp
)->text
, vflags
);
10492 /* Print the command if xflag is set. */
10493 if (xflag
&& !inps4
) {
10494 const char *pfx
= "";
10497 fdprintf(preverrout_fd
, "%s", expandstr(ps4val(), DQSYNTAX
));
10502 char *varval
= sp
->text
;
10503 char *eq
= strchrnul(varval
, '=');
10506 fdprintf(preverrout_fd
, "%s%.*s%s",
10508 (int)(eq
- varval
), varval
,
10509 maybe_single_quote(eq
)
10517 fdprintf(preverrout_fd
, "%s%s",
10519 /* always quote if matches reserved word: */
10521 ? single_quote(sp
->text
)
10522 : maybe_single_quote(sp
->text
)
10527 safe_write(preverrout_fd
, "\n", 1);
10530 /* Now locate the command. */
10531 if (cmdentry
.cmdtype
!= CMDBUILTIN
10532 || !(IS_BUILTIN_REGULAR(cmdentry
.u
.cmd
))
10534 path
= path
? path
: pathval();
10535 find_command(argv
[0], &cmdentry
, cmd_flag
| DO_ERR
, path
);
10540 /* Execute the command. */
10541 switch (cmdentry
.cmdtype
) {
10544 flush_stdout_stderr();
10549 #if ENABLE_FEATURE_SH_STANDALONE \
10550 && ENABLE_FEATURE_SH_NOFORK \
10552 /* (1) BUG: if variables are set, we need to fork, or save/restore them
10553 * around run_nofork_applet() call.
10554 * (2) Should this check also be done in forkshell()?
10555 * (perhaps it should, so that "VAR=VAL nofork" at least avoids exec...)
10557 /* find_command() encodes applet_no as (-2 - applet_no) */
10558 int applet_no
= (- cmdentry
.u
.index
- 2);
10559 if (applet_no
>= 0 && APPLET_IS_NOFORK(applet_no
)) {
10563 sv_environ
= environ
;
10564 environ
= listvars(VEXPORT
, VUNSET
, varlist
.list
, /*end:*/ NULL
);
10566 * Run <applet>_main().
10567 * Signals (^C) can't interrupt here.
10568 * Otherwise we can mangle stdio or malloc internal state.
10569 * This makes applets which can run for a long time
10570 * and/or wait for user input ineligible for NOFORK:
10571 * for example, "yes" or "rm" (rm -i waits for input).
10573 exitstatus
= run_nofork_applet(applet_no
, argv
);
10574 environ
= sv_environ
;
10576 * Try enabling NOFORK for "yes" applet.
10577 * ^C _will_ stop it (write returns EINTR),
10578 * but this causes stdout FILE to be stuck
10579 * and needing clearerr(). What if other applets
10580 * also can get EINTRs? Do we need to switch
10581 * our signals to SA_RESTART?
10583 /*clearerr(stdout);*/
10588 /* Can we avoid forking? For example, very last command
10589 * in a script or a subshell does not need forking,
10590 * we can just exec it.
10592 if (!(flags
& EV_EXIT
) || may_have_traps
) {
10593 /* No, forking off a child is necessary */
10596 jp
= makejob(/*cmd,*/ 1);
10597 if (forkshell(jp
, cmd
, FORK_FG
) != 0) {
10603 /* fall through to exec'ing external program */
10605 shellexec(argv
[0], argv
, path
, cmdentry
.u
.index
);
10609 if (evalbltin(cmdentry
.u
.cmd
, argc
, argv
, flags
)
10610 && !(exception_type
== EXERROR
&& spclbltin
<= 0)
10613 longjmp(exception_handler
->loc
, 1);
10618 if (evalfun(cmdentry
.u
.func
, argc
, argv
, flags
))
10623 status
= waitforjob(jp
);
10625 TRACE(("forked child exited with %d\n", status
));
10629 if (cmd
->ncmd
.redirect
)
10630 popredir(/*drop:*/ cmd_is_exec
);
10631 unwindredir(redir_stop
);
10632 unwindfiles(file_stop
);
10633 unwindlocalvars(localvar_stop
);
10635 /* dsl: I think this is intended to be used to support
10636 * '_' in 'vi' command mode during line editing...
10637 * However I implemented that within libedit itself.
10639 setvar0("_", lastarg
);
10646 evalbltin(const struct builtincmd
*cmd
, int argc
, char **argv
, int flags
)
10648 char *volatile savecmdname
;
10649 struct jmploc
*volatile savehandler
;
10650 struct jmploc jmploc
;
10654 savecmdname
= commandname
;
10655 savehandler
= exception_handler
;
10656 i
= setjmp(jmploc
.loc
);
10659 exception_handler
= &jmploc
;
10660 commandname
= argv
[0];
10662 optptr
= NULL
; /* initialize nextopt */
10663 if (cmd
== EVALCMD
)
10664 status
= evalcmd(argc
, argv
, flags
);
10666 status
= (*cmd
->builtin
)(argc
, argv
);
10667 flush_stdout_stderr();
10668 status
|= ferror(stdout
);
10669 exitstatus
= status
;
10672 commandname
= savecmdname
;
10673 exception_handler
= savehandler
;
10679 goodname(const char *p
)
10681 return endofname(p
)[0] == '\0';
10686 * Search for a command. This is called before we fork so that the
10687 * location of the command will be available in the parent as well as
10688 * the child. The check for "goodname" is an overly conservative
10689 * check that the name will not be subject to expansion.
10692 prehash(union node
*n
)
10694 struct cmdentry entry
;
10696 if (n
->type
== NCMD
&& n
->ncmd
.args
&& goodname(n
->ncmd
.args
->narg
.text
))
10697 find_command(n
->ncmd
.args
->narg
.text
, &entry
, 0, pathval());
10701 /* ============ Builtin commands
10703 * Builtin commands whose functions are closely tied to evaluation
10704 * are implemented here.
10708 * Handle break and continue commands. Break, continue, and return are
10709 * all handled by setting the evalskip flag. The evaluation routines
10710 * above all check this flag, and if it is set they start skipping
10711 * commands rather than executing them. The variable skipcount is
10712 * the number of loops to break/continue, or the number of function
10713 * levels to return. (The latter is always 1.) It should probably
10714 * be an error to break out of more loops than exist, but it isn't
10715 * in the standard shell so we don't make it one here.
10717 static int FAST_FUNC
10718 breakcmd(int argc UNUSED_PARAM
, char **argv
)
10720 int n
= argv
[1] ? number(argv
[1]) : 1;
10723 ash_msg_and_raise_error(msg_illnum
, argv
[1]);
10727 evalskip
= (**argv
== 'c') ? SKIPCONT
: SKIPBREAK
;
10735 * This implements the input routines used by the parser.
10739 INPUT_PUSH_FILE
= 1,
10740 INPUT_NOFILE_OK
= 2,
10743 static smallint checkkwd
;
10744 /* values of checkkwd variable */
10745 #define CHKALIAS 0x1
10748 #define CHKEOFMARK 0x8
10751 * Push a string back onto the input at this current parsefile level.
10752 * We handle aliases this way.
10754 #if !ENABLE_ASH_ALIAS
10755 #define pushstring(s, ap) pushstring(s)
10758 pushstring(char *s
, struct alias
*ap
)
10760 struct strpush
*sp
;
10765 if (g_parsefile
->strpush
|| g_parsefile
->spfree
) {
10766 sp
= ckzalloc(sizeof(*sp
));
10767 sp
->prev
= g_parsefile
->strpush
;
10769 sp
= &(g_parsefile
->basestrpush
);
10771 g_parsefile
->strpush
= sp
;
10772 sp
->prev_string
= g_parsefile
->next_to_pgetc
;
10773 sp
->prev_left_in_line
= g_parsefile
->left_in_line
;
10774 sp
->unget
= g_parsefile
->unget
;
10775 sp
->spfree
= g_parsefile
->spfree
;
10776 memcpy(sp
->lastc
, g_parsefile
->lastc
, sizeof(sp
->lastc
));
10777 #if ENABLE_ASH_ALIAS
10780 ap
->flag
|= ALIASINUSE
;
10784 g_parsefile
->next_to_pgetc
= s
;
10785 g_parsefile
->left_in_line
= len
;
10786 g_parsefile
->unget
= 0;
10787 g_parsefile
->spfree
= NULL
;
10791 static void popstring(void)
10793 struct strpush
*sp
= g_parsefile
->strpush
;
10796 #if ENABLE_ASH_ALIAS
10798 if (g_parsefile
->next_to_pgetc
[-1] == ' '
10799 || g_parsefile
->next_to_pgetc
[-1] == '\t'
10801 checkkwd
|= CHKALIAS
;
10803 if (sp
->string
!= sp
->ap
->val
) {
10808 g_parsefile
->next_to_pgetc
= sp
->prev_string
;
10809 g_parsefile
->left_in_line
= sp
->prev_left_in_line
;
10810 g_parsefile
->unget
= sp
->unget
;
10811 memcpy(g_parsefile
->lastc
, sp
->lastc
, sizeof(sp
->lastc
));
10812 g_parsefile
->strpush
= sp
->prev
;
10813 g_parsefile
->spfree
= sp
;
10821 char *buf
= g_parsefile
->buf
;
10823 g_parsefile
->next_to_pgetc
= buf
;
10824 #if ENABLE_FEATURE_EDITING
10826 if (!iflag
|| g_parsefile
->pf_fd
!= STDIN_FILENO
)
10827 nr
= nonblock_immune_read(g_parsefile
->pf_fd
, buf
, IBUFSIZ
- 1);
10829 # if ENABLE_ASH_IDLE_TIMEOUT
10831 const char *tmout_var
= lookupvar("TMOUT");
10833 timeout
= atoi(tmout_var
) * 1000;
10837 line_input_state
->timeout
= timeout
;
10839 # if ENABLE_FEATURE_TAB_COMPLETION
10840 line_input_state
->path_lookup
= pathval();
10842 reinit_unicode_for_ash();
10844 /* For shell, LI_INTERRUPTIBLE is set:
10845 * read_line_input will abort on either
10846 * getting EINTR in poll() and bb_got_signal became != 0,
10847 * or if it sees bb_got_signal != 0
10848 * (IOW: if signal arrives before poll() is reached).
10849 * Interactive testcases:
10850 * (while kill -INT $$; do sleep 1; done) &
10851 * #^^^ prints ^C, prints prompt, repeats
10852 * trap 'echo I' int; (while kill -INT $$; do sleep 1; done) &
10853 * #^^^ prints ^C, prints "I", prints prompt, repeats
10854 * trap 'echo T' term; (while kill $$; do sleep 1; done) &
10855 * #^^^ prints "T", prints prompt, repeats
10856 * #(bash 5.0.17 exits after first "T", looks like a bug)
10859 INT_OFF
; /* no longjmp'ing out of read_line_input please */
10860 nr
= read_line_input(line_input_state
, cmdedit_prompt
, buf
, IBUFSIZ
);
10861 if (bb_got_signal
== SIGINT
)
10862 write(STDOUT_FILENO
, "^C\n", 3);
10863 INT_ON
; /* here non-blocked SIGINT will longjmp */
10865 /* ^C pressed, "convert" to SIGINT */
10866 write(STDOUT_FILENO
, "^C\n", 3);
10867 raise(SIGINT
); /* here non-blocked SIGINT will longjmp */
10868 /* raise(SIGINT) did not work! (e.g. if SIGINT
10869 * is SIG_IGNed on startup, it stays SIG_IGNed)
10871 if (trap
[SIGINT
]) {
10877 exitstatus
= 128 + SIGINT
;
10878 /* bash behavior on ^C + ignored SIGINT: */
10886 else if (errno
== EINTR
) { /* got signal? */
10887 if (bb_got_signal
!= SIGINT
)
10888 write(STDOUT_FILENO
, "\n", 1);
10889 goto empty_line_input
;
10891 # if ENABLE_ASH_IDLE_TIMEOUT
10892 else if (errno
== EAGAIN
&& timeout
> 0) {
10893 puts("\007timed out waiting for input: auto-logout");
10900 nr
= nonblock_immune_read(g_parsefile
->pf_fd
, buf
, IBUFSIZ
- 1);
10903 #if 0 /* disabled: nonblock_immune_read() handles this problem */
10905 if (parsefile
->fd
== 0 && errno
== EWOULDBLOCK
) {
10906 int flags
= fcntl(0, F_GETFL
);
10907 if (flags
>= 0 && (flags
& O_NONBLOCK
)) {
10908 flags
&= ~O_NONBLOCK
;
10909 if (fcntl(0, F_SETFL
, flags
) >= 0) {
10910 out2str("sh: turning off NDELAY mode\n");
10921 * Refill the input buffer and return the next input character:
10923 * 1) If a string was pushed back on the input, pop it;
10924 * 2) If we are reading from a string we can't refill the buffer, return EOF.
10925 * 3) If there is more stuff in this buffer, use it else call read to fill it.
10926 * 4) Process input up to the next newline, deleting nul characters.
10928 //#define pgetc_debug(...) bb_error_msg(__VA_ARGS__)
10929 #define pgetc_debug(...) ((void)0)
10930 static int __pgetc(void);
10937 if (unlikely(g_parsefile
->strpush
)) {
10942 if (g_parsefile
->buf
== NULL
) {
10943 pgetc_debug("preadbuffer PEOF1");
10947 more
= g_parsefile
->left_in_buffer
;
10949 flush_stdout_stderr();
10953 g_parsefile
->left_in_buffer
= g_parsefile
->left_in_line
= 0;
10954 pgetc_debug("preadbuffer PEOF2");
10959 /* Find out where's the end of line.
10960 * Set g_parsefile->left_in_line
10961 * and g_parsefile->left_in_buffer acordingly.
10962 * NUL chars are deleted.
10964 q
= g_parsefile
->next_to_pgetc
;
10972 memmove(q
, q
+ 1, more
);
10976 g_parsefile
->left_in_line
= q
- g_parsefile
->next_to_pgetc
- 1;
10982 g_parsefile
->left_in_line
= q
- g_parsefile
->next_to_pgetc
- 1;
10983 if (g_parsefile
->left_in_line
< 0)
10988 g_parsefile
->left_in_buffer
= more
;
10993 out2str(g_parsefile
->next_to_pgetc
);
10997 pgetc_debug("preadbuffer at %d:%p'%s'",
10998 g_parsefile
->left_in_line
,
10999 g_parsefile
->next_to_pgetc
,
11000 g_parsefile
->next_to_pgetc
);
11001 return (unsigned char)*g_parsefile
->next_to_pgetc
++;
11007 if (trap_depth
== 0)
11008 g_parsefile
->linno
++;
11009 setprompt_if(doprompt
, 2);
11014 if (trap_depth
== 0)
11015 g_parsefile
->linno
++;
11016 needprompt
= doprompt
;
11019 static void freestrings(struct strpush
*sp
)
11023 struct strpush
*psp
;
11024 #if ENABLE_ASH_ALIAS
11026 sp
->ap
->flag
&= ~ALIASINUSE
;
11027 if (sp
->ap
->flag
& ALIASDEAD
) {
11028 unalias(sp
->ap
->name
);
11035 if (psp
!= &(g_parsefile
->basestrpush
))
11039 g_parsefile
->spfree
= NULL
;
11043 static int __pgetc(void)
11047 pgetc_debug("pgetc at %d:%p'%s'",
11048 g_parsefile
->left_in_line
,
11049 g_parsefile
->next_to_pgetc
,
11050 g_parsefile
->next_to_pgetc
);
11051 if (g_parsefile
->unget
)
11052 return g_parsefile
->lastc
[--g_parsefile
->unget
];
11054 if (--g_parsefile
->left_in_line
>= 0)
11055 c
= (unsigned char)*g_parsefile
->next_to_pgetc
++;
11059 g_parsefile
->lastc
[1] = g_parsefile
->lastc
[0];
11060 g_parsefile
->lastc
[0] = c
;
11066 * Read a character from the script, returning PEOF on end of file.
11067 * Nul characters in the input are silently discarded.
11069 static int pgetc(void)
11071 struct strpush
*sp
= g_parsefile
->spfree
;
11080 * Undo a call to pgetc. Only two characters may be pushed back.
11081 * PEOF may be pushed back.
11086 g_parsefile
->unget
++;
11089 /* This one eats backslash+newline */
11095 while ((c
= pgetc()) == '\\') {
11096 if (pgetc() != '\n') {
11109 uint8_t innerdq
:1;
11110 uint8_t varpushed
:1;
11111 uint8_t dblquote
:1;
11112 int varnest
; /* levels of variables expansion */
11113 int dqvarnest
; /* levels of variables expansion within double quotes */
11114 int parenlevel
; /* levels of parens in arithmetic */
11115 struct synstack
*prev
;
11116 struct synstack
*next
;
11120 pgetc_top(struct synstack
*stack
)
11122 return stack
->syntax
== SQSYNTAX
? pgetc() : pgetc_eatbnl();
11126 synstack_push(struct synstack
**stack
, struct synstack
*next
, int syntax
)
11128 memset(next
, 0, sizeof(*next
));
11129 next
->syntax
= syntax
;
11130 next
->next
= *stack
;
11131 (*stack
)->prev
= next
;
11135 static ALWAYS_INLINE
void
11136 synstack_pop(struct synstack
**stack
)
11138 *stack
= (*stack
)->next
;
11142 * To handle the "." command, a stack of input files is used. Pushfile
11143 * adds a new entry to the stack and popfile restores the previous level.
11148 struct parsefile
*pf
;
11150 pf
= ckzalloc(sizeof(*pf
));
11151 pf
->prev
= g_parsefile
;
11153 /*pf->strpush = NULL; - ckzalloc did it */
11154 /*pf->spfree = NULL;*/
11155 /*pf->basestrpush.prev = NULL;*/
11163 struct parsefile
*pf
= g_parsefile
;
11169 if (pf
->pf_fd
>= 0)
11172 if (g_parsefile
->spfree
)
11173 freestrings(g_parsefile
->spfree
);
11174 while (pf
->strpush
) {
11176 freestrings(g_parsefile
->spfree
);
11178 g_parsefile
= pf
->prev
;
11184 unwindfiles(struct parsefile
*stop
)
11186 while (g_parsefile
!= stop
)
11191 * Return to top level.
11196 unwindfiles(&basepf
);
11200 * Close the file(s) that the shell is reading commands from. Called
11201 * after a fork is done.
11207 if (g_parsefile
->pf_fd
> 0) {
11208 close(g_parsefile
->pf_fd
);
11209 g_parsefile
->pf_fd
= 0;
11214 * Like setinputfile, but takes an open file descriptor. Call this with
11218 setinputfd(int fd
, int push
)
11222 g_parsefile
->buf
= NULL
;
11224 g_parsefile
->pf_fd
= fd
;
11225 if (g_parsefile
->buf
== NULL
)
11226 g_parsefile
->buf
= ckmalloc(IBUFSIZ
);
11227 g_parsefile
->left_in_buffer
= 0;
11228 g_parsefile
->left_in_line
= 0;
11229 g_parsefile
->linno
= 1;
11233 * Set the input to take input from a file. If push is set, push the
11234 * old input onto the stack first.
11237 setinputfile(const char *fname
, int flags
)
11242 fd
= open(fname
, O_RDONLY
| O_CLOEXEC
);
11244 if (flags
& INPUT_NOFILE_OK
)
11247 ash_msg_and_raise_perror("can't open '%s'", fname
);
11251 else if (O_CLOEXEC
== 0) /* old libc */
11252 close_on_exec_on(fd
);
11254 setinputfd(fd
, flags
& INPUT_PUSH_FILE
);
11261 * Like setinputfile, but takes input from a string.
11264 setinputstring(char *string
)
11268 g_parsefile
->next_to_pgetc
= string
;
11269 g_parsefile
->left_in_line
= strlen(string
);
11270 g_parsefile
->buf
= NULL
;
11271 g_parsefile
->linno
= lineno
;
11277 * Routines to check for mail.
11280 #if ENABLE_ASH_MAIL
11282 /* Hash of mtimes of mailboxes */
11283 /* Cleared to 0 if MAIL or MAILPATH is changed */
11284 static unsigned mailtime_hash
;
11287 * Print appropriate message(s) if mail has arrived.
11288 * If mailtime_hash is zero,
11289 * then the value of MAIL has changed,
11290 * so we just update the hash value.
11299 struct stackmark smark
;
11302 setstackmark(&smark
);
11303 mpath
= mpathset() ? mpathval() : mailval();
11308 len
= padvance_magic(&mpath
, nullstr
, 2);
11314 for (q
= p
; *q
; q
++)
11320 q
[-1] = '\0'; /* delete trailing '/' */
11321 if (stat(p
, &statb
) < 0) {
11324 /* Very simplistic "hash": just a sum of all mtimes */
11325 new_hash
+= (unsigned)statb
.st_mtime
;
11327 if (mailtime_hash
!= new_hash
) {
11328 if (mailtime_hash
!= 0)
11329 out2str("you have mail\n");
11330 mailtime_hash
= new_hash
;
11332 popstackmark(&smark
);
11335 static void FAST_FUNC
11336 changemail(const char *val UNUSED_PARAM
)
11343 # define chkmail() ((void)0)
11345 #endif /* ASH_MAIL */
11348 /* ============ ??? */
11351 * Set the shell parameters.
11354 setparam(char **argv
)
11360 for (nparam
= 0; argv
[nparam
]; nparam
++)
11362 ap
= newparam
= ckmalloc((nparam
+ 1) * sizeof(*ap
));
11364 *ap
++ = ckstrdup(*argv
++);
11367 freeparam(&shellparam
);
11368 shellparam
.malloced
= 1;
11369 shellparam
.nparam
= nparam
;
11370 shellparam
.p
= newparam
;
11371 #if ENABLE_ASH_GETOPTS
11372 shellparam
.optind
= 1;
11373 shellparam
.optoff
= -1;
11378 * Process shell options. The global variable argptr contains a pointer
11379 * to the argument list; we advance it past the options.
11381 * SUSv3 section 2.8.1 "Consequences of Shell Errors" says:
11382 * For a non-interactive shell, an error condition encountered
11383 * by a special built-in ... shall cause the shell to write a diagnostic message
11384 * to standard error and exit as shown in the following table:
11385 * Error Special Built-In
11387 * Utility syntax error (option or operand error) Shall exit
11389 * However, in bug 1142 (http://busybox.net/bugs/view.php?id=1142)
11390 * we see that bash does not do that (set "finishes" with error code 1 instead,
11391 * and shell continues), and people rely on this behavior!
11393 * set -o barfoo 2>/dev/null
11396 * Oh well. Let's mimic that.
11399 plus_minus_o(char *name
, int val
)
11404 for (i
= 0; i
< NOPTS
; i
++) {
11405 if (strcmp(name
, optnames(i
)) == 0) {
11410 ash_msg("illegal option %co %s", val
? '-' : '+', name
);
11413 for (i
= 0; i
< NOPTS
; i
++) {
11414 if (optnames(i
)[0] == '\0')
11417 out1fmt("%-16s%s\n", optnames(i
), optlist
[i
] ? "on" : "off");
11419 out1fmt("set %co %s\n", optlist
[i
] ? '-' : '+', optnames(i
));
11425 setoption(int flag
, int val
)
11429 for (i
= 0; i
< NOPTS
; i
++) {
11430 if (optletters(i
) == flag
&& optnames(i
)[0] != '\0') {
11435 ash_msg_and_raise_error("illegal option %c%c", val
? '-' : '+', flag
);
11438 /* If login_sh is not NULL, we are called to parse command line opts,
11442 options(int *login_sh
)
11448 if (login_sh
!= NULL
) /* if we came from startup code */
11450 while ((p
= *argptr
) != NULL
) {
11452 if (c
!= '-' && c
!= '+')
11455 val
= 0; /* val = 0 if c == '+' */
11458 if (p
[0] == '\0' || LONE_DASH(p
)) {
11459 if (login_sh
== NULL
) { /* we came from setcmd() */
11460 /* "-" means turn off -x and -v */
11463 /* "--" means reset params */
11464 else if (*argptr
== NULL
)
11467 break; /* "-" or "--" terminates options */
11470 /* first char was + or - */
11471 while ((c
= *p
++) != '\0') {
11472 if (login_sh
!= NULL
) { /* if we came from startup code */
11473 /* bash 3.2 indeed handles -c CMD and +c CMD the same */
11475 minusc
= p
; /* command is after shell args */
11479 if (c
== 's') { /* -s, +s */
11483 if (c
== 'i') { /* -i, +i */
11488 *login_sh
= 1; /* -l or +l == --login */
11491 /* bash does not accept +-login, we also won't */
11492 if (val
&& (c
== '-')) { /* long options */
11493 if (strcmp(p
, "login") == 0) {
11496 /* TODO: --noprofile: e.g. if I want to run emergency shell from sulogin,
11497 * I want minimal/no shell init scripts - but it insists on running it as "-ash"...
11503 if (plus_minus_o(*argptr
, val
)) {
11504 /* it already printed err message */
11505 return 1; /* error */
11518 * The shift builtin command.
11520 static int FAST_FUNC
11521 shiftcmd(int argc UNUSED_PARAM
, char **argv
)
11528 n
= number(argv
[1]);
11529 if (n
> shellparam
.nparam
)
11532 shellparam
.nparam
-= n
;
11533 for (ap1
= shellparam
.p
; --n
>= 0; ap1
++) {
11534 if (shellparam
.malloced
)
11537 ap2
= shellparam
.p
;
11538 while ((*ap2
++ = *ap1
++) != NULL
)
11540 #if ENABLE_ASH_GETOPTS
11541 shellparam
.optind
= 1;
11542 shellparam
.optoff
= -1;
11549 * POSIX requires that 'set' (but not export or readonly) output the
11550 * variables in lexicographic order - by the locale's collating order (sigh).
11551 * Maybe we could keep them in an ordered balanced binary tree
11552 * instead of hashed lists.
11553 * For now just roll 'em through qsort for printing...
11556 showvars(const char *sep_prefix
, int on
, int off
)
11559 char **ep
, **epend
;
11561 ep
= listvars(on
, off
, /*strlist:*/ NULL
, &epend
);
11562 qsort(ep
, epend
- ep
, sizeof(char *), vpcmp
);
11564 sep
= *sep_prefix
? " " : sep_prefix
;
11566 for (; ep
< epend
; ep
++) {
11570 p
= endofname(*ep
);
11571 /* Used to have simple "p = strchrnul(*ep, '=')" here instead, but this
11572 * makes "export -p" to have output not suitable for "eval":
11574 * os.environ["test-test"]="test"
11575 * if os.fork() == 0:
11576 * os.execv("ash", [ 'ash', '-c', 'eval $(export -p); echo OK' ]) # fixes this
11577 * os.execv("ash", [ 'ash', '-c', 'env | grep test-test' ])
11581 q
= single_quote(++p
);
11582 out1fmt("%s%s%.*s%s\n", sep_prefix
, sep
, (int)(p
- *ep
), *ep
, q
);
11588 * The set command builtin.
11590 static int FAST_FUNC
11591 setcmd(int argc UNUSED_PARAM
, char **argv UNUSED_PARAM
)
11596 return showvars(nullstr
, 0, VUNSET
);
11599 retval
= options(/*login_sh:*/ NULL
);
11600 if (retval
== 0) { /* if no parse error... */
11602 if (*argptr
!= NULL
) {
11610 #if ENABLE_ASH_RANDOM_SUPPORT
11611 static void FAST_FUNC
11612 change_random(const char *value
)
11616 if (value
== NULL
) {
11617 /* "get", generate */
11618 t
= next_random(&random_gen
);
11619 /* set without recursion */
11620 setvar(vrandom
.var_text
, utoa(t
), VNOFUNC
);
11621 vrandom
.flags
&= ~VNOFUNC
;
11624 t
= strtoul(value
, NULL
, 10);
11625 INIT_RANDOM_T(&random_gen
, (t
? t
: 1), t
);
11630 #if BASH_EPOCH_VARS
11631 static void FAST_FUNC
11632 change_epoch(struct var
*vepoch
, const char *fmt
)
11635 char buffer
[sizeof("%llu.nnnnnn") + sizeof(long long)*3];
11637 xgettimeofday(&tv
);
11638 sprintf(buffer
, fmt
, (unsigned long long)tv
.tv_sec
, (unsigned)tv
.tv_usec
);
11639 setvar(vepoch
->var_text
, buffer
, VNOFUNC
);
11640 vepoch
->flags
&= ~VNOFUNC
;
11643 static void FAST_FUNC
11644 change_seconds(const char *value UNUSED_PARAM
)
11646 change_epoch(&vepochs
, "%llu");
11649 static void FAST_FUNC
11650 change_realtime(const char *value UNUSED_PARAM
)
11652 change_epoch(&vepochr
, "%llu.%06u");
11656 #if ENABLE_ASH_GETOPTS
11658 getopts(char *optstr
, char *optvar
, char **optfirst
)
11665 int ind
= shellparam
.optind
;
11666 int off
= shellparam
.optoff
;
11670 shellparam
.optind
= -1;
11671 optnext
= optfirst
+ ind
- 1;
11673 if (ind
<= 1 || off
< 0 || (int)strlen(optnext
[-1]) < off
)
11676 p
= optnext
[-1] + off
;
11677 if (p
== NULL
|| *p
== '\0') {
11678 /* Current word is done, advance */
11680 if (p
== NULL
|| *p
!= '-' || *++p
== '\0') {
11682 unsetvar("OPTARG");
11688 if (LONE_DASH(p
)) /* check for "--" */
11693 for (q
= optstr
; *q
!= c
;) {
11695 /* OPTERR is a bashism */
11696 const char *cp
= lookupvar("OPTERR");
11697 if ((cp
&& LONE_CHAR(cp
, '0'))
11698 || (optstr
[0] == ':')
11701 /*sbuf[1] = '\0'; - already is */
11702 setvar0("OPTARG", sbuf
);
11704 fprintf(stderr
, "Illegal option -%c\n", c
);
11705 unsetvar("OPTARG");
11715 if (*p
== '\0' && (p
= *optnext
) == NULL
) {
11716 /* OPTERR is a bashism */
11717 const char *cp
= lookupvar("OPTERR");
11718 if ((cp
&& LONE_CHAR(cp
, '0'))
11719 || (optstr
[0] == ':')
11722 /*sbuf[1] = '\0'; - already is */
11723 setvar0("OPTARG", sbuf
);
11726 fprintf(stderr
, "No arg for -%c option\n", c
);
11727 unsetvar("OPTARG");
11735 setvar0("OPTARG", p
);
11738 setvar0("OPTARG", nullstr
);
11740 ind
= optnext
- optfirst
+ 1;
11741 setvar("OPTIND", itoa(ind
), VNOFUNC
);
11743 /*sbuf[1] = '\0'; - already is */
11744 setvar0(optvar
, sbuf
);
11746 shellparam
.optoff
= p
? p
- *(optnext
- 1) : -1;
11747 shellparam
.optind
= ind
;
11753 * The getopts builtin. Shellparam.optnext points to the next argument
11754 * to be processed. Shellparam.optptr points to the next character to
11755 * be processed in the current argument. If shellparam.optnext is NULL,
11756 * then it's the first time getopts has been called.
11758 static int FAST_FUNC
11759 getoptscmd(int argc
, char **argv
)
11764 ash_msg_and_raise_error("usage: getopts optstring var [arg]");
11766 optbase
= shellparam
.p
;
11767 if ((unsigned)shellparam
.optind
> shellparam
.nparam
+ 1) {
11768 shellparam
.optind
= 1;
11769 shellparam
.optoff
= -1;
11772 optbase
= &argv
[3];
11773 if ((unsigned)shellparam
.optind
> argc
- 2) {
11774 shellparam
.optind
= 1;
11775 shellparam
.optoff
= -1;
11779 return getopts(argv
[1], argv
[2], optbase
);
11781 #endif /* ASH_GETOPTS */
11784 /* ============ Shell parser */
11787 struct heredoc
*next
; /* next here document in list */
11788 union node
*here
; /* redirection node */
11789 char *eofmark
; /* string indicating end of input */
11790 smallint striptabs
; /* if set, strip leading tabs */
11793 static smallint tokpushback
; /* last token pushed back */
11794 static smallint quoteflag
; /* set if (part of) last token was quoted */
11795 static token_id_t lasttoken
; /* last token read (integer id Txxx) */
11796 static struct heredoc
*heredoclist
; /* list of here documents to read */
11797 static char *wordtext
; /* text of last word returned by readtoken */
11798 static struct nodelist
*backquotelist
;
11799 static union node
*redirnode
;
11800 static struct heredoc
*heredoc
;
11802 static const char *
11803 tokname(char *buf
, int tok
)
11806 return tokname_array
[tok
];
11807 sprintf(buf
, "\"%s\"", tokname_array
[tok
]);
11811 /* raise_error_unexpected_syntax:
11812 * Called when an unexpected token is read during the parse. The argument
11813 * is the token that is expected, or -1 if more than one type of token can
11814 * occur at this point.
11816 static void raise_error_unexpected_syntax(int) NORETURN
;
11818 raise_error_unexpected_syntax(int token
)
11824 l
= sprintf(msg
, "unexpected %s", tokname(buf
, lasttoken
));
11826 sprintf(msg
+ l
, " (expecting %s)", tokname(buf
, token
));
11827 raise_error_syntax(msg
);
11831 /* parsing is heavily cross-recursive, need these forward decls */
11832 static union node
*andor(void);
11833 static union node
*pipeline(void);
11834 static union node
*parse_command(void);
11835 static void parseheredoc(void);
11836 static int readtoken(void);
11838 static union node
*
11841 int chknl
= nlflag
& 1 ? 0 : CHKNL
;
11842 union node
*n1
, *n2
, *n3
;
11847 checkkwd
= chknl
| CHKKWD
| CHKALIAS
;
11865 if (nlflag
== 2 && ((1 << tok
) & tokendlist
))
11871 if (tok
== TBACKGND
) {
11872 if (n2
->type
== NPIPE
) {
11873 n2
->npipe
.pipe_backgnd
= 1;
11875 if (n2
->type
!= NREDIR
) {
11876 n3
= stzalloc(sizeof(struct nredir
));
11878 /*n3->nredir.redirect = NULL; - stzalloc did it */
11881 n2
->type
= NBACKGND
;
11887 n3
= stzalloc(sizeof(struct nbinary
));
11889 n3
->nbinary
.ch1
= n1
;
11890 n3
->nbinary
.ch2
= n2
;
11904 raise_error_unexpected_syntax(-1);
11911 static union node
*
11914 union node
*n1
, *n2
, *n3
;
11922 } else if (t
== TOR
) {
11928 checkkwd
= CHKNL
| CHKKWD
| CHKALIAS
;
11930 n3
= stzalloc(sizeof(struct nbinary
));
11932 n3
->nbinary
.ch1
= n1
;
11933 n3
->nbinary
.ch2
= n2
;
11938 static union node
*
11941 union node
*n1
, *n2
, *pipenode
;
11942 struct nodelist
*lp
, *prev
;
11946 TRACE(("pipeline: entered\n"));
11947 if (readtoken() == TNOT
) {
11949 checkkwd
= CHKKWD
| CHKALIAS
;
11952 n1
= parse_command();
11953 if (readtoken() == TPIPE
) {
11954 pipenode
= stzalloc(sizeof(struct npipe
));
11955 pipenode
->type
= NPIPE
;
11956 /*pipenode->npipe.pipe_backgnd = 0; - stzalloc did it */
11957 lp
= stzalloc(sizeof(struct nodelist
));
11958 pipenode
->npipe
.cmdlist
= lp
;
11962 lp
= stzalloc(sizeof(struct nodelist
));
11963 checkkwd
= CHKNL
| CHKKWD
| CHKALIAS
;
11964 lp
->n
= parse_command();
11966 } while (readtoken() == TPIPE
);
11972 n2
= stzalloc(sizeof(struct nnot
));
11980 static union node
*
11985 n
= stzalloc(sizeof(struct narg
));
11987 /*n->narg.next = NULL; - stzalloc did it */
11988 n
->narg
.text
= wordtext
;
11989 n
->narg
.backquote
= backquotelist
;
11994 fixredir(union node
*n
, const char *text
, int err
)
11998 TRACE(("Fix redir %s %d\n", text
, err
));
12000 n
->ndup
.vname
= NULL
;
12002 fd
= bb_strtou(text
, NULL
, 10);
12003 if (!errno
&& fd
>= 0)
12004 n
->ndup
.dupfd
= fd
;
12005 else if (LONE_DASH(text
))
12006 n
->ndup
.dupfd
= -1;
12009 raise_error_syntax("bad fd number");
12010 n
->ndup
.vname
= makename();
12017 union node
*n
= redirnode
;
12019 if (n
->type
== NHERE
)
12020 checkkwd
= CHKEOFMARK
;
12021 if (readtoken() != TWORD
)
12022 raise_error_unexpected_syntax(-1);
12023 if (n
->type
== NHERE
) {
12024 struct heredoc
*here
= heredoc
;
12027 if (quoteflag
== 0)
12029 TRACE(("Here document %d\n", n
->type
));
12030 rmescapes(wordtext
, 0, NULL
);
12031 here
->eofmark
= wordtext
;
12033 if (heredoclist
== NULL
)
12034 heredoclist
= here
;
12036 for (p
= heredoclist
; p
->next
; p
= p
->next
)
12040 } else if (n
->type
== NTOFD
|| n
->type
== NFROMFD
) {
12041 fixredir(n
, wordtext
, 0);
12043 n
->nfile
.fname
= makename();
12047 static union node
*
12050 union node
*args
, **app
;
12051 union node
*n
= NULL
;
12052 union node
*vars
, **vpp
;
12053 union node
**rpp
, *redir
;
12057 smallint double_brackets_flag
= 0;
12059 IF_BASH_FUNCTION(smallint function_flag
= 0;)
12068 savecheckkwd
= CHKALIAS
;
12069 savelinno
= g_parsefile
->linno
;
12072 checkkwd
= savecheckkwd
;
12077 if (readtoken() != TWORD
)
12078 raise_error_unexpected_syntax(TWORD
);
12084 case TAND
: /* "&&" */
12085 case TOR
: /* "||" */
12086 if (!double_brackets_flag
) {
12090 /* pass "&&" or "||" to [[ ]] as literal args */
12091 wordtext
= (char *) (t
== TAND
? "&&" : "||");
12094 n
= stzalloc(sizeof(struct narg
));
12096 /*n->narg.next = NULL; - stzalloc did it */
12097 n
->narg
.text
= wordtext
;
12099 if (strcmp("[[", wordtext
) == 0)
12100 double_brackets_flag
= 1;
12101 else if (strcmp("]]", wordtext
) == 0)
12102 double_brackets_flag
= 0;
12104 n
->narg
.backquote
= backquotelist
;
12105 if (savecheckkwd
&& isassignment(wordtext
)) {
12107 vpp
= &n
->narg
.next
;
12110 app
= &n
->narg
.next
;
12114 if (function_flag
) {
12115 checkkwd
= CHKNL
| CHKKWD
;
12131 if (strcmp("[[", wordtext
) == 0)
12136 raise_error_unexpected_syntax(-1);
12142 *rpp
= n
= redirnode
;
12143 rpp
= &n
->nfile
.next
;
12144 parsefname(); /* read name of redirection file */
12147 IF_BASH_FUNCTION(do_func
:)
12148 if (args
&& app
== &args
->narg
.next
12151 // struct builtincmd *bcmd;
12152 // const char *name;
12154 /* We have a function */
12155 if (IF_BASH_FUNCTION(!function_flag
&&) readtoken() != TRP
)
12156 raise_error_unexpected_syntax(TRP
);
12157 //bash allows functions named "123", "..", "return"!
12158 // name = n->narg.text;
12159 // if (!goodname(name)
12160 // || ((bcmd = find_builtin(name)) && IS_BUILTIN_SPECIAL(bcmd))
12162 // raise_error_syntax("bad function name");
12165 checkkwd
= CHKNL
| CHKKWD
| CHKALIAS
;
12166 n
->ndefun
.text
= n
->narg
.text
;
12167 n
->ndefun
.linno
= g_parsefile
->linno
;
12168 n
->ndefun
.body
= parse_command();
12171 IF_BASH_FUNCTION(function_flag
= 0;)
12182 n
= stzalloc(sizeof(struct ncmd
));
12185 n
->ncmd
.linno
= savelinno
;
12186 n
->ncmd
.args
= args
;
12187 n
->ncmd
.assign
= vars
;
12188 n
->ncmd
.redirect
= redir
;
12192 static union node
*
12193 parse_command(void)
12195 union node
*n1
, *n2
;
12196 union node
*ap
, **app
;
12197 union node
*cp
, **cpp
;
12198 union node
*redir
, **rpp
;
12206 savelinno
= g_parsefile
->linno
;
12208 switch (readtoken()) {
12210 raise_error_unexpected_syntax(-1);
12213 n1
= stzalloc(sizeof(struct nif
));
12215 n1
->nif
.test
= list(0);
12216 if (readtoken() != TTHEN
)
12217 raise_error_unexpected_syntax(TTHEN
);
12218 n1
->nif
.ifpart
= list(0);
12220 while (readtoken() == TELIF
) {
12221 n2
->nif
.elsepart
= stzalloc(sizeof(struct nif
));
12222 n2
= n2
->nif
.elsepart
;
12224 n2
->nif
.test
= list(0);
12225 if (readtoken() != TTHEN
)
12226 raise_error_unexpected_syntax(TTHEN
);
12227 n2
->nif
.ifpart
= list(0);
12229 if (lasttoken
== TELSE
)
12230 n2
->nif
.elsepart
= list(0);
12232 n2
->nif
.elsepart
= NULL
;
12240 n1
= stzalloc(sizeof(struct nbinary
));
12241 n1
->type
= (lasttoken
== TWHILE
) ? NWHILE
: NUNTIL
;
12242 n1
->nbinary
.ch1
= list(0);
12245 TRACE(("expecting DO got '%s' %s\n", tokname_array
[got
],
12246 got
== TWORD
? wordtext
: ""));
12247 raise_error_unexpected_syntax(TDO
);
12249 n1
->nbinary
.ch2
= list(0);
12254 if (readtoken() != TWORD
|| quoteflag
|| !goodname(wordtext
))
12255 raise_error_syntax("bad for loop variable");
12256 n1
= stzalloc(sizeof(struct nfor
));
12258 n1
->nfor
.linno
= savelinno
;
12259 n1
->nfor
.var
= wordtext
;
12260 checkkwd
= CHKNL
| CHKKWD
| CHKALIAS
;
12261 if (readtoken() == TIN
) {
12263 while (readtoken() == TWORD
) {
12264 n2
= stzalloc(sizeof(struct narg
));
12266 /*n2->narg.next = NULL; - stzalloc did it */
12267 n2
->narg
.text
= wordtext
;
12268 n2
->narg
.backquote
= backquotelist
;
12270 app
= &n2
->narg
.next
;
12273 n1
->nfor
.args
= ap
;
12274 if (lasttoken
!= TNL
&& lasttoken
!= TSEMI
)
12275 raise_error_unexpected_syntax(-1);
12277 n2
= stzalloc(sizeof(struct narg
));
12279 /*n2->narg.next = NULL; - stzalloc did it */
12280 n2
->narg
.text
= (char *)dolatstr
;
12281 /*n2->narg.backquote = NULL;*/
12282 n1
->nfor
.args
= n2
;
12284 * Newline or semicolon here is optional (but note
12285 * that the original Bourne shell only allowed NL).
12287 if (lasttoken
!= TSEMI
)
12290 checkkwd
= CHKNL
| CHKKWD
| CHKALIAS
;
12291 if (readtoken() != TDO
)
12292 raise_error_unexpected_syntax(TDO
);
12293 n1
->nfor
.body
= list(0);
12297 n1
= stzalloc(sizeof(struct ncase
));
12299 n1
->ncase
.linno
= savelinno
;
12300 if (readtoken() != TWORD
)
12301 raise_error_unexpected_syntax(TWORD
);
12302 n1
->ncase
.expr
= n2
= stzalloc(sizeof(struct narg
));
12304 /*n2->narg.next = NULL; - stzalloc did it */
12305 n2
->narg
.text
= wordtext
;
12306 n2
->narg
.backquote
= backquotelist
;
12307 checkkwd
= CHKNL
| CHKKWD
| CHKALIAS
;
12308 if (readtoken() != TIN
)
12309 raise_error_unexpected_syntax(TIN
);
12310 cpp
= &n1
->ncase
.cases
;
12312 checkkwd
= CHKNL
| CHKKWD
;
12314 while (t
!= TESAC
) {
12315 if (lasttoken
== TLP
)
12317 *cpp
= cp
= stzalloc(sizeof(struct nclist
));
12319 app
= &cp
->nclist
.pattern
;
12321 *app
= ap
= stzalloc(sizeof(struct narg
));
12323 /*ap->narg.next = NULL; - stzalloc did it */
12324 ap
->narg
.text
= wordtext
;
12325 ap
->narg
.backquote
= backquotelist
;
12326 if (readtoken() != TPIPE
)
12328 app
= &ap
->narg
.next
;
12331 //ap->narg.next = NULL;
12332 if (lasttoken
!= TRP
)
12333 raise_error_unexpected_syntax(TRP
);
12334 cp
->nclist
.body
= list(2);
12336 cpp
= &cp
->nclist
.next
;
12338 checkkwd
= CHKNL
| CHKKWD
;
12342 raise_error_unexpected_syntax(TENDCASE
);
12349 n1
= stzalloc(sizeof(struct nredir
));
12350 n1
->type
= NSUBSHELL
;
12351 n1
->nredir
.linno
= savelinno
;
12352 n1
->nredir
.n
= list(0);
12353 /*n1->nredir.redirect = NULL; - stzalloc did it */
12360 IF_BASH_FUNCTION(case TFUNCTION
:)
12364 return simplecmd();
12367 if (readtoken() != t
)
12368 raise_error_unexpected_syntax(t
);
12371 /* Now check for redirection which may follow command */
12372 checkkwd
= CHKKWD
| CHKALIAS
;
12374 while (readtoken() == TREDIR
) {
12375 *rpp
= n2
= redirnode
;
12376 rpp
= &n2
->nfile
.next
;
12382 if (n1
->type
!= NSUBSHELL
) {
12383 n2
= stzalloc(sizeof(struct nredir
));
12385 n2
->nredir
.linno
= savelinno
;
12389 n1
->nredir
.redirect
= redir
;
12394 #if BASH_DOLLAR_SQUOTE
12396 decode_dollar_squote(void)
12398 static const char C_escapes
[] ALIGN1
= "nrbtfav""x\\01234567";
12404 p
= strchr(C_escapes
, c
);
12409 if ((unsigned char)(c
- '0') <= 7) { /* \ooo */
12413 } while ((unsigned char)(c
- '0') <= 7 && --cnt
);
12415 } else if (c
== 'x') { /* \xHH */
12419 } while (isxdigit(c
) && --cnt
);
12421 if (cnt
== 3) { /* \x but next char is "bad" */
12425 } else { /* simple seq like \\ or \t */
12430 c
= bb_process_escape_sequence((void*)&p
);
12431 } else { /* unrecognized "\z": print both chars unless ' or " */
12432 if (c
!= '\'' && c
!= '"') {
12434 c
|= 0x100; /* "please encode \, then me" */
12441 /* Used by expandstr to get here-doc like behaviour. */
12442 #define FAKEEOFMARK ((char*)(uintptr_t)1)
12444 static ALWAYS_INLINE
int
12445 realeofmark(const char *eofmark
)
12447 return eofmark
&& eofmark
!= FAKEEOFMARK
;
12451 * If eofmark is NULL, read a word or a redirection symbol. If eofmark
12452 * is not NULL, read a here document. In the latter case, eofmark is the
12453 * word which marks the end of the document and striptabs is true if
12454 * leading tabs should be stripped from the document. The argument c
12455 * is the first character of the input token or document.
12457 * Because C does not have internal subroutines, I have simulated them
12458 * using goto's to implement the subroutine linkage. The following macros
12459 * will run code that appears at the end of readtoken1.
12461 #define CHECKEND() {goto checkend; checkend_return:;}
12462 #define PARSEREDIR() {goto parseredir; parseredir_return:;}
12463 #define PARSESUB() {goto parsesub; parsesub_return:;}
12464 #define PARSEBACKQOLD() {style = OLD; goto parsebackq; parsebackq_oldreturn:;}
12465 #define PARSEBACKQNEW() {style = NEW; goto parsebackq; parsebackq_newreturn:;}
12466 #define PARSEPROCSUB() {style = PSUB; goto parsebackq; parsebackq_psreturn:;}
12467 #define PARSEARITH() {goto parsearith; parsearith_return:;}
12469 readtoken1(int c
, int syntax
, char *eofmark
, int striptabs
)
12471 /* NB: syntax parameter fits into smallint */
12472 /* c parameter is an unsigned char or PEOF */
12475 struct nodelist
*bqlist
;
12478 enum { OLD
, NEW
, PSUB
};
12479 #define oldstyle (style == OLD)
12480 smallint pssyntax
; /* we are expanding a prompt string */
12481 IF_BASH_DOLLAR_SQUOTE(smallint bash_dollar_squote
= 0;)
12483 struct synstack synbase
= { };
12484 struct synstack
*synstack
= &synbase
;
12486 #if ENABLE_ASH_EXPAND_PRMT
12487 pssyntax
= (syntax
== PSSYNTAX
);
12491 pssyntax
= 0; /* constant */
12493 synstack
->syntax
= syntax
;
12495 if (syntax
== DQSYNTAX
)
12496 synstack
->dblquote
= 1;
12500 STARTSTACKSTR(out
);
12502 /* For each line, until end of word */
12503 CHECKEND(); /* set c to PEOF if at end of here document */
12504 for (;;) { /* until end of line or end of word */
12505 CHECKSTRSPACE(4, out
); /* permit 4 calls to USTPUTC */
12506 switch (SIT(c
, synstack
->syntax
)) {
12507 case CNL
: /* '\n' */
12508 if (synstack
->syntax
== BASESYNTAX
12509 && !synstack
->varnest
12511 goto endword
; /* exit outer loop */
12515 c
= pgetc_top(synstack
);
12516 goto loop
; /* continue outer loop */
12521 #if BASH_DOLLAR_SQUOTE
12522 if (c
== '\\' && bash_dollar_squote
) {
12523 c
= decode_dollar_squote();
12525 /* skip $'\000', $'\x00' (like bash) */
12529 /* Unknown escape. Encode as '\z' */
12530 c
= (unsigned char)c
;
12531 if (eofmark
== NULL
|| synstack
->dblquote
)
12532 USTPUTC(CTLESC
, out
);
12533 USTPUTC('\\', out
);
12537 if (!eofmark
|| synstack
->dblquote
|| synstack
->varnest
)
12538 USTPUTC(CTLESC
, out
);
12541 case CBACK
: /* backslash */
12544 USTPUTC(CTLESC
, out
);
12545 USTPUTC('\\', out
);
12548 if (pssyntax
&& c
== '$') {
12549 USTPUTC(CTLESC
, out
);
12550 USTPUTC('\\', out
);
12552 /* Backslash is retained if we are in "str"
12553 * and next char isn't dquote-special.
12555 if (synstack
->dblquote
12559 && (c
!= '"' || (eofmark
!= NULL
&& !synstack
->varnest
))
12560 && (c
!= '}' || !synstack
->varnest
)
12562 USTPUTC(CTLESC
, out
); /* protect '\' from glob */
12563 USTPUTC('\\', out
);
12565 USTPUTC(CTLESC
, out
);
12571 synstack
->syntax
= SQSYNTAX
;
12573 if (eofmark
== NULL
) {
12574 USTPUTC(CTLQUOTEMARK
, out
);
12578 synstack
->syntax
= DQSYNTAX
;
12579 synstack
->dblquote
= 1;
12581 if (synstack
->varnest
)
12582 synstack
->innerdq
^= 1;
12585 IF_BASH_DOLLAR_SQUOTE(bash_dollar_squote
= 0;)
12586 if (eofmark
!= NULL
&& synstack
->varnest
== 0) {
12591 if (synstack
->dqvarnest
== 0) {
12592 synstack
->syntax
= BASESYNTAX
;
12593 synstack
->dblquote
= 0;
12602 case CVAR
: /* '$' */
12603 PARSESUB(); /* parse substitution */
12605 case CENDVAR
: /* '}' */
12606 if (!synstack
->innerdq
&& synstack
->varnest
> 0) {
12607 if (!--synstack
->varnest
&& synstack
->varpushed
)
12608 synstack_pop(&synstack
);
12609 else if (synstack
->dqvarnest
> 0)
12610 synstack
->dqvarnest
--;
12615 #if ENABLE_FEATURE_SH_MATH
12616 case CLP
: /* '(' in arithmetic */
12617 synstack
->parenlevel
++;
12620 case CRP
: /* ')' in arithmetic */
12621 if (synstack
->parenlevel
> 0) {
12622 synstack
->parenlevel
--;
12624 if (pgetc_eatbnl() == ')') {
12626 synstack_pop(&synstack
);
12629 * unbalanced parens
12630 * (don't 2nd guess - no error)
12638 case CBQUOTE
: /* '`' */
12639 if (checkkwd
& CHKEOFMARK
) {
12648 goto endword
; /* exit outer loop */
12650 if (synstack
->varnest
== 0) {
12651 #if BASH_REDIR_OUTPUT
12653 //Can't call pgetc_eatbnl() here, this requires three-deep pungetc()
12654 if (pgetc() == '>')
12655 c
= 0x100 + '>'; /* flag &> */
12659 #if BASH_PROCESS_SUBST
12660 if (c
== '<' || c
== '>') {
12661 if (pgetc() == '(') {
12668 goto endword
; /* exit outer loop */
12672 c
= pgetc_top(synstack
);
12676 #if ENABLE_FEATURE_SH_MATH
12677 if (synstack
->syntax
== ARISYNTAX
)
12678 raise_error_syntax("missing '))'");
12680 if (synstack
->syntax
!= BASESYNTAX
&& eofmark
== NULL
)
12681 raise_error_syntax("unterminated quoted string");
12682 if (synstack
->varnest
!= 0) {
12684 raise_error_syntax("missing '}'");
12686 USTPUTC('\0', out
);
12687 len
= out
- (char *)stackblock();
12688 out
= stackblock();
12689 if (eofmark
== NULL
) {
12690 if ((c
== '>' || c
== '<' IF_BASH_REDIR_OUTPUT( || c
== 0x100 + '>'))
12693 if (isdigit_str9(out
)) {
12694 PARSEREDIR(); /* passed as params: out, c */
12695 lasttoken
= TREDIR
;
12698 /* else: non-number X seen, interpret it
12699 * as "NNNX>file" = "NNNX >file" */
12703 quoteflag
= quotef
;
12704 backquotelist
= bqlist
;
12705 grabstackblock(len
);
12709 /* end of readtoken routine */
12712 * Check to see whether we are at the end of the here document. When this
12713 * is called, c is set to the first character of the next input line. If
12714 * we are at the end of the here document, this routine sets the c to PEOF.
12717 if (realeofmark(eofmark
)) {
12726 markloc
= out
- (char *)stackblock();
12727 for (p
= eofmark
; STPUTC(c
, out
), *p
; p
++) {
12730 /* FIXME: fails for backslash-newlined terminator:
12735 * (see heredoc_bkslash_newline2.tests)
12740 if (c
== '\n' || c
== PEOF
) {
12742 if (trap_depth
== 0)
12743 g_parsefile
->linno
++;
12744 needprompt
= doprompt
;
12749 p
= (char *)stackblock() + markloc
+ 1;
12750 len_here
= out
- p
;
12753 len_here
-= (c
>= PEOF
);
12759 str
= alloca(len_here
+ 1);
12760 *(char *)mempcpy(str
, p
, len_here
) = '\0';
12762 pushstring(str
, NULL
);
12767 STADJUST((char *)stackblock() + markloc
- out
, out
);
12769 goto checkend_return
;
12773 * Parse a redirection operator. The variable "out" points to a string
12774 * specifying the fd to be redirected. The variable "c" contains the
12775 * first character of the redirection operator.
12778 /* out is already checked to be a valid number or "" */
12779 int fd
= (*out
== '\0' ? -1 : atoi(out
));
12782 np
= stzalloc(sizeof(struct nfile
));
12785 c
= pgetc_eatbnl();
12787 np
->type
= NAPPEND
;
12789 np
->type
= NCLOBBER
;
12792 /* it also can be NTO2 (>&file), but we can't figure it out yet */
12798 #if BASH_REDIR_OUTPUT
12799 else if (c
== 0x100 + '>') { /* this flags &> redirection */
12801 pgetc(); /* this is '>', no need to check */
12805 else { /* c == '<' */
12806 /*np->nfile.fd = 0; - stzalloc did it */
12807 c
= pgetc_eatbnl();
12810 if (sizeof(struct nfile
) != sizeof(struct nhere
)) {
12811 np
= stzalloc(sizeof(struct nhere
));
12812 /*np->nfile.fd = 0; - stzalloc did it */
12815 heredoc
= stzalloc(sizeof(struct heredoc
));
12816 heredoc
->here
= np
;
12817 c
= pgetc_eatbnl();
12819 heredoc
->striptabs
= 1;
12821 /*heredoc->striptabs = 0; - stzalloc did it */
12827 np
->type
= NFROMFD
;
12831 np
->type
= NFROMTO
;
12843 goto parseredir_return
;
12847 * Parse a substitution. At this point, we have read the dollar sign
12848 * and nothing else.
12851 /* is_special(c) evaluates to 1 for c in "!#$*-0123456789?@"; 0 otherwise
12852 * (assuming ascii char codes, as the original implementation did) */
12853 #define is_special(c) \
12854 (((unsigned)(c) - 33 < 32) \
12855 && ((0xc1ff920dU >> ((unsigned)(c) - 33)) & 1))
12857 unsigned char subtype
;
12860 c
= pgetc_eatbnl();
12861 if ((checkkwd
& CHKEOFMARK
)
12862 || (c
!= '(' && c
!= '{' && !is_name(c
) && !is_special(c
))
12864 #if BASH_DOLLAR_SQUOTE
12865 if (synstack
->syntax
!= DQSYNTAX
&& c
== '\'')
12866 bash_dollar_squote
= 1;
12871 } else if (c
== '(') {
12872 /* $(command) or $((arith)) */
12873 if (pgetc_eatbnl() == '(') {
12874 #if ENABLE_FEATURE_SH_MATH
12877 raise_error_syntax("support for $((arith)) is disabled");
12884 /* $VAR, $<specialchar>, ${...}, or PEOF */
12885 smalluint newsyn
= synstack
->syntax
;
12887 USTPUTC(CTLVAR
, out
);
12888 typeloc
= out
- (char *)stackblock();
12890 subtype
= VSNORMAL
;
12892 c
= pgetc_eatbnl();
12897 /* $[{[#]]NAME[}] */
12900 c
= pgetc_eatbnl();
12901 } while (is_in_name(c
));
12902 } else if (isdigit(c
)) {
12903 /* $[{[#]]NUM[}] */
12906 c
= pgetc_eatbnl();
12907 } while ((subtype
== 0 || subtype
== VSLENGTH
) && isdigit(c
));
12908 } else if (c
!= '}') {
12909 /* $[{[#]]<specialchar>[}] */
12912 c
= pgetc_eatbnl();
12913 if (!subtype
&& cc
== '#') {
12914 subtype
= VSLENGTH
;
12915 if (c
== '_' || isalnum(c
))
12918 c
= pgetc_eatbnl();
12919 if (cc
== '}' || c
!= '}') {
12927 if (!is_special(cc
)) {
12928 if (subtype
== VSLENGTH
)
12937 if (subtype
== 0) {
12938 static const char types
[] ALIGN1
= "}-+?=";
12939 /* ${VAR...} but not $VAR or ${#VAR} */
12940 /* c == first char after VAR */
12945 c
= pgetc_eatbnl();
12947 /* This check is only needed to not misinterpret
12948 * ${VAR:-WORD}, ${VAR:+WORD}, ${VAR:=WORD}, ${VAR:?WORD}
12951 if (!strchr(types
, c
)) {
12952 subtype
= VSSUBSTR
;
12954 break; /* "goto badsub" is bigger (!) */
12960 const char *p
= strchr(types
, c
);
12963 subtype
|= p
- types
+ VSNORMAL
;
12968 subtype
= (c
== '#' ? VSTRIMLEFT
: VSTRIMRIGHT
);
12969 c
= pgetc_eatbnl();
12975 newsyn
= BASESYNTAX
;
12977 #if BASH_PATTERN_SUBST
12979 /* ${v/[/]pattern/repl} */
12980 //TODO: encode pattern and repl separately.
12981 // Currently cases like: v=1;echo ${v/$((1/1))/ONE}
12982 // are broken (should print "ONE")
12983 subtype
= VSREPLACE
;
12984 newsyn
= BASESYNTAX
;
12985 c
= pgetc_eatbnl();
12988 subtype
++; /* VSREPLACEALL */
12993 if (subtype
== VSLENGTH
&& c
!= '}')
12999 if (newsyn
== ARISYNTAX
)
13002 if ((newsyn
!= synstack
->syntax
|| synstack
->innerdq
)
13003 && subtype
!= VSNORMAL
13005 synstack_push(&synstack
,
13006 synstack
->prev
?: alloca(sizeof(*synstack
)),
13009 synstack
->varpushed
= 1;
13010 synstack
->dblquote
= newsyn
!= BASESYNTAX
;
13013 ((unsigned char *)stackblock())[typeloc
] = subtype
;
13014 if (subtype
!= VSNORMAL
) {
13015 synstack
->varnest
++;
13016 if (synstack
->dblquote
)
13017 synstack
->dqvarnest
++;
13021 goto parsesub_return
;
13025 * Called to parse command substitutions. Newstyle is set if the command
13026 * is enclosed inside $(...); nlpp is a pointer to the head of the linked
13027 * list of commands (passed by reference), and savelen is the number of
13028 * characters on the top of the stack which must be preserved.
13031 struct nodelist
**nlpp
;
13035 struct heredoc
*saveheredoclist
;
13036 smallint saveprompt
= 0;
13039 savelen
= out
- (char *)stackblock();
13042 * FIXME: this can allocate very large block on stack and SEGV.
13044 * echo "..<100kbytes>..`true` $(true) `true` ..."
13045 * allocates 100kb for every command subst. With about
13046 * a hundred command substitutions stack overflows.
13047 * With larger prepended string, SEGV happens sooner.
13049 str
= alloca(savelen
);
13050 memcpy(str
, stackblock(), savelen
);
13054 /* We must read until the closing backquote, giving special
13055 * treatment to some slashes, and then push the string and
13056 * reread it as input, interpreting it normally.
13062 STARTSTACKSTR(pout
);
13066 setprompt_if(needprompt
, 2);
13067 pc
= pgetc_eatbnl();
13073 pc
= pgetc(); /* not pgetc_eatbnl! */
13074 if (pc
!= '\\' && pc
!= '`' && pc
!= '$'
13075 && (!synstack
->dblquote
|| pc
!= '"')
13077 STPUTC('\\', pout
);
13082 raise_error_syntax("EOF in backquote substitution");
13094 STPUTC('\0', pout
);
13095 psavelen
= pout
- (char *)stackblock();
13096 if (psavelen
> 0) {
13097 pstr
= grabstackstr(pout
);
13098 setinputstring(pstr
);
13103 nlpp
= &(*nlpp
)->next
;
13104 *nlpp
= stzalloc(sizeof(**nlpp
));
13105 /* (*nlpp)->next = NULL; - stzalloc did it */
13107 saveheredoclist
= heredoclist
;
13108 heredoclist
= NULL
;
13111 saveprompt
= doprompt
;
13118 doprompt
= saveprompt
;
13120 if (readtoken() != TRP
)
13121 raise_error_unexpected_syntax(TRP
);
13122 setinputstring(nullstr
);
13126 heredoclist
= saveheredoclist
;
13129 /* Start reading from old file again. */
13131 /* Ignore any pushed back tokens left from the backquote parsing. */
13134 out
= growstackto(savelen
+ 1);
13136 memcpy(out
, str
, savelen
);
13137 STADJUST(savelen
, out
);
13139 #if BASH_PROCESS_SUBST
13141 USTPUTC(c
== '<' ? CTLFROMPROC
: CTLTOPROC
, out
);
13144 USTPUTC(CTLBACKQ
, out
);
13146 goto parsebackq_oldreturn
;
13147 #if BASH_PROCESS_SUBST
13148 else if (style
== PSUB
)
13149 goto parsebackq_psreturn
;
13151 goto parsebackq_newreturn
;
13154 #if ENABLE_FEATURE_SH_MATH
13156 * Parse an arithmetic expansion (indicate start of one and set state)
13160 synstack_push(&synstack
,
13161 synstack
->prev
?: alloca(sizeof(*synstack
)),
13163 synstack
->dblquote
= 1;
13164 USTPUTC(CTLARI
, out
);
13165 goto parsearith_return
;
13168 } /* end of readtoken */
13171 * Read the next input token.
13172 * If the token is a word, we set backquotelist to the list of cmds in
13173 * backquotes. We set quoteflag to true if any part of the word was
13175 * If the token is TREDIR, then we set redirnode to a structure containing
13178 * [Change comment: here documents and internal procedures]
13179 * [Readtoken shouldn't have any arguments. Perhaps we should make the
13180 * word parsing code into a separate routine. In this case, readtoken
13181 * doesn't need to have any internal procedures, but parseword does.
13182 * We could also make parseoperator in essence the main routine, and
13183 * have parseword (readtoken1?) handle both words and redirection.]
13185 #define NEW_xxreadtoken
13186 #ifdef NEW_xxreadtoken
13187 /* singles must be first! */
13188 static const char xxreadtoken_chars
[7] ALIGN1
= {
13189 '\n', '(', ')', /* singles */
13190 '&', '|', ';', /* doubles */
13194 #define xxreadtoken_singles 3
13195 #define xxreadtoken_doubles 3
13197 static const char xxreadtoken_tokens
[] ALIGN1
= {
13198 TNL
, TLP
, TRP
, /* only single occurrence allowed */
13199 TBACKGND
, TPIPE
, TSEMI
, /* if single occurrence */
13200 TEOF
, /* corresponds to trailing nul */
13201 TAND
, TOR
, TENDCASE
/* if double occurrence */
13213 setprompt_if(needprompt
, 2);
13214 for (;;) { /* until token or start of word found */
13215 c
= pgetc_eatbnl();
13216 if (c
== ' ' || c
== '\t')
13220 while ((c
= pgetc()) != '\n' && c
!= PEOF
)
13223 } else if (c
== '\\') {
13224 break; /* return readtoken1(...) */
13228 p
= xxreadtoken_chars
+ sizeof(xxreadtoken_chars
) - 1;
13234 p
= strchr(xxreadtoken_chars
, c
);
13236 break; /* return readtoken1(...) */
13238 if ((int)(p
- xxreadtoken_chars
) >= xxreadtoken_singles
) {
13239 int cc
= pgetc_eatbnl();
13240 if (cc
== c
) { /* double occurrence? */
13241 p
+= xxreadtoken_doubles
+ 1;
13244 #if BASH_REDIR_OUTPUT
13245 if (c
== '&' && cc
== '>') /* &> */
13246 break; /* return readtoken1(...) */
13251 lasttoken
= xxreadtoken_tokens
[p
- xxreadtoken_chars
];
13256 return readtoken1(c
, BASESYNTAX
, (char *) NULL
, 0);
13258 #else /* old xxreadtoken */
13259 #define RETURN(token) return lasttoken = token
13269 setprompt_if(needprompt
, 2);
13270 for (;;) { /* until token or start of word found */
13271 c
= pgetc_eatbnl();
13273 case ' ': case '\t':
13276 while ((c
= pgetc()) != '\n' && c
!= PEOF
)
13286 if (pgetc_eatbnl() == '&')
13291 if (pgetc_eatbnl() == '|')
13296 if (pgetc_eatbnl() == ';')
13307 return readtoken1(c
, BASESYNTAX
, (char *)NULL
, 0);
13310 #endif /* old xxreadtoken */
13316 int kwd
= checkkwd
;
13318 smallint alreadyseen
= tokpushback
;
13321 #if ENABLE_ASH_ALIAS
13341 if (t
!= TWORD
|| quoteflag
) {
13346 * check for keywords
13348 if (kwd
& CHKKWD
) {
13349 const char *const *pp
;
13351 pp
= findkwd(wordtext
);
13353 lasttoken
= t
= pp
- tokname_array
;
13354 TRACE(("keyword '%s' recognized\n", tokname_array
[t
]));
13359 if (kwd
& CHKALIAS
) {
13360 #if ENABLE_ASH_ALIAS
13362 ap
= lookupalias(wordtext
, 1);
13365 pushstring(ap
->val
, ap
);
13374 TRACE(("token '%s' %s\n", tokname_array
[t
], t
== TWORD
? wordtext
: ""));
13376 TRACE(("reread token '%s' %s\n", tokname_array
[t
], t
== TWORD
? wordtext
: ""));
13382 * Read and parse a command. Returns NODE_EOF on end of file.
13383 * (NULL is a valid parse tree indicating a blank line.)
13385 static union node
*
13386 parsecmd(int interact
)
13391 doprompt
= interact
;
13392 setprompt_if(doprompt
, doprompt
);
13398 * Input any here documents.
13403 struct heredoc
*here
;
13406 here
= heredoclist
;
13407 heredoclist
= NULL
;
13411 setprompt_if(needprompt
, 2);
13412 if (here
->here
->type
== NHERE
)
13413 readtoken1(pgetc(), SQSYNTAX
, here
->eofmark
, here
->striptabs
);
13415 readtoken1(pgetc_eatbnl(), DQSYNTAX
, here
->eofmark
, here
->striptabs
);
13416 n
= stzalloc(sizeof(struct narg
));
13417 n
->narg
.type
= NARG
;
13418 /*n->narg.next = NULL; - stzalloc did it */
13419 n
->narg
.text
= wordtext
;
13420 n
->narg
.backquote
= backquotelist
;
13421 here
->here
->nhere
.doc
= n
;
13427 static const char *
13428 expandstr(const char *ps
, int syntax_type
)
13430 struct parsefile
*file_stop
;
13431 struct jmploc
*volatile savehandler
;
13432 struct heredoc
*saveheredoclist
;
13433 const char *result
;
13435 struct jmploc jmploc
;
13439 file_stop
= g_parsefile
;
13441 /* XXX Fix (char *) cast. */
13442 setinputstring((char *)ps
);
13444 saveheredoclist
= heredoclist
;
13445 heredoclist
= NULL
;
13446 saveprompt
= doprompt
;
13449 savehandler
= exception_handler
;
13450 err
= setjmp(jmploc
.loc
);
13454 /* readtoken1() might die horribly.
13455 * Try a prompt with syntactically wrong command:
13456 * PS1='$(date "+%H:%M:%S) > '
13458 exception_handler
= &jmploc
;
13459 readtoken1(pgetc_eatbnl(), syntax_type
, FAKEEOFMARK
, 0);
13461 n
.narg
.type
= NARG
;
13462 n
.narg
.next
= NULL
;
13463 n
.narg
.text
= wordtext
;
13464 n
.narg
.backquote
= backquotelist
;
13466 /* expandarg() might fail too:
13469 expandarg(&n
, NULL
, EXP_QUOTED
);
13470 result
= stackblock();
13473 exception_handler
= savehandler
;
13474 if (err
&& exception_type
!= EXERROR
)
13475 longjmp(exception_handler
->loc
, 1);
13477 doprompt
= saveprompt
;
13478 /* Try: PS1='`xxx(`' */
13479 unwindfiles(file_stop
);
13480 heredoclist
= saveheredoclist
;
13488 return tokpushback
&& lasttoken
== TEOF
;
13492 * Execute a command or commands contained in a string.
13495 evalstring(char *s
, int flags
)
13497 struct jmploc
*volatile savehandler
;
13498 struct jmploc jmploc
;
13502 struct stackmark smark
;
13507 setstackmark(&smark
);
13510 /* On exception inside execution loop, we must popfile().
13511 * Try interactively:
13513 * command eval "a=b" # throws "is read only" error
13514 * "command BLTIN" is not supposed to abort (even in non-interactive use).
13515 * But if we skip popfile(), we hit EOF in eval's string, and exit.
13517 savehandler
= exception_handler
;
13518 ex
= setjmp(jmploc
.loc
);
13521 exception_handler
= &jmploc
;
13523 while ((n
= parsecmd(0)) != NODE_EOF
) {
13526 i
= evaltree(n
, flags
& ~(parser_eof() ? 0 : EV_EXIT
));
13529 popstackmark(&smark
);
13534 popstackmark(&smark
);
13538 exception_handler
= savehandler
;
13540 longjmp(exception_handler
->loc
, ex
);
13546 * The eval command.
13548 static int FAST_FUNC
13549 evalcmd(int argc UNUSED_PARAM
, char **argv
, int flags
)
13558 STARTSTACKSTR(concat
);
13560 concat
= stack_putstr(p
, concat
);
13564 STPUTC(' ', concat
);
13566 STPUTC('\0', concat
);
13567 p
= grabstackstr(concat
);
13569 return evalstring(p
, flags
& EV_TESTED
);
13575 * Read and execute commands.
13576 * "Top" is nonzero for the top level command loop;
13577 * it turns on prompting if the shell is interactive.
13583 struct stackmark smark
;
13588 TRACE(("cmdloop(%d) called\n", top
));
13592 setstackmark(&smark
);
13595 showjobs(SHOW_CHANGED
|SHOW_STDERR
);
13598 if (iflag
&& top
) {
13602 n
= parsecmd(inter
);
13604 if (DEBUG
> 2 && debug
&& (n
!= NODE_EOF
))
13607 if (n
== NODE_EOF
) {
13608 if (!top
|| numeof
>= 50)
13610 if (!stoppedjobs()) {
13614 newline_and_flush(stderr
);
13617 /* "set -o ignoreeof" active, do not exit command loop on ^D */
13618 out2str("\nUse \"exit\" to leave shell.\n");
13624 /* job_warning can only be 2,1,0. Here 2->1, 1/0->0 */
13627 i
= evaltree(n
, 0);
13631 popstackmark(&smark
);
13635 evalskip
&= ~(SKIPFUNC
| SKIPFUNCDEF
);
13643 * Take commands from a file. To be compatible we should do a path
13644 * search for the file, which is necessary to find sub-commands.
13647 find_dot_file(char *basename
)
13654 /* don't try this for absolute or relative paths */
13655 if (strchr(basename
, '/'))
13659 while ((len
= padvance(&path
, basename
)) >= 0) {
13660 fullname
= stackblock();
13661 if ((!pathopt
|| *pathopt
== 'f')
13662 && !stat(fullname
, &statb
) && S_ISREG(statb
.st_mode
)
13664 /* This will be freed by the caller. */
13665 return stalloc(len
);
13668 /* not found in PATH */
13670 #if ENABLE_ASH_BASH_SOURCE_CURDIR
13673 ash_msg_and_raise_error("%s: not found", basename
);
13678 static int FAST_FUNC
13679 dotcmd(int argc_ UNUSED_PARAM
, char **argv_ UNUSED_PARAM
)
13681 /* "false; . empty_file; echo $?" should print 0, not 1: */
13685 char *args_need_save
;
13686 volatile struct shparam saveparam
;
13689 // struct strlist *sp;
13690 // for (sp = cmdenviron; sp; sp = sp->next)
13691 // setvareq(ckstrdup(sp->text), VSTRFIXED | VTEXTFIXED);
13693 nextopt(nullstr
); /* handle possible "--" */
13697 /* bash says: "bash: .: filename argument required" */
13698 return 2; /* bash compat */
13701 /* This aborts if file isn't found, which is POSIXly correct.
13702 * bash returns exitcode 1 instead.
13704 fullname
= find_dot_file(argv
[0]);
13706 args_need_save
= argv
[0];
13707 if (args_need_save
) { /* ". FILE ARGS", and ARGS are not empty */
13709 saveparam
= shellparam
;
13710 shellparam
.malloced
= 0;
13714 shellparam
.nparam
= argc
;
13715 shellparam
.p
= argv
;
13718 /* This aborts if file can't be opened, which is POSIXly correct.
13719 * bash returns exitcode 1 instead.
13721 setinputfile(fullname
, INPUT_PUSH_FILE
);
13722 commandname
= fullname
;
13723 status
= cmdloop(0);
13726 if (args_need_save
) {
13727 freeparam(&shellparam
);
13728 shellparam
= saveparam
;
13734 static int FAST_FUNC
13735 exitcmd(int argc UNUSED_PARAM
, char **argv
)
13741 savestatus
= number(argv
[1]);
13743 //TODO: this script
13744 // trap 'echo trap:$FUNCNAME' EXIT
13747 //prints "trap:f" in bash. We can call exitshell() here to achieve this.
13748 //For now, keeping dash code:
13749 raise_exception(EXEXIT
);
13754 * Read a file containing shell functions.
13757 readcmdfile(char *name
)
13759 setinputfile(name
, INPUT_PUSH_FILE
);
13765 /* ============ find_command inplementation */
13768 * Resolve a command name. If you change this routine, you may have to
13769 * change the shellexec routine as well.
13772 find_command(char *name
, struct cmdentry
*entry
, int act
, const char *path
)
13774 struct tblentry
*cmdp
;
13781 struct builtincmd
*bcmd
;
13784 /* If name contains a slash, don't use PATH or hash table */
13785 if (strchr(name
, '/') != NULL
) {
13786 entry
->u
.index
= -1;
13787 if (act
& DO_ABS
) {
13788 while (stat(name
, &statb
) < 0) {
13790 if (errno
== EINTR
)
13793 entry
->cmdtype
= CMDUNKNOWN
;
13797 entry
->cmdtype
= CMDNORMAL
;
13801 /* #if ENABLE_FEATURE_SH_STANDALONE... moved after builtin check */
13803 updatetbl
= (path
== pathval());
13807 /* If name is in the table, check answer will be ok */
13808 cmdp
= cmdlookup(name
, 0);
13809 if (cmdp
!= NULL
) {
13812 switch (cmdp
->cmdtype
) {
13818 bit
= DO_ALTPATH
| DO_REGBLTIN
;
13824 bit
= IS_BUILTIN_REGULAR(cmdp
->param
.cmd
) ? 0 : DO_REGBLTIN
;
13828 if (act
& bit
& DO_REGBLTIN
)
13833 } else if (cmdp
->rehash
== 0)
13834 /* if not invalidated by cd, we're done */
13838 /* If %builtin not in path, check for builtin next */
13839 bcmd
= find_builtin(name
);
13841 if (IS_BUILTIN_REGULAR(bcmd
))
13842 goto builtin_success
;
13843 if (act
& DO_ALTPATH
)
13844 goto builtin_success
;
13845 if (builtinloc
<= 0)
13846 goto builtin_success
;
13849 if (act
& DO_REGBLTIN
)
13852 #if ENABLE_FEATURE_SH_STANDALONE
13854 int applet_no
= find_applet_by_name(name
);
13855 if (applet_no
>= 0) {
13856 entry
->cmdtype
= CMDNORMAL
;
13857 entry
->u
.index
= -2 - applet_no
;
13863 /* We have to search path. */
13864 prev
= -1; /* where to start */
13865 if (cmdp
&& cmdp
->rehash
) { /* doing a rehash */
13866 if (cmdp
->cmdtype
== CMDBUILTIN
)
13869 prev
= cmdp
->param
.index
;
13875 while ((len
= padvance(&path
, name
)) >= 0) {
13876 const char *lpathopt
= pathopt
;
13878 fullname
= stackblock();
13881 if (*lpathopt
== 'b') {
13883 goto builtin_success
;
13885 } else if (!(act
& DO_NOFUNC
)) {
13886 /* handled below */
13888 /* ignore unimplemented options */
13892 /* if rehash, don't redo absolute path names */
13893 if (fullname
[0] == '/' && idx
<= prev
) {
13896 TRACE(("searchexec \"%s\": no change\n", name
));
13899 while (stat(fullname
, &statb
) < 0) {
13901 if (errno
== EINTR
)
13904 if (errno
!= ENOENT
&& errno
!= ENOTDIR
)
13908 e
= EACCES
; /* if we fail, this will be the error */
13909 if (!S_ISREG(statb
.st_mode
))
13911 if (lpathopt
) { /* this is a %func directory */
13913 /* NB: stalloc will return space pointed by fullname
13914 * (because we don't have any intervening allocations
13915 * between stunalloc above and this stalloc) */
13916 readcmdfile(fullname
);
13917 cmdp
= cmdlookup(name
, 0);
13918 if (cmdp
== NULL
|| cmdp
->cmdtype
!= CMDFUNCTION
)
13919 ash_msg_and_raise_error("%s not defined in %s", name
, fullname
);
13920 stunalloc(fullname
);
13923 TRACE(("searchexec \"%s\" returns \"%s\"\n", name
, fullname
));
13925 entry
->cmdtype
= CMDNORMAL
;
13926 entry
->u
.index
= idx
;
13930 cmdp
= cmdlookup(name
, 1);
13931 cmdp
->cmdtype
= CMDNORMAL
;
13932 cmdp
->param
.index
= idx
;
13937 /* We failed. If there was an entry for this command, delete it */
13938 if (cmdp
&& updatetbl
)
13939 delete_cmd_entry();
13940 if (act
& DO_ERR
) {
13941 #if ENABLE_ASH_BASH_NOT_FOUND_HOOK
13942 struct tblentry
*hookp
= cmdlookup("command_not_found_handle", 0);
13943 if (hookp
&& hookp
->cmdtype
== CMDFUNCTION
) {
13945 argv
[0] = (char*) "command_not_found_handle";
13948 evalfun(hookp
->param
.func
, 2, argv
, 0);
13949 entry
->cmdtype
= CMDUNKNOWN
;
13953 ash_msg("%s: %s", name
, errmsg(e
, "not found"));
13956 entry
->cmdtype
= CMDUNKNOWN
;
13961 entry
->cmdtype
= CMDBUILTIN
;
13962 entry
->u
.cmd
= bcmd
;
13966 cmdp
= cmdlookup(name
, 1);
13967 cmdp
->cmdtype
= CMDBUILTIN
;
13968 cmdp
->param
.cmd
= bcmd
;
13972 entry
->cmdtype
= cmdp
->cmdtype
;
13973 entry
->u
= cmdp
->param
;
13978 * The trap builtin.
13980 static int FAST_FUNC
13981 trapcmd(int argc UNUSED_PARAM
, char **argv UNUSED_PARAM
)
13985 int signo
, exitcode
;
13990 for (signo
= 0; signo
<= NTRAP_LAST
; signo
++) {
13991 char *tr
= trap_ptr
[signo
];
13993 /* note: bash adds "SIG", but only if invoked
13994 * as "bash". If called as "sh", or if set -o posix,
13995 * then it prints short signal names.
13996 * We are printing short names: */
13997 out1fmt("trap -- %s %s\n",
13999 (signo
== NTRAP_ERR
) ? "ERR" : get_signame(signo
));
14000 /* trap_ptr != trap only if we are in special-cased `trap` code.
14001 * In this case, we will exit very soon, no need to free(). */
14002 /* if (trap_ptr != trap && tp[0]) */
14007 if (trap_ptr != trap) {
14015 /* Why the second check?
14016 * "trap NUM [sig2]..." is the same as "trap - NUM [sig2]..."
14017 * In this case, NUM is signal no, not an action.
14020 if (ap
[1] && !is_number(ap
[0]))
14025 signo
= strcmp(*ap
, "ERR") == 0 ? NTRAP_ERR
: get_signum(*ap
);
14027 /* Mimic bash message exactly */
14028 ash_msg("%s: invalid signal specification", *ap
);
14034 if (LONE_DASH(action
))
14037 if (action
[0]) /* not NULL and not "" and not "-" */
14038 may_have_traps
= 1;
14039 action
= ckstrdup(action
);
14043 trap
[signo
] = action
;
14044 if (signo
!= 0 && signo
< NSIG
)
14054 /* ============ Builtins */
14056 #if ENABLE_ASH_HELP
14057 static int FAST_FUNC
14058 helpcmd(int argc UNUSED_PARAM
, char **argv UNUSED_PARAM
)
14064 "Built-in commands:\n"
14065 "------------------\n");
14066 for (col
= 0, i
= 0; i
< ARRAY_SIZE(builtintab
); i
++) {
14067 col
+= out1fmt("%c%s", ((col
== 0) ? '\t' : ' '),
14068 builtintab
[i
].name
+ 1);
14074 # if ENABLE_FEATURE_SH_STANDALONE
14076 const char *a
= applet_names
;
14078 col
+= out1fmt("%c%s", ((col
== 0) ? '\t' : ' '), a
);
14083 while (*a
++ != '\0')
14088 newline_and_flush(stdout
);
14089 return EXIT_SUCCESS
;
14094 static int FAST_FUNC
14095 historycmd(int argc UNUSED_PARAM
, char **argv UNUSED_PARAM
)
14097 show_history(line_input_state
);
14098 return EXIT_SUCCESS
;
14103 * The export and readonly commands.
14105 static int FAST_FUNC
14106 exportcmd(int argc UNUSED_PARAM
, char **argv
)
14116 /* "readonly" in bash accepts, but ignores -n.
14117 * We do the same: it saves a conditional in nextopt's param.
14120 while ((opt
= nextopt("np")) != '\0') {
14122 flag_off
= VEXPORT
;
14125 if (argv
[0][0] == 'r') {
14127 flag_off
= 0; /* readonly ignores -n */
14129 flag_off
= ~flag_off
;
14131 /*if (opt_p_not_specified) - bash doesn't check this. Try "export -p NAME" */
14137 p
= strchr(name
, '=');
14141 vp
= *findvar(hashvar(name
), name
);
14143 vp
->flags
= ((vp
->flags
| flag
) & flag_off
);
14147 setvar(name
, p
, (flag
& flag_off
));
14148 } while ((name
= *++aptr
) != NULL
);
14153 /* No arguments. Show the list of exported or readonly vars.
14156 showvars(argv
[0], flag
, 0);
14161 * Delete a function if it exists.
14164 unsetfunc(const char *name
)
14166 struct tblentry
*cmdp
;
14168 cmdp
= cmdlookup(name
, 0);
14169 if (cmdp
!= NULL
&& cmdp
->cmdtype
== CMDFUNCTION
)
14170 delete_cmd_entry();
14174 * The unset builtin command. We unset the function before we unset the
14175 * variable to allow a function to be unset when there is a readonly variable
14176 * with the same name.
14178 static int FAST_FUNC
14179 unsetcmd(int argc UNUSED_PARAM
, char **argv UNUSED_PARAM
)
14185 while ((i
= nextopt("vf")) != 0) {
14189 for (ap
= argptr
; *ap
; ap
++) {
14200 static const unsigned char timescmd_str
[] ALIGN1
= {
14201 ' ', offsetof(struct tms
, tms_utime
),
14202 '\n', offsetof(struct tms
, tms_stime
),
14203 ' ', offsetof(struct tms
, tms_cutime
),
14204 '\n', offsetof(struct tms
, tms_cstime
),
14207 static int FAST_FUNC
14208 timescmd(int argc UNUSED_PARAM
, char **argv UNUSED_PARAM
)
14211 const unsigned char *p
;
14214 clk_tck
= bb_clk_tck();
14219 unsigned sec
, frac
;
14221 t
= *(clock_t *)(((char *) &buf
) + p
[1]);
14223 frac
= t
% clk_tck
;
14224 out1fmt("%um%u.%03us%c",
14225 sec
/ 60, sec
% 60,
14226 (frac
* 1000) / clk_tck
,
14234 #if ENABLE_FEATURE_SH_MATH
14236 * The let builtin. Partially stolen from GNU Bash, the Bourne Again SHell.
14237 * Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
14239 * Copyright (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
14241 static int FAST_FUNC
14242 letcmd(int argc UNUSED_PARAM
, char **argv
)
14248 ash_msg_and_raise_error("expression expected");
14250 i
= ash_arith(*argv
);
14258 * The read builtin. Options:
14259 * -r Do not interpret '\' specially
14260 * -s Turn off echo (tty only)
14261 * -n NCHARS Read NCHARS max
14262 * -p PROMPT Display PROMPT on stderr (if input is from tty)
14263 * -t SECONDS Timeout after SECONDS (tty or pipe only)
14264 * -u FD Read from given FD instead of fd 0
14265 * -d DELIM End on DELIM char, not newline
14266 * This uses unbuffered input, which may be avoidable in some cases.
14267 * TODO: bash also has:
14268 * -a ARRAY Read into array[0],[1],etc
14269 * -e Use line editing (tty only)
14271 static int FAST_FUNC
14272 readcmd(int argc UNUSED_PARAM
, char **argv UNUSED_PARAM
)
14274 struct builtin_read_params params
;
14278 memset(¶ms
, 0, sizeof(params
));
14280 while ((i
= nextopt("p:u:rt:n:sd:")) != '\0') {
14283 params
.opt_p
= optionarg
;
14286 params
.opt_n
= optionarg
;
14289 params
.read_flags
|= BUILTIN_READ_SILENT
;
14292 params
.opt_t
= optionarg
;
14295 params
.read_flags
|= BUILTIN_READ_RAW
;
14298 params
.opt_u
= optionarg
;
14302 params
.opt_d
= optionarg
;
14310 if (!ENABLE_ASH_BASH_COMPAT
&& !argptr
) {
14311 bb_simple_error_msg("read: need variable name");
14314 params
.argv
= argptr
;
14315 params
.setvar
= setvar0
;
14316 params
.ifs
= bltinlookup("IFS"); /* can be NULL */
14318 /* "read -s" needs to save/restore termios, can't allow ^C
14319 * to jump out of it.
14323 r
= shell_builtin_read(¶ms
);
14326 if ((uintptr_t)r
== 1 && errno
== EINTR
) {
14327 /* To get SIGCHLD: sleep 1 & read x; echo $x
14328 * Correct behavior is to not exit "read"
14330 if (pending_sig
== 0)
14334 if ((uintptr_t)r
> 1)
14335 ash_msg_and_raise_error(r
);
14337 return (uintptr_t)r
;
14340 static int FAST_FUNC
14341 umaskcmd(int argc UNUSED_PARAM
, char **argv UNUSED_PARAM
)
14343 static const char permuser
[3] ALIGN1
= "ogu";
14346 int symbolic_mode
= 0;
14348 while (nextopt("S") != '\0') {
14357 if (*argptr
== NULL
) {
14358 if (symbolic_mode
) {
14359 char buf
[sizeof(",u=rwx,g=rwx,o=rwx")];
14366 *p
++ = permuser
[i
];
14368 /* mask is 0..0uuugggooo. i=2 selects uuu bits */
14369 if (!(mask
& 0400)) *p
++ = 'r';
14370 if (!(mask
& 0200)) *p
++ = 'w';
14371 if (!(mask
& 0100)) *p
++ = 'x';
14379 out1fmt("%04o\n", mask
);
14382 char *modestr
= *argptr
;
14383 /* numeric umasks are taken as-is */
14384 /* symbolic umasks are inverted: "umask a=rx" calls umask(222) */
14385 if (!isdigit(modestr
[0]))
14387 mask
= bb_parse_mode(modestr
, mask
);
14388 if ((unsigned)mask
> 0777) {
14389 ash_msg_and_raise_error("illegal mode: %s", modestr
);
14391 if (!isdigit(modestr
[0]))
14398 static int FAST_FUNC
14399 ulimitcmd(int argc UNUSED_PARAM
, char **argv
)
14401 return shell_builtin_ulimit(argv
);
14404 /* ============ main() and helpers */
14407 * This routine is called when an error or an interrupt occurs in an
14408 * interactive shell and control is returned to the main command loop
14409 * but prior to exitshell.
14415 if (savestatus
>= 0) {
14416 if (exception_type
== EXEXIT
|| evalskip
== SKIPFUNCDEF
)
14417 exitstatus
= savestatus
;
14424 /* from expand.c: */
14427 /* from redir.c: */
14432 * This routine is called when an error or an interrupt occurs in an
14433 * interactive shell and control is returned to the main command loop.
14434 * (In dash, this function is auto-generated by build machinery).
14439 /* from input.c: */
14440 g_parsefile
->left_in_buffer
= 0;
14441 g_parsefile
->left_in_line
= 0; /* clear input buffer */
14442 g_parsefile
->unget
= 0;
14446 unwindlocalvars(NULL
);
14450 * Called to exit the shell.
14458 #if ENABLE_FEATURE_EDITING_SAVE_ON_EXIT
14459 save_history(line_input_state
); /* may be NULL */
14461 savestatus
= exitstatus
;
14462 TRACE(("pid %d, exitshell(%d)\n", getpid(), savestatus
));
14463 if (setjmp(loc
.loc
))
14465 exception_handler
= &loc
;
14473 evalskip
= SKIPFUNCDEF
;
14474 /*free(p); - we'll exit soon */
14478 /* dash wraps setjobctl(0) in "if (setjmp(loc.loc) == 0) {...}".
14479 * our setjobctl(0) does not panic if tcsetpgrp fails inside it.
14482 flush_stdout_stderr();
14487 /* Don't inline: conserve stack of caller from having our locals too */
14488 static NOINLINE
void
14491 /* we will never free this */
14492 basepf
.next_to_pgetc
= basepf
.buf
= ckzalloc(IBUFSIZ
);
14495 sigmode
[SIGCHLD
- 1] = S_DFL
; /* ensure we install handler even if it is SIG_IGNed */
14496 setsignal(SIGCHLD
);
14503 for (envp
= environ
; envp
&& *envp
; envp
++) {
14505 * p = endofname(*envp);
14506 * if (p != *envp && *p == '=') {
14507 * here to weed out badly-named variables, but this breaks
14508 * scenarios where people do want them passed to children:
14510 * os.environ["test-test"]="test"
14511 * if os.fork() == 0:
14512 * os.execv("ash", [ 'ash', '-c', 'eval $(export -p); echo OK' ]) # fixes this
14513 * os.execv("ash", [ 'ash', '-c', 'env | grep test-test' ]) # breaks this
14515 if (strchr(*envp
, '=')) {
14516 setvareq(*envp
, VEXPORT
|VTEXTFIXED
);
14520 setvareq((char*)defifsvar
, VTEXTFIXED
);
14521 setvareq((char*)defoptindvar
, VTEXTFIXED
);
14523 setvar0("PPID", utoa(getppid()));
14525 p
= lookupvar("SHLVL");
14526 setvar("SHLVL", utoa((p
? atoi(p
) : 0) + 1), VEXPORT
);
14528 #if BASH_HOSTNAME_VAR
14529 if (!lookupvar("HOSTNAME")) {
14530 struct utsname uts
;
14532 setvar0("HOSTNAME", uts
.nodename
);
14535 p
= lookupvar("PWD");
14537 struct stat st1
, st2
;
14538 if (p
[0] != '/' || stat(p
, &st1
) || stat(".", &st2
)
14539 || st1
.st_dev
!= st2
.st_dev
|| st1
.st_ino
!= st2
.st_ino
14549 //usage:#define ash_trivial_usage
14550 //usage: "[-il] [-|+Cabefmnuvx] [-|+o OPT]... [-c 'SCRIPT' [ARG0 ARGS] | FILE ARGS | -s ARGS]"
14551 //////// comes from ^^^^^^^^^^optletters
14552 //usage:#define ash_full_usage "\n\n"
14553 //usage: "Unix shell interpreter"
14556 * Process the shell command line arguments.
14559 procargs(char **argv
)
14562 const char *xminusc
;
14567 login_sh
= xargv
[0] && xargv
[0][0] == '-';
14568 #if NUM_SCRIPTS > 0
14573 /* if (xargv[0]) - mmm, this is always true! */
14576 for (i
= 0; i
< NOPTS
; i
++)
14578 if (options(&login_sh
)) {
14579 /* it already printed err message */
14580 raise_exception(EXERROR
); /* does not return */
14584 if (*xargv
== NULL
) {
14586 ash_msg_and_raise_error(bb_msg_requires_arg
, "-c");
14589 if (iflag
== 2 /* no explicit -i given */
14590 && sflag
== 1 /* -s given (or implied) */
14591 && !minusc
/* bash compat: ash -sc 'echo $-' is not interactive (dash is) */
14592 && isatty(0) && isatty(1) /* we are on tty */
14598 /* Unset options which weren't explicitly set or unset */
14599 for (i
= 0; i
< NOPTS
; i
++)
14600 optlist
[i
] &= 1; /* same effect as "if (optlist[i] == 2) optlist[i] = 0;" */
14604 /* POSIX 1003.2: first arg after "-c CMD" is $0, remainder $1... */
14609 } else if (!sflag
) {
14610 setinputfile(*xargv
, 0);
14613 commandname
= arg0
;
14616 shellparam
.p
= xargv
;
14617 #if ENABLE_ASH_GETOPTS
14618 shellparam
.optind
= 1;
14619 shellparam
.optoff
= -1;
14621 /* assert(shellparam.malloced == 0 && shellparam.nparam == 0); */
14623 shellparam
.nparam
++;
14627 /* Interactive bash re-enables SIGHUP which is SIG_IGNed on entry.
14629 * trap '' hup; bash; echo RET # type "kill -hup $$", see SIGHUP having effect
14630 * trap '' hup; bash -c 'kill -hup $$; echo ALIVE' # here SIGHUP is SIG_IGNed
14631 * NB: must do it before setting up signals (in optschanged())
14632 * and reading .profile etc (after we return from here):
14635 signal(SIGHUP
, SIG_DFL
);
14643 * Read /etc/profile, ~/.profile, $ENV.
14646 read_profile(const char *name
)
14648 name
= expandstr(name
, DQSYNTAX
);
14649 if (setinputfile(name
, INPUT_PUSH_FILE
| INPUT_NOFILE_OK
) < 0)
14656 static short profile_buf
[16384];
14657 extern int etext();
14661 * Main routine. We initialize things, parse the arguments, execute
14662 * profiles if we're a login shell, and then call cmdloop to execute
14663 * commands. The setjmp call sets up the location to jump to when an
14664 * exception occurs. When an exception occurs the variable "state"
14665 * is used to figure out how far we had gotten.
14667 int ash_main(int argc
, char **argv
) MAIN_EXTERNALLY_VISIBLE
;
14668 #if NUM_SCRIPTS > 0
14669 int ash_main(int argc
, char **argv
)
14671 int ash_main(int argc UNUSED_PARAM
, char **argv
)
14673 /* note: 'argc' is used only if embedded scripts are enabled */
14675 volatile smallint state
;
14676 struct jmploc jmploc
;
14677 struct stackmark smark
;
14680 /* Initialize global data */
14684 #if ENABLE_ASH_ALIAS
14690 monitor(4, etext
, profile_buf
, sizeof(profile_buf
), 50);
14694 if (setjmp(jmploc
.loc
)) {
14700 e
= exception_type
;
14702 if (e
== EXEND
|| e
== EXEXIT
|| s
== 0 || iflag
== 0 || shlvl
) {
14709 newline_and_flush(stderr
);
14712 popstackmark(&smark
);
14713 FORCE_INT_ON
; /* enable interrupts */
14722 exception_handler
= &jmploc
;
14723 rootpid
= getpid();
14726 setstackmark(&smark
);
14728 #if NUM_SCRIPTS > 0
14730 /* Non-NULL minusc tells procargs that an embedded script is being run */
14731 minusc
= get_script_content(-argc
- 1);
14733 login_sh
= procargs(argv
);
14735 TRACE(("Shell args: "));
14736 trace_puts_args(argv
);
14743 read_profile("/etc/profile");
14746 hp
= lookupvar("HOME");
14748 read_profile("$HOME/.profile");
14754 && getuid() == geteuid() && getgid() == getegid()
14757 const char *shinit
= lookupvar("ENV");
14758 if (shinit
!= NULL
&& *shinit
!= '\0')
14759 read_profile(shinit
);
14761 popstackmark(&smark
);
14765 /* evalstring pushes parsefile stack.
14766 * Ensure we don't falsely claim that 0 (stdin)
14767 * is one of stacked source fds.
14768 * Testcase: ash -c 'exec 1>&0' must not complain. */
14770 // if (!sflag) g_parsefile->pf_fd = -1;
14771 // ^^ not necessary since now we special-case fd 0
14772 // in save_fd_on_redirect()
14774 lineno
= 0; // bash compat
14775 // dash: evalstring(minusc, sflag ? 0 : EV_EXIT);
14777 // ash -sc 'echo $-'
14778 // continue reading input from stdin after running 'echo'.
14779 // bash does not do this: it prints "hBcs" and exits.
14780 evalstring(minusc
, EV_EXIT
);
14783 if (sflag
|| minusc
== NULL
) {
14784 #if MAX_HISTORY > 0 && ENABLE_FEATURE_EDITING_SAVEHISTORY
14785 if (line_input_state
) {
14786 const char *hp
= lookupvar("HISTFILE");
14788 hp
= lookupvar("HOME");
14791 hp
= concat_path_file(hp
, ".ash_history");
14792 setvar0("HISTFILE", hp
);
14795 hp
= lookupvar("HISTFILE");
14799 line_input_state
->hist_file
= xstrdup(hp
);
14800 # if ENABLE_FEATURE_SH_HISTFILESIZE
14801 hp
= lookupvar("HISTFILESIZE");
14802 line_input_state
->max_history
= size_from_HISTFILESIZE(hp
);
14806 state4
: /* XXX ??? - why isn't this before the "if" statement */
14814 extern void _mcleanup(void);
14818 TRACE(("End of main reached\n"));
14825 * Copyright (c) 1989, 1991, 1993, 1994
14826 * The Regents of the University of California. All rights reserved.
14828 * This code is derived from software contributed to Berkeley by
14829 * Kenneth Almquist.
14831 * Redistribution and use in source and binary forms, with or without
14832 * modification, are permitted provided that the following conditions
14834 * 1. Redistributions of source code must retain the above copyright
14835 * notice, this list of conditions and the following disclaimer.
14836 * 2. Redistributions in binary form must reproduce the above copyright
14837 * notice, this list of conditions and the following disclaimer in the
14838 * documentation and/or other materials provided with the distribution.
14839 * 3. Neither the name of the University nor the names of its contributors
14840 * may be used to endorse or promote products derived from this software
14841 * without specific prior written permission.
14843 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND
14844 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
14845 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
14846 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
14847 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
14848 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
14849 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
14850 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
14851 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
14852 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF