Use setjmp and alarm to break out of options handling

This commit is contained in:
Kevin Lange 2011-12-04 03:43:33 -06:00
parent f841e5fe16
commit f18f1e401a
1 changed files with 86 additions and 68 deletions

View File

@ -46,6 +46,7 @@
#include <unistd.h> #include <unistd.h>
#include <signal.h> #include <signal.h>
#include <time.h> #include <time.h>
#include <setjmp.h>
#include "telnet.h" #include "telnet.h"
/* The animation frames are stored separately. */ /* The animation frames are stored separately. */
@ -89,6 +90,18 @@ void SIGINT_handler(int sig){
exit(0); 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) { void newline(int n) {
int i = 0; int i = 0;
for (i = 0; i < n; ++i) { for (i = 0; i < n; ++i) {
@ -200,77 +213,82 @@ int main(int argc, char ** argv) {
} }
} }
signal(SIGALRM, SIGALRM_handler);
/* Negotiate options */ /* Negotiate options */
while (!feof(stdin) && !done) { if (!setjmp(environment)) {
unsigned char i = getchar(); alarm(1);
unsigned char opt = 0; while (!feof(stdin) && !done) {
if (i == IAC) { unsigned char i = getchar();
i = getchar(); unsigned char opt = 0;
switch (i) { if (i == IAC) {
case SE: i = getchar();
/* End of extended option mode */ switch (i) {
sb_mode = 0; case SE:
if (sb[0] == TTYPE) { /* End of extended option mode */
strcpy(term, &sb[2]); sb_mode = 0;
goto ready; if (sb[0] == TTYPE) {
} alarm(0);
break; strcpy(term, &sb[2]);
case NOP: goto ready;
/* No Op */ }
send_command(NOP, 0); break;
fflush(stdout); case NOP:
break; /* No Op */
case WILL: send_command(NOP, 0);
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); fflush(stdout);
} break;
break; case WILL:
case DO: case WONT:
case DONT: /* Will / Won't Negotiation */
/* Do / Don't Negotation */ opt = getchar();
opt = getchar(); if (!telnet_willack[opt]) {
if (!telnet_options[opt]) { telnet_willack[opt] = WONT;
telnet_options[opt] = DONT; }
} send_command(telnet_willack[opt], opt);
send_command(telnet_options[opt], opt); fflush(stdout);
if (opt == ECHO) { if ((i == WILL) && (opt == TTYPE)) {
/* We don't really need this, as we don't accept input, but, /* WILL TTYPE? Great, let's do that now! */
* in case we do in the future, set our echo mode */ printf("%c%c%c%c%c%c", IAC, SB, TTYPE, SEND, IAC, SE);
do_echo = (i == DO); fflush(stdout);
} }
fflush(stdout); break;
break; case DO:
case SB: case DONT:
/* Begin Extended Option Mode */ /* Do / Don't Negotation */
sb_mode = 1; opt = getchar();
sb_len = 0; if (!telnet_options[opt]) {
memset(sb, 0, 1024); telnet_options[opt] = DONT;
break; }
case IAC: send_command(telnet_options[opt], opt);
/* Connection Closed During Negotiation */ if (opt == ECHO) {
done = 1; /* We don't really need this, as we don't accept input, but,
break; * in case we do in the future, set our echo mode */
default: do_echo = (i == DO);
break; }
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 if (sb_mode) {
/* Extended Option Mode -> Accept character */
if (sb_len < 1023) {
sb[sb_len] = i;
sb_len++;
}
} else {
goto ready;
} }
} }
} }