diff options
| author | Ron Yorston <rmy@pobox.com> | 2017-08-28 19:59:23 +0100 |
|---|---|---|
| committer | Ron Yorston <rmy@pobox.com> | 2017-08-30 17:17:14 +0100 |
| commit | 97e2c4a05e8efa0e3e3a3c256daa05676dc5484e (patch) | |
| tree | a473ebe18bdd37baafc4882a8a84d44b272fda88 | |
| parent | 862e1bd8d6117d5b44e3ab431b3a6837d8e44040 (diff) | |
| download | busybox-w32-97e2c4a05e8efa0e3e3a3c256daa05676dc5484e.tar.gz busybox-w32-97e2c4a05e8efa0e3e3a3c256daa05676dc5484e.tar.bz2 busybox-w32-97e2c4a05e8efa0e3e3a3c256daa05676dc5484e.zip | |
win32: changes to treatment of scripts
Simplify how scripts are detected by parse_interpreter. It now:
- uses strtok to parse the line buffer;
- returns any options as a single string, not an array of separate options;
- returns both the full path of the interpreter and its name.
When a script is detected the sequence is now:
- if the path to the interpreter refers to an executable run that;
- else look up the interpreter name as a applet (if so configured) and
run the applet found;
- else search for the interpreter name on PATH.
| -rw-r--r-- | win32/process.c | 94 |
1 files changed, 36 insertions, 58 deletions
diff --git a/win32/process.c b/win32/process.c index 919d46043..e47fbac1e 100644 --- a/win32/process.c +++ b/win32/process.c | |||
| @@ -39,22 +39,13 @@ next_path_sep(const char *path) | |||
| 39 | return strchr(has_dos_drive_prefix(path) ? path+2 : path, ':'); | 39 | return strchr(has_dos_drive_prefix(path) ? path+2 : path, ':'); |
| 40 | } | 40 | } |
| 41 | 41 | ||
| 42 | #define MAX_OPT 10 | 42 | static char * |
| 43 | 43 | parse_interpreter(const char *cmd, char **name, char **opts) | |
| 44 | static const char * | ||
| 45 | parse_interpreter(const char *cmd, char ***opts, int *nopts) | ||
| 46 | { | 44 | { |
| 47 | static char buf[100], *opt[MAX_OPT]; | 45 | static char buf[100]; |
| 48 | char *p, *s, *t; | 46 | char *path, *t; |
| 49 | int n, fd; | 47 | int n, fd; |
| 50 | 48 | ||
| 51 | *nopts = 0; | ||
| 52 | *opts = opt; | ||
| 53 | |||
| 54 | /* don't even try a .exe */ | ||
| 55 | if (has_exe_suffix(cmd)) | ||
| 56 | return NULL; | ||
| 57 | |||
| 58 | fd = open(cmd, O_RDONLY); | 49 | fd = open(cmd, O_RDONLY); |
| 59 | if (fd < 0) | 50 | if (fd < 0) |
| 60 | return NULL; | 51 | return NULL; |
| @@ -70,43 +61,21 @@ parse_interpreter(const char *cmd, char ***opts, int *nopts) | |||
| 70 | if (buf[0] != '#' || buf[1] != '!') | 61 | if (buf[0] != '#' || buf[1] != '!') |
| 71 | return NULL; | 62 | return NULL; |
| 72 | buf[n] = '\0'; | 63 | buf[n] = '\0'; |
| 73 | p = strchr(buf, '\n'); | 64 | if ((t=strchr(buf, '\n')) == NULL) |
| 74 | if (!p) | ||
| 75 | return NULL; | 65 | return NULL; |
| 76 | *p = '\0'; | 66 | t[1] = '\0'; |
| 77 | |||
| 78 | /* remove trailing whitespace */ | ||
| 79 | while ( isspace(*--p) ) { | ||
| 80 | *p = '\0'; | ||
| 81 | } | ||
| 82 | |||
| 83 | /* skip whitespace after '#!' */ | ||
| 84 | for ( s=buf+2; *s && isspace(*s); ++s ) { | ||
| 85 | } | ||
| 86 | |||
| 87 | /* move to end of interpreter path (which may not contain spaces) */ | ||
| 88 | for ( ; *s && !isspace(*s); ++s ) { | ||
| 89 | } | ||
| 90 | 67 | ||
| 91 | n = 0; | 68 | if ((path=strtok(buf+2, " \t\r\n")) == NULL) |
| 92 | if ( *s != '\0' ) { | 69 | return NULL; |
| 93 | /* there are options */ | ||
| 94 | *s++ = '\0'; | ||
| 95 | |||
| 96 | while ( (t=strtok(s, " \t")) && n < MAX_OPT ) { | ||
| 97 | s = NULL; | ||
| 98 | opt[n++] = t; | ||
| 99 | } | ||
| 100 | } | ||
| 101 | 70 | ||
| 102 | /* find interpreter name */ | 71 | t = (char *)bb_basename(path); |
| 103 | if (!(p = strrchr(buf+2, '/'))) | 72 | if (*t == '\0') |
| 104 | return NULL; | 73 | return NULL; |
| 105 | 74 | ||
| 106 | *nopts = n; | 75 | *name = t; |
| 107 | *opts = opt; | 76 | *opts = strtok(NULL, "\r\n"); |
| 108 | 77 | ||
| 109 | return p+1; | 78 | return path; |
| 110 | } | 79 | } |
| 111 | 80 | ||
| 112 | /* | 81 | /* |
| @@ -246,42 +215,51 @@ static intptr_t | |||
| 246 | mingw_spawn_interpreter(int mode, const char *prog, char *const *argv, char *const *envp) | 215 | mingw_spawn_interpreter(int mode, const char *prog, char *const *argv, char *const *envp) |
| 247 | { | 216 | { |
| 248 | intptr_t ret; | 217 | intptr_t ret; |
| 249 | char **opts; | ||
| 250 | int nopts; | 218 | int nopts; |
| 251 | const char *interpr = parse_interpreter(prog, &opts, &nopts); | 219 | char *int_name, *opts; |
| 220 | char *int_path = parse_interpreter(prog, &int_name, &opts); | ||
| 252 | char **new_argv; | 221 | char **new_argv; |
| 253 | int argc = 0; | 222 | int argc = 0; |
| 223 | char *fullpath = NULL; | ||
| 254 | 224 | ||
| 255 | if (!interpr) | 225 | if (!int_path) |
| 256 | return spawnveq(mode, prog, argv, envp); | 226 | return spawnveq(mode, prog, argv, envp); |
| 257 | 227 | ||
| 258 | 228 | nopts = opts != NULL; | |
| 259 | while (argv[argc]) | 229 | while (argv[argc]) |
| 260 | argc++; | 230 | argc++; |
| 261 | new_argv = malloc(sizeof(*argv)*(argc+nopts+2)); | 231 | |
| 262 | memcpy(new_argv+1, opts, sizeof(*opts)*nopts); | 232 | new_argv = xmalloc(sizeof(*argv)*(argc+nopts+2)); |
| 263 | memcpy(new_argv+nopts+2, argv+1, sizeof(*argv)*argc); | 233 | new_argv[1] = opts; |
| 264 | new_argv[nopts+1] = (char *)prog; /* pass absolute path */ | 234 | new_argv[nopts+1] = (char *)prog; /* pass absolute path */ |
| 235 | memcpy(new_argv+nopts+2, argv+1, sizeof(*argv)*argc); | ||
| 265 | 236 | ||
| 237 | if (file_is_executable(int_path) || | ||
| 238 | (fullpath=file_is_win32_executable(int_path)) != NULL) { | ||
| 239 | new_argv[0] = fullpath ? fullpath : int_path; | ||
| 240 | ret = spawnveq(mode, new_argv[0], new_argv, envp); | ||
| 241 | free(fullpath); | ||
| 242 | } else | ||
| 266 | #if ENABLE_FEATURE_PREFER_APPLETS || ENABLE_FEATURE_SH_STANDALONE | 243 | #if ENABLE_FEATURE_PREFER_APPLETS || ENABLE_FEATURE_SH_STANDALONE |
| 267 | if (find_applet_by_name(interpr) >= 0) { | 244 | if (find_applet_by_name(int_name) >= 0) { |
| 268 | new_argv[0] = (char *)interpr; | 245 | new_argv[0] = int_name; |
| 269 | ret = mingw_spawn_applet(mode, new_argv, envp); | 246 | ret = mingw_spawn_applet(mode, new_argv, envp); |
| 270 | } else | 247 | } else |
| 271 | #endif | 248 | #endif |
| 272 | { | 249 | { |
| 273 | char *path = xstrdup(getenv("PATH")); | 250 | char *path = xstrdup(getenv("PATH")); |
| 274 | char *tmp = path; | 251 | char *tmp = path; |
| 275 | char *iprog = find_executable(interpr, &tmp); | 252 | |
| 253 | fullpath = find_executable(int_name, &tmp); | ||
| 276 | free(path); | 254 | free(path); |
| 277 | if (!iprog) { | 255 | if (!fullpath) { |
| 278 | free(new_argv); | 256 | free(new_argv); |
| 279 | errno = ENOENT; | 257 | errno = ENOENT; |
| 280 | return -1; | 258 | return -1; |
| 281 | } | 259 | } |
| 282 | new_argv[0] = iprog; | 260 | new_argv[0] = fullpath; |
| 283 | ret = spawnveq(mode, iprog, new_argv, envp); | 261 | ret = spawnveq(mode, fullpath, new_argv, envp); |
| 284 | free(iprog); | 262 | free(fullpath); |
| 285 | } | 263 | } |
| 286 | 264 | ||
| 287 | free(new_argv); | 265 | free(new_argv); |
