{-# LINE 1 "libraries/base/System/Environment/ExecutablePath.hsc" #-} {-# LANGUAGE Safe #-} {-# LANGUAGE CPP #-} ----------------------------------------------------------------------------- -- | -- Module : System.Environment.ExecutablePath -- Copyright : (c) The University of Glasgow 2001 -- License : BSD-style (see the file libraries/base/LICENSE) -- -- Maintainer : libraries@haskell.org -- Stability : provisional -- Portability : portable -- -- Function to retrieve the absolute filepath of the current executable. -- -- @since 4.6.0.0 ----------------------------------------------------------------------------- module System.Environment.ExecutablePath ( getExecutablePath , executablePath ) where -- The imports are purposely kept completely disjoint to prevent edits -- to one OS implementation from breaking another. {-# LINE 37 "libraries/base/System/Environment/ExecutablePath.hsc" #-} import Data.List (isSuffixOf) import Foreign.C import Foreign.Marshal.Array import System.Posix.Internals {-# LINE 68 "libraries/base/System/Environment/ExecutablePath.hsc" #-} -- The exported function is defined outside any if-guard to make sure -- every OS implements it with the same type. -- | Returns the absolute pathname of the current executable, -- or @argv[0]@ if the operating system does not provide a reliable -- way query the current executable. -- -- Note that for scripts and interactive sessions, this is the path to -- the interpreter (e.g. ghci.) -- -- Since base 4.11.0.0, 'getExecutablePath' resolves symlinks on Windows. -- If an executable is launched through a symlink, 'getExecutablePath' -- returns the absolute path of the original executable. -- -- If the executable has been deleted, behaviour is ill-defined and -- varies by operating system. See 'executablePath' for a more -- reliable way to query the current executable. -- -- @since 4.6.0.0 getExecutablePath :: IO FilePath -- | Get an action to query the absolute pathname of the current executable. -- -- If the operating system provides a reliable way to determine the current -- executable, return the query action, otherwise return @Nothing@. The action -- is defined on FreeBSD, Linux, MacOS and Windows. -- -- Even where the query action is defined, there may be situations where no -- result is available, e.g. if the executable file was deleted while the -- program is running. Therefore the result of the query action is a @Maybe -- FilePath@. -- -- Note that for scripts and interactive sessions, the result is the path to -- the interpreter (e.g. ghci.) -- -- @since 4.17.0.0 executablePath :: Maybe (IO (Maybe FilePath)) -------------------------------------------------------------------------------- -- Mac OS X {-# LINE 163 "libraries/base/System/Environment/ExecutablePath.hsc" #-} foreign import ccall unsafe "readlink" c_readlink :: CString -> CString -> CSize -> IO CInt -- | Reads the @FilePath@ pointed to by the symbolic link and returns -- it. -- -- See readlink(2) readSymbolicLink :: FilePath -> IO FilePath readSymbolicLink file = allocaArray0 4096 $ \buf -> withFilePath file $ \s -> do len <- throwErrnoPathIfMinus1 "readSymbolicLink" file $ c_readlink s buf 4096 peekFilePathLen (buf,fromIntegral len) getExecutablePath = readSymbolicLink $ "/proc/self/exe" executablePath = Just (check <$> getExecutablePath) where -- procfs(5): If the pathname has been unlinked, the symbolic link will -- contain the string '(deleted)' appended to the original pathname. -- -- See also https://gitlab.haskell.org/ghc/ghc/-/issues/10957 check s | "(deleted)" `isSuffixOf` s = Nothing | otherwise = Just s -------------------------------------------------------------------------------- -- FreeBSD {-# LINE 362 "libraries/base/System/Environment/ExecutablePath.hsc" #-}