{-# LANGUAGE CPP #-} module DoRequest(XCallState,initXCall,doRequest,getAsyncInput) where import Control.Applicative --import DialogueIO import P_IO_data import ContinuationIO(stdin,stdout,stderr) import System.Environment as IO(getEnv,getProgName) #ifdef __HUGS__ import System(system) import Control.Exception(bracket) #else import System.Process(system) import System.IO(withBinaryFile) #endif import System.Exit as IO import qualified IOUtil as IO import qualified System.IO as IO --import qualified System.IO.Error as IO import System.Directory #ifdef MIN_VERSION_bytestring import qualified Data.ByteString.Lazy as BS #endif #ifdef MIN_VERSION_old_time import System.Time(getClockTime,toCalendarTime) #endif #ifdef MIN_VERSION_time import Data.Time(getCurrentTime,getZonedTime) #endif import XCall import CmdLineEnv(argFlag) --import System import Prelude hiding (IOError) --import Ap deb = argFlag "dorequest" False doRequest = if not deb then doRequest' else \state req -> do eprint req resp <- doRequest' state req eprint resp return resp where eprint x = IO.hPutStrLn IO.stderr . take 239 . show $ x --doRequest' :: XCallState -> Request -> IO Response doRequest' state req = case req of ReadFile filename -> rdCatch (readFile filename) WriteFile filename contents -> wrCatch (writeFile filename contents) ReadBinaryFile filename -> rdCatch (readBinaryFile filename) WriteBinaryFile filename contents -> wrCatch (writeBinaryFile filename contents) #ifdef MIN_VERSION_bytestring ReadBinFile filename -> rdCatch' Bn (BS.readFile filename) WriteBinFile filename contents -> wrCatch (BS.writeFile filename contents) AppendBinFile filename contents -> wrCatch (BS.appendFile filename contents) #endif AppendFile filename contents -> wrCatch (appendFile filename contents) StatusFile filename -> catchIo SearchError (statusFile filename) where statusFile path = do f <- doesFileExist path if f then permissions 'f' path else do d <- doesDirectoryExist path if d then permissions 'd' path else fail path permissions t path = do p <- getPermissions path let r = if readable p then 'r' else '-' w = if writable p then 'w' else '-' return (Str [t,r,w]) RenameFile from to -> otCatch (renameFile from to>>ok) GetCurrentDirectory -> Str <$> getCurrentDirectory #ifdef MIN_VERSION_old_time GetModificationTime path -> catchIo SearchError (ClockTime <$> IO.getModificationTime path) #else GetModificationTime path -> catchIo SearchError (UTCTime <$> IO.getModificationTime path) #endif ReadDirectory dir -> rdCatch' StrList (getDirectoryContents dir) DeleteFile filename -> otCatch (removeFile filename>>ok) CreateDirectory path mask -> otCatch (createDirectory path>>ok) #ifndef __HUGS__ ReadXdgFile xdg path -> rdCatch $ do dir <- getAppXdgDir xdg readFile (dir++"/"++path) WriteXdgFile xdg path s -> wrCatch $ do dir <- getAppXdgDir xdg createDirectoryIfMissing True dir writeFile (dir++"/"++path) s #endif ReadChan channelname -> if channelname==stdin then rdCatch getContents else rfail $ ReadError $ "ReadChan: unknown channel "++channelname AppendChan channelname contents | channelname==stdout -> wr IO.stdout | channelname==stderr -> wr IO.stderr | otherwise -> rfail $ WriteError $ "AppendChan: unknown channel "++channelname where wr chan = wrCatch (IO.hPutStr chan contents>>IO.hFlush chan) XRequest _ -> doXCall state req XCommand _ -> doXCall state req GetAsyncInput -> doSCall state req SocketRequest _ -> doSCall state req Select _ -> doSCall state req Exit n -> exitWith (if n==0 then ExitSuccess else ExitFailure n) #ifdef MIN_VERSION_old_time GetLocalTime -> otCatch $ do CalendarTime <$> (toCalendarTime =<< getClockTime) --s <- readIO (formatCalendarTime undefined "%s" t) --GHC bug(?) workaround: --let s = ctSec t+60*(ctMin t+60*(ctHour t)) --return (Dbl (fromIntegral s)) GetTime -> otCatch $ ClockTime <$> getClockTime ToCalendarTime t -> CalendarTime <$> toCalendarTime t #endif GetEnv var -> catchIo SearchError (Str <$> getEnv var) System cmd -> do exitcode <- system cmd case exitcode of ExitSuccess -> ok ExitFailure n -> rfail $ OtherError $ "System: Return code="++show n #ifdef MIN_VERSION_time GetCurrentTime -> otCatch $ UTCTime <$> getCurrentTime GetZonedTime -> otCatch $ ZonedTime <$> getZonedTime #endif -- StrIO (Opaque io) -> otCatch $ Str <$> io _ -> do IO.hPutStrLn IO.stderr msg rfail $ OtherError msg where msg = "doRequest: unimplemented request: "++show req --getAsyncInput state = otCatch $ getAsyncInput' state rdCatch = rdCatch' Str rdCatch' c io = catchIo ReadError (c <$> io) wrCatch io = catchIo WriteError (io >> ok) #ifdef __HUGS__ otCatch io = catchIo OtherError io catchIo e io = IO.catch io (rfail . e . show) ok :: IO Response ok = return Success rfail e = return (Failure e) #endif ---- Should be put elsewhere: -- #ifndef __GLASGOW_HASKELL__ -- instance Functor IO where map f io = io >>= (return . f) -- #endif -- readBinaryFile path = IO.hGetContents =<< IO.openBinaryFile path IO.ReadMode writeBinaryFile path s = withBinaryFile path IO.WriteMode (flip IO.hPutStr s) #ifndef __HUGS__ getAppXdgDir xdg = getXdgDirectory xdg =<< getProgName #endif #ifdef __HUGS__ withBinaryFile path mode = bracket (IO.openBinaryFile path mode) IO.hClose #endif