138905Sborman /* 2*61451Sbostic * Copyright (c) 1989, 1993 3*61451Sbostic * The Regents of the University of California. All rights reserved. 438905Sborman * 542673Sbostic * %sccs.include.redist.c% 638905Sborman */ 738905Sborman 838905Sborman #ifndef lint 9*61451Sbostic static char sccsid[] = "@(#)utility.c 8.1 (Berkeley) 06/04/93"; 1038905Sborman #endif /* not lint */ 1138905Sborman 1244364Sborman #define PRINTOPTIONS 1338905Sborman #include "telnetd.h" 1438905Sborman 1538905Sborman /* 1638905Sborman * utility functions performing io related tasks 1738905Sborman */ 1838905Sborman 1938905Sborman /* 2038905Sborman * ttloop 2138905Sborman * 2238905Sborman * A small subroutine to flush the network output buffer, get some data 2338905Sborman * from the network, and pass it through the telnet state machine. We 2438905Sborman * also flush the pty input buffer (by dropping its data) if it becomes 2538905Sborman * too full. 2638905Sborman */ 2738905Sborman 2846809Sdab void 2938905Sborman ttloop() 3038905Sborman { 3138905Sborman void netflush(); 3238905Sborman 3346809Sdab DIAG(TD_REPORT, {sprintf(nfrontp, "td: ttloop\r\n"); 3446809Sdab nfrontp += strlen(nfrontp);}); 3538905Sborman if (nfrontp-nbackp) { 3638905Sborman netflush(); 3738905Sborman } 3838905Sborman ncc = read(net, netibuf, sizeof netibuf); 3938905Sborman if (ncc < 0) { 4038905Sborman syslog(LOG_INFO, "ttloop: read: %m\n"); 4138905Sborman exit(1); 4238905Sborman } else if (ncc == 0) { 4338905Sborman syslog(LOG_INFO, "ttloop: peer died: %m\n"); 4438905Sborman exit(1); 4538905Sborman } 4646809Sdab DIAG(TD_REPORT, {sprintf(nfrontp, "td: ttloop read %d chars\r\n", ncc); 4746809Sdab nfrontp += strlen(nfrontp);}); 4838905Sborman netip = netibuf; 4938905Sborman telrcv(); /* state machine */ 5038905Sborman if (ncc > 0) { 5138905Sborman pfrontp = pbackp = ptyobuf; 5238905Sborman telrcv(); 5338905Sborman } 5438905Sborman } /* end of ttloop */ 5538905Sborman 5638905Sborman /* 5738905Sborman * Check a descriptor to see if out of band data exists on it. 5838905Sborman */ 5946809Sdab int 6038905Sborman stilloob(s) 6146809Sdab int s; /* socket number */ 6238905Sborman { 6338905Sborman static struct timeval timeout = { 0 }; 6438905Sborman fd_set excepts; 6538905Sborman int value; 6638905Sborman 6738905Sborman do { 6838905Sborman FD_ZERO(&excepts); 6938905Sborman FD_SET(s, &excepts); 7038905Sborman value = select(s+1, (fd_set *)0, (fd_set *)0, &excepts, &timeout); 7138905Sborman } while ((value == -1) && (errno == EINTR)); 7238905Sborman 7338905Sborman if (value < 0) { 7438905Sborman fatalperror(pty, "select"); 7538905Sborman } 7638905Sborman if (FD_ISSET(s, &excepts)) { 7738905Sborman return 1; 7838905Sborman } else { 7938905Sborman return 0; 8038905Sborman } 8138905Sborman } 8238905Sborman 8346809Sdab void 8438905Sborman ptyflush() 8538905Sborman { 8638905Sborman int n; 8738905Sborman 8844364Sborman if ((n = pfrontp - pbackp) > 0) { 8946809Sdab DIAG((TD_REPORT | TD_PTYDATA), 9046809Sdab { sprintf(nfrontp, "td: ptyflush %d chars\r\n", n); 9146809Sdab nfrontp += strlen(nfrontp); }); 9246809Sdab DIAG(TD_PTYDATA, printdata("pd", pbackp, n)); 9338905Sborman n = write(pty, pbackp, n); 9444364Sborman } 9546809Sdab if (n < 0) { 9646809Sdab if (errno == EWOULDBLOCK || errno == EINTR) 9746809Sdab return; 9846809Sdab cleanup(0); 9946809Sdab } 10038905Sborman pbackp += n; 10138905Sborman if (pbackp == pfrontp) 10238905Sborman pbackp = pfrontp = ptyobuf; 10338905Sborman } 10438905Sborman 10538905Sborman /* 10638905Sborman * nextitem() 10738905Sborman * 10838905Sborman * Return the address of the next "item" in the TELNET data 10938905Sborman * stream. This will be the address of the next character if 11038905Sborman * the current address is a user data character, or it will 11138905Sborman * be the address of the character following the TELNET command 11238905Sborman * if the current address is a TELNET IAC ("I Am a Command") 11338905Sborman * character. 11438905Sborman */ 11546809Sdab char * 11638905Sborman nextitem(current) 11746809Sdab char *current; 11838905Sborman { 11938905Sborman if ((*current&0xff) != IAC) { 12038905Sborman return current+1; 12138905Sborman } 12238905Sborman switch (*(current+1)&0xff) { 12338905Sborman case DO: 12438905Sborman case DONT: 12538905Sborman case WILL: 12638905Sborman case WONT: 12738905Sborman return current+3; 12838905Sborman case SB: /* loop forever looking for the SE */ 12938905Sborman { 13038905Sborman register char *look = current+2; 13138905Sborman 13238905Sborman for (;;) { 13338905Sborman if ((*look++&0xff) == IAC) { 13438905Sborman if ((*look++&0xff) == SE) { 13538905Sborman return look; 13638905Sborman } 13738905Sborman } 13838905Sborman } 13938905Sborman } 14038905Sborman default: 14138905Sborman return current+2; 14238905Sborman } 14338905Sborman } /* end of nextitem */ 14438905Sborman 14538905Sborman 14638905Sborman /* 14738905Sborman * netclear() 14838905Sborman * 14938905Sborman * We are about to do a TELNET SYNCH operation. Clear 15038905Sborman * the path to the network. 15138905Sborman * 15238905Sborman * Things are a bit tricky since we may have sent the first 15338905Sborman * byte or so of a previous TELNET command into the network. 15438905Sborman * So, we have to scan the network buffer from the beginning 15538905Sborman * until we are up to where we want to be. 15638905Sborman * 15738905Sborman * A side effect of what we do, just to keep things 15838905Sborman * simple, is to clear the urgent data pointer. The principal 15938905Sborman * caller should be setting the urgent data pointer AFTER calling 16038905Sborman * us in any case. 16138905Sborman */ 16246809Sdab void 16338905Sborman netclear() 16438905Sborman { 16538905Sborman register char *thisitem, *next; 16638905Sborman char *good; 16738905Sborman #define wewant(p) ((nfrontp > p) && ((*p&0xff) == IAC) && \ 16838905Sborman ((*(p+1)&0xff) != EC) && ((*(p+1)&0xff) != EL)) 16938905Sborman 17060151Sdab #ifdef ENCRYPTION 17146809Sdab thisitem = nclearto > netobuf ? nclearto : netobuf; 17260151Sdab #else /* ENCRYPTION */ 17338905Sborman thisitem = netobuf; 17460151Sdab #endif /* ENCRYPTION */ 17538905Sborman 17638905Sborman while ((next = nextitem(thisitem)) <= nbackp) { 17738905Sborman thisitem = next; 17838905Sborman } 17938905Sborman 18038905Sborman /* Now, thisitem is first before/at boundary. */ 18138905Sborman 18260151Sdab #ifdef ENCRYPTION 18346809Sdab good = nclearto > netobuf ? nclearto : netobuf; 18460151Sdab #else /* ENCRYPTION */ 18538905Sborman good = netobuf; /* where the good bytes go */ 18660151Sdab #endif /* ENCRYPTION */ 18738905Sborman 18838905Sborman while (nfrontp > thisitem) { 18938905Sborman if (wewant(thisitem)) { 19038905Sborman int length; 19138905Sborman 19238905Sborman next = thisitem; 19338905Sborman do { 19438905Sborman next = nextitem(next); 19538905Sborman } while (wewant(next) && (nfrontp > next)); 19638905Sborman length = next-thisitem; 19738905Sborman bcopy(thisitem, good, length); 19838905Sborman good += length; 19938905Sborman thisitem = next; 20038905Sborman } else { 20138905Sborman thisitem = nextitem(thisitem); 20238905Sborman } 20338905Sborman } 20438905Sborman 20538905Sborman nbackp = netobuf; 20638905Sborman nfrontp = good; /* next byte to be sent */ 20738905Sborman neturg = 0; 20838905Sborman } /* end of netclear */ 20938905Sborman 21038905Sborman /* 21138905Sborman * netflush 21238905Sborman * Send as much data as possible to the network, 21338905Sborman * handling requests for urgent data. 21438905Sborman */ 21546809Sdab void 21638905Sborman netflush() 21738905Sborman { 21838905Sborman int n; 21938905Sborman extern int not42; 22038905Sborman 22138905Sborman if ((n = nfrontp - nbackp) > 0) { 22246809Sdab DIAG(TD_REPORT, 22346809Sdab { sprintf(nfrontp, "td: netflush %d chars\r\n", n); 22446809Sdab n += strlen(nfrontp); /* get count first */ 22546809Sdab nfrontp += strlen(nfrontp); /* then move pointer */ 22646809Sdab }); 22760151Sdab #ifdef ENCRYPTION 22846809Sdab if (encrypt_output) { 22946809Sdab char *s = nclearto ? nclearto : nbackp; 23046809Sdab if (nfrontp - s > 0) { 23146809Sdab (*encrypt_output)((unsigned char *)s, nfrontp-s); 23246809Sdab nclearto = nfrontp; 23346809Sdab } 23444364Sborman } 23560151Sdab #endif /* ENCRYPTION */ 23638905Sborman /* 23738905Sborman * if no urgent data, or if the other side appears to be an 23838905Sborman * old 4.2 client (and thus unable to survive TCP urgent data), 23938905Sborman * write the entire buffer in non-OOB mode. 24038905Sborman */ 24138905Sborman if ((neturg == 0) || (not42 == 0)) { 24238905Sborman n = write(net, nbackp, n); /* normal write */ 24338905Sborman } else { 24438905Sborman n = neturg - nbackp; 24538905Sborman /* 24638905Sborman * In 4.2 (and 4.3) systems, there is some question about 24738905Sborman * what byte in a sendOOB operation is the "OOB" data. 24838905Sborman * To make ourselves compatible, we only send ONE byte 24938905Sborman * out of band, the one WE THINK should be OOB (though 25038905Sborman * we really have more the TCP philosophy of urgent data 25138905Sborman * rather than the Unix philosophy of OOB data). 25238905Sborman */ 25338905Sborman if (n > 1) { 25438905Sborman n = send(net, nbackp, n-1, 0); /* send URGENT all by itself */ 25538905Sborman } else { 25638905Sborman n = send(net, nbackp, n, MSG_OOB); /* URGENT data */ 25738905Sborman } 25838905Sborman } 25938905Sborman } 26038905Sborman if (n < 0) { 26138905Sborman if (errno == EWOULDBLOCK || errno == EINTR) 26238905Sborman return; 26346809Sdab cleanup(0); 26438905Sborman } 26538905Sborman nbackp += n; 26660151Sdab #ifdef ENCRYPTION 26746809Sdab if (nbackp > nclearto) 26846809Sdab nclearto = 0; 26960151Sdab #endif /* ENCRYPTION */ 27038905Sborman if (nbackp >= neturg) { 27138905Sborman neturg = 0; 27238905Sborman } 27338905Sborman if (nbackp == nfrontp) { 27438905Sborman nbackp = nfrontp = netobuf; 27560151Sdab #ifdef ENCRYPTION 27646809Sdab nclearto = 0; 27760151Sdab #endif /* ENCRYPTION */ 27838905Sborman } 27938905Sborman return; 28038905Sborman } /* end of netflush */ 28138905Sborman 28238905Sborman 28338905Sborman /* 28438905Sborman * writenet 28538905Sborman * 28638905Sborman * Just a handy little function to write a bit of raw data to the net. 28738905Sborman * It will force a transmit of the buffer if necessary 28838905Sborman * 28938905Sborman * arguments 29038905Sborman * ptr - A pointer to a character string to write 29138905Sborman * len - How many bytes to write 29238905Sborman */ 29346809Sdab void 29438905Sborman writenet(ptr, len) 29546809Sdab register unsigned char *ptr; 29646809Sdab register int len; 29738905Sborman { 29838905Sborman /* flush buffer if no room for new data) */ 29938905Sborman if ((&netobuf[BUFSIZ] - nfrontp) < len) { 30038905Sborman /* if this fails, don't worry, buffer is a little big */ 30138905Sborman netflush(); 30238905Sborman } 30338905Sborman 30438905Sborman bcopy(ptr, nfrontp, len); 30538905Sborman nfrontp += len; 30638905Sborman 30738905Sborman } /* end of writenet */ 30838905Sborman 30938905Sborman 31038905Sborman /* 31138905Sborman * miscellaneous functions doing a variety of little jobs follow ... 31238905Sborman */ 31338905Sborman 31438905Sborman 31546809Sdab void 31638905Sborman fatal(f, msg) 31738905Sborman int f; 31838905Sborman char *msg; 31938905Sborman { 32038905Sborman char buf[BUFSIZ]; 32138905Sborman 32238905Sborman (void) sprintf(buf, "telnetd: %s.\r\n", msg); 32360151Sdab #ifdef ENCRYPTION 32446809Sdab if (encrypt_output) { 32546809Sdab /* 32646809Sdab * Better turn off encryption first.... 32746809Sdab * Hope it flushes... 32846809Sdab */ 32946809Sdab encrypt_send_end(); 33046809Sdab netflush(); 33146809Sdab } 33260151Sdab #endif /* ENCRYPTION */ 33338905Sborman (void) write(f, buf, (int)strlen(buf)); 33438905Sborman sleep(1); /*XXX*/ 33538905Sborman exit(1); 33638905Sborman } 33738905Sborman 33846809Sdab void 33938905Sborman fatalperror(f, msg) 34038905Sborman int f; 34138905Sborman char *msg; 34238905Sborman { 34342411Sbostic char buf[BUFSIZ], *strerror(); 34438905Sborman 34542411Sbostic (void) sprintf(buf, "%s: %s\r\n", msg, strerror(errno)); 34638905Sborman fatal(f, buf); 34738905Sborman } 34838905Sborman 34938905Sborman char editedhost[32]; 35038905Sborman 35146809Sdab void 35238905Sborman edithost(pat, host) 35338905Sborman register char *pat; 35438905Sborman register char *host; 35538905Sborman { 35638905Sborman register char *res = editedhost; 35738905Sborman char *strncpy(); 35838905Sborman 35938905Sborman if (!pat) 36038905Sborman pat = ""; 36138905Sborman while (*pat) { 36238905Sborman switch (*pat) { 36338905Sborman 36438905Sborman case '#': 36538905Sborman if (*host) 36638905Sborman host++; 36738905Sborman break; 36838905Sborman 36938905Sborman case '@': 37038905Sborman if (*host) 37138905Sborman *res++ = *host++; 37238905Sborman break; 37338905Sborman 37438905Sborman default: 37538905Sborman *res++ = *pat; 37638905Sborman break; 37738905Sborman } 37838905Sborman if (res == &editedhost[sizeof editedhost - 1]) { 37938905Sborman *res = '\0'; 38038905Sborman return; 38138905Sborman } 38238905Sborman pat++; 38338905Sborman } 38438905Sborman if (*host) 38538905Sborman (void) strncpy(res, host, 38638905Sborman sizeof editedhost - (res - editedhost) -1); 38738905Sborman else 38838905Sborman *res = '\0'; 38938905Sborman editedhost[sizeof editedhost - 1] = '\0'; 39038905Sborman } 39138905Sborman 39238905Sborman static char *putlocation; 39338905Sborman 39446809Sdab void 39538905Sborman putstr(s) 39646809Sdab register char *s; 39738905Sborman { 39838905Sborman 39938905Sborman while (*s) 40038905Sborman putchr(*s++); 40138905Sborman } 40238905Sborman 40346809Sdab void 40438905Sborman putchr(cc) 40546809Sdab int cc; 40638905Sborman { 40738905Sborman *putlocation++ = cc; 40838905Sborman } 40938905Sborman 41046809Sdab /* 41146809Sdab * This is split on two lines so that SCCS will not see the M 41246809Sdab * between two % signs and expand it... 41346809Sdab */ 41446809Sdab static char fmtstr[] = { "%l:%M\ 41546809Sdab %P on %A, %d %B %Y" }; 41646809Sdab 41746809Sdab void 41838905Sborman putf(cp, where) 41946809Sdab register char *cp; 42046809Sdab char *where; 42138905Sborman { 42246809Sdab char *slash; 42346123Sbostic time_t t; 42446809Sdab char db[100]; 42538905Sborman extern char *rindex(); 42638905Sborman 42738905Sborman putlocation = where; 42838905Sborman 42938905Sborman while (*cp) { 43038905Sborman if (*cp != '%') { 43138905Sborman putchr(*cp++); 43238905Sborman continue; 43338905Sborman } 43438905Sborman switch (*++cp) { 43538905Sborman 43638905Sborman case 't': 43757212Sdab #ifdef STREAMSPTY 43857212Sdab /* names are like /dev/pts/2 -- we want pts/2 */ 43957212Sdab slash = index(line+1, '/'); 44057212Sdab #else 44138905Sborman slash = rindex(line, '/'); 44257212Sdab #endif 44338905Sborman if (slash == (char *) 0) 44438905Sborman putstr(line); 44538905Sborman else 44638905Sborman putstr(&slash[1]); 44738905Sborman break; 44838905Sborman 44938905Sborman case 'h': 45038905Sborman putstr(editedhost); 45138905Sborman break; 45238905Sborman 45346809Sdab case 'd': 45446123Sbostic (void)time(&t); 45546809Sdab (void)strftime(db, sizeof(db), fmtstr, localtime(&t)); 45646123Sbostic putstr(db); 45738905Sborman break; 45838905Sborman 45938905Sborman case '%': 46038905Sborman putchr('%'); 46138905Sborman break; 46238905Sborman } 46338905Sborman cp++; 46438905Sborman } 46538905Sborman } 46638905Sborman 46744364Sborman #ifdef DIAGNOSTICS 46844364Sborman /* 46944364Sborman * Print telnet options and commands in plain text, if possible. 47044364Sborman */ 47146809Sdab void 47244364Sborman printoption(fmt, option) 47346809Sdab register char *fmt; 47446809Sdab register int option; 47544364Sborman { 47644364Sborman if (TELOPT_OK(option)) 47744364Sborman sprintf(nfrontp, "%s %s\r\n", fmt, TELOPT(option)); 47844364Sborman else if (TELCMD_OK(option)) 47944364Sborman sprintf(nfrontp, "%s %s\r\n", fmt, TELCMD(option)); 48044364Sborman else 48144364Sborman sprintf(nfrontp, "%s %d\r\n", fmt, option); 48244364Sborman nfrontp += strlen(nfrontp); 48344364Sborman return; 48444364Sborman } 48544364Sborman 48646809Sdab void 48746809Sdab printsub(direction, pointer, length) 48846809Sdab char direction; /* '<' or '>' */ 48946809Sdab unsigned char *pointer; /* where suboption data sits */ 49046809Sdab int length; /* length of suboption data */ 49144364Sborman { 49244364Sborman register int i; 49347611Sdab char buf[512]; 49444364Sborman 49546809Sdab if (!(diagnostic & TD_OPTIONS)) 49646809Sdab return; 49746809Sdab 49846809Sdab if (direction) { 49946809Sdab sprintf(nfrontp, "td: %s suboption ", 50046809Sdab direction == '<' ? "recv" : "send"); 50144364Sborman nfrontp += strlen(nfrontp); 50244364Sborman if (length >= 3) { 50344364Sborman register int j; 50444364Sborman 50544364Sborman i = pointer[length-2]; 50644364Sborman j = pointer[length-1]; 50744364Sborman 50844364Sborman if (i != IAC || j != SE) { 50944364Sborman sprintf(nfrontp, "(terminated by "); 51044364Sborman nfrontp += strlen(nfrontp); 51144364Sborman if (TELOPT_OK(i)) 51244364Sborman sprintf(nfrontp, "%s ", TELOPT(i)); 51344364Sborman else if (TELCMD_OK(i)) 51444364Sborman sprintf(nfrontp, "%s ", TELCMD(i)); 51544364Sborman else 51644364Sborman sprintf(nfrontp, "%d ", i); 51744364Sborman nfrontp += strlen(nfrontp); 51844364Sborman if (TELOPT_OK(j)) 51944364Sborman sprintf(nfrontp, "%s", TELOPT(j)); 52044364Sborman else if (TELCMD_OK(j)) 52144364Sborman sprintf(nfrontp, "%s", TELCMD(j)); 52244364Sborman else 52344364Sborman sprintf(nfrontp, "%d", j); 52444364Sborman nfrontp += strlen(nfrontp); 52544364Sborman sprintf(nfrontp, ", not IAC SE!) "); 52644364Sborman nfrontp += strlen(nfrontp); 52744364Sborman } 52844364Sborman } 52944364Sborman length -= 2; 53044364Sborman } 53144364Sborman if (length < 1) { 53244364Sborman sprintf(nfrontp, "(Empty suboption???)"); 53344364Sborman nfrontp += strlen(nfrontp); 53444364Sborman return; 53544364Sborman } 53644364Sborman switch (pointer[0]) { 53744364Sborman case TELOPT_TTYPE: 53844364Sborman sprintf(nfrontp, "TERMINAL-TYPE "); 53944364Sborman nfrontp += strlen(nfrontp); 54044364Sborman switch (pointer[1]) { 54144364Sborman case TELQUAL_IS: 54244364Sborman sprintf(nfrontp, "IS \"%.*s\"", length-2, (char *)pointer+2); 54344364Sborman break; 54444364Sborman case TELQUAL_SEND: 54544364Sborman sprintf(nfrontp, "SEND"); 54644364Sborman break; 54744364Sborman default: 54844364Sborman sprintf(nfrontp, 54944364Sborman "- unknown qualifier %d (0x%x).", 55044364Sborman pointer[1], pointer[1]); 55144364Sborman } 55244364Sborman nfrontp += strlen(nfrontp); 55344364Sborman break; 55444364Sborman case TELOPT_TSPEED: 55544364Sborman sprintf(nfrontp, "TERMINAL-SPEED"); 55644364Sborman nfrontp += strlen(nfrontp); 55744364Sborman if (length < 2) { 55844364Sborman sprintf(nfrontp, " (empty suboption???)"); 55944364Sborman nfrontp += strlen(nfrontp); 56044364Sborman break; 56144364Sborman } 56244364Sborman switch (pointer[1]) { 56344364Sborman case TELQUAL_IS: 56444364Sborman sprintf(nfrontp, " IS %.*s", length-2, (char *)pointer+2); 56544364Sborman nfrontp += strlen(nfrontp); 56644364Sborman break; 56744364Sborman default: 56844364Sborman if (pointer[1] == 1) 56944364Sborman sprintf(nfrontp, " SEND"); 57044364Sborman else 57144364Sborman sprintf(nfrontp, " %d (unknown)", pointer[1]); 57244364Sborman nfrontp += strlen(nfrontp); 57344364Sborman for (i = 2; i < length; i++) { 57444364Sborman sprintf(nfrontp, " ?%d?", pointer[i]); 57544364Sborman nfrontp += strlen(nfrontp); 57644364Sborman } 57744364Sborman break; 57844364Sborman } 57944364Sborman break; 58044364Sborman 58144364Sborman case TELOPT_LFLOW: 58244364Sborman sprintf(nfrontp, "TOGGLE-FLOW-CONTROL"); 58344364Sborman nfrontp += strlen(nfrontp); 58444364Sborman if (length < 2) { 58544364Sborman sprintf(nfrontp, " (empty suboption???)"); 58644364Sborman nfrontp += strlen(nfrontp); 58744364Sborman break; 58844364Sborman } 58944364Sborman switch (pointer[1]) { 59057597Sdab case LFLOW_OFF: 59144364Sborman sprintf(nfrontp, " OFF"); break; 59257597Sdab case LFLOW_ON: 59344364Sborman sprintf(nfrontp, " ON"); break; 59457597Sdab case LFLOW_RESTART_ANY: 59557597Sdab sprintf(nfrontp, " RESTART-ANY"); break; 59657597Sdab case LFLOW_RESTART_XON: 59757597Sdab sprintf(nfrontp, " RESTART-XON"); break; 59844364Sborman default: 59944364Sborman sprintf(nfrontp, " %d (unknown)", pointer[1]); 60044364Sborman } 60144364Sborman nfrontp += strlen(nfrontp); 60244364Sborman for (i = 2; i < length; i++) { 60344364Sborman sprintf(nfrontp, " ?%d?", pointer[i]); 60444364Sborman nfrontp += strlen(nfrontp); 60544364Sborman } 60644364Sborman break; 60744364Sborman 60844364Sborman case TELOPT_NAWS: 60944364Sborman sprintf(nfrontp, "NAWS"); 61044364Sborman nfrontp += strlen(nfrontp); 61144364Sborman if (length < 2) { 61244364Sborman sprintf(nfrontp, " (empty suboption???)"); 61344364Sborman nfrontp += strlen(nfrontp); 61444364Sborman break; 61544364Sborman } 61644364Sborman if (length == 2) { 61744364Sborman sprintf(nfrontp, " ?%d?", pointer[1]); 61844364Sborman nfrontp += strlen(nfrontp); 61944364Sborman break; 62044364Sborman } 62144364Sborman sprintf(nfrontp, " %d %d (%d)", 62244364Sborman pointer[1], pointer[2], 62344364Sborman (int)((((unsigned int)pointer[1])<<8)|((unsigned int)pointer[2]))); 62444364Sborman nfrontp += strlen(nfrontp); 62544364Sborman if (length == 4) { 62644364Sborman sprintf(nfrontp, " ?%d?", pointer[3]); 62744364Sborman nfrontp += strlen(nfrontp); 62844364Sborman break; 62944364Sborman } 63044364Sborman sprintf(nfrontp, " %d %d (%d)", 63144364Sborman pointer[3], pointer[4], 63244364Sborman (int)((((unsigned int)pointer[3])<<8)|((unsigned int)pointer[4]))); 63344364Sborman nfrontp += strlen(nfrontp); 63444364Sborman for (i = 5; i < length; i++) { 63544364Sborman sprintf(nfrontp, " ?%d?", pointer[i]); 63644364Sborman nfrontp += strlen(nfrontp); 63744364Sborman } 63844364Sborman break; 63944364Sborman 64044364Sborman case TELOPT_LINEMODE: 64144364Sborman sprintf(nfrontp, "LINEMODE "); 64244364Sborman nfrontp += strlen(nfrontp); 64344364Sborman if (length < 2) { 64444364Sborman sprintf(nfrontp, " (empty suboption???)"); 64544364Sborman nfrontp += strlen(nfrontp); 64644364Sborman break; 64744364Sborman } 64844364Sborman switch (pointer[1]) { 64944364Sborman case WILL: 65044364Sborman sprintf(nfrontp, "WILL "); 65144364Sborman goto common; 65244364Sborman case WONT: 65344364Sborman sprintf(nfrontp, "WONT "); 65444364Sborman goto common; 65544364Sborman case DO: 65644364Sborman sprintf(nfrontp, "DO "); 65744364Sborman goto common; 65844364Sborman case DONT: 65944364Sborman sprintf(nfrontp, "DONT "); 66044364Sborman common: 66144364Sborman nfrontp += strlen(nfrontp); 66244364Sborman if (length < 3) { 66344364Sborman sprintf(nfrontp, "(no option???)"); 66444364Sborman nfrontp += strlen(nfrontp); 66544364Sborman break; 66644364Sborman } 66744364Sborman switch (pointer[2]) { 66844364Sborman case LM_FORWARDMASK: 66944364Sborman sprintf(nfrontp, "Forward Mask"); 67044364Sborman nfrontp += strlen(nfrontp); 67144364Sborman for (i = 3; i < length; i++) { 67244364Sborman sprintf(nfrontp, " %x", pointer[i]); 67344364Sborman nfrontp += strlen(nfrontp); 67444364Sborman } 67544364Sborman break; 67644364Sborman default: 67744364Sborman sprintf(nfrontp, "%d (unknown)", pointer[2]); 67844364Sborman nfrontp += strlen(nfrontp); 67944364Sborman for (i = 3; i < length; i++) { 68044364Sborman sprintf(nfrontp, " %d", pointer[i]); 68144364Sborman nfrontp += strlen(nfrontp); 68244364Sborman } 68344364Sborman break; 68444364Sborman } 68544364Sborman break; 68644364Sborman 68744364Sborman case LM_SLC: 68844364Sborman sprintf(nfrontp, "SLC"); 68944364Sborman nfrontp += strlen(nfrontp); 69044364Sborman for (i = 2; i < length - 2; i += 3) { 69146809Sdab if (SLC_NAME_OK(pointer[i+SLC_FUNC])) 69246809Sdab sprintf(nfrontp, " %s", SLC_NAME(pointer[i+SLC_FUNC])); 69344364Sborman else 69444364Sborman sprintf(nfrontp, " %d", pointer[i+SLC_FUNC]); 69544364Sborman nfrontp += strlen(nfrontp); 69644364Sborman switch (pointer[i+SLC_FLAGS]&SLC_LEVELBITS) { 69744364Sborman case SLC_NOSUPPORT: 69844364Sborman sprintf(nfrontp, " NOSUPPORT"); break; 69944364Sborman case SLC_CANTCHANGE: 70044364Sborman sprintf(nfrontp, " CANTCHANGE"); break; 70144364Sborman case SLC_VARIABLE: 70244364Sborman sprintf(nfrontp, " VARIABLE"); break; 70344364Sborman case SLC_DEFAULT: 70444364Sborman sprintf(nfrontp, " DEFAULT"); break; 70544364Sborman } 70644364Sborman nfrontp += strlen(nfrontp); 70744364Sborman sprintf(nfrontp, "%s%s%s", 70844364Sborman pointer[i+SLC_FLAGS]&SLC_ACK ? "|ACK" : "", 70944364Sborman pointer[i+SLC_FLAGS]&SLC_FLUSHIN ? "|FLUSHIN" : "", 71044364Sborman pointer[i+SLC_FLAGS]&SLC_FLUSHOUT ? "|FLUSHOUT" : ""); 71144364Sborman nfrontp += strlen(nfrontp); 71244364Sborman if (pointer[i+SLC_FLAGS]& ~(SLC_ACK|SLC_FLUSHIN| 71344364Sborman SLC_FLUSHOUT| SLC_LEVELBITS)) { 71444364Sborman sprintf(nfrontp, "(0x%x)", pointer[i+SLC_FLAGS]); 71544364Sborman nfrontp += strlen(nfrontp); 71644364Sborman } 71744364Sborman sprintf(nfrontp, " %d;", pointer[i+SLC_VALUE]); 71844364Sborman nfrontp += strlen(nfrontp); 71944364Sborman if ((pointer[i+SLC_VALUE] == IAC) && 72044364Sborman (pointer[i+SLC_VALUE+1] == IAC)) 72144364Sborman i++; 72244364Sborman } 72344364Sborman for (; i < length; i++) { 72444364Sborman sprintf(nfrontp, " ?%d?", pointer[i]); 72544364Sborman nfrontp += strlen(nfrontp); 72644364Sborman } 72744364Sborman break; 72844364Sborman 72944364Sborman case LM_MODE: 73044364Sborman sprintf(nfrontp, "MODE "); 73144364Sborman nfrontp += strlen(nfrontp); 73244364Sborman if (length < 3) { 73344364Sborman sprintf(nfrontp, "(no mode???)"); 73444364Sborman nfrontp += strlen(nfrontp); 73544364Sborman break; 73644364Sborman } 73744364Sborman { 73844364Sborman char tbuf[32]; 73944364Sborman sprintf(tbuf, "%s%s%s%s%s", 74044364Sborman pointer[2]&MODE_EDIT ? "|EDIT" : "", 74144364Sborman pointer[2]&MODE_TRAPSIG ? "|TRAPSIG" : "", 74244364Sborman pointer[2]&MODE_SOFT_TAB ? "|SOFT_TAB" : "", 74344364Sborman pointer[2]&MODE_LIT_ECHO ? "|LIT_ECHO" : "", 74444364Sborman pointer[2]&MODE_ACK ? "|ACK" : ""); 74544364Sborman sprintf(nfrontp, "%s", tbuf[1] ? &tbuf[1] : "0"); 74644364Sborman nfrontp += strlen(nfrontp); 74744364Sborman } 74844364Sborman if (pointer[2]&~(MODE_EDIT|MODE_TRAPSIG|MODE_ACK)) { 74944364Sborman sprintf(nfrontp, " (0x%x)", pointer[2]); 75044364Sborman nfrontp += strlen(nfrontp); 75144364Sborman } 75244364Sborman for (i = 3; i < length; i++) { 75344364Sborman sprintf(nfrontp, " ?0x%x?", pointer[i]); 75444364Sborman nfrontp += strlen(nfrontp); 75544364Sborman } 75644364Sborman break; 75744364Sborman default: 75844364Sborman sprintf(nfrontp, "%d (unknown)", pointer[1]); 75944364Sborman nfrontp += strlen(nfrontp); 76044364Sborman for (i = 2; i < length; i++) { 76144364Sborman sprintf(nfrontp, " %d", pointer[i]); 76244364Sborman nfrontp += strlen(nfrontp); 76344364Sborman } 76444364Sborman } 76544364Sborman break; 76644364Sborman 76744364Sborman case TELOPT_STATUS: { 76844364Sborman register char *cp; 76944364Sborman register int j, k; 77044364Sborman 77144364Sborman sprintf(nfrontp, "STATUS"); 77244364Sborman nfrontp += strlen(nfrontp); 77344364Sborman 77444364Sborman switch (pointer[1]) { 77544364Sborman default: 77644364Sborman if (pointer[1] == TELQUAL_SEND) 77744364Sborman sprintf(nfrontp, " SEND"); 77844364Sborman else 77944364Sborman sprintf(nfrontp, " %d (unknown)", pointer[1]); 78044364Sborman nfrontp += strlen(nfrontp); 78144364Sborman for (i = 2; i < length; i++) { 78244364Sborman sprintf(nfrontp, " ?%d?", pointer[i]); 78344364Sborman nfrontp += strlen(nfrontp); 78444364Sborman } 78544364Sborman break; 78644364Sborman case TELQUAL_IS: 78744364Sborman sprintf(nfrontp, " IS\r\n"); 78844364Sborman nfrontp += strlen(nfrontp); 78944364Sborman 79044364Sborman for (i = 2; i < length; i++) { 79144364Sborman switch(pointer[i]) { 79244364Sborman case DO: cp = "DO"; goto common2; 79344364Sborman case DONT: cp = "DONT"; goto common2; 79444364Sborman case WILL: cp = "WILL"; goto common2; 79544364Sborman case WONT: cp = "WONT"; goto common2; 79644364Sborman common2: 79744364Sborman i++; 79858971Sdab if (TELOPT_OK(pointer[i])) 79944364Sborman sprintf(nfrontp, " %s %s", cp, TELOPT(pointer[i])); 80044364Sborman else 80144364Sborman sprintf(nfrontp, " %s %d", cp, pointer[i]); 80244364Sborman nfrontp += strlen(nfrontp); 80344364Sborman 80444364Sborman sprintf(nfrontp, "\r\n"); 80544364Sborman nfrontp += strlen(nfrontp); 80644364Sborman break; 80744364Sborman 80844364Sborman case SB: 80944364Sborman sprintf(nfrontp, " SB "); 81044364Sborman nfrontp += strlen(nfrontp); 81144364Sborman i++; 81244364Sborman j = k = i; 81344364Sborman while (j < length) { 81444364Sborman if (pointer[j] == SE) { 81544364Sborman if (j+1 == length) 81644364Sborman break; 81744364Sborman if (pointer[j+1] == SE) 81844364Sborman j++; 81944364Sborman else 82044364Sborman break; 82144364Sborman } 82244364Sborman pointer[k++] = pointer[j++]; 82344364Sborman } 82444364Sborman printsub(0, &pointer[i], k - i); 82544364Sborman if (i < length) { 82644364Sborman sprintf(nfrontp, " SE"); 82744364Sborman nfrontp += strlen(nfrontp); 82844364Sborman i = j; 82944364Sborman } else 83044364Sborman i = j - 1; 83144364Sborman 83244364Sborman sprintf(nfrontp, "\r\n"); 83344364Sborman nfrontp += strlen(nfrontp); 83444364Sborman 83544364Sborman break; 83644364Sborman 83744364Sborman default: 83844364Sborman sprintf(nfrontp, " %d", pointer[i]); 83944364Sborman nfrontp += strlen(nfrontp); 84044364Sborman break; 84144364Sborman } 84244364Sborman } 84344364Sborman break; 84444364Sborman } 84544364Sborman break; 84644364Sborman } 84744364Sborman 84844364Sborman case TELOPT_XDISPLOC: 84944364Sborman sprintf(nfrontp, "X-DISPLAY-LOCATION "); 85044364Sborman nfrontp += strlen(nfrontp); 85144364Sborman switch (pointer[1]) { 85244364Sborman case TELQUAL_IS: 85344364Sborman sprintf(nfrontp, "IS \"%.*s\"", length-2, (char *)pointer+2); 85444364Sborman break; 85544364Sborman case TELQUAL_SEND: 85644364Sborman sprintf(nfrontp, "SEND"); 85744364Sborman break; 85844364Sborman default: 85944364Sborman sprintf(nfrontp, "- unknown qualifier %d (0x%x).", 86044364Sborman pointer[1], pointer[1]); 86144364Sborman } 86244364Sborman nfrontp += strlen(nfrontp); 86344364Sborman break; 86444364Sborman 86544364Sborman case TELOPT_ENVIRON: 86644364Sborman sprintf(nfrontp, "ENVIRON "); 86744364Sborman nfrontp += strlen(nfrontp); 86844364Sborman switch (pointer[1]) { 86944364Sborman case TELQUAL_IS: 87044364Sborman sprintf(nfrontp, "IS "); 87144364Sborman goto env_common; 87244364Sborman case TELQUAL_SEND: 87344364Sborman sprintf(nfrontp, "SEND "); 87444364Sborman goto env_common; 87544364Sborman case TELQUAL_INFO: 87644364Sborman sprintf(nfrontp, "INFO "); 87744364Sborman env_common: 87844364Sborman nfrontp += strlen(nfrontp); 87944364Sborman { 88044364Sborman register int noquote = 2; 88144364Sborman for (i = 2; i < length; i++ ) { 88244364Sborman switch (pointer[i]) { 88344364Sborman case ENV_VAR: 88444364Sborman sprintf(nfrontp, "\" VAR " + noquote); 88544364Sborman nfrontp += strlen(nfrontp); 88644364Sborman noquote = 2; 88744364Sborman break; 88844364Sborman 88944364Sborman case ENV_VALUE: 89044364Sborman sprintf(nfrontp, "\" VALUE " + noquote); 89144364Sborman nfrontp += strlen(nfrontp); 89244364Sborman noquote = 2; 89344364Sborman break; 89444364Sborman 89544364Sborman case ENV_ESC: 89644364Sborman sprintf(nfrontp, "\" ESC " + noquote); 89744364Sborman nfrontp += strlen(nfrontp); 89844364Sborman noquote = 2; 89944364Sborman break; 90044364Sborman 90157212Sdab case ENV_USERVAR: 90257212Sdab sprintf(nfrontp, "\" USERVAR " + noquote); 90357212Sdab nfrontp += strlen(nfrontp); 90457212Sdab noquote = 2; 90557212Sdab break; 90657212Sdab 90744364Sborman default: 90844364Sborman def_case: 90944364Sborman if (isprint(pointer[i]) && pointer[i] != '"') { 91044364Sborman if (noquote) { 91144364Sborman *nfrontp++ = '"'; 91244364Sborman noquote = 0; 91344364Sborman } 91444364Sborman *nfrontp++ = pointer[i]; 91544364Sborman } else { 91644364Sborman sprintf(nfrontp, "\" %03o " + noquote, 91744364Sborman pointer[i]); 91844364Sborman nfrontp += strlen(nfrontp); 91944364Sborman noquote = 2; 92044364Sborman } 92144364Sborman break; 92244364Sborman } 92344364Sborman } 92444364Sborman if (!noquote) 92544364Sborman *nfrontp++ = '"'; 92644364Sborman break; 92744364Sborman } 92844364Sborman } 92944364Sborman break; 93044364Sborman 93157212Sdab #if defined(AUTHENTICATION) 93246809Sdab case TELOPT_AUTHENTICATION: 93346809Sdab sprintf(nfrontp, "AUTHENTICATION"); 93446809Sdab nfrontp += strlen(nfrontp); 93546809Sdab 93646809Sdab if (length < 2) { 93746809Sdab sprintf(nfrontp, " (empty suboption???)"); 93846809Sdab nfrontp += strlen(nfrontp); 93946809Sdab break; 94046809Sdab } 94146809Sdab switch (pointer[1]) { 94246809Sdab case TELQUAL_REPLY: 94346809Sdab case TELQUAL_IS: 94446809Sdab sprintf(nfrontp, " %s ", (pointer[1] == TELQUAL_IS) ? 94546809Sdab "IS" : "REPLY"); 94646809Sdab nfrontp += strlen(nfrontp); 94746809Sdab if (AUTHTYPE_NAME_OK(pointer[2])) 94846809Sdab sprintf(nfrontp, "%s ", AUTHTYPE_NAME(pointer[2])); 94946809Sdab else 95046809Sdab sprintf(nfrontp, "%d ", pointer[2]); 95146809Sdab nfrontp += strlen(nfrontp); 95246809Sdab if (length < 3) { 95346809Sdab sprintf(nfrontp, "(partial suboption???)"); 95446809Sdab nfrontp += strlen(nfrontp); 95546809Sdab break; 95646809Sdab } 95746809Sdab sprintf(nfrontp, "%s|%s", 95847611Sdab ((pointer[3] & AUTH_WHO_MASK) == AUTH_WHO_CLIENT) ? 95946809Sdab "CLIENT" : "SERVER", 96047611Sdab ((pointer[3] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) ? 96146809Sdab "MUTUAL" : "ONE-WAY"); 96246809Sdab nfrontp += strlen(nfrontp); 96346809Sdab 96446809Sdab auth_printsub(&pointer[1], length - 1, buf, sizeof(buf)); 96546809Sdab sprintf(nfrontp, "%s", buf); 96646809Sdab nfrontp += strlen(nfrontp); 96746809Sdab break; 96846809Sdab 96946809Sdab case TELQUAL_SEND: 97046809Sdab i = 2; 97146809Sdab sprintf(nfrontp, " SEND "); 97246809Sdab nfrontp += strlen(nfrontp); 97346809Sdab while (i < length) { 97446809Sdab if (AUTHTYPE_NAME_OK(pointer[i])) 97546809Sdab sprintf(nfrontp, "%s ", AUTHTYPE_NAME(pointer[i])); 97646809Sdab else 97746809Sdab sprintf(nfrontp, "%d ", pointer[i]); 97846809Sdab nfrontp += strlen(nfrontp); 97946809Sdab if (++i >= length) { 98046809Sdab sprintf(nfrontp, "(partial suboption???)"); 98146809Sdab nfrontp += strlen(nfrontp); 98246809Sdab break; 98346809Sdab } 98446809Sdab sprintf(nfrontp, "%s|%s ", 98547611Sdab ((pointer[i] & AUTH_WHO_MASK) == AUTH_WHO_CLIENT) ? 98646809Sdab "CLIENT" : "SERVER", 98747611Sdab ((pointer[i] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) ? 98846809Sdab "MUTUAL" : "ONE-WAY"); 98946809Sdab nfrontp += strlen(nfrontp); 99046809Sdab ++i; 99146809Sdab } 99246809Sdab break; 99346809Sdab 99447611Sdab case TELQUAL_NAME: 99547611Sdab i = 2; 99647611Sdab sprintf(nfrontp, " NAME \""); 99747611Sdab nfrontp += strlen(nfrontp); 99847611Sdab while (i < length) 99947611Sdab *nfrontp += pointer[i++]; 100047611Sdab *nfrontp += '"'; 100147611Sdab break; 100247611Sdab 100346809Sdab default: 100446809Sdab for (i = 2; i < length; i++) { 100546809Sdab sprintf(nfrontp, " ?%d?", pointer[i]); 100646809Sdab nfrontp += strlen(nfrontp); 100746809Sdab } 100846809Sdab break; 100946809Sdab } 101046809Sdab break; 101146809Sdab #endif 101246809Sdab 101360151Sdab #ifdef ENCRYPTION 101446809Sdab case TELOPT_ENCRYPT: 101546809Sdab sprintf(nfrontp, "ENCRYPT"); 101646809Sdab nfrontp += strlen(nfrontp); 101746809Sdab if (length < 2) { 101846809Sdab sprintf(nfrontp, " (empty suboption???)"); 101946809Sdab nfrontp += strlen(nfrontp); 102046809Sdab break; 102146809Sdab } 102246809Sdab switch (pointer[1]) { 102346809Sdab case ENCRYPT_START: 102446809Sdab sprintf(nfrontp, " START"); 102546809Sdab nfrontp += strlen(nfrontp); 102646809Sdab break; 102746809Sdab 102846809Sdab case ENCRYPT_END: 102946809Sdab sprintf(nfrontp, " END"); 103046809Sdab nfrontp += strlen(nfrontp); 103146809Sdab break; 103246809Sdab 103346809Sdab case ENCRYPT_REQSTART: 103446809Sdab sprintf(nfrontp, " REQUEST-START"); 103546809Sdab nfrontp += strlen(nfrontp); 103646809Sdab break; 103746809Sdab 103846809Sdab case ENCRYPT_REQEND: 103946809Sdab sprintf(nfrontp, " REQUEST-END"); 104046809Sdab nfrontp += strlen(nfrontp); 104146809Sdab break; 104246809Sdab 104346809Sdab case ENCRYPT_IS: 104446809Sdab case ENCRYPT_REPLY: 104546809Sdab sprintf(nfrontp, " %s ", (pointer[1] == ENCRYPT_IS) ? 104646809Sdab "IS" : "REPLY"); 104746809Sdab nfrontp += strlen(nfrontp); 104846809Sdab if (length < 3) { 104946809Sdab sprintf(nfrontp, " (partial suboption???)"); 105046809Sdab nfrontp += strlen(nfrontp); 105146809Sdab break; 105246809Sdab } 105346809Sdab if (ENCTYPE_NAME_OK(pointer[2])) 105446809Sdab sprintf(nfrontp, "%s ", ENCTYPE_NAME(pointer[2])); 105546809Sdab else 105646809Sdab sprintf(nfrontp, " %d (unknown)", pointer[2]); 105746809Sdab nfrontp += strlen(nfrontp); 105846809Sdab 105946809Sdab encrypt_printsub(&pointer[1], length - 1, buf, sizeof(buf)); 106046809Sdab sprintf(nfrontp, "%s", buf); 106146809Sdab nfrontp += strlen(nfrontp); 106246809Sdab break; 106346809Sdab 106446809Sdab case ENCRYPT_SUPPORT: 106546809Sdab i = 2; 106646809Sdab sprintf(nfrontp, " SUPPORT "); 106746809Sdab nfrontp += strlen(nfrontp); 106846809Sdab while (i < length) { 106946809Sdab if (ENCTYPE_NAME_OK(pointer[i])) 107046809Sdab sprintf(nfrontp, "%s ", ENCTYPE_NAME(pointer[i])); 107146809Sdab else 107246809Sdab sprintf(nfrontp, "%d ", pointer[i]); 107346809Sdab nfrontp += strlen(nfrontp); 107446809Sdab i++; 107546809Sdab } 107646809Sdab break; 107746809Sdab 107847611Sdab case ENCRYPT_ENC_KEYID: 107947611Sdab sprintf(nfrontp, " ENC_KEYID", pointer[1]); 108047611Sdab nfrontp += strlen(nfrontp); 108147611Sdab goto encommon; 108247611Sdab 108347611Sdab case ENCRYPT_DEC_KEYID: 108447611Sdab sprintf(nfrontp, " DEC_KEYID", pointer[1]); 108547611Sdab nfrontp += strlen(nfrontp); 108647611Sdab goto encommon; 108747611Sdab 108846809Sdab default: 108947611Sdab sprintf(nfrontp, " %d (unknown)", pointer[1]); 109046809Sdab nfrontp += strlen(nfrontp); 109147611Sdab encommon: 109246809Sdab for (i = 2; i < length; i++) { 109346809Sdab sprintf(nfrontp, " %d", pointer[i]); 109446809Sdab nfrontp += strlen(nfrontp); 109546809Sdab } 109646809Sdab break; 109746809Sdab } 109846809Sdab break; 109960151Sdab #endif /* ENCRYPTION */ 110046809Sdab 110144364Sborman default: 110246809Sdab if (TELOPT_OK(pointer[0])) 110346809Sdab sprintf(nfrontp, "%s (unknown)", TELOPT(pointer[0])); 110446809Sdab else 110546809Sdab sprintf(nfrontp, "%d (unknown)", pointer[i]); 110644364Sborman nfrontp += strlen(nfrontp); 110746809Sdab for (i = 1; i < length; i++) { 110844364Sborman sprintf(nfrontp, " %d", pointer[i]); 110944364Sborman nfrontp += strlen(nfrontp); 111044364Sborman } 111144364Sborman break; 111244364Sborman } 111344364Sborman sprintf(nfrontp, "\r\n"); 111444364Sborman nfrontp += strlen(nfrontp); 111544364Sborman } 111644364Sborman 111744364Sborman /* 111844364Sborman * Dump a data buffer in hex and ascii to the output data stream. 111944364Sborman */ 112046809Sdab void 112144364Sborman printdata(tag, ptr, cnt) 112246809Sdab register char *tag; 112346809Sdab register char *ptr; 112446809Sdab register int cnt; 112544364Sborman { 112646809Sdab register int i; 112746809Sdab char xbuf[30]; 112844364Sborman 112944364Sborman while (cnt) { 113044364Sborman /* flush net output buffer if no room for new data) */ 113144364Sborman if ((&netobuf[BUFSIZ] - nfrontp) < 80) { 113244364Sborman netflush(); 113344364Sborman } 113444364Sborman 113544364Sborman /* add a line of output */ 113644364Sborman sprintf(nfrontp, "%s: ", tag); 113744364Sborman nfrontp += strlen(nfrontp); 113844364Sborman for (i = 0; i < 20 && cnt; i++) { 113944364Sborman sprintf(nfrontp, "%02x", *ptr); 114044364Sborman nfrontp += strlen(nfrontp); 114144364Sborman if (isprint(*ptr)) { 114244364Sborman xbuf[i] = *ptr; 114344364Sborman } else { 114444364Sborman xbuf[i] = '.'; 114544364Sborman } 114644364Sborman if (i % 2) { 114744364Sborman *nfrontp = ' '; 114844364Sborman nfrontp++; 114944364Sborman } 115044364Sborman cnt--; 115144364Sborman ptr++; 115244364Sborman } 115344364Sborman xbuf[i] = '\0'; 115444364Sborman sprintf(nfrontp, " %s\r\n", xbuf ); 115544364Sborman nfrontp += strlen(nfrontp); 115644364Sborman } 115744364Sborman } 115844364Sborman #endif /* DIAGNOSTICS */ 1159