On 2010-10-05 12:02, Simon Josefsson wrote:
Tommy Lindgren<tommy.lindg...@gmail.com> writes:
The function is always returning LIBSSH2_ERROR_NONE. I'm not sure if
it should returning anything else? (Perhaps if the malloc fails? Other
API functions don't seem to do this though.)
It needs to handle memory allocation errors and return
LIBSSH2_ERROR_ALLOC when it happens.
OK. Updated patch attached.
Regards,
Tommy
diff --git a/docs/Makefile.am b/docs/Makefile.am
index 9f905d8..0207a65 100644
--- a/docs/Makefile.am
+++ b/docs/Makefile.am
@@ -26,6 +26,7 @@ dist_man_MANS = \
libssh2_channel_forward_listen_ex.3 \
libssh2_channel_free.3 \
libssh2_channel_get_exit_status.3 \
+ libssh2_channel_get_exit_signal.3 \
libssh2_channel_handle_extended_data.3 \
libssh2_channel_handle_extended_data2.3 \
libssh2_channel_ignore_extended_data.3 \
diff --git a/docs/libssh2_channel_get_exit_signal.3 b/docs/libssh2_channel_get_exit_signal.3
new file mode 100644
index 0000000..3a18653
--- /dev/null
+++ b/docs/libssh2_channel_get_exit_signal.3
@@ -0,0 +1,36 @@
+.\" $Id$
+.\"
+.TH libssh2_channel_get_exit_signal 3 "4 Oct 2010" "libssh2 1.2.8" "libssh2 manual"
+.SH NAME
+libssh2_channel_get_exit_signal - get the remote exit signal
+.SH SYNOPSIS
+#include <libssh2.h>
+
+int
+libssh2_channel_get_exit_signal(LIBSSH2_CHANNEL *channel, char **exitsignal, size_t *exitsignal_len, char **errmsg, size_t *errmsg_len, char **langtag, size_t *langtag_len);
+
+.SH DESCRIPTION
+\fIchannel\fP - Closed channel stream to retrieve exit signal from.
+
+\fIexitsignal\fP - If not NULL, is populated by reference with the exit signal
+(without leading "SIG"). Note that the string is stored in a newly allocated
+buffer. If the remote program exited cleanly, the referenced string pointer
+will be set to NULL.
+
+\fIexitsignal_len\fP - If not NULL, is populated by reference with the length
+of exitsignal.
+
+\fIerrmsg\fP - If not NULL, is populated by reference with the error message
+(if provided by remote server, if not it will be set to NULL). Note that the
+string is stored in a newly allocated buffer.
+
+\fIerrmsg_len\fP - If not NULL, is populated by reference with the length of errmsg.
+
+\fIlangtag\fP - If not NULL, is populated by reference with the language tag
+(if provided by remote server, if not it will be set to NULL). Note that the
+string is stored in a newly allocated buffer.
+
+\fIlangtag_len\fP - If not NULL, is populated by reference with the length of langtag.
+
+.SH RETURN VALUE
+Numeric error code corresponding to the the Error Code constants.
diff --git a/example/ssh2_exec.c b/example/ssh2_exec.c
index 1b74abc..90d81c5 100644
--- a/example/ssh2_exec.c
+++ b/example/ssh2_exec.c
@@ -86,6 +86,7 @@ int main(int argc, char *argv[])
LIBSSH2_CHANNEL *channel;
int rc;
int exitcode;
+ char *exitsignal;
int bytecount = 0;
size_t len;
LIBSSH2_KNOWNHOSTS *nh;
@@ -286,8 +287,13 @@ int main(int argc, char *argv[])
if( rc == 0 )
{
exitcode = libssh2_channel_get_exit_status( channel );
+ libssh2_channel_get_exit_signal(channel, &exitsignal, NULL, NULL, NULL, NULL, NULL);
}
- printf("\nEXIT: %d bytecount: %d\n", exitcode, bytecount);
+
+ if (exitsignal)
+ printf("\nGot signal: %s\n", exitsignal);
+ else
+ printf("\nEXIT: %d bytecount: %d\n", exitcode, bytecount);
libssh2_channel_free(channel);
channel = NULL;
diff --git a/include/libssh2.h b/include/libssh2.h
index df065a0..fd2b8bf 100644
--- a/include/libssh2.h
+++ b/include/libssh2.h
@@ -701,6 +701,13 @@ LIBSSH2_API int libssh2_channel_flush_ex(LIBSSH2_CHANNEL *channel,
libssh2_channel_flush_ex((channel), SSH_EXTENDED_DATA_STDERR)
LIBSSH2_API int libssh2_channel_get_exit_status(LIBSSH2_CHANNEL* channel);
+LIBSSH2_API int libssh2_channel_get_exit_signal(LIBSSH2_CHANNEL* channel,
+ char **exitsignal,
+ size_t *exitsignal_len,
+ char **errmsg,
+ size_t *errmsg_len,
+ char **langtag,
+ size_t *langtag_len);
LIBSSH2_API int libssh2_channel_send_eof(LIBSSH2_CHANNEL *channel);
LIBSSH2_API int libssh2_channel_eof(LIBSSH2_CHANNEL *channel);
LIBSSH2_API int libssh2_channel_wait_eof(LIBSSH2_CHANNEL *channel);
diff --git a/src/channel.c b/src/channel.c
index 2698777..c88de48 100644
--- a/src/channel.c
+++ b/src/channel.c
@@ -1459,6 +1459,67 @@ libssh2_channel_get_exit_status(LIBSSH2_CHANNEL *channel)
return channel->exit_status;
}
+/*
+ * libssh2_channel_get_exit_signal
+ *
+ * Get exit signal (without leading "SIG"), error message, and language
+ * tag into newly allocated buffers of indicated length. Caller can
+ * use NULL pointers to indicate that the value should not be set. The
+ * *_len variables are set if they are non-NULL even if the
+ * corresponding string parameter is NULL. Returns LIBSSH2_ERROR_NONE
+ * on success, or an API error code.
+ */
+LIBSSH2_API int
+libssh2_channel_get_exit_signal(LIBSSH2_CHANNEL *channel,
+ char **exitsignal,
+ size_t *exitsignal_len,
+ char **errmsg,
+ size_t *errmsg_len,
+ char **langtag,
+ size_t *langtag_len)
+{
+ LIBSSH2_SESSION *session = channel->session;
+ size_t namelen = 0;
+
+ if (channel) {
+ if (channel->exit_signal) {
+ namelen = strlen(channel->exit_signal);
+ if (exitsignal) {
+ *exitsignal = LIBSSH2_ALLOC(session, namelen + 1);
+ if (!*exitsignal) {
+ return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+ "Unable to allocate memory for signal name");
+ }
+ memcpy(*exitsignal, channel->exit_signal, namelen);
+ (*exitsignal)[namelen] = '\0';
+ }
+ if (exitsignal_len)
+ *exitsignal_len = namelen;
+ } else {
+ if (exitsignal)
+ *exitsignal = NULL;
+ if (exitsignal_len)
+ *exitsignal_len = 0;
+ }
+
+ /* TODO: set error message and language tag */
+
+ if (errmsg)
+ *errmsg = NULL;
+
+ if (errmsg_len)
+ *errmsg_len = 0;
+
+ if (langtag)
+ *langtag = NULL;
+
+ if (langtag_len)
+ *langtag_len = 0;
+ }
+
+ return LIBSSH2_ERROR_NONE;
+}
+
/*
* _libssh2_channel_receive_window_adjust
*
@@ -2394,6 +2455,10 @@ int _libssh2_channel_free(LIBSSH2_CHANNEL *channel)
channel->free_state = libssh2_NB_state_idle;
+ if (channel->exit_signal) {
+ LIBSSH2_FREE(session, channel->exit_signal);
+ }
+
/*
* channel->remote.close *might* not be set yet, Well...
* We've sent the close packet, what more do you want?
diff --git a/src/libssh2_priv.h b/src/libssh2_priv.h
index 037e781..a7aba9f 100644
--- a/src/libssh2_priv.h
+++ b/src/libssh2_priv.h
@@ -347,6 +347,9 @@ struct _LIBSSH2_CHANNEL
/* channel's program exit status */
int exit_status;
+ /* channel's program exit signal (without the SIG prefix) */
+ char *exit_signal;
+
libssh2_channel_data local, remote;
/* Amount of bytes to be refunded to receive window (but not yet sent) */
unsigned long adjust_queue;
diff --git a/src/packet.c b/src/packet.c
index 8315f9c..bcf84bb 100644
--- a/src/packet.c
+++ b/src/packet.c
@@ -762,6 +762,40 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
return 0;
}
+ if (strlen == sizeof("exit-signal") - 1
+ && !memcmp("exit-signal", data + 9,
+ sizeof("exit-signal") - 1)) {
+
+ /* command terminated due to signal */
+ session->packAdd_channel =
+ _libssh2_channel_locate(session, channel);
+
+ if (session->packAdd_channel) {
+ /* set signal name (without SIG prefix) */
+ uint32_t namelen = _libssh2_ntohu32(data + 9 + sizeof("exit-signal"));
+ session->packAdd_channel->exit_signal =
+ LIBSSH2_ALLOC(session, namelen + 1);
+ if (!session->packAdd_channel->exit_signal) {
+ _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
+ "Unable to allocate memory for signal name");
+ } else {
+ memcpy(session->packAdd_channel->exit_signal,
+ data + 13 + sizeof("exit_signal"), namelen);
+ session->packAdd_channel->exit_signal[namelen] = '\0';
+ /* TODO: save error message and language tag */
+ _libssh2_debug(session, LIBSSH2_TRACE_CONN,
+ "Exit signal %s received for channel %lu/%lu",
+ session->packAdd_channel->exit_signal,
+ session->packAdd_channel->local.id,
+ session->packAdd_channel->remote.id);
+ }
+ }
+
+ LIBSSH2_FREE(session, data);
+ session->packAdd_state = libssh2_NB_state_idle;
+ return 0;
+ }
+
if (want_reply) {
libssh2_packet_add_jump_point4:
session->packAdd_state = libssh2_NB_state_jump4;
_______________________________________________
libssh2-devel http://cool.haxx.se/cgi-bin/mailman/listinfo/libssh2-devel