module Network.SSH.Client.SimpleSSH
( SimpleSSHError(..)
, SimpleSSH
, Session
, Result(..)
, runSimpleSSH
, openSession
, authenticateWithPassword
, authenticateWithKey
, execCommand
, sendFile
, closeSession
, withSessionPassword
, withSessionKey
) where
import Control.Applicative
import Control.Monad.Error
import qualified Data.ByteString.Char8 as BS
import Foreign.C.String
import Foreign.Marshal.Alloc
import Foreign.Ptr
import Network.SSH.Client.SimpleSSH.Foreign
import Network.SSH.Client.SimpleSSH.Types
getValue :: CEither -> (Ptr () -> b) -> IO b
getValue eitherC build = build <$> getValueC eitherC
getError :: CEither -> IO SimpleSSHError
getError eitherC = readError <$> getErrorC eitherC
getContent :: CResult -> IO BS.ByteString
getContent ptr = BS.packCString =<< getContentC ptr
getExitCode :: CResult -> IO Integer
getExitCode ptr = toInteger <$> getExitCodeC ptr
readResult :: CResult -> IO Result
readResult resultC = Result <$> getContent resultC <*> getExitCode resultC
readCount :: CCount -> IO Integer
readCount countC = toInteger <$> getCountC countC
liftIOEither :: IO (Either SimpleSSHError a) -> SimpleSSH a
liftIOEither ioAction = do
eRes <- liftIO ioAction
case eRes of
Left err -> throwError err
Right res -> return res
liftEitherCFree :: (CEither -> IO ())
-> (Ptr () -> a)
-> IO CEither
-> IO (Either SimpleSSHError a)
liftEitherCFree customFree constr action = do
eitherC <- action
checkLeft <- isLeftC eitherC
res <- if checkLeft == 0
then Right <$> getValue eitherC constr
else Left <$> getError eitherC
customFree eitherC
return res
liftEitherC :: (Ptr () -> a) -> IO CEither -> IO (Either SimpleSSHError a)
liftEitherC = liftEitherCFree free
openSession :: String
-> Integer
-> String
-> SimpleSSH Session
openSession hostname port knownhostsPath = liftIOEither $ do
hostnameC <- newCString hostname
knownhostsPathC <- newCString knownhostsPath
let portC = fromInteger port
res <- liftEitherC Session $ openSessionC hostnameC portC knownhostsPathC
free hostnameC
free knownhostsPathC
return res
authenticateWithPassword :: Session
-> String
-> String
-> SimpleSSH Session
authenticateWithPassword session username password = liftIOEither $ do
usernameC <- newCString username
passwordC <- newCString password
res <- liftEitherC Session $ authenticatePasswordC session usernameC passwordC
free usernameC
free passwordC
return res
authenticateWithKey :: Session
-> String
-> FilePath
-> FilePath
-> String
-> SimpleSSH Session
authenticateWithKey session username publicKeyPath privateKeyPath passphrase = liftIOEither $ do
(usernameC, publicKeyPathC, privateKeyPathC, passphraseC) <-
(,,,) <$> newCString username
<*> newCString publicKeyPath
<*> newCString privateKeyPath
<*> newCString passphrase
res <- liftEitherC Session $ authenticateKeyC session usernameC publicKeyPathC privateKeyPathC passphraseC
mapM_ free [usernameC, publicKeyPathC, privateKeyPathC, passphraseC]
return res
execCommand :: Session
-> String
-> SimpleSSH Result
execCommand session command = do
result <- liftIOEither $ do
commandC <- newCString command
res <- liftEitherCFree freeEitherResultC CResult $ execCommandC session commandC
free commandC
return res
liftIO $ readResult result
sendFile :: Session
-> Integer
-> String
-> String
-> SimpleSSH Integer
sendFile session mode source target = do
count <- liftIOEither $ do
sourceC <- newCString source
targetC <- newCString target
let modeC = fromInteger mode
res <- liftEitherCFree freeEitherCountC CCount $ sendFileC session modeC sourceC targetC
free sourceC
free targetC
return res
liftIO $ readCount count
closeSession :: Session -> SimpleSSH ()
closeSession = lift . closeSessionC
withSessionPassword :: String
-> Integer
-> String
-> String
-> String
-> (Session -> SimpleSSH a)
-> SimpleSSH a
withSessionPassword hostname port knownhostsPath username password action = do
session <- openSession hostname port knownhostsPath
authenticatedSession <- authenticateWithPassword session username password
res <- action authenticatedSession
closeSession authenticatedSession
return res
withSessionKey :: String
-> Integer
-> String
-> String
-> String
-> String
-> String
-> (Session -> SimpleSSH a)
-> SimpleSSH a
withSessionKey hostname port knownhostsPath username publicKeyPath privateKeyPath passphrase action = do
session <- openSession hostname port knownhostsPath
authenticatedSession <- authenticateWithKey session username publicKeyPath privateKeyPath passphrase
res <- action authenticatedSession
closeSession authenticatedSession
return res