{- | The documentation of "System.Environment.getProgName" says that \"However, this is hard-to-impossible to implement on some non-Unix OSes, so instead, for maximum portability, we just return the leafname of the program as invoked. Even then there are some differences between platforms: on Windows, for example, a program invoked as foo is probably really FOO.EXE, and that is what "getProgName" will return.\" This library tries to fix this issue. It also provides some platform-specific functions (most notably getting the path of the application bundle on OSX). Supported operating systems: * Win32 (tested on Windows 7) * Mac OS X * Linux * FreeBSD (tested on FreeBSD 6.4) * \*BSD (with procfs mounted, plus fallback for certain shells; untested) * Solaris (untested, and probably works on Solaris 10 only) -} {-# LANGUAGE CPP #-} module System.Environment.Executable ( getExecutablePath , splitExecutablePath #ifdef mingw32_HOST_OS , getModulePath #endif #ifdef darwin_HOST_OS , getApplicationBundlePath #endif #ifdef WE_HAVE_GHC , ScriptPath(..) , getScriptPath #endif ) where import Control.Monad (liftM) import System.FilePath (splitFileName) import System.Directory (canonicalizePath) import Data.Char (toLower) import Data.List (find,findIndex) #ifdef WE_HAVE_GHC import GHC.Environment #endif -------------------------------------------------------------------------------- #ifdef mingw32_HOST_OS #define SUPPORTED_OS import System.Environment.Executable.Win32 #endif #ifdef darwin_HOST_OS #define SUPPORTED_OS import System.Environment.Executable.MacOSX #endif #ifdef linux_HOST_OS #define SUPPORTED_OS import System.Environment.Executable.Linux #endif #ifdef freebsd_HOST_OS #define SUPPORTED_OS import System.Environment.Executable.FreeBSD #endif #ifdef netbsd_HOST_OS #define SUPPORTED_OS import System.Environment.Executable.BSD #endif #ifdef openbsd_HOST_OS #define SUPPORTED_OS import System.Environment.Executable.BSD #endif #ifdef solaris_HOST_OS #define SUPPORTED_OS import System.Environment.Executable.Solaris #endif -------------------------------------------------------------------------------- splitExecutablePath :: IO (FilePath,FilePath) splitExecutablePath = liftM splitFileName getExecutablePath -------------------------------------------------------------------------------- #ifndef SUPPORTED_OS {-# WARNING getExecutablePath "the host OS is not supported!" #-} getExecutablePath :: IO String getExecutablePath = error "host OS not supported" #endif -------------------------------------------------------------------------------- #ifdef WE_HAVE_GHC -- | An experimental hack which tries to figure out if the program -- was run with @runghc@ or @runhaskell@ or @ghci@, and then tries to find -- out the directory of the /source/ (or object file). -- -- GHC only. getScriptPath :: IO ScriptPath getScriptPath = do fargs <- getFullArgs exec <- getExecutablePath let (pt,fn) = splitFileName exec case fargs of [] -> return (Executable exec) _ -> case map toLower fn of #ifdef mingw32_HOST_OS "ghc.exe" -> do #else "ghc" -> do #endif case find f1 fargs of Just s -> do path <- canonicalizePath $ init (drop n1 s) return $ RunGHC path Nothing -> case findIndex f2 fargs of Just i -> return Interactive Nothing -> return (Executable exec) _ -> return (Executable exec) where f1 xs = take n1 xs == s1 s1 = ":set prog \"" n1 = length s1 f2 xs = xs == "--interactive" data ScriptPath = Executable FilePath -- ^ it was (probably) a proper compiled executable | RunGHC FilePath -- ^ it was a script run by runghc/runhaskell | Interactive -- ^ we are in GHCi deriving Show #endif --------------------------------------------------------------------------------