WL500gPControl (empty) → 0.3.1
raw patch · 6 files changed
+195/−0 lines, 6 filesdep +WL500gPLibrarydep +basedep +mtlsetup-changed
Dependencies added: WL500gPLibrary, base, mtl, unix
Files
- LICENSE +0/−0
- Setup.lhs +5/−0
- WL500gPControl.cabal +23/−0
- src/Common.hs +33/−0
- src/Control/Main.hs +96/−0
- src/Status/Main.hs +38/−0
+ LICENSE view
+ Setup.lhs view
@@ -0,0 +1,5 @@+#!/usr/bin/env runhaskell++> import Distribution.Simple+> main = defaultMain+
+ WL500gPControl.cabal view
@@ -0,0 +1,23 @@+name: WL500gPControl+version: 0.3.1+cabal-version: >= 1.2+license: BSD3+license-file: LICENSE+author: Vasyl Pasternak <vasyl.pasternak@gmail.com>+category: Network, UI+synopsis: A simple command line tools to control the + Asus WL500gP router+build-type: Simple++executable WL500gPStatus+ main-is: Status/Main.hs+ build-depends: base < 4, WL500gPLibrary >= 0.3+ hs-source-dirs: src+ other-modules: Common++executable WL500gPControl+ main-is: Control/Main.hs+ build-depends: base < 4, WL500gPLibrary >= 0.3, mtl, unix+ hs-source-dirs: src+ other-modules: Common+
+ src/Common.hs view
@@ -0,0 +1,33 @@++module Common + (+ defaultCredsFile+ ,parseCredsFile+ )where++import System.IO.Unsafe (unsafePerformIO)+import System.Environment (getEnv)+import Text.Printf (printf)+import qualified Network.Asus.WL500gP as W+import Data.Char (toLower)+import Control.Monad (liftM)+ +homeDirectory = unsafePerformIO $ getEnv "HOME"++defaultCredsFile = printf "%s/.wl500gp" homeDirectory :: String+++parseCredsFile :: String -> IO (Maybe W.Connection)+parseCredsFile fname = + let toPair (a:b:[]) = (map toLower a, b)+ toPair _ = ("", "")+ parse = filter (/= ("", "")) . map (toPair . words) . lines+ in do+ contentsMap <- liftM parse $ readFile fname+ return $ do (host:passwd:user:[]) <- + mapM (`lookup` contentsMap) ["host:"+ ,"password:"+ ,"user:"]+ return $ W.Connection {W.user = user+ ,W.password = passwd+ ,W.hostname = host}
+ src/Control/Main.hs view
@@ -0,0 +1,96 @@++module Main where++import System.Console.GetOpt+import System.Environment (getArgs, getProgName)+import Data.Maybe (maybe)+import Common+import Control.Monad (sequence_, zipWithM_)+import Text.Printf (printf)+import qualified Network.Asus.WL500gP as W+import Data.Either (either)+import Data.List (intersperse)+import Control.Monad.Trans (liftIO)+import System.Posix.Unistd (sleep)++data Operation = Connect + | Disconnect + | Reconnect Int+ | Status + | Log Int+ | ClearLog deriving (Show)++options :: [OptDescr Operation]+options = + [Option ['c'] ["connect"] (NoArg Connect) + "Connects to the WAN"+ ,Option ['d'] ["disconnect"] (NoArg Disconnect) + "Disconnects from the provider"+ ,Option ['r'] ["reconnect"] (OptArg (Reconnect . maybe 5 read) "S") + "Disconnects from WAN, waits S seconds and reconnects to the WAN"+ ,Option ['s'] ["status"] (NoArg Status) + "Prints the connection status"+ ,Option ['l'] ["log"] (OptArg (Log . maybe 25 read) "N") + "Prints last N lines from the log"+ ,Option ['x'] ["log-clear"] (NoArg ClearLog) + "Clears log"+ ]++-- returns the list of flags and the config filename+parseOpts :: [String] -> IO (Operation, String)+parseOpts argv = + case getOpt Permute options argv of+ (o, n, []) -> let creds = if null n + then defaultCredsFile + else (head n)+ op = if null o + then Status+ else (head o)+ in return (op, creds)+ (_, _, errs) -> do + progName <- getProgName+ let header = printf "Usage: %s OPERATION CREDENTIAL_FILE" progName+ ioError (userError (concat errs ++ usageInfo header options))+ ++main :: IO ()+main = do+ (oper, creds) <- getArgs >>= parseOpts+ parseCredsFile creds >>= maybe + (ioError $ userError $ printf "Failed to open credentials file '%s'" creds) + (switch oper)++brace :: String -> String -> W.Conn () -> W.Conn ()+brace b a c = sequence_ [liftIO $ putStrLn b, c, liftIO $ putStrLn a]++switch op conn = + W.withConnection conn $ + case op of + Connect -> brace "Connecting..." "Done" W.connectWan+ Disconnect -> brace "Disconnecting..." "Done" W.disconnectWan+ ClearLog -> brace "Erasing log.." "Done" W.clearLog+ Reconnect n -> brace "Reconnecting..." "Done" $ + sequence_ [W.disconnectWan+ ,liftIO (sleep n >> return ())+ ,W.connectWan]+ Status -> W.readStatus >>= liftIO . either (ioError . userError) showStatus+ Log n -> W.readLog >>= liftIO . either (ioError . userError) (showLog n)++showStatus stat = do+ printf "Connection status:\n" + case W.connectionStatus stat of+ W.Disconnected -> printf "\tWAN disconnected\n"+ _ -> do printf " WAN Connected\n"+ zipWithM_ printf [" IP:\t\t%s\n"+ ," Subnet Mask:\t%s\n"+ ," Gateway:\t%s\n"+ ," DNS Servers:\t%s\n"+ ] $ + map ($ stat) [W.ip+ ,W.subnetMask+ ,W.defaultGateway+ ,concat . intersperse ", " . W.dnsServers]+++showLog n = printf "%s" . unlines . reverse . take n . reverse+
+ src/Status/Main.hs view
@@ -0,0 +1,38 @@++module Main where++import qualified Network.Asus.WL500gP as W+import System.Environment (getArgs)+import Text.Printf (printf)+import Common+import Data.Either (either)++data Status = StatusConnected | StatusDisconnected | StatusError String deriving Eq++fromConnStatus :: W.ConnectionStatus -> Status+fromConnStatus W.Connected = StatusConnected+fromConnStatus W.Disconnected = StatusDisconnected++main :: IO ()+main = do+ args <- getArgs+ -- config file name should be the last argument+ let configFile = if null args + then defaultCredsFile+ else head (reverse args)+ -- '-c' - for colorized output+ let outString = printStatus ("-c" `elem` args)+ let configError = outString (StatusError $ printf "Failed to open file %s " configFile)+ let getStatus conn = + either (outString . StatusError) + (outString . fromConnStatus . W.connectionStatus) =<< + W.withConnection conn W.readStatus++ maybe configError getStatus =<< parseCredsFile configFile+ +printStatus c StatusConnected = format c "#00ff00" "Connected"+printStatus c StatusDisconnected = format c "#ff0000" "Disconnected"+printStatus c (StatusError e) = format c "#dddddd" (if c then "N/A" else e)++format True col s = printf "<fc=%s>%s</fc>" col s+format _ _ s = printf s