From 00f2d33f37da42e17e5d978958659c4899cb2f0a Mon Sep 17 00:00:00 2001 From: Ron Yorston Date: Mon, 26 Feb 2018 10:08:50 +0000 Subject: 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. --- win32/mingw.c | 43 +++++++++++++++++++++++++++++++------------ win32/process.c | 28 ++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+), 12 deletions(-) (limited to 'win32') 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) if (!mingw_stat(name, &s) && S_ISREG(s.st_mode)) { - /* stat marks .exe and .com files as executable */ + /* stat marks files as executable according to their suffix */ if ((s.st_mode&S_IEXEC)) { return 0; } @@ -1060,12 +1060,30 @@ int mingw_rmdir(const char *path) return rmdir(path); } -int has_exe_suffix(const char *name) +const char win_suffix[4][4] = { "com", "exe", "bat", "cmd" }; + +static int has_win_suffix(const char *name, int start) { - int len = strlen(name); + int i, len = strlen(name); - return len > 4 && (!strcasecmp(name+len-4, ".exe") || - !strcasecmp(name+len-4, ".com")); + if (len > 4) { + for (i=start; i<4; ++i) { + if (!strcasecmp(name+len-3, win_suffix[i])) { + return 1; + } + } + } + return 0; +} + +int has_bat_suffix(const char *name) +{ + return has_win_suffix(name, 2); +} + +int has_exe_suffix(const char *name) +{ + return has_win_suffix(name, 0); } /* check if path can be made into an executable by adding a suffix; @@ -1077,19 +1095,20 @@ int has_exe_suffix(const char *name) char *file_is_win32_executable(const char *p) { char *path; + int i, len; if (has_exe_suffix(p)) { return NULL; } - path = xasprintf("%s.exe", p); - if (file_is_executable(path)) { - return path; - } + len = strlen(p); + path = xasprintf("%s.com", p); - memcpy(path+strlen(p), ".com", 5); - if (file_is_executable(path)) { - return path; + for (i=0; i<4; ++i) { + memcpy(path+len+1, win_suffix[i], 4); + if (file_is_executable(path)) { + return path; + } } 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) new_argv[i] = quote_arg(argv[i]); new_argv[argc] = NULL; + /* + * Special case: spawnve won't execute a batch file when the path + * starts with a '.' and contains forward slashes. + */ + if (new_argv[0][0] == '.') { + char *s, *p; + + if (has_bat_suffix(new_argv[0])) { + p = strdup(new_argv[0]); + } + else { + p = file_is_win32_executable(new_argv[0]); + } + + if (p != NULL && has_bat_suffix(p)) { + for (s=p; *s; ++s) { + if (*s == '/') + *s = '\\'; + } + if (new_argv[0] != argv[0]) + free(new_argv[0]); + new_argv[0] = p; + } + else { + free(p); + } + } + ret = spawnve(mode, path, new_argv, env); for (i = 0;i < argc;i++) -- cgit v1.2.3-55-g6feb