diff options
Diffstat (limited to 'whosocket.hs')
-rw-r--r-- | whosocket.hs | 91 |
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 @@ | |||
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 | ||