summaryrefslogtreecommitdiff
path: root/shell/hush.c
diff options
context:
space:
mode:
Diffstat (limited to 'shell/hush.c')
-rw-r--r--shell/hush.c58
1 files changed, 37 insertions, 21 deletions
diff --git a/shell/hush.c b/shell/hush.c
index 9b15efb30..8baccf246 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -39,25 +39,28 @@
39 * 39 *
40 * POSIX syntax not implemented: 40 * POSIX syntax not implemented:
41 * aliases 41 * aliases
42 * <(list) and >(list) Process Substitution
43 * Tilde Expansion 42 * Tilde Expansion
44 * 43 *
45 * Bash stuff (optionally enabled): 44 * Bash compat TODO:
46 * &> and >& redirection of stdout+stderr 45 * redirection of stdout+stderr: &> and >&
47 * Brace Expansion 46 * brace expansion: one/{two,three,four}
48 * reserved words: [[ ]] function select 47 * reserved words: function select
49 * substrings ${var:1:5} 48 * advanced test: [[ ]]
49 * substrings: ${var:1:5}
50 * process substitution: <(list) and >(list)
51 * =~: regex operator
50 * let EXPR [EXPR...] 52 * let EXPR [EXPR...]
51 * Each EXPR is an arithmetic expression (ARITHMETIC EVALUATION) 53 * Each EXPR is an arithmetic expression (ARITHMETIC EVALUATION)
52 * If the last arg evaluates to 0, let returns 1; 0 otherwise. 54 * If the last arg evaluates to 0, let returns 1; 0 otherwise.
53 * NB: let `echo 'a=a + 1'` - error (IOW: multi-word expansion is used) 55 * NB: let `echo 'a=a + 1'` - error (IOW: multi-word expansion is used)
54 * ((EXPR)) 56 * ((EXPR))
55 * The EXPR is evaluated according to ARITHMETIC EVALUATION. 57 * The EXPR is evaluated according to ARITHMETIC EVALUATION.
56 * This is exactly equivalent to let "expression". 58 * This is exactly equivalent to let "EXPR".
59 * $[EXPR]: synonym for $((EXPR))
57 * 60 *
58 * TODOs: 61 * TODOs:
59 * grep for "TODO" and fix (some of them are easy) 62 * grep for "TODO" and fix (some of them are easy)
60 * special variables (done: PWD) 63 * special variables (done: PWD, PPID, RANDOM)
61 * follow IFS rules more precisely, including update semantics 64 * follow IFS rules more precisely, including update semantics
62 * export builtin should be special, its arguments are assignments 65 * export builtin should be special, its arguments are assignments
63 * and therefore expansion of them should be "one-word" expansion: 66 * and therefore expansion of them should be "one-word" expansion:
@@ -673,6 +676,9 @@ static const struct built_in_command bltins1[] = {
673#endif 676#endif
674 BLTIN("set" , builtin_set , "Set/unset positional parameters"), 677 BLTIN("set" , builtin_set , "Set/unset positional parameters"),
675 BLTIN("shift" , builtin_shift , "Shift positional parameters"), 678 BLTIN("shift" , builtin_shift , "Shift positional parameters"),
679#if ENABLE_HUSH_BASH_COMPAT
680 BLTIN("source" , builtin_source , "Run commands in a file"),
681#endif
676 BLTIN("trap" , builtin_trap , "Trap signals"), 682 BLTIN("trap" , builtin_trap , "Trap signals"),
677 BLTIN("type" , builtin_type , "Show command type"), 683 BLTIN("type" , builtin_type , "Show command type"),
678 BLTIN("ulimit" , shell_builtin_ulimit , "Control resource limits"), 684 BLTIN("ulimit" , shell_builtin_ulimit , "Control resource limits"),
@@ -6232,10 +6238,15 @@ static struct pipe *parse_stream(char **pstring,
6232 is_special = "{}<>;&|()#'" /* special outside of "str" */ 6238 is_special = "{}<>;&|()#'" /* special outside of "str" */
6233 "\\$\"" IF_HUSH_TICK("`"); /* always special */ 6239 "\\$\"" IF_HUSH_TICK("`"); /* always special */
6234 /* Are { and } special here? */ 6240 /* Are { and } special here? */
6235 if (ctx.command->argv /* word [word]{... */ 6241 if (ctx.command->argv /* word [word]{... - non-special */
6236 || dest.length /* word{... */ 6242 || dest.length /* word{... - non-special */
6237 || dest.o_quoted /* ""{... */ 6243 || dest.o_quoted /* ""{... - non-special */
6238 || (next != ';' && next != ')' && !strchr(G.ifs, next)) /* {word */ 6244 || (next != ';' /* }; - special */
6245 && next != ')' /* }) - special */
6246 && next != '&' /* }& and }&& ... - special */
6247 && next != '|' /* }|| ... - special */
6248 && !strchr(G.ifs, next) /* {word - non-special */
6249 )
6239 ) { 6250 ) {
6240 /* They are not special, skip "{}" */ 6251 /* They are not special, skip "{}" */
6241 is_special += 2; 6252 is_special += 2;
@@ -7859,21 +7870,26 @@ static int FAST_FUNC builtin_shift(char **argv)
7859 7870
7860static int FAST_FUNC builtin_source(char **argv) 7871static int FAST_FUNC builtin_source(char **argv)
7861{ 7872{
7862 char *arg_path; 7873 char *arg_path, *filename;
7863 FILE *input; 7874 FILE *input;
7864 save_arg_t sv; 7875 save_arg_t sv;
7865#if ENABLE_HUSH_FUNCTIONS 7876#if ENABLE_HUSH_FUNCTIONS
7866 smallint sv_flg; 7877 smallint sv_flg;
7867#endif 7878#endif
7868 7879
7869 if (*++argv == NULL) 7880 arg_path = NULL;
7870 return EXIT_FAILURE; 7881 filename = *++argv;
7871 7882 if (!filename) {
7872 if (strchr(*argv, '/') == NULL && (arg_path = find_in_path(*argv)) != NULL) { 7883 /* bash says: "bash: .: filename argument required" */
7873 input = fopen_for_read(arg_path); 7884 return 2; /* bash compat */
7874 free(arg_path); 7885 }
7875 } else 7886 if (!strchr(filename, '/')) {
7876 input = fopen_or_warn(*argv, "r"); 7887 arg_path = find_in_path(filename);
7888 if (arg_path)
7889 filename = arg_path;
7890 }
7891 input = fopen_or_warn(filename, "r");
7892 free(arg_path);
7877 if (!input) { 7893 if (!input) {
7878 /* bb_perror_msg("%s", *argv); - done by fopen_or_warn */ 7894 /* bb_perror_msg("%s", *argv); - done by fopen_or_warn */
7879 return EXIT_FAILURE; 7895 return EXIT_FAILURE;