{-# 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" forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= 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 forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [String]
excludes = 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 = forall a b c. (a -> b -> c) -> b -> a -> c
flip forall a. IO a -> (IOError -> IO a) -> IO a
catchIOError (forall a b. a -> b -> a
const forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) a. Monad m => a -> m a
return Bool
False) forall a b. (a -> b) -> a -> b
$ do
ByteString
operstate <- String -> IO ByteString
B.readFile (String -> String
operstateDir String
d)
forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$! (forall a. [a] -> a
head forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> [ByteString]
B.lines) ByteString
operstate forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [ByteString
"up", ByteString
"unknown"]
readNetDev :: [String] -> IO NetDevRawTotal
readNetDev :: [String] -> IO NetDevRawTotal
readNetDev ~[String
d, String
x, String
y] = do
Bool
up <- forall a. IO a -> IO a
unsafeInterleaveIO forall a b. (a -> b) -> a -> b
$ String -> IO Bool
isUp String
d
forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall num. String -> NetDevInfo num -> NetDev num
N String
d (if Bool
up then forall num. num -> num -> NetDevInfo num
ND (forall {a}. (Num a, Read a) => String -> a
r String
x) (forall {a}. (Num a, Read a) => String -> a
r String
y) else forall num. NetDevInfo num
NI)
where r :: String -> a
r String
s | String
s forall a. Eq a => a -> a -> Bool
== String
"" = a
0
| Bool
otherwise = forall a. Read a => String -> a
read String
s
netParser :: B.ByteString -> IO [NetDevRawTotal]
netParser :: ByteString -> IO [NetDevRawTotal]
netParser = forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM ([String] -> IO NetDevRawTotal
readNetDev forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> [String]
splitDevLine) forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> [ByteString]
readDevLines
where readDevLines :: ByteString -> [ByteString]
readDevLines = forall a. Int -> [a] -> [a]
drop Int
2 forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> [ByteString]
B.lines
splitDevLine :: ByteString -> [String]
splitDevLine = forall a b. (a -> b) -> [a] -> [b]
map ByteString -> String
B.unpack forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall {b}. [b] -> [b]
selectCols forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. (a -> Bool) -> [a] -> [a]
filter (Bool -> Bool
not forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Bool
B.null) forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Char -> Bool) -> ByteString -> [ByteString]
B.splitWith (forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Char
' ',Char
':'])
selectCols :: [b] -> [b]
selectCols [b]
cols = forall a b. (a -> b) -> [a] -> [b]
map ([b]
colsforall a. [a] -> Int -> a
!!) [Int
0,Int
1,Int
9]
findNetDev :: String -> IO NetDevRawTotal
findNetDev :: String -> IO NetDevRawTotal
findNetDev String
dev = do
[NetDevRawTotal]
nds <- String -> IO ByteString
B.readFile String
"/proc/net/dev" forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= ByteString -> IO [NetDevRawTotal]
netParser
case forall a. (a -> Bool) -> [a] -> [a]
filter forall {num}. NetDev num -> Bool
isDev [NetDevRawTotal]
nds of
NetDevRawTotal
x:[NetDevRawTotal]
_ -> forall (m :: * -> *) a. Monad m => a -> m a
return NetDevRawTotal
x
[NetDevRawTotal]
_ -> forall (m :: * -> *) a. Monad m => a -> m a
return forall num. NetDev num
NA
where isDev :: NetDev num -> Bool
isDev (N String
d NetDevInfo num
_) = String
d forall a. Eq a => a -> a -> Bool
== String
dev
isDev NetDev num
NA = Bool
False