{-# LANGUAGE OverloadedStrings #-}
module Xmobar.Plugins.Monitors.Net.Linux (
existingDevs
, findNetDev
) where
import Xmobar.Plugins.Monitors.Net.Common (NetDevRawTotal, NetDev(..), NetDevInfo(..))
import Control.Monad (filterM)
import System.Directory (getDirectoryContents, doesFileExist)
import System.FilePath ((</>))
import System.IO.Error (catchIOError)
import System.IO.Unsafe (unsafeInterleaveIO)
import qualified Data.ByteString.Char8 as B
operstateDir :: String -> FilePath
operstateDir :: String -> String
operstateDir String
d = String
"/sys/class/net" String -> String -> String
</> String
d String -> String -> String
</> String
"operstate"
existingDevs :: IO [String]
existingDevs :: IO [String]
existingDevs = String -> IO [String]
getDirectoryContents String
"/sys/class/net" IO [String] -> ([String] -> IO [String]) -> IO [String]
forall a b. IO a -> (a -> IO b) -> IO b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (String -> IO Bool) -> [String] -> IO [String]
forall (m :: * -> *) a.
Applicative m =>
(a -> m Bool) -> [a] -> m [a]
filterM String -> IO Bool
isDev
where isDev :: String -> IO Bool
isDev String
d | String
d String -> [String] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [String]
excludes = Bool -> IO Bool
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
False
| Bool
otherwise = String -> IO Bool
doesFileExist (String -> String
operstateDir String
d)
excludes :: [String]
excludes = [String
".", String
"..", String
"lo"]
isUp :: String -> IO Bool
isUp :: String -> IO Bool
isUp String
d = (IO Bool -> (IOError -> IO Bool) -> IO Bool)
-> (IOError -> IO Bool) -> IO Bool -> IO Bool
forall a b c. (a -> b -> c) -> b -> a -> c
flip IO Bool -> (IOError -> IO Bool) -> IO Bool
forall a. IO a -> (IOError -> IO a) -> IO a
catchIOError (IO Bool -> IOError -> IO Bool
forall a b. a -> b -> a
const (IO Bool -> IOError -> IO Bool) -> IO Bool -> IOError -> IO Bool
forall a b. (a -> b) -> a -> b
$ Bool -> IO Bool
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
False) (IO Bool -> IO Bool) -> IO Bool -> IO Bool
forall a b. (a -> b) -> a -> b
$ do
operstate <- String -> IO ByteString
B.readFile (String -> String
operstateDir String
d)
return $! (head . B.lines) operstate `elem` ["up", "unknown"]
readNetDev :: [String] -> IO NetDevRawTotal
readNetDev :: [String] -> IO NetDevRawTotal
readNetDev [String]
ds = do
let (String
d, String
x, String
y) = case [String]
ds of
String
d':String
x':String
y':[String]
_ -> (String
d', String
x', String
y')
[String]
_ -> (String
"", String
"", String
"")
up <- IO Bool -> IO Bool
forall a. IO a -> IO a
unsafeInterleaveIO (IO Bool -> IO Bool) -> IO Bool -> IO Bool
forall a b. (a -> b) -> a -> b
$ String -> IO Bool
isUp String
d
return $ N d (if up then ND (r x) (r y) else NI)
where r :: String -> a
r String
s | String
s String -> String -> Bool
forall a. Eq a => a -> a -> Bool
== String
"" = a
0
| Bool
otherwise = String -> a
forall a. Read a => String -> a
read String
s
netParser :: B.ByteString -> IO [NetDevRawTotal]
netParser :: ByteString -> IO [NetDevRawTotal]
netParser = (ByteString -> IO NetDevRawTotal)
-> [ByteString] -> IO [NetDevRawTotal]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
mapM ([String] -> IO NetDevRawTotal
readNetDev ([String] -> IO NetDevRawTotal)
-> (ByteString -> [String]) -> ByteString -> IO NetDevRawTotal
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> [String]
splitDevLine) ([ByteString] -> IO [NetDevRawTotal])
-> (ByteString -> [ByteString])
-> ByteString
-> IO [NetDevRawTotal]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> [ByteString]
readDevLines
where readDevLines :: ByteString -> [ByteString]
readDevLines = Int -> [ByteString] -> [ByteString]
forall a. Int -> [a] -> [a]
drop Int
2 ([ByteString] -> [ByteString])
-> (ByteString -> [ByteString]) -> ByteString -> [ByteString]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> [ByteString]
B.lines
splitDevLine :: ByteString -> [String]
splitDevLine = (ByteString -> String) -> [ByteString] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map ByteString -> String
B.unpack ([ByteString] -> [String])
-> (ByteString -> [ByteString]) -> ByteString -> [String]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [ByteString] -> [ByteString]
forall {b}. [b] -> [b]
selectCols ([ByteString] -> [ByteString])
-> (ByteString -> [ByteString]) -> ByteString -> [ByteString]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (ByteString -> Bool) -> [ByteString] -> [ByteString]
forall a. (a -> Bool) -> [a] -> [a]
filter (Bool -> Bool
not (Bool -> Bool) -> (ByteString -> Bool) -> ByteString -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Bool
B.null) ([ByteString] -> [ByteString])
-> (ByteString -> [ByteString]) -> ByteString -> [ByteString]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Char -> Bool) -> ByteString -> [ByteString]
B.splitWith (Char -> String -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Char
' ',Char
':'])
selectCols :: [b] -> [b]
selectCols [b]
cols = (Int -> b) -> [Int] -> [b]
forall a b. (a -> b) -> [a] -> [b]
map ([b]
cols[b] -> Int -> b
forall a. HasCallStack => [a] -> Int -> a
!!) [Int
0,Int
1,Int
9]
findNetDev :: String -> IO NetDevRawTotal
findNetDev :: String -> IO NetDevRawTotal
findNetDev String
dev = do
nds <- String -> IO ByteString
B.readFile String
"/proc/net/dev" IO ByteString
-> (ByteString -> IO [NetDevRawTotal]) -> IO [NetDevRawTotal]
forall a b. IO a -> (a -> IO b) -> IO b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= ByteString -> IO [NetDevRawTotal]
netParser
case filter isDev nds of
NetDevRawTotal
x:[NetDevRawTotal]
_ -> NetDevRawTotal -> IO NetDevRawTotal
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return NetDevRawTotal
x
[NetDevRawTotal]
_ -> NetDevRawTotal -> IO NetDevRawTotal
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return NetDevRawTotal
forall num. NetDev num
NA
where isDev :: NetDev num -> Bool
isDev (N String
d NetDevInfo num
_) = String
d String -> String -> Bool
forall a. Eq a => a -> a -> Bool
== String
dev
isDev NetDev num
NA = Bool
False