diff options
Diffstat (limited to 'libexec/telnetd/state.c')
-rw-r--r-- | libexec/telnetd/state.c | 2073 |
1 files changed, 910 insertions, 1163 deletions
diff --git a/libexec/telnetd/state.c b/libexec/telnetd/state.c index 2c9d2bb9a3b..3d8428852b9 100644 --- a/libexec/telnetd/state.c +++ b/libexec/telnetd/state.c @@ -1,6 +1,3 @@ -/* $OpenBSD: state.c,v 1.13 2000/12/08 10:11:42 hin Exp $ */ -/* $NetBSD: state.c,v 1.9 1996/02/28 20:38:19 thorpej Exp $ */ - /* * Copyright (c) 1989, 1993 * The Regents of the University of California. All rights reserved. @@ -34,22 +31,10 @@ * SUCH DAMAGE. */ -#ifndef lint -#if 0 -static char sccsid[] = "@(#)state.c 8.5 (Berkeley) 5/30/95"; -static char rcsid[] = "$NetBSD: state.c,v 1.9 1996/02/28 20:38:19 thorpej Exp $"; -#else -static char rcsid[] = "$OpenBSD: state.c,v 1.13 2000/12/08 10:11:42 hin Exp $"; -#endif -#endif /* not lint */ - #include "telnetd.h" -#if defined(AUTHENTICATION) -#include <libtelnet/auth.h> -#endif -#if defined(ENCRYPTION) -#include <libtelnet/encrypt.h> -#endif +#include <syslog.h> + +/* RCSID("$KTH: state.c,v 1.14 2000/10/02 05:06:02 assar Exp $"); */ unsigned char doopt[] = { IAC, DO, '%', 'c', 0 }; unsigned char dont[] = { IAC, DONT, '%', 'c', 0 }; @@ -61,13 +46,13 @@ int not42 = 1; * Buffer for sub-options, and macros * for suboptions buffer manipulations */ -unsigned char subbuffer[512], *subpointer= subbuffer, *subend= subbuffer; +unsigned char subbuffer[2048], *subpointer= subbuffer, *subend= subbuffer; #define SB_CLEAR() subpointer = subbuffer #define SB_TERM() { subend = subpointer; SB_CLEAR(); } #define SB_ACCUM(c) if (subpointer < (subbuffer+sizeof subbuffer)) { \ - *subpointer++ = (c); \ - } + *subpointer++ = (c); \ + } #define SB_GET() ((*subpointer++)&0xff) #define SB_EOF() (subpointer >= subend) #define SB_LEN() (subend - subpointer) @@ -88,286 +73,276 @@ unsigned char *subsave; #define TS_SB 3 /* throw away begin's... */ #define TS_SE 4 /* ...end's (suboption negotiation) */ #define TS_WILL 5 /* will option negotiation */ -#define TS_WONT 6 /* wont " */ -#define TS_DO 7 /* do " */ -#define TS_DONT 8 /* dont " */ +#define TS_WONT 6 /* wont -''- */ +#define TS_DO 7 /* do -''- */ +#define TS_DONT 8 /* dont -''- */ - void -telrcv() +void +telrcv(void) { - register int c; - static int state = TS_DATA; + int c; + static int state = TS_DATA; - while (ncc > 0) { - if ((&ptyobuf[BUFSIZ] - pfrontp) < 2) - break; - c = *netip++ & 0377, ncc--; + while (ncc > 0) { + if ((&ptyobuf[BUFSIZ] - pfrontp) < 2) + break; + c = *netip++ & 0377, ncc--; #ifdef ENCRYPTION - if (decrypt_input) - c = (*decrypt_input)(c); + if (decrypt_input) + c = (*decrypt_input)(c); #endif - switch (state) { + switch (state) { - case TS_CR: - state = TS_DATA; - /* Strip off \n or \0 after a \r */ - if ((c == 0) || (c == '\n')) { - break; - } - /* FALL THROUGH */ + case TS_CR: + state = TS_DATA; + /* Strip off \n or \0 after a \r */ + if ((c == 0) || (c == '\n')) { + break; + } + /* FALL THROUGH */ - case TS_DATA: - if (c == IAC) { - state = TS_IAC; - break; - } - /* - * We now map \r\n ==> \r for pragmatic reasons. - * Many client implementations send \r\n when - * the user hits the CarriageReturn key. - * - * We USED to map \r\n ==> \n, since \r\n says - * that we want to be in column 1 of the next - * printable line, and \n is the standard - * unix way of saying that (\r is only good - * if CRMOD is set, which it normally is). - */ - if ((c == '\r') && his_state_is_wont(TELOPT_BINARY)) { - int nc = *netip; + case TS_DATA: + if (c == IAC) { + state = TS_IAC; + break; + } + /* + * We now map \r\n ==> \r for pragmatic reasons. + * Many client implementations send \r\n when + * the user hits the CarriageReturn key. + * + * We USED to map \r\n ==> \n, since \r\n says + * that we want to be in column 1 of the next + * printable line, and \n is the standard + * unix way of saying that (\r is only good + * if CRMOD is set, which it normally is). + */ + if ((c == '\r') && his_state_is_wont(TELOPT_BINARY)) { + int nc = *netip; #ifdef ENCRYPTION - if (decrypt_input) - nc = (*decrypt_input)(nc & 0xff); -#endif -#ifdef LINEMODE - /* - * If we are operating in linemode, - * convert to local end-of-line. - */ - if (linemode && (ncc > 0) && (('\n' == nc) || - ((0 == nc) && tty_iscrnl())) ) { - netip++; ncc--; - c = '\n'; - } else + if (decrypt_input) + nc = (*decrypt_input)(nc & 0xff); #endif - { + { #ifdef ENCRYPTION - if (decrypt_input) - (void)(*decrypt_input)(-1); + if (decrypt_input) + (void)(*decrypt_input)(-1); #endif - state = TS_CR; - } - } - *pfrontp++ = c; - break; + state = TS_CR; + } + } + *pfrontp++ = c; + break; - case TS_IAC: -gotiac: switch (c) { - - /* - * Send the process on the pty side an - * interrupt. Do this with a NULL or - * interrupt char; depending on the tty mode. - */ - case IP: - DIAG(TD_OPTIONS, - printoption("td: recv IAC", c)); - interrupt(); - break; - - case BREAK: - DIAG(TD_OPTIONS, - printoption("td: recv IAC", c)); - sendbrk(); - break; - - /* - * Are You There? - */ - case AYT: - DIAG(TD_OPTIONS, - printoption("td: recv IAC", c)); - recv_ayt(); - break; - - /* - * Abort Output - */ - case AO: - { - DIAG(TD_OPTIONS, - printoption("td: recv IAC", c)); - ptyflush(); /* half-hearted */ - init_termbuf(); - - if (slctab[SLC_AO].sptr && - *slctab[SLC_AO].sptr != (cc_t)(_POSIX_VDISABLE)) { - *pfrontp++ = - (unsigned char)*slctab[SLC_AO].sptr; - } - - netclear(); /* clear buffer back */ - *nfrontp++ = IAC; - *nfrontp++ = DM; - neturg = nfrontp-1; /* off by one XXX */ - DIAG(TD_OPTIONS, - printoption("td: send IAC", DM)); - break; - } + case TS_IAC: + gotiac: switch (c) { - /* - * Erase Character and - * Erase Line - */ - case EC: - case EL: - { - cc_t ch; - - DIAG(TD_OPTIONS, - printoption("td: recv IAC", c)); - ptyflush(); /* half-hearted */ - init_termbuf(); - if (c == EC) - ch = *slctab[SLC_EC].sptr; - else - ch = *slctab[SLC_EL].sptr; - if (ch != (cc_t)(_POSIX_VDISABLE)) - *pfrontp++ = (unsigned char)ch; - break; - } + /* + * Send the process on the pty side an + * interrupt. Do this with a NULL or + * interrupt char; depending on the tty mode. + */ + case IP: + DIAG(TD_OPTIONS, + printoption("td: recv IAC", c)); + interrupt(); + break; - /* - * Check for urgent data... - */ - case DM: - DIAG(TD_OPTIONS, - printoption("td: recv IAC", c)); - SYNCHing = stilloob(net); - settimer(gotDM); - break; - - - /* - * Begin option subnegotiation... - */ - case SB: - state = TS_SB; - SB_CLEAR(); - continue; - - case WILL: - state = TS_WILL; - continue; - - case WONT: - state = TS_WONT; - continue; - - case DO: - state = TS_DO; - continue; - - case DONT: - state = TS_DONT; - continue; - case EOR: - if (his_state_is_will(TELOPT_EOR)) - doeof(); - break; - - /* - * Handle RFC 10xx Telnet linemode option additions - * to command stream (EOF, SUSP, ABORT). - */ - case xEOF: - doeof(); - break; - - case SUSP: - sendsusp(); - break; - - case ABORT: - sendbrk(); - break; - - case IAC: - *pfrontp++ = c; - break; - } - state = TS_DATA; - break; + case BREAK: + DIAG(TD_OPTIONS, + printoption("td: recv IAC", c)); + sendbrk(); + break; - case TS_SB: - if (c == IAC) { - state = TS_SE; - } else { - SB_ACCUM(c); - } - break; + /* + * Are You There? + */ + case AYT: + DIAG(TD_OPTIONS, + printoption("td: recv IAC", c)); + recv_ayt(); + break; - case TS_SE: - if (c != SE) { - if (c != IAC) { - /* - * bad form of suboption negotiation. - * handle it in such a way as to avoid - * damage to local state. Parse - * suboption buffer found so far, - * then treat remaining stream as - * another command sequence. - */ - - /* for DIAGNOSTICS */ - SB_ACCUM(IAC); - SB_ACCUM(c); - subpointer -= 2; - - SB_TERM(); - suboption(); - state = TS_IAC; - goto gotiac; - } - SB_ACCUM(c); - state = TS_SB; - } else { - /* for DIAGNOSTICS */ - SB_ACCUM(IAC); - SB_ACCUM(SE); - subpointer -= 2; - - SB_TERM(); - suboption(); /* handle sub-option */ - state = TS_DATA; - } - break; + /* + * Abort Output + */ + case AO: + { + DIAG(TD_OPTIONS, + printoption("td: recv IAC", c)); + ptyflush(); /* half-hearted */ + init_termbuf(); + + if (slctab[SLC_AO].sptr && + *slctab[SLC_AO].sptr != (cc_t)(_POSIX_VDISABLE)) { + *pfrontp++ = + (unsigned char)*slctab[SLC_AO].sptr; + } + + netclear(); /* clear buffer back */ + output_data ("%c%c", IAC, DM); + neturg = nfrontp-1; /* off by one XXX */ + DIAG(TD_OPTIONS, + printoption("td: send IAC", DM)); + break; + } - case TS_WILL: - willoption(c); - state = TS_DATA; - continue; - - case TS_WONT: - wontoption(c); - state = TS_DATA; - continue; - - case TS_DO: - dooption(c); - state = TS_DATA; - continue; - - case TS_DONT: - dontoption(c); - state = TS_DATA; - continue; - - default: - syslog(LOG_ERR, "telnetd: panic state=%d", state); - printf("telnetd: panic state=%d\n", state); - exit(1); + /* + * Erase Character and + * Erase Line + */ + case EC: + case EL: + { + cc_t ch; + + DIAG(TD_OPTIONS, + printoption("td: recv IAC", c)); + ptyflush(); /* half-hearted */ + init_termbuf(); + if (c == EC) + ch = *slctab[SLC_EC].sptr; + else + ch = *slctab[SLC_EL].sptr; + if (ch != (cc_t)(_POSIX_VDISABLE)) + *pfrontp++ = (unsigned char)ch; + break; + } + + /* + * Check for urgent data... + */ + case DM: + DIAG(TD_OPTIONS, + printoption("td: recv IAC", c)); + SYNCHing = stilloob(net); + settimer(gotDM); + break; + + + /* + * Begin option subnegotiation... + */ + case SB: + state = TS_SB; + SB_CLEAR(); + continue; + + case WILL: + state = TS_WILL; + continue; + + case WONT: + state = TS_WONT; + continue; + + case DO: + state = TS_DO; + continue; + + case DONT: + state = TS_DONT; + continue; + case EOR: + if (his_state_is_will(TELOPT_EOR)) + doeof(); + break; + + /* + * Handle RFC 10xx Telnet linemode option additions + * to command stream (EOF, SUSP, ABORT). + */ + case xEOF: + doeof(); + break; + + case SUSP: + sendsusp(); + break; + + case ABORT: + sendbrk(); + break; + + case IAC: + *pfrontp++ = c; + break; + } + state = TS_DATA; + break; + + case TS_SB: + if (c == IAC) { + state = TS_SE; + } else { + SB_ACCUM(c); + } + break; + + case TS_SE: + if (c != SE) { + if (c != IAC) { + /* + * bad form of suboption negotiation. + * handle it in such a way as to avoid + * damage to local state. Parse + * suboption buffer found so far, + * then treat remaining stream as + * another command sequence. + */ + + /* for DIAGNOSTICS */ + SB_ACCUM(IAC); + SB_ACCUM(c); + subpointer -= 2; + + SB_TERM(); + suboption(); + state = TS_IAC; + goto gotiac; } + SB_ACCUM(c); + state = TS_SB; + } else { + /* for DIAGNOSTICS */ + SB_ACCUM(IAC); + SB_ACCUM(SE); + subpointer -= 2; + + SB_TERM(); + suboption(); /* handle sub-option */ + state = TS_DATA; + } + break; + + case TS_WILL: + willoption(c); + state = TS_DATA; + continue; + + case TS_WONT: + wontoption(c); + if (c==TELOPT_ENCRYPT && his_do_dont_is_changing(TELOPT_ENCRYPT) ) + dontoption(c); + state = TS_DATA; + continue; + + case TS_DO: + dooption(c); + state = TS_DATA; + continue; + + case TS_DONT: + dontoption(c); + state = TS_DATA; + continue; + + default: + syslog(LOG_ERR, "telnetd: panic state=%d\n", state); + printf("telnetd: panic state=%d\n", state); + exit(1); } + } } /* end of telrcv */ /* @@ -426,322 +401,246 @@ gotiac: switch (c) { * is complete. * */ - void -send_do(option, init) - int option, init; +void +send_do(int option, int init) { - if (init) { - if ((do_dont_resp[option] == 0 && his_state_is_will(option)) || - his_want_state_is_will(option)) - return; - /* - * Special case for TELOPT_TM: We send a DO, but pretend - * that we sent a DONT, so that we can send more DOs if - * we want to. - */ - if (option == TELOPT_TM) - set_his_want_state_wont(option); - else - set_his_want_state_will(option); - do_dont_resp[option]++; - } - (void) sprintf(nfrontp, (char *)doopt, option); - nfrontp += sizeof (dont) - 2; - - DIAG(TD_OPTIONS, printoption("td: send do", option)); + if (init) { + if ((do_dont_resp[option] == 0 && his_state_is_will(option)) || + his_want_state_is_will(option)) + return; + /* + * Special case for TELOPT_TM: We send a DO, but pretend + * that we sent a DONT, so that we can send more DOs if + * we want to. + */ + if (option == TELOPT_TM) + set_his_want_state_wont(option); + else + set_his_want_state_will(option); + do_dont_resp[option]++; + } + output_data((const char *)doopt, option); + + DIAG(TD_OPTIONS, printoption("td: send do", option)); } #ifdef AUTHENTICATION extern void auth_request(void); #endif -#ifdef LINEMODE -extern void doclientstat(); -#endif -#ifdef ENCRYPTION +#ifdef ENCRYPTION extern void encrypt_send_support(); #endif - - void -willoption(option) - int option; +void +willoption(int option) { - int changeok = 0; - void (*func)() = 0; - - /* - * process input from peer. - */ - - DIAG(TD_OPTIONS, printoption("td: recv will", option)); + int changeok = 0; + void (*func)() = 0; + + /* + * process input from peer. + */ + + DIAG(TD_OPTIONS, printoption("td: recv will", option)); + + if (do_dont_resp[option]) { + do_dont_resp[option]--; + if (do_dont_resp[option] && his_state_is_will(option)) + do_dont_resp[option]--; + } + if (do_dont_resp[option] == 0) { + if (his_want_state_is_wont(option)) { + switch (option) { + + case TELOPT_BINARY: + init_termbuf(); + tty_binaryin(1); + set_termbuf(); + changeok++; + break; - if (do_dont_resp[option]) { - do_dont_resp[option]--; - if (do_dont_resp[option] && his_state_is_will(option)) - do_dont_resp[option]--; - } - if (do_dont_resp[option] == 0) { - if (his_want_state_is_wont(option)) { - switch (option) { - - case TELOPT_BINARY: - init_termbuf(); - tty_binaryin(1); - set_termbuf(); - changeok++; - break; + case TELOPT_ECHO: + /* + * See comments below for more info. + */ + not42 = 0; /* looks like a 4.2 system */ + break; - case TELOPT_ECHO: - /* - * See comments below for more info. - */ - not42 = 0; /* looks like a 4.2 system */ - break; + case TELOPT_TM: + /* + * We never respond to a WILL TM, and + * we leave the state WONT. + */ + return; - case TELOPT_TM: -#if defined(LINEMODE) && defined(KLUDGELINEMODE) - /* - * This telnetd implementation does not really - * support timing marks, it just uses them to - * support the kludge linemode stuff. If we - * receive a will or wont TM in response to our - * do TM request that may have been sent to - * determine kludge linemode support, process - * it, otherwise TM should get a negative - * response back. - */ - /* - * Handle the linemode kludge stuff. - * If we are not currently supporting any - * linemode at all, then we assume that this - * is the client telling us to use kludge - * linemode in response to our query. Set the - * linemode type that is to be supported, note - * that the client wishes to use linemode, and - * eat the will TM as though it never arrived. - */ - if (lmodetype < KLUDGE_LINEMODE) { - lmodetype = KLUDGE_LINEMODE; - clientstat(TELOPT_LINEMODE, WILL, 0); - send_wont(TELOPT_SGA, 1); - } else if (lmodetype == NO_AUTOKLUDGE) { - lmodetype = KLUDGE_OK; - } -#endif /* defined(LINEMODE) && defined(KLUDGELINEMODE) */ - /* - * We never respond to a WILL TM, and - * we leave the state WONT. - */ - return; - - case TELOPT_LFLOW: - /* - * If we are going to support flow control - * option, then don't worry peer that we can't - * change the flow control characters. - */ - slctab[SLC_XON].defset.flag &= ~SLC_LEVELBITS; - slctab[SLC_XON].defset.flag |= SLC_DEFAULT; - slctab[SLC_XOFF].defset.flag &= ~SLC_LEVELBITS; - slctab[SLC_XOFF].defset.flag |= SLC_DEFAULT; - case TELOPT_TTYPE: - case TELOPT_SGA: - case TELOPT_NAWS: - case TELOPT_TSPEED: - case TELOPT_XDISPLOC: - case TELOPT_NEW_ENVIRON: - case TELOPT_OLD_ENVIRON: - changeok++; - break; + case TELOPT_LFLOW: + /* + * If we are going to support flow control + * option, then don't worry peer that we can't + * change the flow control characters. + */ + slctab[SLC_XON].defset.flag &= ~SLC_LEVELBITS; + slctab[SLC_XON].defset.flag |= SLC_DEFAULT; + slctab[SLC_XOFF].defset.flag &= ~SLC_LEVELBITS; + slctab[SLC_XOFF].defset.flag |= SLC_DEFAULT; + case TELOPT_TTYPE: + case TELOPT_SGA: + case TELOPT_NAWS: + case TELOPT_TSPEED: + case TELOPT_XDISPLOC: + case TELOPT_NEW_ENVIRON: + case TELOPT_OLD_ENVIRON: + changeok++; + break; -#ifdef LINEMODE - case TELOPT_LINEMODE: -# ifdef KLUDGELINEMODE - /* - * Note client's desire to use linemode. - */ - lmodetype = REAL_LINEMODE; -# endif /* KLUDGELINEMODE */ - func = doclientstat; - changeok++; - break; -#endif /* LINEMODE */ #ifdef AUTHENTICATION - case TELOPT_AUTHENTICATION: - func = auth_request; - changeok++; - break; + case TELOPT_AUTHENTICATION: + func = auth_request; + changeok++; + break; #endif -#ifdef ENCRYPTION - case TELOPT_ENCRYPT: - func = encrypt_send_support; - changeok++; - break; +#ifdef ENCRYPTION + case TELOPT_ENCRYPT: + func = encrypt_send_support; + changeok++; + break; #endif - - default: - break; - } - if (changeok) { - set_his_want_state_will(option); - send_do(option, 0); - } else { - do_dont_resp[option]++; - send_dont(option, 0); - } + + default: + break; + } + if (changeok) { + set_his_want_state_will(option); + send_do(option, 0); } else { + do_dont_resp[option]++; + send_dont(option, 0); + } + } else { + /* + * Option processing that should happen when + * we receive conformation of a change in + * state that we had requested. + */ + switch (option) { + case TELOPT_ECHO: + not42 = 0; /* looks like a 4.2 system */ /* - * Option processing that should happen when - * we receive conformation of a change in - * state that we had requested. + * Egads, he responded "WILL ECHO". Turn + * it off right now! */ - switch (option) { - case TELOPT_ECHO: - not42 = 0; /* looks like a 4.2 system */ - /* - * Egads, he responded "WILL ECHO". Turn - * it off right now! - */ - send_dont(option, 1); - /* - * "WILL ECHO". Kludge upon kludge! - * A 4.2 client is now echoing user input at - * the tty. This is probably undesireable and - * it should be stopped. The client will - * respond WONT TM to the DO TM that we send to - * check for kludge linemode. When the WONT TM - * arrives, linemode will be turned off and a - * change propogated to the pty. This change - * will cause us to process the new pty state - * in localstat(), which will notice that - * linemode is off and send a WILL ECHO - * so that we are properly in character mode and - * all is well. - */ - break; -#ifdef LINEMODE - case TELOPT_LINEMODE: -# ifdef KLUDGELINEMODE - /* - * Note client's desire to use linemode. - */ - lmodetype = REAL_LINEMODE; -# endif /* KLUDGELINEMODE */ - func = doclientstat; - break; -#endif /* LINEMODE */ + send_dont(option, 1); + /* + * "WILL ECHO". Kludge upon kludge! + * A 4.2 client is now echoing user input at + * the tty. This is probably undesireable and + * it should be stopped. The client will + * respond WONT TM to the DO TM that we send to + * check for kludge linemode. When the WONT TM + * arrives, linemode will be turned off and a + * change propogated to the pty. This change + * will cause us to process the new pty state + * in localstat(), which will notice that + * linemode is off and send a WILL ECHO + * so that we are properly in character mode and + * all is well. + */ + break; #ifdef AUTHENTICATION - case TELOPT_AUTHENTICATION: - func = auth_request; - break; + case TELOPT_AUTHENTICATION: + func = auth_request; + break; #endif -#ifdef ENCRYPTION - case TELOPT_ENCRYPT: - func = encrypt_send_support; - break; +#ifdef ENCRYPTION + case TELOPT_ENCRYPT: + func = encrypt_send_support; + break; #endif - case TELOPT_LFLOW: - func = flowstat; - break; - } + case TELOPT_LFLOW: + func = flowstat; + break; } } - set_his_state_will(option); - if (func) - (*func)(); + } + set_his_state_will(option); + if (func) + (*func)(); } /* end of willoption */ - void -send_dont(option, init) - int option, init; +void +send_dont(int option, int init) { - if (init) { - if ((do_dont_resp[option] == 0 && his_state_is_wont(option)) || - his_want_state_is_wont(option)) - return; - set_his_want_state_wont(option); - do_dont_resp[option]++; - } - (void) sprintf(nfrontp, (char *)dont, option); - nfrontp += sizeof (doopt) - 2; - - DIAG(TD_OPTIONS, printoption("td: send dont", option)); + if (init) { + if ((do_dont_resp[option] == 0 && his_state_is_wont(option)) || + his_want_state_is_wont(option)) + return; + set_his_want_state_wont(option); + do_dont_resp[option]++; + } + output_data((const char *)dont, option); + + DIAG(TD_OPTIONS, printoption("td: send dont", option)); } - void -wontoption(option) - int option; +void +wontoption(int option) { - /* - * Process client input. + /* + * Process client input. */ - DIAG(TD_OPTIONS, printoption("td: recv wont", option)); + DIAG(TD_OPTIONS, printoption("td: recv wont", option)); + + if (do_dont_resp[option]) { + do_dont_resp[option]--; + if (do_dont_resp[option] && his_state_is_wont(option)) + do_dont_resp[option]--; + } + if (do_dont_resp[option] == 0) { + if (his_want_state_is_will(option)) { + /* it is always ok to change to negative state */ + switch (option) { + case TELOPT_ECHO: + not42 = 1; /* doesn't seem to be a 4.2 system */ + break; - if (do_dont_resp[option]) { - do_dont_resp[option]--; - if (do_dont_resp[option] && his_state_is_wont(option)) - do_dont_resp[option]--; - } - if (do_dont_resp[option] == 0) { - if (his_want_state_is_will(option)) { - /* it is always ok to change to negative state */ - switch (option) { - case TELOPT_ECHO: - not42 = 1; /* doesn't seem to be a 4.2 system */ - break; + case TELOPT_BINARY: + init_termbuf(); + tty_binaryin(0); + set_termbuf(); + break; - case TELOPT_BINARY: - init_termbuf(); - tty_binaryin(0); - set_termbuf(); - break; + case TELOPT_TM: + /* + * If we get a WONT TM, and had sent a DO TM, + * don't respond with a DONT TM, just leave it + * as is. Short circut the state machine to + * achive this. + */ + set_his_want_state_wont(TELOPT_TM); + return; -#ifdef LINEMODE - case TELOPT_LINEMODE: -# ifdef KLUDGELINEMODE - /* - * If real linemode is supported, then client is - * asking to turn linemode off. - */ - if (lmodetype != REAL_LINEMODE) - break; -# endif /* KLUDGELINEMODE */ - clientstat(TELOPT_LINEMODE, WONT, 0); - break; -#endif /* LINEMODE */ - - case TELOPT_TM: - /* - * If we get a WONT TM, and had sent a DO TM, - * don't respond with a DONT TM, just leave it - * as is. Short circut the state machine to - * achive this. - */ - set_his_want_state_wont(TELOPT_TM); - return; - - case TELOPT_LFLOW: - /* - * If we are not going to support flow control - * option, then let peer know that we can't - * change the flow control characters. - */ - slctab[SLC_XON].defset.flag &= ~SLC_LEVELBITS; - slctab[SLC_XON].defset.flag |= SLC_CANTCHANGE; - slctab[SLC_XOFF].defset.flag &= ~SLC_LEVELBITS; - slctab[SLC_XOFF].defset.flag |= SLC_CANTCHANGE; - break; + case TELOPT_LFLOW: + /* + * If we are not going to support flow control + * option, then let peer know that we can't + * change the flow control characters. + */ + slctab[SLC_XON].defset.flag &= ~SLC_LEVELBITS; + slctab[SLC_XON].defset.flag |= SLC_CANTCHANGE; + slctab[SLC_XOFF].defset.flag &= ~SLC_LEVELBITS; + slctab[SLC_XOFF].defset.flag |= SLC_CANTCHANGE; + break; -#if defined(AUTHENTICATION) - case TELOPT_AUTHENTICATION: - auth_finished(0, AUTH_REJECT); - break; +#ifdef AUTHENTICATION + case TELOPT_AUTHENTICATION: + auth_finished(0, AUTH_REJECT); + break; #endif /* @@ -752,77 +651,66 @@ wontoption(option) * to the sub-negotiation, (by updating the timers) * so that we'll break out of the loop. */ - case TELOPT_TTYPE: - settimer(ttypesubopt); - break; + case TELOPT_TTYPE: + settimer(ttypesubopt); + break; - case TELOPT_TSPEED: - settimer(tspeedsubopt); - break; + case TELOPT_TSPEED: + settimer(tspeedsubopt); + break; - case TELOPT_XDISPLOC: - settimer(xdisplocsubopt); - break; + case TELOPT_XDISPLOC: + settimer(xdisplocsubopt); + break; - case TELOPT_OLD_ENVIRON: - settimer(oenvironsubopt); - break; + case TELOPT_OLD_ENVIRON: + settimer(oenvironsubopt); + break; - case TELOPT_NEW_ENVIRON: - settimer(environsubopt); - break; + case TELOPT_NEW_ENVIRON: + settimer(environsubopt); + break; - default: - break; - } - set_his_want_state_wont(option); - if (his_state_is_will(option)) - send_dont(option, 0); - } else { - switch (option) { - case TELOPT_TM: -#if defined(LINEMODE) && defined(KLUDGELINEMODE) - if (lmodetype < NO_AUTOKLUDGE) { - lmodetype = NO_LINEMODE; - clientstat(TELOPT_LINEMODE, WONT, 0); - send_will(TELOPT_SGA, 1); - send_will(TELOPT_ECHO, 1); - } -#endif /* defined(LINEMODE) && defined(KLUDGELINEMODE) */ - break; + default: + break; + } + set_his_want_state_wont(option); + if (his_state_is_will(option)) + send_dont(option, 0); + } else { + switch (option) { + case TELOPT_TM: + break; -#if defined(AUTHENTICATION) - case TELOPT_AUTHENTICATION: - auth_finished(0, AUTH_REJECT); - break; +#ifdef AUTHENTICATION + case TELOPT_AUTHENTICATION: + auth_finished(0, AUTH_REJECT); + break; #endif - default: - break; - } + default: + break; } } - set_his_state_wont(option); + } + set_his_state_wont(option); } /* end of wontoption */ - void -send_will(option, init) - int option, init; +void +send_will(int option, int init) { - if (init) { - if ((will_wont_resp[option] == 0 && my_state_is_will(option))|| - my_want_state_is_will(option)) - return; - set_my_want_state_will(option); - will_wont_resp[option]++; - } - (void) sprintf(nfrontp, (char *)will, option); - nfrontp += sizeof (doopt) - 2; - - DIAG(TD_OPTIONS, printoption("td: send will", option)); + if (init) { + if ((will_wont_resp[option] == 0 && my_state_is_will(option))|| + my_want_state_is_will(option)) + return; + set_my_want_state_will(option); + will_wont_resp[option]++; + } + output_data ((const char *)will, option); + + DIAG(TD_OPTIONS, printoption("td: send will", option)); } -#if !defined(LINEMODE) || !defined(KLUDGELINEMODE) /* * When we get a DONT SGA, we will try once to turn it * back on. If the other side responds DONT SGA, we @@ -831,238 +719,169 @@ send_will(option, init) * we'll keep them in char-at-a-time mode. */ int turn_on_sga = 0; -#endif - void -dooption(option) - int option; +void +dooption(int option) { - int changeok = 0; - - /* - * Process client input. - */ + int changeok = 0; + + /* + * Process client input. + */ + + DIAG(TD_OPTIONS, printoption("td: recv do", option)); + + if (will_wont_resp[option]) { + will_wont_resp[option]--; + if (will_wont_resp[option] && my_state_is_will(option)) + will_wont_resp[option]--; + } + if ((will_wont_resp[option] == 0) && (my_want_state_is_wont(option))) { + switch (option) { + case TELOPT_ECHO: + { + init_termbuf(); + tty_setecho(1); + set_termbuf(); + } + changeok++; + break; - DIAG(TD_OPTIONS, printoption("td: recv do", option)); + case TELOPT_BINARY: + init_termbuf(); + tty_binaryout(1); + set_termbuf(); + changeok++; + break; - if (will_wont_resp[option]) { - will_wont_resp[option]--; - if (will_wont_resp[option] && my_state_is_will(option)) - will_wont_resp[option]--; - } - if ((will_wont_resp[option] == 0) && (my_want_state_is_wont(option))) { - switch (option) { - case TELOPT_ECHO: -#ifdef LINEMODE -# ifdef KLUDGELINEMODE - if (lmodetype == NO_LINEMODE) -# else - if (his_state_is_wont(TELOPT_LINEMODE)) -# endif -#endif - { - init_termbuf(); - tty_setecho(1); - set_termbuf(); - } - changeok++; - break; + case TELOPT_SGA: + turn_on_sga = 0; + changeok++; + break; - case TELOPT_BINARY: - init_termbuf(); - tty_binaryout(1); - set_termbuf(); - changeok++; - break; + case TELOPT_STATUS: + changeok++; + break; - case TELOPT_SGA: -#if defined(LINEMODE) && defined(KLUDGELINEMODE) - /* - * If kludge linemode is in use, then we must - * process an incoming do SGA for linemode - * purposes. - */ - if (lmodetype == KLUDGE_LINEMODE) { - /* - * Receipt of "do SGA" in kludge - * linemode is the peer asking us to - * turn off linemode. Make note of - * the request. - */ - clientstat(TELOPT_LINEMODE, WONT, 0); - /* - * If linemode did not get turned off - * then don't tell peer that we did. - * Breaking here forces a wont SGA to - * be returned. - */ - if (linemode) - break; - } -#else - turn_on_sga = 0; -#endif /* defined(LINEMODE) && defined(KLUDGELINEMODE) */ - changeok++; - break; + case TELOPT_TM: + /* + * Special case for TM. We send a WILL, but + * pretend we sent a WONT. + */ + send_will(option, 0); + set_my_want_state_wont(option); + set_my_state_wont(option); + return; - case TELOPT_STATUS: - changeok++; - break; + case TELOPT_LOGOUT: + /* + * When we get a LOGOUT option, respond + * with a WILL LOGOUT, make sure that + * it gets written out to the network, + * and then just go away... + */ + set_my_want_state_will(TELOPT_LOGOUT); + send_will(TELOPT_LOGOUT, 0); + set_my_state_will(TELOPT_LOGOUT); + netflush(); + cleanup(0); + /* NOT REACHED */ + break; - case TELOPT_TM: - /* - * Special case for TM. We send a WILL, but - * pretend we sent a WONT. - */ - send_will(option, 0); - set_my_want_state_wont(option); - set_my_state_wont(option); - return; - - case TELOPT_LOGOUT: - /* - * When we get a LOGOUT option, respond - * with a WILL LOGOUT, make sure that - * it gets written out to the network, - * and then just go away... - */ - set_my_want_state_will(TELOPT_LOGOUT); - send_will(TELOPT_LOGOUT, 0); - set_my_state_will(TELOPT_LOGOUT); - (void)netflush(); - cleanup(0); - /* NOT REACHED */ - break; #ifdef ENCRYPTION - case TELOPT_ENCRYPT: - changeok++; - break; + case TELOPT_ENCRYPT: + changeok++; + break; #endif - - case TELOPT_LINEMODE: - case TELOPT_TTYPE: - case TELOPT_NAWS: - case TELOPT_TSPEED: - case TELOPT_LFLOW: - case TELOPT_XDISPLOC: + case TELOPT_LINEMODE: + case TELOPT_TTYPE: + case TELOPT_NAWS: + case TELOPT_TSPEED: + case TELOPT_LFLOW: + case TELOPT_XDISPLOC: #ifdef TELOPT_ENVIRON - case TELOPT_NEW_ENVIRON: + case TELOPT_NEW_ENVIRON: #endif - case TELOPT_OLD_ENVIRON: - default: - break; - } - if (changeok) { - set_my_want_state_will(option); - send_will(option, 0); - } else { - will_wont_resp[option]++; - send_wont(option, 0); - } + case TELOPT_OLD_ENVIRON: + default: + break; + } + if (changeok) { + set_my_want_state_will(option); + send_will(option, 0); + } else { + will_wont_resp[option]++; + send_wont(option, 0); } - set_my_state_will(option); + } + set_my_state_will(option); } /* end of dooption */ - void -send_wont(option, init) - int option, init; +void +send_wont(int option, int init) { - if (init) { - if ((will_wont_resp[option] == 0 && my_state_is_wont(option)) || - my_want_state_is_wont(option)) - return; - set_my_want_state_wont(option); - will_wont_resp[option]++; - } - (void) sprintf(nfrontp, (char *)wont, option); - nfrontp += sizeof (wont) - 2; - - DIAG(TD_OPTIONS, printoption("td: send wont", option)); + if (init) { + if ((will_wont_resp[option] == 0 && my_state_is_wont(option)) || + my_want_state_is_wont(option)) + return; + set_my_want_state_wont(option); + will_wont_resp[option]++; + } + output_data ((const char *)wont, option); + + DIAG(TD_OPTIONS, printoption("td: send wont", option)); } - void -dontoption(option) - int option; +void +dontoption(int option) { - /* - * Process client input. + /* + * Process client input. */ - DIAG(TD_OPTIONS, printoption("td: recv dont", option)); + DIAG(TD_OPTIONS, printoption("td: recv dont", option)); - if (will_wont_resp[option]) { - will_wont_resp[option]--; - if (will_wont_resp[option] && my_state_is_wont(option)) - will_wont_resp[option]--; - } - if ((will_wont_resp[option] == 0) && (my_want_state_is_will(option))) { - switch (option) { - case TELOPT_BINARY: - init_termbuf(); - tty_binaryout(0); - set_termbuf(); - break; + if (will_wont_resp[option]) { + will_wont_resp[option]--; + if (will_wont_resp[option] && my_state_is_wont(option)) + will_wont_resp[option]--; + } + if ((will_wont_resp[option] == 0) && (my_want_state_is_will(option))) { + switch (option) { + case TELOPT_BINARY: + init_termbuf(); + tty_binaryout(0); + set_termbuf(); + break; - case TELOPT_ECHO: /* we should stop echoing */ -#ifdef LINEMODE -# ifdef KLUDGELINEMODE - if ((lmodetype != REAL_LINEMODE) && - (lmodetype != KLUDGE_LINEMODE)) -# else - if (his_state_is_wont(TELOPT_LINEMODE)) -# endif -#endif - { - init_termbuf(); - tty_setecho(0); - set_termbuf(); - } - break; + case TELOPT_ECHO: /* we should stop echoing */ + { + init_termbuf(); + tty_setecho(0); + set_termbuf(); + } + break; - case TELOPT_SGA: -#if defined(LINEMODE) && defined(KLUDGELINEMODE) - /* - * If kludge linemode is in use, then we - * must process an incoming do SGA for - * linemode purposes. - */ - if ((lmodetype == KLUDGE_LINEMODE) || - (lmodetype == KLUDGE_OK)) { - /* - * The client is asking us to turn - * linemode on. - */ - lmodetype = KLUDGE_LINEMODE; - clientstat(TELOPT_LINEMODE, WILL, 0); - /* - * If we did not turn line mode on, - * then what do we say? Will SGA? - * This violates design of telnet. - * Gross. Very Gross. - */ - } - break; -#else - set_my_want_state_wont(option); - if (my_state_is_will(option)) - send_wont(option, 0); - set_my_state_wont(option); - if (turn_on_sga ^= 1) - send_will(option, 1); - return; -#endif /* defined(LINEMODE) && defined(KLUDGELINEMODE) */ - - default: - break; - } + case TELOPT_SGA: + set_my_want_state_wont(option); + if (my_state_is_will(option)) + send_wont(option, 0); + set_my_state_wont(option); + if (turn_on_sga ^= 1) + send_will(option, 1); + return; - set_my_want_state_wont(option); - if (my_state_is_will(option)) - send_wont(option, 0); + default: + break; } - set_my_state_wont(option); + + set_my_want_state_wont(option); + if (my_state_is_will(option)) + send_wont(option, 0); + } + set_my_state_wont(option); } /* end of dontoption */ @@ -1081,38 +900,38 @@ int env_ovalue = -1; * should be dropped. */ char *badenv_table[] = { - "IFS=", - "LD_", - "_RLD_", - "SHLIB_PATH=", - "LIBPATH=", - "KRB", - "ENV=", - "BASH_ENV=", - NULL, + "IFS=", + "LD_", + "_RLD_", + "SHLIB_PATH=", + "LIBPATH=", + "KRB", + "ENV=", + "BASH_ENV=", + NULL, }; /* envvarok(char*) */ /* check that variable is safe to pass to login or shell */ static int envvarok(varp) - char *varp; + char *varp; { - int i; - int len; - - if (strchr(varp, '=')) - return (0); - for (i = 0; badenv_table[i]; i++) { - len = strlen(badenv_table[i]); - if (badenv_table[i][len-1] == '=' && - !strncmp(badenv_table[i], varp, len-1) && - varp[len-2] == '\0') - return (0); - if (!strncmp(badenv_table[i], varp, len-1)) - return (0); - } - return (1); + int i; + int len; + + if (strchr(varp, '=')) + return (0); + for (i = 0; badenv_table[i]; i++) { + len = strlen(badenv_table[i]); + if (badenv_table[i][len-1] == '=' && + !strncmp(badenv_table[i], varp, len-1) && + varp[len-2] == '\0') + return (0); + if (!strncmp(badenv_table[i], varp, len-1)) + return (0); + } + return (1); } /* @@ -1128,31 +947,31 @@ envvarok(varp) * Window size * Terminal speed */ - void -suboption() +void +suboption(void) { - register int subchar; + int subchar; DIAG(TD_OPTIONS, {netflush(); printsub('<', subpointer, SB_LEN()+2);}); subchar = SB_GET(); switch (subchar) { case TELOPT_TSPEED: { - register int xspeed, rspeed; + int xspeed, rspeed; if (his_state_is_wont(TELOPT_TSPEED)) /* Ignore if option disabled */ - break; + break; settimer(tspeedsubopt); if (SB_EOF() || SB_GET() != TELQUAL_IS) - return; + return; xspeed = atoi((char *)subpointer); while (SB_GET() != ',' && !SB_EOF()); if (SB_EOF()) - return; + return; rspeed = atoi((char *)subpointer); clientstat(TELOPT_TSPEED, xspeed, rspeed); @@ -1165,7 +984,7 @@ suboption() static char terminalname[41]; if (his_state_is_wont(TELOPT_TTYPE)) /* Ignore if option disabled */ - break; + break; settimer(ttypesubopt); if (SB_EOF() || SB_GET() != TELQUAL_IS) { @@ -1175,8 +994,8 @@ suboption() terminaltype = terminalname; while ((terminaltype < (terminalname + sizeof terminalname-1)) && - !SB_EOF()) { - register int c; + !SB_EOF()) { + int c; c = SB_GET(); if (isupper(c)) { @@ -1190,22 +1009,22 @@ suboption() } /* end of case TELOPT_TTYPE */ case TELOPT_NAWS: { - register int xwinsize, ywinsize; + int xwinsize, ywinsize; if (his_state_is_wont(TELOPT_NAWS)) /* Ignore if option disabled */ - break; + break; if (SB_EOF()) - return; + return; xwinsize = SB_GET() << 8; if (SB_EOF()) - return; + return; xwinsize |= SB_GET(); if (SB_EOF()) - return; + return; ywinsize = SB_GET() << 8; if (SB_EOF()) - return; + return; ywinsize |= SB_GET(); clientstat(TELOPT_NAWS, xwinsize, ywinsize); @@ -1213,54 +1032,6 @@ suboption() } /* end of case TELOPT_NAWS */ -#ifdef LINEMODE - case TELOPT_LINEMODE: { - register int request; - - if (his_state_is_wont(TELOPT_LINEMODE)) /* Ignore if option disabled */ - break; - /* - * Process linemode suboptions. - */ - if (SB_EOF()) - break; /* garbage was sent */ - request = SB_GET(); /* get will/wont */ - - if (SB_EOF()) - break; /* another garbage check */ - - if (request == LM_SLC) { /* SLC is not preceeded by WILL or WONT */ - /* - * Process suboption buffer of slc's - */ - start_slc(1); - do_opt_slc(subpointer, subend - subpointer); - (void) end_slc(0); - break; - } else if (request == LM_MODE) { - if (SB_EOF()) - return; - useeditmode = SB_GET(); /* get mode flag */ - clientstat(LM_MODE, 0, 0); - break; - } - - if (SB_EOF()) - break; - switch (SB_GET()) { /* what suboption? */ - case LM_FORWARDMASK: - /* - * According to spec, only server can send request for - * forwardmask, and client can only return a positive response. - * So don't worry about it. - */ - - default: - break; - } - break; - } /* end of case TELOPT_LINEMODE */ -#endif case TELOPT_STATUS: { int mode; @@ -1284,11 +1055,10 @@ suboption() case TELOPT_XDISPLOC: { if (SB_EOF() || SB_GET() != TELQUAL_IS) - return; + return; settimer(xdisplocsubopt); subpointer[SB_LEN()] = '\0'; - /* XXX allocation failure? */ - (void)setenv("DISPLAY", (char *)subpointer, 1); + esetenv("DISPLAY", (char *)subpointer, 1); break; } /* end of case TELOPT_XDISPLOC */ @@ -1296,19 +1066,19 @@ suboption() case TELOPT_NEW_ENVIRON: #endif case TELOPT_OLD_ENVIRON: { - register int c; - register char *cp, *varp, *valp; + int c; + char *cp, *varp, *valp; if (SB_EOF()) - return; + return; c = SB_GET(); if (c == TELQUAL_IS) { - if (subchar == TELOPT_OLD_ENVIRON) - settimer(oenvironsubopt); - else - settimer(environsubopt); + if (subchar == TELOPT_OLD_ENVIRON) + settimer(oenvironsubopt); + else + settimer(environsubopt); } else if (c != TELQUAL_INFO) { - return; + return; } #ifdef TELOPT_NEW_ENVIRON @@ -1316,236 +1086,234 @@ suboption() while (!SB_EOF()) { c = SB_GET(); if ((c == NEW_ENV_VAR) || (c == ENV_USERVAR)) - break; + break; } } else #endif - { + { #ifdef ENV_HACK - /* - * We only want to do this if we haven't already decided - * whether or not the other side has its VALUE and VAR - * reversed. - */ - if (env_ovar < 0) { - register int last = -1; /* invalid value */ - int empty = 0; - int got_var = 0, got_value = 0, got_uservar = 0; - /* - * The other side might have its VALUE and VAR values - * reversed. To be interoperable, we need to determine - * which way it is. If the first recognized character - * is a VAR or VALUE, then that will tell us what - * type of client it is. If the fist recognized - * character is a USERVAR, then we continue scanning - * the suboption looking for two consecutive - * VAR or VALUE fields. We should not get two - * consecutive VALUE fields, so finding two - * consecutive VALUE or VAR fields will tell us - * what the client is. + * We only want to do this if we haven't already decided + * whether or not the other side has its VALUE and VAR + * reversed. */ - SB_SAVE(); - while (!SB_EOF()) { + if (env_ovar < 0) { + int last = -1; /* invalid value */ + int empty = 0; + int got_var = 0, got_value = 0, got_uservar = 0; + + /* + * The other side might have its VALUE and VAR values + * reversed. To be interoperable, we need to determine + * which way it is. If the first recognized character + * is a VAR or VALUE, then that will tell us what + * type of client it is. If the fist recognized + * character is a USERVAR, then we continue scanning + * the suboption looking for two consecutive + * VAR or VALUE fields. We should not get two + * consecutive VALUE fields, so finding two + * consecutive VALUE or VAR fields will tell us + * what the client is. + */ + SB_SAVE(); + while (!SB_EOF()) { c = SB_GET(); switch(c) { case OLD_ENV_VAR: - if (last < 0 || last == OLD_ENV_VAR - || (empty && (last == OLD_ENV_VALUE))) - goto env_ovar_ok; - got_var++; - last = OLD_ENV_VAR; - break; + if (last < 0 || last == OLD_ENV_VAR + || (empty && (last == OLD_ENV_VALUE))) + goto env_ovar_ok; + got_var++; + last = OLD_ENV_VAR; + break; case OLD_ENV_VALUE: - if (last < 0 || last == OLD_ENV_VALUE - || (empty && (last == OLD_ENV_VAR))) - goto env_ovar_wrong; - got_value++; - last = OLD_ENV_VALUE; - break; + if (last < 0 || last == OLD_ENV_VALUE + || (empty && (last == OLD_ENV_VAR))) + goto env_ovar_wrong; + got_value++; + last = OLD_ENV_VALUE; + break; case ENV_USERVAR: - /* count strings of USERVAR as one */ - if (last != ENV_USERVAR) - got_uservar++; - if (empty) { - if (last == OLD_ENV_VALUE) - goto env_ovar_ok; - if (last == OLD_ENV_VAR) - goto env_ovar_wrong; - } - last = ENV_USERVAR; - break; + /* count strings of USERVAR as one */ + if (last != ENV_USERVAR) + got_uservar++; + if (empty) { + if (last == OLD_ENV_VALUE) + goto env_ovar_ok; + if (last == OLD_ENV_VAR) + goto env_ovar_wrong; + } + last = ENV_USERVAR; + break; case ENV_ESC: - if (!SB_EOF()) - c = SB_GET(); - /* FALL THROUGH */ + if (!SB_EOF()) + c = SB_GET(); + /* FALL THROUGH */ default: - empty = 0; - continue; + empty = 0; + continue; } empty = 1; - } - if (empty) { + } + if (empty) { if (last == OLD_ENV_VALUE) - goto env_ovar_ok; + goto env_ovar_ok; if (last == OLD_ENV_VAR) - goto env_ovar_wrong; - } - /* - * Ok, the first thing was a USERVAR, and there - * are not two consecutive VAR or VALUE commands, - * and none of the VAR or VALUE commands are empty. - * If the client has sent us a well-formed option, - * then the number of VALUEs received should always - * be less than or equal to the number of VARs and - * USERVARs received. - * - * If we got exactly as many VALUEs as VARs and - * USERVARs, the client has the same definitions. - * - * If we got exactly as many VARs as VALUEs and - * USERVARS, the client has reversed definitions. - */ - if (got_uservar + got_var == got_value) { - env_ovar_ok: + goto env_ovar_wrong; + } + /* + * Ok, the first thing was a USERVAR, and there + * are not two consecutive VAR or VALUE commands, + * and none of the VAR or VALUE commands are empty. + * If the client has sent us a well-formed option, + * then the number of VALUEs received should always + * be less than or equal to the number of VARs and + * USERVARs received. + * + * If we got exactly as many VALUEs as VARs and + * USERVARs, the client has the same definitions. + * + * If we got exactly as many VARs as VALUEs and + * USERVARS, the client has reversed definitions. + */ + if (got_uservar + got_var == got_value) { + env_ovar_ok: env_ovar = OLD_ENV_VAR; env_ovalue = OLD_ENV_VALUE; - } else if (got_uservar + got_value == got_var) { - env_ovar_wrong: + } else if (got_uservar + got_value == got_var) { + env_ovar_wrong: env_ovar = OLD_ENV_VALUE; env_ovalue = OLD_ENV_VAR; - DIAG(TD_OPTIONS, {sprintf(nfrontp, - "ENVIRON VALUE and VAR are reversed!\r\n"); - nfrontp += strlen(nfrontp);}); + DIAG(TD_OPTIONS, { + output_data("ENVIRON VALUE and VAR are reversed!\r\n"); + }); + } } - } - SB_RESTORE(); + SB_RESTORE(); #endif - while (!SB_EOF()) { - c = SB_GET(); - if ((c == env_ovar) || (c == ENV_USERVAR)) + while (!SB_EOF()) { + c = SB_GET(); + if ((c == env_ovar) || (c == ENV_USERVAR)) break; + } } - } if (SB_EOF()) - return; + return; cp = varp = (char *)subpointer; valp = 0; while (!SB_EOF()) { - c = SB_GET(); - if (subchar == TELOPT_OLD_ENVIRON) { - if (c == env_ovar) - c = NEW_ENV_VAR; - else if (c == env_ovalue) - c = NEW_ENV_VALUE; - } - switch (c) { - - case NEW_ENV_VALUE: - *cp = '\0'; - cp = valp = (char *)subpointer; - break; + c = SB_GET(); + if (subchar == TELOPT_OLD_ENVIRON) { + if (c == env_ovar) + c = NEW_ENV_VAR; + else if (c == env_ovalue) + c = NEW_ENV_VALUE; + } + switch (c) { - case NEW_ENV_VAR: - case ENV_USERVAR: - *cp = '\0'; - if (envvarok(varp)) { - if (valp) - /* XXX allocation failure? */ - (void)setenv(varp, valp, 1); - else - unsetenv(varp); - } - cp = varp = (char *)subpointer; - valp = 0; - break; + case NEW_ENV_VALUE: + *cp = '\0'; + cp = valp = (char *)subpointer; + break; - case ENV_ESC: - if (SB_EOF()) - break; - c = SB_GET(); - /* FALL THROUGH */ - default: - *cp++ = c; - break; + case NEW_ENV_VAR: + case ENV_USERVAR: + *cp = '\0'; + if(envvarok(varp)) { + if (valp) + esetenv(varp, valp, 1); + else + unsetenv(varp); } + cp = varp = (char *)subpointer; + valp = 0; + break; + + case ENV_ESC: + if (SB_EOF()) + break; + c = SB_GET(); + /* FALL THROUGH */ + default: + *cp++ = c; + break; + } } *cp = '\0'; - if (envvarok(varp)) { - if (valp) - /* XXX allocation failure? */ - (void)setenv(varp, valp, 1); - else - unsetenv(varp); + if(envvarok(varp)) { + if (valp) + esetenv(varp, valp, 1); + else + unsetenv(varp); } break; } /* end of case TELOPT_NEW_ENVIRON */ -#if defined(AUTHENTICATION) +#ifdef AUTHENTICATION case TELOPT_AUTHENTICATION: if (SB_EOF()) - break; + break; switch(SB_GET()) { case TELQUAL_SEND: case TELQUAL_REPLY: - /* - * These are sent by us and cannot be sent by - * the client. - */ - break; + /* + * These are sent by us and cannot be sent by + * the client. + */ + break; case TELQUAL_IS: - auth_is(subpointer, SB_LEN()); - break; + auth_is(subpointer, SB_LEN()); + break; case TELQUAL_NAME: - auth_name(subpointer, SB_LEN()); - break; + auth_name(subpointer, SB_LEN()); + break; } break; #endif #ifdef ENCRYPTION - case TELOPT_ENCRYPT: - if (SB_EOF()) - break; + case TELOPT_ENCRYPT: + if (SB_EOF()) + break; switch(SB_GET()) { case ENCRYPT_SUPPORT: - encrypt_support(subpointer, SB_LEN()); - break; + encrypt_support(subpointer, SB_LEN()); + break; case ENCRYPT_IS: - encrypt_is(subpointer, SB_LEN()); - break; + encrypt_is(subpointer, SB_LEN()); + break; case ENCRYPT_REPLY: - encrypt_reply(subpointer, SB_LEN()); - break; + encrypt_reply(subpointer, SB_LEN()); + break; case ENCRYPT_START: - encrypt_start(subpointer, SB_LEN()); - break; + encrypt_start(subpointer, SB_LEN()); + break; case ENCRYPT_END: - encrypt_end(); - break; + encrypt_end(); + break; case ENCRYPT_REQSTART: - encrypt_request_start(subpointer, SB_LEN()); - break; + encrypt_request_start(subpointer, SB_LEN()); + break; case ENCRYPT_REQEND: - /* - * 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; + /* + * 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_ENC_KEYID: - encrypt_enc_keyid(subpointer, SB_LEN()); - break; + encrypt_enc_keyid(subpointer, SB_LEN()); + break; case ENCRYPT_DEC_KEYID: - encrypt_dec_keyid(subpointer, SB_LEN()); - break; + encrypt_dec_keyid(subpointer, SB_LEN()); + break; default: - break; + break; } break; #endif @@ -1556,100 +1324,79 @@ suboption() } /* end of suboption */ - void -doclientstat() +void +doclientstat(void) { - clientstat(TELOPT_LINEMODE, WILL, 0); + clientstat(TELOPT_LINEMODE, WILL, 0); } #define ADD(c) *ncp++ = c #define ADD_DATA(c) { *ncp++ = c; if (c == SE || c == IAC) *ncp++ = c; } - void -send_status() -{ - unsigned char statusbuf[256]; - register unsigned char *ncp; - register unsigned char i; - ncp = statusbuf; - - netflush(); /* get rid of anything waiting to go out */ +void +send_status(void) +{ + unsigned char statusbuf[256]; + unsigned char *ncp; + unsigned char i; + + ncp = statusbuf; + + netflush(); /* get rid of anything waiting to go out */ + + ADD(IAC); + ADD(SB); + ADD(TELOPT_STATUS); + ADD(TELQUAL_IS); + + /* + * We check the want_state rather than the current state, + * because if we received a DO/WILL for an option that we + * don't support, and the other side didn't send a DONT/WONT + * in response to our WONT/DONT, then the "state" will be + * WILL/DO, and the "want_state" will be WONT/DONT. We + * need to go by the latter. + */ + for (i = 0; i < (unsigned char)NTELOPTS; i++) { + if (my_want_state_is_will(i)) { + ADD(WILL); + ADD_DATA(i); + } + if (his_want_state_is_will(i)) { + ADD(DO); + ADD_DATA(i); + } + } - ADD(IAC); + if (his_want_state_is_will(TELOPT_LFLOW)) { ADD(SB); - ADD(TELOPT_STATUS); - ADD(TELQUAL_IS); - - /* - * We check the want_state rather than the current state, - * because if we received a DO/WILL for an option that we - * don't support, and the other side didn't send a DONT/WONT - * in response to our WONT/DONT, then the "state" will be - * WILL/DO, and the "want_state" will be WONT/DONT. We - * need to go by the latter. - */ - for (i = 0; i < (unsigned char)NTELOPTS; i++) { - if (my_want_state_is_will(i)) { - ADD(WILL); - ADD_DATA(i); - } - if (his_want_state_is_will(i)) { - ADD(DO); - ADD_DATA(i); - } + ADD(TELOPT_LFLOW); + if (flowmode) { + ADD(LFLOW_ON); + } else { + ADD(LFLOW_OFF); } + ADD(SE); - if (his_want_state_is_will(TELOPT_LFLOW)) { - ADD(SB); - ADD(TELOPT_LFLOW); - if (flowmode) { - ADD(LFLOW_ON); - } else { - ADD(LFLOW_OFF); - } - ADD(SE); - - if (restartany >= 0) { - ADD(SB); - ADD(TELOPT_LFLOW); - if (restartany) { - ADD(LFLOW_RESTART_ANY); - } else { - ADD(LFLOW_RESTART_XON); - } - ADD(SE); - } + if (restartany >= 0) { + ADD(SB); + ADD(TELOPT_LFLOW); + if (restartany) { + ADD(LFLOW_RESTART_ANY); + } else { + ADD(LFLOW_RESTART_XON); + } + ADD(SE); } + } -#ifdef LINEMODE - if (his_want_state_is_will(TELOPT_LINEMODE)) { - unsigned char *cp, *cpe; - int len; - - ADD(SB); - ADD(TELOPT_LINEMODE); - ADD(LM_MODE); - ADD_DATA(editmode); - ADD(SE); - - ADD(SB); - ADD(TELOPT_LINEMODE); - ADD(LM_SLC); - start_slc(0); - send_slc(); - len = end_slc(&cp); - for (cpe = cp + len; cp < cpe; cp++) - ADD_DATA(*cp); - ADD(SE); - } -#endif /* LINEMODE */ - ADD(IAC); - ADD(SE); + ADD(IAC); + ADD(SE); - writenet(statusbuf, ncp - statusbuf); - netflush(); /* Send it on its way */ + writenet(statusbuf, ncp - statusbuf); + netflush(); /* Send it on its way */ - DIAG(TD_OPTIONS, - {printsub('>', statusbuf, ncp - statusbuf); netflush();}); + DIAG(TD_OPTIONS, + {printsub('>', statusbuf, ncp - statusbuf); netflush();}); } |