home *** CD-ROM | disk | FTP | other *** search
- /****************************************************************
- * NCSA Telnet for the Macintosh *
- * *
- * National Center for Supercomputing Applications *
- * Software Development Group *
- * 152 Computing Applications Building *
- * 605 E. Springfield Ave. *
- * Champaign, IL 61820 *
- * *
- * Copyright (c) 1986-1994, *
- * Board of Trustees of the University of Illinois *
- ****************************************************************/
-
- #ifdef MPW
- #pragma segment Parse
- #endif
-
-
- #include "parse.h" // For our #defines
- #include "wind.h" /* For WindRec structure */
- /* For putln proto */
-
- #include "network.proto.h" /* For net functions */
- #include "linemode.proto.h"
- #include "vgtek.proto.h"
- #include "vsdata.h"
- #include "vsinterf.proto.h"
- #include "maclook.proto.h"
- #include "tekrgmac.proto.h"
- #include "menuseg.proto.h"
- #include "translate.proto.h"
- #include "vr.h"
- #include "vr.proto.h"
- #include "tnae.h"
- #include "authencrypt.h"
- #include "authencrypt.proto.h"
- #include "wdefpatch.proto.h"
-
- //#define OPTS_DEBUG
- #ifdef OPTS_DEBUG
- #include "optsdebug.h"
- #define opts_debug_print(x) putln(x)
- static char munger[255];
- #else
- #define opts_debug_print(x)
- #endif
-
- #include "Profiler.h"
-
- extern short scrn;
- extern WindRec *screens;
-
- #include "parse.proto.h"
-
- static char *getcname(struct WindRec *tw);
- static void encryptStatechange(struct WindRec *tw);
- static void process_suboption(struct WindRec *tw, unsigned char *start, unsigned char *end);
- static void send_will(short port, short option);
- static void send_wont(short port, short option);
- static void telnet_do(struct WindRec *tw, short option);
- static void telnet_dont(struct WindRec *tw, short option);
- static void telnet_will(struct WindRec *tw, short option);
- static void telnet_wont(struct WindRec *tw, short option);
-
- void Parseunload(void) {}
-
- void SendStringAsIfTyped(struct WindRec *tw, char *string, short len)
- {
- trbuf_nat_mac((unsigned char *)string, len, tw->national);
-
- netpush(tw->port);
-
- if (tw->kblen > 0) { /* need to flush buffer */
- netwrite(tw->port, tw->kbbuf, tw->kblen);
- tw->kblen=0;
- }
-
- netwrite(tw->port, string, len);
-
- if (tw->echo)
- parse(tw, (unsigned char *)string, len);
- }
-
- /*********************************************************************/
- /* parse
- * look at the string which has just come in from outside and
- * check for special sequences that we are interested in.
- *
- * Tries to pass through routine strings immediately, waiting for special
- * characters ESC and 255 to change modes.
- */
-
- void parse (struct WindRec *tw, unsigned char *st, short cnt)
- {
- short i,temptw;
- unsigned char *mark,*orig;
-
- // ProfilerSetStatus(true);
-
- orig = st; /* remember beginning point */
- mark = st + cnt; /* set to end of input string */
- /*
- * raw mode for debugging, passes through escape sequences and other
- * special characters as <27> symbols
- */
- if (tw->termstate == DUMBTYPE)
- {
- for (i=0; i < cnt; i++,st++) /* put on screen raw */
- if (*st == 27 || *st > 126)
- {
- sprintf((char *)tw->parsedat,"<%d>",*st);
- VSwrite(tw->vs,(char *)tw->parsedat,strlen((char *)tw->parsedat)); /* send to virtual screen */
- }
- else
- VSwrite(tw->vs,(char *) st,1); /* BYU LSC */
- }
- else
- {
-
- /*
- * traverse string, looking for any special characters which indicate that
- * we need to change modes.
- */
- while (st < mark)
- {
- switch (tw->telstate)
- {
- case GS:
- case ESCFOUND:
- if (tw->tektype >= 0) { /* we'll allow the TEK */
- if ((*st == 12) || (tw->telstate == GS)) { /* esc-FF */
- if ((*st == 12) &&
- ((tw->termstate == VTEKTYPE) || (!tw->tekclear))) {
- if (tw->termstate == VTEKTYPE)
- putln("Entering Tek mode");
- else if (tw->curgraph > -1)
- detachGraphics(tw->curgraph);
-
- if (tw->curgraph <= -1) { // No current TEK window
- temptw = VGnewwin(TEK_DEVICE_WINDOW,tw->vs);
-
- if (temptw > -1) {
- Str255 scratchPstring;
-
- tw->curgraph = temptw;
-
- VGgiveinfo(temptw);
- GetWTitle(tw->wind, scratchPstring);
- PtoCstr(scratchPstring);
- RGattach(temptw,tw->vs,(char *)scratchPstring, tw->tektype);
- }
- else
- tw->telstate = TS_NORM; // Can't create TEK window
- }
-
- if (tw->telstate != TS_NORM)
- tw->termstate = TEKTYPE;
- }
-
- if (tw->telstate == GS) {
- st++;
- VGwrite(tw->curgraph,"\035",1);
- }
- else if (tw->telstate != TS_NORM)
- VGwrite(tw->curgraph,"\037\033\014",3);
-
- tw->telstate = TS_NORM;
- break;
- } // FF or GS
- } // tw->tektype >= 0
-
- if (*st == '^') { /* ESC- ^ */
- tw->termstate = RASTYPE;
- tw->telstate = TS_NORM;
- VRwrite("\033^",2); /* Put it through */
- orig = ++st;
- break;
- }
-
- if (tw->termstate == TEKTYPE)
- VGwrite(tw->curgraph,"\033",1);
- else if (tw->termstate == RASTYPE)
- VRwrite("\033",1);
- else
- VSwrite(tw->vs,"\033",1); /* send the missing ESC */
- tw->telstate = TS_NORM;
- break;
-
-
- /*------------------------------------------------------------------------------*
- * IACFOUND: This is the start of the Telnet option negotiation. If Telnet *
- * gets an IAC character, then negotiation data follows, and is ready to be *
- * parsed. *
- *------------------------------------------------------------------------------*/
- case IACFOUND: /* telnet option negotiation- START */
- if (*st == TEL_IAC) { /* real data = 255 */
- orig = st; // MP: translation mod (break will make it miss
- // this assignment later on in the case, Jim!)
- st++; /* real 255 will get sent */
- tw->telstate = TS_NORM;
- break;
- }
- else {
- switch (*st++) {
- case TEL_EOF: /* BYU LSC */
- case TEL_EL: /* thanx Quincey!!! */
- case TEL_EC:
- case TEL_AYT:
- case TEL_AO:
- case TEL_IP:
- case TEL_BREAK:
- case TEL_DM:
- case TEL_NOP:
- case TEL_SE:
- case TEL_GA:
- #ifdef OPTS_DEBUG
- sprintf(munger,"RECV: %s",telstates[tw->telstate]);
- opts_debug_print(munger);
- #endif
- tw->telstate = TS_NORM;
- orig=st;
- break;
-
- case TEL_DOTEL:
- tw->telstate = TS_DO;
- orig = st;
- break;
-
- case TEL_WILLTEL:
- tw->telstate = TS_WILL;
- orig = st;
- break;
-
- case TEL_DONTTEL:
- tw->telstate = TS_DONT;
- orig = st;
- break;
-
- case TEL_WONTTEL:
- tw->telstate = TS_WONT;
- orig = st;
- break;
-
- /*------------------------------------------------------------------------------*
- * SUBNEGOTIATION -- If there is an SB token found, then Telnet needs to do *
- * some subnegotiating. The subnegotiation data follows, and needs to be put *
- * somewhere safe. Make sure and update the state, so that we know that *
- * Telnet is doing some subnegotiations and not just horsing around *
- *------------------------------------------------------------------------------*/
- case TEL_SB:
- tw->telstate = TS_SB; /* Guess what I'm doing... */
- orig=st;
- tw->parseIndex = 0; /* No data yet! Clear any possible garbage */
- break;
-
- default: // Means we got IAC <xx> where xx isn't recognized
- orig = st;
- tw->telstate = TS_NORM;
- #ifdef OPTS_DEBUG
- sprintf(munger,"RECVD: IAC %c",*(st-1));
- opts_debug_print(munger);
- #endif
- break;
- } // switch (*st++)
- } // else from it (*st == TEL_IAC)
- break; // case IACFOUND
-
- case TS_DO:
- telnet_do(tw, *st++);
- orig = st;
- tw->telstate = TS_NORM;
- break;
-
- case TS_DONT:
- telnet_dont(tw, *st++);
- orig = st;
- tw->telstate = TS_NORM;
- break;
-
- case TS_WILL:
- telnet_will(tw, *st++);
- orig = st;
- tw->telstate = TS_NORM;
- break;
-
- case TS_WONT:
- telnet_wont(tw, *st++);
- orig = st;
- tw->telstate = TS_NORM;
- break;
-
- case TS_SB:
- if (*st == TEL_IAC)
- {
- st++;
- if (*st == TEL_SE) //subnegotiation over
- {
- st++;
- process_suboption(tw, st, mark);
- orig = st;
- tw->telstate = TS_NORM;
- }
- else
- {
- if (*st == TEL_IAC) //doubled IAC
- tw->parsedat[tw->parseIndex++] = *st++;
- else
- { //process this, then go IAC found
-
- tw->parsedat[tw->parseIndex++] = TEL_IAC; //why do we add this to
- tw->parsedat[tw->parseIndex++] = *st; //the parsedat? We don't
- process_suboption(tw, st, mark); //need it for the options
- tw->substat = IACFOUND;
- }
- }
- }
- else // Collect subnegotiation data
- tw->parsedat[tw->parseIndex++] = *st++;
- break;
-
- default:
- tw->telstate = TS_NORM;
- break;
- } // switch(tw->telstate)
-
- /*
- * quick scan of the remaining string, skip chars while they are
- * uninteresting
- */
- if (tw->telstate == TS_NORM) {
- /*
- * skip along as fast as possible until an interesting character is found
- */
-
- if (!tw->eightbit) { /* BYU 2.4.10 */
- while (st < mark) { /* BYU 2.4.10 */
- if (*st == IAC) /* BYU 2.4.10 */
- break; /* BYU 2.4.10 */
- else { /* BYU 2.4.10 */
- *st &= 0x7f; /* BYU 2.4.10 */
- if (*st == ESC || *st == GS) /* BYU 2.4.10 */
- break; /* BYU 2.4.10 */
- st++; /* BYU 2.4.10 */
- } } /* BYU 2.4.10 */
- } else /* BYU 2.4.10 */
- while (st < mark && *st != ESC && *st < 255 && *st != GS) // MP: translation mod
- st++; /* BYU 2.4.10 */
- /*
- * send the string where it belongs
- */
- if (!tw->timing) {
- if (tw->termstate == TEKTYPE) {
- short i;
-
- i = VGwrite( tw->curgraph,(char *) orig, st-orig); /* BYU LSC */
- if (i < (st - orig)) {
- detachGraphics(tw->curgraph);
- st = orig + i;
- }
- }
- else if (tw->termstate == RASTYPE) {
- short i;
-
- i= VRwrite((char *) orig, st-orig); /* BYU LSC */
- if (i <(st-orig)) {
- tw->termstate = VTEKTYPE;
- st = orig +i; /* Next char to parse */
- }
- }
- else
- VSwrite( tw->vs,(char *) orig,st-orig); /* BYU LSC - send to virtual VT102 */
- }
-
- orig = st; /* forget what we have sent already */
-
- if (st < mark)
- switch (*st) {
- case TEL_IAC: /* telnet IAC */
- tw->telstate = IACFOUND;
- st++;
- break;
- case GS:
- if (tw->telstate != GS) {
- tw->telstate = GS;
- }
- else
- tw->telstate = TS_NORM;
- st++;
- break;
-
- case ESC: /* ESCape code */
- if (st == mark-1 || *(st+1) == 12 || *(st+1) == '^' ) {
- tw->telstate = ESCFOUND;
- }
- st++; /* strip or accept ESC char */
- break;
-
- default:
- if (*st++ > 127) {
- if (st==mark) /*new addition */
- VSwrite(tw->vs,(char *) orig,1); /* BYU LSC */
- }
- break;
- } // switch(*st)
- } // tw->telstate == TS_NORM
- } // while (st < mark)
- } // tw->termstate != DUMBTYPE
-
- // ProfilerSetStatus(false);
-
- } /* parse */
-
- void SendNAWSinfo(WindRec *s, short horiz, short vert)
- {
- char blah[20];
- unsigned char height, width;
-
- height = vert & 0xff;
- width = horiz & 0xff;
-
- /* 931112, ragge, NADA, KTH, ugly patch to not send IAC as window size */
- if(height == 0xFF) height = 0xFE;
- if(width == 0xFF) width = 0xFE;
-
- netpush (s->port);
-
- /* NCSA: syntax for command is: IAC SB NAWS widthHI widthLO heightHI heightLO IAC SE */
-
- netwrite(s->port,"\377\372\037\000",4);
- sprintf(blah,"%c\000", width);
- netwrite(s->port,blah,2);
- sprintf(blah,"%c\377\360", height);
- netwrite(s->port,blah,3);
- opts_debug_print("SENT: IAC SB NAWS <data> IAC SE");
- }
-
- /*
- * Implementation specific Kerberos routines
- */
-
-
- /*
- * getcname
- * Return a pointer to the cannonical host name
- */
- static char *getcname (WindRec *tw)
- {
- char *cp;
- static char *b, buf[100];
-
- cp = 0;
- if (tw->cannon[0])
- cp = tw->cannon;
-
- // Doing the following is bad because we disposed of our init params!
- // else if ((*(*(ConnInitParams **)(tw->myInitParams))->session)->hostname)
- // cp = (char *)(*(*(ConnInitParams **)(tw->myInitParams))->session)->hostname;
-
- /* make a local copy to avoid locking handles */
- if (cp) {
- b = buf;
- while (*cp)
- *b++ = *cp++;
- *b++ = '\0';
- return buf;
- }
-
- return cp;
- }
-
-
- /*
- * encryptStatechange
- * Called when the encryption state changes
- */
- #define kOurHit 32
- static void encryptStatechange (struct WindRec *tw)
- {
- MyWDEFPatch(zoomDocProc, tw->wind, wDraw, kOurHit);
- }
-
- void telnet_send_initial_options(WindRec *tw)
- {
- if (tw->authenticate) {
- send_will(tw->port, OPT_AUTHENTICATION);
- (tw->myopts)[OPT_AUTHENTICATION-MHOPTS_BASE] = 1;
-
- if (tw->encrypt) {
- send_will(tw->port, OPT_ENCRYPT); /* will encrypt */
- (tw->myopts)[OPT_ENCRYPT-MHOPTS_BASE] = 1;
- }
- }
-
- send_do(tw->port, N_ECHO); // Do ECHO
- tw->echo = 1;
-
- send_do(tw->port, N_SGA); // Do SGA
- tw->Usga=1;
-
- send_wont(tw->port, N_XDISPLOC);
-
- send_will(tw->port, N_NAWS);
-
- }
-
- static void process_suboption(struct WindRec *tw, unsigned char *start, unsigned char *end)
- {
- unsigned long sendlength;
- unsigned char sendbuffer[1500];
- short s;
- char IACSB[] = { TEL_IAC, TEL_SB, 0, 0};
- char IACSE[] = { TEL_IAC, TEL_SE};
-
- switch(tw->parsedat[0]) {
- /*------------------------------------------------------------------------------*
- * SUBNegotiate Termtype: send the term type data now *
- *------------------------------------------------------------------------------*/
- case N_TERMTYP:
- if (tw->parsedat[1]==1) {
- char s[60], termtmp[40];
- BlockMove(tw->answerback, termtmp, 32);
- PtoCstr((StringPtr)termtmp);
- #ifdef OPTS_DEBUG
- sprintf(munger,"RECV: SB TERMINAL-TYPE SEND\r\nSEND: SB TERMINAL-TYPE IS %s\r\n",termtmp);
- opts_debug_print(munger);
- #endif
- IACSB[2] = '\030';
- IACSB[3] = 0;
- netpush(tw->port);
- netwrite(tw->port,IACSB,4);
- netpush(tw->port);
- sprintf(s,"%s%c%c",termtmp, TEL_IAC, TEL_SE);
- netwrite(tw->port, s, strlen(s));
- }
- break;
-
- /*------------------------------------------------------------------------------*
- * SUBNegotiate ENCRYPTION: *
- *------------------------------------------------------------------------------*/
- case N_ENCRYPT:
- sendlength = sizeof(sendbuffer);
- s = encrypt_suboption((tnParams **)&tw->aedata, tw->parsedat,
- tw->parseIndex,
- sendbuffer, &sendlength, getcname(tw),
- tw->hisopts[OPT_ENCRYPT - MHOPTS_BASE],
- tw->myopts[OPT_ENCRYPT - MHOPTS_BASE]);
- netportencryptstate(tw->port, (Ptr)tw->aedata);
- encryptStatechange(tw);
-
- /*
- * If we turned on encryption, we must decrypt the rest of the buffer.
- */
- if (s == TNREP_START_DECRYPT) {
- unsigned char *cp = start;
- while (cp < end) {
- *cp = decrypt((tnParams *)tw->aedata, (long)(*cp));
- cp++;
- }
- }
-
- if (sizeof(sendbuffer) - sendlength)
- netwrite(tw->port, sendbuffer, sizeof(sendbuffer)-sendlength);
-
- /*
- * transfer the encrypting flag here, after the buffer
- * with encrypt-start has gone out.
- */
- if (((tnParams *)tw->aedata)->startencrypting) {
- ((tnParams *)tw->aedata)->startencrypting = false;
- ((tnParams *)tw->aedata)->encrypting = true;
- }
- break;
-
- /*------------------------------------------------------------------------------*
- * SUBNegotiate Authentication: send the authentication data now *
- *------------------------------------------------------------------------------*/
- case N_AUTHENTICATION:
- sendlength = sizeof(sendbuffer);
- auth_suboption((tnParams **)&tw->aedata, tw->parsedat,
- tw->parseIndex,
- sendbuffer, &sendlength, getcname(tw),
- tw->hisopts[OPT_ENCRYPT-MHOPTS_BASE],
- tw->myopts[OPT_ENCRYPT-MHOPTS_BASE]);
- if (sizeof(sendbuffer) - sendlength) {
- netwrite(tw->port, sendbuffer, sizeof(sendbuffer)-sendlength);
- }
- break;
-
- /*------------------------------------------------------------------------------*
- * SUBNegotiate Linemode: set up local characters, modes, and such *
- *------------------------------------------------------------------------------*/
- case N_LINEMODE:
- linemode_suboption(tw);
- break;
-
- /*------------------------------------------------------------------------------*
- * SUBNegotiate REMOTE_FLOW_CONTROL: determine whether we control flow, and *
- * what restarts flow *
- *------------------------------------------------------------------------------*/
- case N_REMOTEFLOW:
- switch (tw->parsedat[1])
- {
-
- case FLOW_OFF:
- #ifdef OPTS_DEBUG
- sprintf(munger,"RECV: SB REMOTE_FLOW FLOW_OFF");
- opts_debug_print(munger);
- #endif
- tw->allow_flow = FALSE;
- break;
-
- case FLOW_ON:
- #ifdef OPTS_DEBUG
- sprintf(munger,"RECV: SB REMOTE_FLOW FLOW_ON");
- opts_debug_print(munger);
- #endif
- tw->allow_flow = TRUE;
- break;
-
- case FLOW_RESTART_ANY:
- #ifdef OPTS_DEBUG
- sprintf(munger,"RECV: SB REMOTE_FLOW FLOW_RESTART_ANY");
- opts_debug_print(munger);
- #endif
- tw->restart_any_flow = TRUE;
- break;
-
- case FLOW_RESTART_XON:
- #ifdef OPTS_DEBUG
- sprintf(munger,"RECV: SB REMOTE_FLOW FLOW_RESTART_XON");
- opts_debug_print(munger);
- #endif
- tw->restart_any_flow = FALSE;
- break;
-
- default:
- break;
- }
-
- default: //dont know this subnegotiation!!
- break;
- }
- }
-
- static void telnet_do(struct WindRec *tw, short option)
- {
- #ifdef OPTS_DEBUG
- sprintf(munger,"RECV: %s %s",telstates[TEL_DOTEL-TEL_SE],teloptions[option]);
- opts_debug_print(munger);
- #endif
- switch(option) {
- case N_SGA: /* Sure we'll supress GA */
- if (!tw->Isga) {
- tw->Isga=1;
- send_will(tw->port, N_SGA);
- }
- break;
-
- case N_TERMTYP: /* And we'll even tell you about ourselves */
- if (!tw->Ittype) {
- tw->Ittype=1;
- send_will(tw->port, N_TERMTYP);
- }
- break;
-
- case N_NAWS: /* NCSA: sure, I like changing the window size! */
- tw->naws =1; /* NCSA: this session is now NAWS */
- send_will(tw->port, N_NAWS);
-
- SendNAWSinfo(tw, VSmaxwidth(tw->vs) + 1, VSgetlines(tw->vs));
- #ifdef OPTS_DEBUG
- opts_debug_print("SENT: IAC TEL_SB N_NAWS <data> IAC TEL_SE");
- #endif
- break; /* NCSA */
-
- case N_LINEMODE: /* Sure I'll do line mode... */
- if (tw->lineAllow)
- {
- send_will(tw->port, N_LINEMODE);
- doLinemode(tw);
- }
- else
- send_wont(tw->port, N_LINEMODE);
- break;
-
- case N_AUTHENTICATION: /* do auth */
- if (!tw->myopts[OPT_AUTHENTICATION-MHOPTS_BASE]) {
- if (tw->authenticate) {
- (tw->myopts)[OPT_AUTHENTICATION-MHOPTS_BASE] = 1;
- send_will(tw->port, N_AUTHENTICATION);
- }
- else {
- send_wont(tw->port, N_AUTHENTICATION);
- }
- }
- break;
-
- case N_ENCRYPT: /* do encrypt */
- if (!tw->myopts[OPT_ENCRYPT-MHOPTS_BASE]) {
- if (tw->encrypt) {
- (tw->myopts)[OPT_ENCRYPT-MHOPTS_BASE] = 1;
- send_will(tw->port, N_ENCRYPT);
- } else {
- send_wont(tw->port, N_ENCRYPT);
- }
- }
- break;
-
- case N_REMOTEFLOW:
- if (!tw->remote_flow)
- {
- tw->remote_flow = TRUE;
- send_will(tw->port, option);
- }
- break;
-
- default: /* But, we won't do .... */
- send_wont(tw->port, option);
- break;
- }
- }
-
- static void telnet_dont(struct WindRec *tw, short option)
- {
- #ifdef OPTS_DEBUG
- sprintf(munger,"RECV: %s %s",telstates[TEL_DONTTEL-TEL_SE],teloptions[option]);
- opts_debug_print(munger);
- #endif
-
- switch (option) {
- case N_ENCRYPT: /* dont encrypt */
- case N_AUTHENTICATION: /* dont authenticate */
- tw->myopts[option - MHOPTS_BASE] = 0;
- send_wont(tw->port, option);
- break;
- case N_LINEMODE: /* Ok. turn it off if its on */
- if (tw->lmode)
- {
- send_wont(tw->port, N_LINEMODE);
- if (tw->kblen > 0)
- {
- netpush(tw->port);
- netwrite(tw->port, tw->kbbuf, tw->kblen);
- }
- tw->lmode = 0;
- tw->lmodeBits = 0;
- tw->litNext = 0;
- }
- break;
-
-
- }
- }
-
- static void telnet_will(struct WindRec *tw, short option)
- {
- #ifdef OPTS_DEBUG
- sprintf(munger,"RECV: %s %s",telstates[TEL_WILLTEL-TEL_SE],teloptions[option]);
- opts_debug_print(munger);
- #endif
- switch(option)
- {
- case N_ECHO: /* Echo on the other end*/
- #ifdef OPTS_DEBUG
- if (!tw->echo)
- opts_debug_print("tw->echo is False.");
- #endif
- if (!tw->echo)
- break;
- tw->echo = 0; /* Ok, in that case they can echo... */
- changeport(scrn,scrn);
- send_do(tw->port, N_ECHO);
- break;
-
- case N_SGA: /* Supress GA */
- #ifdef OPTS_DEBUG
- if (tw->Usga)
- opts_debug_print("tw->Usga is True.");
- #endif
- if (tw->Usga)
- break;
- tw->Usga = 1; /* Go Ahead and supress GA */
- send_do(tw->port, N_SGA);
- break;
-
- case N_TIMING: /* Timing Mark */
- tw->timing = 0;
- break;
-
- case N_AUTHENTICATION: /* will auth */
- if (!tw->hisopts[OPT_AUTHENTICATION-MHOPTS_BASE]) {
- if (tw->authenticate) {
- (tw->hisopts)[OPT_AUTHENTICATION-MHOPTS_BASE] = 1;
- send_do(tw->port, N_AUTHENTICATION);
- }
- else {
- send_dont(tw->port, N_AUTHENTICATION);
- }
- }
- break;
-
- case N_ENCRYPT: /* will encrypt */
- if (!tw->hisopts[OPT_ENCRYPT-MHOPTS_BASE]) {
- if (tw->encrypt) {
- (tw->hisopts)[OPT_ENCRYPT-MHOPTS_BASE] = 1;
- send_do(tw->port, N_ENCRYPT);
- } else {
- send_dont(tw->port, N_ENCRYPT);
- }
- }
- break;
-
- case N_REMOTEFLOW: /* they want to toggle flow control */
- if (!tw->remote_flow)
- {
- tw->remote_flow = 1;
- #ifdef OPTS_DEBUG
- opts_debug_print("tw->remote_flow is True.");
- #endif
- send_do(tw->port, N_REMOTEFLOW);
- }
-
- default:
- send_dont(tw->port, option);
- }
- }
-
- static void telnet_wont(struct WindRec *tw, short option)
- {
- #ifdef OPTS_DEBUG
- sprintf(munger,"RECV: %s %s",telstates[TEL_WONTTEL-TEL_SE],teloptions[option]);
- opts_debug_print(munger);
- #endif
- switch(option)
- { /* which option? */
- case N_ECHO: /* echo */
- if (tw->echo)
- break;
- tw->echo = 1; /* Ok, I will echo if I have to... */
- changeport(scrn,scrn);
- send_dont(tw->port,N_ECHO);
- break;
-
- case N_SGA:
- if (!tw->Usga)
- break;
- tw->Usga = 0;
- send_dont(tw->port,N_SGA);
- break;
-
- case N_TIMING: /* Timing Mark */
- tw->timing = 0;
- break;
-
- case N_ENCRYPT: /* wont encrypt */
- case N_AUTHENTICATION: /* wont authenticate */
- tw->hisopts[option-MHOPTS_BASE] = 0;
- send_dont(tw->port, option);
- break;
-
- default:
- break;
- }
- }
-
- void send_do(short port, short option)
- {
- char data[] = { IAC, TEL_DOTEL, 0};
-
- data[2] = option;
- netpush(port);
- netwrite(port, data, 3);
- #ifdef OPTS_DEBUG
- sprintf(munger,"SENT: DO %s",teloptions[option]);
- opts_debug_print(munger);
- #endif
- }
-
- void send_dont(short port, short option)
- {
- char data[] = { IAC, TEL_DONTTEL, 0};
-
- data[2] = option;
- netpush(port);
- netwrite(port, data, 3);
- #ifdef OPTS_DEBUG
- sprintf(munger,"SENT: DONT %s",teloptions[option]);
- opts_debug_print(munger);
- #endif
- }
-
- static void send_will(short port, short option)
- {
- char data[] = { IAC, TEL_WILLTEL, 0};
-
- data[2] = option;
- netpush(port);
- netwrite(port, data, 3);
- #ifdef OPTS_DEBUG
- sprintf(munger,"SENT: WILL %s",teloptions[option]);
- opts_debug_print(munger);
- #endif
- }
-
- static void send_wont(short port, short option)
- {
- char data[] = { IAC, TEL_WONTTEL, 0};
-
- data[2] = option;
- netpush(port);
- netwrite(port, data, 3);
- #ifdef OPTS_DEBUG
- sprintf(munger,"SENT: WONT %s",teloptions[option]);
- opts_debug_print(munger);
- #endif
- }