aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2018-02-28 19:57:02 +0000
committerRon Yorston <rmy@pobox.com>2018-02-28 20:23:18 +0000
commitf5783ef14f9ad96ae483f16e639953d0212ca7d0 (patch)
tree521ecd0a4cfa4c789f559fcef3982271d3c21bf6
parent92dbd3c0932abbfb6814554603abd38e3eb9d953 (diff)
downloadbusybox-w32-f5783ef14f9ad96ae483f16e639953d0212ca7d0.tar.gz
busybox-w32-f5783ef14f9ad96ae483f16e639953d0212ca7d0.tar.bz2
busybox-w32-f5783ef14f9ad96ae483f16e639953d0212ca7d0.zip
win32: additional improvements to handling of executables
Consistent processing of file extensions, as described in the previous commit, has been applied to the 'which' applet and the functions find_executable and mingw_spawn_interpreter. In spawnveq check that the file to be executed exists and is executable, and ensure that it won't have any extensions added by spawnve. It's intended that all files passed to spawnve should have their names fully specified. If this isn't the case the tests here will cause errors which will need to be fixed.
-rw-r--r--debianutils/which.c11
-rw-r--r--libbb/executable.c12
-rw-r--r--win32/process.c34
3 files changed, 36 insertions, 21 deletions
diff --git a/debianutils/which.c b/debianutils/which.c
index 9060a5b47..0b0a6a645 100644
--- a/debianutils/which.c
+++ b/debianutils/which.c
@@ -66,17 +66,18 @@ int which_main(int argc UNUSED_PARAM, char **argv)
66 66
67 /* If file contains a slash don't use PATH */ 67 /* If file contains a slash don't use PATH */
68 if (strchr(*argv, '/') || (ENABLE_PLATFORM_MINGW32 && strchr(*argv, '\\'))) { 68 if (strchr(*argv, '/') || (ENABLE_PLATFORM_MINGW32 && strchr(*argv, '\\'))) {
69 if (file_is_executable(*argv)) {
70 missing = 0;
71 puts(*argv);
72 }
73#if ENABLE_PLATFORM_MINGW32 69#if ENABLE_PLATFORM_MINGW32
74 else if ((p=add_win32_extension(*argv)) != NULL) { 70 if ((p=add_win32_extension(*argv)) != NULL) {
75 missing = 0; 71 missing = 0;
76 puts(p); 72 puts(p);
77 free(p); 73 free(p);
78 } 74 }
75 else
79#endif 76#endif
77 if (file_is_executable(*argv)) {
78 missing = 0;
79 puts(*argv);
80 }
80 } else { 81 } else {
81 char *path; 82 char *path;
82 83
diff --git a/libbb/executable.c b/libbb/executable.c
index 76b10f790..aec829945 100644
--- a/libbb/executable.c
+++ b/libbb/executable.c
@@ -66,23 +66,23 @@ char* FAST_FUNC find_executable(const char *filename, char **PATHp)
66 p[0] ? p : ".", /* handle "::" case */ 66 p[0] ? p : ".", /* handle "::" case */
67 filename 67 filename
68 ); 68 );
69 ex = file_is_executable(p);
70#if ENABLE_PLATFORM_MINGW32 69#if ENABLE_PLATFORM_MINGW32
71 if (n) *n++ = sep; 70 if (n) *n++ = sep;
72#else 71#else
73 if (n) *n++ = ':'; 72 if (n) *n++ = ':';
74#endif 73#endif
75 if (ex) {
76 *PATHp = n;
77 return p;
78 }
79#if ENABLE_PLATFORM_MINGW32 74#if ENABLE_PLATFORM_MINGW32
80 else if ((w=add_win32_extension(p))) { 75 if ((w=add_win32_extension(p))) {
81 *PATHp = n; 76 *PATHp = n;
82 free(p); 77 free(p);
83 return w; 78 return w;
84 } 79 }
85#endif 80#endif
81 ex = file_is_executable(p);
82 if (ex) {
83 *PATHp = n;
84 return p;
85 }
86 free(p); 86 free(p);
87 p = n; 87 p = n;
88 } /* on loop exit p == NULL */ 88 } /* on loop exit p == NULL */
diff --git a/win32/process.c b/win32/process.c
index eda143e0e..96561c482 100644
--- a/win32/process.c
+++ b/win32/process.c
@@ -195,6 +195,23 @@ spawnveq(int mode, const char *path, char *const *argv, char *const *env)
195 char *new_path = NULL; 195 char *new_path = NULL;
196 int i, argc = -1; 196 int i, argc = -1;
197 intptr_t ret; 197 intptr_t ret;
198 struct stat st;
199
200 /*
201 * Require that the file exists, is a regular file and is executable.
202 * It may still contain garbage but we let spawnve deal with that.
203 */
204 if (stat(path, &st) == 0) {
205 if (!S_ISREG(st.st_mode) || !(st.st_mode&S_IXUSR)) {
206 errno = EACCES;
207 fprintf(stderr, "spawnveq: %s: %s\n", path, strerror(errno));
208 return -1;
209 }
210 }
211 else {
212 fprintf(stderr, "spawnveq: %s: %s\n", path, strerror(errno));
213 return -1;
214 }
198 215
199 while (argv[++argc]) 216 while (argv[++argc])
200 ; 217 ;
@@ -233,15 +250,12 @@ spawnveq(int mode, const char *path, char *const *argv, char *const *env)
233 } 250 }
234 251
235 /* 252 /*
236 * Another special case: if a binary executable doesn't have an 253 * Another special case: if a file doesn't have an extension add
237 * extension spawnve will only run it if the filename ends with a '.'. 254 * a '.' at the end. This forces spawnve to use precisely the
255 * file specified without trying to add an extension.
238 */ 256 */
239 if (!has_exe_suffix(path)) { 257 if (!strchr(bb_basename(path), '.')) {
240 int len = strlen(path); 258 new_path = xasprintf("%s.", path);
241
242 if (path[len-1] != '.' && has_exec_format(path)) {
243 new_path = xasprintf("%s.", path);
244 }
245 } 259 }
246 260
247 ret = spawnve(mode, new_path ? new_path : path, new_argv, env); 261 ret = spawnve(mode, new_path ? new_path : path, new_argv, env);
@@ -288,8 +302,8 @@ mingw_spawn_interpreter(int mode, const char *prog, char *const *argv, char *con
288 new_argv[nopts+1] = (char *)prog; /* pass absolute path */ 302 new_argv[nopts+1] = (char *)prog; /* pass absolute path */
289 memcpy(new_argv+nopts+2, argv+1, sizeof(*argv)*argc); 303 memcpy(new_argv+nopts+2, argv+1, sizeof(*argv)*argc);
290 304
291 if (file_is_executable(int_path) || 305 if ((fullpath=add_win32_extension(int_path)) != NULL ||
292 (fullpath=add_win32_extension(int_path)) != NULL) { 306 file_is_executable(int_path)) {
293 new_argv[0] = fullpath ? fullpath : int_path; 307 new_argv[0] = fullpath ? fullpath : int_path;
294 ret = spawnveq(mode, new_argv[0], new_argv, envp); 308 ret = spawnveq(mode, new_argv[0], new_argv, envp);
295 } else 309 } else