aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2017-08-28 19:59:23 +0100
committerRon Yorston <rmy@pobox.com>2017-08-30 17:17:14 +0100
commit97e2c4a05e8efa0e3e3a3c256daa05676dc5484e (patch)
treea473ebe18bdd37baafc4882a8a84d44b272fda88
parent862e1bd8d6117d5b44e3ab431b3a6837d8e44040 (diff)
downloadbusybox-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.c94
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 42static char *
43 43parse_interpreter(const char *cmd, char **name, char **opts)
44static const char *
45parse_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
246mingw_spawn_interpreter(int mode, const char *prog, char *const *argv, char *const *envp) 215mingw_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);