diff options
author | Ron Yorston <rmy@pobox.com> | 2018-02-26 10:08:50 +0000 |
---|---|---|
committer | Ron Yorston <rmy@pobox.com> | 2018-02-26 10:08:50 +0000 |
commit | 00f2d33f37da42e17e5d978958659c4899cb2f0a (patch) | |
tree | 5d43272aa7c6a4f3be2dd4f9e9d1edf3963ec69d | |
parent | 7288179d1218f8e0308455d4d58346aec268eb2e (diff) | |
download | busybox-w32-00f2d33f37da42e17e5d978958659c4899cb2f0a.tar.gz busybox-w32-00f2d33f37da42e17e5d978958659c4899cb2f0a.tar.bz2 busybox-w32-00f2d33f37da42e17e5d978958659c4899cb2f0a.zip |
win32: add support for batch files
Support batch files with .bat and .cmd extensions, similar to
what's done for .exe and .com.
Check extensions in the same order as Windows' spawn function:
.com, .exe, .bat, .cmd.
-rw-r--r-- | include/mingw.h | 1 | ||||
-rw-r--r-- | shell/ash.c | 40 | ||||
-rw-r--r-- | win32/mingw.c | 43 | ||||
-rw-r--r-- | win32/process.c | 28 |
4 files changed, 82 insertions, 30 deletions
diff --git a/include/mingw.h b/include/mingw.h index 8f7e529ba..09c140d31 100644 --- a/include/mingw.h +++ b/include/mingw.h | |||
@@ -475,6 +475,7 @@ const char *get_busybox_exec_path(void); | |||
475 | void init_winsock(void); | 475 | void init_winsock(void); |
476 | 476 | ||
477 | int has_exe_suffix(const char *p); | 477 | int has_exe_suffix(const char *p); |
478 | int has_bat_suffix(const char *p); | ||
478 | char *file_is_win32_executable(const char *p); | 479 | char *file_is_win32_executable(const char *p); |
479 | 480 | ||
480 | int err_win_to_posix(DWORD winerr); | 481 | int err_win_to_posix(DWORD winerr); |
diff --git a/shell/ash.c b/shell/ash.c index 4c9c76b8c..30f3b558b 100644 --- a/shell/ash.c +++ b/shell/ash.c | |||
@@ -2620,7 +2620,7 @@ path_advance(const char **path, const char *name) | |||
2620 | #endif | 2620 | #endif |
2621 | len = p - start + strlen(name) + 2; /* "2" is for '/' and '\0' */ | 2621 | len = p - start + strlen(name) + 2; /* "2" is for '/' and '\0' */ |
2622 | 2622 | ||
2623 | /* preserve space for .exe too */ | 2623 | /* reserve space for suffix on WIN32 */ |
2624 | while (stackblocksize() < (ENABLE_PLATFORM_MINGW32 ? len+4 : len)) | 2624 | while (stackblocksize() < (ENABLE_PLATFORM_MINGW32 ? len+4 : len)) |
2625 | growstackblock(); | 2625 | growstackblock(); |
2626 | q = stackblock(); | 2626 | q = stackblock(); |
@@ -13646,7 +13646,6 @@ find_command(char *name, struct cmdentry *entry, int act, const char *path) | |||
13646 | struct stat statb; | 13646 | struct stat statb; |
13647 | int e; | 13647 | int e; |
13648 | int updatetbl; | 13648 | int updatetbl; |
13649 | IF_PLATFORM_MINGW32(int len;) | ||
13650 | struct builtincmd *bcmd; | 13649 | struct builtincmd *bcmd; |
13651 | 13650 | ||
13652 | /* If name contains a slash, don't use PATH or hash table */ | 13651 | /* If name contains a slash, don't use PATH or hash table */ |
@@ -13779,26 +13778,31 @@ find_command(char *name, struct cmdentry *entry, int act, const char *path) | |||
13779 | } | 13778 | } |
13780 | } | 13779 | } |
13781 | else { | 13780 | else { |
13782 | /* path_advance() has reserved space for .exe */ | 13781 | extern const char win_suffix[4][4]; |
13782 | int i, len; | ||
13783 | |||
13784 | /* path_advance() has reserved space for suffix */ | ||
13783 | len = strlen(fullname); | 13785 | len = strlen(fullname); |
13784 | strcat(fullname, ".exe"); | 13786 | fullname[len] = '.'; |
13785 | if (stat(fullname, &statb) < 0) { | 13787 | for (i=0; i<4; ++i) { |
13786 | memcpy(fullname+len, ".com", 5); | 13788 | memcpy(fullname+len+1, win_suffix[i], 4); |
13789 | if (stat(fullname, &statb) == 0) | ||
13790 | break; | ||
13791 | } | ||
13792 | fullname[len] = '\0'; | ||
13793 | |||
13794 | if (i == 4) { | ||
13795 | /* suffix didn't work, try without */ | ||
13787 | if (stat(fullname, &statb) < 0) { | 13796 | if (stat(fullname, &statb) < 0) { |
13788 | /* check for script */ | 13797 | if (errno != ENOENT && errno != ENOTDIR) |
13789 | fullname[len] = '\0'; | 13798 | e = errno; |
13790 | if (stat(fullname, &statb) < 0) { | 13799 | goto loop; |
13791 | if (errno != ENOENT && errno != ENOTDIR) | 13800 | } |
13792 | e = errno; | 13801 | if (!file_is_executable(fullname)) { |
13793 | goto loop; | 13802 | e = ENOEXEC; |
13794 | } | 13803 | goto loop; |
13795 | if (!file_is_executable(fullname)) { | ||
13796 | e = ENOEXEC; | ||
13797 | goto loop; | ||
13798 | } | ||
13799 | } | 13804 | } |
13800 | } | 13805 | } |
13801 | fullname[len] = '\0'; | ||
13802 | } | 13806 | } |
13803 | #else | 13807 | #else |
13804 | while (stat(fullname, &statb) < 0) { | 13808 | while (stat(fullname, &statb) < 0) { |
diff --git a/win32/mingw.c b/win32/mingw.c index 86f649674..ad1c3c16f 100644 --- a/win32/mingw.c +++ b/win32/mingw.c | |||
@@ -1003,7 +1003,7 @@ int mingw_access(const char *name, int mode) | |||
1003 | 1003 | ||
1004 | if (!mingw_stat(name, &s) && S_ISREG(s.st_mode)) { | 1004 | if (!mingw_stat(name, &s) && S_ISREG(s.st_mode)) { |
1005 | 1005 | ||
1006 | /* stat marks .exe and .com files as executable */ | 1006 | /* stat marks files as executable according to their suffix */ |
1007 | if ((s.st_mode&S_IEXEC)) { | 1007 | if ((s.st_mode&S_IEXEC)) { |
1008 | return 0; | 1008 | return 0; |
1009 | } | 1009 | } |
@@ -1060,12 +1060,30 @@ int mingw_rmdir(const char *path) | |||
1060 | return rmdir(path); | 1060 | return rmdir(path); |
1061 | } | 1061 | } |
1062 | 1062 | ||
1063 | int has_exe_suffix(const char *name) | 1063 | const char win_suffix[4][4] = { "com", "exe", "bat", "cmd" }; |
1064 | |||
1065 | static int has_win_suffix(const char *name, int start) | ||
1064 | { | 1066 | { |
1065 | int len = strlen(name); | 1067 | int i, len = strlen(name); |
1066 | 1068 | ||
1067 | return len > 4 && (!strcasecmp(name+len-4, ".exe") || | 1069 | if (len > 4) { |
1068 | !strcasecmp(name+len-4, ".com")); | 1070 | for (i=start; i<4; ++i) { |
1071 | if (!strcasecmp(name+len-3, win_suffix[i])) { | ||
1072 | return 1; | ||
1073 | } | ||
1074 | } | ||
1075 | } | ||
1076 | return 0; | ||
1077 | } | ||
1078 | |||
1079 | int has_bat_suffix(const char *name) | ||
1080 | { | ||
1081 | return has_win_suffix(name, 2); | ||
1082 | } | ||
1083 | |||
1084 | int has_exe_suffix(const char *name) | ||
1085 | { | ||
1086 | return has_win_suffix(name, 0); | ||
1069 | } | 1087 | } |
1070 | 1088 | ||
1071 | /* check if path can be made into an executable by adding a suffix; | 1089 | /* check if path can be made into an executable by adding a suffix; |
@@ -1077,19 +1095,20 @@ int has_exe_suffix(const char *name) | |||
1077 | char *file_is_win32_executable(const char *p) | 1095 | char *file_is_win32_executable(const char *p) |
1078 | { | 1096 | { |
1079 | char *path; | 1097 | char *path; |
1098 | int i, len; | ||
1080 | 1099 | ||
1081 | if (has_exe_suffix(p)) { | 1100 | if (has_exe_suffix(p)) { |
1082 | return NULL; | 1101 | return NULL; |
1083 | } | 1102 | } |
1084 | 1103 | ||
1085 | path = xasprintf("%s.exe", p); | 1104 | len = strlen(p); |
1086 | if (file_is_executable(path)) { | 1105 | path = xasprintf("%s.com", p); |
1087 | return path; | ||
1088 | } | ||
1089 | 1106 | ||
1090 | memcpy(path+strlen(p), ".com", 5); | 1107 | for (i=0; i<4; ++i) { |
1091 | if (file_is_executable(path)) { | 1108 | memcpy(path+len+1, win_suffix[i], 4); |
1092 | return path; | 1109 | if (file_is_executable(path)) { |
1110 | return path; | ||
1111 | } | ||
1093 | } | 1112 | } |
1094 | 1113 | ||
1095 | free(path); | 1114 | free(path); |
diff --git a/win32/process.c b/win32/process.c index a0e8b96e0..da83d1c96 100644 --- a/win32/process.c +++ b/win32/process.c | |||
@@ -203,6 +203,34 @@ spawnveq(int mode, const char *path, char *const *argv, char *const *env) | |||
203 | new_argv[i] = quote_arg(argv[i]); | 203 | new_argv[i] = quote_arg(argv[i]); |
204 | new_argv[argc] = NULL; | 204 | new_argv[argc] = NULL; |
205 | 205 | ||
206 | /* | ||
207 | * Special case: spawnve won't execute a batch file when the path | ||
208 | * starts with a '.' and contains forward slashes. | ||
209 | */ | ||
210 | if (new_argv[0][0] == '.') { | ||
211 | char *s, *p; | ||
212 | |||
213 | if (has_bat_suffix(new_argv[0])) { | ||
214 | p = strdup(new_argv[0]); | ||
215 | } | ||
216 | else { | ||
217 | p = file_is_win32_executable(new_argv[0]); | ||
218 | } | ||
219 | |||
220 | if (p != NULL && has_bat_suffix(p)) { | ||
221 | for (s=p; *s; ++s) { | ||
222 | if (*s == '/') | ||
223 | *s = '\\'; | ||
224 | } | ||
225 | if (new_argv[0] != argv[0]) | ||
226 | free(new_argv[0]); | ||
227 | new_argv[0] = p; | ||
228 | } | ||
229 | else { | ||
230 | free(p); | ||
231 | } | ||
232 | } | ||
233 | |||
206 | ret = spawnve(mode, path, new_argv, env); | 234 | ret = spawnve(mode, path, new_argv, env); |
207 | 235 | ||
208 | for (i = 0;i < argc;i++) | 236 | for (i = 0;i < argc;i++) |