diff options
author | joe <joe@jerkface.net> | 2013-06-17 21:34:56 -0400 |
---|---|---|
committer | joe <joe@jerkface.net> | 2013-06-17 21:34:56 -0400 |
commit | 012a3b625c0ea236afc1ea09c89d0dcd435a66bd (patch) | |
tree | ba105c111665d0587620b76ff18c8b21076fb3f3 | |
parent | cc93b83b5a8c9e00839777c59991c5eb8cf0d75a (diff) |
State changes on vt switch.
-rw-r--r-- | Presence/ByteStringOperators.hs | 20 | ||||
-rw-r--r-- | Presence/main.hs | 49 |
2 files changed, 57 insertions, 12 deletions
diff --git a/Presence/ByteStringOperators.hs b/Presence/ByteStringOperators.hs index 26b64bcf..2815f05a 100644 --- a/Presence/ByteStringOperators.hs +++ b/Presence/ByteStringOperators.hs | |||
@@ -3,6 +3,11 @@ module ByteStringOperators where | |||
3 | import qualified Data.ByteString as S (ByteString) | 3 | import qualified Data.ByteString as S (ByteString) |
4 | import Data.ByteString.Lazy.Char8 as L | 4 | import Data.ByteString.Lazy.Char8 as L |
5 | 5 | ||
6 | -- These two were imported to provide an NFData instance. | ||
7 | import qualified Data.ByteString.Lazy.Internal as L (ByteString(..)) | ||
8 | import Control.DeepSeq | ||
9 | |||
10 | |||
6 | (<++>) :: ByteString -> ByteString -> ByteString | 11 | (<++>) :: ByteString -> ByteString -> ByteString |
7 | (<++.>) :: ByteString -> S.ByteString -> ByteString | 12 | (<++.>) :: ByteString -> S.ByteString -> ByteString |
8 | (<.++>) :: S.ByteString -> ByteString -> ByteString | 13 | (<.++>) :: S.ByteString -> ByteString -> ByteString |
@@ -16,5 +21,20 @@ infixr 5 <.++> | |||
16 | infixr 5 <++> | 21 | infixr 5 <++> |
17 | infixr 5 <++.> | 22 | infixr 5 <++.> |
18 | 23 | ||
24 | Nothing <?++> b = b | ||
25 | Just a <?++> b = a <++> b | ||
26 | infixr 5 <?++> | ||
27 | |||
28 | a <++?> Nothing = a | ||
29 | a <++?> Just b = a <++> b | ||
30 | infixr 5 <++?> | ||
31 | |||
19 | bshow :: Show a => a -> ByteString | 32 | bshow :: Show a => a -> ByteString |
20 | bshow = L.pack . show | 33 | bshow = L.pack . show |
34 | |||
35 | |||
36 | instance NFData L.ByteString where | ||
37 | rnf L.Empty = () | ||
38 | rnf (L.Chunk _ b) = rnf b | ||
39 | |||
40 | |||
diff --git a/Presence/main.hs b/Presence/main.hs index 36796b6e..ff2f18cf 100644 --- a/Presence/main.hs +++ b/Presence/main.hs | |||
@@ -9,6 +9,7 @@ import System.Posix.Signals | |||
9 | import System.Posix.Types | 9 | import System.Posix.Types |
10 | import System.Posix.Process | 10 | import System.Posix.Process |
11 | import Data.Maybe | 11 | import Data.Maybe |
12 | import Data.Char | ||
12 | 13 | ||
13 | import System.INotify | 14 | import System.INotify |
14 | #ifndef NOUTMP | 15 | #ifndef NOUTMP |
@@ -31,22 +32,40 @@ import LocalPeerCred | |||
31 | import System.Posix.User | 32 | import System.Posix.User |
32 | import qualified Data.Set as Set | 33 | import qualified Data.Set as Set |
33 | import Data.Set as Set (Set,(\\)) | 34 | import Data.Set as Set (Set,(\\)) |
35 | import Control.Concurrent.MVar.Strict | ||
36 | import Control.DeepSeq | ||
34 | 37 | ||
35 | import ByteStringOperators | 38 | import ByteStringOperators |
36 | import qualified Data.ByteString.Lazy.Char8 as L | 39 | import qualified Data.ByteString.Lazy.Char8 as L |
37 | import Data.ByteString.Lazy.Char8 as L (putStrLn) | 40 | import Data.ByteString.Lazy.Char8 as L (ByteString,putStrLn) |
38 | import qualified Prelude | 41 | import qualified Prelude |
39 | import Prelude hiding (putStrLn) | 42 | import Prelude hiding (putStrLn) |
40 | 43 | ||
41 | 44 | ||
42 | jid user host rsrc = user <++> "@" <++> host <++> "/" <++> rsrc | 45 | -- | Jabber ID (JID) datatype |
46 | data JID = JID { name :: Maybe ByteString | ||
47 | -- ^ Account name | ||
48 | , server :: ByteString | ||
49 | -- ^ Server adress | ||
50 | , resource :: Maybe ByteString | ||
51 | -- ^ Resource name | ||
52 | } | ||
53 | deriving (Ord,Eq) | ||
54 | |||
55 | instance Show JID where | ||
56 | show (JID n s r ) = L.unpack $ fmap (<++>"@") n <?++> s <++?> fmap ("/"<++>) r | ||
57 | |||
58 | instance NFData JID where | ||
59 | rnf v@(JID n s r) = n `seq` s `seq` r `seq` () | ||
60 | |||
61 | jid user host rsrc = JID (Just user) host (Just rsrc) -- user <++> "@" <++> host <++> "/" <++> rsrc | ||
43 | 62 | ||
44 | toJabberId host (user,tty,_) = | 63 | toJabberId host (user,tty,_) = |
45 | if L.take 3 tty == "tty" | 64 | if L.take 3 tty == "tty" |
46 | then Just (jid user host tty) | 65 | then Just (jid user host tty) |
47 | else Nothing | 66 | else Nothing |
48 | 67 | ||
49 | track_login :: IORef (Set L.ByteString) -> t -> IO () | 68 | track_login :: MVar (Set JID) -> t -> IO () |
50 | track_login tracked e = do | 69 | track_login tracked e = do |
51 | #ifndef NOUTMP | 70 | #ifndef NOUTMP |
52 | us <- users | 71 | us <- users |
@@ -54,15 +73,13 @@ track_login tracked e = do | |||
54 | let us = [] | 73 | let us = [] |
55 | #endif | 74 | #endif |
56 | let ids = Set.fromList $ mapMaybe (toJabberId "localhost") us | 75 | let ids = Set.fromList $ mapMaybe (toJabberId "localhost") us |
57 | -- forM_ ids L.putStrLn | 76 | state <- swapMVar tracked ids |
58 | state <- readIORef tracked | ||
59 | let arrivals = ids \\ state | 77 | let arrivals = ids \\ state |
60 | departures = state \\ ids | 78 | departures = state \\ ids |
61 | forM_ (Set.toList departures) $ \id -> do | 79 | forM_ (Set.toList departures) $ \id -> do |
62 | putStrLn $ id <++> " logged out." | 80 | putStrLn $ bshow id <++> " Offline." |
63 | forM_ (Set.toList arrivals) $ \id -> do | 81 | forM_ (Set.toList arrivals) $ \id -> do |
64 | putStrLn $ id <++> " logged in." | 82 | putStrLn $ bshow id <++> " Available." |
65 | writeIORef tracked ids | ||
66 | 83 | ||
67 | data UnixSession = UnixSession { | 84 | data UnixSession = UnixSession { |
68 | unix_uid :: (IORef (Maybe UserID)), | 85 | unix_uid :: (IORef (Maybe UserID)), |
@@ -99,12 +116,20 @@ instance XMPPSession UnixSession where | |||
99 | return jid | 116 | return jid |
100 | closeSession _ = L.putStrLn "SESSION: close" | 117 | closeSession _ = L.putStrLn "SESSION: close" |
101 | 118 | ||
102 | on_chvt vtnum = do | 119 | on_chvt tracked vtnum = do |
103 | L.putStrLn $ "changed vt to " <++> bshow vtnum | 120 | let tty = L.snoc "tty" $ intToDigit (fromIntegral vtnum) |
121 | L.putStrLn $ "changed vt to " <++> tty | ||
122 | state <- readMVar tracked | ||
123 | forM_ (Set.toList state) $ \jid -> do | ||
124 | case fmap (==tty) $ resource jid of | ||
125 | Just True -> putStrLn $ bshow jid <++> " Available." | ||
126 | Just False -> putStrLn $ bshow jid <++> " Away." | ||
127 | Nothing -> return () | ||
128 | |||
104 | 129 | ||
105 | start :: IO () | 130 | start :: IO () |
106 | start = do | 131 | start = do |
107 | tracked <- newIORef Set.empty | 132 | tracked <- newMVar Set.empty |
108 | let dologin e = track_login tracked e | 133 | let dologin e = track_login tracked e |
109 | dologin :: t -> IO () | 134 | dologin :: t -> IO () |
110 | dologin () | 135 | dologin () |
@@ -120,7 +145,7 @@ start = do | |||
120 | utmp_file | 145 | utmp_file |
121 | dologin | 146 | dologin |
122 | #endif | 147 | #endif |
123 | mtty <- monitorTTY on_chvt | 148 | mtty <- monitorTTY (on_chvt tracked) |
124 | sock <- listenForXmppClients UnixSessions 5222 HNil | 149 | sock <- listenForXmppClients UnixSessions 5222 HNil |
125 | putStrLn "Hit enter to terminate..." | 150 | putStrLn "Hit enter to terminate..." |
126 | getLine | 151 | getLine |