@@ -871,6 +871,62 @@ _findCommand(SearchInfo *search, const wchar_t *command, int commandLength)
871871}
872872
873873
874+ int
875+ _useShebangAsExecutable (SearchInfo * search , const wchar_t * shebang , int shebangLength )
876+ {
877+ wchar_t buffer [MAXLEN ];
878+ wchar_t script [MAXLEN ];
879+ wchar_t command [MAXLEN ];
880+
881+ int commandLength = 0 ;
882+ int inQuote = 0 ;
883+
884+ if (!shebang || !shebangLength ) {
885+ return 0 ;
886+ }
887+
888+ wchar_t * pC = command ;
889+ for (int i = 0 ; i < shebangLength ; ++ i ) {
890+ wchar_t c = shebang [i ];
891+ if (isspace (c ) && !inQuote ) {
892+ commandLength = i ;
893+ break ;
894+ } else if (c == L'"' ) {
895+ inQuote = !inQuote ;
896+ } else if (c == L'/' || c == L'\\' ) {
897+ * pC ++ = L'\\' ;
898+ } else {
899+ * pC ++ = c ;
900+ }
901+ }
902+ * pC = L'\0' ;
903+
904+ if (!GetCurrentDirectoryW (MAXLEN , buffer ) ||
905+ wcsncpy_s (script , MAXLEN , search -> scriptFile , search -> scriptFileLength ) ||
906+ FAILED (PathCchCombineEx (buffer , MAXLEN , buffer , script ,
907+ PATHCCH_ALLOW_LONG_PATHS )) ||
908+ FAILED (PathCchRemoveFileSpec (buffer , MAXLEN )) ||
909+ FAILED (PathCchCombineEx (buffer , MAXLEN , buffer , command ,
910+ PATHCCH_ALLOW_LONG_PATHS ))
911+ ) {
912+ return RC_NO_MEMORY ;
913+ }
914+
915+ int n = (int )wcsnlen (buffer , MAXLEN );
916+ wchar_t * path = allocSearchInfoBuffer (search , n + 1 );
917+ if (!path ) {
918+ return RC_NO_MEMORY ;
919+ }
920+ wcscpy_s (path , n + 1 , buffer );
921+ search -> executablePath = path ;
922+ if (commandLength ) {
923+ search -> executableArgs = & shebang [commandLength ];
924+ search -> executableArgsLength = shebangLength - commandLength ;
925+ }
926+ return 0 ;
927+ }
928+
929+
874930int
875931checkShebang (SearchInfo * search )
876932{
@@ -963,13 +1019,19 @@ checkShebang(SearchInfo *search)
9631019 L"/usr/bin/env " ,
9641020 L"/usr/bin/" ,
9651021 L"/usr/local/bin/" ,
966- L"" ,
1022+ L"python " ,
9671023 NULL
9681024 };
9691025
9701026 for (const wchar_t * * tmpl = shebangTemplates ; * tmpl ; ++ tmpl ) {
9711027 if (_shebangStartsWith (shebang , shebangLength , * tmpl , & command )) {
9721028 commandLength = 0 ;
1029+ // Normally "python" is the start of the command, but we also need it
1030+ // as a shebang prefix for back-compat. We move the command marker back
1031+ // if we match on that one.
1032+ if (0 == wcscmp (* tmpl , L"python" )) {
1033+ command -= 6 ;
1034+ }
9731035 while (command [commandLength ] && !isspace (command [commandLength ])) {
9741036 commandLength += 1 ;
9751037 }
@@ -1012,11 +1074,14 @@ checkShebang(SearchInfo *search)
10121074 debug (L"# Found shebang command but could not execute it: %.*s\n" ,
10131075 commandLength , command );
10141076 }
1015- break ;
1077+ // search is done by this point
1078+ return 0 ;
10161079 }
10171080 }
10181081
1019- return 0 ;
1082+ // Unrecognised commands are joined to the script's directory and treated
1083+ // as the executable path
1084+ return _useShebangAsExecutable (search , shebang , shebangLength );
10201085}
10211086
10221087
0 commit comments