Skip to content

Commit 425ef5e

Browse files
committed
Merge release/0.5.10
2 parents a24ef52 + 7902f5d commit 425ef5e

File tree

5 files changed

+86
-63
lines changed

5 files changed

+86
-63
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ Thanks to [Ryan Stradling](http://github.com/rstradling) for these.
163163
Via [clojars](http://clojars.org) and
164164
[Leiningen](http://github.com/technomancy/leiningen).
165165

166-
:dependencies [clj-ssh "0.5.9"]
166+
:dependencies [clj-ssh "0.5.10"]
167167

168168
or your favourite maven repository aware tool.
169169

ReleaseNotes.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,12 @@
1+
## 0.5.10
2+
3+
- Fix session? predicate
4+
5+
- Factor out ssh-exec-proc and ssh-shell-proc
6+
These provide a lower level interface with more flexible stream handling.
7+
8+
- Add java.awt.headless to default java opts
9+
110
## 0.5.9
211

312
- Publish new jars

profiles.clj

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,11 @@
11
{:dev
22
{:dependencies [[ch.qos.logback/logback-classic "1.0.0"]]
33
:plugins [[lein-pallet-release "RELEASE"]]
4-
:pallet-release
5-
{:url "https://pbors:${GH_TOKEN}@github.com/hugoduncan/clj-ssh.git",
6-
:branch "master"}
74
:aliases {"test" ["with-profile"
85
"clojure-1.4.0:clojure-1.5.1:clojure-1.6.0"
96
"test"]}}
107
:clojure-1.2.1 {:dependencies [[org.clojure/clojure "1.2.1"]]}
118
:clojure-1.3.0 {:dependencies [[org.clojure/clojure "1.3.0"]]}
129
:clojure-1.4.0 {:dependencies [[org.clojure/clojure "1.4.0"]]}
1310
:clojure-1.5.1 {:dependencies [[org.clojure/clojure "1.5.1"]]}
14-
:clojure-1.6.0 {:dependencies [[org.clojure/clojure "1.6.0"]]}
15-
:doc {:dependencies [[com.palletops/pallet-codox "0.1.0-SNAPSHOT"]
16-
[codox-md "0.2.0" :exclusions [org.clojure/clojure]]]
17-
:plugins [[codox/codox.leiningen "0.6.4"]
18-
[lein-marginalia "0.7.1"]]
19-
:codox {:writer codox-md.writer/write-docs
20-
:output-dir "doc/0.5/api"
21-
:src-dir-uri "https://github.com/hugoduncan/clj-ssh/blob/develop"
22-
:src-linenum-anchor-prefix "L"}
23-
:aliases {"marg" ["marg" "-d" "doc/0.5/annotated"]
24-
"codox" ["doc"]
25-
"doc" ["do" "codox," "marg"]}}}
11+
:clojure-1.6.0 {:dependencies [[org.clojure/clojure "1.6.0"]]}}

project.clj

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
(def agentproxy-version "0.0.7")
22

3-
(defproject clj-ssh "0.5.9"
3+
(defproject clj-ssh "0.5.10"
44
:description "Library for using SSH from clojure."
55
:url "https://github.com/hugoduncan/clj-ssh"
66
:license {:name "Eclipse Public License"
@@ -14,4 +14,5 @@
1414
[com.jcraft/jsch.agentproxy.pageant ~agentproxy-version]
1515
[com.jcraft/jsch.agentproxy.core ~agentproxy-version]
1616
[com.jcraft/jsch.agentproxy.jsch ~agentproxy-version]
17-
[com.jcraft/jsch "0.1.51"]])
17+
[com.jcraft/jsch "0.1.51"]]
18+
:jvm-opts ["-Djava.awt.headless=true"])

src/clj_ssh/ssh.clj

Lines changed: 72 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,9 @@
8888
(def ^java.nio.charset.Charset ascii
8989
(java.nio.charset.Charset/forName "US-ASCII"))
9090

91+
(def ^java.nio.charset.Charset utf-8
92+
(java.nio.charset.Charset/forName "UTF-8"))
93+
9194
(defn- ^{:tag (Class/forName "[B")} as-bytes
9295
"Return arg as a byte array. arg must be a string or a byte array."
9396
[arg]
@@ -126,7 +129,7 @@
126129
(defn session?
127130
"Predicate to test for a session"
128131
[x]
129-
(satisfies? x protocols/Session))
132+
(satisfies? protocols/Session x))
130133

131134
;;; Agent
132135
(defn ssh-agent
@@ -589,30 +592,42 @@ config options."
589592
(let [os (PipedInputStream. (int *piped-stream-buffer-size*))]
590593
[os (PipedOutputStream. os)]))
591594

592-
(defn ssh-shell
595+
(defn string-stream
596+
"Return an input stream with content from the string s."
597+
[^String s]
598+
{:pre [(string? s)]}
599+
(ByteArrayInputStream. (.getBytes s utf-8)))
600+
601+
(defn ssh-shell-proc
593602
"Run a ssh-shell."
594-
[^Session session in out opts]
595-
(let [^ChannelShell shell (open-channel session :shell)
596-
[out-stream out-inputstream] (streams-for-out out)]
603+
[^Session session in {:keys [agent-forwarding pty out err] :as opts}]
604+
{:pre [in]}
605+
(let [^ChannelShell shell (open-channel session :shell)]
597606
(doto shell
598-
(.setInputStream
599-
(if (string? in)
600-
(ByteArrayInputStream. (.getBytes (str in ";exit $?;\n")))
601-
in)
602-
false)
603-
(.setOutputStream out-stream))
607+
(.setInputStream in false))
608+
(when out
609+
(.setOutputStream shell out))
604610
(when (contains? opts :pty)
605-
(reflect/call-method
606-
com.jcraft.jsch.ChannelSession 'setPty [Boolean/TYPE]
607-
shell (boolean (opts :pty))))
611+
(.setPty shell (boolean (opts :pty))))
608612
(when (contains? opts :agent-forwarding)
609-
(reflect/call-method
610-
com.jcraft.jsch.ChannelSession 'setAgentForwarding [Boolean/TYPE]
611-
shell (boolean (opts :agent-forwarding))))
613+
(.setAgentForwarding shell (boolean (opts :agent-forwarding))))
614+
(let [resp {:channel shell
615+
:out (or out (.getInputStream shell))
616+
:in (or in (.getOutputStream shell))}]
617+
(connect-channel shell)
618+
resp)))
619+
620+
(defn ssh-shell
621+
"Run a ssh-shell."
622+
[^Session session in out opts]
623+
(let [[out-stream out-inputstream] (streams-for-out out)
624+
resp (ssh-shell-proc
625+
session
626+
(if (string? in) (string-stream (str in ";exit $?;\n")) in)
627+
(merge {:out out-stream} opts))
628+
^ChannelShell shell (:channel resp)]
612629
(if out-inputstream
613-
(do
614-
(connect-channel shell)
615-
{:channel shell :out-stream out-inputstream})
630+
{:channel shell :out-stream out-inputstream}
616631
(with-channel-connection shell
617632
(while (connected-channel? shell)
618633
(Thread/sleep 100))
@@ -621,37 +636,49 @@ config options."
621636
(.toByteArray ^ByteArrayOutputStream out-stream)
622637
(.toString out-stream))}))))
623638

639+
(defn ssh-exec-proc
640+
"Run a command via exec, returning a map with the process streams."
641+
[^Session session ^String cmd
642+
{:keys [agent-forwarding pty in out err] :as opts}]
643+
(let [^ChannelExec exec (open-channel session :exec)]
644+
(doto exec
645+
(.setCommand cmd)
646+
(.setInputStream in false))
647+
(when (contains? opts :pty)
648+
(.setPty exec (boolean (opts :pty))))
649+
(when (contains? opts :agent-forwarding)
650+
(.setAgentForwarding exec (boolean (opts :agent-forwarding))))
651+
652+
(when out
653+
(.setOutputStream exec out))
654+
(when err
655+
(.setErrStream exec err))
656+
(let [resp {:channel exec
657+
:out (or out (.getInputStream exec))
658+
:err (or err (.getErrStream exec))
659+
:in (or in (.getOutputStream exec))}]
660+
(connect-channel exec)
661+
resp)))
662+
624663
(defn ssh-exec
625664
"Run a command via ssh-exec."
626665
[^Session session ^String cmd in out opts]
627-
(let [^ChannelExec exec (open-channel session :exec)
628-
[^PipedOutputStream out-stream
666+
(let [[^PipedOutputStream out-stream
629667
^PipedInputStream out-inputstream] (streams-for-out out)
630668
[^PipedOutputStream err-stream
631-
^PipedInputStream err-inputstream] (streams-for-out out)]
632-
(doto exec
633-
(.setInputStream
634-
(if (string? in)
635-
(ByteArrayInputStream. (.getBytes ^String in))
636-
in)
637-
false)
638-
(.setOutputStream out-stream)
639-
(.setErrStream err-stream)
640-
(.setCommand cmd))
641-
(when (contains? opts :pty)
642-
(reflect/call-method
643-
com.jcraft.jsch.ChannelSession 'setPty [Boolean/TYPE]
644-
exec (boolean (opts :pty))))
645-
(when (contains? opts :agent-forwarding)
646-
(reflect/call-method
647-
com.jcraft.jsch.ChannelSession 'setAgentForwarding [Boolean/TYPE]
648-
exec (boolean (opts :agent-forwarding))))
669+
^PipedInputStream err-inputstream] (streams-for-out out)
670+
proc (ssh-exec-proc
671+
session cmd
672+
(merge
673+
{:in (if (string? in) (string-stream in) in)
674+
:out out-stream
675+
:err err-stream}
676+
opts))
677+
^ChannelExec exec (:channel proc)]
649678
(if out-inputstream
650-
(do
651-
(connect-channel exec)
652-
{:channel exec
653-
:out-stream out-inputstream
654-
:err-stream err-inputstream})
679+
{:channel exec
680+
:out-stream out-inputstream
681+
:err-stream err-inputstream}
655682
(with-channel-connection exec
656683
(while (connected-channel? exec)
657684
(Thread/sleep 100))

0 commit comments

Comments
 (0)