88
88
(def ^java.nio.charset.Charset ascii
89
89
(java.nio.charset.Charset/forName " US-ASCII" ))
90
90
91
+ (def ^java.nio.charset.Charset utf-8
92
+ (java.nio.charset.Charset/forName " UTF-8" ))
93
+
91
94
(defn- ^{:tag (Class/forName " [B" )} as-bytes
92
95
" Return arg as a byte array. arg must be a string or a byte array."
93
96
[arg]
126
129
(defn session?
127
130
" Predicate to test for a session"
128
131
[x]
129
- (satisfies? x protocols/Session))
132
+ (satisfies? protocols/Session x ))
130
133
131
134
; ;; Agent
132
135
(defn ssh-agent
@@ -589,30 +592,42 @@ config options."
589
592
(let [os (PipedInputStream. (int *piped-stream-buffer-size*))]
590
593
[os (PipedOutputStream. os)]))
591
594
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
593
602
" 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 )]
597
606
(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))
604
610
(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 ))))
608
612
(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)]
612
629
(if out-inputstream
613
- (do
614
- (connect-channel shell)
615
- {:channel shell :out-stream out-inputstream})
630
+ {:channel shell :out-stream out-inputstream}
616
631
(with-channel-connection shell
617
632
(while (connected-channel? shell)
618
633
(Thread/sleep 100 ))
@@ -621,37 +636,49 @@ config options."
621
636
(.toByteArray ^ByteArrayOutputStream out-stream)
622
637
(.toString out-stream))}))))
623
638
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
+
624
663
(defn ssh-exec
625
664
" Run a command via ssh-exec."
626
665
[^Session session ^String cmd in out opts]
627
- (let [^ChannelExec exec (open-channel session :exec )
628
- [^PipedOutputStream out-stream
666
+ (let [[^PipedOutputStream out-stream
629
667
^PipedInputStream out-inputstream] (streams-for-out out)
630
668
[^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)]
649
678
(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}
655
682
(with-channel-connection exec
656
683
(while (connected-channel? exec)
657
684
(Thread/sleep 100 ))
0 commit comments