summaryrefslogtreecommitdiff
path: root/Presence
diff options
context:
space:
mode:
Diffstat (limited to 'Presence')
-rw-r--r--Presence/ConsoleWriter.hs8
-rw-r--r--Presence/FGConsole.hs25
-rw-r--r--Presence/Presence.hs17
-rw-r--r--Presence/monitortty.c15
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
17import Data.Char 17import Data.Char
18import Data.Maybe 18import Data.Maybe
19import System.Environment hiding (setEnv) 19import System.Environment hiding (setEnv)
20import System.Process ( rawSystem )
21import System.Exit ( ExitCode(ExitSuccess) ) 20import System.Exit ( ExitCode(ExitSuccess) )
22import System.Posix.Env ( setEnv ) 21import System.Posix.Env ( setEnv )
23import System.Posix.Process ( forkProcess, exitImmediately, executeFile ) 22import System.Posix.Process ( forkProcess, exitImmediately, executeFile )
@@ -36,7 +35,7 @@ import qualified Data.Text as Text
36import qualified Network.BSD as BSD 35import qualified Network.BSD as BSD
37 36
38import UTmp ( users2, utmp_file, UtmpRecord(..), UT_Type(..) ) 37import UTmp ( users2, utmp_file, UtmpRecord(..), UT_Type(..) )
39import FGConsole ( monitorTTY ) 38import FGConsole ( forkTTYMonitor )
40import XMPPServer ( Stanza, makePresenceStanza, JabberShow(..), stanzaType 39import XMPPServer ( Stanza, makePresenceStanza, JabberShow(..), stanzaType
41 , LangSpecificMessage(..), msgLangMap, cloneStanza, stanzaFrom ) 40 , LangSpecificMessage(..), msgLangMap, cloneStanza, stanzaFrom )
42import ControlMaybe ( handleIO_ ) 41import 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.
112newConsoleWriter :: IO ConsoleWriter 111newConsoleWriter :: IO (Maybe ConsoleWriter)
113newConsoleWriter = do 112newConsoleWriter = 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
11import Control.Exception as E 11import Control.Exception as E
12-- import Prelude as E 12-- import Prelude as E
13import Control.Monad 13import Control.Monad
14import Foreign.C.Error
15import Foreign.C 14import Foreign.C
16 15
17import Logging 16import 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
22foreign import ccall "monitorTTY" c_monitorTTY :: Fd -> IO () 21foreign import ccall "monitorTTY" c_monitorTTY :: Fd -> IO CInt
23foreign import ccall "closeTTY" c_closeTTY :: IO () 22foreign import ccall "closeTTY" c_closeTTY :: IO ()
24 23
25monitorTTY :: (Word8 -> IO ()) -> IO (Fd,ThreadId) 24forkTTYMonitor :: (Word8 -> IO ()) -> IO (Maybe (Fd,ThreadId))
26monitorTTY handler = do 25forkTTYMonitor 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
53unmonitorTTY :: (Fd, ThreadId) -> IO () 58killTTYMonitor :: (Fd, ThreadId) -> IO ()
54unmonitorTTY (rfd,thread) = do 59killTTYMonitor (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
437deliverToConsole :: PresenceState -> IO () -> Stanza -> IO () 437deliverToConsole :: PresenceState -> IO () -> Stanza -> IO ()
438deliverToConsole state fail msg = do 438deliverToConsole 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 ()
442deliverToConsole _ fail _ = fail
443 443
444-- | deliver <message/> or error stanza 444-- | deliver <message/> or error stanza
445deliverMessage :: PresenceState 445deliverMessage :: 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
639consoleClients :: PresenceState -> STM (Map Text ClientState)
640consoleClients PresenceState{ consoleWriter = Just cw } = readTVar (cwClients cw)
641consoleClients _ = return Map.empty
642
643
639answerProbe :: PresenceState 644answerProbe :: PresenceState
640 -> Maybe Text -> ConnectionKey -> TChan Stanza -> IO () 645 -> Maybe Text -> ConnectionKey -> TChan Stanza -> IO ()
641answerProbe state mto k chan = do 646answerProbe 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
149void monitorTTY(int fd) { 149// Returns 0 on success.
150int 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
155void closeTTY() { 164void closeTTY() {