aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorKevin Lange <k@dakko.us>2011-12-04 03:43:33 -0600
committerKevin Lange <k@dakko.us>2011-12-04 03:43:33 -0600
commitf18f1e401a8190d29a3ba2fdc8dcbb9170de2c78 (patch)
tree9f3769c4c89bd4a38998f778f34e8fbbaa001609 /src
parentf841e5fe165614e6f5eefb51fd1605aa55ad1c04 (diff)
downloadnyancat-f18f1e401a8190d29a3ba2fdc8dcbb9170de2c78.tar.gz
Use setjmp and alarm to break out of options handling
Diffstat (limited to 'src')
-rw-r--r--src/nyancat.c154
1 files 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 <unistd.h>
#include <signal.h>
#include <time.h>
+#include <setjmp.h>
#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;
}
}
}