diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2009-04-17 18:54:50 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2009-04-17 18:54:50 +0000 |
commit | 270b1c3f68d48797ccc2475c03024ccd91f8e07c (patch) | |
tree | 7319719ad3cddd5f8b09703c6d3b0906eecbf8f2 /shell | |
parent | 4ea187fd62c57799784b06f3c37b63b7e3f6794a (diff) | |
download | busybox-w32-270b1c3f68d48797ccc2475c03024ccd91f8e07c.tar.gz busybox-w32-270b1c3f68d48797ccc2475c03024ccd91f8e07c.tar.bz2 busybox-w32-270b1c3f68d48797ccc2475c03024ccd91f8e07c.zip |
hush: set $n properly for "source" builtin
function old new delta
restore_G_args - 78 +78
save_and_replace_G_args - 64 +64
builtin_source 72 107 +35
run_list 2549 2367 -182
------------------------------------------------------------------------------
(add/remove: 2/0 grow/shrink: 1/1 up/down: 177/-182) Total: -5 bytes
Diffstat (limited to 'shell')
-rw-r--r-- | shell/hush.c | 97 |
1 files changed, 57 insertions, 40 deletions
diff --git a/shell/hush.c b/shell/hush.c index 4a0fc2353..84364e0e7 100644 --- a/shell/hush.c +++ b/shell/hush.c | |||
@@ -939,6 +939,52 @@ static void free_strings(char **strings) | |||
939 | } | 939 | } |
940 | 940 | ||
941 | 941 | ||
942 | /* Helpers for setting new $n and restoring them back | ||
943 | */ | ||
944 | typedef struct save_arg_t { | ||
945 | char *sv_argv0; | ||
946 | char **sv_g_argv; | ||
947 | int sv_g_argc; | ||
948 | smallint sv_g_malloced; | ||
949 | } save_arg_t; | ||
950 | |||
951 | static void save_and_replace_G_args(save_arg_t *sv, char **argv) | ||
952 | { | ||
953 | int n; | ||
954 | |||
955 | sv->sv_argv0 = argv[0]; | ||
956 | sv->sv_g_argv = G.global_argv; | ||
957 | sv->sv_g_argc = G.global_argc; | ||
958 | sv->sv_g_malloced = G.global_args_malloced; | ||
959 | |||
960 | argv[0] = G.global_argv[0]; /* retain $0 */ | ||
961 | G.global_argv = argv; | ||
962 | G.global_args_malloced = 0; | ||
963 | |||
964 | n = 1; | ||
965 | while (*++argv) | ||
966 | n++; | ||
967 | G.global_argc = n; | ||
968 | } | ||
969 | |||
970 | static void restore_G_args(save_arg_t *sv, char **argv) | ||
971 | { | ||
972 | char **pp; | ||
973 | |||
974 | if (G.global_args_malloced) { | ||
975 | /* someone ran "set -- arg1 arg2 ...", undo */ | ||
976 | pp = G.global_argv; | ||
977 | while (*++pp) /* note: does not free $0 */ | ||
978 | free(*pp); | ||
979 | free(G.global_argv); | ||
980 | } | ||
981 | argv[0] = sv->sv_argv0; | ||
982 | G.global_argv = sv->sv_g_argv; | ||
983 | G.global_argc = sv->sv_g_argc; | ||
984 | G.global_args_malloced = sv->sv_g_malloced; | ||
985 | } | ||
986 | |||
987 | |||
942 | /* Basic theory of signal handling in shell | 988 | /* Basic theory of signal handling in shell |
943 | * ======================================== | 989 | * ======================================== |
944 | * This does not describe what hush does, rather, it is current understanding | 990 | * This does not describe what hush does, rather, it is current understanding |
@@ -2802,54 +2848,24 @@ static void exec_function(nommu_save_t *nommu_save, | |||
2802 | 2848 | ||
2803 | static int run_function(const struct function *funcp, char **argv) | 2849 | static int run_function(const struct function *funcp, char **argv) |
2804 | { | 2850 | { |
2805 | int n; | 2851 | int rc; |
2806 | char **pp; | 2852 | save_arg_t sv; |
2807 | char *sv_argv0; | ||
2808 | smallint sv_g_malloced; | ||
2809 | int sv_g_argc; | ||
2810 | char **sv_g_argv; | ||
2811 | |||
2812 | sv_argv0 = argv[0]; | ||
2813 | sv_g_malloced = G.global_args_malloced; | ||
2814 | sv_g_argc = G.global_argc; | ||
2815 | sv_g_argv = G.global_argv; | ||
2816 | |||
2817 | pp = argv; | ||
2818 | n = 1; | ||
2819 | while (*++pp) | ||
2820 | n++; | ||
2821 | |||
2822 | argv[0] = G.global_argv[0]; /* retain $0 */ | ||
2823 | G.global_args_malloced = 0; | ||
2824 | G.global_argc = n; | ||
2825 | G.global_argv = argv; | ||
2826 | 2853 | ||
2854 | save_and_replace_G_args(&sv, argv); | ||
2827 | /* On MMU, funcp->body is always non-NULL */ | 2855 | /* On MMU, funcp->body is always non-NULL */ |
2828 | #if !BB_MMU | 2856 | #if !BB_MMU |
2829 | if (!funcp->body) { | 2857 | if (!funcp->body) { |
2830 | /* Function defined by -F */ | 2858 | /* Function defined by -F */ |
2831 | parse_and_run_string(funcp->body_as_string); | 2859 | parse_and_run_string(funcp->body_as_string); |
2832 | n = G.last_exitcode; | 2860 | rc = G.last_exitcode; |
2833 | } else | 2861 | } else |
2834 | #endif | 2862 | #endif |
2835 | { | 2863 | { |
2836 | n = run_list(funcp->body); | 2864 | rc = run_list(funcp->body); |
2837 | } | ||
2838 | |||
2839 | if (G.global_args_malloced) { | ||
2840 | /* function ran "set -- arg1 arg2 ..." */ | ||
2841 | pp = G.global_argv; | ||
2842 | while (*++pp) | ||
2843 | free(*pp); | ||
2844 | free(G.global_argv); | ||
2845 | } | 2865 | } |
2866 | restore_G_args(&sv, argv); | ||
2846 | 2867 | ||
2847 | argv[0] = sv_argv0; | 2868 | return rc; |
2848 | G.global_args_malloced = sv_g_malloced; | ||
2849 | G.global_argc = sv_g_argc; | ||
2850 | G.global_argv = sv_g_argv; | ||
2851 | |||
2852 | return n; | ||
2853 | } | 2869 | } |
2854 | #endif | 2870 | #endif |
2855 | 2871 | ||
@@ -6659,6 +6675,7 @@ static int builtin_shift(char **argv) | |||
6659 | static int builtin_source(char **argv) | 6675 | static int builtin_source(char **argv) |
6660 | { | 6676 | { |
6661 | FILE *input; | 6677 | FILE *input; |
6678 | save_arg_t sv; | ||
6662 | 6679 | ||
6663 | if (*++argv == NULL) | 6680 | if (*++argv == NULL) |
6664 | return EXIT_FAILURE; | 6681 | return EXIT_FAILURE; |
@@ -6672,11 +6689,11 @@ static int builtin_source(char **argv) | |||
6672 | close_on_exec_on(fileno(input)); | 6689 | close_on_exec_on(fileno(input)); |
6673 | 6690 | ||
6674 | /* Now run the file */ | 6691 | /* Now run the file */ |
6675 | /* TODO: argv and argc are broken; need to save old G.global_argv | 6692 | save_and_replace_G_args(&sv, argv); |
6676 | * (pointer only is OK!) on this stack frame, | ||
6677 | * set G.global_argv=argv+1, recurse, and restore. */ | ||
6678 | parse_and_run_file(input); | 6693 | parse_and_run_file(input); |
6694 | restore_G_args(&sv, argv); | ||
6679 | fclose(input); | 6695 | fclose(input); |
6696 | |||
6680 | return G.last_exitcode; | 6697 | return G.last_exitcode; |
6681 | } | 6698 | } |
6682 | 6699 | ||