From f18f1e401a8190d29a3ba2fdc8dcbb9170de2c78 Mon Sep 17 00:00:00 2001 From: Kevin Lange Date: Sun, 4 Dec 2011 03:43:33 -0600 Subject: Use setjmp and alarm to break out of options handling --- src/nyancat.c | 154 ++++++++++++++++++++++++++++++++-------------------------- 1 file changed, 86 insertions(+), 68 deletions(-) diff --git a/src/nyancat.c b/src/nyancat.c index 21abfa8..5f5939f 100644 --- a/src/nyancat.c +++ b/src/nyancat.c @@ -46,6 +46,7 @@ #include #include #include +#include #include "telnet.h" /* The animation frames are stored separately. */ @@ -89,6 +90,18 @@ void SIGINT_handler(int sig){ exit(0); } +jmp_buf environment; + +/* + * Handle the alarm which breaks us off of options + * handling if we didn't receive a terminal + */ +void SIGALRM_handler(int sig) { + alarm(0); + longjmp(environment, 1); + /* Unreachable */ +} + void newline(int n) { int i = 0; for (i = 0; i < n; ++i) { @@ -200,77 +213,82 @@ int main(int argc, char ** argv) { } } + signal(SIGALRM, SIGALRM_handler); /* Negotiate options */ - while (!feof(stdin) && !done) { - unsigned char i = getchar(); - unsigned char opt = 0; - if (i == IAC) { - i = getchar(); - switch (i) { - case SE: - /* End of extended option mode */ - sb_mode = 0; - if (sb[0] == TTYPE) { - strcpy(term, &sb[2]); - goto ready; - } - break; - case NOP: - /* No Op */ - send_command(NOP, 0); - fflush(stdout); - break; - case WILL: - case WONT: - /* Will / Won't Negotiation */ - opt = getchar(); - if (!telnet_willack[opt]) { - telnet_willack[opt] = WONT; - } - send_command(telnet_willack[opt], opt); - fflush(stdout); - if ((i == WILL) && (opt == TTYPE)) { - /* WILL TTYPE? Great, let's do that now! */ - printf("%c%c%c%c%c%c", IAC, SB, TTYPE, SEND, IAC, SE); + if (!setjmp(environment)) { + alarm(1); + while (!feof(stdin) && !done) { + unsigned char i = getchar(); + unsigned char opt = 0; + if (i == IAC) { + i = getchar(); + switch (i) { + case SE: + /* End of extended option mode */ + sb_mode = 0; + if (sb[0] == TTYPE) { + alarm(0); + strcpy(term, &sb[2]); + goto ready; + } + break; + case NOP: + /* No Op */ + send_command(NOP, 0); fflush(stdout); - } - break; - case DO: - case DONT: - /* Do / Don't Negotation */ - opt = getchar(); - if (!telnet_options[opt]) { - telnet_options[opt] = DONT; - } - send_command(telnet_options[opt], opt); - if (opt == ECHO) { - /* We don't really need this, as we don't accept input, but, - * in case we do in the future, set our echo mode */ - do_echo = (i == DO); - } - fflush(stdout); - break; - case SB: - /* Begin Extended Option Mode */ - sb_mode = 1; - sb_len = 0; - memset(sb, 0, 1024); - break; - case IAC: - /* Connection Closed During Negotiation */ - done = 1; - break; - default: - break; - } - } else if (sb_mode) { - /* Extended Option Mode -> Accept character */ - if (sb_len < 1023) { - sb[sb_len] = i; - sb_len++; + break; + case WILL: + case WONT: + /* Will / Won't Negotiation */ + opt = getchar(); + if (!telnet_willack[opt]) { + telnet_willack[opt] = WONT; + } + send_command(telnet_willack[opt], opt); + fflush(stdout); + if ((i == WILL) && (opt == TTYPE)) { + /* WILL TTYPE? Great, let's do that now! */ + printf("%c%c%c%c%c%c", IAC, SB, TTYPE, SEND, IAC, SE); + fflush(stdout); + } + break; + case DO: + case DONT: + /* Do / Don't Negotation */ + opt = getchar(); + if (!telnet_options[opt]) { + telnet_options[opt] = DONT; + } + send_command(telnet_options[opt], opt); + if (opt == ECHO) { + /* We don't really need this, as we don't accept input, but, + * in case we do in the future, set our echo mode */ + do_echo = (i == DO); + } + fflush(stdout); + break; + case SB: + /* Begin Extended Option Mode */ + sb_mode = 1; + sb_len = 0; + memset(sb, 0, 1024); + break; + case IAC: + /* Connection Closed During Negotiation */ + done = 1; + break; + default: + break; + } + } else if (sb_mode) { + /* Extended Option Mode -> Accept character */ + if (sb_len < 1023) { + sb[sb_len] = i; + sb_len++; + } + } else { + goto ready; } - } else { - goto ready; } } } -- cgit v1.2.3