    {-# LINE 1 "libraries/ghc-internal/src/GHC/Internal/System/Environment/ExecutablePath.hsc" #-}
    {-# LANGUAGE Trustworthy #-}
    {-# LANGUAGE CPP #-}

    -----------------------------------------------------------------------------
    -- |
    -- Module      :  GHC.Internal.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 base-4.6.0.0
    -----------------------------------------------------------------------------

    module GHC.Internal.System.Environment.ExecutablePath
      ( getExecutablePath
      , executablePath
      ) where

    #if defined(javascript_HOST_ARCH)

    import GHC.Internal.Base
    import GHC.Internal.IO (FilePath)

    getExecutablePath :: IO FilePath
    getExecutablePath = return "a.jsexe"

    executablePath :: Maybe (IO (Maybe FilePath))
    executablePath = Nothing

    #else

    -- The imports are purposely kept completely disjoint to prevent edits
    -- to one OS implementation from breaking another.

    import GHC.Internal.Base
    import GHC.Internal.IO (FilePath)
    import GHC.Internal.Real

    {-# LINE 55 "libraries/ghc-internal/src/GHC/Internal/System/Environment/ExecutablePath.hsc" #-}
    import GHC.Internal.Data.Functor
    import GHC.Internal.Data.List (isSuffixOf)
    import GHC.Internal.Foreign.C.Types
    import GHC.Internal.Foreign.C.Error
    import GHC.Internal.Foreign.C.String
    import GHC.Internal.Foreign.Marshal.Array
    import GHC.Internal.System.Posix.Internals

    {-# LINE 107 "libraries/ghc-internal/src/GHC/Internal/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 base-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, NetBSD, Solaris, 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.)
    --
    -- Note also that while most operating systems return @Nothing@ if the
    -- executable file was deleted/unlinked, some (including NetBSD) return the
    -- original path.
    --
    -- @since base-4.17.0.0
    executablePath :: Maybe (IO (Maybe FilePath))

    --------------------------------------------------------------------------------
    -- Mac OS X

    {-# LINE 206 "libraries/ghc-internal/src/GHC/Internal/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)

    {-# LINE 223 "libraries/ghc-internal/src/GHC/Internal/System/Environment/ExecutablePath.hsc" #-}
    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

    {-# LINE 244 "libraries/ghc-internal/src/GHC/Internal/System/Environment/ExecutablePath.hsc" #-}

    --------------------------------------------------------------------------------
    -- FreeBSD / NetBSD

    {-# LINE 426 "libraries/ghc-internal/src/GHC/Internal/System/Environment/ExecutablePath.hsc" #-}

    #endif