summaryrefslogtreecommitdiff
path: root/whosocket.hs
diff options
context:
space:
mode:
Diffstat (limited to 'whosocket.hs')
-rw-r--r--whosocket.hs91
1 files changed, 91 insertions, 0 deletions
diff --git a/whosocket.hs b/whosocket.hs
new file mode 100644
index 00000000..5968b152
--- /dev/null
+++ b/whosocket.hs
@@ -0,0 +1,91 @@
1module Main where
2
3import LocalPeerCred
4import ControlMaybe
5
6import System.Directory
7import Data.Char
8import System.Posix.Types
9import System.Posix.Files
10import Data.ByteString.Lazy.Char8 as L (unpack)
11import Data.List (groupBy)
12import Data.Maybe (listToMaybe)
13
14import Network.Socket
15import System.Environment
16import Control.Arrow (first)
17
18usage = do
19 putStrLn $ "whosocket numeric-address port"
20
21main = 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
27whosocket 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
46makeUidStr "4294967295" = "invalid"
47makeUidStr uid = uid
48
49
50scanProc 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
77ttyOrDisplay pid ttydev | take 8 ttydev == "/dev/tty" = return (drop 5 ttydev)
78ttyOrDisplay 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