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