diff options
Diffstat (limited to 'Presence')
-rw-r--r-- | Presence/ConsoleWriter.hs | 8 | ||||
-rw-r--r-- | Presence/FGConsole.hs | 25 | ||||
-rw-r--r-- | Presence/Presence.hs | 17 | ||||
-rw-r--r-- | Presence/monitortty.c | 15 |
4 files changed, 42 insertions, 23 deletions
diff --git a/Presence/ConsoleWriter.hs b/Presence/ConsoleWriter.hs index e755b27f..986294f4 100644 --- a/Presence/ConsoleWriter.hs +++ b/Presence/ConsoleWriter.hs | |||
@@ -17,7 +17,6 @@ import Data.Monoid | |||
17 | import Data.Char | 17 | import Data.Char |
18 | import Data.Maybe | 18 | import Data.Maybe |
19 | import System.Environment hiding (setEnv) | 19 | import System.Environment hiding (setEnv) |
20 | import System.Process ( rawSystem ) | ||
21 | import System.Exit ( ExitCode(ExitSuccess) ) | 20 | import System.Exit ( ExitCode(ExitSuccess) ) |
22 | import System.Posix.Env ( setEnv ) | 21 | import System.Posix.Env ( setEnv ) |
23 | import System.Posix.Process ( forkProcess, exitImmediately, executeFile ) | 22 | import System.Posix.Process ( forkProcess, exitImmediately, executeFile ) |
@@ -36,7 +35,7 @@ import qualified Data.Text as Text | |||
36 | import qualified Network.BSD as BSD | 35 | import qualified Network.BSD as BSD |
37 | 36 | ||
38 | import UTmp ( users2, utmp_file, UtmpRecord(..), UT_Type(..) ) | 37 | import UTmp ( users2, utmp_file, UtmpRecord(..), UT_Type(..) ) |
39 | import FGConsole ( monitorTTY ) | 38 | import FGConsole ( forkTTYMonitor ) |
40 | import XMPPServer ( Stanza, makePresenceStanza, JabberShow(..), stanzaType | 39 | import XMPPServer ( Stanza, makePresenceStanza, JabberShow(..), stanzaType |
41 | , LangSpecificMessage(..), msgLangMap, cloneStanza, stanzaFrom ) | 40 | , LangSpecificMessage(..), msgLangMap, cloneStanza, stanzaFrom ) |
42 | import ControlMaybe ( handleIO_ ) | 41 | import ControlMaybe ( handleIO_ ) |
@@ -109,7 +108,7 @@ onLogin cs start = \e -> do | |||
109 | -- | Sets up threads to monitor tty switches and logins that are | 108 | -- | Sets up threads to monitor tty switches and logins that are |
110 | -- written to the system utmp file and returns a 'ConsoleWriter' | 109 | -- written to the system utmp file and returns a 'ConsoleWriter' |
111 | -- object for interacting with that information. | 110 | -- object for interacting with that information. |
112 | newConsoleWriter :: IO ConsoleWriter | 111 | newConsoleWriter :: IO (Maybe ConsoleWriter) |
113 | newConsoleWriter = do | 112 | newConsoleWriter = do |
114 | chan <- atomically $ newEmptyTMVar | 113 | chan <- atomically $ newEmptyTMVar |
115 | cs <- atomically $ do | 114 | cs <- atomically $ do |
@@ -136,7 +135,8 @@ newConsoleWriter = do | |||
136 | inotify <- initINotify | 135 | inotify <- initINotify |
137 | 136 | ||
138 | -- get active tty | 137 | -- get active tty |
139 | mtty <- monitorTTY (onTTY outvar cs) | 138 | mtty <- forkTTYMonitor (onTTY outvar cs) |
139 | forM mtty $ \_ -> do | ||
140 | atomically $ retryWhen (readTVar $ csActiveTTY cs) (==0) | 140 | atomically $ retryWhen (readTVar $ csActiveTTY cs) (==0) |
141 | 141 | ||
142 | -- read utmp | 142 | -- read utmp |
diff --git a/Presence/FGConsole.hs b/Presence/FGConsole.hs index 623fb493..03aaebf2 100644 --- a/Presence/FGConsole.hs +++ b/Presence/FGConsole.hs | |||
@@ -11,7 +11,6 @@ import Unsafe.Coerce | |||
11 | import Control.Exception as E | 11 | import Control.Exception as E |
12 | -- import Prelude as E | 12 | -- import Prelude as E |
13 | import Control.Monad | 13 | import Control.Monad |
14 | import Foreign.C.Error | ||
15 | import Foreign.C | 14 | import Foreign.C |
16 | 15 | ||
17 | import Logging | 16 | import Logging |
@@ -19,12 +18,13 @@ import System.Posix.Signals | |||
19 | 18 | ||
20 | -- c_monitorTTY fd = trace "c_monitorTTY" (return ()) -- (trace "WTF" todo) | 19 | -- c_monitorTTY fd = trace "c_monitorTTY" (return ()) -- (trace "WTF" todo) |
21 | 20 | ||
22 | foreign import ccall "monitorTTY" c_monitorTTY :: Fd -> IO () | 21 | foreign import ccall "monitorTTY" c_monitorTTY :: Fd -> IO CInt |
23 | foreign import ccall "closeTTY" c_closeTTY :: IO () | 22 | foreign import ccall "closeTTY" c_closeTTY :: IO () |
24 | 23 | ||
25 | monitorTTY :: (Word8 -> IO ()) -> IO (Fd,ThreadId) | 24 | forkTTYMonitor :: (Word8 -> IO ()) -> IO (Maybe (Fd,ThreadId)) |
26 | monitorTTY handler = do | 25 | forkTTYMonitor handler = do |
27 | (rfd,wfd) <- createPipe | 26 | (rfd,wfd) <- createPipe |
27 | retvar <- newEmptyMVar | ||
28 | thread <- forkIO $ do | 28 | thread <- forkIO $ do |
29 | let cleanup = do | 29 | let cleanup = do |
30 | trace "quitting monitorTTY thread." (return ()) | 30 | trace "quitting monitorTTY thread." (return ()) |
@@ -32,8 +32,10 @@ monitorTTY handler = do | |||
32 | closeFd rfd `E.catch` \(e::IOException) -> return () | 32 | closeFd rfd `E.catch` \(e::IOException) -> return () |
33 | c_closeTTY | 33 | c_closeTTY |
34 | -- rh <- fdToHandle rfd | 34 | -- rh <- fdToHandle rfd |
35 | c_monitorTTY wfd | 35 | didfork <- c_monitorTTY wfd |
36 | let monitor = | 36 | putMVar retvar didfork |
37 | when (didfork == 0) $ do | ||
38 | let monitor = | ||
37 | (do | 39 | (do |
38 | threadWaitRead rfd | 40 | threadWaitRead rfd |
39 | (cs,cnt) <- fdRead rfd 1 | 41 | (cs,cnt) <- fdRead rfd 1 |
@@ -45,13 +47,16 @@ monitorTTY handler = do | |||
45 | case () of | 47 | case () of |
46 | _ | err==eAGAIN -> monitor | 48 | _ | err==eAGAIN -> monitor |
47 | _ | otherwise -> cleanup | 49 | _ | otherwise -> cleanup |
48 | `E.catch` | 50 | `E.catch` |
49 | \(e :: AsyncException) -> cleanup | 51 | \(e :: AsyncException) -> cleanup |
50 | monitor | 52 | monitor |
51 | return (rfd,thread) | 53 | didfork <- takeMVar retvar |
54 | if didfork == 0 | ||
55 | then return $! Just (rfd,thread) | ||
56 | else return $! Nothing | ||
52 | 57 | ||
53 | unmonitorTTY :: (Fd, ThreadId) -> IO () | 58 | killTTYMonitor :: (Fd, ThreadId) -> IO () |
54 | unmonitorTTY (rfd,thread) = do | 59 | killTTYMonitor (rfd,thread) = do |
55 | closeFd rfd | 60 | closeFd rfd |
56 | yield | 61 | yield |
57 | killThread thread | 62 | killThread thread |
diff --git a/Presence/Presence.hs b/Presence/Presence.hs index 2344fb75..9660b29f 100644 --- a/Presence/Presence.hs +++ b/Presence/Presence.hs | |||
@@ -148,7 +148,7 @@ data PresenceState = PresenceState | |||
148 | , associatedPeers :: TVar (Map SockAddr ()) | 148 | , associatedPeers :: TVar (Map SockAddr ()) |
149 | , server :: TMVar XMPPServer | 149 | , server :: TMVar XMPPServer |
150 | , keyToChan :: TVar (Map ConnectionKey Conn) | 150 | , keyToChan :: TVar (Map ConnectionKey Conn) |
151 | , consoleWriter :: ConsoleWriter | 151 | , consoleWriter :: Maybe ConsoleWriter |
152 | } | 152 | } |
153 | 153 | ||
154 | 154 | ||
@@ -435,11 +435,11 @@ rewriteJIDForPeer jid = do | |||
435 | in (to',addr) | 435 | in (to',addr) |
436 | 436 | ||
437 | deliverToConsole :: PresenceState -> IO () -> Stanza -> IO () | 437 | deliverToConsole :: PresenceState -> IO () -> Stanza -> IO () |
438 | deliverToConsole state fail msg = do | 438 | deliverToConsole PresenceState{ consoleWriter = Just cw } fail msg = do |
439 | putStrLn $ "TODO: deliver to console" | 439 | did1 <- writeActiveTTY cw msg |
440 | did1 <- writeActiveTTY (consoleWriter state) msg | 440 | did2 <- writeAllPty cw msg |
441 | did2 <- writeAllPty (consoleWriter state) msg | ||
442 | if not (did1 || did2) then fail else return () | 441 | if not (did1 || did2) then fail else return () |
442 | deliverToConsole _ fail _ = fail | ||
443 | 443 | ||
444 | -- | deliver <message/> or error stanza | 444 | -- | deliver <message/> or error stanza |
445 | deliverMessage :: PresenceState | 445 | deliverMessage :: PresenceState |
@@ -636,6 +636,11 @@ informPeerPresence state k stanza = do | |||
636 | sendModifiedStanzaToClient (dup { stanzaFrom=Just from' }) | 636 | sendModifiedStanzaToClient (dup { stanzaFrom=Just from' }) |
637 | (connChan con) | 637 | (connChan con) |
638 | 638 | ||
639 | consoleClients :: PresenceState -> STM (Map Text ClientState) | ||
640 | consoleClients PresenceState{ consoleWriter = Just cw } = readTVar (cwClients cw) | ||
641 | consoleClients _ = return Map.empty | ||
642 | |||
643 | |||
639 | answerProbe :: PresenceState | 644 | answerProbe :: PresenceState |
640 | -> Maybe Text -> ConnectionKey -> TChan Stanza -> IO () | 645 | -> Maybe Text -> ConnectionKey -> TChan Stanza -> IO () |
641 | answerProbe state mto k chan = do | 646 | answerProbe state mto k chan = do |
@@ -671,7 +676,7 @@ answerProbe state mto k chan = do | |||
671 | replies <- runTraversableT $ do | 676 | replies <- runTraversableT $ do |
672 | cbu <- lift . atomically $ readTVar (clientsByUser state) | 677 | cbu <- lift . atomically $ readTVar (clientsByUser state) |
673 | let lpres = maybeToList $ Map.lookup u cbu | 678 | let lpres = maybeToList $ Map.lookup u cbu |
674 | cw <- lift . atomically $ readTVar (cwClients $ consoleWriter state) | 679 | cw <- lift . atomically $ consoleClients state |
675 | clientState <- liftT $ (lpres >>= Map.elems . networkClients) | 680 | clientState <- liftT $ (lpres >>= Map.elems . networkClients) |
676 | ++ Map.elems cw | 681 | ++ Map.elems cw |
677 | stanza <- liftIOMaybe $ atomically (readTVar (clientStatus clientState)) | 682 | stanza <- liftIOMaybe $ atomically (readTVar (clientStatus clientState)) |
diff --git a/Presence/monitortty.c b/Presence/monitortty.c index a9a095cf..7582aa56 100644 --- a/Presence/monitortty.c +++ b/Presence/monitortty.c | |||
@@ -146,10 +146,19 @@ void *write_vtch(void *pfd) { | |||
146 | } | 146 | } |
147 | 147 | ||
148 | 148 | ||
149 | void monitorTTY(int fd) { | 149 | // Returns 0 on success. |
150 | int monitorTTY(int fd) { | ||
151 | int er = -1, dev = -1; | ||
150 | pthread_mutex_init(&mu,NULL); | 152 | pthread_mutex_init(&mu,NULL); |
151 | // printf ("Hello world.\n"); | 153 | // Ensure we can open a device before we bother forking a thread. |
152 | pthread_create (&mt, NULL, write_vtch, (void*)(intptr_t)fd); | 154 | dev = ttyfd(); |
155 | if( dev != -1 ) { | ||
156 | er = pthread_create (&mt, NULL, write_vtch, (void*)(intptr_t)fd); | ||
157 | return er; | ||
158 | } | ||
159 | else { | ||
160 | return -1; | ||
161 | } | ||
153 | } | 162 | } |
154 | 163 | ||
155 | void closeTTY() { | 164 | void closeTTY() { |