Simon Josefsson <si...@josefsson.org> writes:

> Tommy Lindgren <tommy.lindg...@gmail.com> writes:
>
>> On 2010-10-01 16:29, Simon Josefsson wrote:
>>> Tommy Lindgren<tommy.lindg...@gmail.com>  writes:
>>>
>>>> Hi,
>>>>
>>>> I've implemented rudimentary support for exit-signal messages (see RFC
>>>> 4254 section 6.10) which I'd like to see included in libssh2, please
>>>> see attached patch. The patch only adds support for retrieving the
>>>> signal name, I skipped the part about the (optional) error message.
>>>
>>> It looks good to me, thanks for this!  However a question: why skip the
>>> error message part?
>>
>> Simply because the error message didn't seem to get set in my test
>> cases, so I didn't bother to write code for it.
>
> I think it would be an improvement if the API was modified to make it
> possible for a future libssh2 to supply the error message to the
> application, when someone improves the protocol parser.

Any opinion on how that modification should look? Personally I think it
looks nicer with a separate function for retrieving the error message
(and language tag). But if we are extending the new function I guess the
signature could look something like

LIBSSH2_API const char *
libssh2_channel_get_exit_signal(LIBSSH2_CHANNEL *channel, char *errmsg,
                                char **langtag)

or possibly 

LIBSSH2_API const char *
libssh2_channel_get_exit_signal(LIBSSH2_CHANNEL *channel, char *errmsg,
                                int *errmsg_len, char **langtag, int 
*langtag_len)

Thoughts?

> Btw, shouldn't the return value of the API use a 'const' qualifier?  The
> string should not be modifiable by the application.

True, fixed. I'm not really a C coder, I just pretend to be one.

Attached new patch with const fix and modified ssh2_exec.c example. The
patch can be tested with:

$ example/ssh2_exec host user pass "kill -TERM \$\$"

Regards,
Tommy

diff --git a/example/ssh2_exec.c b/example/ssh2_exec.c
index 1b74abc..20afded 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;
+    const char *exitsignal;
     int bytecount = 0;
     size_t len;
     LIBSSH2_KNOWNHOSTS *nh;
@@ -286,8 +287,9 @@ int main(int argc, char *argv[])
     if( rc == 0 )
     {
         exitcode = libssh2_channel_get_exit_status( channel );
+        exitsignal = libssh2_channel_get_exit_signal( channel );
     }
-    printf("\nEXIT: %d bytecount: %d\n", exitcode, bytecount);
+    printf("\nEXIT: %d signal: %s bytecount: %d\n", exitcode, exitsignal, bytecount);
 
     libssh2_channel_free(channel);
     channel = NULL;
diff --git a/src/channel.c b/src/channel.c
index 2698777..164826b 100644
--- a/src/channel.c
+++ b/src/channel.c
@@ -1460,6 +1460,22 @@ libssh2_channel_get_exit_status(LIBSSH2_CHANNEL *channel)
 }
 
 /*
+ * libssh2_channel_get_exit_signal
+ *
+ * Return the channel's program exit signal (without the SIG prefix). NULL
+ * if the program exited cleanly.
+ *
+ */
+LIBSSH2_API const char *
+libssh2_channel_get_exit_signal(LIBSSH2_CHANNEL *channel)
+{
+    if(!channel)
+        return NULL;
+
+    return channel->exit_signal;
+}
+
+/*
  * _libssh2_channel_receive_window_adjust
  *
  * Adjust the receive window for a channel by adjustment bytes. If the amount
@@ -2394,6 +2410,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..ca04d63 100644
--- a/src/packet.c
+++ b/src/packet.c
@@ -762,6 +762,34 @@ _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);
+                    memcpy(session->packAdd_channel->exit_signal,
+                        data + 13 + sizeof("exit_signal"), namelen);
+                    session->packAdd_channel->exit_signal[namelen] = '\0';
+                    _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

Reply via email to