diff options
| author | Artyom Poptsov <poptsov.artyom@gmail.com> | 2014-01-02 23:14:41 +0400 |
|---|---|---|
| committer | Artyom Poptsov <poptsov.artyom@gmail.com> | 2014-01-02 23:14:41 +0400 |
| commit | e0171febf8cb240a8defdabeeed51dcd6ac2eefe (patch) | |
| tree | 8df32d2d3ec00d57d1fb9ea3f8ae2470b2b0105f | |
| parent | configure.ac, NEWS: Bump version to 0.4.0 (diff) | |
| download | guile-ssh-e0171febf8cb240a8defdabeeed51dcd6ac2eefe.tar.gz | |
Use Guile port API to implement Guile-SSH channels.
* src/channel-func.c (guile_ssh_channel_read)
(guile_ssh_channel_write): Remove.
* src/channel-func.h (guile_ssh_channel_read): Remove.
* src/channel-type.c (ptob_fill_input, ptob_write, ptob_flush)
(ptob_input_waiting, _ssh_channel_to_scm): New procedures.
(guile_ssh_make_channel): Use `_ssh_channel_to_scm'.
(_scm_to_ssh_channel): Use `SCM_STREAM' macro.
(init_channel_type): Register Guile port callbacks.
* src/channel-type.h (_ssh_channel_to_scm): Export.
* src/channel.scm (channel-read, channel-write): Remove.
* src/message-func.c
(guile_ssh_message_channel_request_open_reply_accept): Use
`_ssh_channel_to_scm'.
* examples/echo: Add to the repository.
* examples/Makefile.am: Add echo server/client example.
* examples/README: Update.
* examples/sssh.scm: Update.
* README: Update.
| -rw-r--r-- | ChangeLog | 22 | ||||
| -rw-r--r-- | README | 8 | ||||
| -rw-r--r-- | examples/Makefile.am | 4 | ||||
| -rw-r--r-- | examples/README | 18 | ||||
| -rwxr-xr-x | examples/echo/client.scm | 144 | ||||
| -rwxr-xr-x | examples/echo/server.scm | 145 | ||||
| -rwxr-xr-x | examples/sssh.scm | 11 | ||||
| -rw-r--r-- | src/channel-func.c | 68 | ||||
| -rw-r--r-- | src/channel-func.h | 3 | ||||
| -rw-r--r-- | src/channel-type.c | 136 | ||||
| -rw-r--r-- | src/channel-type.h | 6 | ||||
| -rw-r--r-- | src/channel.scm | 4 | ||||
| -rw-r--r-- | src/message-func.c | 17 |
13 files changed, 460 insertions, 126 deletions
@@ -1,3 +1,25 @@ +2014-01-02 Artyom Poptsov <poptsov.artyom@gmail.com> + + Use Guile port API to implement Guile-SSH channels. + * src/channel-func.c (guile_ssh_channel_read) + (guile_ssh_channel_write): Remove. + * src/channel-func.h (guile_ssh_channel_read): Remove. + * src/channel-type.c (ptob_fill_input, ptob_write, ptob_flush) + (ptob_input_waiting, _ssh_channel_to_scm): New procedures. + (guile_ssh_make_channel): Use `_ssh_channel_to_scm'. + (_scm_to_ssh_channel): Use `SCM_STREAM' macro. + (init_channel_type): Register Guile port callbacks. + * src/channel-type.h (_ssh_channel_to_scm): Export. + * src/channel.scm (channel-read, channel-write): Remove. + * src/message-func.c + (guile_ssh_message_channel_request_open_reply_accept): Use + `_ssh_channel_to_scm'. + * examples/echo: Add to the repository. + * examples/Makefile.am: Add echo server/client example. + * examples/README: Update. + * examples/sssh.scm: Update. + * README: Update. + 2013-11-26 Artyom Poptsov <poptsov.artyom@gmail.com> * configure.ac, NEWS: Bump version to 0.4.0 @@ -45,9 +45,11 @@ Guile modules, in ${GUILE_SITE}/ssh: - version.scm -- Information about versions. Examples, in ${prefix}/share/libguile-ssh/examples - - ssshd.scm -- SSH server example. - - sssh.scm -- SSH client example. - + - ssshd.scm -- SSH server example. + - sssh.scm -- SSH client example. + + echo/ + - client.scm -- Echo client example. + - server.scm -- Echo server example. * Installation For a basic explanation of the installation of the package, see the diff --git a/examples/Makefile.am b/examples/Makefile.am index 2679423..77bbcde 100644 --- a/examples/Makefile.am +++ b/examples/Makefile.am @@ -1,4 +1,4 @@ -## Copyright (C) 2013 Artyom V. Poptsov <poptsov.artyom@gmail.com> +## Copyright (C) 2013, 2014 Artyom V. Poptsov <poptsov.artyom@gmail.com> ## ## This file is part of libguile-ssh. ## @@ -17,4 +17,6 @@ ## <http://www.gnu.org/licenses/>. examplesdir = $(pkgdatadir)/examples +examples_echodir = $(pkgdatadir)/examples/echo dist_examples_DATA = README sssh.scm ssshd.scm +dist_examples_echo_DATA = echo/*.scm diff --git a/examples/README b/examples/README index 3e2917c..f83ecb2 100644 --- a/examples/README +++ b/examples/README @@ -1,31 +1,29 @@ -# -*- mode: outline; -*- +# -*- mode: org; -*- * Overview - This directory includes an examples of programs that use Guile-SSH library to access SSH protocol * Scheme Secure Shell (SSSH) - SSSH uses Guile-SSH API to implement basic SSH client functionality. - ** Usage - Please see - ./sssh.scm --help for information about program usage. ** Examples - ./sssh.scm --identity=~/.ssh/id_rsa --user=avp localhost "uname -a" * Scheme Secure Shell Daemon (SSSHD) - SSSHD uses Guile-SSH API to implement basic SSH server functionality. - ** Usage - ./ssshd.scm +* Echo server and client +Implementation of an SSH based echo protocol ([[https://tools.ietf.org/html/rfc862][RFC862]]) with Guile-SSH. +Please find sources in `echo/' directory: + - echo/client.scm + - echo/server.scm + + diff --git a/examples/echo/client.scm b/examples/echo/client.scm new file mode 100755 index 0000000..478aa67 --- /dev/null +++ b/examples/echo/client.scm @@ -0,0 +1,144 @@ +#!/usr/bin/guile \ +--debug -e main +!# + +;;; client.scm -- Echo client example. + +;; Copyright (C) 2013-2014 Artyom V. Poptsov <poptsov.artyom@gmail.com> +;; +;; This program 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. +;; +;; This program 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 this program. If not, see +;; <http://www.gnu.org/licenses/>. + + +;;; Commentary: + + +;;; Code: + +(use-modules (ice-9 getopt-long) + (ice-9 rdelim) + (ssh channel) + (ssh session) + (ssh auth) + (ssh key)) + +(define *program-name* "echo-client") +(define *default-identity-file* + (string-append (getenv "HOME") "/.ssh/id_rsa")) + + +;; Command line options +(define *option-spec* + '((user (single-char #\u) (value #t)) + (port (single-char #\p) (value #t)) + (identity-file (single-char #\i) (value #t)) + (help (single-char #\h) (value #f)))) + + +(define (print-help) + "Print information about program usage." + (display + (string-append + *program-name* " -- Echo client example.\n" + "Copyright (C) Artyom Poptsov <poptsov.artyom@gmail.com>\n" + "Licensed under GNU GPLv3+\n" + "\n" + "Usage: " *program-name* " [ -upidv ] <host> <string>\n" + "\n" + "Options:\n" + " --user=<user>, -u <user> User name\n" + " --port=<port-number>, -p <port-number> Port number\n" + " --identity-file=<file>, -i <file> Path to private key\n"))) + + +(define (handle-error session) + "Handle a SSH error." + (display (get-error session)) + (newline) + (exit 1)) + +(define (get-prvkey session identity-file) + (let ((prvkey (private-key-from-file session identity-file))) + (if (not prvkey) + (handle-error session)) + prvkey)) + +(define (get-pubkey session prvkey) + (let ((pubkey (private-key->public-key prvkey))) + (if (not pubkey) + (handle-error session)) + pubkey)) + + +(define (main args) + "Entry point of the program." + (if (null? (cdr args)) + (begin + (print-help) + (exit 0))) + + (let* ((options (getopt-long args *option-spec*)) + (user (option-ref options 'user (getenv "USER"))) + (port (string->number (option-ref options 'port "22"))) + (identity-file (option-ref options 'identity-file + *default-identity-file*)) + (help-needed? (option-ref options 'help #f)) + (args (option-ref options '() #f))) + + + + (if help-needed? + (begin + (print-help) + (exit 0))) + + (if (or (null? args) (null? (cdr args))) + (begin + (print-help) + (exit 0))) + + (let* ((host (car args)) + (str (cadr args)) + (session (make-session #:user user + #:host host + #:port port + #:log-verbosity 0))) ;Be quiet + + (connect! session) + (case (authenticate-server session) + ((not-known) (display " The server is unknown. Please check MD5.\n"))) + + (let* ((private-key (get-prvkey session identity-file)) + (public-key (get-pubkey session private-key))) + + (if (eqv? (userauth-pubkey! session #f public-key private-key) 'error) + (handle-error session)) + + (let ((channel (make-channel session))) + + (if (not channel) + (handle-error session)) + + (channel-open-session channel) + + (display str channel) + + (let poll ((count #f)) + (if (or (not count) (zero? count)) + (poll (channel-poll channel #f)) + (begin + (display (read-line channel)) + (newline))))))))) + +;;; echo.scm ends here. diff --git a/examples/echo/server.scm b/examples/echo/server.scm new file mode 100755 index 0000000..29b1376 --- /dev/null +++ b/examples/echo/server.scm @@ -0,0 +1,145 @@ +#!/usr/bin/guile \ +--debug -e main -s +!# + +(use-modules (ice-9 rdelim) + (ice-9 popen) + (ssh server) + (ssh message) + (ssh session) + (ssh channel) + (ssh key) + (ssh auth)) ; userauth-* + +(define *default-bindport* 12345) +(define *default-log-verbosity* 0) +(define *default-rsakey* (string-append (getenv "HOME") + "/.ssh/id_rsa")) + +(define (handle-req-auth session msg msg-type) + (let ((subtype (cadr msg-type))) + + (format #t " subtype: ~a~%" subtype) + + ;; Allowed authentication methods + (message-auth-set-methods! msg '(public-key)) + + (case subtype + ((auth-method-publickey) + (let* ((req (message-get-req msg)) + (user (auth-req:user req)) + (pubkey (auth-req:pubkey req)) + (pubkey-state (auth-req:pubkey-state req))) + (format #t + (string-append " User ~a wants to authenticate with a public key (~a)~%" + " Public key state: ~a~%") + user (get-key-type pubkey) pubkey-state) + + (case pubkey-state + ((none) + (message-auth-reply-public-key-ok msg)) + + ((valid) + (message-reply-success msg)) + + (else + (format #t " Bad public key state: ~a~%" pubkey-state) + (message-reply-default msg))))) + + (else + (message-reply-default msg))))) + +(define (handle-req-channel-open msg msg-type) + (let ((subtype (cadr msg-type))) + (format #t " subtype: ~a~%" subtype) + (case subtype + ((channel-session) + (message-channel-request-open-reply-accept msg)) + (else + (message-reply-default msg) + #f)))) + +(define (handle-req-channel msg msg-type channel) + (let ((subtype (cadr msg-type))) + + (format #t " subtype: ~a~%" subtype) + + (case subtype + + ((channel-request-env) + (let* ((env-req (message-get-req msg)) + (name (env-req:name env-req)) + (value (env-req:value env-req))) + (format #t + (string-append " env requested:~%" + " name: ~a~%" + " value: ~a~%") + name value) + (setenv name value) + (message-reply-success msg))) + + (else + (message-reply-success msg))))) + +(define (main args) + (let ((server (make-server #:bindport *default-bindport* + #:rsakey *default-rsakey* + #:log-verbosity *default-log-verbosity* + #:banner "Scheme Secure Shell Daemon")) + (channel #f)) + + (format #t (string-append + "Using private key ~a~%" + "Listening on port ~a~%") + *default-rsakey* + *default-bindport*) + + ;; Start listen to incoming connections. + (server-listen server) + + ;; Accept new connections from clients. Every connection is + ;; handled in its own SSH session. + (let main-loop ((session (server-accept server))) + (display "Client accepted.\n") + (server-handle-key-exchange session) + ;; Handle messages from the connected SSH client. + (let session-loop ((msg (server-message-get session))) + (if msg + (let ((msg-type (message-get-type msg))) + (format #t "Message: ~a~%" msg-type) + ;; Check the type of the message + (case (car msg-type) + ((request-service) + (let ((srv-req (message-get-req msg))) + (format #t " Service requested: ~a~%" + (service-req:service srv-req)) + (message-reply-success msg))) + + ((request-auth) + (handle-req-auth session msg msg-type)) + + ((request-channel-open) + (set! channel (handle-req-channel-open msg msg-type)) + (let poll ((count #f)) + (if (or (not count) (zero? count)) + (poll (channel-poll channel #f)) + (let ((str (read-line channel))) + (format #t "Received message: ~a~%" str) + (display "Echoing back...\n") + (display str channel))))) + + ((request-channel) + (handle-req-channel msg msg-type channel)) + + (else + (display "Reply default\n") + (message-reply-default msg))))) + ;; (if channel + ;; (let ((str (read-line channel))) + ;; (display str)))) + (if (connected? session) + (session-loop (server-message-get session)))) + (disconnect! session) + (main-loop (server-accept server))))) + +;;; server.scm ends here. diff --git a/examples/sssh.scm b/examples/sssh.scm index 27be506..f49c825 100755 --- a/examples/sssh.scm +++ b/examples/sssh.scm @@ -4,7 +4,7 @@ ;;; sssh.scm -- Scheme Secure Shell. -;; Copyright (C) 2013 Artyom V. Poptsov <poptsov.artyom@gmail.com> +;; Copyright (C) 2013, 2014 Artyom V. Poptsov <poptsov.artyom@gmail.com> ;; ;; This program is free software: you can redistribute it and/or ;; modify it under the terms of the GNU General Public License as @@ -30,6 +30,7 @@ ;;; Code: (use-modules (ice-9 getopt-long) + (ice-9 rdelim) (ssh channel) (ssh session) (ssh auth) @@ -200,11 +201,7 @@ (poll (channel-poll channel #f)) (begin (print-debug "10. channel-read (ssh_channel_read)\n") - (let ((result (channel-read channel count #f))) - (if (not result) - (handle-error session) - (begin - (display result) - (newline)))))))))))) + (display (read-line channel)) + (newline))))))))) ;;; sssh.scm ends here diff --git a/src/channel-func.c b/src/channel-func.c index 6da8b69..429aab7 100644 --- a/src/channel-func.c +++ b/src/channel-func.c @@ -1,6 +1,6 @@ /* channel-func.c -- SSH channel manipulation functions. * - * Copyright (C) 2013 Artyom V. Poptsov <poptsov.artyom@gmail.com> + * Copyright (C) 2013, 2014 Artyom V. Poptsov <poptsov.artyom@gmail.com> * * This file is part of libguile-ssh * @@ -184,72 +184,6 @@ SCM_DEFINE (guile_ssh_channel_pool, "channel-poll", 2, 0, 0, } #undef FUNC_NAME -/* Read data from the channel. - - Return #f if no data is available. Throw guile-ssh-error on - error. */ -SCM_DEFINE (guile_ssh_channel_read, "channel-read", 3, 0, 0, - (SCM channel, SCM count, SCM is_stderr), - "Read data from the channel CHANNEL.") -#define FUNC_NAME s_guile_ssh_channel_read -{ - struct channel_data *data = _scm_to_ssh_channel (channel); - int res; - char *buffer; /* Buffer for data. */ - uint32_t c_count; /* Size of buffer. */ - SCM obtained_data = SCM_BOOL_F; /* Obtained data from the channel. */ - - SCM_ASSERT (scm_is_unsigned_integer (count, 0, UINT32_MAX), count, - SCM_ARG2, FUNC_NAME); - SCM_ASSERT (scm_is_bool (is_stderr), is_stderr, SCM_ARG3, FUNC_NAME); - - c_count = scm_to_unsigned_integer (count, 0, UINT32_MAX); - buffer = scm_gc_calloc (sizeof (char) * c_count + 1, "data buffer"); - res = ssh_channel_read (data->ssh_channel, buffer, c_count + 1, - scm_is_true (is_stderr)); - - if (res > 0) - { - buffer[res] = 0; /* Avoid getting garbage in a SCM string */ - obtained_data = scm_from_locale_string (buffer); - } - - scm_gc_free (buffer, sizeof (char) + c_count + 1, "data buffer"); - - if (res < 0) - { - /* Throw the exception only if an error is occured (res < 0). - Return #t if res == 0 (no data is available). */ - guile_ssh_error1 (FUNC_NAME, "Couldn't read data from a channel.", - SCM_BOOL_F); - } - - return obtained_data; -} -#undef FUNC_NAME - -SCM_DEFINE (guile_ssh_channel_write, "channel-write", 3, 0, 0, - (SCM channel, SCM len, SCM data), - "Write data DATA of the length LEN to the channel CHANNEL") -#define FUNC_NAME s_guile_ssh_channel_write -{ - struct channel_data *channel_data = _scm_to_ssh_channel (channel); - int res; - uint32_t c_len; - char *c_data; - - SCM_ASSERT (scm_is_unsigned_integer (len, 0, UINT32_MAX), len, - SCM_ARG2, FUNC_NAME); - - c_len = scm_to_uint32 (len); - c_data = scm_to_locale_string (data); - - res = ssh_channel_write (channel_data->ssh_channel, c_data, c_len); - - return (res != SSH_ERROR) ? scm_from_int (res) : SCM_BOOL_F; -} -#undef FUNC_NAME - /* Close a channel. */ SCM_DEFINE (guile_ssh_channel_close, "close-channel!", 1, 0, 0, (SCM channel), diff --git a/src/channel-func.h b/src/channel-func.h index 94390dd..fbc9716 100644 --- a/src/channel-func.h +++ b/src/channel-func.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2013 Artyom V. Poptsov <poptsov.artyom@gmail.com> +/* Copyright (C) 2013, 2014 Artyom V. Poptsov <poptsov.artyom@gmail.com> * * This file is part of libguile-ssh * @@ -22,7 +22,6 @@ extern SCM guile_ssh_channel_open_session (SCM arg1); extern SCM guile_ssh_channel_request_exec (SCM arg1, SCM arg2); extern SCM guile_ssh_channel_pool (SCM arg1, SCM arg2); -extern SCM guile_ssh_channel_read (SCM arg1, SCM arg2, SCM arg3); extern SCM guile_ssh_channel_close (SCM arg1); extern SCM guile_ssh_channel_is_open_p (SCM arg1); diff --git a/src/channel-type.c b/src/channel-type.c index 7084f52..b4dba66 100644 --- a/src/channel-type.c +++ b/src/channel-type.c @@ -1,6 +1,6 @@ /* channel-type.c -- SSH channel smob. * - * Copyright (C) 2013 Artyom V. Poptsov <poptsov.artyom@gmail.com> + * Copyright (C) 2013, 2014 Artyom V. Poptsov <poptsov.artyom@gmail.com> * * This file is part of libguile-ssh * @@ -20,6 +20,7 @@ #include <libguile.h> #include <libssh/libssh.h> +#include <assert.h> #include "session-type.h" #include "channel-type.h" @@ -27,8 +28,64 @@ scm_t_bits channel_tag; /* Smob tag. */ +enum { PORT_BUFSZ = 256 }; /* Size of the port's buffer */ + -/* Smob specific procedures */ +/* Ptob specific procedures */ + +/* Read data from the channel. + + Return EOF if no data is available or an error occured */ +static int +ptob_fill_input (SCM port) +{ + /* DEBUG */ + scm_puts ("fill_input: Called.\n", scm_current_output_port ()); + + struct channel_data *cd = _scm_to_ssh_channel (port); + scm_port *pt = SCM_PTAB_ENTRY (port); + int res; + + res = ssh_channel_read (cd->ssh_channel, + pt->read_buf, PORT_BUFSZ, + cd->is_stderr); + + if (res >= 0) + pt->read_end = pt->read_buf + res; + + return (res > 0) ? 0 : EOF; +} + +static void +ptob_write (SCM channel, const void *data, size_t sz) +{ + /* DEBUG */ + scm_puts ("write: Called.\n", scm_current_output_port ()); + + struct channel_data *channel_data = _scm_to_ssh_channel (channel); + int res = ssh_channel_write (channel_data->ssh_channel, data, sz); + if (res == SSH_ERROR) + { + ssh_session session = ssh_channel_get_session (channel_data->ssh_channel); + guile_ssh_error1 ("write", ssh_get_error (session), channel); + } +} + +static void +ptob_flush (SCM channel) +{ + /* DEBUG */ + scm_puts ("flush: Called.\n", scm_current_output_port ()); + scm_port *pt = SCM_PTAB_ENTRY (channel); + pt->read_end = pt->read_buf; +} + +static int +ptob_input_waiting (SCM channel) +{ + /* DEBUG */ + scm_puts ("input_waiting: Called.\n", scm_current_output_port ()); +} SCM mark_channel (SCM channel_smob) @@ -48,7 +105,12 @@ static int print_channel (SCM smob, SCM port, scm_print_state *pstate) { struct channel_data *ch = _scm_to_ssh_channel (smob); + + assert (ch); + assert (ch->ssh_channel); + int is_open = ssh_channel_is_open (ch->ssh_channel); + scm_puts ("#<", port); scm_puts (is_open ? "open" : "closed", port); scm_puts (" ssh channel>", port); @@ -56,24 +118,58 @@ print_channel (SCM smob, SCM port, scm_print_state *pstate) return 1; } +/* Pack the SSH channel CH to a Scheme port and return newly created + port. */ +SCM +_ssh_channel_to_scm (ssh_channel ch) +{ + struct channel_data *channel_data; + SCM ptob; + scm_port *pt; + + channel_data = scm_gc_malloc (sizeof (struct channel_data), "channel"); + + channel_data->ssh_channel = ch; + channel_data->is_stderr = 0; /* Reading from stderr disabled by default */ + + ptob = scm_new_port_table_entry (channel_tag); + pt = SCM_PTAB_ENTRY (ptob); + + pt->rw_random = 0; + + /* Output init */ + pt->write_buf = scm_gc_malloc (PORT_BUFSZ, "port write buffer"); + pt->write_buf_size = PORT_BUFSZ; + pt->write_pos = pt->write_buf; + pt->write_end = pt->write_buf; + + /* Input init */ + pt->read_buf = scm_gc_malloc (PORT_BUFSZ, "port read buffer"); + pt->read_buf_size = PORT_BUFSZ; + pt->read_pos = pt->read_buf; + pt->read_end = pt->read_buf; + + SCM_SET_CELL_TYPE (ptob, + (channel_tag | SCM_OPN + | SCM_RDNG | SCM_WRTNG + | SCM_BUFLINE)); + SCM_SETSTREAM (ptob, channel_data); + + return ptob; +} + /* Allocate a new SSH channel. */ SCM_DEFINE (guile_ssh_make_channel, "make-channel", 1, 0, 0, (SCM arg1), "Allocate a new SSH channel.") { - SCM smob; - struct session_data *session_data = _scm_to_ssh_session (arg1); - struct channel_data *channel_data - = (struct channel_data *) scm_gc_malloc (sizeof (struct channel_data), - "channel"); - channel_data->ssh_channel = ssh_channel_new (session_data->ssh_session); - if (channel_data->ssh_channel == NULL) - return SCM_BOOL_F; + ssh_channel ch = ssh_channel_new (session_data->ssh_session); - SCM_NEWSMOB (smob, channel_tag, channel_data); + if (! ch) + return SCM_BOOL_F; - return smob; + return _ssh_channel_to_scm (ch); } @@ -108,7 +204,7 @@ struct channel_data * _scm_to_ssh_channel (SCM x) { scm_assert_smob_type (channel_tag, x); - return (struct channel_data *) SCM_SMOB_DATA (x); + return (struct channel_data *) SCM_STREAM (x); } @@ -116,12 +212,14 @@ _scm_to_ssh_channel (SCM x) void init_channel_type (void) { - channel_tag = scm_make_smob_type ("channel", - sizeof (struct channel_data)); - scm_set_smob_mark (channel_tag, mark_channel); - scm_set_smob_free (channel_tag, free_channel); - scm_set_smob_print (channel_tag, print_channel); - scm_set_smob_equalp (channel_tag, equalp_channel); + channel_tag = scm_make_port_type ("channel", + &ptob_fill_input, + &ptob_write); + scm_set_port_flush (channel_tag, ptob_flush); + scm_set_port_mark (channel_tag, mark_channel); + scm_set_port_free (channel_tag, free_channel); + scm_set_port_print (channel_tag, print_channel); + scm_set_port_equalp (channel_tag, equalp_channel); #include "channel-type.x" } diff --git a/src/channel-type.h b/src/channel-type.h index 8a79a7e..56816a2 100644 --- a/src/channel-type.h +++ b/src/channel-type.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2013 Artyom V. Poptsov <poptsov.artyom@gmail.com> +/* Copyright (C) 2013, 2014 Artyom V. Poptsov <poptsov.artyom@gmail.com> * * This file is part of libguile-ssh * @@ -28,6 +28,7 @@ extern scm_t_bits channel_tag; /* Smob data. */ struct channel_data { ssh_channel ssh_channel; + uint8_t is_stderr; }; @@ -40,6 +41,7 @@ extern void init_channel_type (void); /* Helper procedures */ -struct channel_data *_scm_to_ssh_channel (SCM x); +extern struct channel_data *_scm_to_ssh_channel (SCM x); +extern SCM _ssh_channel_to_scm (ssh_channel ch); #endif /* ifndef __CHANNEL_TYPE_H__ */ diff --git a/src/channel.scm b/src/channel.scm index 008ac64..5b58e1c 100644 --- a/src/channel.scm +++ b/src/channel.scm @@ -37,8 +37,6 @@ ;; channel-request-shell ;; channel-set-pty-size! ;; channel-poll -;; channel-read -;; channel-write ;; channel-open? ;; channel-eof? @@ -59,8 +57,6 @@ channel-request-shell channel-set-pty-size! channel-poll - channel-read - channel-write channel-open? channel-eof?)) diff --git a/src/message-func.c b/src/message-func.c index 5968a48..5c7123b 100644 --- a/src/message-func.c +++ b/src/message-func.c @@ -1,6 +1,6 @@ /* message-func.c -- Functions for working with SSH messages. * - * Copyright (C) 2013 Artyom V. Poptsov <poptsov.artyom@gmail.com> + * Copyright (C) 2013, 2014 Artyom V. Poptsov <poptsov.artyom@gmail.com> * * This file is part of libguile-ssh * @@ -119,19 +119,14 @@ SCM_DEFINE (guile_ssh_message_channel_request_open_reply_accept, "Accept open-channel request.\n" "Return a new SSH channel.") { - SCM smob; struct message_data *msg_data = _scm_to_ssh_message (msg); - struct channel_data *channel_data - = (struct channel_data *) scm_gc_malloc (sizeof (struct channel_data), - "channel"); - channel_data->ssh_channel - = ssh_message_channel_request_open_reply_accept (msg_data->message); - if (channel_data->ssh_channel == NULL) - return SCM_BOOL_F; + ssh_channel *ch; - SCM_NEWSMOB (smob, channel_tag, channel_data); + ch = ssh_message_channel_request_open_reply_accept (msg_data->message); + if (! ch) + return SCM_BOOL_F; - return smob; + return _ssh_channel_to_scm (ch); } |
