summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/api-channels.texi10
-rw-r--r--libguile-ssh/channel-func.c3
-rw-r--r--libguile-ssh/channel-type.c39
-rw-r--r--libguile-ssh/channel-type.h5
-rw-r--r--libguile-ssh/message-func.c3
-rw-r--r--modules/ssh/channel.scm11
6 files changed, 56 insertions, 15 deletions
diff --git a/doc/api-channels.texi b/doc/api-channels.texi
index 6123027..03c5b7b 100644
--- a/doc/api-channels.texi
+++ b/doc/api-channels.texi
@@ -33,9 +33,13 @@ Return @code{#t} if @var{x} is a Guile-SSH channel, @code{#f}
otherwise.
@end deffn
-@deffn {Scheme Procedure} make-channel session
-Allocate a new Guile-SSH channel for the @var{session}
-(@pxref{Sessions}).
+@deffn {Scheme Procedure} make-channel session [flags]
+Allocate a new Guile-SSH channel for the @var{session} (@pxref{Sessions}).
+
+@var{flags} are determine what kind of a channel should be created. Possible
+flags are: @code{O_RDONLY}, @code{O_WRONLY}, @code{O_RDWR}. They play similar
+role to @code{open} procedure flags, and allow to create an ihput channel,
+output channel or input/output channel respectively.
@end deffn
@deffn {Scheme Procedure} channel-open-session channel
diff --git a/libguile-ssh/channel-func.c b/libguile-ssh/channel-func.c
index eb2ca62..152b5cd 100644
--- a/libguile-ssh/channel-func.c
+++ b/libguile-ssh/channel-func.c
@@ -316,7 +316,8 @@ SCM_GSSH_DEFINE (guile_ssh_channel_accept_forward,
&port);
if (c_channel)
{
- channel = _scm_from_channel_data (c_channel, session);
+ channel = _scm_from_channel_data (c_channel, session,
+ SCM_RDNG | SCM_WRTNG);
SCM_SET_CELL_TYPE (channel, SCM_CELL_TYPE (channel) | SCM_OPN);
}
diff --git a/libguile-ssh/channel-type.c b/libguile-ssh/channel-type.c
index cd11b36..8e992ab 100644
--- a/libguile-ssh/channel-type.c
+++ b/libguile-ssh/channel-type.c
@@ -182,7 +182,14 @@ static int
print_channel (SCM channel, SCM port, scm_print_state *pstate)
{
struct channel_data *ch = _scm_to_channel_data (channel);
- scm_puts ("#<channel ", port);
+
+ if (SCM_INPUT_PORT_P (port) && SCM_OUTPUT_PORT_P (port))
+ scm_puts ("#<channel ", port);
+ else if (SCM_INPUT_PORT_P (port))
+ scm_puts ("#<input channel ", port);
+ else if (SCM_OUTPUT_PORT_P (port))
+ scm_puts ("#<output channel ", port);
+
if (! ch)
{
scm_puts ("(freed) ", port);
@@ -202,20 +209,26 @@ print_channel (SCM channel, SCM port, scm_print_state *pstate)
}
/* Allocate a new SSH channel. */
-SCM_DEFINE (guile_ssh_make_channel, "make-channel", 1, 0, 0,
- (SCM arg1),
+SCM_DEFINE (guile_ssh_make_channel, "%make-channel", 2, 0, 0,
+ (SCM arg1, SCM flags),
"\
Allocate a new SSH channel.\
")
+#define FUNC_NAME s_guile_ssh_make_channel
{
struct session_data *session_data = _scm_to_session_data (arg1);
- ssh_channel ch = ssh_channel_new (session_data->ssh_session);
+ ssh_channel ch;
+
+ SCM_ASSERT (scm_is_integer (flags), flags, SCM_ARG2, FUNC_NAME);
+
+ ch = ssh_channel_new (session_data->ssh_session);
if (! ch)
return SCM_BOOL_F;
- return _scm_from_channel_data (ch, arg1);
+ return _scm_from_channel_data (ch, arg1, scm_to_long (flags));
}
+#undef FUNC_NAME
/* Predicates */
@@ -247,9 +260,13 @@ equalp_channel (SCM x1, SCM x2)
/* Helper procedures */
/* Pack the SSH channel CH to a Scheme port and return newly created
- port. */
+ port.
+
+ Asserts:
+ - mode has only SCM_RDNG and SCM_WRTNG bits set.
+ */
SCM
-_scm_from_channel_data (ssh_channel ch, SCM session)
+_scm_from_channel_data (ssh_channel ch, SCM session, long flags)
{
struct channel_data *channel_data;
SCM ptob;
@@ -278,7 +295,10 @@ _scm_from_channel_data (ssh_channel ch, SCM session)
pt->read_pos = pt->read_buf;
pt->read_end = pt->read_buf;
- SCM_SET_CELL_TYPE (ptob, channel_tag | SCM_RDNG | SCM_WRTNG);
+ assert ((flags ^ (SCM_RDNG | SCM_WRTNG)) == 0);
+
+ SCM_SET_CELL_TYPE (ptob, channel_tag | flags);
+
SCM_SETSTREAM (ptob, channel_data);
return ptob;
@@ -311,6 +331,9 @@ init_channel_type (void)
scm_set_port_print (channel_tag, print_channel);
scm_set_port_equalp (channel_tag, equalp_channel);
+ scm_c_define ("RDNG", scm_from_int (SCM_RDNG));
+ scm_c_define ("WRTNG", scm_from_int (SCM_WRTNG));
+
#include "channel-type.x"
}
diff --git a/libguile-ssh/channel-type.h b/libguile-ssh/channel-type.h
index 1ac8a28..8810248 100644
--- a/libguile-ssh/channel-type.h
+++ b/libguile-ssh/channel-type.h
@@ -52,7 +52,7 @@ struct channel_data {
/* API */
-extern SCM guile_ssh_make_channel (SCM arg1);
+extern SCM guile_ssh_make_channel (SCM arg1, SCM flags);
extern SCM guile_ssh_is_channel_p (SCM arg1);
extern SCM guile_ssh_channel_get_session (SCM arg1);
@@ -61,6 +61,7 @@ extern void init_channel_type (void);
/* Helper procedures */
extern struct channel_data *_scm_to_channel_data (SCM x);
-extern SCM _scm_from_channel_data (ssh_channel ch, SCM session);
+extern SCM _scm_from_channel_data (ssh_channel ch, SCM session,
+ long flags);
#endif /* ifndef __CHANNEL_TYPE_H__ */
diff --git a/libguile-ssh/message-func.c b/libguile-ssh/message-func.c
index 428af34..aa7a8e2 100644
--- a/libguile-ssh/message-func.c
+++ b/libguile-ssh/message-func.c
@@ -138,7 +138,8 @@ Return a new SSH channel.\
if (! ch)
return SCM_BOOL_F;
- SCM channel = _scm_from_channel_data (ch, msg_data->session);
+ SCM channel = _scm_from_channel_data (ch, msg_data->session,
+ SCM_RDNG | SCM_WRTNG);
SCM_SET_CELL_TYPE (channel, SCM_CELL_TYPE (channel) | SCM_OPN);
diff --git a/modules/ssh/channel.scm b/modules/ssh/channel.scm
index eddb91b..7b3629e 100644
--- a/modules/ssh/channel.scm
+++ b/modules/ssh/channel.scm
@@ -72,6 +72,17 @@
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