diff options
author | andersen <andersen@69ca8d6d-28ef-0310-b511-8ec308f3f277> | 2001-05-15 16:30:25 +0000 |
---|---|---|
committer | andersen <andersen@69ca8d6d-28ef-0310-b511-8ec308f3f277> | 2001-05-15 16:30:25 +0000 |
commit | b45349e24eca0dfc36dce437fa62d57a0a76d529 (patch) | |
tree | 0976bdb774d95a758d27dbeab282c979ba3cee4c /shell | |
parent | c74efb2e987da5ddd74112a71287f54008bf35b2 (diff) | |
download | busybox-w32-b45349e24eca0dfc36dce437fa62d57a0a76d529.tar.gz busybox-w32-b45349e24eca0dfc36dce437fa62d57a0a76d529.tar.bz2 busybox-w32-b45349e24eca0dfc36dce437fa62d57a0a76d529.zip |
This patch covers one big part of variable handling.
$ a=b foo
should be handled correctly.
$ a=b
is parsed OK, but the actual variable setting is not
yet written. Except for some weird exceptions related
to quoting rules, this code passes (matches ash behavior)
all the tests I threw at it.
If someone now writes set_local_var(), and updates lookup_param()
to match, we can claim success!
- Larry
git-svn-id: svn://busybox.net/trunk/busybox@2644 69ca8d6d-28ef-0310-b511-8ec308f3f277
Diffstat (limited to 'shell')
-rw-r--r-- | shell/hush.c | 54 |
1 files changed, 49 insertions, 5 deletions
diff --git a/shell/hush.c b/shell/hush.c index 5ea946066..9f1614d1f 100644 --- a/shell/hush.c +++ b/shell/hush.c | |||
@@ -43,6 +43,7 @@ | |||
43 | * Brace Expansion | 43 | * Brace Expansion |
44 | * Tilde Expansion | 44 | * Tilde Expansion |
45 | * fancy forms of Parameter Expansion | 45 | * fancy forms of Parameter Expansion |
46 | * aliases | ||
46 | * Arithmetic Expansion | 47 | * Arithmetic Expansion |
47 | * <(list) and >(list) Process Substitution | 48 | * <(list) and >(list) Process Substitution |
48 | * reserved words: case, esac, select, function | 49 | * reserved words: case, esac, select, function |
@@ -54,15 +55,14 @@ | |||
54 | * to-do: | 55 | * to-do: |
55 | * port selected bugfixes from post-0.49 busybox lash - done? | 56 | * port selected bugfixes from post-0.49 busybox lash - done? |
56 | * finish implementing reserved words: for, while, until, do, done | 57 | * finish implementing reserved words: for, while, until, do, done |
58 | * finish implementing local variable assignment | ||
57 | * change { and } from special chars to reserved words | 59 | * change { and } from special chars to reserved words |
58 | * builtins: break, continue, eval, return, set, trap, ulimit | 60 | * builtins: break, continue, eval, return, set, trap, ulimit |
59 | * test magic exec | 61 | * test magic exec |
60 | * handle children going into background | 62 | * handle children going into background |
61 | * clean up recognition of null pipes | 63 | * clean up recognition of null pipes |
62 | * have builtin_exec set flag to avoid restore_redirects | ||
63 | * check setting of global_argc and global_argv | 64 | * check setting of global_argc and global_argv |
64 | * control-C handling, probably with longjmp | 65 | * control-C handling, probably with longjmp |
65 | * VAR=value prefix for simple commands | ||
66 | * follow IFS rules more precisely, including update semantics | 66 | * follow IFS rules more precisely, including update semantics |
67 | * figure out what to do with backslash-newline | 67 | * figure out what to do with backslash-newline |
68 | * explain why we use signal instead of sigaction | 68 | * explain why we use signal instead of sigaction |
@@ -70,6 +70,7 @@ | |||
70 | * continuation lines, both explicit and implicit - done? | 70 | * continuation lines, both explicit and implicit - done? |
71 | * memory leak finding and plugging - done? | 71 | * memory leak finding and plugging - done? |
72 | * more testing, especially quoting rules and redirection | 72 | * more testing, especially quoting rules and redirection |
73 | * document how quoting rules not precisely followed for variable assignments | ||
73 | * maybe change map[] to use 2-bit entries | 74 | * maybe change map[] to use 2-bit entries |
74 | * (eventually) remove all the printf's | 75 | * (eventually) remove all the printf's |
75 | * | 76 | * |
@@ -359,6 +360,9 @@ static int run_pipe_real(struct pipe *pi); | |||
359 | static int globhack(const char *src, int flags, glob_t *pglob); | 360 | static int globhack(const char *src, int flags, glob_t *pglob); |
360 | static int glob_needed(const char *s); | 361 | static int glob_needed(const char *s); |
361 | static int xglob(o_string *dest, int flags, glob_t *pglob); | 362 | static int xglob(o_string *dest, int flags, glob_t *pglob); |
363 | /* variable assignment: */ | ||
364 | static int set_local_var(const char *s); | ||
365 | static int is_assignment(const char *s); | ||
362 | /* data structure manipulation: */ | 366 | /* data structure manipulation: */ |
363 | static int setup_redirect(struct p_context *ctx, int fd, redir_type style, struct in_str *input); | 367 | static int setup_redirect(struct p_context *ctx, int fd, redir_type style, struct in_str *input); |
364 | static void initialize_context(struct p_context *ctx); | 368 | static void initialize_context(struct p_context *ctx); |
@@ -1001,9 +1005,20 @@ static int pipe_wait(struct pipe *pi) | |||
1001 | /* very simple version for testing */ | 1005 | /* very simple version for testing */ |
1002 | static void pseudo_exec(struct child_prog *child) | 1006 | static void pseudo_exec(struct child_prog *child) |
1003 | { | 1007 | { |
1004 | int rcode; | 1008 | int i, rcode; |
1005 | struct built_in_command *x; | 1009 | struct built_in_command *x; |
1006 | if (child->argv) { | 1010 | if (child->argv) { |
1011 | for (i=0; is_assignment(child->argv[i]); i++) { | ||
1012 | putenv(strdup(child->argv[i])); | ||
1013 | } | ||
1014 | child->argv+=i; /* XXX this hack isn't so horrible, since we are about | ||
1015 | to exit, and therefore don't need to keep data | ||
1016 | structures consistent for free() use. */ | ||
1017 | /* If a variable is assigned in a forest, and nobody listens, | ||
1018 | * was it ever really set? | ||
1019 | */ | ||
1020 | if (child->argv[0] == NULL) exit(EXIT_SUCCESS); | ||
1021 | |||
1007 | /* | 1022 | /* |
1008 | * Check if the command matches any of the builtins. | 1023 | * Check if the command matches any of the builtins. |
1009 | * Depending on context, this might be redundant. But it's | 1024 | * Depending on context, this might be redundant. But it's |
@@ -1253,11 +1268,19 @@ static int run_pipe_real(struct pipe *pi) | |||
1253 | restore_redirects(squirrel); | 1268 | restore_redirects(squirrel); |
1254 | return rcode; | 1269 | return rcode; |
1255 | } | 1270 | } |
1271 | for (i=0; is_assignment(child->argv[i]); i++) { /* nothing */ } | ||
1272 | if (i!=0 && child->argv[i]==NULL) { | ||
1273 | /* assignments, but no command: set the local environment */ | ||
1274 | for (i=0; child->argv[i]!=NULL; i++) { | ||
1275 | set_local_var(child->argv[i]); | ||
1276 | } | ||
1277 | return EXIT_SUCCESS; /* don't worry about errors in set_local_var() yet */ | ||
1278 | } | ||
1256 | for (x = bltins; x->cmd; x++) { | 1279 | for (x = bltins; x->cmd; x++) { |
1257 | if (strcmp(child->argv[0], x->cmd) == 0 ) { | 1280 | if (strcmp(child->argv[i], x->cmd) == 0 ) { |
1258 | int squirrel[] = {-1, -1, -1}; | 1281 | int squirrel[] = {-1, -1, -1}; |
1259 | int rcode; | 1282 | int rcode; |
1260 | if (x->function == builtin_exec && child->argv[1]==NULL) { | 1283 | if (x->function == builtin_exec && child->argv[i+1]==NULL) { |
1261 | debug_printf("magic exec\n"); | 1284 | debug_printf("magic exec\n"); |
1262 | setup_redirects(child,NULL); | 1285 | setup_redirects(child,NULL); |
1263 | return EXIT_SUCCESS; | 1286 | return EXIT_SUCCESS; |
@@ -1268,7 +1291,12 @@ static int run_pipe_real(struct pipe *pi) | |||
1268 | * Is it really safe for inline use? Experimentally, | 1291 | * Is it really safe for inline use? Experimentally, |
1269 | * things seem to work with glibc. */ | 1292 | * things seem to work with glibc. */ |
1270 | setup_redirects(child, squirrel); | 1293 | setup_redirects(child, squirrel); |
1294 | for (i=0; is_assignment(child->argv[i]); i++) { | ||
1295 | putenv(strdup(child->argv[i])); | ||
1296 | } | ||
1297 | child->argv+=i; /* XXX horrible hack */ | ||
1271 | rcode = x->function(child); | 1298 | rcode = x->function(child); |
1299 | child->argv-=i; /* XXX restore hack so free() can work right */ | ||
1272 | restore_redirects(squirrel); | 1300 | restore_redirects(squirrel); |
1273 | return rcode; | 1301 | return rcode; |
1274 | } | 1302 | } |
@@ -1581,6 +1609,22 @@ static int xglob(o_string *dest, int flags, glob_t *pglob) | |||
1581 | return gr; | 1609 | return gr; |
1582 | } | 1610 | } |
1583 | 1611 | ||
1612 | |||
1613 | static int set_local_var(const char *s) | ||
1614 | { | ||
1615 | /* when you write this, also need to update lookup_param() */ | ||
1616 | printf("assignment %s not handled: write me!\n",s); | ||
1617 | return 0; | ||
1618 | } | ||
1619 | |||
1620 | static int is_assignment(const char *s) | ||
1621 | { | ||
1622 | if (s==NULL || !isalpha(*s)) return 0; | ||
1623 | ++s; | ||
1624 | while(isalnum(*s) || *s=='_') ++s; | ||
1625 | return *s=='='; | ||
1626 | } | ||
1627 | |||
1584 | /* the src parameter allows us to peek forward to a possible &n syntax | 1628 | /* the src parameter allows us to peek forward to a possible &n syntax |
1585 | * for file descriptor duplication, e.g., "2>&1". | 1629 | * for file descriptor duplication, e.g., "2>&1". |
1586 | * Return code is 0 normally, 1 if a syntax error is detected in src. | 1630 | * Return code is 0 normally, 1 if a syntax error is detected in src. |