diff options
| author | andersen <andersen@69ca8d6d-28ef-0310-b511-8ec308f3f277> | 2001-05-22 19:05:18 +0000 |
|---|---|---|
| committer | andersen <andersen@69ca8d6d-28ef-0310-b511-8ec308f3f277> | 2001-05-22 19:05:18 +0000 |
| commit | b309e4d987c190986ecf39a7326e54aa89c3840f (patch) | |
| tree | d0c5b6b4897035700f1957dffc4db6c5d18a8ba7 /shell | |
| parent | d653ef9ed86810374931663ec8fb3acacb6c087b (diff) | |
| download | busybox-w32-b309e4d987c190986ecf39a7326e54aa89c3840f.tar.gz busybox-w32-b309e4d987c190986ecf39a7326e54aa89c3840f.tar.bz2 busybox-w32-b309e4d987c190986ecf39a7326e54aa89c3840f.zip | |
Updates from both Vladimir and Larry
git-svn-id: svn://busybox.net/trunk/busybox@2706 69ca8d6d-28ef-0310-b511-8ec308f3f277
Diffstat (limited to 'shell')
| -rw-r--r-- | shell/hush.c | 153 |
1 files changed, 89 insertions, 64 deletions
diff --git a/shell/hush.c b/shell/hush.c index 722dcf7ac..2b100983e 100644 --- a/shell/hush.c +++ b/shell/hush.c | |||
| @@ -256,10 +256,8 @@ static const char *cwd; | |||
| 256 | static struct jobset *job_list; | 256 | static struct jobset *job_list; |
| 257 | static unsigned int last_bg_pid; | 257 | static unsigned int last_bg_pid; |
| 258 | static char *PS1; | 258 | static char *PS1; |
| 259 | static char PS2[] = "> "; | 259 | static char *PS2; |
| 260 | |||
| 261 | struct variables shell_ver = { "HUSH_VERSION", "0.01", 1, 1, 0 }; | 260 | struct variables shell_ver = { "HUSH_VERSION", "0.01", 1, 1, 0 }; |
| 262 | |||
| 263 | struct variables *top_vars = &shell_ver; | 261 | struct variables *top_vars = &shell_ver; |
| 264 | 262 | ||
| 265 | #define B_CHUNK (100) | 263 | #define B_CHUNK (100) |
| @@ -505,29 +503,29 @@ static int builtin_export(struct child_prog *child) | |||
| 505 | name = strdup(name); | 503 | name = strdup(name); |
| 506 | 504 | ||
| 507 | if(name) { | 505 | if(name) { |
| 508 | char *value = strchr(name, '='); | 506 | char *value = strchr(name, '='); |
| 509 | 507 | ||
| 510 | if (!value) { | 508 | if (!value) { |
| 511 | char *tmp; | 509 | char *tmp; |
| 512 | /* They are exporting something without an =VALUE */ | 510 | /* They are exporting something without an =VALUE */ |
| 513 | 511 | ||
| 514 | value = get_local_var(name); | 512 | value = get_local_var(name); |
| 515 | if (value) { | 513 | if (value) { |
| 516 | size_t ln = strlen(name); | 514 | size_t ln = strlen(name); |
| 517 | 515 | ||
| 518 | tmp = realloc(name, ln+strlen(value)+2); | 516 | tmp = realloc(name, ln+strlen(value)+2); |
| 519 | if(tmp==NULL) | 517 | if(tmp==NULL) |
| 520 | res = -1; | 518 | res = -1; |
| 521 | else { | 519 | else { |
| 522 | sprintf(tmp+ln, "=%s", value); | 520 | sprintf(tmp+ln, "=%s", value); |
| 523 | name = tmp; | 521 | name = tmp; |
| 522 | } | ||
| 523 | } else { | ||
| 524 | /* bash does not return an error when trying to export | ||
| 525 | * an undefined variable. Do likewise. */ | ||
| 526 | res = 1; | ||
| 524 | } | 527 | } |
| 525 | } else { | ||
| 526 | /* bash not put error and set error code | ||
| 527 | if exporting not defined variable */ | ||
| 528 | res = 1; | ||
| 529 | } | 528 | } |
| 530 | } | ||
| 531 | } | 529 | } |
| 532 | if (res<0) | 530 | if (res<0) |
| 533 | perror_msg("export"); | 531 | perror_msg("export"); |
| @@ -641,7 +639,7 @@ static int builtin_read(struct child_prog *child) | |||
| 641 | char string[BUFSIZ]; | 639 | char string[BUFSIZ]; |
| 642 | char *var = 0; | 640 | char *var = 0; |
| 643 | 641 | ||
| 644 | string[0] = 0; /* for correct work if stdin have "only EOF" */ | 642 | string[0] = 0; /* In case stdin has only EOF */ |
| 645 | /* read string */ | 643 | /* read string */ |
| 646 | fgets(string, sizeof(string), stdin); | 644 | fgets(string, sizeof(string), stdin); |
| 647 | chomp(string); | 645 | chomp(string); |
| @@ -650,10 +648,10 @@ static int builtin_read(struct child_prog *child) | |||
| 650 | sprintf(var, "%s=%s", child->argv[1], string); | 648 | sprintf(var, "%s=%s", child->argv[1], string); |
| 651 | res = set_local_var(var, 0); | 649 | res = set_local_var(var, 0); |
| 652 | } else | 650 | } else |
| 653 | res = -1; | 651 | res = -1; |
| 654 | if (res) | 652 | if (res) |
| 655 | fprintf(stderr, "read: %m\n"); | 653 | fprintf(stderr, "read: %m\n"); |
| 656 | free(var); /* not move up - saved errno */ | 654 | free(var); /* So not move up to avoid breaking errno */ |
| 657 | return res; | 655 | return res; |
| 658 | } else { | 656 | } else { |
| 659 | do res=getchar(); while(res!='\n' && res!=EOF); | 657 | do res=getchar(); while(res!='\n' && res!=EOF); |
| @@ -1061,6 +1059,9 @@ static int pipe_wait(struct pipe *pi) | |||
| 1061 | } | 1059 | } |
| 1062 | 1060 | ||
| 1063 | /* never returns */ | 1061 | /* never returns */ |
| 1062 | /* XXX no exit() here. If you don't exec, use _exit instead. | ||
| 1063 | * The at_exit handlers apparently confuse the calling process, | ||
| 1064 | * in particular stdin handling. Not sure why? */ | ||
| 1064 | static void pseudo_exec(struct child_prog *child) | 1065 | static void pseudo_exec(struct child_prog *child) |
| 1065 | { | 1066 | { |
| 1066 | int i, rcode; | 1067 | int i, rcode; |
| @@ -1076,7 +1077,9 @@ static void pseudo_exec(struct child_prog *child) | |||
| 1076 | /* If a variable is assigned in a forest, and nobody listens, | 1077 | /* If a variable is assigned in a forest, and nobody listens, |
| 1077 | * was it ever really set? | 1078 | * was it ever really set? |
| 1078 | */ | 1079 | */ |
| 1079 | if (child->argv[0] == NULL) exit(EXIT_SUCCESS); | 1080 | if (child->argv[0] == NULL) { |
| 1081 | _exit(EXIT_SUCCESS); | ||
| 1082 | } | ||
| 1080 | 1083 | ||
| 1081 | /* | 1084 | /* |
| 1082 | * Check if the command matches any of the builtins. | 1085 | * Check if the command matches any of the builtins. |
| @@ -1087,7 +1090,7 @@ static void pseudo_exec(struct child_prog *child) | |||
| 1087 | for (x = bltins; x->cmd; x++) { | 1090 | for (x = bltins; x->cmd; x++) { |
| 1088 | if (strcmp(child->argv[0], x->cmd) == 0 ) { | 1091 | if (strcmp(child->argv[0], x->cmd) == 0 ) { |
| 1089 | debug_printf("builtin exec %s\n", child->argv[0]); | 1092 | debug_printf("builtin exec %s\n", child->argv[0]); |
| 1090 | exit(x->function(child)); | 1093 | _exit(x->function(child)); |
| 1091 | } | 1094 | } |
| 1092 | } | 1095 | } |
| 1093 | 1096 | ||
| @@ -1128,18 +1131,18 @@ static void pseudo_exec(struct child_prog *child) | |||
| 1128 | debug_printf("exec of %s\n",child->argv[0]); | 1131 | debug_printf("exec of %s\n",child->argv[0]); |
| 1129 | execvp(child->argv[0],child->argv); | 1132 | execvp(child->argv[0],child->argv); |
| 1130 | perror_msg("couldn't exec: %s",child->argv[0]); | 1133 | perror_msg("couldn't exec: %s",child->argv[0]); |
| 1131 | exit(1); | 1134 | _exit(1); |
| 1132 | } else if (child->group) { | 1135 | } else if (child->group) { |
| 1133 | debug_printf("runtime nesting to group\n"); | 1136 | debug_printf("runtime nesting to group\n"); |
| 1134 | interactive=0; /* crucial!!!! */ | 1137 | interactive=0; /* crucial!!!! */ |
| 1135 | rcode = run_list_real(child->group); | 1138 | rcode = run_list_real(child->group); |
| 1136 | /* OK to leak memory by not calling run_list_test, | 1139 | /* OK to leak memory by not calling run_list_test, |
| 1137 | * since this process is about to exit */ | 1140 | * since this process is about to exit */ |
| 1138 | exit(rcode); | 1141 | _exit(rcode); |
| 1139 | } else { | 1142 | } else { |
| 1140 | /* Can happen. See what bash does with ">foo" by itself. */ | 1143 | /* Can happen. See what bash does with ">foo" by itself. */ |
| 1141 | debug_printf("trying to pseudo_exec null command\n"); | 1144 | debug_printf("trying to pseudo_exec null command\n"); |
| 1142 | exit(EXIT_SUCCESS); | 1145 | _exit(EXIT_SUCCESS); |
| 1143 | } | 1146 | } |
| 1144 | } | 1147 | } |
| 1145 | 1148 | ||
| @@ -1713,23 +1716,29 @@ static int set_local_var(const char *s, int flg_export) | |||
| 1713 | } else { | 1716 | } else { |
| 1714 | *value++ = 0; | 1717 | *value++ = 0; |
| 1715 | 1718 | ||
| 1716 | for(cur = top_vars; cur; cur = cur->next) | 1719 | for(cur = top_vars; cur; cur = cur->next) { |
| 1717 | if(strcmp(cur->name, name)==0) | 1720 | if(strcmp(cur->name, name)==0) |
| 1718 | break; | 1721 | break; |
| 1722 | } | ||
| 1719 | 1723 | ||
| 1720 | if(cur) { | 1724 | if(cur) { |
| 1721 | if(strcmp(cur->value, value)==0) { | 1725 | if(strcmp(cur->value, value)==0) { |
| 1722 | result = cur->flg_export == flg_export; | 1726 | if(flg_export>0 && cur->flg_export==0) |
| 1727 | cur->flg_export=flg_export; | ||
| 1728 | else | ||
| 1729 | result++; | ||
| 1723 | } else { | 1730 | } else { |
| 1724 | if(cur->flg_read_only) { | 1731 | if(cur->flg_read_only) { |
| 1725 | result = -1; | 1732 | result = -1; |
| 1726 | error_msg("%s: readonly variable", name); | 1733 | error_msg("%s: readonly variable", name); |
| 1727 | } else { | 1734 | } else { |
| 1735 | if(flg_export>0 || cur->flg_export>1) | ||
| 1736 | cur->flg_export=1; | ||
| 1728 | free(cur->value); | 1737 | free(cur->value); |
| 1729 | cur->value = newval; | 1738 | cur->value = newval; |
| 1730 | newval = 0; /* protect free */ | 1739 | newval = 0; /* protect free */ |
| 1731 | } | 1740 | } |
| 1732 | } | 1741 | } |
| 1733 | } else { | 1742 | } else { |
| 1734 | cur = malloc(sizeof(struct variables)); | 1743 | cur = malloc(sizeof(struct variables)); |
| 1735 | if(cur==0) { | 1744 | if(cur==0) { |
| @@ -1738,10 +1747,9 @@ static int set_local_var(const char *s, int flg_export) | |||
| 1738 | cur->name = strdup(name); | 1747 | cur->name = strdup(name); |
| 1739 | if(cur->name == 0) { | 1748 | if(cur->name == 0) { |
| 1740 | free(cur); | 1749 | free(cur); |
| 1741 | result = -1; | 1750 | result = -1; |
| 1742 | } else { | 1751 | } else { |
| 1743 | struct variables *bottom = top_vars; | 1752 | struct variables *bottom = top_vars; |
| 1744 | |||
| 1745 | cur->value = newval; | 1753 | cur->value = newval; |
| 1746 | newval = 0; /* protect free */ | 1754 | newval = 0; /* protect free */ |
| 1747 | cur->next = 0; | 1755 | cur->next = 0; |
| @@ -1749,16 +1757,16 @@ static int set_local_var(const char *s, int flg_export) | |||
| 1749 | cur->flg_read_only = 0; | 1757 | cur->flg_read_only = 0; |
| 1750 | while(bottom->next) bottom=bottom->next; | 1758 | while(bottom->next) bottom=bottom->next; |
| 1751 | bottom->next = cur; | 1759 | bottom->next = cur; |
| 1760 | } | ||
| 1752 | } | 1761 | } |
| 1753 | } | 1762 | } |
| 1754 | } | 1763 | } |
| 1755 | } | ||
| 1756 | 1764 | ||
| 1757 | if((result==0 && flg_export==1) || (result>0 && cur->flg_export>0)) { | 1765 | if(result==0 && cur->flg_export==1) { |
| 1758 | *(value-1) = '='; | 1766 | *(value-1) = '='; |
| 1759 | result = putenv(name); | 1767 | result = putenv(name); |
| 1760 | } else { | 1768 | } else { |
| 1761 | free(name); | 1769 | free(name); |
| 1762 | if(result>0) /* equivalent to previous set */ | 1770 | if(result>0) /* equivalent to previous set */ |
| 1763 | result = 0; | 1771 | result = 0; |
| 1764 | } | 1772 | } |
| @@ -1771,14 +1779,16 @@ static void unset_local_var(const char *name) | |||
| 1771 | struct variables *cur; | 1779 | struct variables *cur; |
| 1772 | 1780 | ||
| 1773 | if (name) { | 1781 | if (name) { |
| 1774 | for (cur = top_vars; cur; cur=cur->next) | 1782 | for (cur = top_vars; cur; cur=cur->next) { |
| 1775 | if(strcmp(cur->name, name)==0) | 1783 | if(strcmp(cur->name, name)==0) |
| 1776 | break; | 1784 | break; |
| 1785 | } | ||
| 1777 | if(cur!=0) { | 1786 | if(cur!=0) { |
| 1778 | struct variables *next = top_vars; | 1787 | struct variables *next = top_vars; |
| 1779 | if(cur==next) | 1788 | if(cur->flg_read_only) { |
| 1780 | return; | 1789 | error_msg("%s: readonly variable", name); |
| 1781 | else { | 1790 | return; |
| 1791 | } else { | ||
| 1782 | if(cur->flg_export) | 1792 | if(cur->flg_export) |
| 1783 | unsetenv(cur->name); | 1793 | unsetenv(cur->name); |
| 1784 | free(cur->name); | 1794 | free(cur->name); |
| @@ -2103,9 +2113,9 @@ FILE *generate_stream_from_list(struct pipe *head) | |||
| 2103 | #if 0 | 2113 | #if 0 |
| 2104 | #define SURROGATE "surrogate response" | 2114 | #define SURROGATE "surrogate response" |
| 2105 | write(1,SURROGATE,sizeof(SURROGATE)); | 2115 | write(1,SURROGATE,sizeof(SURROGATE)); |
| 2106 | exit(run_list(head)); | 2116 | _exit(run_list(head)); |
| 2107 | #else | 2117 | #else |
| 2108 | exit(run_list_real(head)); /* leaks memory */ | 2118 | _exit(run_list_real(head)); /* leaks memory */ |
| 2109 | #endif | 2119 | #endif |
| 2110 | } | 2120 | } |
| 2111 | debug_printf("forked child %d\n",pid); | 2121 | debug_printf("forked child %d\n",pid); |
| @@ -2531,18 +2541,43 @@ int shell_main(int argc, char **argv) | |||
| 2531 | struct jobset joblist_end = { NULL, NULL }; | 2541 | struct jobset joblist_end = { NULL, NULL }; |
| 2532 | char **e = environ; | 2542 | char **e = environ; |
| 2533 | 2543 | ||
| 2534 | /* initialize globals */ | 2544 | /* FIXME */ |
| 2545 | fprintf(stderr, "sizeof(map)=%d\n", sizeof(map)); | ||
| 2546 | |||
| 2547 | |||
| 2548 | /* XXX what should these be while sourcing /etc/profile? */ | ||
| 2549 | global_argc = argc; | ||
| 2550 | global_argv = argv; | ||
| 2551 | |||
| 2552 | /* (re?) initialize globals. Sometimes shell_main() ends up calling | ||
| 2553 | * shell_main(), therefore we cannot rely on the BSS to zero out this | ||
| 2554 | * stuff. Reset these to 0 every time. */ | ||
| 2555 | ifs = NULL; | ||
| 2556 | memset(map,0,sizeof(map)); | ||
| 2557 | fake_mode = 0; | ||
| 2558 | interactive = 0; | ||
| 2559 | close_me_head = NULL; | ||
| 2560 | last_bg_pid = 0; | ||
| 2561 | |||
| 2562 | /* Initialize some more globals to non-zero values */ | ||
| 2563 | set_cwd(); | ||
| 2564 | job_list = &joblist_end; | ||
| 2565 | #ifdef BB_FEATURE_COMMAND_EDITING | ||
| 2566 | cmdedit_set_initial_prompt(); | ||
| 2567 | #else | ||
| 2568 | PS1 = NULL; | ||
| 2569 | #endif | ||
| 2570 | PS2 = "> "; | ||
| 2571 | |||
| 2572 | /* initialize our shell local variables with the values | ||
| 2573 | * currently living in the environment */ | ||
| 2535 | if (e) { | 2574 | if (e) { |
| 2536 | for (; *e; e++) | 2575 | for (; *e; e++) |
| 2537 | set_local_var(*e, 2); /* without call putenv() */ | 2576 | set_local_var(*e, 2); /* without call putenv() */ |
| 2538 | } | 2577 | } |
| 2539 | job_list = &joblist_end; | ||
| 2540 | 2578 | ||
| 2541 | last_return_code=EXIT_SUCCESS; | 2579 | last_return_code=EXIT_SUCCESS; |
| 2542 | 2580 | ||
| 2543 | /* XXX what should these be while sourcing /etc/profile? */ | ||
| 2544 | global_argc = argc; | ||
| 2545 | global_argv = argv; | ||
| 2546 | 2581 | ||
| 2547 | /* If we get started under a job aware app (like bash | 2582 | /* If we get started under a job aware app (like bash |
| 2548 | * for example), make sure we are now in charge so we | 2583 | * for example), make sure we are now in charge so we |
| @@ -2563,16 +2598,6 @@ int shell_main(int argc, char **argv) | |||
| 2563 | } | 2598 | } |
| 2564 | input=stdin; | 2599 | input=stdin; |
| 2565 | 2600 | ||
| 2566 | /* initialize the cwd -- this is never freed...*/ | ||
| 2567 | cwd = xgetcwd(0); | ||
| 2568 | if (!cwd) | ||
| 2569 | cwd = unknown; | ||
| 2570 | #ifdef BB_FEATURE_COMMAND_EDITING | ||
| 2571 | cmdedit_set_initial_prompt(); | ||
| 2572 | #else | ||
| 2573 | PS1 = NULL; | ||
| 2574 | #endif | ||
| 2575 | |||
| 2576 | while ((opt = getopt(argc, argv, "c:xif")) > 0) { | 2601 | while ((opt = getopt(argc, argv, "c:xif")) > 0) { |
| 2577 | switch (opt) { | 2602 | switch (opt) { |
| 2578 | case 'c': | 2603 | case 'c': |
