libssh2 0.2.0.5 → 0.2.0.6
raw patch · 6 files changed
+68/−66 lines, 6 filesdep +unixdep −select
Dependencies added: unix
Dependencies removed: select
Files
- libssh2.cabal +16/−11
- src/Network/SSH/Client/LibSSH2.hs +3/−3
- src/Network/SSH/Client/LibSSH2/Errors.chs +2/−4
- src/Network/SSH/Client/LibSSH2/Foreign.chs +43/−43
- src/Network/SSH/Client/LibSSH2/Types.chs +0/−1
- ssh-client.hs +4/−4
libssh2.cabal view
@@ -1,6 +1,6 @@ Name: libssh2 -Version: 0.2.0.5+Version: 0.2.0.6 Synopsis: FFI bindings to libssh2 SSH2 client library (http://libssh2.org/) @@ -10,15 +10,15 @@ rather than in C code. This means that all calls are now interruptable using Haskell asynchronous exceptions; for instance, it is now possible to use "System.Timeout" in- combination with "libssh2". + combination with "libssh2". . /Note on usage on Windows/: On Windows you MUST compile your executable with @-threaded@ or 'libssh2' will NOT- work. We have tested 'libssh2' on Windows using + work. We have tested 'libssh2' on Windows using <http://mingw.org/>, with <http://www.openssl.org/> and <http://libssh2.org/> compiled from source (be sure to pass the 'shared' option to the configure script for 'openssl'- to enable the shared libraries). + to enable the shared libraries). Homepage: https://github.com/portnov/libssh2-hs @@ -31,7 +31,7 @@ Maintainer: portnov84@rambler.ru -- A copyright notice.--- Copyright: +-- Copyright: Category: Network @@ -56,20 +56,21 @@ Network.SSH.Client.LibSSH2.Errors Network.SSH.Client.LibSSH2.WaitSocket Network.SSH.Client.LibSSH2- + Include-dirs: include Includes: include/libssh2_local.h Build-depends: base >= 4 && < 5, network >= 2.3, syb >= 0.3.3, time >= 1.2,- bytestring >= 0.9, select >= 0.4+ bytestring >= 0.9,+ unix Extra-libraries: "ssh2" pkgconfig-depends: libssh2 >= 1.2.8 GHC-Options: -Wall- - -- Other-modules: - ++ -- Other-modules:+ Build-tools: c2hs HS-Source-Dirs: src @@ -78,7 +79,7 @@ Includes: gcrypt-fix.h Exposed-modules: Network.SSH.Client.LibSSH2.GCrypt Cpp-options: -DGCRYPT- + Executable hs-ssh-client if flag(example-client) Build-depends: base, utf8-string, libssh2 >= 0.2, syb, network, filepath, bytestring, time@@ -86,3 +87,7 @@ buildable: False Main-Is: ssh-client.hs GHC-Options: -threaded++Source-repository head+ type: git+ location: https://github.com/portnov/libssh2-hs
src/Network/SSH/Client/LibSSH2.hs view
@@ -51,7 +51,7 @@ socketConnect :: String -> Int -> IO Socket socketConnect hostname port = do proto <- getProtocolNumber "tcp"- bracketOnError (socket AF_INET Stream proto) (sClose)+ bracketOnError (socket AF_INET Stream proto) (close) (\sock -> do he <- getHostByName hostname connect sock (SockAddrInet (fromIntegral port) (hostAddress he))@@ -154,8 +154,8 @@ where go :: [BSS.ByteString] -> IO BSL.ByteString go acc = do- bs <- do isReadable <- pollChannelRead ch- if isReadable+ bs <- do readable <- pollChannelRead ch+ if readable then readChannel ch 0x400 else return BSS.empty if BSS.length bs > 0
src/Network/SSH/Client/LibSSH2/Errors.chs view
@@ -1,10 +1,9 @@ {-# LANGUAGE ForeignFunctionInterface, DeriveDataTypeable, FlexibleInstances #-} -#ifdef __APPLE__ +#ifdef __APPLE__ #define _ANSI_SOURCE-#define __AVAILABILITY__ #define __OSX_AVAILABLE_STARTING(_mac, _iphone)-#define __OSX_AVAILABLE_BUT_DEPRECATED(_macIntro, _macDep, _iphoneIntro, _iphoneDep) +#define __OSX_AVAILABLE_BUT_DEPRECATED(_macIntro, _macDep, _iphoneIntro, _iphoneDep) #endif #include <libssh2.h>@@ -37,7 +36,6 @@ import Data.Generics import Foreign import Foreign.C.Types-import Control.Monad (when) import Network.SSH.Client.LibSSH2.Types import Network.SSH.Client.LibSSH2.WaitSocket
src/Network/SSH/Client/LibSSH2/Foreign.chs view
@@ -1,10 +1,9 @@ {-# LANGUAGE CPP, ForeignFunctionInterface #-} -#ifdef __APPLE__ +#ifdef __APPLE__ #define _ANSI_SOURCE-#define __AVAILABILITY__ #define __OSX_AVAILABLE_STARTING(_mac, _iphone)-#define __OSX_AVAILABLE_BUT_DEPRECATED(_macIntro, _macDep, _iphoneIntro, _iphoneDep) +#define __OSX_AVAILABLE_BUT_DEPRECATED(_macIntro, _macDep, _iphoneIntro, _iphoneDep) #endif #include "libssh2_local.h"@@ -22,7 +21,7 @@ initSession, freeSession, disconnectSession, handshake, setBlocking,- + -- * Known hosts functions initKnownHosts, freeKnownHosts, knownHostsReadFile, getHostKey, checkKnownHost,@@ -56,20 +55,20 @@ TraceFlag (..), setTraceMode ) where -import Foreign+import Control.Monad (void)+import Data.Time.Clock.POSIX+import Foreign hiding (void) import Foreign.C.Types import Foreign.C.String import System.IO-import Network.Socket (Socket(MkSocket), fdSocket)-import Data.Time.Clock.POSIX-import System.Posix.IO.Select-import System.Posix.IO.Select.Types-import System.Posix.Types+import Network.Socket (Socket(MkSocket), isReadable) import qualified Data.ByteString as BSS import qualified Data.ByteString.Unsafe as BSS import Network.SSH.Client.LibSSH2.Types import Network.SSH.Client.LibSSH2.Errors++ #ifdef GCRYPT import Network.SSH.Client.LibSSH2.GCrypt #endif@@ -130,7 +129,7 @@ init_crypto False = 1 init_crypto True = 0 -ssh2socket :: Socket +ssh2socket :: Socket #ifdef mingw32_HOST_OS #ifdef x86_64_HOST_ARCH -> CULLong@@ -169,7 +168,7 @@ -- | Create Session object initSession :: IO Session-initSession = handleNullPtr (Nothing :: Maybe Session) sessionFromPointer $ +initSession = handleNullPtr (Nothing :: Maybe Session) sessionFromPointer $ {# call session_init_ex #} nullFunPtr nullFunPtr nullFunPtr nullPtr {# fun session_free as freeSession_@@ -185,7 +184,7 @@ -- | Disconnect session (but do not free memory) disconnectSession :: Session -> String -- ^ Goodbye message- -> IO () + -> IO () disconnectSession s msg = void . handleInt (Just s) $ disconnectSessionEx s 11 msg "" {# fun session_set_blocking as setBlocking@@ -238,7 +237,7 @@ castPtr `Ptr ()' } -> `KnownHostResult' int2khresult #} -- | Check host data against known hosts.-checkKnownHost :: KnownHosts -- +checkKnownHost :: KnownHosts -- -> String -- ^ Host name -> Int -- ^ Port number (usually 22) -> String -- ^ Host public key@@ -261,7 +260,7 @@ -> String -- ^ Path to private key -> String -- ^ Passphrase -> IO ()-publicKeyAuthFile session username public private passphrase = void . handleInt (Just session) $ +publicKeyAuthFile session username public private passphrase = void . handleInt (Just session) $ publicKeyAuthFile_ session username public private passphrase -- | Perform username/password authentication.@@ -283,24 +282,24 @@ -- | Open a channel for session. openChannelSession :: Session -> IO Channel-openChannelSession s = handleNullPtr (Just s) (channelFromPointer s) $ +openChannelSession s = handleNullPtr (Just s) (channelFromPointer s) $ openSessionChannelEx s "session" 65536 32768 "" -channelProcess :: Channel -> String -> String -> IO () +channelProcess :: Channel -> String -> String -> IO () channelProcess ch kind command = void . handleInt (Just $ channelSession ch) $ channelProcessStartup_ ch kind command -- | Execute command-channelExecute :: Channel -> String -> IO () +channelExecute :: Channel -> String -> IO () channelExecute c command = channelProcess c "exec" command -{# fun channel_process_startup as channelProcessStartup_ +{# fun channel_process_startup as channelProcessStartup_ { toPointer `Channel', `String' &, `String' & } -> `Int' #} -- | Execute shell command-channelShell :: Channel -> IO () +channelShell :: Channel -> IO () channelShell c = void . handleInt (Just $ channelSession c) $ do withCStringLen "shell" $ \(s,l) -> do res <- channelProcessStartup_'_ (toPointer c) s (fromIntegral l) nullPtr 0@@ -313,34 +312,34 @@ `Int', `Int', `Int', `Int' } -> `Int' #} -requestPTY :: Channel -> String -> IO () +requestPTY :: Channel -> String -> IO () requestPTY ch term = void . handleInt (Just $ channelSession ch) $ requestPTYEx ch term "" 0 0 0 0 -readChannelEx :: Channel -> Int -> Size -> IO BSS.ByteString +readChannelEx :: Channel -> Int -> Size -> IO BSS.ByteString readChannelEx ch i size = do allocaBytes (fromIntegral size) $ \buffer -> do rc <- handleInt (Just $ channelSession ch) $ {# call channel_read_ex #} (toPointer ch) (fromIntegral i) buffer size BSS.packCStringLen (buffer, fromIntegral rc) -- | Read data from channel.-readChannel :: Channel -- +readChannel :: Channel -- -> Size -- ^ Amount of data to read- -> IO BSS.ByteString + -> IO BSS.ByteString readChannel c sz = readChannelEx c 0 sz -- | Write data to channel.-writeChannel :: Channel -> BSS.ByteString -> IO () -writeChannel ch bs = +writeChannel :: Channel -> BSS.ByteString -> IO ()+writeChannel ch bs = BSS.unsafeUseAsCString bs $ go 0 (fromIntegral $ BSS.length bs) where- go :: Int -> CULong -> CString -> IO () + go :: Int -> CULong -> CString -> IO () go offset len cstr = do- written <- handleInt (Just $ channelSession ch) - $ {# call channel_write_ex #} (toPointer ch) - 0 - (cstr `plusPtr` offset) + written <- handleInt (Just $ channelSession ch)+ $ {# call channel_write_ex #} (toPointer ch)+ 0+ (cstr `plusPtr` offset) (fromIntegral len)- if fromIntegral written < len + if fromIntegral written < len then go (offset + fromIntegral written) (len - fromIntegral written) cstr else return () @@ -388,21 +387,21 @@ -- | Write all data to channel from handle. -- Returns amount of transferred data. writeChannelFromHandle :: Channel -> Handle -> IO Integer-writeChannelFromHandle ch h = +writeChannelFromHandle ch h = let go :: Integer -> Ptr a -> IO Integer go done buffer = do sz <- hGetBuf h buffer bufferSize send 0 (fromIntegral sz) buffer- let newDone = done + fromIntegral sz + let newDone = done + fromIntegral sz if sz < bufferSize- then return newDone + then return newDone else go newDone buffer- - send :: Int -> CLong -> Ptr a -> IO () - send _ 0 _ = return () ++ send :: Int -> CLong -> Ptr a -> IO ()+ send _ 0 _ = return () send written size buffer = do- sent <- handleInt (Just $ channelSession ch) $ + sent <- handleInt (Just $ channelSession ch) $ {# call channel_write_ex #} (toPointer ch) 0@@ -412,7 +411,7 @@ bufferSize = 0x100000 - in allocaBytes bufferSize $ go 0 + in allocaBytes bufferSize $ go 0 -- | Read all data from channel to handle. -- Returns amount of transferred data.@@ -430,7 +429,7 @@ readChannelCB ch buffer bufferSize fileSize callback = let go got = do let toRead = min (fromIntegral fileSize - got) (fromIntegral bufferSize)- sz <- handleInt (Just $ channelSession ch) $ + sz <- handleInt (Just $ channelSession ch) $ {# call channel_read_ex #} (toPointer ch) 0@@ -494,7 +493,7 @@ -- | Create SCP file send channel. scpSendChannel :: Session -> String -> Int -> Int64 -> POSIXTime -> POSIXTime -> IO Channel-scpSendChannel session remotePath mode size mtime atime = handleNullPtr (Just session) (channelFromPointer session) $ +scpSendChannel session remotePath mode size mtime atime = handleNullPtr (Just session) (channelFromPointer session) $ scpSendChannel_ session remotePath mode size mtime atime type Offset = {# type off_t #}@@ -519,7 +518,7 @@ mbSocket <- sessionGetSocket (channelSession ch) case mbSocket of Nothing -> error "pollChannelRead without socket present"- Just socket -> (== 1) <$> select'' [Fd $ fdSocket socket] [] [] (finite 0 100)+ Just socket -> isReadable socket -- -- | Sftp support@@ -719,6 +718,7 @@ {# call sftp_fstat_ex #} (toPointer sftph) sftpattrptr 0 parseSftpAttributes sftpattrptr +parseSftpAttributes :: Ptr a -> IO SftpAttributes -- TODO why not storable? parseSftpAttributes sftpattrptr = do flags<- {# get _LIBSSH2_SFTP_ATTRIBUTES->flags #} sftpattrptr size <- {# get _LIBSSH2_SFTP_ATTRIBUTES->filesize #} sftpattrptr
src/Network/SSH/Client/LibSSH2/Types.chs view
@@ -2,7 +2,6 @@ #ifdef __APPLE__ #define _ANSI_SOURCE-#define __AVAILABILITY__ #define __OSX_AVAILABLE_STARTING(_mac, _iphone) #define __OSX_AVAILABLE_BUT_DEPRECATED(_macIntro, _macDep, _iphoneIntro, _iphoneDep) #endif
ssh-client.hs view
@@ -12,21 +12,21 @@ ["command", user, host, port, cmd] -> runCommand user host (read port) cmd ["send", user, host, port, path] -> sendFile user host (read port) path ["receive", user, host, port, path] -> receiveFile user host (read port) path- _ -> putStrLn "Synopsis: ssh-client USERNAME HOSTNAME PORT COMMAND"+ _ -> putStrLn "Synopsis: ssh-client ACTION USERNAME HOSTNAME PORT ARG" runCommand login host port command =- ssh login host port $ \s -> + ssh login host port $ \s -> withChannel s $ \ch -> do channelExecute ch command result <- readAllChannel ch BSL.putStr result -sendFile login host port path = +sendFile login host port path = ssh login host port $ \s -> do sz <- scpSendFile s 0o644 path (takeFileName path) putStrLn $ "Sent: " ++ show sz ++ " bytes." -receiveFile login host port path = +receiveFile login host port path = ssh login host port $ \s -> do sz <- scpReceiveFile s (takeFileName path) path putStrLn $ "Received: " ++ show sz ++ " bytes."