diff options
author | Eric Andersen <andersen@codepoet.org> | 2001-03-08 17:17:13 +0000 |
---|---|---|
committer | Eric Andersen <andersen@codepoet.org> | 2001-03-08 17:17:13 +0000 |
commit | ca6045955d8e51b268e242f59f3b63b9fdcf90e6 (patch) | |
tree | 7114ee07aff93918d343d2b4afb156b6413cf9ca | |
parent | e2c44fc966d30ba719dcf3bc65c60f275ee7d8a4 (diff) | |
download | busybox-w32-ca6045955d8e51b268e242f59f3b63b9fdcf90e6.tar.gz busybox-w32-ca6045955d8e51b268e242f59f3b63b9fdcf90e6.tar.bz2 busybox-w32-ca6045955d8e51b268e242f59f3b63b9fdcf90e6.zip |
Rework environment variable handling to use wordexp, per a suggestion from
Larry Doolittle a couple of months ago. This makes the stuff-expansion in lash
be ever so standards compliant. This change needs testing by everyone, but
appears to be solid enough to let us close bug #1090.
It works for me; however, please test this change!
-Erik
-rw-r--r-- | lash.c | 191 | ||||
-rw-r--r-- | sh.c | 191 | ||||
-rw-r--r-- | shell/lash.c | 191 | ||||
-rw-r--r-- | utility.c | 2 |
4 files changed, 250 insertions, 325 deletions
@@ -54,7 +54,7 @@ | |||
54 | #include <ctype.h> | 54 | #include <ctype.h> |
55 | #include <errno.h> | 55 | #include <errno.h> |
56 | #include <fcntl.h> | 56 | #include <fcntl.h> |
57 | #include <glob.h> | 57 | #include <wordexp.h> |
58 | #include <signal.h> | 58 | #include <signal.h> |
59 | #include <string.h> | 59 | #include <string.h> |
60 | #include <sys/ioctl.h> | 60 | #include <sys/ioctl.h> |
@@ -96,8 +96,6 @@ struct child_prog { | |||
96 | char **argv; /* program name and arguments */ | 96 | char **argv; /* program name and arguments */ |
97 | int num_redirects; /* elements in redirection array */ | 97 | int num_redirects; /* elements in redirection array */ |
98 | struct redir_struct *redirects; /* I/O redirects */ | 98 | struct redir_struct *redirects; /* I/O redirects */ |
99 | glob_t glob_result; /* result of parameter globbing */ | ||
100 | int free_glob; /* should we globfree(&glob_result)? */ | ||
101 | int is_stopped; /* is the program currently running? */ | 99 | int is_stopped; /* is the program currently running? */ |
102 | struct job *family; /* pointer back to the child's parent job */ | 100 | struct job *family; /* pointer back to the child's parent job */ |
103 | }; | 101 | }; |
@@ -209,9 +207,9 @@ static int argc; | |||
209 | static char **argv; | 207 | static char **argv; |
210 | static struct close_me *close_me_head; | 208 | static struct close_me *close_me_head; |
211 | #ifdef BB_FEATURE_SH_ENVIRONMENT | 209 | #ifdef BB_FEATURE_SH_ENVIRONMENT |
212 | static int last_bg_pid=-1; | 210 | static int last_bg_pid; |
213 | static int last_return_code=-1; | 211 | static int last_return_code; |
214 | static int show_x_trace=FALSE; | 212 | static int show_x_trace; |
215 | #endif | 213 | #endif |
216 | #ifdef BB_FEATURE_SH_IF_EXPRESSIONS | 214 | #ifdef BB_FEATURE_SH_IF_EXPRESSIONS |
217 | static char syntax_err[]="syntax error near unexpected token"; | 215 | static char syntax_err[]="syntax error near unexpected token"; |
@@ -650,8 +648,6 @@ static void free_job(struct job *cmd) | |||
650 | free(cmd->progs[i].argv); | 648 | free(cmd->progs[i].argv); |
651 | if (cmd->progs[i].redirects) | 649 | if (cmd->progs[i].redirects) |
652 | free(cmd->progs[i].redirects); | 650 | free(cmd->progs[i].redirects); |
653 | if (cmd->progs[i].free_glob) | ||
654 | globfree(&cmd->progs[i].glob_result); | ||
655 | } | 651 | } |
656 | free(cmd->progs); | 652 | free(cmd->progs); |
657 | if (cmd->text) | 653 | if (cmd->text) |
@@ -875,7 +871,7 @@ static int get_command(FILE * source, char *command) | |||
875 | } | 871 | } |
876 | 872 | ||
877 | /* remove trailing newline */ | 873 | /* remove trailing newline */ |
878 | command[strlen(command) - 1] = '\0'; | 874 | chomp(command); |
879 | 875 | ||
880 | return 0; | 876 | return 0; |
881 | } | 877 | } |
@@ -900,125 +896,102 @@ static char* itoa(register int i) | |||
900 | *--b = '-'; | 896 | *--b = '-'; |
901 | return b; | 897 | return b; |
902 | } | 898 | } |
903 | #endif | 899 | #endif |
904 | 900 | ||
905 | static void expand_argument(struct child_prog *prog, int *argcPtr, | 901 | static int expand_arguments(char *command) |
906 | int *argv_alloced_ptr) | ||
907 | { | 902 | { |
908 | int argc_l = *argcPtr; | 903 | #ifdef BB_FEATURE_SH_ENVIRONMENT |
909 | int argv_alloced = *argv_alloced_ptr; | 904 | wordexp_t wrdexp; |
910 | int rc; | ||
911 | int flags; | ||
912 | int i; | ||
913 | char *src, *dst, *var; | 905 | char *src, *dst, *var; |
906 | int i=0, length, total_length=0, retval; | ||
907 | #endif | ||
908 | |||
909 | /* get rid of the terminating \n */ | ||
910 | chomp(command); | ||
914 | 911 | ||
915 | if (argc_l > 1) { /* cmd->glob_result is already initialized */ | ||
916 | flags = GLOB_APPEND; | ||
917 | i = prog->glob_result.gl_pathc; | ||
918 | } else { | ||
919 | prog->free_glob = 1; | ||
920 | flags = 0; | ||
921 | i = 0; | ||
922 | } | ||
923 | #ifdef BB_FEATURE_SH_ENVIRONMENT | 912 | #ifdef BB_FEATURE_SH_ENVIRONMENT |
924 | /* do shell variable substitution */ | 913 | |
925 | src = prog->argv[argc_l - 1]; | 914 | /* This first part uses wordexp() which is a wonderful C lib |
915 | * function which expands nearly everything. */ | ||
916 | |||
917 | retval = wordexp (command, &wrdexp, 0); | ||
918 | |||
919 | if (retval == WRDE_NOSPACE) { | ||
920 | /* Mem may have been allocated... */ | ||
921 | wordfree (&wrdexp); | ||
922 | error_msg("out of space during expansion"); | ||
923 | return FALSE; | ||
924 | } | ||
925 | if (retval < 0) { | ||
926 | /* Some other error. */ | ||
927 | error_msg("syntax error"); | ||
928 | return FALSE; | ||
929 | } | ||
930 | |||
931 | /* Convert from char** (one word per string) to a simple char*, | ||
932 | * but don't overflow command which is BUFSIZ in length */ | ||
933 | *command = '\0'; | ||
934 | while (i < wrdexp.we_wordc && total_length < BUFSIZ) { | ||
935 | length=strlen(wrdexp.we_wordv[i])+1; | ||
936 | if (BUFSIZ-total_length-length <= 0) { | ||
937 | error_msg("out of space during expansion"); | ||
938 | return FALSE; | ||
939 | } | ||
940 | strcat(command+total_length, wrdexp.we_wordv[i++]); | ||
941 | strcat(command+total_length, " "); | ||
942 | total_length+=length; | ||
943 | } | ||
944 | wordfree (&wrdexp); | ||
945 | |||
946 | |||
947 | /* Now do the shell variable substitutions which | ||
948 | * wordexp can't do for us, namely $? and $! */ | ||
949 | src = command; | ||
926 | while((dst = strchr(src,'$')) != NULL){ | 950 | while((dst = strchr(src,'$')) != NULL){ |
927 | if (!(var = getenv(dst + 1))) { | 951 | if (!(var = getenv(dst + 1))) { |
928 | switch(*(dst+1)) { | 952 | switch(*(dst+1)) { |
929 | case '?': | 953 | case '?': |
930 | var = itoa(last_return_code); | 954 | var = itoa(last_return_code); |
931 | break; | 955 | break; |
932 | case '$': | ||
933 | var = itoa(getpid()); | ||
934 | break; | ||
935 | case '#': | ||
936 | var = itoa(argc-1); | ||
937 | break; | ||
938 | case '!': | 956 | case '!': |
939 | if (last_bg_pid==-1) | 957 | if (last_bg_pid==-1) |
940 | *(var)='\0'; | 958 | *(var)='\0'; |
941 | else | 959 | else |
942 | var = itoa(last_bg_pid); | 960 | var = itoa(last_bg_pid); |
943 | break; | 961 | break; |
962 | #if 0 | ||
963 | /* Everything else like $$, $#, $[0-9], etcshould all be | ||
964 | * expanded by wordexp(), so we can skip that stuff here */ | ||
965 | case '$': | ||
966 | case '#': | ||
944 | case '0':case '1':case '2':case '3':case '4': | 967 | case '0':case '1':case '2':case '3':case '4': |
945 | case '5':case '6':case '7':case '8':case '9': | 968 | case '5':case '6':case '7':case '8':case '9': |
946 | { | ||
947 | int index=*(dst + 1)-48; | ||
948 | if (index >= argc) { | ||
949 | var='\0'; | ||
950 | } else { | ||
951 | var = argv[index]; | ||
952 | } | ||
953 | } | ||
954 | break; | 969 | break; |
970 | #endif | ||
955 | } | 971 | } |
956 | } | 972 | } |
957 | if (var) { | 973 | if (var) { |
958 | int offset = dst-src; | 974 | int subst_len = strlen(var); |
959 | #warning I have a memory leak which needs to be plugged somehow | 975 | char *next_dst; |
960 | src = (char*)xmalloc(strlen(src)-strlen(dst)+strlen(var)+1); | 976 | if ((next_dst=strpbrk(dst+1, " \t~`!$^&*()=|\\{}[];\"'<>?")) == NULL) { |
961 | strncpy(src, prog->argv[argc_l -1], offset); | 977 | next_dst = dst; |
962 | safe_strncpy(src+offset, var, strlen(var)+1); | ||
963 | /* If there are any remaining $ variables in the src string, put them back */ | ||
964 | if ((dst = strchr(prog->argv[argc_l -1]+offset+1,'$')) != NULL) { | ||
965 | offset=strlen(src); | ||
966 | safe_strncpy(src+strlen(src), dst, strlen(dst)+1); | ||
967 | } | 978 | } |
968 | prog->argv[argc_l -1] = src; | 979 | src = (char*)xrealloc(src, strlen(src) - strlen(next_dst)+strlen(var)+1); |
969 | } else { | 980 | /* Move stuff to the end of the string to accommodate filling |
970 | memset(dst, 0, strlen(src)-strlen(dst)); | 981 | * the created gap with the new stuff */ |
982 | memmove(dst+subst_len, next_dst+1, subst_len); | ||
983 | /* Now copy in the new stuff */ | ||
984 | strncpy(dst, var, subst_len); | ||
971 | } | 985 | } |
986 | src = dst; | ||
987 | src++; | ||
972 | } | 988 | } |
973 | #endif | ||
974 | 989 | ||
975 | if (strpbrk(prog->argv[argc_l - 1],"*[]?")!= NULL){ | 990 | |
976 | rc = glob(prog->argv[argc_l - 1], flags, NULL, &prog->glob_result); | 991 | |
977 | if (rc == GLOB_NOSPACE) { | 992 | |
978 | error_msg("out of space during glob operation"); | 993 | #endif |
979 | return; | 994 | return TRUE; |
980 | } else if (rc == GLOB_NOMATCH || | ||
981 | (!rc && (prog->glob_result.gl_pathc - i) == 1 && | ||
982 | strcmp(prog->argv[argc_l - 1], | ||
983 | prog->glob_result.gl_pathv[i]) == 0)) { | ||
984 | /* we need to remove whatever \ quoting is still present */ | ||
985 | src = dst = prog->argv[argc_l - 1]; | ||
986 | while (*src) { | ||
987 | if (*src == '\\') { | ||
988 | src++; | ||
989 | *dst++ = process_escape_sequence(&src); | ||
990 | } else { | ||
991 | *dst++ = *src; | ||
992 | src++; | ||
993 | } | ||
994 | } | ||
995 | *dst = '\0'; | ||
996 | } else if (!rc) { | ||
997 | argv_alloced += (prog->glob_result.gl_pathc - i); | ||
998 | prog->argv = xrealloc(prog->argv, argv_alloced * sizeof(*prog->argv)); | ||
999 | memcpy(prog->argv + (argc_l - 1), prog->glob_result.gl_pathv + i, | ||
1000 | sizeof(*(prog->argv)) * (prog->glob_result.gl_pathc - i)); | ||
1001 | argc_l += (prog->glob_result.gl_pathc - i - 1); | ||
1002 | } | ||
1003 | }else{ | ||
1004 | src = dst = prog->argv[argc_l - 1]; | ||
1005 | while (*src) { | ||
1006 | if (*src == '\\') { | ||
1007 | src++; | ||
1008 | *dst++ = process_escape_sequence(&src); | ||
1009 | } else { | ||
1010 | *dst++ = *src; | ||
1011 | src++; | ||
1012 | } | ||
1013 | } | ||
1014 | *dst = '\0'; | ||
1015 | |||
1016 | prog->glob_result.gl_pathc=0; | ||
1017 | if (flags==0) | ||
1018 | prog->glob_result.gl_pathv=NULL; | ||
1019 | } | ||
1020 | *argv_alloced_ptr = argv_alloced; | ||
1021 | *argcPtr = argc_l; | ||
1022 | } | 995 | } |
1023 | 996 | ||
1024 | /* Return cmd->num_progs as 0 if no command is present (e.g. an empty | 997 | /* Return cmd->num_progs as 0 if no command is present (e.g. an empty |
@@ -1066,7 +1039,6 @@ static int parse_command(char **command_ptr, struct job *job, int *inbg) | |||
1066 | prog = job->progs; | 1039 | prog = job->progs; |
1067 | prog->num_redirects = 0; | 1040 | prog->num_redirects = 0; |
1068 | prog->redirects = NULL; | 1041 | prog->redirects = NULL; |
1069 | prog->free_glob = 0; | ||
1070 | prog->is_stopped = 0; | 1042 | prog->is_stopped = 0; |
1071 | prog->family = job; | 1043 | prog->family = job; |
1072 | 1044 | ||
@@ -1106,7 +1078,6 @@ static int parse_command(char **command_ptr, struct job *job, int *inbg) | |||
1106 | sizeof(*prog->argv) * | 1078 | sizeof(*prog->argv) * |
1107 | argv_alloced); | 1079 | argv_alloced); |
1108 | } | 1080 | } |
1109 | expand_argument(prog, &argc_l, &argv_alloced); | ||
1110 | prog->argv[argc_l] = buf; | 1081 | prog->argv[argc_l] = buf; |
1111 | } | 1082 | } |
1112 | } else | 1083 | } else |
@@ -1139,7 +1110,6 @@ static int parse_command(char **command_ptr, struct job *job, int *inbg) | |||
1139 | 1110 | ||
1140 | if (*chptr && *prog->argv[argc_l]) { | 1111 | if (*chptr && *prog->argv[argc_l]) { |
1141 | buf++, argc_l++; | 1112 | buf++, argc_l++; |
1142 | expand_argument(prog, &argc_l, &argv_alloced); | ||
1143 | prog->argv[argc_l] = buf; | 1113 | prog->argv[argc_l] = buf; |
1144 | } | 1114 | } |
1145 | } | 1115 | } |
@@ -1200,7 +1170,6 @@ static int parse_command(char **command_ptr, struct job *job, int *inbg) | |||
1200 | prog = job->progs + (job->num_progs - 1); | 1170 | prog = job->progs + (job->num_progs - 1); |
1201 | prog->num_redirects = 0; | 1171 | prog->num_redirects = 0; |
1202 | prog->redirects = NULL; | 1172 | prog->redirects = NULL; |
1203 | prog->free_glob = 0; | ||
1204 | prog->is_stopped = 0; | 1173 | prog->is_stopped = 0; |
1205 | prog->family = job; | 1174 | prog->family = job; |
1206 | argc_l = 0; | 1175 | argc_l = 0; |
@@ -1356,7 +1325,6 @@ static int parse_command(char **command_ptr, struct job *job, int *inbg) | |||
1356 | 1325 | ||
1357 | if (*prog->argv[argc_l]) { | 1326 | if (*prog->argv[argc_l]) { |
1358 | argc_l++; | 1327 | argc_l++; |
1359 | expand_argument(prog, &argc_l, &argv_alloced); | ||
1360 | } | 1328 | } |
1361 | if (!argc_l) { | 1329 | if (!argc_l) { |
1362 | free_job(job); | 1330 | free_job(job); |
@@ -1624,6 +1592,13 @@ static int busy_loop(FILE * input) | |||
1624 | next_command = command; | 1592 | next_command = command; |
1625 | } | 1593 | } |
1626 | 1594 | ||
1595 | if (expand_arguments(next_command) == FALSE) { | ||
1596 | free(command); | ||
1597 | command = (char *) xcalloc(BUFSIZ, sizeof(char)); | ||
1598 | next_command = NULL; | ||
1599 | continue; | ||
1600 | } | ||
1601 | |||
1627 | if (!parse_command(&next_command, &newjob, &inbg) && | 1602 | if (!parse_command(&next_command, &newjob, &inbg) && |
1628 | newjob.num_progs) { | 1603 | newjob.num_progs) { |
1629 | int pipefds[2] = {-1,-1}; | 1604 | int pipefds[2] = {-1,-1}; |
@@ -1723,8 +1698,8 @@ int shell_main(int argc_l, char **argv_l) | |||
1723 | job_list.head = NULL; | 1698 | job_list.head = NULL; |
1724 | job_list.fg = NULL; | 1699 | job_list.fg = NULL; |
1725 | #ifdef BB_FEATURE_SH_ENVIRONMENT | 1700 | #ifdef BB_FEATURE_SH_ENVIRONMENT |
1726 | last_bg_pid=-1; | 1701 | last_bg_pid=1; |
1727 | last_return_code=-1; | 1702 | last_return_code=1; |
1728 | show_x_trace=FALSE; | 1703 | show_x_trace=FALSE; |
1729 | #endif | 1704 | #endif |
1730 | 1705 | ||
@@ -54,7 +54,7 @@ | |||
54 | #include <ctype.h> | 54 | #include <ctype.h> |
55 | #include <errno.h> | 55 | #include <errno.h> |
56 | #include <fcntl.h> | 56 | #include <fcntl.h> |
57 | #include <glob.h> | 57 | #include <wordexp.h> |
58 | #include <signal.h> | 58 | #include <signal.h> |
59 | #include <string.h> | 59 | #include <string.h> |
60 | #include <sys/ioctl.h> | 60 | #include <sys/ioctl.h> |
@@ -96,8 +96,6 @@ struct child_prog { | |||
96 | char **argv; /* program name and arguments */ | 96 | char **argv; /* program name and arguments */ |
97 | int num_redirects; /* elements in redirection array */ | 97 | int num_redirects; /* elements in redirection array */ |
98 | struct redir_struct *redirects; /* I/O redirects */ | 98 | struct redir_struct *redirects; /* I/O redirects */ |
99 | glob_t glob_result; /* result of parameter globbing */ | ||
100 | int free_glob; /* should we globfree(&glob_result)? */ | ||
101 | int is_stopped; /* is the program currently running? */ | 99 | int is_stopped; /* is the program currently running? */ |
102 | struct job *family; /* pointer back to the child's parent job */ | 100 | struct job *family; /* pointer back to the child's parent job */ |
103 | }; | 101 | }; |
@@ -209,9 +207,9 @@ static int argc; | |||
209 | static char **argv; | 207 | static char **argv; |
210 | static struct close_me *close_me_head; | 208 | static struct close_me *close_me_head; |
211 | #ifdef BB_FEATURE_SH_ENVIRONMENT | 209 | #ifdef BB_FEATURE_SH_ENVIRONMENT |
212 | static int last_bg_pid=-1; | 210 | static int last_bg_pid; |
213 | static int last_return_code=-1; | 211 | static int last_return_code; |
214 | static int show_x_trace=FALSE; | 212 | static int show_x_trace; |
215 | #endif | 213 | #endif |
216 | #ifdef BB_FEATURE_SH_IF_EXPRESSIONS | 214 | #ifdef BB_FEATURE_SH_IF_EXPRESSIONS |
217 | static char syntax_err[]="syntax error near unexpected token"; | 215 | static char syntax_err[]="syntax error near unexpected token"; |
@@ -650,8 +648,6 @@ static void free_job(struct job *cmd) | |||
650 | free(cmd->progs[i].argv); | 648 | free(cmd->progs[i].argv); |
651 | if (cmd->progs[i].redirects) | 649 | if (cmd->progs[i].redirects) |
652 | free(cmd->progs[i].redirects); | 650 | free(cmd->progs[i].redirects); |
653 | if (cmd->progs[i].free_glob) | ||
654 | globfree(&cmd->progs[i].glob_result); | ||
655 | } | 651 | } |
656 | free(cmd->progs); | 652 | free(cmd->progs); |
657 | if (cmd->text) | 653 | if (cmd->text) |
@@ -875,7 +871,7 @@ static int get_command(FILE * source, char *command) | |||
875 | } | 871 | } |
876 | 872 | ||
877 | /* remove trailing newline */ | 873 | /* remove trailing newline */ |
878 | command[strlen(command) - 1] = '\0'; | 874 | chomp(command); |
879 | 875 | ||
880 | return 0; | 876 | return 0; |
881 | } | 877 | } |
@@ -900,125 +896,102 @@ static char* itoa(register int i) | |||
900 | *--b = '-'; | 896 | *--b = '-'; |
901 | return b; | 897 | return b; |
902 | } | 898 | } |
903 | #endif | 899 | #endif |
904 | 900 | ||
905 | static void expand_argument(struct child_prog *prog, int *argcPtr, | 901 | static int expand_arguments(char *command) |
906 | int *argv_alloced_ptr) | ||
907 | { | 902 | { |
908 | int argc_l = *argcPtr; | 903 | #ifdef BB_FEATURE_SH_ENVIRONMENT |
909 | int argv_alloced = *argv_alloced_ptr; | 904 | wordexp_t wrdexp; |
910 | int rc; | ||
911 | int flags; | ||
912 | int i; | ||
913 | char *src, *dst, *var; | 905 | char *src, *dst, *var; |
906 | int i=0, length, total_length=0, retval; | ||
907 | #endif | ||
908 | |||
909 | /* get rid of the terminating \n */ | ||
910 | chomp(command); | ||
914 | 911 | ||
915 | if (argc_l > 1) { /* cmd->glob_result is already initialized */ | ||
916 | flags = GLOB_APPEND; | ||
917 | i = prog->glob_result.gl_pathc; | ||
918 | } else { | ||
919 | prog->free_glob = 1; | ||
920 | flags = 0; | ||
921 | i = 0; | ||
922 | } | ||
923 | #ifdef BB_FEATURE_SH_ENVIRONMENT | 912 | #ifdef BB_FEATURE_SH_ENVIRONMENT |
924 | /* do shell variable substitution */ | 913 | |
925 | src = prog->argv[argc_l - 1]; | 914 | /* This first part uses wordexp() which is a wonderful C lib |
915 | * function which expands nearly everything. */ | ||
916 | |||
917 | retval = wordexp (command, &wrdexp, 0); | ||
918 | |||
919 | if (retval == WRDE_NOSPACE) { | ||
920 | /* Mem may have been allocated... */ | ||
921 | wordfree (&wrdexp); | ||
922 | error_msg("out of space during expansion"); | ||
923 | return FALSE; | ||
924 | } | ||
925 | if (retval < 0) { | ||
926 | /* Some other error. */ | ||
927 | error_msg("syntax error"); | ||
928 | return FALSE; | ||
929 | } | ||
930 | |||
931 | /* Convert from char** (one word per string) to a simple char*, | ||
932 | * but don't overflow command which is BUFSIZ in length */ | ||
933 | *command = '\0'; | ||
934 | while (i < wrdexp.we_wordc && total_length < BUFSIZ) { | ||
935 | length=strlen(wrdexp.we_wordv[i])+1; | ||
936 | if (BUFSIZ-total_length-length <= 0) { | ||
937 | error_msg("out of space during expansion"); | ||
938 | return FALSE; | ||
939 | } | ||
940 | strcat(command+total_length, wrdexp.we_wordv[i++]); | ||
941 | strcat(command+total_length, " "); | ||
942 | total_length+=length; | ||
943 | } | ||
944 | wordfree (&wrdexp); | ||
945 | |||
946 | |||
947 | /* Now do the shell variable substitutions which | ||
948 | * wordexp can't do for us, namely $? and $! */ | ||
949 | src = command; | ||
926 | while((dst = strchr(src,'$')) != NULL){ | 950 | while((dst = strchr(src,'$')) != NULL){ |
927 | if (!(var = getenv(dst + 1))) { | 951 | if (!(var = getenv(dst + 1))) { |
928 | switch(*(dst+1)) { | 952 | switch(*(dst+1)) { |
929 | case '?': | 953 | case '?': |
930 | var = itoa(last_return_code); | 954 | var = itoa(last_return_code); |
931 | break; | 955 | break; |
932 | case '$': | ||
933 | var = itoa(getpid()); | ||
934 | break; | ||
935 | case '#': | ||
936 | var = itoa(argc-1); | ||
937 | break; | ||
938 | case '!': | 956 | case '!': |
939 | if (last_bg_pid==-1) | 957 | if (last_bg_pid==-1) |
940 | *(var)='\0'; | 958 | *(var)='\0'; |
941 | else | 959 | else |
942 | var = itoa(last_bg_pid); | 960 | var = itoa(last_bg_pid); |
943 | break; | 961 | break; |
962 | #if 0 | ||
963 | /* Everything else like $$, $#, $[0-9], etcshould all be | ||
964 | * expanded by wordexp(), so we can skip that stuff here */ | ||
965 | case '$': | ||
966 | case '#': | ||
944 | case '0':case '1':case '2':case '3':case '4': | 967 | case '0':case '1':case '2':case '3':case '4': |
945 | case '5':case '6':case '7':case '8':case '9': | 968 | case '5':case '6':case '7':case '8':case '9': |
946 | { | ||
947 | int index=*(dst + 1)-48; | ||
948 | if (index >= argc) { | ||
949 | var='\0'; | ||
950 | } else { | ||
951 | var = argv[index]; | ||
952 | } | ||
953 | } | ||
954 | break; | 969 | break; |
970 | #endif | ||
955 | } | 971 | } |
956 | } | 972 | } |
957 | if (var) { | 973 | if (var) { |
958 | int offset = dst-src; | 974 | int subst_len = strlen(var); |
959 | #warning I have a memory leak which needs to be plugged somehow | 975 | char *next_dst; |
960 | src = (char*)xmalloc(strlen(src)-strlen(dst)+strlen(var)+1); | 976 | if ((next_dst=strpbrk(dst+1, " \t~`!$^&*()=|\\{}[];\"'<>?")) == NULL) { |
961 | strncpy(src, prog->argv[argc_l -1], offset); | 977 | next_dst = dst; |
962 | safe_strncpy(src+offset, var, strlen(var)+1); | ||
963 | /* If there are any remaining $ variables in the src string, put them back */ | ||
964 | if ((dst = strchr(prog->argv[argc_l -1]+offset+1,'$')) != NULL) { | ||
965 | offset=strlen(src); | ||
966 | safe_strncpy(src+strlen(src), dst, strlen(dst)+1); | ||
967 | } | 978 | } |
968 | prog->argv[argc_l -1] = src; | 979 | src = (char*)xrealloc(src, strlen(src) - strlen(next_dst)+strlen(var)+1); |
969 | } else { | 980 | /* Move stuff to the end of the string to accommodate filling |
970 | memset(dst, 0, strlen(src)-strlen(dst)); | 981 | * the created gap with the new stuff */ |
982 | memmove(dst+subst_len, next_dst+1, subst_len); | ||
983 | /* Now copy in the new stuff */ | ||
984 | strncpy(dst, var, subst_len); | ||
971 | } | 985 | } |
986 | src = dst; | ||
987 | src++; | ||
972 | } | 988 | } |
973 | #endif | ||
974 | 989 | ||
975 | if (strpbrk(prog->argv[argc_l - 1],"*[]?")!= NULL){ | 990 | |
976 | rc = glob(prog->argv[argc_l - 1], flags, NULL, &prog->glob_result); | 991 | |
977 | if (rc == GLOB_NOSPACE) { | 992 | |
978 | error_msg("out of space during glob operation"); | 993 | #endif |
979 | return; | 994 | return TRUE; |
980 | } else if (rc == GLOB_NOMATCH || | ||
981 | (!rc && (prog->glob_result.gl_pathc - i) == 1 && | ||
982 | strcmp(prog->argv[argc_l - 1], | ||
983 | prog->glob_result.gl_pathv[i]) == 0)) { | ||
984 | /* we need to remove whatever \ quoting is still present */ | ||
985 | src = dst = prog->argv[argc_l - 1]; | ||
986 | while (*src) { | ||
987 | if (*src == '\\') { | ||
988 | src++; | ||
989 | *dst++ = process_escape_sequence(&src); | ||
990 | } else { | ||
991 | *dst++ = *src; | ||
992 | src++; | ||
993 | } | ||
994 | } | ||
995 | *dst = '\0'; | ||
996 | } else if (!rc) { | ||
997 | argv_alloced += (prog->glob_result.gl_pathc - i); | ||
998 | prog->argv = xrealloc(prog->argv, argv_alloced * sizeof(*prog->argv)); | ||
999 | memcpy(prog->argv + (argc_l - 1), prog->glob_result.gl_pathv + i, | ||
1000 | sizeof(*(prog->argv)) * (prog->glob_result.gl_pathc - i)); | ||
1001 | argc_l += (prog->glob_result.gl_pathc - i - 1); | ||
1002 | } | ||
1003 | }else{ | ||
1004 | src = dst = prog->argv[argc_l - 1]; | ||
1005 | while (*src) { | ||
1006 | if (*src == '\\') { | ||
1007 | src++; | ||
1008 | *dst++ = process_escape_sequence(&src); | ||
1009 | } else { | ||
1010 | *dst++ = *src; | ||
1011 | src++; | ||
1012 | } | ||
1013 | } | ||
1014 | *dst = '\0'; | ||
1015 | |||
1016 | prog->glob_result.gl_pathc=0; | ||
1017 | if (flags==0) | ||
1018 | prog->glob_result.gl_pathv=NULL; | ||
1019 | } | ||
1020 | *argv_alloced_ptr = argv_alloced; | ||
1021 | *argcPtr = argc_l; | ||
1022 | } | 995 | } |
1023 | 996 | ||
1024 | /* Return cmd->num_progs as 0 if no command is present (e.g. an empty | 997 | /* Return cmd->num_progs as 0 if no command is present (e.g. an empty |
@@ -1066,7 +1039,6 @@ static int parse_command(char **command_ptr, struct job *job, int *inbg) | |||
1066 | prog = job->progs; | 1039 | prog = job->progs; |
1067 | prog->num_redirects = 0; | 1040 | prog->num_redirects = 0; |
1068 | prog->redirects = NULL; | 1041 | prog->redirects = NULL; |
1069 | prog->free_glob = 0; | ||
1070 | prog->is_stopped = 0; | 1042 | prog->is_stopped = 0; |
1071 | prog->family = job; | 1043 | prog->family = job; |
1072 | 1044 | ||
@@ -1106,7 +1078,6 @@ static int parse_command(char **command_ptr, struct job *job, int *inbg) | |||
1106 | sizeof(*prog->argv) * | 1078 | sizeof(*prog->argv) * |
1107 | argv_alloced); | 1079 | argv_alloced); |
1108 | } | 1080 | } |
1109 | expand_argument(prog, &argc_l, &argv_alloced); | ||
1110 | prog->argv[argc_l] = buf; | 1081 | prog->argv[argc_l] = buf; |
1111 | } | 1082 | } |
1112 | } else | 1083 | } else |
@@ -1139,7 +1110,6 @@ static int parse_command(char **command_ptr, struct job *job, int *inbg) | |||
1139 | 1110 | ||
1140 | if (*chptr && *prog->argv[argc_l]) { | 1111 | if (*chptr && *prog->argv[argc_l]) { |
1141 | buf++, argc_l++; | 1112 | buf++, argc_l++; |
1142 | expand_argument(prog, &argc_l, &argv_alloced); | ||
1143 | prog->argv[argc_l] = buf; | 1113 | prog->argv[argc_l] = buf; |
1144 | } | 1114 | } |
1145 | } | 1115 | } |
@@ -1200,7 +1170,6 @@ static int parse_command(char **command_ptr, struct job *job, int *inbg) | |||
1200 | prog = job->progs + (job->num_progs - 1); | 1170 | prog = job->progs + (job->num_progs - 1); |
1201 | prog->num_redirects = 0; | 1171 | prog->num_redirects = 0; |
1202 | prog->redirects = NULL; | 1172 | prog->redirects = NULL; |
1203 | prog->free_glob = 0; | ||
1204 | prog->is_stopped = 0; | 1173 | prog->is_stopped = 0; |
1205 | prog->family = job; | 1174 | prog->family = job; |
1206 | argc_l = 0; | 1175 | argc_l = 0; |
@@ -1356,7 +1325,6 @@ static int parse_command(char **command_ptr, struct job *job, int *inbg) | |||
1356 | 1325 | ||
1357 | if (*prog->argv[argc_l]) { | 1326 | if (*prog->argv[argc_l]) { |
1358 | argc_l++; | 1327 | argc_l++; |
1359 | expand_argument(prog, &argc_l, &argv_alloced); | ||
1360 | } | 1328 | } |
1361 | if (!argc_l) { | 1329 | if (!argc_l) { |
1362 | free_job(job); | 1330 | free_job(job); |
@@ -1624,6 +1592,13 @@ static int busy_loop(FILE * input) | |||
1624 | next_command = command; | 1592 | next_command = command; |
1625 | } | 1593 | } |
1626 | 1594 | ||
1595 | if (expand_arguments(next_command) == FALSE) { | ||
1596 | free(command); | ||
1597 | command = (char *) xcalloc(BUFSIZ, sizeof(char)); | ||
1598 | next_command = NULL; | ||
1599 | continue; | ||
1600 | } | ||
1601 | |||
1627 | if (!parse_command(&next_command, &newjob, &inbg) && | 1602 | if (!parse_command(&next_command, &newjob, &inbg) && |
1628 | newjob.num_progs) { | 1603 | newjob.num_progs) { |
1629 | int pipefds[2] = {-1,-1}; | 1604 | int pipefds[2] = {-1,-1}; |
@@ -1723,8 +1698,8 @@ int shell_main(int argc_l, char **argv_l) | |||
1723 | job_list.head = NULL; | 1698 | job_list.head = NULL; |
1724 | job_list.fg = NULL; | 1699 | job_list.fg = NULL; |
1725 | #ifdef BB_FEATURE_SH_ENVIRONMENT | 1700 | #ifdef BB_FEATURE_SH_ENVIRONMENT |
1726 | last_bg_pid=-1; | 1701 | last_bg_pid=1; |
1727 | last_return_code=-1; | 1702 | last_return_code=1; |
1728 | show_x_trace=FALSE; | 1703 | show_x_trace=FALSE; |
1729 | #endif | 1704 | #endif |
1730 | 1705 | ||
diff --git a/shell/lash.c b/shell/lash.c index 150055bb1..874c0aca9 100644 --- a/shell/lash.c +++ b/shell/lash.c | |||
@@ -54,7 +54,7 @@ | |||
54 | #include <ctype.h> | 54 | #include <ctype.h> |
55 | #include <errno.h> | 55 | #include <errno.h> |
56 | #include <fcntl.h> | 56 | #include <fcntl.h> |
57 | #include <glob.h> | 57 | #include <wordexp.h> |
58 | #include <signal.h> | 58 | #include <signal.h> |
59 | #include <string.h> | 59 | #include <string.h> |
60 | #include <sys/ioctl.h> | 60 | #include <sys/ioctl.h> |
@@ -96,8 +96,6 @@ struct child_prog { | |||
96 | char **argv; /* program name and arguments */ | 96 | char **argv; /* program name and arguments */ |
97 | int num_redirects; /* elements in redirection array */ | 97 | int num_redirects; /* elements in redirection array */ |
98 | struct redir_struct *redirects; /* I/O redirects */ | 98 | struct redir_struct *redirects; /* I/O redirects */ |
99 | glob_t glob_result; /* result of parameter globbing */ | ||
100 | int free_glob; /* should we globfree(&glob_result)? */ | ||
101 | int is_stopped; /* is the program currently running? */ | 99 | int is_stopped; /* is the program currently running? */ |
102 | struct job *family; /* pointer back to the child's parent job */ | 100 | struct job *family; /* pointer back to the child's parent job */ |
103 | }; | 101 | }; |
@@ -209,9 +207,9 @@ static int argc; | |||
209 | static char **argv; | 207 | static char **argv; |
210 | static struct close_me *close_me_head; | 208 | static struct close_me *close_me_head; |
211 | #ifdef BB_FEATURE_SH_ENVIRONMENT | 209 | #ifdef BB_FEATURE_SH_ENVIRONMENT |
212 | static int last_bg_pid=-1; | 210 | static int last_bg_pid; |
213 | static int last_return_code=-1; | 211 | static int last_return_code; |
214 | static int show_x_trace=FALSE; | 212 | static int show_x_trace; |
215 | #endif | 213 | #endif |
216 | #ifdef BB_FEATURE_SH_IF_EXPRESSIONS | 214 | #ifdef BB_FEATURE_SH_IF_EXPRESSIONS |
217 | static char syntax_err[]="syntax error near unexpected token"; | 215 | static char syntax_err[]="syntax error near unexpected token"; |
@@ -650,8 +648,6 @@ static void free_job(struct job *cmd) | |||
650 | free(cmd->progs[i].argv); | 648 | free(cmd->progs[i].argv); |
651 | if (cmd->progs[i].redirects) | 649 | if (cmd->progs[i].redirects) |
652 | free(cmd->progs[i].redirects); | 650 | free(cmd->progs[i].redirects); |
653 | if (cmd->progs[i].free_glob) | ||
654 | globfree(&cmd->progs[i].glob_result); | ||
655 | } | 651 | } |
656 | free(cmd->progs); | 652 | free(cmd->progs); |
657 | if (cmd->text) | 653 | if (cmd->text) |
@@ -875,7 +871,7 @@ static int get_command(FILE * source, char *command) | |||
875 | } | 871 | } |
876 | 872 | ||
877 | /* remove trailing newline */ | 873 | /* remove trailing newline */ |
878 | command[strlen(command) - 1] = '\0'; | 874 | chomp(command); |
879 | 875 | ||
880 | return 0; | 876 | return 0; |
881 | } | 877 | } |
@@ -900,125 +896,102 @@ static char* itoa(register int i) | |||
900 | *--b = '-'; | 896 | *--b = '-'; |
901 | return b; | 897 | return b; |
902 | } | 898 | } |
903 | #endif | 899 | #endif |
904 | 900 | ||
905 | static void expand_argument(struct child_prog *prog, int *argcPtr, | 901 | static int expand_arguments(char *command) |
906 | int *argv_alloced_ptr) | ||
907 | { | 902 | { |
908 | int argc_l = *argcPtr; | 903 | #ifdef BB_FEATURE_SH_ENVIRONMENT |
909 | int argv_alloced = *argv_alloced_ptr; | 904 | wordexp_t wrdexp; |
910 | int rc; | ||
911 | int flags; | ||
912 | int i; | ||
913 | char *src, *dst, *var; | 905 | char *src, *dst, *var; |
906 | int i=0, length, total_length=0, retval; | ||
907 | #endif | ||
908 | |||
909 | /* get rid of the terminating \n */ | ||
910 | chomp(command); | ||
914 | 911 | ||
915 | if (argc_l > 1) { /* cmd->glob_result is already initialized */ | ||
916 | flags = GLOB_APPEND; | ||
917 | i = prog->glob_result.gl_pathc; | ||
918 | } else { | ||
919 | prog->free_glob = 1; | ||
920 | flags = 0; | ||
921 | i = 0; | ||
922 | } | ||
923 | #ifdef BB_FEATURE_SH_ENVIRONMENT | 912 | #ifdef BB_FEATURE_SH_ENVIRONMENT |
924 | /* do shell variable substitution */ | 913 | |
925 | src = prog->argv[argc_l - 1]; | 914 | /* This first part uses wordexp() which is a wonderful C lib |
915 | * function which expands nearly everything. */ | ||
916 | |||
917 | retval = wordexp (command, &wrdexp, 0); | ||
918 | |||
919 | if (retval == WRDE_NOSPACE) { | ||
920 | /* Mem may have been allocated... */ | ||
921 | wordfree (&wrdexp); | ||
922 | error_msg("out of space during expansion"); | ||
923 | return FALSE; | ||
924 | } | ||
925 | if (retval < 0) { | ||
926 | /* Some other error. */ | ||
927 | error_msg("syntax error"); | ||
928 | return FALSE; | ||
929 | } | ||
930 | |||
931 | /* Convert from char** (one word per string) to a simple char*, | ||
932 | * but don't overflow command which is BUFSIZ in length */ | ||
933 | *command = '\0'; | ||
934 | while (i < wrdexp.we_wordc && total_length < BUFSIZ) { | ||
935 | length=strlen(wrdexp.we_wordv[i])+1; | ||
936 | if (BUFSIZ-total_length-length <= 0) { | ||
937 | error_msg("out of space during expansion"); | ||
938 | return FALSE; | ||
939 | } | ||
940 | strcat(command+total_length, wrdexp.we_wordv[i++]); | ||
941 | strcat(command+total_length, " "); | ||
942 | total_length+=length; | ||
943 | } | ||
944 | wordfree (&wrdexp); | ||
945 | |||
946 | |||
947 | /* Now do the shell variable substitutions which | ||
948 | * wordexp can't do for us, namely $? and $! */ | ||
949 | src = command; | ||
926 | while((dst = strchr(src,'$')) != NULL){ | 950 | while((dst = strchr(src,'$')) != NULL){ |
927 | if (!(var = getenv(dst + 1))) { | 951 | if (!(var = getenv(dst + 1))) { |
928 | switch(*(dst+1)) { | 952 | switch(*(dst+1)) { |
929 | case '?': | 953 | case '?': |
930 | var = itoa(last_return_code); | 954 | var = itoa(last_return_code); |
931 | break; | 955 | break; |
932 | case '$': | ||
933 | var = itoa(getpid()); | ||
934 | break; | ||
935 | case '#': | ||
936 | var = itoa(argc-1); | ||
937 | break; | ||
938 | case '!': | 956 | case '!': |
939 | if (last_bg_pid==-1) | 957 | if (last_bg_pid==-1) |
940 | *(var)='\0'; | 958 | *(var)='\0'; |
941 | else | 959 | else |
942 | var = itoa(last_bg_pid); | 960 | var = itoa(last_bg_pid); |
943 | break; | 961 | break; |
962 | #if 0 | ||
963 | /* Everything else like $$, $#, $[0-9], etcshould all be | ||
964 | * expanded by wordexp(), so we can skip that stuff here */ | ||
965 | case '$': | ||
966 | case '#': | ||
944 | case '0':case '1':case '2':case '3':case '4': | 967 | case '0':case '1':case '2':case '3':case '4': |
945 | case '5':case '6':case '7':case '8':case '9': | 968 | case '5':case '6':case '7':case '8':case '9': |
946 | { | ||
947 | int index=*(dst + 1)-48; | ||
948 | if (index >= argc) { | ||
949 | var='\0'; | ||
950 | } else { | ||
951 | var = argv[index]; | ||
952 | } | ||
953 | } | ||
954 | break; | 969 | break; |
970 | #endif | ||
955 | } | 971 | } |
956 | } | 972 | } |
957 | if (var) { | 973 | if (var) { |
958 | int offset = dst-src; | 974 | int subst_len = strlen(var); |
959 | #warning I have a memory leak which needs to be plugged somehow | 975 | char *next_dst; |
960 | src = (char*)xmalloc(strlen(src)-strlen(dst)+strlen(var)+1); | 976 | if ((next_dst=strpbrk(dst+1, " \t~`!$^&*()=|\\{}[];\"'<>?")) == NULL) { |
961 | strncpy(src, prog->argv[argc_l -1], offset); | 977 | next_dst = dst; |
962 | safe_strncpy(src+offset, var, strlen(var)+1); | ||
963 | /* If there are any remaining $ variables in the src string, put them back */ | ||
964 | if ((dst = strchr(prog->argv[argc_l -1]+offset+1,'$')) != NULL) { | ||
965 | offset=strlen(src); | ||
966 | safe_strncpy(src+strlen(src), dst, strlen(dst)+1); | ||
967 | } | 978 | } |
968 | prog->argv[argc_l -1] = src; | 979 | src = (char*)xrealloc(src, strlen(src) - strlen(next_dst)+strlen(var)+1); |
969 | } else { | 980 | /* Move stuff to the end of the string to accommodate filling |
970 | memset(dst, 0, strlen(src)-strlen(dst)); | 981 | * the created gap with the new stuff */ |
982 | memmove(dst+subst_len, next_dst+1, subst_len); | ||
983 | /* Now copy in the new stuff */ | ||
984 | strncpy(dst, var, subst_len); | ||
971 | } | 985 | } |
986 | src = dst; | ||
987 | src++; | ||
972 | } | 988 | } |
973 | #endif | ||
974 | 989 | ||
975 | if (strpbrk(prog->argv[argc_l - 1],"*[]?")!= NULL){ | 990 | |
976 | rc = glob(prog->argv[argc_l - 1], flags, NULL, &prog->glob_result); | 991 | |
977 | if (rc == GLOB_NOSPACE) { | 992 | |
978 | error_msg("out of space during glob operation"); | 993 | #endif |
979 | return; | 994 | return TRUE; |
980 | } else if (rc == GLOB_NOMATCH || | ||
981 | (!rc && (prog->glob_result.gl_pathc - i) == 1 && | ||
982 | strcmp(prog->argv[argc_l - 1], | ||
983 | prog->glob_result.gl_pathv[i]) == 0)) { | ||
984 | /* we need to remove whatever \ quoting is still present */ | ||
985 | src = dst = prog->argv[argc_l - 1]; | ||
986 | while (*src) { | ||
987 | if (*src == '\\') { | ||
988 | src++; | ||
989 | *dst++ = process_escape_sequence(&src); | ||
990 | } else { | ||
991 | *dst++ = *src; | ||
992 | src++; | ||
993 | } | ||
994 | } | ||
995 | *dst = '\0'; | ||
996 | } else if (!rc) { | ||
997 | argv_alloced += (prog->glob_result.gl_pathc - i); | ||
998 | prog->argv = xrealloc(prog->argv, argv_alloced * sizeof(*prog->argv)); | ||
999 | memcpy(prog->argv + (argc_l - 1), prog->glob_result.gl_pathv + i, | ||
1000 | sizeof(*(prog->argv)) * (prog->glob_result.gl_pathc - i)); | ||
1001 | argc_l += (prog->glob_result.gl_pathc - i - 1); | ||
1002 | } | ||
1003 | }else{ | ||
1004 | src = dst = prog->argv[argc_l - 1]; | ||
1005 | while (*src) { | ||
1006 | if (*src == '\\') { | ||
1007 | src++; | ||
1008 | *dst++ = process_escape_sequence(&src); | ||
1009 | } else { | ||
1010 | *dst++ = *src; | ||
1011 | src++; | ||
1012 | } | ||
1013 | } | ||
1014 | *dst = '\0'; | ||
1015 | |||
1016 | prog->glob_result.gl_pathc=0; | ||
1017 | if (flags==0) | ||
1018 | prog->glob_result.gl_pathv=NULL; | ||
1019 | } | ||
1020 | *argv_alloced_ptr = argv_alloced; | ||
1021 | *argcPtr = argc_l; | ||
1022 | } | 995 | } |
1023 | 996 | ||
1024 | /* Return cmd->num_progs as 0 if no command is present (e.g. an empty | 997 | /* Return cmd->num_progs as 0 if no command is present (e.g. an empty |
@@ -1066,7 +1039,6 @@ static int parse_command(char **command_ptr, struct job *job, int *inbg) | |||
1066 | prog = job->progs; | 1039 | prog = job->progs; |
1067 | prog->num_redirects = 0; | 1040 | prog->num_redirects = 0; |
1068 | prog->redirects = NULL; | 1041 | prog->redirects = NULL; |
1069 | prog->free_glob = 0; | ||
1070 | prog->is_stopped = 0; | 1042 | prog->is_stopped = 0; |
1071 | prog->family = job; | 1043 | prog->family = job; |
1072 | 1044 | ||
@@ -1106,7 +1078,6 @@ static int parse_command(char **command_ptr, struct job *job, int *inbg) | |||
1106 | sizeof(*prog->argv) * | 1078 | sizeof(*prog->argv) * |
1107 | argv_alloced); | 1079 | argv_alloced); |
1108 | } | 1080 | } |
1109 | expand_argument(prog, &argc_l, &argv_alloced); | ||
1110 | prog->argv[argc_l] = buf; | 1081 | prog->argv[argc_l] = buf; |
1111 | } | 1082 | } |
1112 | } else | 1083 | } else |
@@ -1139,7 +1110,6 @@ static int parse_command(char **command_ptr, struct job *job, int *inbg) | |||
1139 | 1110 | ||
1140 | if (*chptr && *prog->argv[argc_l]) { | 1111 | if (*chptr && *prog->argv[argc_l]) { |
1141 | buf++, argc_l++; | 1112 | buf++, argc_l++; |
1142 | expand_argument(prog, &argc_l, &argv_alloced); | ||
1143 | prog->argv[argc_l] = buf; | 1113 | prog->argv[argc_l] = buf; |
1144 | } | 1114 | } |
1145 | } | 1115 | } |
@@ -1200,7 +1170,6 @@ static int parse_command(char **command_ptr, struct job *job, int *inbg) | |||
1200 | prog = job->progs + (job->num_progs - 1); | 1170 | prog = job->progs + (job->num_progs - 1); |
1201 | prog->num_redirects = 0; | 1171 | prog->num_redirects = 0; |
1202 | prog->redirects = NULL; | 1172 | prog->redirects = NULL; |
1203 | prog->free_glob = 0; | ||
1204 | prog->is_stopped = 0; | 1173 | prog->is_stopped = 0; |
1205 | prog->family = job; | 1174 | prog->family = job; |
1206 | argc_l = 0; | 1175 | argc_l = 0; |
@@ -1356,7 +1325,6 @@ static int parse_command(char **command_ptr, struct job *job, int *inbg) | |||
1356 | 1325 | ||
1357 | if (*prog->argv[argc_l]) { | 1326 | if (*prog->argv[argc_l]) { |
1358 | argc_l++; | 1327 | argc_l++; |
1359 | expand_argument(prog, &argc_l, &argv_alloced); | ||
1360 | } | 1328 | } |
1361 | if (!argc_l) { | 1329 | if (!argc_l) { |
1362 | free_job(job); | 1330 | free_job(job); |
@@ -1624,6 +1592,13 @@ static int busy_loop(FILE * input) | |||
1624 | next_command = command; | 1592 | next_command = command; |
1625 | } | 1593 | } |
1626 | 1594 | ||
1595 | if (expand_arguments(next_command) == FALSE) { | ||
1596 | free(command); | ||
1597 | command = (char *) xcalloc(BUFSIZ, sizeof(char)); | ||
1598 | next_command = NULL; | ||
1599 | continue; | ||
1600 | } | ||
1601 | |||
1627 | if (!parse_command(&next_command, &newjob, &inbg) && | 1602 | if (!parse_command(&next_command, &newjob, &inbg) && |
1628 | newjob.num_progs) { | 1603 | newjob.num_progs) { |
1629 | int pipefds[2] = {-1,-1}; | 1604 | int pipefds[2] = {-1,-1}; |
@@ -1723,8 +1698,8 @@ int shell_main(int argc_l, char **argv_l) | |||
1723 | job_list.head = NULL; | 1698 | job_list.head = NULL; |
1724 | job_list.fg = NULL; | 1699 | job_list.fg = NULL; |
1725 | #ifdef BB_FEATURE_SH_ENVIRONMENT | 1700 | #ifdef BB_FEATURE_SH_ENVIRONMENT |
1726 | last_bg_pid=-1; | 1701 | last_bg_pid=1; |
1727 | last_return_code=-1; | 1702 | last_return_code=1; |
1728 | show_x_trace=FALSE; | 1703 | show_x_trace=FALSE; |
1729 | #endif | 1704 | #endif |
1730 | 1705 | ||
@@ -1815,7 +1815,7 @@ const char *make_human_readable_str(unsigned long val, unsigned long hr) | |||
1815 | } | 1815 | } |
1816 | #endif | 1816 | #endif |
1817 | 1817 | ||
1818 | #if defined(BB_GREP) || defined(BB_HOSTNAME) || defined(BB_SED) || defined(BB_TAR) || defined(BB_WGET) || defined(BB_XARGS) | 1818 | #if defined(BB_GREP) || defined(BB_HOSTNAME) || defined(BB_SED) || defined(BB_TAR) || defined(BB_WGET) || defined(BB_XARGS) || defined(BB_SH) |
1819 | void chomp(char *s) | 1819 | void chomp(char *s) |
1820 | { | 1820 | { |
1821 | size_t len = strlen(s); | 1821 | size_t len = strlen(s); |