summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--consolation.hs65
1 files changed, 45 insertions, 20 deletions
diff --git a/consolation.hs b/consolation.hs
index bced2839..640b51c2 100644
--- a/consolation.hs
+++ b/consolation.hs
@@ -6,6 +6,7 @@ import Control.Applicative
6import Control.Concurrent 6import Control.Concurrent
7import Control.Concurrent.STM 7import Control.Concurrent.STM
8import Data.Monoid 8import Data.Monoid
9import Data.Char
9import System.INotify ( initINotify, EventVariety(Modify), addWatch ) 10import System.INotify ( initINotify, EventVariety(Modify), addWatch )
10import Data.Word ( Word8 ) 11import Data.Word ( Word8 )
11import Data.Text ( Text ) 12import Data.Text ( Text )
@@ -43,14 +44,23 @@ onLogin cs start = \e -> do
43 Traversable.mapM (flip writeTVar Nothing) dead 44 Traversable.mapM (flip writeTVar Nothing) dead
44 writeTVar (csUtmp cs) $ (old `Map.union` newborn) Map.\\ dead 45 writeTVar (csUtmp cs) $ (old `Map.union` newborn) Map.\\ dead
45 return newborn 46 return newborn
47 let getActive = do
48 tty <- readTVar $ csActiveTTY cs
49 utmp <- readTVar $ csUtmp cs
50 flip (maybe $ return (tty,Nothing))
51 (Map.lookup ("tty"<>tshow tty) utmp)
52 $ \tuvar -> do
53 tu <- readTVar tuvar
54 return (tty,tu)
55
46 forM_ (Map.elems newborn) $ 56 forM_ (Map.elems newborn) $
47 forkIO . start (csActiveTTY cs) 57 forkIO . start getActive
48 -- forM_ (Map.elems dead ) $ putStrLn . ("gone: "++) . show 58 -- forM_ (Map.elems dead ) $ putStrLn . ("gone: "++) . show
49 59
50onTTY cs vtnum = atomically $ writeTVar (csActiveTTY cs) vtnum 60onTTY cs vtnum = atomically $ writeTVar (csActiveTTY cs) vtnum
51 61
52retryWhen var pred = do 62retryWhen var pred = do
53 value <- readTVar var 63 value <- var
54 if pred value then retry 64 if pred value then retry
55 else return value 65 else return value
56 66
@@ -71,38 +81,53 @@ ujid u = do
71 h <- textHostName 81 h <- textHostName
72 return $ utmpUser u <> "@" <> h <> "/" <> resource u 82 return $ utmpUser u <> "@" <> h <> "/" <> resource u
73 83
74newCon :: (Text -> IO ()) -> TVar Word8 -> TVar (Maybe UtmpRecord) -> IO () 84newCon :: (Text -> IO ()) -> STM (Word8,Maybe UtmpRecord) -> TVar (Maybe UtmpRecord) -> IO ()
75newCon log activeTTY utmp = do 85newCon log activeTTY utmp = do
76 (tty,u) <- atomically $ 86 ((tty,tu),u) <- atomically $
77 liftM2 (,) (readTVar activeTTY) 87 liftM2 (,) activeTTY
78 (readTVar utmp) 88 (readTVar utmp)
79 flip (maybe $ return ()) u $ \u -> do 89 flip (maybe $ return ()) u $ \u -> do
80 jid <- ujid u 90 jid <- ujid u
81 log $ status (resource u) tty <> " " <> jid <> " pid=" <> tshow (utmpPid u) 91 log $ status (resource u) tty tu <> " " <> jid <> " pid=" <> tshow (utmpPid u)
82 loop tty (Just u) 92 <> if istty (resource u)
93 then " host=" <> tshow (utmpHost u)
94 else ""
95 loop tty tu (Just u)
83 where 96 where
84 bstatus r ttynum = r == "tty" <> tshow ttynum 97 bstatus r ttynum mtu
85 status r ttynum = 98 = r == ttystr
86 if bstatus r ttynum 99 || match mtu
100 where ttystr = "tty" <> tshow ttynum
101 searchstr mtu = maybe ttystr utmpHost $ do
102 tu <- mtu
103 guard (not $ Text.null $ utmpHost tu)
104 return tu
105 match mtu = searchstr mtu `Text.isInfixOf` Text.dropWhile (/=':') r
106 status r ttynum tu =
107 if bstatus r ttynum tu
87 then "Available" 108 then "Available"
88 else "Away " 109 else "Away "
89 110
90 loop tty u = do 111 istty r = fst3 == "tty" && Text.all isDigit rst
112 where
113 (fst3,rst) = Text.splitAt 3 r
114
115 loop tty tu u = do
91 what <- atomically $ foldr1 orElse 116 what <- atomically $ foldr1 orElse
92 [ do tty' <- retryWhen activeTTY 117 [ do (tty',tu') <- retryWhen activeTTY
93 (\tty' -> bstatus r tty == bstatus r tty') 118 (\ttyu -> bstatus r tty tu == uncurry (bstatus r) ttyu)
94 return $ ttyChanged tty' 119 return $ ttyChanged tty' tu'
95 , do u' <- retryWhen utmp (==u) 120 , do u' <- retryWhen (readTVar utmp) (==u)
96 return $ utmpChanged u' 121 return $ utmpChanged u'
97 ] 122 ]
98 what 123 what
99 where 124 where
100 r = maybe "" resource u 125 r = maybe "" resource u
101 126
102 ttyChanged tty' = do 127 ttyChanged tty' tu' = do
103 jid <- maybe (return "") ujid u 128 jid <- maybe (return "") ujid u
104 log $ status r tty' <> " " <> jid 129 log $ status r tty' tu' <> " " <> jid
105 loop tty' u 130 loop tty' tu' u
106 131
107 utmpChanged u' = maybe dead changed u' 132 utmpChanged u' = maybe dead changed u'
108 where 133 where
@@ -110,7 +135,7 @@ newCon log activeTTY utmp = do
110 jid0 <- maybe (return "") ujid u 135 jid0 <- maybe (return "") ujid u
111 jid <- ujid u' 136 jid <- ujid u'
112 log $ "changed: " <> jid0 <> " --> " <> jid 137 log $ "changed: " <> jid0 <> " --> " <> jid
113 loop tty (Just u') 138 loop tty tu (Just u')
114 dead = do 139 dead = do
115 jid <- maybe (return "") ujid u 140 jid <- maybe (return "") ujid u
116 log $ "Offline " <> jid 141 log $ "Offline " <> jid
@@ -129,7 +154,7 @@ main = do
129 154
130 -- get active tty 155 -- get active tty
131 mtty <- monitorTTY (onTTY cs) 156 mtty <- monitorTTY (onTTY cs)
132 atomically $ retryWhen (csActiveTTY cs) (==0) 157 atomically $ retryWhen (readTVar $ csActiveTTY cs) (==0)
133 158
134 -- read utmp 159 -- read utmp
135 onLogin cs (newCon $ logit outvar) Modify 160 onLogin cs (newCon $ logit outvar) Modify