Windows: Handle shebang in external special remote program.

This commit is contained in:
Joey Hess 2016-09-05 12:09:23 -04:00
parent 1a085ca4dd
commit f292f78366
No known key found for this signature in database
GPG key ID: C910D9222512E3C7
5 changed files with 66 additions and 30 deletions

View file

@ -9,6 +9,19 @@
module Utility.Shell where
import Utility.SafeCommand
#ifdef mingw32_HOST_OS
import Utility.Path
import Utility.FileSystemEncoding
import Utility.Exception
import Utility.PartialPrelude
#endif
#ifdef mingw32_HOST_OS
import System.IO
import System.FilePath
#endif
shellPath_portable :: FilePath
shellPath_portable = "/bin/sh"
@ -24,3 +37,32 @@ shebang_portable = "#!" ++ shellPath_portable
shebang_local :: String
shebang_local = "#!" ++ shellPath_local
-- | On Windows, shebang is not handled by the kernel, so to support
-- shell scripts etc, have to look at the program being run and
-- parse it for shebang.
--
-- This has no effect on Unix.
findShellCommand :: FilePath -> IO (FilePath, [CommandParam])
findShellCommand f = do
#ifndef mingw32_HOST_OS
defcmd
#else
l <- catchDefaultIO Nothing $ withFile f ReadMode $ \h -> do
fileEncoding h
headMaybe . lines <$> hGetContents h
case l of
Just ('#':'!':rest) -> case words rest of
[] -> defcmd
(c:ps) -> do
let ps' = map Param ps ++ [File f]
-- If the command is not inPath,
-- take the base of it, and run eg "sh"
-- which in some cases on windows will work
-- despite it not being inPath.
ok <- inPath c
return (if ok then c else takeFileName c, ps')
_ -> defcmd
#endif
where
defcmd = return (f, [])