packages feed

libssh2 0.2.0.3 → 0.2.0.4

raw patch · 5 files changed

+745/−24 lines, 5 files

Files

libssh2.cabal view
@@ -1,6 +1,6 @@ Name:                libssh2 -Version:             0.2.0.3+Version:             0.2.0.4  Synopsis:            FFI bindings to libssh2 SSH2 client library (http://libssh2.org/) 
src/Network/SSH/Client/LibSSH2.hs view
@@ -55,14 +55,14 @@          -> String            -- ^ Remote user name          -> String            -- ^ Remote host name          -> Int               -- ^ Remote port number (usually 22)-         -> (Session -> IO a) -- ^ Actions to perform on session -         -> IO a +         -> (Session -> IO a) -- ^ Actions to perform on session+         -> IO a withSSH2 known_hosts public private passphrase login hostname port fn =   withSession hostname port $ \s -> do     r <- checkHost s hostname port known_hosts-    when (r == MISMATCH) $ +    when (r == MISMATCH) $       error $ "Host key mismatch for host " ++ hostname-    publicKeyAuthFile s login public private passphrase +    publicKeyAuthFile s login public private passphrase     fn s  -- | Execute some actions within SSH2 connection.@@ -122,22 +122,35 @@  -- | Execute some actions withing SSH2 channel withChannel :: Session -> (Channel -> IO a) -> IO (Int, a)-withChannel s = withChannelBy (openChannelSession s) id +withChannel s = withChannelBy (openChannelSession s) id --- | Read all data from the channel +-- | Read all data from the channel -- -- Although this function returns a lazy bytestring, the data is /not/ read -- lazily.-readAllChannel :: Channel -> IO BSL.ByteString +readAllChannel :: Channel -> IO BSL.ByteString readAllChannel ch = go []   where     go :: [BSS.ByteString] -> IO BSL.ByteString     go acc = do       bs <- readChannel ch 0x400       if BSS.length bs > 0-        then go (bs : acc) -        else return (BSL.fromChunks $ reverse acc) +        then go (bs : acc)+        else return (BSL.fromChunks $ reverse acc) +readAllChannelNonBlocking :: Channel -> IO BSL.ByteString+readAllChannelNonBlocking ch = go []+  where+    go :: [BSS.ByteString] -> IO BSL.ByteString+    go acc = do+      bs <- do i <- pollChannelRead_ ch+               if i == 1+                  then readChannel ch 0x400+                  else return BSS.empty+      if BSS.length bs > 0+        then go (bs : acc)+        else return (BSL.fromChunks $ reverse acc)+ -- | Write a lazy bytestring to the channel writeAllChannel :: Channel -> BSL.ByteString -> IO () writeAllChannel ch = mapM_ (writeChannel ch) . BSL.toChunks@@ -146,23 +159,23 @@ runShellCommands s commands = withChannel s $ \ch -> do   requestPTY ch "linux"   channelShell ch-  _hello <- readAllChannel ch+  _hello <- readAllChannelNonBlocking ch   out <- forM commands $ \cmd -> do              writeChannel ch (BSSC.pack $ cmd ++ "\n")-             r <- readAllChannel ch+             r <- readAllChannelNonBlocking ch              return r   channelSendEOF ch   return out  execCommands :: Session -> [String] -> IO (Int, [BSL.ByteString])-execCommands s commands = withChannel s $ \ch -> +execCommands s commands = withChannel s $ \ch ->   forM commands $ \cmd -> do       channelExecute ch cmd       readAllChannel ch  -- | Send a file to remote host via SCP. -- Returns size of sent data.-scpSendFile :: Session   +scpSendFile :: Session             -> Int       -- ^ File creation mode (0o777, for example)             -> FilePath  -- ^ Path to local file             -> FilePath  -- ^ Remote file path@@ -176,7 +189,7 @@     channelWaitEOF ch     return written   hClose h-  return result +  return result  -- | Receive file from remote host via SCP. -- Returns size of received data.@@ -186,7 +199,7 @@                -> IO Integer scpReceiveFile s remote local = do   h <- openFile local WriteMode-  (_, result) <- withChannelBy (scpReceiveChannel s remote) fst $ \(ch, fileSize) -> do  +  (_, result) <- withChannelBy (scpReceiveChannel s remote) fst $ \(ch, fileSize) -> do     readChannelToHandle ch h fileSize   hClose h   return result@@ -194,12 +207,12 @@ -- | Generalization of 'withChannel' withChannelBy :: IO a            -- ^ Create a channel (and possibly other stuff)               -> (a -> Channel)  -- ^ Extract the channel from "other stuff"-              -> (a -> IO b)     -- ^ Actions to execute on the channel +              -> (a -> IO b)     -- ^ Actions to execute on the channel               -> IO (Int, b)     -- ^ Channel exit status and return value withChannelBy createChannel extractChannel actions = do   stuff <- createChannel   let ch = extractChannel stuff-  result <- actions stuff +  result <- actions stuff   closeChannel ch   exitStatus <- channelExitStatus ch   freeChannel ch
src/Network/SSH/Client/LibSSH2/Errors.chs view
@@ -125,6 +125,9 @@ instance IntResult CLong where   intResult = fromIntegral +instance IntResult CLLong where+  intResult = fromIntegral+ {# fun session_last_error as getLastError_   { toPointer `Session',     alloca- `String' peekCStringPtr*,@@ -165,7 +168,7 @@         (r, _) <- getLastError session         case int2error r of           EAGAIN -> threadWaitSession (Just session) >> handleNullPtr s fromPointer io-          _      -> throw NULL_POINTER -- TODO: should we throw the error instead?+          err      -> throw err     else fromPointer p  -- | Get currently blocked directions@@ -180,5 +183,7 @@     Nothing -> error "EAGAIN thrown on session without socket"     Just socket -> do        dirs <- blockedDirections s-      when (INBOUND `elem` dirs)  $ threadWaitRead socket-      when (OUTBOUND `elem` dirs) $ threadWaitWrite socket+      if (OUTBOUND `elem` dirs)+        then threadWaitWrite socket+        else threadWaitRead socket+
src/Network/SSH/Client/LibSSH2/Foreign.chs view
@@ -38,7 +38,7 @@    channelProcess, channelExecute, channelShell,    requestPTY, requestPTYEx,    channelExitStatus, channelExitSignal,-   scpSendChannel, scpReceiveChannel,+   scpSendChannel, scpReceiveChannel, pollChannelRead_,     -- * Debug    TraceFlag (..), setTraceMode@@ -117,7 +117,11 @@  ssh2socket :: Socket  #ifdef mingw32_HOST_OS+    #ifdef x86_64_HOST_ARCH+           -> CULLong+    #else            -> CUInt+    #endif #else            -> CInt #endif@@ -282,7 +286,10 @@  -- | Execute shell command channelShell :: Channel -> IO () -channelShell c = void . handleInt (Just $ channelSession c) $ channelProcessStartup_ c "shell" ""  +channelShell c = void . handleInt (Just $ channelSession c) $ do+  withCStringLen "shell" $ \(s,l) -> do+    res <- channelProcessStartup_'_ (toPointer c) s (fromIntegral l) nullPtr 0+    return $ (res :: CInt)  {# fun channel_request_pty_ex as requestPTYEx   { toPointer `Channel',@@ -295,7 +302,7 @@ requestPTY ch term = void . handleInt (Just $ channelSession ch) $ requestPTYEx ch term "" 0 0 0 0  readChannelEx :: Channel -> Int -> Size -> IO BSS.ByteString -readChannelEx ch i size =+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)@@ -488,3 +495,6 @@        channel <- handleNullPtr (Just s) (channelFromPointer s) $ {# call scp_recv #} (toPointer s) pathptr statptr        size <- {# get stat_t->st_size #} statptr        return (channel, size)++{# fun poll_channel_read as pollChannelRead_+    { toPointer `Channel' } -> `Int' #}
+ src/Network/SSH/Client/LibSSH2/Foreign.hs view
@@ -0,0 +1,693 @@+-- GENERATED by C->Haskell Compiler, version 0.16.3 Crystal Seed, 24 Jan 2009 (Haskell)+-- Edit the ORIGNAL .chs file instead!+++{-# LINE 1 "src/Network/SSH/Client/LibSSH2/Foreign.chs" #-}{-# LANGUAGE CPP, ForeignFunctionInterface #-}++++{-# LINE 6 "src/Network/SSH/Client/LibSSH2/Foreign.chs" #-}++module Network.SSH.Client.LibSSH2.Foreign+  (-- * Types+   KnownHosts, KnownHostResult (..), KnownHostType (..), KnownHost (..),++   -- * Session functions+   initialize, exit,+   initSession, freeSession, disconnectSession,+   handshake,+   setBlocking,+   +   -- * Known hosts functions+   initKnownHosts, freeKnownHosts, knownHostsReadFile,+   getHostKey, checkKnownHost,++   -- * Authentication+   publicKeyAuthFile,+   usernamePasswordAuth,++   -- * Channel functions+   openChannelSession, closeChannel, freeChannel,+   channelSendEOF, channelWaitEOF, channelIsEOF,+   readChannel, writeChannel,+   writeChannelFromHandle, readChannelToHandle,+   channelProcess, channelExecute, channelShell,+   requestPTY, requestPTYEx,+   channelExitStatus, channelExitSignal,+   scpSendChannel, scpReceiveChannel,++   -- * Debug+   TraceFlag (..), setTraceMode+  ) where++import Foreign+import Foreign.C.Types+import Foreign.C.String+import System.IO+import Network.Socket (Socket(MkSocket))+import Data.Time.Clock.POSIX+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++-- Known host flags. See libssh2 documentation.+data KnownHostType =+    TYPE_MASK+  | TYPE_PLAIN+  | TYPE_SHA1+  | TYPE_CUSTOM+  | KEYENC_MASK+  | KEYENC_RAW+  | KEYENC_BASE64+  | KEY_MASK+  | KEY_SHIFT+  | KEY_RSA1+  | KEY_SSHRSA+  | KEY_SSHDSS+  deriving (Eq, Show)++kht2int :: KnownHostType -> CInt+kht2int TYPE_MASK   = 0xffff+kht2int TYPE_PLAIN  = 1+kht2int TYPE_SHA1   = 2+kht2int TYPE_CUSTOM = 3+kht2int KEYENC_MASK = 3 `shiftL` 16+kht2int KEYENC_RAW  = 1 `shiftL` 16+kht2int KEYENC_BASE64 = 2 `shiftL` 16+kht2int KEY_MASK    = 3 `shiftL` 18+kht2int KEY_SHIFT   = 18+kht2int KEY_RSA1    = 1 `shiftL` 18+kht2int KEY_SSHRSA  = 2 `shiftL` 18+kht2int KEY_SSHDSS  = 3 `shiftL` 18++typemask2int :: [KnownHostType] -> CInt+typemask2int list = foldr (.|.) 0 (map kht2int list)++-- Result of matching host against known_hosts.+data KnownHostResult =+    MATCH+  | MISMATCH+  | NOTFOUND+  | FAILURE+  deriving (Eq, Show, Ord, Enum)++int2khresult :: CInt -> KnownHostResult+int2khresult = toEnum . fromIntegral++data KnownHost = KnownHost {+  khMagic :: CUInt,+  khNode :: Ptr (),+  khName :: String,+  khKey :: String,+  khTypeMask :: [KnownHostType] }+  deriving (Eq, Show)++init_crypto :: Bool -> CInt+init_crypto False = 1+init_crypto True  = 0++ssh2socket :: Socket +           -> CInt+ssh2socket (MkSocket s _ _ _ _) =+  s++initialize_ :: Bool -> IO (Int)+initialize_ a1 =+  let {a1' = init_crypto a1} in +  initialize_'_ a1' >>= \res ->+  let {res' = fromIntegral res} in+  return (res')+{-# LINE 125 "src/Network/SSH/Client/LibSSH2/Foreign.chs" #-}++-- | Initialize libssh2. Pass True to enable encryption+-- or False to disable it.+initialize :: Bool -> IO ()+initialize flags = void . handleInt Nothing $ initialize_ flags++-- | Deinitialize libssh2.+exit :: IO ()+exit =+  exit'_ >>= \res ->+  return ()+{-# LINE 142 "src/Network/SSH/Client/LibSSH2/Foreign.chs" #-}++-- | Create Session object+initSession :: IO Session+initSession = handleNullPtr Nothing sessionFromPointer $ +  libssh2_session_init_ex nullFunPtr nullFunPtr nullFunPtr nullPtr++freeSession_ :: Session -> IO (Int)+freeSession_ a1 =+  let {a1' = toPointer a1} in +  freeSession_'_ a1' >>= \res ->+  let {res' = fromIntegral res} in+  return (res')+{-# LINE 150 "src/Network/SSH/Client/LibSSH2/Foreign.chs" #-}++-- | Free Session object's memory+freeSession :: Session -> IO ()+freeSession session = void . handleInt (Just session) $ freeSession_ session++disconnectSessionEx :: Session -> Int -> String -> String -> IO (Int)+disconnectSessionEx a1 a2 a3 a4 =+  let {a1' = toPointer a1} in +  let {a2' = fromIntegral a2} in +  withCString a3 $ \a3' -> +  withCString a4 $ \a4' -> +  disconnectSessionEx'_ a1' a2' a3' a4' >>= \res ->+  let {res' = fromIntegral res} in+  return (res')+{-# LINE 157 "src/Network/SSH/Client/LibSSH2/Foreign.chs" #-}++-- | Disconnect session (but do not free memory)+disconnectSession :: Session+                  -> String  -- ^ Goodbye message+                  -> IO () +disconnectSession s msg = void . handleInt (Just s) $ disconnectSessionEx s 11 msg ""++setBlocking :: Session -> Bool -> IO ()+setBlocking a1 a2 =+  let {a1' = toPointer a1} in +  let {a2' = bool2int a2} in +  setBlocking'_ a1' a2' >>= \res ->+  return ()+{-# LINE 166 "src/Network/SSH/Client/LibSSH2/Foreign.chs" #-}++bool2int :: Bool -> CInt+bool2int True  = 1+bool2int False = 0++handshake_ :: Session -> Socket -> IO (Int)+handshake_ a1 a2 =+  let {a1' = toPointer a1} in +  let {a2' = ssh2socket a2} in +  handshake_'_ a1' a2' >>= \res ->+  let {res' = fromIntegral res} in+  return (res')+{-# LINE 173 "src/Network/SSH/Client/LibSSH2/Foreign.chs" #-}++-- | Run SSH handshake on network socket.+handshake :: Session -> Socket -> IO ()+handshake session socket = do+  sessionSetSocket session (Just socket)+  void . handleInt (Just session) $ handshake_ session socket++initKnownHosts_ :: Session -> IO (Ptr ())+initKnownHosts_ a1 =+  let {a1' = toPointer a1} in +  initKnownHosts_'_ a1' >>= \res ->+  let {res' = id res} in+  return (res')+{-# LINE 182 "src/Network/SSH/Client/LibSSH2/Foreign.chs" #-}++-- | Create KnownHosts object for given session.+initKnownHosts :: Session -> IO KnownHosts+initKnownHosts session = handleNullPtr Nothing knownHostsFromPointer $ initKnownHosts_ session++-- | Free KnownHosts object's memory+freeKnownHosts :: KnownHosts -> IO ()+freeKnownHosts a1 =+  let {a1' = toPointer a1} in +  freeKnownHosts'_ a1' >>= \res ->+  return ()+{-# LINE 190 "src/Network/SSH/Client/LibSSH2/Foreign.chs" #-}++knownHostsReadFile_ :: KnownHosts -> String -> CInt -> IO (Int)+knownHostsReadFile_ a1 a2 a3 =+  let {a1' = toPointer a1} in +  withCString a2 $ \a2' -> +  let {a3' = id a3} in +  knownHostsReadFile_'_ a1' a2' a3' >>= \res ->+  let {res' = fromIntegral res} in+  return (res')+{-# LINE 193 "src/Network/SSH/Client/LibSSH2/Foreign.chs" #-}++-- | Read known hosts from file+knownHostsReadFile :: KnownHosts+                   -> FilePath   -- ^ Path to known_hosts file+                   -> IO Int+knownHostsReadFile kh path = handleInt Nothing $ knownHostsReadFile_ kh path 1++-- | Get remote host public key+getHostKey :: Session -> IO (String, Size, CInt)+getHostKey a1 =+  let {a1' = toPointer a1} in +  alloca $ \a2' -> +  alloca $ \a3' -> +  getHostKey'_ a1' a2' a3' >>= \res ->+  peek  a2'>>= \a2'' -> +  peek  a3'>>= \a3'' -> +  peekCString res >>= \res' ->+  return (res', a2'', a3'')+{-# LINE 203 "src/Network/SSH/Client/LibSSH2/Foreign.chs" #-}++checkKnownHost_ :: KnownHosts -> String -> Int -> String -> Int -> [KnownHostType] -> Ptr () -> IO (KnownHostResult)+checkKnownHost_ a1 a2 a3 a4 a5 a6 a7 =+  let {a1' = toPointer a1} in +  withCString a2 $ \a2' -> +  let {a3' = fromIntegral a3} in +  withCString a4 $ \a4' -> +  let {a5' = fromIntegral a5} in +  let {a6' = typemask2int a6} in +  let {a7' = castPtr a7} in +  checkKnownHost_'_ a1' a2' a3' a4' a5' a6' a7' >>= \res ->+  let {res' = int2khresult res} in+  return (res')+{-# LINE 212 "src/Network/SSH/Client/LibSSH2/Foreign.chs" #-}++-- | Check host data against known hosts.+checkKnownHost :: KnownHosts         -- +               -> String             -- ^ Host name+               -> Int                -- ^ Port number (usually 22)+               -> String             -- ^ Host public key+               -> [KnownHostType]    -- ^ Host flags (see libssh2 documentation)+               -> IO KnownHostResult+checkKnownHost kh host port key flags = checkKnownHost_ kh host port key (length key) flags nullPtr++-- TODO: I don't see the '&' in the libssh2 docs?+publicKeyAuthFile_ :: Session -> String -> String -> String -> String -> IO (Int)+publicKeyAuthFile_ a1 a2 a3 a4 a5 =+  let {a1' = toPointer a1} in +  withCStringLenIntConv a2 $ \(a2'1, a2'2) -> +  withCString a3 $ \a3' -> +  withCString a4 $ \a4' -> +  withCString a5 $ \a5' -> +  publicKeyAuthFile_'_ a1' a2'1  a2'2 a3' a4' a5' >>= \res ->+  let {res' = fromIntegral res} in+  return (res')+{-# LINE 229 "src/Network/SSH/Client/LibSSH2/Foreign.chs" #-}++-- | Perform public key authentication.+publicKeyAuthFile :: Session -- ^ Session+                  -> String  -- ^ Username+                  -> String  -- ^ Path to public key+                  -> String  -- ^ Path to private key+                  -> String  -- ^ Passphrase+                  -> IO ()+publicKeyAuthFile session username public private passphrase = void . handleInt (Just session) $ +  publicKeyAuthFile_ session username public private passphrase++-- | Perform username/password authentication.+usernamePasswordAuth :: Session -- ^ Session+                     -> String  -- ^ Username+                     -> String  -- ^ Password+                     -> IO ()+usernamePasswordAuth session username password =+  withCString username $ \usernameptr -> do+    withCString password $ \passwordptr -> do+      void . handleInt (Just session) $+        libssh2_userauth_password_ex (toPointer session) usernameptr (toEnum $ length username) passwordptr (toEnum $ length password) nullFunPtr++openSessionChannelEx :: Session -> String -> Int -> Int -> String -> IO (Ptr ())+openSessionChannelEx a1 a2 a3 a4 a5 =+  let {a1' = toPointer a1} in +  withCStringLenIntConv a2 $ \(a2'1, a2'2) -> +  let {a3' = fromIntegral a3} in +  let {a4' = fromIntegral a4} in +  withCStringLenIntConv a5 $ \(a5'1, a5'2) -> +  openSessionChannelEx'_ a1' a2'1  a2'2 a3' a4' a5'1  a5'2 >>= \res ->+  let {res' = id res} in+  return (res')+{-# LINE 256 "src/Network/SSH/Client/LibSSH2/Foreign.chs" #-}++-- | Open a channel for session.+openChannelSession :: Session -> IO Channel+openChannelSession s = handleNullPtr (Just s) (channelFromPointer s) $ +  openSessionChannelEx s "session" 65536 32768 ""++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 c command = channelProcess c "exec" command++channelProcessStartup_ :: Channel -> String -> String -> IO (Int)+channelProcessStartup_ a1 a2 a3 =+  let {a1' = toPointer a1} in +  withCStringLenIntConv a2 $ \(a2'1, a2'2) -> +  withCStringLenIntConv a3 $ \(a3'1, a3'2) -> +  channelProcessStartup_'_ a1' a2'1  a2'2 a3'1  a3'2 >>= \res ->+  let {res' = fromIntegral res} in+  return (res')+{-# LINE 274 "src/Network/SSH/Client/LibSSH2/Foreign.chs" #-}++-- | Execute shell command+channelShell :: Channel -> IO () +channelShell c = void . handleInt (Just $ channelSession c) $ channelProcessStartup_ c "shell" ""  ++requestPTYEx :: Channel -> String -> String -> Int -> Int -> Int -> Int -> IO (Int)+requestPTYEx a1 a2 a3 a4 a5 a6 a7 =+  let {a1' = toPointer a1} in +  withCStringLenIntConv a2 $ \(a2'1, a2'2) -> +  withCStringLenIntConv a3 $ \(a3'1, a3'2) -> +  let {a4' = fromIntegral a4} in +  let {a5' = fromIntegral a5} in +  let {a6' = fromIntegral a6} in +  let {a7' = fromIntegral a7} in +  requestPTYEx'_ a1' a2'1  a2'2 a3'1  a3'2 a4' a5' a6' a7' >>= \res ->+  let {res' = fromIntegral res} in+  return (res')+{-# LINE 285 "src/Network/SSH/Client/LibSSH2/Foreign.chs" #-}++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 ch i size =+  allocaBytes (fromIntegral size) $ \buffer -> do+    rc <- handleInt (Just $ channelSession ch) $ libssh2_channel_read_ex (toPointer ch) (fromIntegral i) buffer size+    BSS.packCStringLen (buffer, fromIntegral rc)++-- | Read data from channel.+readChannel :: Channel         -- +            -> Size             -- ^ Amount of data to read+            -> IO BSS.ByteString +readChannel c sz = readChannelEx c 0 sz++-- | Write data to channel.+writeChannel :: Channel -> BSS.ByteString -> IO () +writeChannel ch bs = +    BSS.unsafeUseAsCString bs $ go 0 (fromIntegral $ BSS.length bs)+  where+    go :: Int -> CULong -> CString -> IO () +    go offset len cstr = do+      written <- handleInt (Just $ channelSession ch) +                           $ libssh2_channel_write_ex (toPointer ch) +                                                         0 +                                                         (cstr `plusPtr` offset) +                                                         (fromIntegral len)+      if fromIntegral written < len +        then go (offset + fromIntegral written) (len - fromIntegral written) cstr+        else return ()++channelSendEOF_ :: Channel -> IO (Int)+channelSendEOF_ a1 =+  let {a1' = toPointer a1} in +  channelSendEOF_'_ a1' >>= \res ->+  let {res' = fromIntegral res} in+  return (res')+{-# LINE 319 "src/Network/SSH/Client/LibSSH2/Foreign.chs" #-}++channelSendEOF :: Channel -> IO ()+channelSendEOF channel = void . handleInt (Just $ channelSession channel) $ channelSendEOF_ channel++channelWaitEOF_ :: Channel -> IO (Int)+channelWaitEOF_ a1 =+  let {a1' = toPointer a1} in +  channelWaitEOF_'_ a1' >>= \res ->+  let {res' = fromIntegral res} in+  return (res')+{-# LINE 325 "src/Network/SSH/Client/LibSSH2/Foreign.chs" #-}++channelWaitEOF :: Channel -> IO ()+channelWaitEOF channel = void . handleInt (Just $ channelSession channel) $ channelWaitEOF_ channel++data TraceFlag =+    T_TRANS+  | T_KEX+  | T_AUTH+  | T_CONN+  | T_SCP+  | T_SFTP+  | T_ERROR+  | T_PUBLICKEY+  | T_SOCKET+  deriving (Eq, Show)++tf2int :: TraceFlag -> CInt+tf2int T_TRANS = 1 `shiftL` 1+tf2int T_KEX   = 1 `shiftL` 2+tf2int T_AUTH  = 1 `shiftL` 3+tf2int T_CONN  = 1 `shiftL` 4+tf2int T_SCP   = 1 `shiftL` 5+tf2int T_SFTP  = 1 `shiftL` 6+tf2int T_ERROR = 1 `shiftL` 7+tf2int T_PUBLICKEY = 1 `shiftL` 8+tf2int T_SOCKET = 1 `shiftL` 9++trace2int :: [TraceFlag] -> CInt+trace2int flags = foldr (.|.) 0 (map tf2int flags)++setTraceMode :: Session -> [TraceFlag] -> IO ()+setTraceMode a1 a2 =+  let {a1' = toPointer a1} in +  let {a2' = trace2int a2} in +  setTraceMode'_ a1' a2' >>= \res ->+  return ()+{-# LINE 357 "src/Network/SSH/Client/LibSSH2/Foreign.chs" #-}++-- | Write all data to channel from handle.+-- Returns amount of transferred data.+writeChannelFromHandle :: Channel -> Handle -> IO Integer+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 +      if sz < bufferSize+        then return newDone +        else go newDone buffer+ +    send :: Int -> CLong -> Ptr a -> IO () +    send _ 0 _ = return () +    send written size buffer = do+      sent <- handleInt (Just $ channelSession ch) $ +                libssh2_channel_write_ex+{-# LINE 377 "src/Network/SSH/Client/LibSSH2/Foreign.chs" #-}+                  (toPointer ch)+                  0+                  (plusPtr buffer written)+                  (fromIntegral size)+      send (written + fromIntegral sent) (size - fromIntegral sent) buffer++    bufferSize = 0x100000++  in allocaBytes bufferSize $ go 0 ++-- | Read all data from channel to handle.+-- Returns amount of transferred data.+readChannelToHandle :: Channel -> Handle -> Offset -> IO Integer+readChannelToHandle ch h fileSize = do+    allocaBytes bufferSize $ \buffer ->+        readChannelCB ch buffer bufferSize fileSize callback+  where+    callback buffer size = hPutBuf h buffer size++    bufferSize :: Int+    bufferSize = 0x100000++readChannelCB :: Channel -> CString -> Int -> Offset -> (CString -> Int -> IO ()) -> IO Integer+readChannelCB ch buffer bufferSize fileSize callback =+  let go got = do+        let toRead = min (fromIntegral fileSize - got) (fromIntegral bufferSize)+        sz <- handleInt (Just $ channelSession ch) $ +                libssh2_channel_read_ex+{-# LINE 405 "src/Network/SSH/Client/LibSSH2/Foreign.chs" #-}+                  (toPointer ch)+                  0+                  buffer+                  (fromIntegral toRead)+        let isz :: Integer+            isz = fromIntegral sz+        callback buffer (fromIntegral sz)+        eof <- libssh2_channel_eof (toPointer ch)+        let newGot = got + fromIntegral sz+        if  (eof == 1) || (newGot == fromIntegral fileSize)+          then do+               return isz+          else do+               rest <- go newGot+               return $ isz + rest+  in go (0 :: Integer)++channelIsEOF :: Channel -> IO (Bool)+channelIsEOF a1 =+  let {a1' = toPointer a1} in +  channelIsEOF'_ a1' >>= \res ->+  handleBool res >>= \res' ->+  return (res')+{-# LINE 424 "src/Network/SSH/Client/LibSSH2/Foreign.chs" #-}++closeChannel_ :: Channel -> IO (Int)+closeChannel_ a1 =+  let {a1' = toPointer a1} in +  closeChannel_'_ a1' >>= \res ->+  let {res' = fromIntegral res} in+  return (res')+{-# LINE 427 "src/Network/SSH/Client/LibSSH2/Foreign.chs" #-}++-- | Close channel (but do not free memory)+closeChannel :: Channel -> IO ()+closeChannel channel = void . handleInt (Just $ channelSession channel) $ closeChannel_ channel++freeChannel_ :: Channel -> IO (Int)+freeChannel_ a1 =+  let {a1' = toPointer a1} in +  freeChannel_'_ a1' >>= \res ->+  let {res' = fromIntegral res} in+  return (res')+{-# LINE 434 "src/Network/SSH/Client/LibSSH2/Foreign.chs" #-}++-- | Free channel object's memory+freeChannel :: Channel -> IO ()+freeChannel channel = void . handleInt (Just $ channelSession channel) $ freeChannel_ channel++-- | Get channel exit status+channelExitStatus :: Channel -> IO (Int)+channelExitStatus a1 =+  let {a1' = toPointer a1} in +  channelExitStatus'_ a1' >>= \res ->+  let {res' = fromIntegral res} in+  return (res')+{-# LINE 442 "src/Network/SSH/Client/LibSSH2/Foreign.chs" #-}++channelExitSignal_ :: Channel -> Ptr Int -> Ptr Int -> Ptr Int -> IO (Int, String, Maybe String, Maybe String)+channelExitSignal_ a1 a3 a5 a7 =+  let {a1' = toPointer a1} in +  alloca $ \a2' -> +  let {a3' = castPtr a3} in +  alloca $ \a4' -> +  let {a5' = castPtr a5} in +  alloca $ \a6' -> +  let {a7' = castPtr a7} in +  channelExitSignal_'_ a1' a2' a3' a4' a5' a6' a7' >>= \res ->+  peekCStringPtr  a2'>>= \a2'' -> +  peekMaybeCStringPtr  a4'>>= \a4'' -> +  peekMaybeCStringPtr  a6'>>= \a6'' -> +  let {res' = fromIntegral res} in+  return (res', a2'', a4'', a6'')+{-# LINE 451 "src/Network/SSH/Client/LibSSH2/Foreign.chs" #-}++-- | Get channel exit signal. Returns:+-- (possibly error code, exit signal name, possibly error message, possibly language code).+channelExitSignal :: Channel -> IO (Int, String, Maybe String, Maybe String)+channelExitSignal ch = handleInt (Just $ channelSession ch) $ channelExitSignal_ ch nullPtr nullPtr nullPtr++scpSendChannel_ :: Session -> String -> Int -> Int64 -> POSIXTime -> POSIXTime -> IO (Ptr ())+scpSendChannel_ a1 a2 a3 a4 a5 a6 =+  let {a1' = toPointer a1} in +  withCString a2 $ \a2' -> +  let {a3' = fromIntegral a3} in +  let {a4' = fromIntegral a4} in +  let {a5' = round a5} in +  let {a6' = round a6} in +  scpSendChannel_'_ a1' a2' a3' a4' a5' a6' >>= \res ->+  let {res' = id res} in+  return (res')+{-# LINE 464 "src/Network/SSH/Client/LibSSH2/Foreign.chs" #-}++-- | 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++type Offset = (CLong)+{-# LINE 471 "src/Network/SSH/Client/LibSSH2/Foreign.chs" #-}++-- {# pointer *stat_t as Stat newtype #}++-- | Create SCP file receive channel.+-- TODO: receive struct stat also.+scpReceiveChannel :: Session -> FilePath -> IO (Channel, Offset)+scpReceiveChannel s path = do+  withCString path $ \pathptr ->+     allocaBytes 144 $ \statptr -> do+       channel <- handleNullPtr (Just s) (channelFromPointer s) $ libssh2_scp_recv (toPointer s) pathptr statptr+       size <- (\ptr -> do {peekByteOff ptr 48 ::IO CLong}) statptr+       return (channel, size)++foreign import ccall safe "src/Network/SSH/Client/LibSSH2/Foreign.chs.h libssh2_init"+  initialize_'_ :: (CInt -> (IO CInt))++foreign import ccall safe "src/Network/SSH/Client/LibSSH2/Foreign.chs.h libssh2_exit"+  exit'_ :: (IO ())++foreign import ccall safe "src/Network/SSH/Client/LibSSH2/Foreign.chs.h libssh2_session_init_ex"+  libssh2_session_init_ex :: ((FunPtr (CULong -> ((Ptr (Ptr ())) -> (IO (Ptr ()))))) -> ((FunPtr ((Ptr ()) -> ((Ptr (Ptr ())) -> (IO ())))) -> ((FunPtr ((Ptr ()) -> (CULong -> ((Ptr (Ptr ())) -> (IO (Ptr ())))))) -> ((Ptr ()) -> (IO (Ptr ()))))))++foreign import ccall safe "src/Network/SSH/Client/LibSSH2/Foreign.chs.h libssh2_session_free"+  freeSession_'_ :: ((Ptr ()) -> (IO CInt))++foreign import ccall safe "src/Network/SSH/Client/LibSSH2/Foreign.chs.h libssh2_session_disconnect_ex"+  disconnectSessionEx'_ :: ((Ptr ()) -> (CInt -> ((Ptr CChar) -> ((Ptr CChar) -> (IO CInt)))))++foreign import ccall safe "src/Network/SSH/Client/LibSSH2/Foreign.chs.h libssh2_session_set_blocking"+  setBlocking'_ :: ((Ptr ()) -> (CInt -> (IO ())))++foreign import ccall safe "src/Network/SSH/Client/LibSSH2/Foreign.chs.h libssh2_session_handshake"+  handshake_'_ :: ((Ptr ()) -> (CInt -> (IO CInt)))++foreign import ccall safe "src/Network/SSH/Client/LibSSH2/Foreign.chs.h libssh2_knownhost_init"+  initKnownHosts_'_ :: ((Ptr ()) -> (IO (Ptr ())))++foreign import ccall safe "src/Network/SSH/Client/LibSSH2/Foreign.chs.h libssh2_knownhost_free"+  freeKnownHosts'_ :: ((Ptr ()) -> (IO ()))++foreign import ccall safe "src/Network/SSH/Client/LibSSH2/Foreign.chs.h libssh2_knownhost_readfile"+  knownHostsReadFile_'_ :: ((Ptr ()) -> ((Ptr CChar) -> (CInt -> (IO CInt))))++foreign import ccall safe "src/Network/SSH/Client/LibSSH2/Foreign.chs.h libssh2_session_hostkey"+  getHostKey'_ :: ((Ptr ()) -> ((Ptr CULong) -> ((Ptr CInt) -> (IO (Ptr CChar)))))++foreign import ccall safe "src/Network/SSH/Client/LibSSH2/Foreign.chs.h libssh2_knownhost_checkp"+  checkKnownHost_'_ :: ((Ptr ()) -> ((Ptr CChar) -> (CInt -> ((Ptr CChar) -> (CULong -> (CInt -> ((Ptr (Ptr ())) -> (IO CInt))))))))++foreign import ccall safe "src/Network/SSH/Client/LibSSH2/Foreign.chs.h libssh2_userauth_publickey_fromfile_ex"+  publicKeyAuthFile_'_ :: ((Ptr ()) -> ((Ptr CChar) -> (CUInt -> ((Ptr CChar) -> ((Ptr CChar) -> ((Ptr CChar) -> (IO CInt)))))))++foreign import ccall safe "src/Network/SSH/Client/LibSSH2/Foreign.chs.h libssh2_userauth_password_ex"+  libssh2_userauth_password_ex :: ((Ptr ()) -> ((Ptr CChar) -> (CUInt -> ((Ptr CChar) -> (CUInt -> ((FunPtr ((Ptr ()) -> ((Ptr (Ptr CChar)) -> ((Ptr CInt) -> ((Ptr (Ptr ())) -> (IO ())))))) -> (IO CInt)))))))++foreign import ccall safe "src/Network/SSH/Client/LibSSH2/Foreign.chs.h libssh2_channel_open_ex"+  openSessionChannelEx'_ :: ((Ptr ()) -> ((Ptr CChar) -> (CUInt -> (CUInt -> (CUInt -> ((Ptr CChar) -> (CUInt -> (IO (Ptr ())))))))))++foreign import ccall safe "src/Network/SSH/Client/LibSSH2/Foreign.chs.h libssh2_channel_process_startup"+  channelProcessStartup_'_ :: ((Ptr ()) -> ((Ptr CChar) -> (CUInt -> ((Ptr CChar) -> (CUInt -> (IO CInt))))))++foreign import ccall safe "src/Network/SSH/Client/LibSSH2/Foreign.chs.h libssh2_channel_request_pty_ex"+  requestPTYEx'_ :: ((Ptr ()) -> ((Ptr CChar) -> (CUInt -> ((Ptr CChar) -> (CUInt -> (CInt -> (CInt -> (CInt -> (CInt -> (IO CInt))))))))))++foreign import ccall safe "src/Network/SSH/Client/LibSSH2/Foreign.chs.h libssh2_channel_read_ex"+  libssh2_channel_read_ex :: ((Ptr ()) -> (CInt -> ((Ptr CChar) -> (CULong -> (IO CLong)))))++foreign import ccall safe "src/Network/SSH/Client/LibSSH2/Foreign.chs.h libssh2_channel_write_ex"+  libssh2_channel_write_ex :: ((Ptr ()) -> (CInt -> ((Ptr CChar) -> (CULong -> (IO CLong)))))++foreign import ccall safe "src/Network/SSH/Client/LibSSH2/Foreign.chs.h libssh2_channel_send_eof"+  channelSendEOF_'_ :: ((Ptr ()) -> (IO CInt))++foreign import ccall safe "src/Network/SSH/Client/LibSSH2/Foreign.chs.h libssh2_channel_wait_eof"+  channelWaitEOF_'_ :: ((Ptr ()) -> (IO CInt))++foreign import ccall safe "src/Network/SSH/Client/LibSSH2/Foreign.chs.h libssh2_trace"+  setTraceMode'_ :: ((Ptr ()) -> (CInt -> (IO CInt)))++foreign import ccall safe "src/Network/SSH/Client/LibSSH2/Foreign.chs.h libssh2_channel_eof"+  libssh2_channel_eof :: ((Ptr ()) -> (IO CInt))++foreign import ccall safe "src/Network/SSH/Client/LibSSH2/Foreign.chs.h libssh2_channel_eof"+  channelIsEOF'_ :: ((Ptr ()) -> (IO CInt))++foreign import ccall safe "src/Network/SSH/Client/LibSSH2/Foreign.chs.h libssh2_channel_close"+  closeChannel_'_ :: ((Ptr ()) -> (IO CInt))++foreign import ccall safe "src/Network/SSH/Client/LibSSH2/Foreign.chs.h libssh2_channel_free"+  freeChannel_'_ :: ((Ptr ()) -> (IO CInt))++foreign import ccall safe "src/Network/SSH/Client/LibSSH2/Foreign.chs.h libssh2_channel_get_exit_status"+  channelExitStatus'_ :: ((Ptr ()) -> (IO CInt))++foreign import ccall safe "src/Network/SSH/Client/LibSSH2/Foreign.chs.h libssh2_channel_get_exit_signal"+  channelExitSignal_'_ :: ((Ptr ()) -> ((Ptr (Ptr CChar)) -> ((Ptr CULong) -> ((Ptr (Ptr CChar)) -> ((Ptr CULong) -> ((Ptr (Ptr CChar)) -> ((Ptr CULong) -> (IO CInt))))))))++foreign import ccall safe "src/Network/SSH/Client/LibSSH2/Foreign.chs.h libssh2_scp_send64"+  scpSendChannel_'_ :: ((Ptr ()) -> ((Ptr CChar) -> (CInt -> (CLLong -> (CLong -> (CLong -> (IO (Ptr ()))))))))++foreign import ccall safe "src/Network/SSH/Client/LibSSH2/Foreign.chs.h libssh2_scp_recv"+  libssh2_scp_recv :: ((Ptr ()) -> ((Ptr CChar) -> ((Ptr ()) -> (IO (Ptr ())))))