2013-02-13 18:30:04 +00:00
|
|
|
{- /bin/sh handling
|
|
|
|
-
|
2015-01-21 16:50:09 +00:00
|
|
|
- Copyright 2013 Joey Hess <id@joeyh.name>
|
2013-02-13 18:30:04 +00:00
|
|
|
-
|
2014-05-10 14:01:27 +00:00
|
|
|
- License: BSD-2-clause
|
2013-02-13 18:30:04 +00:00
|
|
|
-}
|
|
|
|
|
|
|
|
{-# LANGUAGE CPP #-}
|
|
|
|
|
|
|
|
module Utility.Shell where
|
|
|
|
|
2016-09-05 16:09:23 +00:00
|
|
|
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
|
|
|
|
|
2013-05-06 19:58:13 +00:00
|
|
|
shellPath_portable :: FilePath
|
|
|
|
shellPath_portable = "/bin/sh"
|
|
|
|
|
|
|
|
shellPath_local :: FilePath
|
2013-02-27 06:39:22 +00:00
|
|
|
#ifndef __ANDROID__
|
2013-05-06 19:58:13 +00:00
|
|
|
shellPath_local = shellPath_portable
|
2013-02-13 18:30:04 +00:00
|
|
|
#else
|
2013-05-06 19:58:13 +00:00
|
|
|
shellPath_local = "/system/bin/sh"
|
2013-02-13 18:30:04 +00:00
|
|
|
#endif
|
|
|
|
|
2013-05-06 19:58:13 +00:00
|
|
|
shebang_portable :: String
|
|
|
|
shebang_portable = "#!" ++ shellPath_portable
|
|
|
|
|
|
|
|
shebang_local :: String
|
|
|
|
shebang_local = "#!" ++ shellPath_local
|
2016-09-05 16:09:23 +00:00
|
|
|
|
|
|
|
-- | 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, [])
|