int DataToNetwork(char *buffer, int count, int done) { register int loop, c; int origCount; origCount = count; while (count) { /* If not enough room for EORs, IACs, etc., wait */ if (NETROOM() < 6) { fd_set o; FD_ZERO(&o); netflush(); while (NETROOM() < 6) { FD_SET(net, &o); (void) select(net+1, (fd_set *) 0, &o, (fd_set *) 0, (struct timeval *) 0); netflush(); } } c = ring_empty_count(&netoring); if (c > count) { c = count; } loop = c; while (loop) { if (((unsigned char)*buffer) == IAC) { break; } buffer++; loop--; } if ((c = c-loop)) { ring_supply_data(&netoring, buffer-c, c); count -= c; } if (loop) { NET2ADD(IAC, IAC); count--; buffer++; } } if (done) { NET2ADD(IAC, EOR); netflush(); /* try to move along as quickly as ... */ } return(origCount - count); }
void sendnaws() { long rows, cols; unsigned char tmp[16]; unsigned char *cp; if (my_state_is_wont(TELOPT_NAWS)) return; #undef PUTSHORT #define PUTSHORT(cp, x) { if ((*cp++ = ((x)>>8)&0xff) == IAC) *cp++ = IAC; \ if ((*cp++ = ((x))&0xff) == IAC) *cp++ = IAC; } if (TerminalWindowSize(&rows, &cols) == 0) { /* Failed */ return; } cp = tmp; *cp++ = IAC; *cp++ = SB; *cp++ = TELOPT_NAWS; PUTSHORT(cp, cols); PUTSHORT(cp, rows); *cp++ = IAC; *cp++ = SE; if (NETROOM() >= cp - tmp) { ring_supply_data(&netoring, tmp, cp-tmp); printsub('>', tmp+2, cp - tmp - 2); } }
int get_status() { unsigned char tmp[16]; unsigned char *cp; if (my_want_state_is_dont(TELOPT_STATUS)) { printf("Remote side does not support STATUS option\n"); return 0; } cp = tmp; *cp++ = IAC; *cp++ = SB; *cp++ = TELOPT_STATUS; *cp++ = TELQUAL_SEND; *cp++ = IAC; *cp++ = SE; if (NETROOM() >= cp - tmp) { ring_supply_data(&netoring, tmp, cp-tmp); printsub('>', tmp+2, cp - tmp - 2); } ++want_status_response; return 1; }
int net_write(unsigned char *str, int len) { if (NETROOM() > len) { ring_supply_data(&netoring, str, len); if (str[0] == IAC && str[1] == SE) printsub('>', &str[2], len-2); return(len); } return(0); }
void slc_import(int def) { if (NETROOM() > (int)sizeof(slc_import_val)) { if (def) { ring_supply_data(&netoring, slc_import_def, sizeof(slc_import_def)); printsub('>', &slc_import_def[2], sizeof(slc_import_def)-2); } else { ring_supply_data(&netoring, slc_import_val, sizeof(slc_import_val)); printsub('>', &slc_import_val[2], sizeof(slc_import_val)-2); } } /*@*/ else printf("slc_import: not enough room\n"); }
void slc_end_reply(void) { int len; /* The end of negotiation command requires 2 bytes. */ if (&slc_replyp[2] > slc_reply_eom) return; *slc_replyp++ = IAC; *slc_replyp++ = SE; len = slc_replyp - slc_reply; if (len <= 6) return; if (NETROOM() > len) { ring_supply_data(&netoring, slc_reply, slc_replyp - slc_reply); printsub('>', &slc_reply[2], slc_replyp - slc_reply - 2); } /*@*/else printf("slc_end_reply: not enough room\n"); }
void lm_will(unsigned char *cmd, int len) { if (len < 1) { /*@*/ printf("lm_will: no command!!!\n"); /* Should not happen... */ return; } switch(cmd[0]) { case LM_FORWARDMASK: /* We shouldn't ever get this... */ default: str_lm[3] = DONT; str_lm[4] = cmd[0]; if (NETROOM() > (int)sizeof(str_lm)) { ring_supply_data(&netoring, str_lm, sizeof(str_lm)); printsub('>', &str_lm[2], sizeof(str_lm)-2); } /*@*/ else printf("lm_will: not enough room in buffer\n"); break; } }
void lm_mode(unsigned char *cmd, int len, int init) { if (len != 1) return; if ((linemode&MODE_MASK&~MODE_ACK) == *cmd) return; if (*cmd&MODE_ACK) return; linemode = *cmd&(MODE_MASK&~MODE_ACK); str_lm_mode[4] = linemode; if (!init) str_lm_mode[4] |= MODE_ACK; if (NETROOM() > (int)sizeof(str_lm_mode)) { ring_supply_data(&netoring, str_lm_mode, sizeof(str_lm_mode)); printsub('>', &str_lm_mode[2], sizeof(str_lm_mode)-2); } /*@*/ else printf("lm_mode: not enough room in buffer\n"); setconnmode(0); /* set changed mode */ }
void env_opt_end(int emptyok) { int len; len = opt_replyp - opt_reply + 2; if (emptyok || len > 6) { opt_add(IAC); opt_add(SE); if (NETROOM() > len) { ring_supply_data(&netoring, opt_reply, len); printsub('>', &opt_reply[2], len - 2); } /*@*/ else printf("slc_end_reply: not enough room\n"); } if (opt_reply) { free(opt_reply); opt_reply = opt_replyp = opt_replyend = NULL; } }
static void slc_end_reply(void) { int len; if (slc_replyp + 2 >= slc_reply + sizeof(slc_reply)) { printf("slc_end_reply: not enough room\n"); return; } slc_add(IAC); slc_add(SE); len = slc_replyp - slc_reply; if (len <= 6) return; if (NETROOM() > len) { ring_supply_data(&netoring, slc_reply, slc_replyp - slc_reply); printsub('>', &slc_reply[2], slc_replyp - slc_reply - 2); } /*@*/else printf("slc_end_reply: not enough room\n"); }
void env_opt_end(int emptyok) { int len; if (opt_replyp + 2 > opt_replyend) return; len = opt_replyp + 2 - opt_reply; if (emptyok || len > 6) { *opt_replyp++ = IAC; *opt_replyp++ = SE; if (NETROOM() > len) { ring_supply_data(&netoring, opt_reply, len); printsub('>', &opt_reply[2], len - 2); } /*@*/ else printf("slc_end_reply: not enough room\n"); } if (opt_reply) { free(opt_reply); opt_reply = opt_replyp = opt_replyend = NULL; } }
static void suboption(void) { unsigned char subchar; printsub('<', subbuffer, SB_LEN()+2); switch (subchar = SB_GET()) { case TELOPT_TTYPE: if (my_want_state_is_wont(TELOPT_TTYPE)) return; if (SB_EOF() || SB_GET() != TELQUAL_SEND) { return; } else { const char *name; unsigned char temp[50]; int len; name = gettermname(); len = strlen(name) + 4 + 2; if (len < NETROOM()) { sprintf(temp, "%c%c%c%c%s%c%c", IAC, SB, TELOPT_TTYPE, TELQUAL_IS, name, IAC, SE); ring_supply_data(&netoring, temp, len); printsub('>', &temp[2], len-2); } else { ExitString("No room in buffer for terminal type.\n", 1); /*NOTREACHED*/ } } break; case TELOPT_TSPEED: if (my_want_state_is_wont(TELOPT_TSPEED)) return; if (SB_EOF()) return; if (SB_GET() == TELQUAL_SEND) { long ospeed, ispeed; unsigned char temp[50]; int len; TerminalSpeeds(&ispeed, &ospeed); sprintf((char *)temp, "%c%c%c%c%ld,%ld%c%c", IAC, SB, TELOPT_TSPEED, TELQUAL_IS, ospeed, ispeed, IAC, SE); len = strlen((char *)temp+4) + 4; /* temp[3] is 0 ... */ if (len < NETROOM()) { ring_supply_data(&netoring, temp, len); printsub('>', temp+2, len - 2); } /*@*/ else printf("lm_will: not enough room in buffer\n"); } break; case TELOPT_LFLOW: if (my_want_state_is_wont(TELOPT_LFLOW)) return; if (SB_EOF()) return; switch(SB_GET()) { case LFLOW_RESTART_ANY: restartany = 1; break; case LFLOW_RESTART_XON: restartany = 0; break; case LFLOW_ON: localflow = 1; break; case LFLOW_OFF: localflow = 0; break; default: return; } setcommandmode(); setconnmode(0); break; case TELOPT_LINEMODE: if (my_want_state_is_wont(TELOPT_LINEMODE)) return; if (SB_EOF()) return; switch (SB_GET()) { case WILL: lm_will(subpointer, SB_LEN()); break; case WONT: lm_wont(subpointer, SB_LEN()); break; case DO: lm_do(subpointer, SB_LEN()); break; case DONT: lm_dont(subpointer, SB_LEN()); break; case LM_SLC: slc(subpointer, SB_LEN()); break; case LM_MODE: lm_mode(subpointer, SB_LEN(), 0); break; default: break; } break; #ifdef OLD_ENVIRON case TELOPT_OLD_ENVIRON: #endif case TELOPT_NEW_ENVIRON: if (SB_EOF()) return; switch(SB_PEEK()) { case TELQUAL_IS: case TELQUAL_INFO: if (my_want_state_is_dont(subchar)) return; break; case TELQUAL_SEND: if (my_want_state_is_wont(subchar)) { return; } break; default: return; } env_opt(subpointer, SB_LEN()); break; case TELOPT_XDISPLOC: if (my_want_state_is_wont(TELOPT_XDISPLOC)) return; if (SB_EOF()) return; if (SB_GET() == TELQUAL_SEND) { unsigned char temp[50], *dp; int len; if ((dp = env_getvalue("DISPLAY")) == NULL || strlen(dp) > sizeof(temp) - 7) { /* * Something happened, we no longer have a DISPLAY * variable. Or it is too long. So, turn off the option. */ send_wont(TELOPT_XDISPLOC, 1); break; } snprintf(temp, sizeof(temp), "%c%c%c%c%s%c%c", IAC, SB, TELOPT_XDISPLOC, TELQUAL_IS, dp, IAC, SE); len = strlen((char *)temp+4) + 4; /* temp[3] is 0 ... */ if (len < NETROOM()) { ring_supply_data(&netoring, temp, len); printsub('>', temp+2, len - 2); } /*@*/ else printf("lm_will: not enough room in buffer\n"); } break; #ifdef AUTHENTICATION case TELOPT_AUTHENTICATION: { if (!autologin) break; if (SB_EOF()) return; switch(SB_GET()) { case TELQUAL_IS: if (my_want_state_is_dont(TELOPT_AUTHENTICATION)) return; auth_is(subpointer, SB_LEN()); break; case TELQUAL_SEND: if (my_want_state_is_wont(TELOPT_AUTHENTICATION)) return; auth_send(subpointer, SB_LEN()); break; case TELQUAL_REPLY: if (my_want_state_is_wont(TELOPT_AUTHENTICATION)) return; auth_reply(subpointer, SB_LEN()); break; case TELQUAL_NAME: if (my_want_state_is_dont(TELOPT_AUTHENTICATION)) return; auth_name(subpointer, SB_LEN()); break; } } break; #endif #ifdef ENCRYPTION case TELOPT_ENCRYPT: if (SB_EOF()) return; switch(SB_GET()) { case ENCRYPT_START: if (my_want_state_is_dont(TELOPT_ENCRYPT)) return; encrypt_start(subpointer, SB_LEN()); break; case ENCRYPT_END: if (my_want_state_is_dont(TELOPT_ENCRYPT)) return; encrypt_end(); break; case ENCRYPT_SUPPORT: if (my_want_state_is_wont(TELOPT_ENCRYPT)) return; encrypt_support(subpointer, SB_LEN()); break; case ENCRYPT_REQSTART: if (my_want_state_is_wont(TELOPT_ENCRYPT)) return; encrypt_request_start(subpointer, SB_LEN()); break; case ENCRYPT_REQEND: if (my_want_state_is_wont(TELOPT_ENCRYPT)) return; /* * We can always send an REQEND so that we cannot * get stuck encrypting. We should only get this * if we have been able to get in the correct mode * anyhow. */ encrypt_request_end(); break; case ENCRYPT_IS: if (my_want_state_is_dont(TELOPT_ENCRYPT)) return; encrypt_is(subpointer, SB_LEN()); break; case ENCRYPT_REPLY: if (my_want_state_is_wont(TELOPT_ENCRYPT)) return; encrypt_reply(subpointer, SB_LEN()); break; case ENCRYPT_ENC_KEYID: if (my_want_state_is_dont(TELOPT_ENCRYPT)) return; encrypt_enc_keyid(subpointer, SB_LEN()); break; case ENCRYPT_DEC_KEYID: if (my_want_state_is_wont(TELOPT_ENCRYPT)) return; encrypt_dec_keyid(subpointer, SB_LEN()); break; default: break; } break; #endif /* ENCRYPTION */ default: break; } }
static int telsnd(void) { int tcc; int count; int returnValue = 0; unsigned char *tbp; tcc = 0; count = 0; while (NETROOM() > 2) { int sc; int c; if (tcc == 0) { if (count) { ring_consumed(&ttyiring, count); returnValue = 1; count = 0; } tbp = ttyiring.consume; tcc = ring_full_consecutive(&ttyiring); if (tcc == 0) { break; } } c = *tbp++ & 0xff, sc = strip(c), tcc--; count++; if (rlogin != _POSIX_VDISABLE) { if (bol) { bol = 0; if (sc == rlogin) { local = 1; continue; } } else if (local) { local = 0; if (sc == '.' || c == termEofChar) { bol = 1; command(0, "close\n", 6); continue; } if (sc == termSuspChar) { bol = 1; command(0, "z\n", 2); continue; } if (sc == escape) { command(0, tbp, tcc); bol = 1; count += tcc; tcc = 0; flushline = 1; break; } if (sc != rlogin) { ++tcc; --tbp; --count; c = sc = rlogin; } } if ((sc == '\n') || (sc == '\r')) bol = 1; } else if (escape != _POSIX_VDISABLE && sc == escape) { /* * Double escape is a pass through of a single escape character. */ if (tcc && strip(*tbp) == escape) { tbp++; tcc--; count++; bol = 0; } else { command(0, (char *)tbp, tcc); bol = 1; count += tcc; tcc = 0; flushline = 1; break; } } else bol = 0; #ifdef KLUDGELINEMODE if (kludgelinemode && (globalmode&MODE_EDIT) && (sc == echoc)) { if (tcc > 0 && strip(*tbp) == echoc) { tcc--; tbp++; count++; } else { dontlecho = !dontlecho; settimer(echotoggle); setconnmode(0); flushline = 1; break; } } #endif if (MODE_LOCAL_CHARS(globalmode)) { if (TerminalSpecialChars(sc) == 0) { bol = 1; break; } } if (my_want_state_is_wont(TELOPT_BINARY)) { switch (c) { case '\n': /* * If we are in CRMOD mode (\r ==> \n) * on our local machine, then probably * a newline (unix) is CRLF (TELNET). */ if (MODE_LOCAL_CHARS(globalmode)) { NETADD('\r'); } NETADD('\n'); bol = flushline = 1; break; case '\r': if (!crlf) { NET2ADD('\r', '\0'); } else { NET2ADD('\r', '\n'); } bol = flushline = 1; break; case IAC: NET2ADD(IAC, IAC); break; default: NETADD(c); break; } } else if (c == IAC) { NET2ADD(IAC, IAC); } else { NETADD(c); } } if (count) ring_consumed(&ttyiring, count); return returnValue||count; /* Non-zero if we did anything */ }
static void suboption(void) { unsigned char subchar; printsub('<', subbuffer, SB_LEN()+2); switch (subchar = SB_GET()) { case TELOPT_TTYPE: if (my_want_state_is_wont(TELOPT_TTYPE)) return; if (SB_EOF() || SB_GET() != TELQUAL_SEND) { return; } else { char *name; unsigned char temp[50]; int len; name = gettermname(); len = strlen(name) + 4 + 2; if (len < NETROOM()) { snprintf((char *)temp, sizeof(temp), "%c%c%c%c%s%c%c", IAC, SB, TELOPT_TTYPE, TELQUAL_IS, name, IAC, SE); ring_supply_data(&netoring, temp, len); printsub('>', &temp[2], len-2); } else ExitString("No room in buffer for terminal type.\n", 1); } break; case TELOPT_TSPEED: if (my_want_state_is_wont(TELOPT_TSPEED)) return; if (SB_EOF()) return; if (SB_GET() == TELQUAL_SEND) { long ospeed, ispeed; unsigned char temp[50]; int len; TerminalSpeeds(&ispeed, &ospeed); snprintf((char *)temp, sizeof(temp), "%c%c%c%c%ld,%ld%c%c", IAC, SB, TELOPT_TSPEED, TELQUAL_IS, ospeed, ispeed, IAC, SE); len = strlen((char *)temp+4) + 4; /* temp[3] is 0 ... */ if (len < NETROOM()) { ring_supply_data(&netoring, temp, len); printsub('>', temp+2, len - 2); } /*@*/ else printf("lm_will: not enough room in buffer\n"); } break; case TELOPT_LFLOW: if (my_want_state_is_wont(TELOPT_LFLOW)) return; if (SB_EOF()) return; switch(SB_GET()) { case LFLOW_RESTART_ANY: restartany = 1; break; case LFLOW_RESTART_XON: restartany = 0; break; case LFLOW_ON: localflow = 1; break; case LFLOW_OFF: localflow = 0; break; default: return; } setcommandmode(); setconnmode(0); break; case TELOPT_LINEMODE: if (my_want_state_is_wont(TELOPT_LINEMODE)) return; if (SB_EOF()) return; switch (SB_GET()) { case WILL: lm_will(subpointer, SB_LEN()); break; case WONT: lm_wont(subpointer, SB_LEN()); break; case DO: lm_do(subpointer, SB_LEN()); break; case DONT: lm_dont(subpointer, SB_LEN()); break; case LM_SLC: slc(subpointer, SB_LEN()); break; case LM_MODE: lm_mode(subpointer, SB_LEN(), 0); break; default: break; } break; case TELOPT_NEW_ENVIRON: if (SB_EOF()) return; switch(SB_PEEK()) { case TELQUAL_IS: case TELQUAL_INFO: if (my_want_state_is_dont(subchar)) return; break; case TELQUAL_SEND: if (my_want_state_is_wont(subchar)) { return; } break; default: return; } env_opt(subpointer, SB_LEN()); break; case TELOPT_XDISPLOC: if (my_want_state_is_wont(TELOPT_XDISPLOC)) return; if (SB_EOF()) return; if (SB_GET() == TELQUAL_SEND) { unsigned char temp[50], *dp; int len; if ((dp = env_getvalue("DISPLAY", 0)) == NULL) { /* * Something happened, we no longer have a DISPLAY * variable. So, turn off the option. */ send_wont(TELOPT_XDISPLOC, 1); break; } snprintf((char *)temp, sizeof(temp), "%c%c%c%c%s%c%c", IAC, SB, TELOPT_XDISPLOC, TELQUAL_IS, dp, IAC, SE); len = strlen((char *)temp+4) + 4; /* temp[3] is 0 ... */ if (len < NETROOM()) { ring_supply_data(&netoring, temp, len); printsub('>', temp+2, len - 2); } /*@*/ else printf("lm_will: not enough room in buffer\n"); } break; default: break; } }