summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArtyom V. Poptsov <poptsov.artyom@gmail.com>2016-10-30 12:36:04 +0400
committerArtyom V. Poptsov <poptsov.artyom@gmail.com>2016-10-30 12:36:04 +0400
commitef80c1f70453b6e52124a1f47b0aeef72e7a48c1 (patch)
tree07a4610261d06c1715544c35418c9ffbf1f57974
parentNEWS: Bump version to 0.10.1 (diff)
downloadguile-ssh-ef80c1f70453b6e52124a1f47b0aeef72e7a48c1.tar.gz
channel.scm (channel-send-eof!): New procedure
* modules/ssh/channel.scm (channel-send-eof!): New procedure. * libguile-ssh/channel-func.c (gssh_channel_send_eof_x): New procedure. * doc/api-channels.texi: Add description of 'channel-send-eof!'. * tests/client-server.scm ("channel-send-eof!"): New TC. * doc/version.texi, NEWS: Update.
-rw-r--r--NEWS8
-rw-r--r--doc/api-channels.texi42
-rw-r--r--doc/version.texi5
-rw-r--r--libguile-ssh/channel-func.c27
-rw-r--r--modules/ssh/channel.scm10
-rw-r--r--tests/client-server.scm26
6 files changed, 117 insertions, 1 deletions
diff --git a/NEWS b/NEWS
index d659fd2..5f984b0 100644
--- a/NEWS
+++ b/NEWS
@@ -7,6 +7,14 @@ Copyright (C) Artyom V. Poptsov <poptsov.artyom@gmail.com>
are permitted in any medium without royalty provided the copyright
notice and this notice are preserved.
+* Unreleased
+** New procedures
+*** New procedure 'channel-send-eof!' in (ssh channel)
+ The procedure allows to send end-of-file (EOF) on a channel. This action
+ doesn't close the channel; you may still read from it but not write.
+ 'channel-send-eof!' is handy when we deal with a remote command that reads
+ data until EOF (such as 'wc'.)
+
* Changes in version 0.10.1 (2016-10-09)
** Bugfixes
*** Fix SMOB freeing callbacks
diff --git a/doc/api-channels.texi b/doc/api-channels.texi
index 827a343..e3231b0 100644
--- a/doc/api-channels.texi
+++ b/doc/api-channels.texi
@@ -132,6 +132,48 @@ Get the session to which belongs the @var{channel}. Throw
@code{guile-ssh-error} on an error. Return the session.
@end deffn
+@deffn {Scheme Procedure} channel-send-eof! channel
+Send an end of file (EOF) on the @var{channel}. This action doesn't close the
+@var{channel}; you may still read from it but not write. Throw
+@code{guile-ssh-error} on an error. Return value is undefined.
+
+Example:
+
+@lisp
+(use-modules (ice-9 rdelim)
+ ;; Guile-SSH modules.
+ (ssh auth)
+ (ssh popen)
+ (ssh session)
+ (ssh channel))
+
+;; Make a session
+(define s (make-session #:host "example.org"))
+
+;; Connect to the server
+(connect! s)
+
+;; Authenticate
+(userauth-agent! s)
+
+;; Open a remote pipe to 'wc' command running on
+;; the server.
+(let ((p (open-remote-pipe s "wc" OPEN_BOTH)))
+
+ ;; Send data to 'wc' command using the remote pipe.
+ (display "Hello Scheme World!" p)
+
+ ;; 'wc' reads data until EOF and writes its result
+ ;; afterwards.
+ (channel-send-eof! p)
+
+ ;; Read the 'wc' output.
+ (read-line p))
+@result{} " 0 3 19"
+@end lisp
+
+@end deffn
+
@deffn {Scheme Procedure} channel-eof? channel
Return @code{#t} if remote has sent @acronym{EOF}, @code{#f} otherwise. Throw
@code{guile-ssh-error} if the channel has been closed and freed.
diff --git a/doc/version.texi b/doc/version.texi
index cc70a06..e2494e1 100644
--- a/doc/version.texi
+++ b/doc/version.texi
@@ -1,4 +1,9 @@
@set UPDATED 9 October 2016
@set UPDATED-MONTH October 2016
+<<<<<<< Updated upstream
@set EDITION 0.10.1
@set VERSION 0.10.1
+=======
+@set EDITION 0.10.0
+@set VERSION 0.10.0
+>>>>>>> Stashed changes
diff --git a/libguile-ssh/channel-func.c b/libguile-ssh/channel-func.c
index 3636cb4..c02286b 100644
--- a/libguile-ssh/channel-func.c
+++ b/libguile-ssh/channel-func.c
@@ -468,6 +468,33 @@ SCM_DEFINE (guile_ssh_channel_is_open_p, "channel-open?", 1, 0, 0,
return SCM_BOOL_F;
}
+SCM_GSSH_DEFINE (gssh_channel_send_eof_x, "%channel-send-eof!",
+ 1, (SCM channel))
+#define FUNC_NAME s_gssh_channel_send_eof_x
+{
+ struct channel_data *cd = _scm_to_channel_data (channel);
+ scm_t_bits pt_bits;
+ int rc;
+
+ GSSH_VALIDATE_CHANNEL_DATA (cd, channel, FUNC_NAME);
+
+ pt_bits = SCM_CELL_TYPE (channel);
+ if ((pt_bits & SCM_WRTNG) == 0)
+ {
+ guile_ssh_error1 (FUNC_NAME, "Could not send EOF on an input channel",
+ channel);
+ }
+
+ rc = ssh_channel_send_eof (cd->ssh_channel);
+ if (rc == SSH_ERROR)
+ guile_ssh_error1 (FUNC_NAME, "Could not send EOF on a channel", channel);
+
+ SCM_SET_CELL_TYPE (channel, pt_bits & ~SCM_WRTNG);
+
+ return SCM_UNDEFINED;
+}
+#undef FUNC_NAME
+
SCM_DEFINE (guile_ssh_channel_is_eof_p, "channel-eof?", 1, 0, 0,
(SCM channel),
"\
diff --git a/modules/ssh/channel.scm b/modules/ssh/channel.scm
index 0dfd6a5..0fe4cb3 100644
--- a/modules/ssh/channel.scm
+++ b/modules/ssh/channel.scm
@@ -1,6 +1,6 @@
;;; channel.scm -- API for SSH channel manipulation.
-;; Copyright (C) 2013, 2014, 2015 Artyom V. Poptsov <poptsov.artyom@gmail.com>
+;; Copyright (C) 2013, 2014, 2015, 2016 Artyom V. Poptsov <poptsov.artyom@gmail.com>
;;
;; This file is a part of Guile-SSH.
;;
@@ -39,6 +39,7 @@
;; channel-set-stream!
;; channel-get-stream
;; channel-open?
+;; channel-send-eof!
;; channel-eof?
@@ -66,6 +67,7 @@
channel-get-session
channel-get-exit-status
channel-open?
+ channel-send-eof!
channel-eof?))
(define* (make-channel session #:optional (mode OPEN_BOTH))
@@ -114,6 +116,12 @@ channel, and the second value is a port number on which the connection was
issued."
(%channel-accept-forward session timeout))
+(define (channel-send-eof! channel)
+ "Send an end of file (EOF) on the CHANNEL. This action doesn't close the
+channel; you may still read from it but not write. Throw 'guile-ssh-error' on
+an error. Return value is undefined."
+ (%channel-send-eof! channel))
+
;;;
diff --git a/tests/client-server.scm b/tests/client-server.scm
index dac6aba..370f0d6 100644
--- a/tests/client-server.scm
+++ b/tests/client-server.scm
@@ -646,6 +646,32 @@
;;;
+;;; Channels
+;;;
+
+;; Client opens a channel to a server, sends data and then sends EOF on the
+;; channel. Server reads data and sends it back. Client checks if the
+;; channel is closed for output, and reads the data.
+(test-assert-with-log "channel-send-eof!"
+ (run-client-test
+ (lambda (server)
+ (start-server/dt-test server
+ (lambda (channel)
+ (let ((str (read-line channel)))
+ (write-line str channel)))))
+ (lambda ()
+ (call-with-connected-session/channel-test
+ (lambda (session)
+ (let ((channel (make-channel/dt-test session))
+ (str "Hello Scheme World!"))
+ (write-line str channel)
+ (channel-send-eof! channel)
+ (and (input-port? channel)
+ (not (output-port? channel))
+ (string=? (read-line channel) str))))))))
+
+
+;;;
(test-end "client-server")