diff options
Diffstat (limited to 'Presence/FGConsole.hs')
-rw-r--r-- | Presence/FGConsole.hs | 62 |
1 files changed, 62 insertions, 0 deletions
diff --git a/Presence/FGConsole.hs b/Presence/FGConsole.hs new file mode 100644 index 00000000..623fb493 --- /dev/null +++ b/Presence/FGConsole.hs | |||
@@ -0,0 +1,62 @@ | |||
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.Error | ||
15 | import Foreign.C | ||
16 | |||
17 | import Logging | ||
18 | import System.Posix.Signals | ||
19 | |||
20 | -- c_monitorTTY fd = trace "c_monitorTTY" (return ()) -- (trace "WTF" todo) | ||
21 | |||
22 | foreign import ccall "monitorTTY" c_monitorTTY :: Fd -> IO () | ||
23 | foreign import ccall "closeTTY" c_closeTTY :: IO () | ||
24 | |||
25 | monitorTTY :: (Word8 -> IO ()) -> IO (Fd,ThreadId) | ||
26 | monitorTTY handler = do | ||
27 | (rfd,wfd) <- createPipe | ||
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 | c_monitorTTY wfd | ||
36 | let monitor = | ||
37 | (do | ||
38 | threadWaitRead rfd | ||
39 | (cs,cnt) <- fdRead rfd 1 | ||
40 | forM_ cs (handler . unsafeCoerce {- . trace "read byte" -}) | ||
41 | monitor) | ||
42 | `E.catch` | ||
43 | \(e :: IOException) -> do | ||
44 | err <- getErrno | ||
45 | case () of | ||
46 | _ | err==eAGAIN -> monitor | ||
47 | _ | otherwise -> cleanup | ||
48 | `E.catch` | ||
49 | \(e :: AsyncException) -> cleanup | ||
50 | monitor | ||
51 | return (rfd,thread) | ||
52 | |||
53 | unmonitorTTY :: (Fd, ThreadId) -> IO () | ||
54 | unmonitorTTY (rfd,thread) = do | ||
55 | closeFd rfd | ||
56 | yield | ||
57 | killThread thread | ||
58 | raiseSignal sigUSR1 | ||
59 | -- threadDelay 1000000 | ||
60 | |||
61 | |||
62 | -- vim:ft=haskell: | ||