1
0
mirror of https://github.com/libssh2/libssh2.git synced 2025-08-08 19:02:07 +03:00

'exit-status' information packet handling added

This commit is contained in:
Mikhail Gusarov
2005-06-23 05:55:01 +00:00
parent 0e5eb4d9c5
commit 77bd3c1215
4 changed files with 48 additions and 17 deletions

View File

@@ -323,7 +323,7 @@ LIBSSH2_API LIBSSH2_CHANNEL *libssh2_channel_open_ex(LIBSSH2_SESSION *session, c
#define libssh2_channel_open_session(session) libssh2_channel_open_ex((session), "session", sizeof("session") - 1, LIBSSH2_CHANNEL_WINDOW_DEFAULT, LIBSSH2_CHANNEL_PACKET_DEFAULT, NULL, 0) #define libssh2_channel_open_session(session) libssh2_channel_open_ex((session), "session", sizeof("session") - 1, LIBSSH2_CHANNEL_WINDOW_DEFAULT, LIBSSH2_CHANNEL_PACKET_DEFAULT, NULL, 0)
LIBSSH2_API LIBSSH2_CHANNEL *libssh2_channel_direct_tcpip_ex(LIBSSH2_SESSION *session, char *host, int port, char *shost, int sport); LIBSSH2_API LIBSSH2_CHANNEL *libssh2_channel_direct_tcpip_ex(LIBSSH2_SESSION *session, char *host, int port, char *shost, int sport);
#define libssh2_channel_direct_tcpip(session, host, port) libssh2_channel_direct_tcpip_ex((session), (host), (port), "127.0.0.1", 22) #define libssh2_channel_direct_tcpip(session, host, port) libssh2_channel_direct_tcpip_ex((session), (host), (port), "127.0.0.1", 22)
LIBSSH2_API LIBSSH2_LISTENER *libssh2_channel_forward_listen_ex(LIBSSH2_SESSION *session, char *host, int port, int *bound_port, int queue_maxsize); LIBSSH2_API LIBSSH2_LISTENER *libssh2_channel_forward_listen_ex(LIBSSH2_SESSION *session, char *host, int port, int *bound_port, int queue_maxsize);
#define libssh2_channel_forward_listen(session, port) libssh2_channel_forward_listen_ex((session), NULL, (port), NULL, 16) #define libssh2_channel_forward_listen(session, port) libssh2_channel_forward_listen_ex((session), NULL, (port), NULL, 16)
@@ -376,6 +376,7 @@ LIBSSH2_API void libssh2_channel_handle_extended_data(LIBSSH2_CHANNEL *channel,
LIBSSH2_API int libssh2_channel_flush_ex(LIBSSH2_CHANNEL *channel, int streamid); LIBSSH2_API int libssh2_channel_flush_ex(LIBSSH2_CHANNEL *channel, int streamid);
#define libssh2_channel_flush(channel) libssh2_channel_flush_ex((channel), 0) #define libssh2_channel_flush(channel) libssh2_channel_flush_ex((channel), 0)
#define libssh2_channel_flush_stderr(channel) libssh2_channel_flush_ex((channel), SSH_EXTENDED_DATA_STDERR) #define libssh2_channel_flush_stderr(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_send_eof(LIBSSH2_CHANNEL *channel); LIBSSH2_API int libssh2_channel_send_eof(LIBSSH2_CHANNEL *channel);
LIBSSH2_API int libssh2_channel_eof(LIBSSH2_CHANNEL *channel); LIBSSH2_API int libssh2_channel_eof(LIBSSH2_CHANNEL *channel);

View File

@@ -112,6 +112,9 @@ struct _LIBSSH2_CHANNEL {
int blocking; int blocking;
/* channel's program exit status */
int exit_status;
libssh2_channel_data local, remote; libssh2_channel_data local, remote;
unsigned long adjust_queue; /* Amount of bytes to be refunded to receive window (but not yet sent) */ unsigned long adjust_queue; /* Amount of bytes to be refunded to receive window (but not yet sent) */

View File

@@ -7,17 +7,17 @@
* *
* Redistributions of source code must retain the above * Redistributions of source code must retain the above
* copyright notice, this list of conditions and the * copyright notice, this list of conditions and the
* following disclaimer. * following disclaimer.
* *
* Redistributions in binary form must reproduce the above * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following * copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials * disclaimer in the documentation and/or other materials
* provided with the distribution. * provided with the distribution.
* *
* Neither the name of the copyright holder nor the names * Neither the name of the copyright holder nor the names
* of any other contributors may be used to endorse or * of any other contributors may be used to endorse or
* promote products derived from this software without * promote products derived from this software without
* specific prior written permission. * specific prior written permission.
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
@@ -99,7 +99,7 @@ LIBSSH2_CHANNEL *libssh2_channel_locate(LIBSSH2_SESSION *session, unsigned long
} \ } \
(channel)->next = NULL; \ (channel)->next = NULL; \
(session)->channels.tail = (channel); \ (session)->channels.tail = (channel); \
(channel)->session = (session); \ (channel)->session = (session); \
} }
/* {{{ libssh2_channel_open_session /* {{{ libssh2_channel_open_session
@@ -112,7 +112,7 @@ LIBSSH2_API LIBSSH2_CHANNEL *libssh2_channel_open_ex(LIBSSH2_SESSION *session, c
LIBSSH2_CHANNEL *channel = NULL; LIBSSH2_CHANNEL *channel = NULL;
unsigned long local_channel = libssh2_channel_nextid(session); unsigned long local_channel = libssh2_channel_nextid(session);
unsigned char *s, *packet = NULL; unsigned char *s, *packet = NULL;
unsigned long packet_len = channel_type_len + message_len + 17; /* packet_type(1) + channel_type_len(4) + sender_channel(4) + unsigned long packet_len = channel_type_len + message_len + 17; /* packet_type(1) + channel_type_len(4) + sender_channel(4) +
window_size(4) + packet_size(4) */ window_size(4) + packet_size(4) */
unsigned char *data = NULL; unsigned char *data = NULL;
unsigned long data_len; unsigned long data_len;
@@ -468,7 +468,7 @@ LIBSSH2_API int libssh2_channel_setenv_ex(LIBSSH2_CHANNEL *channel, char *varnam
LIBSSH2_SESSION *session = channel->session; LIBSSH2_SESSION *session = channel->session;
unsigned char *s, *packet, *data, reply_codes[3] = { SSH_MSG_CHANNEL_SUCCESS, SSH_MSG_CHANNEL_FAILURE, 0 }, local_channel[4]; unsigned char *s, *packet, *data, reply_codes[3] = { SSH_MSG_CHANNEL_SUCCESS, SSH_MSG_CHANNEL_FAILURE, 0 }, local_channel[4];
unsigned long data_len; unsigned long data_len;
unsigned long packet_len = varname_len + value_len + 21; /* packet_type(1) + channel_id(4) + request_len(4) + request(3)"env" + unsigned long packet_len = varname_len + value_len + 21; /* packet_type(1) + channel_id(4) + request_len(4) + request(3)"env" +
want_reply(1) + varname_len(4) + value_len(4) */ want_reply(1) + varname_len(4) + value_len(4) */
#ifdef LIBSSH2_DEBUG_CONNECTION #ifdef LIBSSH2_DEBUG_CONNECTION
@@ -528,7 +528,7 @@ LIBSSH2_API int libssh2_channel_request_pty_ex(LIBSSH2_CHANNEL *channel, char *t
LIBSSH2_SESSION *session = channel->session; LIBSSH2_SESSION *session = channel->session;
unsigned char *s, *packet, *data, reply_codes[3] = { SSH_MSG_CHANNEL_SUCCESS, SSH_MSG_CHANNEL_FAILURE, 0 }, local_channel[4]; unsigned char *s, *packet, *data, reply_codes[3] = { SSH_MSG_CHANNEL_SUCCESS, SSH_MSG_CHANNEL_FAILURE, 0 }, local_channel[4];
unsigned long data_len; unsigned long data_len;
unsigned long packet_len = term_len + modes_len + 41; /* packet_type(1) + channel(4) + pty_req_len(4) + "pty_req"(7) + want_reply(1) + unsigned long packet_len = term_len + modes_len + 41; /* packet_type(1) + channel(4) + pty_req_len(4) + "pty_req"(7) + want_reply(1) +
term_len(4) + width(4) + height(4) + width_px(4) + height_px(4) + modes_len(4) */ term_len(4) + width(4) + height(4) + width_px(4) + height_px(4) + modes_len(4) */
#ifdef LIBSSH2_DEBUG_CONNECTION #ifdef LIBSSH2_DEBUG_CONNECTION
@@ -598,7 +598,7 @@ LIBSSH2_API int libssh2_channel_x11_req_ex(LIBSSH2_CHANNEL *channel, int single_
unsigned long data_len; unsigned long data_len;
unsigned long proto_len = auth_proto ? strlen(auth_proto) : (sizeof("MIT-MAGIC-COOKIE-1") - 1); unsigned long proto_len = auth_proto ? strlen(auth_proto) : (sizeof("MIT-MAGIC-COOKIE-1") - 1);
unsigned long cookie_len = auth_cookie ? strlen(auth_cookie) : LIBSSH2_X11_RANDOM_COOKIE_LEN; unsigned long cookie_len = auth_cookie ? strlen(auth_cookie) : LIBSSH2_X11_RANDOM_COOKIE_LEN;
unsigned long packet_len = proto_len + cookie_len + 41; /* packet_type(1) + channel(4) + x11_req_len(4) + "x11-req"(7) + want_reply(1) + unsigned long packet_len = proto_len + cookie_len + 41; /* packet_type(1) + channel(4) + x11_req_len(4) + "x11-req"(7) + want_reply(1) +
single_cnx(4) + proto_len(4) + cookie_len(4) + screen_num(4) */ single_cnx(4) + proto_len(4) + cookie_len(4) + screen_num(4) */
#ifdef LIBSSH2_DEBUG_CONNECTION #ifdef LIBSSH2_DEBUG_CONNECTION
@@ -787,6 +787,16 @@ LIBSSH2_API int libssh2_channel_flush_ex(LIBSSH2_CHANNEL *channel, int streamid)
} }
/* }}} */ /* }}} */
/* {{{ libssh2_channel_get_exit_status
* Return the channel's program exit status
*/
LIBSSH2_API int libssh2_channel_get_exit_status(LIBSSH2_CHANNEL* channel)
{
return channel->exit_status;
}
/* }}} */
/* {{{ libssh2_channel_receive_window_adjust /* {{{ libssh2_channel_receive_window_adjust
* Adjust the receive window for a channel by adjustment bytes * Adjust the receive window for a channel by adjustment bytes
* If the amount to be adjusted is less than LIBSSH2_CHANNEL_MINADJUST and force is 0 * If the amount to be adjusted is less than LIBSSH2_CHANNEL_MINADJUST and force is 0
@@ -1057,7 +1067,7 @@ LIBSSH2_API int libssh2_channel_eof(LIBSSH2_CHANNEL *channel)
LIBSSH2_PACKET *packet = session->packets.head; LIBSSH2_PACKET *packet = session->packets.head;
while (packet) { while (packet) {
if (((packet->data[0] == SSH_MSG_CHANNEL_DATA) || (packet->data[0] == SSH_MSG_CHANNEL_EXTENDED_DATA)) && if (((packet->data[0] == SSH_MSG_CHANNEL_DATA) || (packet->data[0] == SSH_MSG_CHANNEL_EXTENDED_DATA)) &&
(channel->local.id == libssh2_ntohu32(packet->data + 1))) { (channel->local.id == libssh2_ntohu32(packet->data + 1))) {
/* There's data waiting to be read yet, mask the EOF status */ /* There's data waiting to be read yet, mask the EOF status */
return 0; return 0;
@@ -1122,7 +1132,7 @@ LIBSSH2_API int libssh2_channel_free(LIBSSH2_CHANNEL *channel)
return -1; return -1;
} }
/* channel->remote.close *might* not be set yet, Well... /* channel->remote.close *might* not be set yet, Well...
* We've sent the close packet, what more do you want? * We've sent the close packet, what more do you want?
* Just let packet_add ignore it when it finally arrives * Just let packet_add ignore it when it finally arrives
*/ */

View File

@@ -156,7 +156,7 @@ inline int libssh2_packet_queue_listener(LIBSSH2_SESSION *session, unsigned char
if (libssh2_packet_write(session, packet, 17)) { if (libssh2_packet_write(session, packet, 17)) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, "Unable to send channel open confirmation", 0); libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, "Unable to send channel open confirmation", 0);
return -1; return -1;
} }
/* Link the channel into the end of the queue list */ /* Link the channel into the end of the queue list */
@@ -269,7 +269,7 @@ inline int libssh2_packet_x11_open(LIBSSH2_SESSION *session, unsigned char *data
if (libssh2_packet_write(session, packet, 17)) { if (libssh2_packet_write(session, packet, 17)) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, "Unable to send channel open confirmation", 0); libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, "Unable to send channel open confirmation", 0);
return -1; return -1;
} }
/* Link the channel into the session */ /* Link the channel into the session */
@@ -497,6 +497,23 @@ static int libssh2_packet_add(LIBSSH2_SESSION *session, unsigned char *data, siz
return 0; return 0;
} }
break; break;
case SSH_MSG_CHANNEL_REQUEST:
{
if (libssh2_ntohu32(data+5) == sizeof("exit-status") - 1
&& !memcmp("exit-status", data + 9, sizeof("exit-status") - 1)) {
/* we've got "exit-status" packet. Set the session value */
LIBSSH2_CHANNEL *channel = libssh2_channel_locate(session, libssh2_ntohu32(data+1));
if (channel) {
#ifdef LIBSSH2_DEBUG_CONNECTION
_libssh2_debug(session, LIBSSH2_DBG_CONN, "Exit status received for channel %lu/%lu", channel->local.id, channel->remote.id);
#endif
channel->exit_status = libssh2_ntohu32(data + 9 + sizeof("exit-status"));
}
}
}
break;
case SSH_MSG_CHANNEL_CLOSE: case SSH_MSG_CHANNEL_CLOSE:
{ {
LIBSSH2_CHANNEL *channel = libssh2_channel_locate(session, libssh2_ntohu32(data + 1)); LIBSSH2_CHANNEL *channel = libssh2_channel_locate(session, libssh2_ntohu32(data + 1));
@@ -900,7 +917,7 @@ int libssh2_packet_read(LIBSSH2_SESSION *session, int should_block)
/* {{{ libssh2_packet_ask /* {{{ libssh2_packet_ask
* Scan the brigade for a matching packet type, optionally poll the socket for a packet first * Scan the brigade for a matching packet type, optionally poll the socket for a packet first
*/ */
int libssh2_packet_ask_ex(LIBSSH2_SESSION *session, unsigned char packet_type, unsigned char **data, unsigned long *data_len, int libssh2_packet_ask_ex(LIBSSH2_SESSION *session, unsigned char packet_type, unsigned char **data, unsigned long *data_len,
unsigned long match_ofs, const unsigned char *match_buf, unsigned long match_len, int poll_socket) unsigned long match_ofs, const unsigned char *match_buf, unsigned long match_len, int poll_socket)
{ {
LIBSSH2_PACKET *packet = session->packets.head; LIBSSH2_PACKET *packet = session->packets.head;
@@ -945,7 +962,7 @@ int libssh2_packet_ask_ex(LIBSSH2_SESSION *session, unsigned char packet_type, u
/* {{{ libssh2_packet_askv /* {{{ libssh2_packet_askv
* Scan for any of a list of packet types in the brigade, optionally poll the socket for a packet first * Scan for any of a list of packet types in the brigade, optionally poll the socket for a packet first
*/ */
int libssh2_packet_askv_ex(LIBSSH2_SESSION *session, unsigned char *packet_types, unsigned char **data, unsigned long *data_len, int libssh2_packet_askv_ex(LIBSSH2_SESSION *session, unsigned char *packet_types, unsigned char **data, unsigned long *data_len,
unsigned long match_ofs, const unsigned char *match_buf, unsigned long match_len, int poll_socket) unsigned long match_ofs, const unsigned char *match_buf, unsigned long match_len, int poll_socket)
{ {
int i, packet_types_len = strlen(packet_types); int i, packet_types_len = strlen(packet_types);