aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2018-02-26 10:08:50 +0000
committerRon Yorston <rmy@pobox.com>2018-02-26 10:08:50 +0000
commit00f2d33f37da42e17e5d978958659c4899cb2f0a (patch)
tree5d43272aa7c6a4f3be2dd4f9e9d1edf3963ec69d
parent7288179d1218f8e0308455d4d58346aec268eb2e (diff)
downloadbusybox-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.h1
-rw-r--r--shell/ash.c40
-rw-r--r--win32/mingw.c43
-rw-r--r--win32/process.c28
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);
475void init_winsock(void); 475void init_winsock(void);
476 476
477int has_exe_suffix(const char *p); 477int has_exe_suffix(const char *p);
478int has_bat_suffix(const char *p);
478char *file_is_win32_executable(const char *p); 479char *file_is_win32_executable(const char *p);
479 480
480int err_win_to_posix(DWORD winerr); 481int 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
1063int has_exe_suffix(const char *name) 1063const char win_suffix[4][4] = { "com", "exe", "bat", "cmd" };
1064
1065static 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
1079int has_bat_suffix(const char *name)
1080{
1081 return has_win_suffix(name, 2);
1082}
1083
1084int 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)
1077char *file_is_win32_executable(const char *p) 1095char *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++)