aboutsummaryrefslogtreecommitdiff
path: root/sh.c
diff options
context:
space:
mode:
authorEric Andersen <andersen@codepoet.org>2001-03-09 19:21:37 +0000
committerEric Andersen <andersen@codepoet.org>2001-03-09 19:21:37 +0000
commit195743f195ad4a74735e4aec1d801c498a60f371 (patch)
tree0f7dbc3b592232f49a6696e46dded7b721289391 /sh.c
parenteba8ed71f08f334bc94ac8eeedcd998fcdd05897 (diff)
downloadbusybox-w32-195743f195ad4a74735e4aec1d801c498a60f371.tar.gz
busybox-w32-195743f195ad4a74735e4aec1d801c498a60f371.tar.bz2
busybox-w32-195743f195ad4a74735e4aec1d801c498a60f371.zip
Ok, sh.c should be working now. Many thanks to Larry Doolittle
for his timely help -- nearly all of the work in this patch is his. -Erik
Diffstat (limited to 'sh.c')
-rw-r--r--sh.c168
1 files changed, 83 insertions, 85 deletions
diff --git a/sh.c b/sh.c
index e1bdc875a..865f10b39 100644
--- a/sh.c
+++ b/sh.c
@@ -916,6 +916,7 @@ static int expand_arguments(char *command)
916 expand_t expand_result; 916 expand_t expand_result;
917 char *src, *dst, *var; 917 char *src, *dst, *var;
918 int i=0, length, total_length=0, retval; 918 int i=0, length, total_length=0, retval;
919 const char *out_of_space = "out of space during expansion";
919#endif 920#endif
920 921
921 /* get rid of the terminating \n */ 922 /* get rid of the terminating \n */
@@ -931,7 +932,7 @@ static int expand_arguments(char *command)
931 if (retval == WRDE_NOSPACE) { 932 if (retval == WRDE_NOSPACE) {
932 /* Mem may have been allocated... */ 933 /* Mem may have been allocated... */
933 wordfree (&expand_result); 934 wordfree (&expand_result);
934 error_msg("out of space during expansion"); 935 error_msg(out_of_space);
935 return FALSE; 936 return FALSE;
936 } 937 }
937 if (retval < 0) { 938 if (retval < 0) {
@@ -946,7 +947,7 @@ static int expand_arguments(char *command)
946 while (i < expand_result.we_wordc && total_length < BUFSIZ) { 947 while (i < expand_result.we_wordc && total_length < BUFSIZ) {
947 length=strlen(expand_result.we_wordv[i])+1; 948 length=strlen(expand_result.we_wordv[i])+1;
948 if (BUFSIZ-total_length-length <= 0) { 949 if (BUFSIZ-total_length-length <= 0) {
949 error_msg("out of space during expansion"); 950 error_msg(out_of_space);
950 return FALSE; 951 return FALSE;
951 } 952 }
952 strcat(command+total_length, expand_result.we_wordv[i++]); 953 strcat(command+total_length, expand_result.we_wordv[i++]);
@@ -956,139 +957,136 @@ static int expand_arguments(char *command)
956 wordfree (&expand_result); 957 wordfree (&expand_result);
957#else 958#else
958 959
959 /* Ok. They don't have glibc and they don't have uClibc. Chances are 960 /* Ok. They don't have a recent glibc and they don't have uClibc. Chances
960 * about 100% they don't have wordexp(), so instead, the best we can do is 961 * are about 100% they don't have wordexp(). So instead the best we can do
961 * use glob, which is better then nothing, but certainly not perfect */ 962 * is use glob and then fixup environment variables and such ourselves.
963 * This is better then nothing, but certainly not perfect */
962 964
963 /* It turns out that glob is very stupid. We have to feed it 965 /* It turns out that glob is very stupid. We have to feed it one word at a
964 * one word at a time since it can't cope with a full string. 966 * time since it can't cope with a full string. Here we convert command
965 * Here we convert command (char*) into cmd (char**, one word 967 * (char*) into cmd (char**, one word per string) */
966 * per string) */
967 { 968 {
968 969
969 int flags = GLOB_NOCHECK|GLOB_BRACE|GLOB_TILDE; 970 int flags = GLOB_NOCHECK|GLOB_BRACE|GLOB_TILDE;
970 char * tmpcmd; 971 char * tmpcmd;
971 /* We need a clean copy, so strsep can mess up the copy while 972 /* We need a clean copy, so strsep can mess up the copy while
972 * we write stuff into the original in a minute */ 973 * we write stuff into the original (in a minute) */
973 char * cmd = strdup(command); 974 char * cmd = strdup(command);
975 *command = '\0';
974 for (tmpcmd = cmd; (tmpcmd = strsep(&cmd, " \t")) != NULL;) { 976 for (tmpcmd = cmd; (tmpcmd = strsep(&cmd, " \t")) != NULL;) {
975 if (*tmpcmd == '\0') 977 if (*tmpcmd == '\0')
976 break; 978 break;
977 retval = glob(tmpcmd, flags, NULL, &expand_result); 979 retval = glob(tmpcmd, flags, NULL, &expand_result);
978 /* We can't haveGLOB_APPEND on the first glob call,
979 * so put it there now */
980 if (! (flags & GLOB_APPEND) )
981 flags |= GLOB_APPEND;
982
983 if (retval == GLOB_NOSPACE) { 980 if (retval == GLOB_NOSPACE) {
984 /* Mem may have been allocated... */ 981 /* Mem may have been allocated... */
985 globfree (&expand_result); 982 globfree (&expand_result);
986 error_msg("out of space during expansion"); 983 error_msg(out_of_space);
987 return FALSE; 984 return FALSE;
988 } 985 } else if (retval != 0) {
989 if (retval != 0 && retval != GLOB_NOMATCH) { 986 /* Some other error. GLOB_NOMATCH shouldn't
990 /* Some other error. */ 987 * happen because of the GLOB_NOCHECK flag in
988 * the glob call. */
991 error_msg("syntax error"); 989 error_msg("syntax error");
992 return FALSE; 990 return FALSE;
993 } 991 } else {
994
995 /* Convert from char** (one word per string) to a simple char*, 992 /* Convert from char** (one word per string) to a simple char*,
996 * but don't overflow command which is BUFSIZ in length */ 993 * but don't overflow command which is BUFSIZ in length */
997 if ( expand_result.gl_pathc > 1) { 994 for (i=0; i < expand_result.gl_pathc; i++) {
998 *command = '\0';
999 while (i < expand_result.gl_pathc && total_length < BUFSIZ) {
1000 length=strlen(expand_result.gl_pathv[i])+1; 995 length=strlen(expand_result.gl_pathv[i])+1;
1001 if (BUFSIZ-total_length-length <= 0) { 996 if (BUFSIZ-total_length-length <= 0) {
1002 error_msg("out of space during expansion"); 997 error_msg(out_of_space);
1003 return FALSE; 998 return FALSE;
1004 } 999 }
1005 strcat(command+total_length, expand_result.gl_pathv[i++]); 1000 strcat(command+total_length, expand_result.gl_pathv[i]);
1006 strcat(command+total_length, " "); 1001 strcat(command+total_length, " ");
1007 total_length+=length; 1002 total_length+=length;
1008 } 1003 }
1004 globfree (&expand_result);
1009 } 1005 }
1010 } 1006 }
1011
1012 free(cmd); 1007 free(cmd);
1013 globfree (&expand_result); 1008 trim(command);
1014 } 1009 }
1015 1010
1016#endif 1011#endif
1017 1012
1018 /* FIXME -- this routine (which is only used when folks
1019 * don't have a C library with wordexp) needs a bit of help
1020 * to handle things like 'echo $PATH$0' */
1021
1022 /* Now do the shell variable substitutions which 1013 /* Now do the shell variable substitutions which
1023 * wordexp can't do for us, namely $? and $! */ 1014 * wordexp can't do for us, namely $? and $! */
1024 src = command; 1015 src = command;
1025 while((dst = strchr(src,'$')) != NULL){ 1016 while((dst = strchr(src,'$')) != NULL){
1026 /* Ok -- got a $ -- now clean up any trailing mess */ 1017 printf("dollar '%s'\n", dst);
1027 trim(dst); 1018 var = NULL;
1028 if (!(var = getenv(dst + 1))) { 1019 switch(*(dst+1)) {
1029 switch(*(dst+1)) { 1020 case '?':
1030 case '?': 1021 var = itoa(last_return_code);
1031 var = itoa(last_return_code); 1022 break;
1032 break; 1023 case '!':
1033 case '!': 1024 if (last_bg_pid==-1)
1034 if (last_bg_pid==-1) 1025 *(var)='\0';
1035 *(var)='\0'; 1026 else
1036 else 1027 var = itoa(last_bg_pid);
1037 var = itoa(last_bg_pid); 1028 break;
1038 break;
1039 /* Everything else like $$, $#, $[0-9], etc should all be 1029 /* Everything else like $$, $#, $[0-9], etc should all be
1040 * expanded by wordexp(), so we can in theory skip that stuff 1030 * expanded by wordexp(), so we can in theory skip that stuff
1041 * here, but just to be on the safe side (i.e. since uClibc 1031 * here, but just to be on the safe side (i.e. since uClibc
1042 * wordexp doesn't do this stuff yet), lets leave it in for 1032 * wordexp doesn't do this stuff yet), lets leave it in for
1043 * now. */ 1033 * now. */
1044 case '$': 1034 case '$':
1045 var = itoa(getpid()); 1035 var = itoa(getpid());
1046 break; 1036 break;
1047 case '#': 1037 case '#':
1048 var = itoa(argc-1); 1038 var = itoa(argc-1);
1049 break; 1039 break;
1050 case '0':case '1':case '2':case '3':case '4': 1040 case '0':case '1':case '2':case '3':case '4':
1051 case '5':case '6':case '7':case '8':case '9': 1041 case '5':case '6':case '7':case '8':case '9':
1052 { 1042 {
1053 int index=*(dst + 1)-48; 1043 int index=*(dst + 1)-48;
1054 if (index >= argc) { 1044 if (index >= argc) {
1055 var='\0'; 1045 var='\0';
1056 } else { 1046 } else {
1057 var = argv[index]; 1047 var = argv[index];
1058 }
1059 } 1048 }
1060 break; 1049 }
1050 break;
1061 1051
1062 }
1063 } 1052 }
1064 if (var) { 1053 if (var) {
1065 int subst_len = strlen(var); 1054 /* a single character construction was found, and
1066 char *next_dst; 1055 * already handled in the case statement */
1067 if ((next_dst=strpbrk(dst+1, " \t~`!$^&*()=|\\{}[];\"'<>?.")) == NULL) { 1056 src=dst+2;
1068 next_dst = dst;
1069 }
1070 src = (char*)xrealloc(src, strlen(src) - strlen(next_dst)+strlen(var)+1);
1071 /* Move stuff to the end of the string to accommodate filling
1072 * the created gap with the new stuff */
1073 memmove(dst+subst_len, next_dst+1, subst_len);
1074 /* Now copy in the new stuff */
1075 strncpy(dst, var, subst_len+1);
1076 src = dst;
1077 src++;
1078 } else { 1057 } else {
1058 /* Looks like an environment variable */
1059 char delim_hold;
1060 src=strpbrk(dst+1, " \t~`!$^&*()=|\\{}[];\"'<>?.");
1061 if (src == NULL) {
1062 src = dst+strlen(dst);
1063 }
1064 delim_hold=*src;
1065 *src='\0'; /* temporary */
1066 var = getenv(dst + 1);
1067 *src=delim_hold;
1068 }
1069 if (var == NULL) {
1079 /* Seems we got an un-expandable variable. So delete it. */ 1070 /* Seems we got an un-expandable variable. So delete it. */
1080 char *next_dst; 1071 var = "";
1081 if ((next_dst=strpbrk(dst+1, " \t~`!$^&*()=|\\{}[];\"'<>?.")) == NULL) { 1072 }
1082 next_dst=dst+1+strlen(dst); 1073 {
1074 int subst_len = strlen(var);
1075 int trail_len = strlen(src);
1076 if (dst+subst_len+trail_len >= command+BUFSIZ) {
1077 error_msg(out_of_space);
1078 return FALSE;
1083 } 1079 }
1084 /* Move stuff to the end of the string to accommodate filling 1080 /* Move stuff to the end of the string to accommodate
1085 * the created gap with the new stuff */ 1081 * filling the created gap with the new stuff */
1086 memmove(dst, next_dst, next_dst-dst); 1082 memmove(dst+subst_len, src, trail_len);
1083 *(dst+subst_len+trail_len)='\0';
1084 /* Now copy in the new stuff */
1085 memcpy(dst, var, subst_len);
1086 src = dst+subst_len;
1087 } 1087 }
1088 } 1088 }
1089 1089 printf("expanded '%s'\n", command);
1090
1091
1092 1090
1093#endif 1091#endif
1094 return TRUE; 1092 return TRUE;