diff options
author | Eric Andersen <andersen@codepoet.org> | 2001-05-22 19:05:18 +0000 |
---|---|---|
committer | Eric Andersen <andersen@codepoet.org> | 2001-05-22 19:05:18 +0000 |
commit | 94ac244dea54fca088b12665bc5862875c43e8c2 (patch) | |
tree | d0c5b6b4897035700f1957dffc4db6c5d18a8ba7 | |
parent | 1eb4acfc2399d3ab4a7a122a0aff3f5d5109bf2c (diff) | |
download | busybox-w32-94ac244dea54fca088b12665bc5862875c43e8c2.tar.gz busybox-w32-94ac244dea54fca088b12665bc5862875c43e8c2.tar.bz2 busybox-w32-94ac244dea54fca088b12665bc5862875c43e8c2.zip |
Updates from both Vladimir and Larry
-rw-r--r-- | hush.c | 153 | ||||
-rw-r--r-- | shell/hush.c | 153 |
2 files changed, 178 insertions, 128 deletions
@@ -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': |
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': |