diff options
-rw-r--r-- | Presence/ControlMaybe.hs | 9 | ||||
-rw-r--r-- | Presence/LocalPeerCred.hs | 6 | ||||
-rw-r--r-- | Presence/XMPP.hs | 42 | ||||
-rw-r--r-- | whosocket.hs | 91 |
4 files changed, 123 insertions, 25 deletions
diff --git a/Presence/ControlMaybe.hs b/Presence/ControlMaybe.hs index e277df12..37f6f93c 100644 --- a/Presence/ControlMaybe.hs +++ b/Presence/ControlMaybe.hs | |||
@@ -1,5 +1,9 @@ | |||
1 | {-# LANGUAGE ScopedTypeVariables #-} | ||
1 | module ControlMaybe where | 2 | module ControlMaybe where |
2 | 3 | ||
4 | -- import GHC.IO.Exception (IOException(..)) | ||
5 | import Control.Exception as Exception (IOException(..),catch) | ||
6 | |||
3 | withJust (Just x) f = f x | 7 | withJust (Just x) f = f x |
4 | withJust Nothing f = return () | 8 | withJust Nothing f = return () |
5 | 9 | ||
@@ -8,3 +12,8 @@ whenJust acn f = do | |||
8 | withJust x f | 12 | withJust x f |
9 | 13 | ||
10 | 14 | ||
15 | catchIO_ :: IO a -> IO a -> IO a | ||
16 | catchIO_ a h = Exception.catch a (\(_ :: IOException) -> h) | ||
17 | |||
18 | handleIO_ = flip catchIO_ | ||
19 | |||
diff --git a/Presence/LocalPeerCred.hs b/Presence/LocalPeerCred.hs index d3b8d189..b6ec9491 100644 --- a/Presence/LocalPeerCred.hs +++ b/Presence/LocalPeerCred.hs | |||
@@ -57,7 +57,7 @@ getLocalPeerCred sock = do | |||
57 | addr <- getPeerName sock | 57 | addr <- getPeerName sock |
58 | muid <- getLocalPeerCred' addr | 58 | muid <- getLocalPeerCred' addr |
59 | case muid of | 59 | case muid of |
60 | Just uid -> return (Just uid) | 60 | Just (uid,inode) -> return (Just uid) |
61 | Nothing -> trace "proc failed." $ fmap (validate . CUid . fromIntegral . sndOf3) (getPeerCred sock) | 61 | Nothing -> trace "proc failed." $ fmap (validate . CUid . fromIntegral . sndOf3) (getPeerCred sock) |
62 | where sndOf3 (pid,uid,gid) = uid | 62 | where sndOf3 (pid,uid,gid) = uid |
63 | where | 63 | where |
@@ -81,10 +81,12 @@ parseProcNet port host h = do | |||
81 | addr <- fmap parseHex $ listToMaybe zs | 81 | addr <- fmap parseHex $ listToMaybe zs |
82 | port <- fmap (fromIntegral . as16 . decode . parseHex) $ listToMaybe $ snd (Prelude.splitAt 1 zs) | 82 | port <- fmap (fromIntegral . as16 . decode . parseHex) $ listToMaybe $ snd (Prelude.splitAt 1 zs) |
83 | let ys' = snd (Prelude.splitAt 5 (tail ys)) | 83 | let ys' = snd (Prelude.splitAt 5 (tail ys)) |
84 | ys'' = snd (Prelude.splitAt 2 ys') | ||
84 | uid <- listToMaybe ys' | 85 | uid <- listToMaybe ys' |
86 | inode <- listToMaybe ys'' | ||
85 | let peer = (port,decode addr) | 87 | let peer = (port,decode addr) |
86 | user = toEnum (read (unpack uid) ::Int) ::UserID -- CUid . fromIntegral $ (read (unpack uid)::Int) | 88 | user = toEnum (read (unpack uid) ::Int) ::UserID -- CUid . fromIntegral $ (read (unpack uid)::Int) |
87 | return $ {- trace ("peer:"++show(peer,user)) -} (peer,user) | 89 | return $ {-trace ("peer:"++show(peer,user,inode))-} (peer,(user,inode)) |
88 | ) | 90 | ) |
89 | fmap snd . listToMaybe $ filter ((==(port,host)).fst) rs | 91 | fmap snd . listToMaybe $ filter ((==(port,host)).fst) rs |
90 | {- trace ("found: "++show u) -} | 92 | {- trace ("found: "++show u) -} |
diff --git a/Presence/XMPP.hs b/Presence/XMPP.hs index 3f81f000..d35e5617 100644 --- a/Presence/XMPP.hs +++ b/Presence/XMPP.hs | |||
@@ -241,21 +241,25 @@ tagName (EventBeginElement n _) = n | |||
241 | tagName _ = "" | 241 | tagName _ = "" |
242 | 242 | ||
243 | handleIQSetBind session cmdChan stanza_id = do | 243 | handleIQSetBind session cmdChan stanza_id = do |
244 | whenJust nextElement $ \child -> do | 244 | mchild <- nextElement |
245 | let unhandledBind = liftIO $ putStrLn $ "unhandled-bind: "++show child | 245 | case mchild of |
246 | case tagName child of | 246 | Just child -> do |
247 | "{urn:ietf:params:xml:ns:xmpp-bind}resource" | 247 | let unhandledBind = liftIO $ putStrLn $ "unhandled-bind: "++show child |
248 | -> do | 248 | case tagName child of |
249 | rsc <- lift content | 249 | "{urn:ietf:params:xml:ns:xmpp-bind}resource" |
250 | liftIO $ do | 250 | -> do |
251 | putStrLn $ "iq-set-bind-resource " ++ show rsc | 251 | rsc <- lift content |
252 | setResource session (L.fromChunks [S.encodeUtf8 rsc]) | 252 | liftIO $ do |
253 | jid <- getJID session | 253 | putStrLn $ "iq-set-bind-resource " ++ show rsc |
254 | atomically $ writeTChan cmdChan (Send $ iq_bind_reply stanza_id (toStrict $ L.decodeUtf8 $ L.show jid) ) | 254 | setResource session (L.fromChunks [S.encodeUtf8 rsc]) |
255 | forCachedPresence session $ \presence -> do | 255 | jid <- getJID session |
256 | xs <- xmlifyPresenceForClient presence | 256 | atomically $ writeTChan cmdChan (Send $ iq_bind_reply stanza_id (toStrict $ L.decodeUtf8 $ L.show jid) ) |
257 | atomically . writeTChan cmdChan . Send $ xs | 257 | forCachedPresence session $ \presence -> do |
258 | _ -> unhandledBind | 258 | xs <- xmlifyPresenceForClient presence |
259 | atomically . writeTChan cmdChan . Send $ xs | ||
260 | _ -> unhandledBind | ||
261 | Nothing -> do | ||
262 | liftIO $ putStrLn $ "empty bind request!" | ||
259 | 263 | ||
260 | 264 | ||
261 | iq_session_reply host stanza_id = | 265 | iq_session_reply host stanza_id = |
@@ -598,14 +602,6 @@ fromPeer session = doNestingXML $ do | |||
598 | 602 | ||
599 | 603 | ||
600 | 604 | ||
601 | {- | ||
602 | seekRemotePeers :: XMPPConfig config => | ||
603 | config -> TChan Presence -> IO () | ||
604 | seekRemotePeers config chan = do | ||
605 | putStrLn "unimplemented: seekRemotePeers" | ||
606 | -- TODO | ||
607 | return () | ||
608 | -} | ||
609 | 605 | ||
610 | data OutBoundMessage = OutBoundPresence Presence | PresenceProbe JID JID | 606 | data OutBoundMessage = OutBoundPresence Presence | PresenceProbe JID JID |
611 | deriving Prelude.Show | 607 | deriving Prelude.Show |
diff --git a/whosocket.hs b/whosocket.hs new file mode 100644 index 00000000..5968b152 --- /dev/null +++ b/whosocket.hs | |||
@@ -0,0 +1,91 @@ | |||
1 | module Main where | ||
2 | |||
3 | import LocalPeerCred | ||
4 | import ControlMaybe | ||
5 | |||
6 | import System.Directory | ||
7 | import Data.Char | ||
8 | import System.Posix.Types | ||
9 | import System.Posix.Files | ||
10 | import Data.ByteString.Lazy.Char8 as L (unpack) | ||
11 | import Data.List (groupBy) | ||
12 | import Data.Maybe (listToMaybe) | ||
13 | |||
14 | import Network.Socket | ||
15 | import System.Environment | ||
16 | import Control.Arrow (first) | ||
17 | |||
18 | usage = do | ||
19 | putStrLn $ "whosocket numeric-address port" | ||
20 | |||
21 | main = do | ||
22 | args <- getArgs | ||
23 | case (args??0,args??1) of | ||
24 | (Just addr_str,Just port_str) -> whosocket addr_str port_str | ||
25 | _ -> usage | ||
26 | |||
27 | whosocket addr_str port_str = do | ||
28 | info <- getAddrInfo (Just $ defaultHints { addrFlags = [ AI_NUMERICHOST ] }) | ||
29 | (Just addr_str) | ||
30 | (Just port_str) | ||
31 | let addr = head $ map addrAddress info | ||
32 | r <- getLocalPeerCred' addr | ||
33 | putStrLn $ "r{"++show addr++"} = " ++ show r | ||
34 | |||
35 | let Just (uid,inode) = r | ||
36 | pid <- scanProc (show uid) (L.unpack inode) | ||
37 | putStrLn $ "scanProc --> "++show pid | ||
38 | withJust pid $ \(pid,ttydev) -> do | ||
39 | tty <- ttyOrDisplay pid ttydev | ||
40 | putStrLn $ "pid = " ++ show pid | ||
41 | putStrLn $ "tty = " ++ show tty | ||
42 | |||
43 | return () | ||
44 | |||
45 | |||
46 | makeUidStr "4294967295" = "invalid" | ||
47 | makeUidStr uid = uid | ||
48 | |||
49 | |||
50 | scanProc uid inode = do | ||
51 | contents <- getDirectoryContents "/proc" `catchIO_` return [] | ||
52 | let pids = reverse $ filter (\n -> not (null n) && isDigit (head n)) contents | ||
53 | let searchPids [] = return Nothing | ||
54 | searchPids (pid:pids) = do | ||
55 | loginuid <- fmap makeUidStr $ readFile $ "/proc/"++pid++"/loginuid" | ||
56 | if False -- (uid/=loginuid) -- this check proved bad when mcabber ran on tty3 | ||
57 | then searchPids pids | ||
58 | else do | ||
59 | -- putStrLn $ "pid "++show pid ++ " --> uid "++show loginuid | ||
60 | let loop [] = return Nothing | ||
61 | loop ("0":fds) = loop fds | ||
62 | loop (fd:fds) = do | ||
63 | handleIO_ (loop fds) $ do | ||
64 | what <- readSymbolicLink $ "/proc/"++pid++"/fd/"++fd | ||
65 | -- putStrLn $ " what= "++show what | ||
66 | if (what=="socket:["++inode++"]") | ||
67 | then do | ||
68 | tty <- readSymbolicLink $ "/proc/"++pid++"/fd/0" | ||
69 | return (Just (pid,tty)) | ||
70 | else loop fds | ||
71 | fds <- getDirectoryContents ("/proc/"++pid++"/fd") `catchIO_` return [] | ||
72 | mb <- loop fds | ||
73 | maybe (searchPids pids) (return . Just) mb | ||
74 | |||
75 | fmap (fmap (first (read :: String -> CPid))) $ searchPids pids | ||
76 | |||
77 | ttyOrDisplay pid ttydev | take 8 ttydev == "/dev/tty" = return (drop 5 ttydev) | ||
78 | ttyOrDisplay pid ttydev = do | ||
79 | env <- handleIO_ (return "") . readFile $ "/proc/"++show pid++"/environ" | ||
80 | let vs = unzero $ groupBy (\_ c->c/='\0') env | ||
81 | unzero [] = [] | ||
82 | unzero (v:vs) = v:map tail vs | ||
83 | keyvalue xs = (key,value) | ||
84 | where | ||
85 | (key,ys) = break (=='=') xs | ||
86 | value = case ys of { [] -> []; (_:ys') -> ys' } | ||
87 | display = listToMaybe . filter ((=="DISPLAY").fst) . map keyvalue $ vs | ||
88 | putStrLn $ "display = " ++ show display | ||
89 | case display of | ||
90 | Just (_,disp) -> return disp | ||
91 | _ -> return ttydev | ||