summaryrefslogtreecommitdiff
path: root/shell
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2009-04-17 18:54:50 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2009-04-17 18:54:50 +0000
commit270b1c3f68d48797ccc2475c03024ccd91f8e07c (patch)
tree7319719ad3cddd5f8b09703c6d3b0906eecbf8f2 /shell
parent4ea187fd62c57799784b06f3c37b63b7e3f6794a (diff)
downloadbusybox-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.c97
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 */
944typedef 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
951static 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
970static 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
2803static int run_function(const struct function *funcp, char **argv) 2849static 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)
6659static int builtin_source(char **argv) 6675static 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