diff options
| author | Artyom V. Poptsov <poptsov.artyom@gmail.com> | 2016-10-30 12:36:04 +0400 |
|---|---|---|
| committer | Artyom V. Poptsov <poptsov.artyom@gmail.com> | 2016-10-30 12:36:04 +0400 |
| commit | ef80c1f70453b6e52124a1f47b0aeef72e7a48c1 (patch) | |
| tree | 07a4610261d06c1715544c35418c9ffbf1f57974 | |
| parent | NEWS: Bump version to 0.10.1 (diff) | |
| download | guile-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-- | NEWS | 8 | ||||
| -rw-r--r-- | doc/api-channels.texi | 42 | ||||
| -rw-r--r-- | doc/version.texi | 5 | ||||
| -rw-r--r-- | libguile-ssh/channel-func.c | 27 | ||||
| -rw-r--r-- | modules/ssh/channel.scm | 10 | ||||
| -rw-r--r-- | tests/client-server.scm | 26 |
6 files changed, 117 insertions, 1 deletions
@@ -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") |
