void printoption(const char *direction, int cmd, int option) { if (!showoptions) return; if (cmd == IAC) { if (TELCMD_OK(option)) fprintf(NetTrace, "%s IAC %s", direction, TELCMD(option)); else fprintf(NetTrace, "%s IAC %d", direction, option); } else { const char *fmt; fmt = (cmd == WILL) ? "WILL" : (cmd == WONT) ? "WONT" : (cmd == DO) ? "DO" : (cmd == DONT) ? "DONT" : 0; if (fmt) { fprintf(NetTrace, "%s %s ", direction, fmt); if (TELOPT_OK(option)) fprintf(NetTrace, "%s", TELOPT(option)); else if (option == TELOPT_EXOPL) fprintf(NetTrace, "EXOPL"); else fprintf(NetTrace, "%d", option); } else fprintf(NetTrace, "%s %d %d", direction, cmd, option); } if (NetTrace == stdout) { fprintf(NetTrace, "\r\n"); fflush(NetTrace); } else { fprintf(NetTrace, "\n"); } return; }
/* int length; length of suboption data */ void printsub (char direction, unsigned char *pointer, int length) { register int i; extern int want_status_response; #if defined AUTHENTICATION || defined ENCRYPTION char buf[512]; #endif if (showoptions || direction == 0 || (want_status_response && (pointer[0] == TELOPT_STATUS))) { if (direction) { fprintf (NetTrace, "%s IAC SB ", (direction == '<') ? "RCVD" : "SENT"); if (length >= 3) { register int j; i = pointer[length - 2]; j = pointer[length - 1]; if (i != IAC || j != SE) { fprintf (NetTrace, "(terminated by "); if (TELOPT_OK (i)) fprintf (NetTrace, "%s ", TELOPT (i)); else if (TELCMD_OK (i)) fprintf (NetTrace, "%s ", TELCMD (i)); else fprintf (NetTrace, "%d ", i); if (TELOPT_OK (j)) fprintf (NetTrace, "%s", TELOPT (j)); else if (TELCMD_OK (j)) fprintf (NetTrace, "%s", TELCMD (j)); else fprintf (NetTrace, "%d", j); fprintf (NetTrace, ", not IAC SE!) "); } } length -= 2; } if (length < 1) { fprintf (NetTrace, "(Empty suboption??\?)"); if (NetTrace == stdout) fflush (NetTrace); return; } switch (pointer[0]) { case TELOPT_TTYPE: fprintf (NetTrace, "TERMINAL-TYPE "); switch (pointer[1]) { case TELQUAL_IS: fprintf (NetTrace, "IS \"%.*s\"", length - 2, (char *) pointer + 2); break; case TELQUAL_SEND: fprintf (NetTrace, "SEND"); break; default: fprintf (NetTrace, "- unknown qualifier %d (0x%x).", pointer[1], pointer[1]); } break; case TELOPT_TSPEED: fprintf (NetTrace, "TERMINAL-SPEED"); if (length < 2) { fprintf (NetTrace, " (empty suboption??\?)"); break; } switch (pointer[1]) { case TELQUAL_IS: fprintf (NetTrace, " IS "); fprintf (NetTrace, "%.*s", length - 2, (char *) pointer + 2); break; default: if (pointer[1] == 1) fprintf (NetTrace, " SEND"); else fprintf (NetTrace, " %d (unknown)", pointer[1]); for (i = 2; i < length; i++) fprintf (NetTrace, " ?%d?", pointer[i]); break; } break; case TELOPT_LFLOW: fprintf (NetTrace, "TOGGLE-FLOW-CONTROL"); if (length < 2) { fprintf (NetTrace, " (empty suboption??\?)"); break; } switch (pointer[1]) { case LFLOW_OFF: fprintf (NetTrace, " OFF"); break; case LFLOW_ON: fprintf (NetTrace, " ON"); break; case LFLOW_RESTART_ANY: fprintf (NetTrace, " RESTART-ANY"); break; case LFLOW_RESTART_XON: fprintf (NetTrace, " RESTART-XON"); break; default: fprintf (NetTrace, " %d (unknown)", pointer[1]); } for (i = 2; i < length; i++) fprintf (NetTrace, " ?%d?", pointer[i]); break; case TELOPT_NAWS: fprintf (NetTrace, "NAWS"); if (length < 2) { fprintf (NetTrace, " (empty suboption??\?)"); break; } if (length == 2) { fprintf (NetTrace, " ?%d?", pointer[1]); break; } fprintf (NetTrace, " %d %d (%d)", pointer[1], pointer[2], (int) ((((unsigned int) pointer[1]) << 8) | ((unsigned int) pointer[2]))); if (length == 4) { fprintf (NetTrace, " ?%d?", pointer[3]); break; } fprintf (NetTrace, " %d %d (%d)", pointer[3], pointer[4], (int) ((((unsigned int) pointer[3]) << 8) | ((unsigned int) pointer[4]))); for (i = 5; i < length; i++) fprintf (NetTrace, " ?%d?", pointer[i]); break; #if defined AUTHENTICATION case TELOPT_AUTHENTICATION: fprintf (NetTrace, "AUTHENTICATION"); if (length < 2) { fprintf (NetTrace, " (empty suboption??\?)"); break; } switch (pointer[1]) { case TELQUAL_REPLY: case TELQUAL_IS: fprintf (NetTrace, " %s ", (pointer[1] == TELQUAL_IS) ? "IS" : "REPLY"); if (AUTHTYPE_NAME_OK (pointer[2]) && AUTHTYPE_NAME (pointer[2])) fprintf (NetTrace, "%s ", AUTHTYPE_NAME (pointer[2])); else fprintf (NetTrace, "%d ", pointer[2]); if (length < 3) { fprintf (NetTrace, "(partial suboption??\?)"); break; } fprintf (NetTrace, "%s|%s", ((pointer[3] & AUTH_WHO_MASK) == AUTH_WHO_CLIENT) ? "CLIENT" : "SERVER", ((pointer[3] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) ? "MUTUAL" : "ONE-WAY"); auth_printsub (&pointer[1], length - 1, buf, sizeof (buf)); fprintf (NetTrace, "%s", buf); break; case TELQUAL_SEND: i = 2; fprintf (NetTrace, " SEND "); while (i < length) { if (AUTHTYPE_NAME_OK (pointer[i]) && AUTHTYPE_NAME (pointer[i])) fprintf (NetTrace, "%s ", AUTHTYPE_NAME (pointer[i])); else fprintf (NetTrace, "%d ", pointer[i]); if (++i >= length) { fprintf (NetTrace, "(partial suboption??\?)"); break; } fprintf (NetTrace, "%s|%s ", ((pointer[i] & AUTH_WHO_MASK) == AUTH_WHO_CLIENT) ? "CLIENT" : "SERVER", ((pointer[i] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) ? "MUTUAL" : "ONE-WAY"); ++i; } break; case TELQUAL_NAME: i = 2; fprintf (NetTrace, " NAME \""); while (i < length) putc (pointer[i++], NetTrace); putc ('"', NetTrace); break; default: for (i = 2; i < length; i++) fprintf (NetTrace, " ?%d?", pointer[i]); break; } break; #endif #ifdef ENCRYPTION case TELOPT_ENCRYPT: fprintf (NetTrace, "ENCRYPT"); if (length < 2) { fprintf (NetTrace, " (empty suboption??\?)"); break; } switch (pointer[1]) { case ENCRYPT_START: fprintf (NetTrace, " START"); break; case ENCRYPT_END: fprintf (NetTrace, " END"); break; case ENCRYPT_REQSTART: fprintf (NetTrace, " REQUEST-START"); break; case ENCRYPT_REQEND: fprintf (NetTrace, " REQUEST-END"); break; case ENCRYPT_IS: case ENCRYPT_REPLY: fprintf (NetTrace, " %s ", (pointer[1] == ENCRYPT_IS) ? "IS" : "REPLY"); if (length < 3) { fprintf (NetTrace, " (partial suboption??\?)"); break; } if (ENCTYPE_NAME_OK (pointer[2]) && ENCTYPE_NAME (pointer[2])) fprintf (NetTrace, "%s ", ENCTYPE_NAME (pointer[2])); else fprintf (NetTrace, " %d (unknown)", pointer[2]); encrypt_printsub (&pointer[1], length - 1, buf, sizeof (buf)); fprintf (NetTrace, "%s", buf); break; case ENCRYPT_SUPPORT: i = 2; fprintf (NetTrace, " SUPPORT "); while (i < length) { if (ENCTYPE_NAME_OK (pointer[i]) && ENCTYPE_NAME (pointer[i])) fprintf (NetTrace, "%s ", ENCTYPE_NAME (pointer[i])); else fprintf (NetTrace, "%d ", pointer[i]); i++; } break; case ENCRYPT_ENC_KEYID: fprintf (NetTrace, " ENC_KEYID "); goto encommon; case ENCRYPT_DEC_KEYID: fprintf (NetTrace, " DEC_KEYID "); goto encommon; default: fprintf (NetTrace, " %d (unknown)", pointer[1]); encommon: for (i = 2; i < length; i++) fprintf (NetTrace, " %d", pointer[i]); break; } break; #endif /* ENCRYPTION */ case TELOPT_LINEMODE: fprintf (NetTrace, "LINEMODE "); if (length < 2) { fprintf (NetTrace, " (empty suboption??\?)"); break; } switch (pointer[1]) { case WILL: fprintf (NetTrace, "WILL "); goto common; case WONT: fprintf (NetTrace, "WONT "); goto common; case DO: fprintf (NetTrace, "DO "); goto common; case DONT: fprintf (NetTrace, "DONT "); common: if (length < 3) { fprintf (NetTrace, "(no option??\?)"); break; } switch (pointer[2]) { case LM_FORWARDMASK: fprintf (NetTrace, "Forward Mask"); for (i = 3; i < length; i++) fprintf (NetTrace, " %x", pointer[i]); break; default: fprintf (NetTrace, "%d (unknown)", pointer[2]); for (i = 3; i < length; i++) fprintf (NetTrace, " %d", pointer[i]); break; } break; case LM_SLC: fprintf (NetTrace, "SLC"); for (i = 2; i < length - 2; i += 3) { if (SLC_NAME_OK (pointer[i + SLC_FUNC])) fprintf (NetTrace, " %s", SLC_NAME (pointer[i + SLC_FUNC])); else fprintf (NetTrace, " %d", pointer[i + SLC_FUNC]); switch (pointer[i + SLC_FLAGS] & SLC_LEVELBITS) { case SLC_NOSUPPORT: fprintf (NetTrace, " NOSUPPORT"); break; case SLC_CANTCHANGE: fprintf (NetTrace, " CANTCHANGE"); break; case SLC_VARIABLE: fprintf (NetTrace, " VARIABLE"); break; case SLC_DEFAULT: fprintf (NetTrace, " DEFAULT"); break; } fprintf (NetTrace, "%s%s%s", (pointer[i + SLC_FLAGS] & SLC_ACK) ? "|ACK" : "", (pointer[i + SLC_FLAGS] & SLC_FLUSHIN) ? "|FLUSHIN" : "", (pointer[i + SLC_FLAGS] & SLC_FLUSHOUT) ? "|FLUSHOUT" : ""); if (pointer[i + SLC_FLAGS] & ~(SLC_ACK | SLC_FLUSHIN | SLC_FLUSHOUT | SLC_LEVELBITS)) fprintf (NetTrace, "(0x%x)", pointer[i + SLC_FLAGS]); fprintf (NetTrace, " %d;", pointer[i + SLC_VALUE]); if ((pointer[i + SLC_VALUE] == IAC) && (pointer[i + SLC_VALUE + 1] == IAC)) i++; } for (; i < length; i++) fprintf (NetTrace, " ?%d?", pointer[i]); break; case LM_MODE: fprintf (NetTrace, "MODE "); if (length < 3) { fprintf (NetTrace, "(no mode??\?)"); break; } { char tbuf[64]; sprintf (tbuf, "%s%s%s%s%s", pointer[2] & MODE_EDIT ? "|EDIT" : "", pointer[2] & MODE_TRAPSIG ? "|TRAPSIG" : "", pointer[2] & MODE_SOFT_TAB ? "|SOFT_TAB" : "", pointer[2] & MODE_LIT_ECHO ? "|LIT_ECHO" : "", pointer[2] & MODE_ACK ? "|ACK" : ""); fprintf (NetTrace, "%s", tbuf[1] ? &tbuf[1] : "0"); } if (pointer[2] & ~(MODE_MASK)) fprintf (NetTrace, " (0x%x)", pointer[2]); for (i = 3; i < length; i++) fprintf (NetTrace, " ?0x%x?", pointer[i]); break; default: fprintf (NetTrace, "%d (unknown)", pointer[1]); for (i = 2; i < length; i++) fprintf (NetTrace, " %d", pointer[i]); } break; case TELOPT_STATUS: { register char *cp; register int j, k; fprintf (NetTrace, "STATUS"); switch (pointer[1]) { default: if (pointer[1] == TELQUAL_SEND) fprintf (NetTrace, " SEND"); else fprintf (NetTrace, " %d (unknown)", pointer[1]); for (i = 2; i < length; i++) fprintf (NetTrace, " ?%d?", pointer[i]); break; case TELQUAL_IS: if (--want_status_response < 0) want_status_response = 0; if (NetTrace == stdout) fprintf (NetTrace, " IS\r\n"); else fprintf (NetTrace, " IS\n"); for (i = 2; i < length; i++) { switch (pointer[i]) { case DO: cp = "DO"; goto common2; case DONT: cp = "DONT"; goto common2; case WILL: cp = "WILL"; goto common2; case WONT: cp = "WONT"; goto common2; common2: i++; if (TELOPT_OK ((int) pointer[i])) fprintf (NetTrace, " %s %s", cp, TELOPT (pointer[i])); else fprintf (NetTrace, " %s %d", cp, pointer[i]); if (NetTrace == stdout) fprintf (NetTrace, "\r\n"); else fprintf (NetTrace, "\n"); break; case SB: fprintf (NetTrace, " SB "); i++; j = k = i; while (j < length) { if (pointer[j] == SE) { if (j + 1 == length) break; if (pointer[j + 1] == SE) j++; else break; } pointer[k++] = pointer[j++]; } printsub (0, &pointer[i], k - i); if (i < length) { fprintf (NetTrace, " SE"); i = j; } else i = j - 1; if (NetTrace == stdout) fprintf (NetTrace, "\r\n"); else fprintf (NetTrace, "\n"); break; default: fprintf (NetTrace, " %d", pointer[i]); break; } } break; } break; } case TELOPT_XDISPLOC: fprintf (NetTrace, "X-DISPLAY-LOCATION "); switch (pointer[1]) { case TELQUAL_IS: fprintf (NetTrace, "IS \"%.*s\"", length - 2, (char *) pointer + 2); break; case TELQUAL_SEND: fprintf (NetTrace, "SEND"); break; default: fprintf (NetTrace, "- unknown qualifier %d (0x%x).", pointer[1], pointer[1]); } break; case TELOPT_NEW_ENVIRON: fprintf (NetTrace, "NEW-ENVIRON "); #ifdef OLD_ENVIRON goto env_common1; case TELOPT_OLD_ENVIRON: fprintf (NetTrace, "OLD-ENVIRON"); env_common1: #endif switch (pointer[1]) { case TELQUAL_IS: fprintf (NetTrace, "IS "); goto env_common; case TELQUAL_SEND: fprintf (NetTrace, "SEND "); goto env_common; case TELQUAL_INFO: fprintf (NetTrace, "INFO "); env_common: { const char *quote = ""; #if defined ENV_HACK && defined OLD_ENVIRON extern int old_env_var, old_env_value; #endif for (i = 2; i < length; i++) { switch (pointer[i]) { case NEW_ENV_VALUE: #ifdef OLD_ENVIRON /* case NEW_ENV_OVAR: */ if (pointer[0] == TELOPT_OLD_ENVIRON) { # ifdef ENV_HACK if (old_env_var == OLD_ENV_VALUE) fprintf (NetTrace, "%s(VALUE) ", quote); else # endif fprintf (NetTrace, "%sVAR ", quote); } else #endif /* OLD_ENVIRON */ fprintf (NetTrace, "%sVALUE ", quote); quote = ""; break; case NEW_ENV_VAR: #ifdef OLD_ENVIRON /* case OLD_ENV_VALUE: */ if (pointer[0] == TELOPT_OLD_ENVIRON) { # ifdef ENV_HACK if (old_env_value == OLD_ENV_VAR) fprintf (NetTrace, "%s(VAR) ", quote); else # endif fprintf (NetTrace, "%sVALUE ", quote); } else #endif /* OLD_ENVIRON */ fprintf (NetTrace, "%sVAR ", quote); quote = ""; break; case ENV_ESC: fprintf (NetTrace, "%sESC ", quote); quote = ""; break; case ENV_USERVAR: fprintf (NetTrace, "%sUSERVAR ", quote); quote = ""; break; default: if (isprint (pointer[i]) && pointer[i] != '"') { if (quote[0] == '\0') { putc ('"', NetTrace); quote = "\" "; } putc (pointer[i], NetTrace); } else { fprintf (NetTrace, "%s%03o ", quote, pointer[i]); quote = ""; } break; } } if (quote[0] != '\0') putc ('"', NetTrace); break; } } break; default: if (TELOPT_OK (pointer[0])) fprintf (NetTrace, "%s (unknown)", TELOPT (pointer[0])); else fprintf (NetTrace, "%d (unknown)", pointer[0]); for (i = 1; i < length; i++) fprintf (NetTrace, " %d", pointer[i]); break; } if (direction) { if (NetTrace == stdout) fprintf (NetTrace, "\r\n"); else fprintf (NetTrace, "\n"); } if (NetTrace == stdout) fflush (NetTrace); } }
void optionstatus (void) { register int i; extern char will_wont_resp[], do_dont_resp[]; for (i = 0; i < 256; i++) { if (do_dont_resp[i]) { if (TELOPT_OK (i)) printf ("resp DO_DONT %s: %d\n", TELOPT (i), do_dont_resp[i]); else if (TELCMD_OK (i)) printf ("resp DO_DONT %s: %d\n", TELCMD (i), do_dont_resp[i]); else printf ("resp DO_DONT %d: %d\n", i, do_dont_resp[i]); if (my_want_state_is_do (i)) { if (TELOPT_OK (i)) printf ("want DO %s\n", TELOPT (i)); else if (TELCMD_OK (i)) printf ("want DO %s\n", TELCMD (i)); else printf ("want DO %d\n", i); } else { if (TELOPT_OK (i)) printf ("want DONT %s\n", TELOPT (i)); else if (TELCMD_OK (i)) printf ("want DONT %s\n", TELCMD (i)); else printf ("want DONT %d\n", i); } } else { if (my_state_is_do (i)) { if (TELOPT_OK (i)) printf (" DO %s\n", TELOPT (i)); else if (TELCMD_OK (i)) printf (" DO %s\n", TELCMD (i)); else printf (" DO %d\n", i); } } if (will_wont_resp[i]) { if (TELOPT_OK (i)) printf ("resp WILL_WONT %s: %d\n", TELOPT (i), will_wont_resp[i]); else if (TELCMD_OK (i)) printf ("resp WILL_WONT %s: %d\n", TELCMD (i), will_wont_resp[i]); else printf ("resp WILL_WONT %d: %d\n", i, will_wont_resp[i]); if (my_want_state_is_will (i)) { if (TELOPT_OK (i)) printf ("want WILL %s\n", TELOPT (i)); else if (TELCMD_OK (i)) printf ("want WILL %s\n", TELCMD (i)); else printf ("want WILL %d\n", i); } else { if (TELOPT_OK (i)) printf ("want WONT %s\n", TELOPT (i)); else if (TELCMD_OK (i)) printf ("want WONT %s\n", TELCMD (i)); else printf ("want WONT %d\n", i); } } else { if (my_state_is_will (i)) { if (TELOPT_OK (i)) printf (" WILL %s\n", TELOPT (i)); else if (TELCMD_OK (i)) printf (" WILL %s\n", TELCMD (i)); else printf (" WILL %d\n", i); } } } }
/* input: raw character * output: telnet command if c was handled, otherwise zero. */ unsigned int telnet_handler(unsigned char c) { static unsigned char iac_quote = 0; /* as byte to reduce memory */ static unsigned char iac_opt_req = 0; static unsigned char iac_buf[TELNET_IAC_MAXLEN]; static unsigned int iac_buflen = 0; /* we have to quote all IACs. */ if(c == IAC && !iac_quote) { iac_quote = 1; return NOP; } #ifdef DETECT_CLIENT /* hash client telnet sequences */ if(cuser.userid[0]==0) { if(iac_state == IAC_WAIT_SE) { // skip suboption } else { if(iac_quote) UpdateClientCode(IAC); UpdateClientCode(c); } } #endif /* a special case is the top level iac. otherwise, iac is just a quote. */ if (iac_quote) { if(iac_state == IAC_NONE) iac_state = IAC_COMMAND; if(iac_state == IAC_WAIT_SE && c == SE) iac_state = IAC_PROCESS_OPT; iac_quote = 0; } /* now, let's process commands by state */ switch(iac_state) { case IAC_NONE: return 0; case IAC_COMMAND: #if 0 // def DEBUG { int cx = c; /* to make compiler happy */ write(0, "-", 1); if(TELCMD_OK(cx)) write(0, TELCMD(c), strlen(TELCMD(c))); write(0, " ", 1); } #endif iac_state = IAC_NONE; /* by default we restore state. */ switch(c) { case IAC: // return 0; // we don't want to allow IACs as input. return 1; /* we don't want to process these. or maybe in future. */ case BREAK: /* break */ #ifdef DBG_OUTRPT fakeEscape = !fakeEscape; return NOP; #endif case ABORT: /* Abort process */ case SUSP: /* Suspend process */ case AO: /* abort output--but let prog finish */ case IP: /* interrupt process--permanently */ case EOR: /* end of record (transparent mode) */ case DM: /* data mark--for connect. cleaning */ case xEOF: /* End of file: EOF is already used... */ return NOP; case NOP: /* nop */ return NOP; /* we should process these, but maybe in future. */ case GA: /* you may reverse the line */ case EL: /* erase the current line */ case EC: /* erase the current character */ return NOP; /* good */ case AYT: /* are you there */ { const char *alive = "I'm still alive, loading: "; char buf[STRLEN]; /* respond as fast as we can */ write(0, alive, strlen(alive)); // cpuload(buf); buf[0] = '0'; // TODO: cpuload write(0, buf, strlen(buf)); write(0, "\r\n", 2); } return NOP; case DONT: /* you are not to use option */ case DO: /* please, you use option */ case WONT: /* I won't use option */ case WILL: /* I will use option */ iac_opt_req = c; iac_state = IAC_WAIT_OPT; return NOP; case SB: /* interpret as subnegotiation */ iac_state = IAC_WAIT_SE; iac_buflen = 0; return NOP; case SE: /* end sub negotiation */ default: return NOP; } return 1; case IAC_WAIT_OPT: #if 0 // def DEBUG write(0, "-", 1); if(TELOPT_OK(c)) write(0, TELOPT(c), strlen(TELOPT(c))); write(0, " ", 1); #endif iac_state = IAC_NONE; /* * According to RFC, there're some tricky steps to prevent loop. * However because we have a poor term which does not allow * most abilities, let's be a strong boss here. * * Although my old imeplementation worked, it's even better to follow this: * http://www.tcpipguide.com/free/t_TelnetOptionsandOptionNegotiation-3.htm */ switch(c) { /* i-dont-care: i don't care about what client is. * these should be clamed in init and * client must follow me. */ case TELOPT_TTYPE: /* termtype or line. */ case TELOPT_NAWS: /* resize terminal */ case TELOPT_SGA: /* supress GA */ case TELOPT_ECHO: /* echo */ case TELOPT_BINARY: /* we are CJK. */ break; /* i-dont-agree: i don't understand/agree these. * according to RFC, saying NO stopped further * requests so there'll not be endless loop. */ case TELOPT_RCP: /* prepare to reconnect */ default: if (iac_opt_req == WILL || iac_opt_req == DO) { /* unknown option, reply with won't */ unsigned char cmd[3] = { IAC, DONT, 0 }; if(iac_opt_req == DO) cmd[1] = WONT; cmd[2] = c; write(0, cmd, sizeof(cmd)); } break; } return 1; case IAC_WAIT_SE: iac_buf[iac_buflen++] = c; /* no need to convert state because previous quoting will do. */ if(iac_buflen == TELNET_IAC_MAXLEN) { /* may be broken protocol? * whether finished or not, break for safety * or user may be frozen. */ iac_state = IAC_NONE; return 0; } return 1; case IAC_PROCESS_OPT: iac_state = IAC_NONE; #if 0 // def DEBUG write(0, "-", 1); if(TELOPT_OK(iac_buf[0])) write(0, TELOPT(iac_buf[0]), strlen(TELOPT(iac_buf[0]))); write(0, " ", 1); #endif switch(iac_buf[0]) { /* resize terminal */ case TELOPT_NAWS: { int w = (iac_buf[1] << 8) + (iac_buf[2]); int h = (iac_buf[3] << 8) + (iac_buf[4]); term_resize(w, h); #ifdef DETECT_CLIENT if(cuser.userid[0]==0) { UpdateClientCode(iac_buf[0]); if(w==80 && h==24) UpdateClientCode(1); else if(w==80) UpdateClientCode(2); else if(h==24) UpdateClientCode(3); else UpdateClientCode(4); UpdateClientCode(IAC); UpdateClientCode(SE); } #endif } break; default: #ifdef DETECT_CLIENT if(cuser.userid[0]==0) { int i; for(i=0;i<iac_buflen;i++) UpdateClientCode(iac_buf[i]); UpdateClientCode(IAC); UpdateClientCode(SE); } #endif break; } return 1; } return 1; /* never reached */ }