diff options
Diffstat (limited to '')
-rw-r--r-- | shell/hush.c | 105 |
1 files changed, 59 insertions, 46 deletions
diff --git a/shell/hush.c b/shell/hush.c index fa7e4f563..f9f815289 100644 --- a/shell/hush.c +++ b/shell/hush.c | |||
@@ -913,7 +913,7 @@ static const struct built_in_command bltins2[] = { | |||
913 | */ | 913 | */ |
914 | #if HUSH_DEBUG | 914 | #if HUSH_DEBUG |
915 | /* prevent disasters with G.debug_indent < 0 */ | 915 | /* prevent disasters with G.debug_indent < 0 */ |
916 | # define indent() fprintf(stderr, "%*s", (G.debug_indent * 2) & 0xff, "") | 916 | # define indent() fdprintf(2, "%*s", (G.debug_indent * 2) & 0xff, "") |
917 | # define debug_enter() (G.debug_indent++) | 917 | # define debug_enter() (G.debug_indent++) |
918 | # define debug_leave() (G.debug_indent--) | 918 | # define debug_leave() (G.debug_indent--) |
919 | #else | 919 | #else |
@@ -923,56 +923,56 @@ static const struct built_in_command bltins2[] = { | |||
923 | #endif | 923 | #endif |
924 | 924 | ||
925 | #ifndef debug_printf | 925 | #ifndef debug_printf |
926 | # define debug_printf(...) (indent(), fprintf(stderr, __VA_ARGS__)) | 926 | # define debug_printf(...) (indent(), fdprintf(2, __VA_ARGS__)) |
927 | #endif | 927 | #endif |
928 | 928 | ||
929 | #ifndef debug_printf_parse | 929 | #ifndef debug_printf_parse |
930 | # define debug_printf_parse(...) (indent(), fprintf(stderr, __VA_ARGS__)) | 930 | # define debug_printf_parse(...) (indent(), fdprintf(2, __VA_ARGS__)) |
931 | #endif | 931 | #endif |
932 | 932 | ||
933 | #ifndef debug_printf_exec | 933 | #ifndef debug_printf_exec |
934 | #define debug_printf_exec(...) (indent(), fprintf(stderr, __VA_ARGS__)) | 934 | #define debug_printf_exec(...) (indent(), fdprintf(2, __VA_ARGS__)) |
935 | #endif | 935 | #endif |
936 | 936 | ||
937 | #ifndef debug_printf_env | 937 | #ifndef debug_printf_env |
938 | # define debug_printf_env(...) (indent(), fprintf(stderr, __VA_ARGS__)) | 938 | # define debug_printf_env(...) (indent(), fdprintf(2, __VA_ARGS__)) |
939 | #endif | 939 | #endif |
940 | 940 | ||
941 | #ifndef debug_printf_jobs | 941 | #ifndef debug_printf_jobs |
942 | # define debug_printf_jobs(...) (indent(), fprintf(stderr, __VA_ARGS__)) | 942 | # define debug_printf_jobs(...) (indent(), fdprintf(2, __VA_ARGS__)) |
943 | # define DEBUG_JOBS 1 | 943 | # define DEBUG_JOBS 1 |
944 | #else | 944 | #else |
945 | # define DEBUG_JOBS 0 | 945 | # define DEBUG_JOBS 0 |
946 | #endif | 946 | #endif |
947 | 947 | ||
948 | #ifndef debug_printf_expand | 948 | #ifndef debug_printf_expand |
949 | # define debug_printf_expand(...) (indent(), fprintf(stderr, __VA_ARGS__)) | 949 | # define debug_printf_expand(...) (indent(), fdprintf(2, __VA_ARGS__)) |
950 | # define DEBUG_EXPAND 1 | 950 | # define DEBUG_EXPAND 1 |
951 | #else | 951 | #else |
952 | # define DEBUG_EXPAND 0 | 952 | # define DEBUG_EXPAND 0 |
953 | #endif | 953 | #endif |
954 | 954 | ||
955 | #ifndef debug_printf_varexp | 955 | #ifndef debug_printf_varexp |
956 | # define debug_printf_varexp(...) (indent(), fprintf(stderr, __VA_ARGS__)) | 956 | # define debug_printf_varexp(...) (indent(), fdprintf(2, __VA_ARGS__)) |
957 | #endif | 957 | #endif |
958 | 958 | ||
959 | #ifndef debug_printf_glob | 959 | #ifndef debug_printf_glob |
960 | # define debug_printf_glob(...) (indent(), fprintf(stderr, __VA_ARGS__)) | 960 | # define debug_printf_glob(...) (indent(), fdprintf(2, __VA_ARGS__)) |
961 | # define DEBUG_GLOB 1 | 961 | # define DEBUG_GLOB 1 |
962 | #else | 962 | #else |
963 | # define DEBUG_GLOB 0 | 963 | # define DEBUG_GLOB 0 |
964 | #endif | 964 | #endif |
965 | 965 | ||
966 | #ifndef debug_printf_list | 966 | #ifndef debug_printf_list |
967 | # define debug_printf_list(...) (indent(), fprintf(stderr, __VA_ARGS__)) | 967 | # define debug_printf_list(...) (indent(), fdprintf(2, __VA_ARGS__)) |
968 | #endif | 968 | #endif |
969 | 969 | ||
970 | #ifndef debug_printf_subst | 970 | #ifndef debug_printf_subst |
971 | # define debug_printf_subst(...) (indent(), fprintf(stderr, __VA_ARGS__)) | 971 | # define debug_printf_subst(...) (indent(), fdprintf(2, __VA_ARGS__)) |
972 | #endif | 972 | #endif |
973 | 973 | ||
974 | #ifndef debug_printf_clean | 974 | #ifndef debug_printf_clean |
975 | # define debug_printf_clean(...) (indent(), fprintf(stderr, __VA_ARGS__)) | 975 | # define debug_printf_clean(...) (indent(), fdprintf(2, __VA_ARGS__)) |
976 | # define DEBUG_CLEAN 1 | 976 | # define DEBUG_CLEAN 1 |
977 | #else | 977 | #else |
978 | # define DEBUG_CLEAN 0 | 978 | # define DEBUG_CLEAN 0 |
@@ -982,9 +982,9 @@ static const struct built_in_command bltins2[] = { | |||
982 | static void debug_print_strings(const char *prefix, char **vv) | 982 | static void debug_print_strings(const char *prefix, char **vv) |
983 | { | 983 | { |
984 | indent(); | 984 | indent(); |
985 | fprintf(stderr, "%s:\n", prefix); | 985 | fdprintf(2, "%s:\n", prefix); |
986 | while (*vv) | 986 | while (*vv) |
987 | fprintf(stderr, " '%s'\n", *vv++); | 987 | fdprintf(2, " '%s'\n", *vv++); |
988 | } | 988 | } |
989 | #else | 989 | #else |
990 | # define debug_print_strings(prefix, vv) ((void)0) | 990 | # define debug_print_strings(prefix, vv) ((void)0) |
@@ -1416,6 +1416,22 @@ static void hush_exit(int exitcode) | |||
1416 | builtin_eval(argv); | 1416 | builtin_eval(argv); |
1417 | } | 1417 | } |
1418 | 1418 | ||
1419 | #if ENABLE_FEATURE_CLEAN_UP | ||
1420 | { | ||
1421 | struct variable *cur_var; | ||
1422 | if (G.cwd != bb_msg_unknown) | ||
1423 | free((char*)G.cwd); | ||
1424 | cur_var = G.top_var; | ||
1425 | while (cur_var) { | ||
1426 | struct variable *tmp = cur_var; | ||
1427 | if (!cur_var->max_len) | ||
1428 | free(cur_var->varstr); | ||
1429 | cur_var = cur_var->next; | ||
1430 | free(tmp); | ||
1431 | } | ||
1432 | } | ||
1433 | #endif | ||
1434 | |||
1419 | #if ENABLE_HUSH_JOB | 1435 | #if ENABLE_HUSH_JOB |
1420 | fflush_all(); | 1436 | fflush_all(); |
1421 | sigexit(- (exitcode & 0xff)); | 1437 | sigexit(- (exitcode & 0xff)); |
@@ -2158,22 +2174,22 @@ static void debug_print_list(const char *prefix, o_string *o, int n) | |||
2158 | int i = 0; | 2174 | int i = 0; |
2159 | 2175 | ||
2160 | indent(); | 2176 | indent(); |
2161 | fprintf(stderr, "%s: list:%p n:%d string_start:%d length:%d maxlen:%d glob:%d quoted:%d escape:%d\n", | 2177 | fdprintf(2, "%s: list:%p n:%d string_start:%d length:%d maxlen:%d glob:%d quoted:%d escape:%d\n", |
2162 | prefix, list, n, string_start, o->length, o->maxlen, | 2178 | prefix, list, n, string_start, o->length, o->maxlen, |
2163 | !!(o->o_expflags & EXP_FLAG_GLOB), | 2179 | !!(o->o_expflags & EXP_FLAG_GLOB), |
2164 | o->has_quoted_part, | 2180 | o->has_quoted_part, |
2165 | !!(o->o_expflags & EXP_FLAG_ESC_GLOB_CHARS)); | 2181 | !!(o->o_expflags & EXP_FLAG_ESC_GLOB_CHARS)); |
2166 | while (i < n) { | 2182 | while (i < n) { |
2167 | indent(); | 2183 | indent(); |
2168 | fprintf(stderr, " list[%d]=%d '%s' %p\n", i, (int)list[i], | 2184 | fdprintf(2, " list[%d]=%d '%s' %p\n", i, (int)(uintptr_t)list[i], |
2169 | o->data + (int)list[i] + string_start, | 2185 | o->data + (int)(uintptr_t)list[i] + string_start, |
2170 | o->data + (int)list[i] + string_start); | 2186 | o->data + (int)(uintptr_t)list[i] + string_start); |
2171 | i++; | 2187 | i++; |
2172 | } | 2188 | } |
2173 | if (n) { | 2189 | if (n) { |
2174 | const char *p = o->data + (int)list[n - 1] + string_start; | 2190 | const char *p = o->data + (int)(uintptr_t)list[n - 1] + string_start; |
2175 | indent(); | 2191 | indent(); |
2176 | fprintf(stderr, " total_sz:%ld\n", (long)((p + strlen(p) + 1) - o->data)); | 2192 | fdprintf(2, " total_sz:%ld\n", (long)((p + strlen(p) + 1) - o->data)); |
2177 | } | 2193 | } |
2178 | } | 2194 | } |
2179 | #else | 2195 | #else |
@@ -2672,18 +2688,18 @@ static void debug_print_tree(struct pipe *pi, int lvl) | |||
2672 | 2688 | ||
2673 | pin = 0; | 2689 | pin = 0; |
2674 | while (pi) { | 2690 | while (pi) { |
2675 | fprintf(stderr, "%*spipe %d res_word=%s followup=%d %s\n", lvl*2, "", | 2691 | fdprintf(2, "%*spipe %d res_word=%s followup=%d %s\n", lvl*2, "", |
2676 | pin, RES[pi->res_word], pi->followup, PIPE[pi->followup]); | 2692 | pin, RES[pi->res_word], pi->followup, PIPE[pi->followup]); |
2677 | prn = 0; | 2693 | prn = 0; |
2678 | while (prn < pi->num_cmds) { | 2694 | while (prn < pi->num_cmds) { |
2679 | struct command *command = &pi->cmds[prn]; | 2695 | struct command *command = &pi->cmds[prn]; |
2680 | char **argv = command->argv; | 2696 | char **argv = command->argv; |
2681 | 2697 | ||
2682 | fprintf(stderr, "%*s cmd %d assignment_cnt:%d", | 2698 | fdprintf(2, "%*s cmd %d assignment_cnt:%d", |
2683 | lvl*2, "", prn, | 2699 | lvl*2, "", prn, |
2684 | command->assignment_cnt); | 2700 | command->assignment_cnt); |
2685 | if (command->group) { | 2701 | if (command->group) { |
2686 | fprintf(stderr, " group %s: (argv=%p)%s%s\n", | 2702 | fdprintf(2, " group %s: (argv=%p)%s%s\n", |
2687 | CMDTYPE[command->cmd_type], | 2703 | CMDTYPE[command->cmd_type], |
2688 | argv | 2704 | argv |
2689 | # if !BB_MMU | 2705 | # if !BB_MMU |
@@ -2697,10 +2713,10 @@ static void debug_print_tree(struct pipe *pi, int lvl) | |||
2697 | continue; | 2713 | continue; |
2698 | } | 2714 | } |
2699 | if (argv) while (*argv) { | 2715 | if (argv) while (*argv) { |
2700 | fprintf(stderr, " '%s'", *argv); | 2716 | fdprintf(2, " '%s'", *argv); |
2701 | argv++; | 2717 | argv++; |
2702 | } | 2718 | } |
2703 | fprintf(stderr, "\n"); | 2719 | fdprintf(2, "\n"); |
2704 | prn++; | 2720 | prn++; |
2705 | } | 2721 | } |
2706 | pi = pi->next; | 2722 | pi = pi->next; |
@@ -4106,7 +4122,16 @@ static struct pipe *parse_stream(char **pstring, | |||
4106 | if (IS_NULL_CMD(ctx.command) | 4122 | if (IS_NULL_CMD(ctx.command) |
4107 | && dest.length == 0 && !dest.has_quoted_part | 4123 | && dest.length == 0 && !dest.has_quoted_part |
4108 | ) { | 4124 | ) { |
4109 | continue; | 4125 | /* This newline can be ignored. But... |
4126 | * without the below check, interactive shell | ||
4127 | * will ignore even lines with bare <newline>, | ||
4128 | * and show the continuation prompt: | ||
4129 | * ps1_prompt$ <enter> | ||
4130 | * ps2> _ <=== wrong prompt, should be ps1 | ||
4131 | */ | ||
4132 | struct pipe *pi = ctx.list_head; | ||
4133 | if (pi->num_cmds != 0) | ||
4134 | continue; | ||
4110 | } | 4135 | } |
4111 | /* Treat newline as a command separator. */ | 4136 | /* Treat newline as a command separator. */ |
4112 | done_pipe(&ctx, PIPE_SEQ); | 4137 | done_pipe(&ctx, PIPE_SEQ); |
@@ -7445,7 +7470,7 @@ int hush_main(int argc, char **argv) | |||
7445 | unsigned builtin_argc; | 7470 | unsigned builtin_argc; |
7446 | char **e; | 7471 | char **e; |
7447 | struct variable *cur_var; | 7472 | struct variable *cur_var; |
7448 | struct variable shell_ver; | 7473 | struct variable *shell_ver; |
7449 | 7474 | ||
7450 | INIT_G(); | 7475 | INIT_G(); |
7451 | if (EXIT_SUCCESS) /* if EXIT_SUCCESS == 0, it is already done */ | 7476 | if (EXIT_SUCCESS) /* if EXIT_SUCCESS == 0, it is already done */ |
@@ -7454,17 +7479,17 @@ int hush_main(int argc, char **argv) | |||
7454 | G.argv0_for_re_execing = argv[0]; | 7479 | G.argv0_for_re_execing = argv[0]; |
7455 | #endif | 7480 | #endif |
7456 | /* Deal with HUSH_VERSION */ | 7481 | /* Deal with HUSH_VERSION */ |
7457 | memset(&shell_ver, 0, sizeof(shell_ver)); | 7482 | shell_ver = xzalloc(sizeof(*shell_ver)); |
7458 | shell_ver.flg_export = 1; | 7483 | shell_ver->flg_export = 1; |
7459 | shell_ver.flg_read_only = 1; | 7484 | shell_ver->flg_read_only = 1; |
7460 | /* Code which handles ${var<op>...} needs writable values for all variables, | 7485 | /* Code which handles ${var<op>...} needs writable values for all variables, |
7461 | * therefore we xstrdup: */ | 7486 | * therefore we xstrdup: */ |
7462 | shell_ver.varstr = xstrdup(hush_version_str), | 7487 | shell_ver->varstr = xstrdup(hush_version_str); |
7463 | G.top_var = &shell_ver; | ||
7464 | /* Create shell local variables from the values | 7488 | /* Create shell local variables from the values |
7465 | * currently living in the environment */ | 7489 | * currently living in the environment */ |
7466 | debug_printf_env("unsetenv '%s'\n", "HUSH_VERSION"); | 7490 | debug_printf_env("unsetenv '%s'\n", "HUSH_VERSION"); |
7467 | unsetenv("HUSH_VERSION"); /* in case it exists in initial env */ | 7491 | unsetenv("HUSH_VERSION"); /* in case it exists in initial env */ |
7492 | G.top_var = shell_ver; | ||
7468 | cur_var = G.top_var; | 7493 | cur_var = G.top_var; |
7469 | e = environ; | 7494 | e = environ; |
7470 | if (e) while (*e) { | 7495 | if (e) while (*e) { |
@@ -7479,8 +7504,8 @@ int hush_main(int argc, char **argv) | |||
7479 | e++; | 7504 | e++; |
7480 | } | 7505 | } |
7481 | /* (Re)insert HUSH_VERSION into env (AFTER we scanned the env!) */ | 7506 | /* (Re)insert HUSH_VERSION into env (AFTER we scanned the env!) */ |
7482 | debug_printf_env("putenv '%s'\n", shell_ver.varstr); | 7507 | debug_printf_env("putenv '%s'\n", shell_ver->varstr); |
7483 | putenv(shell_ver.varstr); | 7508 | putenv(shell_ver->varstr); |
7484 | 7509 | ||
7485 | /* Export PWD */ | 7510 | /* Export PWD */ |
7486 | set_pwd_var(/*exp:*/ 1); | 7511 | set_pwd_var(/*exp:*/ 1); |
@@ -7840,18 +7865,6 @@ int hush_main(int argc, char **argv) | |||
7840 | parse_and_run_file(stdin); | 7865 | parse_and_run_file(stdin); |
7841 | 7866 | ||
7842 | final_return: | 7867 | final_return: |
7843 | #if ENABLE_FEATURE_CLEAN_UP | ||
7844 | if (G.cwd != bb_msg_unknown) | ||
7845 | free((char*)G.cwd); | ||
7846 | cur_var = G.top_var->next; | ||
7847 | while (cur_var) { | ||
7848 | struct variable *tmp = cur_var; | ||
7849 | if (!cur_var->max_len) | ||
7850 | free(cur_var->varstr); | ||
7851 | cur_var = cur_var->next; | ||
7852 | free(tmp); | ||
7853 | } | ||
7854 | #endif | ||
7855 | hush_exit(G.last_exitcode); | 7868 | hush_exit(G.last_exitcode); |
7856 | } | 7869 | } |
7857 | 7870 | ||