Commits

Vinay Sajip committed 2677b86

Updated shebang parsing to have greater flexibility.

Comments (0)

Files changed (2)

CLILauncher/launcher.c

 static COMMAND commands[MAX_COMMANDS];
 static int num_commands = 0;
 
+static wchar_t * builtin_prefixes [] = {
+    /* These must be in an order that the longest matches should be found,
+     * i.e. if the prefix is "/usr/bin/env ", it should match that entry
+     * *before* matching "/usr/bin/".
+     */
+    L"/usr/bin/env ",
+    L"/usr/bin/",
+    L"/usr/local/bin/",
+    NULL
+};
+
+static wchar_t * skip_prefix(wchar_t * name)
+{
+    wchar_t ** pp = builtin_prefixes;
+    wchar_t * result = name;
+    size_t n;
+
+    for (; *pp; pp++) {
+        n = wcslen(*pp);
+        if (_wcsnicmp(*pp, name, n) == 0) {
+            result += n;   /* skip the prefix */
+            break;
+        }
+    }
+    return result;
+}
+
 static COMMAND * find_command(wchar_t * name)
 {
     COMMAND * result = NULL;
     wchar_t zapped;
     wchar_t * endp = shebang_line + nchars - 1;
     COMMAND * cp;
+    wchar_t * skipped;
 
     *command = NULL;    /* failure return */
     *suffix = NULL;
                  * stick a NUL after the command while searching for it,
                  * then put back the char we zapped.
                  */
-                p = wcspbrk(shebang_line, L" \t\r\n");
+                skipped = skip_prefix(shebang_line);
+                p = wcspbrk(skipped, L" \t\r\n");
                 if (p != NULL) {
                     zapped = *p;
                     *p = L'\0';
                 }
-                cp = find_command(shebang_line);
+                cp = find_command(skipped);
                 if (p != NULL)
                     *p = zapped;
                 if (cp != NULL) {
 VIRT_PATHS = [
     '/usr/bin/env ',
     '/usr/bin/',
+    '/usr/local/bin/',
+    '',
 ]
 
 class VirtualPath: # think a C struct...
         self.assertIn(DEFAULT_PYTHON2.bdir, stdout)
 
         # Python 3 version
-        shebang = '#!v3\n'
-        path = self.make_script(shebang_line=shebang)
-        stdout, stderr = self.run_child(path)
-        self.assertTrue(stderr.startswith(DEFAULT_PYTHON3.output_version))
+        for prefix in VIRT_PATHS:
+            shebang = '#!%sv3\n' % prefix
+            path = self.make_script(shebang_line=shebang)
+            stdout, stderr = self.run_child(path)
+            self.assertTrue(stderr.startswith(DEFAULT_PYTHON3.output_version))
 
         # Python 2 version
-        shebang = '#!v2\n'
-        path = self.make_script(shebang_line=shebang)
-        stdout, stderr = self.run_child(path)
-        self.assertTrue(stderr.startswith(DEFAULT_PYTHON2.output_version))
+        for prefix in VIRT_PATHS:
+            shebang = '#!%sv2\n' % prefix
+            path = self.make_script(shebang_line=shebang)
+            stdout, stderr = self.run_child(path)
+            self.assertTrue(stderr.startswith(DEFAULT_PYTHON2.output_version))
 
         VERBOSE_START = b'# installing zipimport hook'