133686Sbostic /* 233686Sbostic * Copyright (c) 1988 Regents of the University of California. 333686Sbostic * All rights reserved. 433686Sbostic * 544361Sborman * %sccs.include.redist.c% 633686Sbostic */ 733686Sbostic 833686Sbostic #ifndef lint 9*57213Sdab static char sccsid[] = "@(#)utilities.c 5.5 (Berkeley) 12/18/92"; 1033686Sbostic #endif /* not lint */ 1133686Sbostic 1232149Sminshall #define TELOPTS 1338690Sborman #define TELCMDS 1446808Sdab #define SLC_NAMES 1532149Sminshall #include <arpa/telnet.h> 1632381Sminshall #include <sys/types.h> 1744361Sborman #include <sys/time.h> 1832149Sminshall 1932149Sminshall #include <ctype.h> 2032149Sminshall 2134305Sminshall #include "general.h" 2234305Sminshall 2336280Sminshall #include "fdset.h" 2436280Sminshall 2532381Sminshall #include "ring.h" 2632381Sminshall 2736278Sminshall #include "defines.h" 2836278Sminshall 2932149Sminshall #include "externs.h" 3032149Sminshall 3132149Sminshall FILE *NetTrace = 0; /* Not in bss, since needs to stay */ 3238690Sborman int prettydump; 3332149Sminshall 3432149Sminshall /* 3532149Sminshall * upcase() 3632149Sminshall * 3732149Sminshall * Upcase (in place) the argument. 3832149Sminshall */ 3932149Sminshall 4046808Sdab void 4132149Sminshall upcase(argument) 4246808Sdab register char *argument; 4332149Sminshall { 4432149Sminshall register int c; 4532149Sminshall 4632149Sminshall while ((c = *argument) != 0) { 4732149Sminshall if (islower(c)) { 4832149Sminshall *argument = toupper(c); 4932149Sminshall } 5032149Sminshall argument++; 5132149Sminshall } 5232149Sminshall } 5332149Sminshall 5432149Sminshall /* 5532149Sminshall * SetSockOpt() 5632149Sminshall * 5732149Sminshall * Compensate for differences in 4.2 and 4.3 systems. 5832149Sminshall */ 5932149Sminshall 6046808Sdab int 6132149Sminshall SetSockOpt(fd, level, option, yesno) 6246808Sdab int fd, level, option, yesno; 6332149Sminshall { 6432149Sminshall #ifndef NOT43 6532149Sminshall return setsockopt(fd, level, option, 6632149Sminshall (char *)&yesno, sizeof yesno); 6732149Sminshall #else /* NOT43 */ 6832149Sminshall if (yesno == 0) { /* Can't do that in 4.2! */ 6932149Sminshall fprintf(stderr, "Error: attempt to turn off an option 0x%x.\n", 7032149Sminshall option); 7132149Sminshall return -1; 7232149Sminshall } 7332149Sminshall return setsockopt(fd, level, option, 0, 0); 7432149Sminshall #endif /* NOT43 */ 7532149Sminshall } 7632149Sminshall 7732149Sminshall /* 7832149Sminshall * The following are routines used to print out debugging information. 7932149Sminshall */ 8032149Sminshall 8139529Sborman unsigned char NetTraceFile[256] = "(standard output)"; 8232149Sminshall 8346808Sdab void 8438690Sborman SetNetTrace(file) 8546808Sdab register char *file; 8638690Sborman { 8738690Sborman if (NetTrace && NetTrace != stdout) 8838690Sborman fclose(NetTrace); 8938690Sborman if (file && (strcmp(file, "-") != 0)) { 9038690Sborman NetTrace = fopen(file, "w"); 9138690Sborman if (NetTrace) { 9246808Sdab strcpy((char *)NetTraceFile, file); 9338690Sborman return; 9438690Sborman } 9538690Sborman fprintf(stderr, "Cannot open %s.\n", file); 9638690Sborman } 9738690Sborman NetTrace = stdout; 9846808Sdab strcpy((char *)NetTraceFile, "(standard output)"); 9938690Sborman } 10038690Sborman 10146808Sdab void 10232149Sminshall Dump(direction, buffer, length) 10346808Sdab char direction; 10446808Sdab unsigned char *buffer; 10546808Sdab int length; 10632149Sminshall { 10732149Sminshall # define BYTES_PER_LINE 32 10832149Sminshall # define min(x,y) ((x<y)? x:y) 10946808Sdab unsigned char *pThis; 11032149Sminshall int offset; 11138690Sborman extern pettydump; 11232149Sminshall 11332149Sminshall offset = 0; 11432149Sminshall 11532149Sminshall while (length) { 11632149Sminshall /* print one line */ 11732149Sminshall fprintf(NetTrace, "%c 0x%x\t", direction, offset); 11832149Sminshall pThis = buffer; 11938690Sborman if (prettydump) { 12038909Sborman buffer = buffer + min(length, BYTES_PER_LINE/2); 12138690Sborman while (pThis < buffer) { 12238690Sborman fprintf(NetTrace, "%c%.2x", 12338690Sborman (((*pThis)&0xff) == 0xff) ? '*' : ' ', 12438690Sborman (*pThis)&0xff); 12538690Sborman pThis++; 12638690Sborman } 12738909Sborman length -= BYTES_PER_LINE/2; 12838909Sborman offset += BYTES_PER_LINE/2; 12938690Sborman } else { 13038909Sborman buffer = buffer + min(length, BYTES_PER_LINE); 13138690Sborman while (pThis < buffer) { 13238690Sborman fprintf(NetTrace, "%.2x", (*pThis)&0xff); 13338690Sborman pThis++; 13438690Sborman } 13538909Sborman length -= BYTES_PER_LINE; 13638909Sborman offset += BYTES_PER_LINE; 13732149Sminshall } 13837226Sminshall if (NetTrace == stdout) { 13938207Sminshall fprintf(NetTrace, "\r\n"); 14038207Sminshall } else { 14137226Sminshall fprintf(NetTrace, "\n"); 14237226Sminshall } 14332149Sminshall if (length < 0) { 14436693Sminshall fflush(NetTrace); 14532149Sminshall return; 14632149Sminshall } 14732149Sminshall /* find next unique line */ 14832149Sminshall } 14936693Sminshall fflush(NetTrace); 15032149Sminshall } 15132149Sminshall 15232149Sminshall 15346808Sdab void 15446808Sdab printoption(direction, cmd, option) 15546808Sdab char *direction; 15646808Sdab int cmd, option; 15732149Sminshall { 15832149Sminshall if (!showoptions) 15932149Sminshall return; 16046808Sdab if (cmd == IAC) { 16146808Sdab if (TELCMD_OK(option)) 16246808Sdab fprintf(NetTrace, "%s IAC %s", direction, TELCMD(option)); 16346808Sdab else 16446808Sdab fprintf(NetTrace, "%s IAC %d", direction, option); 16546808Sdab } else { 16646808Sdab register char *fmt; 16746808Sdab fmt = (cmd == WILL) ? "WILL" : (cmd == WONT) ? "WONT" : 16846808Sdab (cmd == DO) ? "DO" : (cmd == DONT) ? "DONT" : 0; 16946808Sdab if (fmt) { 17046808Sdab fprintf(NetTrace, "%s %s ", direction, fmt); 17146808Sdab if (TELOPT_OK(option)) 17246808Sdab fprintf(NetTrace, "%s", TELOPT(option)); 17346808Sdab else if (option == TELOPT_EXOPL) 17446808Sdab fprintf(NetTrace, "EXOPL"); 17546808Sdab else 17646808Sdab fprintf(NetTrace, "%d", option); 17746808Sdab } else 17846808Sdab fprintf(NetTrace, "%s %d %d", direction, cmd, option); 17946808Sdab } 18038690Sborman if (NetTrace == stdout) 18137226Sminshall fprintf(NetTrace, "\r\n"); 18238690Sborman else 18337226Sminshall fprintf(NetTrace, "\n"); 18437226Sminshall return; 18532149Sminshall } 18632149Sminshall 18746808Sdab void 18838690Sborman optionstatus() 18938690Sborman { 19038690Sborman register int i; 19138690Sborman extern char will_wont_resp[], do_dont_resp[]; 19238690Sborman 19338690Sborman for (i = 0; i < 256; i++) { 19438690Sborman if (do_dont_resp[i]) { 19538690Sborman if (TELOPT_OK(i)) 19638690Sborman printf("resp DO_DONT %s: %d\n", TELOPT(i), do_dont_resp[i]); 19738690Sborman else if (TELCMD_OK(i)) 19838690Sborman printf("resp DO_DONT %s: %d\n", TELCMD(i), do_dont_resp[i]); 19938690Sborman else 20038690Sborman printf("resp DO_DONT %d: %d\n", i, 20138690Sborman do_dont_resp[i]); 20238690Sborman if (my_want_state_is_do(i)) { 20338690Sborman if (TELOPT_OK(i)) 20438690Sborman printf("want DO %s\n", TELOPT(i)); 20538690Sborman else if (TELCMD_OK(i)) 20638690Sborman printf("want DO %s\n", TELCMD(i)); 20738690Sborman else 20838690Sborman printf("want DO %d\n", i); 20938690Sborman } else { 21038690Sborman if (TELOPT_OK(i)) 21138690Sborman printf("want DONT %s\n", TELOPT(i)); 21238690Sborman else if (TELCMD_OK(i)) 21338690Sborman printf("want DONT %s\n", TELCMD(i)); 21438690Sborman else 21538690Sborman printf("want DONT %d\n", i); 21638690Sborman } 21738690Sborman } else { 21838690Sborman if (my_state_is_do(i)) { 21938690Sborman if (TELOPT_OK(i)) 22038690Sborman printf(" DO %s\n", TELOPT(i)); 22138690Sborman else if (TELCMD_OK(i)) 22238690Sborman printf(" DO %s\n", TELCMD(i)); 22338690Sborman else 22438690Sborman printf(" DO %d\n", i); 22538690Sborman } 22638690Sborman } 22738690Sborman if (will_wont_resp[i]) { 22838690Sborman if (TELOPT_OK(i)) 22938690Sborman printf("resp WILL_WONT %s: %d\n", TELOPT(i), will_wont_resp[i]); 23038690Sborman else if (TELCMD_OK(i)) 23138690Sborman printf("resp WILL_WONT %s: %d\n", TELCMD(i), will_wont_resp[i]); 23238690Sborman else 23338690Sborman printf("resp WILL_WONT %d: %d\n", 23438690Sborman i, will_wont_resp[i]); 23538690Sborman if (my_want_state_is_will(i)) { 23638690Sborman if (TELOPT_OK(i)) 23738690Sborman printf("want WILL %s\n", TELOPT(i)); 23838690Sborman else if (TELCMD_OK(i)) 23938690Sborman printf("want WILL %s\n", TELCMD(i)); 24038690Sborman else 24138690Sborman printf("want WILL %d\n", i); 24238690Sborman } else { 24338690Sborman if (TELOPT_OK(i)) 24438690Sborman printf("want WONT %s\n", TELOPT(i)); 24538690Sborman else if (TELCMD_OK(i)) 24638690Sborman printf("want WONT %s\n", TELCMD(i)); 24738690Sborman else 24838690Sborman printf("want WONT %d\n", i); 24938690Sborman } 25038690Sborman } else { 25138690Sborman if (my_state_is_will(i)) { 25238690Sborman if (TELOPT_OK(i)) 25338690Sborman printf(" WILL %s\n", TELOPT(i)); 25438690Sborman else if (TELCMD_OK(i)) 25538690Sborman printf(" WILL %s\n", TELCMD(i)); 25638690Sborman else 25738690Sborman printf(" WILL %d\n", i); 25838690Sborman } 25938690Sborman } 26038690Sborman } 26138690Sborman 26238690Sborman } 26338690Sborman 26446808Sdab void 26532149Sminshall printsub(direction, pointer, length) 26646808Sdab char direction; /* '<' or '>' */ 26746808Sdab unsigned char *pointer; /* where suboption data sits */ 26846808Sdab int length; /* length of suboption data */ 26932149Sminshall { 27038690Sborman register int i; 27147608Sdab char buf[512]; 27246808Sdab extern int want_status_response; 27338690Sborman 27446808Sdab if (showoptions || direction == 0 || 27546808Sdab (want_status_response && (pointer[0] == TELOPT_STATUS))) { 27638909Sborman if (direction) { 27746808Sdab fprintf(NetTrace, "%s IAC SB ", 27846808Sdab (direction == '<')? "RCVD":"SENT"); 27938909Sborman if (length >= 3) { 28038909Sborman register int j; 28138690Sborman 28238909Sborman i = pointer[length-2]; 28338909Sborman j = pointer[length-1]; 28438690Sborman 28538909Sborman if (i != IAC || j != SE) { 28638909Sborman fprintf(NetTrace, "(terminated by "); 28738909Sborman if (TELOPT_OK(i)) 28838909Sborman fprintf(NetTrace, "%s ", TELOPT(i)); 28938909Sborman else if (TELCMD_OK(i)) 29038909Sborman fprintf(NetTrace, "%s ", TELCMD(i)); 29138909Sborman else 29238909Sborman fprintf(NetTrace, "%d ", i); 29338909Sborman if (TELOPT_OK(j)) 29438909Sborman fprintf(NetTrace, "%s", TELOPT(j)); 29538909Sborman else if (TELCMD_OK(j)) 29638909Sborman fprintf(NetTrace, "%s", TELCMD(j)); 29738909Sborman else 29838909Sborman fprintf(NetTrace, "%d", j); 29938909Sborman fprintf(NetTrace, ", not IAC SE!) "); 30038909Sborman } 30138690Sborman } 30238909Sborman length -= 2; 30338690Sborman } 30438690Sborman if (length < 1) { 30538690Sborman fprintf(NetTrace, "(Empty suboption???)"); 30638690Sborman return; 30738690Sborman } 30832149Sminshall switch (pointer[0]) { 30932149Sminshall case TELOPT_TTYPE: 31038690Sborman fprintf(NetTrace, "TERMINAL-TYPE "); 31132149Sminshall switch (pointer[1]) { 31232149Sminshall case TELQUAL_IS: 31344361Sborman fprintf(NetTrace, "IS \"%.*s\"", length-2, (char *)pointer+2); 31432149Sminshall break; 31532149Sminshall case TELQUAL_SEND: 31638690Sborman fprintf(NetTrace, "SEND"); 31732149Sminshall break; 31832149Sminshall default: 31932149Sminshall fprintf(NetTrace, 32038690Sborman "- unknown qualifier %d (0x%x).", 32134849Sminshall pointer[1], pointer[1]); 32232149Sminshall } 32332149Sminshall break; 32438690Sborman case TELOPT_TSPEED: 32538690Sborman fprintf(NetTrace, "TERMINAL-SPEED"); 32638690Sborman if (length < 2) { 32738690Sborman fprintf(NetTrace, " (empty suboption???)"); 32838690Sborman break; 32938690Sborman } 33038690Sborman switch (pointer[1]) { 33138909Sborman case TELQUAL_IS: 33238690Sborman fprintf(NetTrace, " IS "); 33344361Sborman fprintf(NetTrace, "%.*s", length-2, (char *)pointer+2); 33438690Sborman break; 33538690Sborman default: 33638690Sborman if (pointer[1] == 1) 33738690Sborman fprintf(NetTrace, " SEND"); 33838690Sborman else 33944361Sborman fprintf(NetTrace, " %d (unknown)", pointer[1]); 34038690Sborman for (i = 2; i < length; i++) 34138690Sborman fprintf(NetTrace, " ?%d?", pointer[i]); 34238690Sborman break; 34338690Sborman } 34438690Sborman break; 34538690Sborman 34638690Sborman case TELOPT_LFLOW: 34738690Sborman fprintf(NetTrace, "TOGGLE-FLOW-CONTROL"); 34838690Sborman if (length < 2) { 34938690Sborman fprintf(NetTrace, " (empty suboption???)"); 35038690Sborman break; 35138690Sborman } 35238690Sborman switch (pointer[1]) { 35338690Sborman case 0: 35438690Sborman fprintf(NetTrace, " OFF"); break; 35538690Sborman case 1: 35638690Sborman fprintf(NetTrace, " ON"); break; 35738690Sborman default: 35844361Sborman fprintf(NetTrace, " %d (unknown)", pointer[1]); 35938690Sborman } 36038690Sborman for (i = 2; i < length; i++) 36138690Sborman fprintf(NetTrace, " ?%d?", pointer[i]); 36238690Sborman break; 36338690Sborman 36438690Sborman case TELOPT_NAWS: 36538690Sborman fprintf(NetTrace, "NAWS"); 36638690Sborman if (length < 2) { 36738690Sborman fprintf(NetTrace, " (empty suboption???)"); 36838690Sborman break; 36938690Sborman } 37038690Sborman if (length == 2) { 37138690Sborman fprintf(NetTrace, " ?%d?", pointer[1]); 37238690Sborman break; 37338690Sborman } 37438690Sborman fprintf(NetTrace, " %d %d (%d)", 37538690Sborman pointer[1], pointer[2], 37644361Sborman (int)((((unsigned int)pointer[1])<<8)|((unsigned int)pointer[2]))); 37738690Sborman if (length == 4) { 37838690Sborman fprintf(NetTrace, " ?%d?", pointer[3]); 37938690Sborman break; 38038690Sborman } 38138690Sborman fprintf(NetTrace, " %d %d (%d)", 38238690Sborman pointer[3], pointer[4], 38344361Sborman (int)((((unsigned int)pointer[3])<<8)|((unsigned int)pointer[4]))); 38438690Sborman for (i = 5; i < length; i++) 38538690Sborman fprintf(NetTrace, " ?%d?", pointer[i]); 38638690Sborman break; 38738690Sborman 388*57213Sdab #if defined(AUTHENTICATION) 38943320Skfall case TELOPT_AUTHENTICATION: 39046808Sdab fprintf(NetTrace, "AUTHENTICATION"); 39146808Sdab if (length < 2) { 39246808Sdab fprintf(NetTrace, " (empty suboption???)"); 39346808Sdab break; 39446808Sdab } 39543320Skfall switch (pointer[1]) { 39646808Sdab case TELQUAL_REPLY: 39743320Skfall case TELQUAL_IS: 39846808Sdab fprintf(NetTrace, " %s ", (pointer[1] == TELQUAL_IS) ? 39946808Sdab "IS" : "REPLY"); 40046808Sdab if (AUTHTYPE_NAME_OK(pointer[2])) 40146808Sdab fprintf(NetTrace, "%s ", AUTHTYPE_NAME(pointer[2])); 40246808Sdab else 40346808Sdab fprintf(NetTrace, "%d ", pointer[2]); 40446808Sdab if (length < 3) { 40546808Sdab fprintf(NetTrace, "(partial suboption???)"); 40646808Sdab break; 40746808Sdab } 40846808Sdab fprintf(NetTrace, "%s|%s", 40947608Sdab ((pointer[3] & AUTH_WHO_MASK) == AUTH_WHO_CLIENT) ? 41046808Sdab "CLIENT" : "SERVER", 41147608Sdab ((pointer[3] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) ? 41246808Sdab "MUTUAL" : "ONE-WAY"); 41343320Skfall 41446808Sdab auth_printsub(&pointer[1], length - 1, buf, sizeof(buf)); 41546808Sdab fprintf(NetTrace, "%s", buf); 41646808Sdab break; 41746808Sdab 41846808Sdab case TELQUAL_SEND: 41946808Sdab i = 2; 42046808Sdab fprintf(NetTrace, " SEND "); 42146808Sdab while (i < length) { 42246808Sdab if (AUTHTYPE_NAME_OK(pointer[i])) 42346808Sdab fprintf(NetTrace, "%s ", AUTHTYPE_NAME(pointer[i])); 42446808Sdab else 42546808Sdab fprintf(NetTrace, "%d ", pointer[i]); 42646808Sdab if (++i >= length) { 42746808Sdab fprintf(NetTrace, "(partial suboption???)"); 42843320Skfall break; 42946808Sdab } 43046808Sdab fprintf(NetTrace, "%s|%s ", 43147608Sdab ((pointer[i] & AUTH_WHO_MASK) == AUTH_WHO_CLIENT) ? 43246808Sdab "CLIENT" : "SERVER", 43347608Sdab ((pointer[i] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) ? 43446808Sdab "MUTUAL" : "ONE-WAY"); 43546808Sdab ++i; 43643320Skfall } 43746808Sdab break; 43843320Skfall 43947608Sdab case TELQUAL_NAME: 44047608Sdab i = 2; 44147608Sdab fprintf(NetTrace, " NAME \""); 44247608Sdab while (i < length) 44347608Sdab putc(pointer[i++], NetTrace); 44447608Sdab putc('"', NetTrace); 44547608Sdab break; 44647608Sdab 44746808Sdab default: 44846808Sdab for (i = 2; i < length; i++) 44946808Sdab fprintf(NetTrace, " ?%d?", pointer[i]); 45046808Sdab break; 45143320Skfall } 45246808Sdab break; 45346808Sdab #endif 45446808Sdab 455*57213Sdab #if defined(ENCRYPTION) 45646808Sdab case TELOPT_ENCRYPT: 45746808Sdab fprintf(NetTrace, "ENCRYPT"); 45846808Sdab if (length < 2) { 45946808Sdab fprintf(NetTrace, " (empty suboption???)"); 46043320Skfall break; 46146808Sdab } 46246808Sdab switch (pointer[1]) { 46346808Sdab case ENCRYPT_START: 46446808Sdab fprintf(NetTrace, " START"); 46546808Sdab break; 46643320Skfall 46746808Sdab case ENCRYPT_END: 46846808Sdab fprintf(NetTrace, " END"); 46946808Sdab break; 47046808Sdab 47146808Sdab case ENCRYPT_REQSTART: 47246808Sdab fprintf(NetTrace, " REQUEST-START"); 47346808Sdab break; 47446808Sdab 47546808Sdab case ENCRYPT_REQEND: 47646808Sdab fprintf(NetTrace, " REQUEST-END"); 47746808Sdab break; 47846808Sdab 47946808Sdab case ENCRYPT_IS: 48046808Sdab case ENCRYPT_REPLY: 48146808Sdab fprintf(NetTrace, " %s ", (pointer[1] == ENCRYPT_IS) ? 48246808Sdab "IS" : "REPLY"); 48346808Sdab if (length < 3) { 48446808Sdab fprintf(NetTrace, " (partial suboption???)"); 48546808Sdab break; 48646808Sdab } 48746808Sdab if (ENCTYPE_NAME_OK(pointer[2])) 48846808Sdab fprintf(NetTrace, "%s ", ENCTYPE_NAME(pointer[2])); 48946808Sdab else 49046808Sdab fprintf(NetTrace, " %d (unknown)", pointer[2]); 49146808Sdab 49246808Sdab encrypt_printsub(&pointer[1], length - 1, buf, sizeof(buf)); 49346808Sdab fprintf(NetTrace, "%s", buf); 49446808Sdab break; 49546808Sdab 49646808Sdab case ENCRYPT_SUPPORT: 49746808Sdab i = 2; 49846808Sdab fprintf(NetTrace, " SUPPORT "); 49946808Sdab while (i < length) { 50046808Sdab if (ENCTYPE_NAME_OK(pointer[i])) 50146808Sdab fprintf(NetTrace, "%s ", ENCTYPE_NAME(pointer[i])); 50246808Sdab else 50346808Sdab fprintf(NetTrace, "%d ", pointer[i]); 50446808Sdab i++; 50546808Sdab } 50646808Sdab break; 50746808Sdab 50847608Sdab case ENCRYPT_ENC_KEYID: 50947608Sdab fprintf(NetTrace, " ENC_KEYID "); 51047608Sdab goto encommon; 51147608Sdab 51247608Sdab case ENCRYPT_DEC_KEYID: 51347608Sdab fprintf(NetTrace, " DEC_KEYID "); 51447608Sdab goto encommon; 51547608Sdab 51643320Skfall default: 51747608Sdab fprintf(NetTrace, " %d (unknown)", pointer[1]); 51847608Sdab encommon: 51946808Sdab for (i = 2; i < length; i++) 52046808Sdab fprintf(NetTrace, " %d", pointer[i]); 52146808Sdab break; 52243320Skfall } 52343320Skfall break; 52446808Sdab #endif 52543320Skfall 52638690Sborman case TELOPT_LINEMODE: 52738690Sborman fprintf(NetTrace, "LINEMODE "); 52838690Sborman if (length < 2) { 52938690Sborman fprintf(NetTrace, " (empty suboption???)"); 53038690Sborman break; 53138690Sborman } 53238690Sborman switch (pointer[1]) { 53338690Sborman case WILL: 53438690Sborman fprintf(NetTrace, "WILL "); 53538690Sborman goto common; 53638690Sborman case WONT: 53738690Sborman fprintf(NetTrace, "WONT "); 53838690Sborman goto common; 53938690Sborman case DO: 54038690Sborman fprintf(NetTrace, "DO "); 54138690Sborman goto common; 54238690Sborman case DONT: 54338690Sborman fprintf(NetTrace, "DONT "); 54438690Sborman common: 54538690Sborman if (length < 3) { 54638690Sborman fprintf(NetTrace, "(no option???)"); 54738690Sborman break; 54838690Sborman } 54938690Sborman switch (pointer[2]) { 55038690Sborman case LM_FORWARDMASK: 55138690Sborman fprintf(NetTrace, "Forward Mask"); 55238690Sborman for (i = 3; i < length; i++) 55338690Sborman fprintf(NetTrace, " %x", pointer[i]); 55438690Sborman break; 55538690Sborman default: 55638690Sborman fprintf(NetTrace, "%d (unknown)", pointer[2]); 55738690Sborman for (i = 3; i < length; i++) 55838690Sborman fprintf(NetTrace, " %d", pointer[i]); 55938690Sborman break; 56038690Sborman } 56138690Sborman break; 56238690Sborman 56338690Sborman case LM_SLC: 56438690Sborman fprintf(NetTrace, "SLC"); 56538690Sborman for (i = 2; i < length - 2; i += 3) { 56646808Sdab if (SLC_NAME_OK(pointer[i+SLC_FUNC])) 56746808Sdab fprintf(NetTrace, " %s", SLC_NAME(pointer[i+SLC_FUNC])); 56838690Sborman else 56938690Sborman fprintf(NetTrace, " %d", pointer[i+SLC_FUNC]); 57038690Sborman switch (pointer[i+SLC_FLAGS]&SLC_LEVELBITS) { 57138690Sborman case SLC_NOSUPPORT: 57238690Sborman fprintf(NetTrace, " NOSUPPORT"); break; 57338690Sborman case SLC_CANTCHANGE: 57438690Sborman fprintf(NetTrace, " CANTCHANGE"); break; 57538690Sborman case SLC_VARIABLE: 57638690Sborman fprintf(NetTrace, " VARIABLE"); break; 57738690Sborman case SLC_DEFAULT: 57838690Sborman fprintf(NetTrace, " DEFAULT"); break; 57938690Sborman } 58038690Sborman fprintf(NetTrace, "%s%s%s", 58138690Sborman pointer[i+SLC_FLAGS]&SLC_ACK ? "|ACK" : "", 58238690Sborman pointer[i+SLC_FLAGS]&SLC_FLUSHIN ? "|FLUSHIN" : "", 58338690Sborman pointer[i+SLC_FLAGS]&SLC_FLUSHOUT ? "|FLUSHOUT" : ""); 58438690Sborman if (pointer[i+SLC_FLAGS]& ~(SLC_ACK|SLC_FLUSHIN| 58538690Sborman SLC_FLUSHOUT| SLC_LEVELBITS)) 58638690Sborman fprintf(NetTrace, "(0x%x)", pointer[i+SLC_FLAGS]); 58738690Sborman fprintf(NetTrace, " %d;", pointer[i+SLC_VALUE]); 58844361Sborman if ((pointer[i+SLC_VALUE] == IAC) && 58944361Sborman (pointer[i+SLC_VALUE+1] == IAC)) 59044361Sborman i++; 59138690Sborman } 59238690Sborman for (; i < length; i++) 59338690Sborman fprintf(NetTrace, " ?%d?", pointer[i]); 59438690Sborman break; 59538690Sborman 59638690Sborman case LM_MODE: 59738690Sborman fprintf(NetTrace, "MODE "); 59838690Sborman if (length < 3) { 59938690Sborman fprintf(NetTrace, "(no mode???)"); 60038690Sborman break; 60138690Sborman } 60238690Sborman { 60344361Sborman char tbuf[64]; 60444361Sborman sprintf(tbuf, "%s%s%s%s%s", 60538690Sborman pointer[2]&MODE_EDIT ? "|EDIT" : "", 60638690Sborman pointer[2]&MODE_TRAPSIG ? "|TRAPSIG" : "", 60744361Sborman pointer[2]&MODE_SOFT_TAB ? "|SOFT_TAB" : "", 60844361Sborman pointer[2]&MODE_LIT_ECHO ? "|LIT_ECHO" : "", 60938690Sborman pointer[2]&MODE_ACK ? "|ACK" : ""); 61038690Sborman fprintf(NetTrace, "%s", tbuf[1] ? &tbuf[1] : "0"); 61138690Sborman } 61246808Sdab if (pointer[2]&~(MODE_MASK)) 61338690Sborman fprintf(NetTrace, " (0x%x)", pointer[2]); 61438690Sborman for (i = 3; i < length; i++) 61538690Sborman fprintf(NetTrace, " ?0x%x?", pointer[i]); 61638690Sborman break; 61738690Sborman default: 61838690Sborman fprintf(NetTrace, "%d (unknown)", pointer[1]); 61938690Sborman for (i = 2; i < length; i++) 62038690Sborman fprintf(NetTrace, " %d", pointer[i]); 62138690Sborman } 62238690Sborman break; 62338690Sborman 62438909Sborman case TELOPT_STATUS: { 62538909Sborman register char *cp; 62638909Sborman register int j, k; 62738909Sborman 62838909Sborman fprintf(NetTrace, "STATUS"); 62938909Sborman 63038909Sborman switch (pointer[1]) { 63138909Sborman default: 63238909Sborman if (pointer[1] == TELQUAL_SEND) 63338909Sborman fprintf(NetTrace, " SEND"); 63438909Sborman else 63544361Sborman fprintf(NetTrace, " %d (unknown)", pointer[1]); 63638909Sborman for (i = 2; i < length; i++) 63738909Sborman fprintf(NetTrace, " ?%d?", pointer[i]); 63838909Sborman break; 63938909Sborman case TELQUAL_IS: 64046808Sdab if (--want_status_response < 0) 64146808Sdab want_status_response = 0; 64238909Sborman if (NetTrace == stdout) 64338909Sborman fprintf(NetTrace, " IS\r\n"); 64438909Sborman else 64538909Sborman fprintf(NetTrace, " IS\n"); 64638909Sborman 64738909Sborman for (i = 2; i < length; i++) { 64838909Sborman switch(pointer[i]) { 64938909Sborman case DO: cp = "DO"; goto common2; 65038909Sborman case DONT: cp = "DONT"; goto common2; 65138909Sborman case WILL: cp = "WILL"; goto common2; 65238909Sborman case WONT: cp = "WONT"; goto common2; 65338909Sborman common2: 65438909Sborman i++; 65544361Sborman if (TELOPT_OK((int)pointer[i])) 65638909Sborman fprintf(NetTrace, " %s %s", cp, TELOPT(pointer[i])); 65738909Sborman else 65838909Sborman fprintf(NetTrace, " %s %d", cp, pointer[i]); 65938909Sborman 66038909Sborman if (NetTrace == stdout) 66138909Sborman fprintf(NetTrace, "\r\n"); 66238909Sborman else 66338909Sborman fprintf(NetTrace, "\n"); 66438909Sborman break; 66538909Sborman 66638909Sborman case SB: 66738909Sborman fprintf(NetTrace, " SB "); 66838909Sborman i++; 66938909Sborman j = k = i; 67038909Sborman while (j < length) { 67138909Sborman if (pointer[j] == SE) { 67238909Sborman if (j+1 == length) 67338909Sborman break; 67438909Sborman if (pointer[j+1] == SE) 67538909Sborman j++; 67638909Sborman else 67738909Sborman break; 67838909Sborman } 67938909Sborman pointer[k++] = pointer[j++]; 68038909Sborman } 68138909Sborman printsub(0, &pointer[i], k - i); 68238909Sborman if (i < length) { 68338909Sborman fprintf(NetTrace, " SE"); 68438909Sborman i = j; 68538909Sborman } else 68638909Sborman i = j - 1; 68738909Sborman 68838909Sborman if (NetTrace == stdout) 68938909Sborman fprintf(NetTrace, "\r\n"); 69038909Sborman else 69138909Sborman fprintf(NetTrace, "\n"); 69238909Sborman 69338909Sborman break; 69438909Sborman 69538909Sborman default: 69638909Sborman fprintf(NetTrace, " %d", pointer[i]); 69738909Sborman break; 69838909Sborman } 69938909Sborman } 70038909Sborman break; 70138909Sborman } 70238909Sborman break; 70338909Sborman } 70438909Sborman 70544361Sborman case TELOPT_XDISPLOC: 70644361Sborman fprintf(NetTrace, "X-DISPLAY-LOCATION "); 70744361Sborman switch (pointer[1]) { 70844361Sborman case TELQUAL_IS: 70944361Sborman fprintf(NetTrace, "IS \"%.*s\"", length-2, (char *)pointer+2); 71044361Sborman break; 71144361Sborman case TELQUAL_SEND: 71244361Sborman fprintf(NetTrace, "SEND"); 71344361Sborman break; 71444361Sborman default: 71544361Sborman fprintf(NetTrace, "- unknown qualifier %d (0x%x).", 71644361Sborman pointer[1], pointer[1]); 71744361Sborman } 71844361Sborman break; 71944361Sborman 72044361Sborman case TELOPT_ENVIRON: 72144361Sborman fprintf(NetTrace, "ENVIRON "); 72244361Sborman switch (pointer[1]) { 72344361Sborman case TELQUAL_IS: 72444361Sborman fprintf(NetTrace, "IS "); 72544361Sborman goto env_common; 72644361Sborman case TELQUAL_SEND: 72744361Sborman fprintf(NetTrace, "SEND "); 72844361Sborman goto env_common; 72944361Sborman case TELQUAL_INFO: 73044361Sborman fprintf(NetTrace, "INFO "); 73144361Sborman env_common: 73244361Sborman { 73344361Sborman register int noquote = 2; 73444361Sborman for (i = 2; i < length; i++ ) { 73544361Sborman switch (pointer[i]) { 73644361Sborman case ENV_VAR: 73744361Sborman if (pointer[1] == TELQUAL_SEND) 73844361Sborman goto def_case; 73944361Sborman fprintf(NetTrace, "\" VAR " + noquote); 74044361Sborman noquote = 2; 74144361Sborman break; 74244361Sborman 74344361Sborman case ENV_VALUE: 74444361Sborman fprintf(NetTrace, "\" VALUE " + noquote); 74544361Sborman noquote = 2; 74644361Sborman break; 74744361Sborman 74844361Sborman case ENV_ESC: 74944361Sborman fprintf(NetTrace, "\" ESC " + noquote); 75044361Sborman noquote = 2; 75144361Sborman break; 75244361Sborman 753*57213Sdab case ENV_USERVAR: 754*57213Sdab if (pointer[1] == TELQUAL_SEND) 755*57213Sdab goto def_case; 756*57213Sdab fprintf(NetTrace, "\" USERVAR " + noquote); 757*57213Sdab noquote = 2; 758*57213Sdab break; 759*57213Sdab 76044361Sborman default: 76144361Sborman def_case: 76244361Sborman if (isprint(pointer[i]) && pointer[i] != '"') { 76344361Sborman if (noquote) { 76444361Sborman putc('"', NetTrace); 76544361Sborman noquote = 0; 76644361Sborman } 76744361Sborman putc(pointer[i], NetTrace); 76844361Sborman } else { 76944361Sborman fprintf(NetTrace, "\" %03o " + noquote, 77044361Sborman pointer[i]); 77144361Sborman noquote = 2; 77244361Sborman } 77344361Sborman break; 77444361Sborman } 77544361Sborman } 77644361Sborman if (!noquote) 77744361Sborman putc('"', NetTrace); 77844361Sborman break; 77944361Sborman } 78044361Sborman } 78144361Sborman break; 78244361Sborman 78332149Sminshall default: 78446808Sdab if (TELOPT_OK(pointer[0])) 78546808Sdab fprintf(NetTrace, "%s (unknown)", TELOPT(pointer[0])); 78646808Sdab else 78756860Storek fprintf(NetTrace, "%d (unknown)", pointer[0]); 78846808Sdab for (i = 1; i < length; i++) 78938690Sborman fprintf(NetTrace, " %d", pointer[i]); 79038690Sborman break; 79132149Sminshall } 79238909Sborman if (direction) { 79338909Sborman if (NetTrace == stdout) 79438909Sborman fprintf(NetTrace, "\r\n"); 79538909Sborman else 79638909Sborman fprintf(NetTrace, "\n"); 79738909Sborman } 79832149Sminshall } 79932149Sminshall } 80036278Sminshall 80136278Sminshall /* EmptyTerminal - called to make sure that the terminal buffer is empty. 80236278Sminshall * Note that we consider the buffer to run all the 80336278Sminshall * way to the kernel (thus the select). 80436278Sminshall */ 80536278Sminshall 80646808Sdab void 80736278Sminshall EmptyTerminal() 80836278Sminshall { 80936278Sminshall #if defined(unix) 81036278Sminshall fd_set o; 81136278Sminshall 81236278Sminshall FD_ZERO(&o); 81336278Sminshall #endif /* defined(unix) */ 81436278Sminshall 81536278Sminshall if (TTYBYTES() == 0) { 81636278Sminshall #if defined(unix) 81736278Sminshall FD_SET(tout, &o); 81836278Sminshall (void) select(tout+1, (fd_set *) 0, &o, (fd_set *) 0, 81936278Sminshall (struct timeval *) 0); /* wait for TTLOWAT */ 82036278Sminshall #endif /* defined(unix) */ 82136278Sminshall } else { 82236278Sminshall while (TTYBYTES()) { 82344361Sborman (void) ttyflush(0); 82436278Sminshall #if defined(unix) 82536278Sminshall FD_SET(tout, &o); 82636278Sminshall (void) select(tout+1, (fd_set *) 0, &o, (fd_set *) 0, 82736278Sminshall (struct timeval *) 0); /* wait for TTLOWAT */ 82836278Sminshall #endif /* defined(unix) */ 82936278Sminshall } 83036278Sminshall } 83136278Sminshall } 83236278Sminshall 83346808Sdab void 83436278Sminshall SetForExit() 83536278Sminshall { 83638690Sborman setconnmode(0); 83736278Sminshall #if defined(TN3270) 83836278Sminshall if (In3270) { 83936278Sminshall Finish3270(); 84036278Sminshall } 84136279Sminshall #else /* defined(TN3270) */ 84236279Sminshall do { 84344361Sborman (void)telrcv(); /* Process any incoming data */ 84436279Sminshall EmptyTerminal(); 84536279Sminshall } while (ring_full_count(&netiring)); /* While there is any */ 84636278Sminshall #endif /* defined(TN3270) */ 84736278Sminshall setcommandmode(); 84836278Sminshall fflush(stdout); 84936278Sminshall fflush(stderr); 85036278Sminshall #if defined(TN3270) 85136278Sminshall if (In3270) { 85236278Sminshall StopScreen(1); 85336278Sminshall } 85436278Sminshall #endif /* defined(TN3270) */ 85538690Sborman setconnmode(0); 85636278Sminshall EmptyTerminal(); /* Flush the path to the tty */ 85736278Sminshall setcommandmode(); 85836278Sminshall } 85936278Sminshall 86046808Sdab void 86136278Sminshall Exit(returnCode) 86246808Sdab int returnCode; 86336278Sminshall { 86436278Sminshall SetForExit(); 86536278Sminshall exit(returnCode); 86636278Sminshall } 86736278Sminshall 86846808Sdab void 86936278Sminshall ExitString(string, returnCode) 87046808Sdab char *string; 87146808Sdab int returnCode; 87236278Sminshall { 87336278Sminshall SetForExit(); 87436278Sminshall fwrite(string, 1, strlen(string), stderr); 87536278Sminshall exit(returnCode); 87636278Sminshall } 877