aboutsummaryrefslogtreecommitdiff
path: root/shell
diff options
context:
space:
mode:
authorandersen <andersen@69ca8d6d-28ef-0310-b511-8ec308f3f277>2001-05-15 16:30:25 +0000
committerandersen <andersen@69ca8d6d-28ef-0310-b511-8ec308f3f277>2001-05-15 16:30:25 +0000
commitb45349e24eca0dfc36dce437fa62d57a0a76d529 (patch)
tree0976bdb774d95a758d27dbeab282c979ba3cee4c /shell
parentc74efb2e987da5ddd74112a71287f54008bf35b2 (diff)
downloadbusybox-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.c54
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);
359static int globhack(const char *src, int flags, glob_t *pglob); 360static int globhack(const char *src, int flags, glob_t *pglob);
360static int glob_needed(const char *s); 361static int glob_needed(const char *s);
361static int xglob(o_string *dest, int flags, glob_t *pglob); 362static int xglob(o_string *dest, int flags, glob_t *pglob);
363/* variable assignment: */
364static int set_local_var(const char *s);
365static int is_assignment(const char *s);
362/* data structure manipulation: */ 366/* data structure manipulation: */
363static int setup_redirect(struct p_context *ctx, int fd, redir_type style, struct in_str *input); 367static int setup_redirect(struct p_context *ctx, int fd, redir_type style, struct in_str *input);
364static void initialize_context(struct p_context *ctx); 368static 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 */
1002static void pseudo_exec(struct child_prog *child) 1006static 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
1613static 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
1620static 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.