From: simon Date: Sat, 29 Dec 2001 15:31:42 +0000 (+0000) Subject: Add a new back-end function to return the exit code of the remote X-Git-Url: https://git.distorted.org.uk/u/mdw/putty/commitdiff_plain/d8d6c7e50e1fcf5171ec15f8a3e9bdcd141f0b64 Add a new back-end function to return the exit code of the remote process. This is functional in SSH, and vestigial (just returns 0) in the other three protocols. Plink's Windows exit code is now determined by the remote process exit code, which should make it more usable in scripting applications. Tested in both SSH1 and SSH2. git-svn-id: svn://svn.tartarus.org/sgt/putty@1518 cda61777-01e9-0310-a592-d414129be87e --- diff --git a/plink.c b/plink.c index 6c211503..f8a9f7ce 100644 --- a/plink.c +++ b/plink.c @@ -444,6 +444,7 @@ int main(int argc, char **argv) SOCKET *sklist; int skcount, sksize; int connopen; + int exitcode; char extra_portfwd[sizeof(cfg.portfwd)]; ssh_get_line = get_line; @@ -967,5 +968,10 @@ int main(int argc, char **argv) break; /* we closed the connection */ } WSACleanup(); - return 0; + exitcode = back->exitcode(); + if (exitcode < 0) { + fprintf(stderr, "Remote process exit code unavailable\n"); + exitcode = 1; /* this is an error condition */ + } + return exitcode; } diff --git a/putty.h b/putty.h index 28639a9b..266d6ac4 100644 --- a/putty.h +++ b/putty.h @@ -214,6 +214,7 @@ typedef struct { void (*size) (void); void (*special) (Telnet_Special code); Socket(*socket) (void); + int (*exitcode) (void); int (*sendok) (void); int (*ldisc) (int); /* diff --git a/raw.c b/raw.c index e3fcbc00..0d27bb77 100644 --- a/raw.c +++ b/raw.c @@ -162,6 +162,12 @@ static int raw_ldisc(int option) return 0; } +static int raw_exitcode(void) +{ + /* Exit codes are a meaningless concept in the Raw protocol */ + return 0; +} + Backend raw_backend = { raw_init, raw_send, @@ -169,6 +175,7 @@ Backend raw_backend = { raw_size, raw_special, raw_socket, + raw_exitcode, raw_sendok, raw_ldisc, raw_unthrottle, diff --git a/rlogin.c b/rlogin.c index 97699aea..ba7dd37b 100644 --- a/rlogin.c +++ b/rlogin.c @@ -217,6 +217,12 @@ static int rlogin_ldisc(int option) return 0; } +static int rlogin_exitcode(void) +{ + /* If we ever implement RSH, we'll probably need to do this properly */ + return 0; +} + Backend rlogin_backend = { rlogin_init, rlogin_send, @@ -224,6 +230,7 @@ Backend rlogin_backend = { rlogin_size, rlogin_special, rlogin_socket, + rlogin_exitcode, rlogin_sendok, rlogin_ldisc, rlogin_unthrottle, diff --git a/ssh.c b/ssh.c index dcb791da..e0fed88b 100644 --- a/ssh.c +++ b/ssh.c @@ -499,6 +499,7 @@ static int ssh_echoing, ssh_editing; static tree234 *ssh_channels; /* indexed by local id */ static struct ssh_channel *mainchan; /* primary session channel */ +static int ssh_exitcode = -1; static tree234 *ssh_rportfwds; @@ -3110,6 +3111,11 @@ static void ssh1_protocol(unsigned char *in, int inlen, int ispkt) /* may be from EXEC_SHELL on some servers * if no pty is available or in other odd cases. Ignore */ } else if (pktin.type == SSH1_SMSG_EXIT_STATUS) { + char buf[100]; + ssh_exitcode = GET_32BIT(pktin.body); + sprintf(buf, "Server sent command exit status %d", + ssh_exitcode); + logevent(buf); send_packet(SSH1_CMSG_EXIT_CONFIRMATION, PKT_END); /* * In case `helpful' firewalls or proxies tack @@ -5061,14 +5067,35 @@ static void do_ssh2_authconn(unsigned char *in, int inlen, int ispkt) } /* - * We don't recognise any form of channel request, - * so we now either ignore the request or respond - * with CHANNEL_FAILURE, depending on want_reply. + * Having got the channel number, we now look at + * the request type string to see if it's something + * we recognise. */ - if (want_reply) { - ssh2_pkt_init(SSH2_MSG_CHANNEL_FAILURE); - ssh2_pkt_adduint32(c->remoteid); - ssh2_pkt_send(); + if (typelen == 11 && !memcmp(type, "exit-status", 11) && + c == mainchan) { + /* We recognise "exit-status" on the primary channel. */ + char buf[100]; + ssh_exitcode = ssh2_pkt_getuint32(); + sprintf(buf, "Server sent command exit status %d", + ssh_exitcode); + logevent(buf); + if (want_reply) { + ssh2_pkt_init(SSH2_MSG_CHANNEL_SUCCESS); + ssh2_pkt_adduint32(c->remoteid); + ssh2_pkt_send(); + } + } else { + /* + * This is a channel request we don't know + * about, so we now either ignore the request + * or respond with CHANNEL_FAILURE, depending + * on want_reply. + */ + if (want_reply) { + ssh2_pkt_init(SSH2_MSG_CHANNEL_FAILURE); + ssh2_pkt_adduint32(c->remoteid); + ssh2_pkt_send(); + } } } else if (pktin.type == SSH2_MSG_CHANNEL_OPEN) { char *type; @@ -5443,6 +5470,11 @@ static int ssh_ldisc(int option) return FALSE; } +static int ssh_return_exitcode(void) +{ + return ssh_exitcode; +} + Backend ssh_backend = { ssh_init, ssh_send, @@ -5450,6 +5482,7 @@ Backend ssh_backend = { ssh_size, ssh_special, ssh_socket, + ssh_return_exitcode, ssh_sendok, ssh_ldisc, ssh_unthrottle, diff --git a/telnet.c b/telnet.c index 5c5d2ce3..5e5fb247 100644 --- a/telnet.c +++ b/telnet.c @@ -848,6 +848,12 @@ static int telnet_ldisc(int option) return FALSE; } +static int telnet_exitcode(void) +{ + /* Telnet doesn't transmit exit codes back to the client */ + return 0; +} + Backend telnet_backend = { telnet_init, telnet_send, @@ -855,6 +861,7 @@ Backend telnet_backend = { telnet_size, telnet_special, telnet_socket, + telnet_exitcode, telnet_sendok, telnet_ldisc, telnet_unthrottle,