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;