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); |