diff options
Diffstat (limited to 'Presence/FGConsole.hs')
-rw-r--r-- | Presence/FGConsole.hs | 67 |
1 files changed, 67 insertions, 0 deletions
diff --git a/Presence/FGConsole.hs b/Presence/FGConsole.hs new file mode 100644 index 00000000..03aaebf2 --- /dev/null +++ b/Presence/FGConsole.hs | |||
@@ -0,0 +1,67 @@ | |||
1 | {-# LANGUAGE ForeignFunctionInterface #-} | ||
2 | {-# LANGUAGE ScopedTypeVariables #-} | ||
3 | module FGConsole where | ||
4 | |||
5 | import Data.Word | ||
6 | import System.Posix.IO | ||
7 | import System.Posix.Types | ||
8 | import Control.Concurrent | ||
9 | -- import GHC.IO.Handle | ||
10 | import Unsafe.Coerce | ||
11 | import Control.Exception as E | ||
12 | -- import Prelude as E | ||
13 | import Control.Monad | ||
14 | import Foreign.C | ||
15 | |||
16 | import Logging | ||
17 | import System.Posix.Signals | ||
18 | |||
19 | -- c_monitorTTY fd = trace "c_monitorTTY" (return ()) -- (trace "WTF" todo) | ||
20 | |||
21 | foreign import ccall "monitorTTY" c_monitorTTY :: Fd -> IO CInt | ||
22 | foreign import ccall "closeTTY" c_closeTTY :: IO () | ||
23 | |||
24 | forkTTYMonitor :: (Word8 -> IO ()) -> IO (Maybe (Fd,ThreadId)) | ||
25 | forkTTYMonitor handler = do | ||
26 | (rfd,wfd) <- createPipe | ||
27 | retvar <- newEmptyMVar | ||
28 | thread <- forkIO $ do | ||
29 | let cleanup = do | ||
30 | trace "quitting monitorTTY thread." (return ()) | ||
31 | closeFd wfd `E.catch` \(e::IOException) -> return () | ||
32 | closeFd rfd `E.catch` \(e::IOException) -> return () | ||
33 | c_closeTTY | ||
34 | -- rh <- fdToHandle rfd | ||
35 | didfork <- c_monitorTTY wfd | ||
36 | putMVar retvar didfork | ||
37 | when (didfork == 0) $ do | ||
38 | let monitor = | ||
39 | (do | ||
40 | threadWaitRead rfd | ||
41 | (cs,cnt) <- fdRead rfd 1 | ||
42 | forM_ cs (handler . unsafeCoerce {- . trace "read byte" -}) | ||
43 | monitor) | ||
44 | `E.catch` | ||
45 | \(e :: IOException) -> do | ||
46 | err <- getErrno | ||
47 | case () of | ||
48 | _ | err==eAGAIN -> monitor | ||
49 | _ | otherwise -> cleanup | ||
50 | `E.catch` | ||
51 | \(e :: AsyncException) -> cleanup | ||
52 | monitor | ||
53 | didfork <- takeMVar retvar | ||
54 | if didfork == 0 | ||
55 | then return $! Just (rfd,thread) | ||
56 | else return $! Nothing | ||
57 | |||
58 | killTTYMonitor :: (Fd, ThreadId) -> IO () | ||
59 | killTTYMonitor (rfd,thread) = do | ||
60 | closeFd rfd | ||
61 | yield | ||
62 | killThread thread | ||
63 | raiseSignal sigUSR1 | ||
64 | -- threadDelay 1000000 | ||
65 | |||
66 | |||
67 | -- vim:ft=haskell: | ||