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 *
- ****************************************************************/
- #include <string.h>
- #include <stdio.h>
- #include "TelnetHeader.h"
- #include "wind.h"
- #include "parse.h"
-
- #include "linemode.proto.h"
- #include "network.proto.h"
-
- #ifdef MPW
- #pragma segment Parse
- #endif
-
- //#define OPTS_DEBUG
- #ifdef OPTS_DEBUG
- #include "optsdebug.h"
- #define opts_debug_print(x) putln(x)
- #else
- #define opts_debug_print(x)
- #endif
-
- static void DemangleLineMode(char *s, short mode);
- static void DemangleLineModeShort(char *s, short mode);
-
- #define SEND_NOSUPPORT_ON_SLC_INIT 1
-
- static unsigned char str_lm[] = { TEL_IAC, TEL_SB, N_LINEMODE, 0, 0, TEL_IAC, TEL_SE };
- static unsigned char str_lm_mode[] = { TEL_IAC, TEL_SB, N_LINEMODE, L_MODE, 0, TEL_IAC, TEL_SE };
- void linemode_suboption(struct WindRec *tw)
- {
- short i;
-
- switch(tw->parsedat[1]) {
- char s[80];
-
- case L_MODE: /* change mode */
- #ifdef OPTS_DEBUG
- strcpy(s, "RECV: SB LINEMODE MODE => ");
- DemangleLineModeShort(s, tw->parsedat[2]);
- opts_debug_print(s);
- #endif
- if (tw->lineAllow) { // First make sure we allowed linemode in the first place.
- // RFC 1184 says client should ignore MODE negotiations with the MODE_ACK bit set, and should not
- // generate a response if the negotiated MODE matches the current MODE
- if (!((tw->parsedat[2] & L_MODE_ACK) || ((tw->parsedat[2] & L_MODE_MASK) == tw->lmode))) {
-
- // This is a hack. Accept the state of L_EDIT and L_TRAPSIG that the server wants. If
- // the server only wants zero, one, two or both of those bits, generate an ack. Otherwise
- // send the server a mode that masks out all requested bits except EDIT and TRAPSIG.
-
- // (Now, since we only support L_EDIT and/or L_TRAPSIG, if those are the only modes requested,)
- // (send an ACK of that MODE to the server.)
-
- tw->lmode = (tw->parsedat[2] & (L_EDIT | L_TRAPSIG)); // Accept the mode.
-
- if ((tw->parsedat[2] & (L_EDIT | L_TRAPSIG)) == tw->parsedat[2]) {
- tw->parsedat[2] |= L_MODE_ACK; // Set the MODE_ACK bit
- }
- // We got a MODE bit we dont support, mask out just what we support and send it back, UNacked.
- else {
- tw->parsedat[2] = tw->parsedat[2] & (L_EDIT | L_TRAPSIG);
- }
-
- sprintf(s,"%c%c%c%c",IAC,TEL_SB,N_LINEMODE,L_MODE);
- netwrite(tw->port,s,4);
- sprintf(s,"%c%c%c",tw->parsedat[2],IAC,TEL_SE);
- netwrite(tw->port,s,3);
- #ifdef OPTS_DEBUG
- opts_debug_print("SENT: IAC SB");
- strcpy(s, "SENT: LM MODE = ");
- DemangleLineModeShort(s, tw->parsedat[2]);
- opts_debug_print(s);
- opts_debug_print("SENT: IAC SE");
- #endif
- }
- #ifdef OPTS_DEBUG
- else {
- strcpy(s, "LINEMODE MODE = ");
- DemangleLineModeShort(s, tw->parsedat[2]);
- opts_debug_print(s);
- if (tw->parsedat[2] & L_MODE_ACK)
- opts_debug_print("\tignored 'cause MODE_ACK was set.");
- else
- opts_debug_print("\tIMPLICITLY ACCEPTED.");
- strcpy(s, "Curr Linemode = ");
- DemangleLineModeShort(s, tw->lmode);
- opts_debug_print(s);
- }
- #endif
-
- }
- break;
-
- case TEL_DOTEL:
- #ifdef OPTS_DEBUG
- sprintf(munger,"RECV: SB LINEMODE DO %c", tw->parsedat[2]);
- opts_debug_print(munger);
- #endif
- str_lm[3] = TEL_WONTTEL;
- str_lm[4] = tw->parsedat[2];
- netpush(tw->port);
- netwrite(tw->port, str_lm, sizeof(str_lm));
- #ifdef OPTS_DEBUG
- sprintf(munger,"SENT: IAC SB LINEMODE DONT %c IAC SE", tw->parsedat[2]);
- opts_debug_print(munger);
- #endif
- break;
-
- case TEL_WILLTEL:
- #ifdef OPTS_DEBUG
- sprintf(munger,"RECV: SB LINEMODE WILL %c", tw->parsedat[2]);
- opts_debug_print(munger);
- #endif
- str_lm[3] = TEL_DONTTEL;
- str_lm[4] = tw->parsedat[2];
- netpush(tw->port);
- netwrite(tw->port, str_lm, sizeof(str_lm));
- #ifdef OPTS_DEBUG
- sprintf(munger,"SENT: IAC SB LINEMODE DONT %c IAC SE", tw->parsedat[2]);
- opts_debug_print(munger);
- #endif
- break;
-
-
- case L_SLC: /* set local chars */
- {
- short lmslcflag = 0;
- #ifdef OPTS_DEBUG
- sprintf(munger,"RECV: SB LINEMODE SLC");
- opts_debug_print(munger);
- for(i=2;(tw->parsedat[i]!='\0') && (tw->parsedat[i]!=IAC); i+=3) {
- if(tw->parsedat[i+1] & SLC_AWK)
- sprintf(munger," %s %s|AWK %d",LMoptions[tw->parsedat[i]],LMflags[tw->parsedat[i+1] & SLC_LEVELBITS],tw->parsedat[i+2]);
- else
- sprintf(munger," %s %s %d",LMoptions[tw->parsedat[i]],LMflags[tw->parsedat[i+1] & SLC_LEVELBITS],tw->parsedat[i+2]);
- opts_debug_print(munger);
- // 2.6b16.1 if ((unsigned char)(tw->parsedat[i+2])==IAC) i++;
- } /* end for */
- #endif
-
- for (i=2, lmslcflag=0; (tw->parsedat[i]!='\0') && (tw->parsedat[i]!=IAC); i+=3) {
-
- // If func = 0, skip it 'cause we are the client.
- // if (tw->parsedat[i] == 0)
- // continue;
-
- // If it's a function we don't know about, say we don't support it. If the server is telling
- // us he doesn't support it, just ignore him.
- if (tw->parsedat[i] > SLC_MAX) {
- if ((tw->parsedat[i+1] & SLC_LEVELBITS) != SLC_NOSUPPORT) {
- if (!lmslcflag) {
- lmslcflag = 1; // Do this only once
- sprintf(s,"%c%c%c%c",IAC,TEL_SB,N_LINEMODE,L_SLC);
- netwrite(tw->port,s,4);
- opts_debug_print("SENT: IAC SB LINEMODE SLC");
- }
- sprintf(s,"%c%c%c",tw->parsedat[i],SLC_NOSUPPORT,0);
- #ifdef OPTS_DEBUG
- sprintf(munger," %d SLC_NOSUPPORT 0",tw->parsedat[i]);
- opts_debug_print(munger);
- #endif
- netwrite(tw->port,s,3);
- }
- else
- continue;
- }
-
- // RFC 1184: If we get a response that is the same as the current setting, ignore it. Technically, we
- // should check the value for a CANTCHANGE response to satisfy part 2 of Sec 5.5. However, since we
- // advertised that key as CANTCHANGE in the first place, the server should not be changing it. This
- // should be fixed later, however I don't see it causing big problems right now. - JMB 12/93
-
- if (! ((((tw->parsedat[i+1] & SLC_LEVELBITS) == SLC_NOSUPPORT) && (tw->slc[tw->parsedat[i]] == -1))
- || (((tw->parsedat[i+1] & SLC_LEVELBITS) == SLC_CANTCHANGE) && (tw->slc[tw->parsedat[i]] != -1)))) {
- // If we get to this point, the value sent to us doesn't agree with what we want.
-
-
- if (!(tw->parsedat[i+1] & SLC_AWK)) {
- if (!lmslcflag) {
- lmslcflag = 1; // Do this only once
- sprintf(s,"%c%c%c%c",IAC,TEL_SB,N_LINEMODE,L_SLC);
- netwrite(tw->port,s,4);
- opts_debug_print("SENT: IAC SB LINEMODE SLC");
- }
-
- if (tw->slc[tw->parsedat[i]]==-1)
- {
- sprintf(s,"%c%c%c",tw->parsedat[i],SLC_NOSUPPORT,0);
- #ifdef OPTS_DEBUG
- sprintf(munger," %s SLC_NOSUPPORT 0",LMoptions[tw->parsedat[i]]);
- #endif
- }
- else
- {
- sprintf(s,"%c%c%c",tw->parsedat[i],SLC_CANTCHANGE,(char)tw->slc[tw->parsedat[i]]);
- #ifdef OPTS_DEBUG
- sprintf(munger," %s SLC_CANTCHANGE %d",LMoptions[tw->parsedat[i]],
- (char)tw->slc[tw->parsedat[i]]);
- #endif
- }
- #ifdef OPTS_DEBUG
- opts_debug_print(munger);
- #endif
- netwrite(tw->port,s,3);
- // 2.6b16.1 if (tw->parsedat[i+2]==IAC) i++;
- }
- }
- }
-
- if (lmslcflag) {
- sprintf(s,"%c%c",IAC,TEL_SE);
- netwrite(tw->port,s,2);
- }
-
-
- /* otherwise just exit */
- }
- break;
-
- default:
- #ifdef OPTS_DEBUG
- sprintf(munger, "RECV: SB LINEMODE ?? (?? = %c)", tw->parsedat[1]);
- opts_debug_print(munger);
- #endif
- break;
-
- }
- }
-
- static void DemangleLineMode(char *s, short mode)
- {
- #ifdef OPTS_DEBUG
- short i;
-
- for (i=0; i<5; i++) {
- if (mode & (1 << i))
- strcat(s, LMmodes[i]);
- }
- #endif
- }
-
- static void DemangleLineModeShort(char *s, short mode)
- {
- #ifdef OPTS_DEBUG
- short i;
-
- for (i=0; i<5; i++) {
- if (mode & (1 << i))
- strcat(s, LMmodeBits[i]);
- else
- strcat(s," ");
- }
- #endif
- }
-