summaryrefslogtreecommitdiff
path: root/modules/ssh/channel.scm
blob: 7b3629ed21b62c422bde38d1661c1636f553d6e7 (about) (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
;;; channel.scm -- API for SSH channel manipulation.

;; Copyright (C) 2013, 2014 Artyom V. Poptsov <poptsov.artyom@gmail.com>
;;
;; This file is a part of Guile-SSH.
;;
;; Guile-SSH is free software: you can redistribute it and/or
;; modify it under the terms of the GNU General Public License as
;; published by the Free Software Foundation, either version 3 of the
;; License, or (at your option) any later version.
;;
;; Guile-SSH is distributed in the hope that it will be useful, but
;; WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
;; General Public License for more details.
;;
;; You should have received a copy of the GNU General Public License
;; along with Guile-SSH.  If not, see
;; <http://www.gnu.org/licenses/>.


;;; Commentary:

;; This module contains API that is used for working with SSH
;; channels.
;;
;; These procedures are exported:
;;
;;   channel?
;;   make-channel
;;   channel-open-session
;;   channel-request-env
;;   channel-request-exec
;;   channel-request-pty
;;   channel-request-shell
;;   channel-open-forward
;;   channel-cancel-forward
;;   channel-set-pty-size!
;;   channel-set-stream!
;;   channel-get-stream
;;   channel-open?
;;   channel-eof?


;;; Code:

(define-module (ssh channel)
  #:use-module (ssh log)
  #:use-module (ssh session)
  #:export (channel
            channel?
            make-channel
            channel-open-session
            channel-request-env
            channel-request-exec
            channel-request-pty
            channel-request-shell
            channel-open-forward
            channel-listen-forward
            channel-accept-forward
            channel-cancel-forward
            channel-request-send-exit-status
            channel-set-pty-size!
            channel-set-stream!
            channel-get-stream
            channel-get-session
            channel-get-exit-status
            channel-open?
            channel-eof?

            ;; High-level procedures.
            open-remote-pipe
            open-remote-pipe*))

(define* (make-channel session #:optional (flags O_RDWR))
  (cond
    ((= flags O_RDWR)
     (%make-channel session (logior RDNG WRTNG)))
    ((= flags O_RDONLY)
     (%make-channel session RDNG))
    ((= flags O_WRONLY)
     (%make-channel session WRTNG))
    (else
     (throw 'guile-ssh-error "Wrong flags" flags))))


(define* (channel-open-forward channel
                               #:key (source-host "localhost") local-port
                               remote-host (remote-port local-port))
  "Open a TCP/IP forwarding channel.  Connect to a REMOTE-HOST and REMOTE-PORT,
and use SOURCE-HOST and LOCAL-PORT as origination of connections.

If the SOURCE-HOST is not set, then \"localhost\" is used.  If REMOTE-PORT is
not set, then it will be set to LOCAL-PORT value.

Please note that the procedure does not bind the LOCAL-PORT and does not
automatically forward the content of a socket to the channel."
  (%channel-open-forward channel
                         remote-host remote-port
                         source-host local-port))

(define* (channel-listen-forward session #:key (address #f) (port 0))
  "Send the \"tcpip-forward\" global request using SESSION to ask the server
to begin listening for inbound connections on the specified ADDRESS and PORT.
If ADDRESS is not specified (or set to #f) then the server binds all addresses
on all protocol families supported by the server.  When 0 is passed as a PORT
then server allocates the next unprivileged port.

The procedure returns two values: the first value is the result of the
operation (either 'ok', 'again' or 'error'), and the second value is the bound
port number (if PORT was set to 0)."
  (%channel-listen-forward session address port))

(define* (channel-accept-forward session #:optional (timeout 0))
  "Accept an incoming TCP/IP forwarding channel and get information about
incoming connection.  Return two values: the first value is the incoming
channel, and the second value is a port number on which the connection was
issued."
  (%channel-accept-forward session timeout))


;;; High-level procedures.

(define (open-remote-pipe session command)
  "Execute a COMMAND on the remote host using a SESSION with a pipe to it.
The pipe works in both directions.  Returns newly created port (channel)."
  (let ((channel (make-channel session)))
    (unless channel
      (throw 'guile-ssh-error "Could not create a channel" session command))
    (channel-open-session channel)
    (channel-request-pty channel)
    (channel-request-exec channel command)
    channel))

(define (open-remote-pipe* session prog . args)
  "Execute COMMANDS on the remote host using a SESSION with a pipe to it.  The
pipe works in both directions.  Returns newly created port (channel)."
  (open-remote-pipe session (string-join (cons prog args))))

;;;


(load-extension "libguile-ssh" "init_channel")

;;; channel.scm ends here.