'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)
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);
#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);
#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)
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_eof(LIBSSH2_CHANNEL *channel);

View File

@ -112,6 +112,9 @@ struct _LIBSSH2_CHANNEL {
int blocking;
/* channel's program exit status */
int exit_status;
libssh2_channel_data local, remote;
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
* copyright notice, this list of conditions and the
* following disclaimer.
* following disclaimer.
*
* Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* 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
* of any other contributors may be used to endorse or
* promote products derived from this software without
* specific prior written permission.
* of any other contributors may be used to endorse or
* promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* 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; \
(session)->channels.tail = (channel); \
(channel)->session = (session); \
(channel)->session = (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;
unsigned long local_channel = libssh2_channel_nextid(session);
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) */
unsigned char *data = NULL;
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;
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 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) */
#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;
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 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) */
#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 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 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) */
#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
* 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
@ -1057,7 +1067,7 @@ LIBSSH2_API int libssh2_channel_eof(LIBSSH2_CHANNEL *channel)
LIBSSH2_PACKET *packet = session->packets.head;
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))) {
/* There's data waiting to be read yet, mask the EOF status */
return 0;
@ -1122,7 +1132,7 @@ LIBSSH2_API int libssh2_channel_free(LIBSSH2_CHANNEL *channel)
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?
* 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)) {
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 */
@ -269,7 +269,7 @@ inline int libssh2_packet_x11_open(LIBSSH2_SESSION *session, unsigned char *data
if (libssh2_packet_write(session, packet, 17)) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, "Unable to send channel open confirmation", 0);
return -1;
return -1;
}
/* Link the channel into the session */
@ -497,6 +497,23 @@ static int libssh2_packet_add(LIBSSH2_SESSION *session, unsigned char *data, siz
return 0;
}
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:
{
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
* 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)
{
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
* 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)
{
int i, packet_types_len = strlen(packet_types);