Commits

Paul Moore committed 87d41c5 Draft

Search PATH for python.exe if shebang line is #!/usr/bin/env python

Comments (0)

Files changed (1)

CLILauncher/launcher.c

 /* Build options. */
 #define SKIP_PREFIX
 #define PYTHON_ARGS
-/* #define SEARCH_PATH */
+#define SEARCH_PATH
 
 /* Just for now - static definition */
 
     }
 }
 
-static wchar_t * builtin_virtual_paths [] = {
-    L"/usr/bin/env python",
-    L"/usr/bin/python",
-    L"/usr/local/bin/python",
-    L"python",
-    NULL
+typedef struct {
+    wchar_t *shebang;
+    BOOL search;
+} SHEBANG;
+
+static SHEBANG builtin_virtual_paths [] = {
+    { L"/usr/bin/env python", TRUE },
+    { L"/usr/bin/python", FALSE },
+    { L"/usr/local/bin/python", FALSE },
+    { L"python", FALSE },
+    { NULL, FALSE },
 };
 
 /* For now, a static array of commands. */
 
 static BOOL
 parse_shebang(wchar_t * shebang_line, int nchars, wchar_t ** command,
-              wchar_t ** suffix)
+              wchar_t ** suffix, BOOL *search)
 {
     BOOL rc = FALSE;
-    wchar_t ** vpp;
+    SHEBANG * vpp;
     size_t plen;
     wchar_t * p;
     wchar_t zapped;
 
     *command = NULL;    /* failure return */
     *suffix = NULL;
+    *search = 0;
 
     if ((*shebang_line++ == L'#') && (*shebang_line++ == L'!')) {
         shebang_line = skip_whitespace(shebang_line);
         if (*shebang_line) {
             *command = shebang_line;
-            for (vpp = builtin_virtual_paths; *vpp; ++vpp) {
-                plen = wcslen(*vpp);
-                if (wcsncmp(shebang_line, *vpp, plen) == 0) {
+            for (vpp = builtin_virtual_paths; vpp->shebang; ++vpp) {
+                plen = wcslen(vpp->shebang);
+                if (wcsncmp(shebang_line, vpp->shebang, plen) == 0) {
                     rc = TRUE;
+                    *search = vpp->search;
                     /* We can do this because all builtin commands contain
                      * "python".
                      */
                     break;
                 }
             }
-            if (*vpp == NULL) {
+            if (vpp->shebang == NULL) {
                 /*
                  * Not found in builtins - look in customised commands.
                  *
     int i, j, nchars = 0;
     int header_len;
     BOOL is_virt;
+    BOOL search;
     wchar_t * command;
     wchar_t * suffix;
+    COMMAND *cmd = NULL;
     INSTALLED_PYTHON * ip;
 
     if (rc == 0) {
             if (nchars > 0) {
                 shebang_line[--nchars] = L'\0';
                 is_virt = parse_shebang(shebang_line, nchars, &command,
-                                        &suffix);
+                                        &suffix, &search);
                 if (command != NULL) {
                     debug(L"parse_shebang: found command: %s\n", command);
                     if (!is_virt) {
                             error(RC_BAD_VIRTUAL_PATH, L"Unknown virtual \
 path '%s'", command);
                         command += 6;   /* skip past "python" */
+                        if (search && *command == L'\0') {
+                            /* Command is eligible for path search, and there
+                             * is no version specification.
+                             */
+                            debug(L"searching PATH for python executable\n");
+                            cmd = find_on_path(L"python");
+                            debug(L"Python on path: %s\n", cmd ? cmd->value : L"<not found>");
+                            if (cmd) {
+                                debug(L"located python on PATH: %s\n", cmd->value);
+                                invoke_child(cmd->value, suffix, cmdline);
+                                /* Exit here, as we have found the command */
+                                return;
+                            }
+                            /* FALL THROUGH: No python found on PATH, so fall
+                             * back to locating the correct installed python.
+                             */
+                        }
                         if (*command && !validate_version(command))
                             error(RC_BAD_VIRTUAL_PATH, L"Invalid version \
 specification: '%s'.\nIn the first line of the script, 'python' needs to be \