138905Sborman /* 238905Sborman * Copyright (c) 1989 Regents of the University of California. 338905Sborman * All rights reserved. 438905Sborman * 542673Sbostic * %sccs.include.redist.c% 638905Sborman */ 738905Sborman 838905Sborman #ifndef lint 9*47611Sdab static char sccsid[] = "@(#)utility.c 5.8 (Berkeley) 03/22/91"; 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 17046809Sdab #if defined(ENCRYPT) 17146809Sdab thisitem = nclearto > netobuf ? nclearto : netobuf; 17246809Sdab #else 17338905Sborman thisitem = netobuf; 17446809Sdab #endif 17538905Sborman 17638905Sborman while ((next = nextitem(thisitem)) <= nbackp) { 17738905Sborman thisitem = next; 17838905Sborman } 17938905Sborman 18038905Sborman /* Now, thisitem is first before/at boundary. */ 18138905Sborman 18246809Sdab #if defined(ENCRYPT) 18346809Sdab good = nclearto > netobuf ? nclearto : netobuf; 18446809Sdab #else 18538905Sborman good = netobuf; /* where the good bytes go */ 18646809Sdab #endif 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 }); 22746809Sdab #if defined(ENCRYPT) 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 } 23546809Sdab #endif 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; 26646809Sdab #if defined(ENCRYPT) 26746809Sdab if (nbackp > nclearto) 26846809Sdab nclearto = 0; 26946809Sdab #endif 27038905Sborman if (nbackp >= neturg) { 27138905Sborman neturg = 0; 27238905Sborman } 27338905Sborman if (nbackp == nfrontp) { 27438905Sborman nbackp = nfrontp = netobuf; 27546809Sdab #if defined(ENCRYPT) 27646809Sdab nclearto = 0; 27746809Sdab #endif 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); 32346809Sdab #if defined(ENCRYPT) 32446809Sdab if (encrypt_output) { 32546809Sdab /* 32646809Sdab * Better turn off encryption first.... 32746809Sdab * Hope it flushes... 32846809Sdab */ 32946809Sdab encrypt_send_end(); 33046809Sdab netflush(); 33146809Sdab } 33246809Sdab #endif 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': 43738905Sborman slash = rindex(line, '/'); 43838905Sborman if (slash == (char *) 0) 43938905Sborman putstr(line); 44038905Sborman else 44138905Sborman putstr(&slash[1]); 44238905Sborman break; 44338905Sborman 44438905Sborman case 'h': 44538905Sborman putstr(editedhost); 44638905Sborman break; 44738905Sborman 44846809Sdab case 'd': 44946123Sbostic (void)time(&t); 45046809Sdab (void)strftime(db, sizeof(db), fmtstr, localtime(&t)); 45146123Sbostic putstr(db); 45238905Sborman break; 45338905Sborman 45438905Sborman case '%': 45538905Sborman putchr('%'); 45638905Sborman break; 45738905Sborman } 45838905Sborman cp++; 45938905Sborman } 46038905Sborman } 46138905Sborman 46244364Sborman #ifdef DIAGNOSTICS 46344364Sborman /* 46444364Sborman * Print telnet options and commands in plain text, if possible. 46544364Sborman */ 46646809Sdab void 46744364Sborman printoption(fmt, option) 46846809Sdab register char *fmt; 46946809Sdab register int option; 47044364Sborman { 47144364Sborman if (TELOPT_OK(option)) 47244364Sborman sprintf(nfrontp, "%s %s\r\n", fmt, TELOPT(option)); 47344364Sborman else if (TELCMD_OK(option)) 47444364Sborman sprintf(nfrontp, "%s %s\r\n", fmt, TELCMD(option)); 47544364Sborman else 47644364Sborman sprintf(nfrontp, "%s %d\r\n", fmt, option); 47744364Sborman nfrontp += strlen(nfrontp); 47844364Sborman return; 47944364Sborman } 48044364Sborman 48146809Sdab void 48246809Sdab printsub(direction, pointer, length) 48346809Sdab char direction; /* '<' or '>' */ 48446809Sdab unsigned char *pointer; /* where suboption data sits */ 48546809Sdab int length; /* length of suboption data */ 48644364Sborman { 48744364Sborman register int i; 488*47611Sdab char buf[512]; 48944364Sborman 49046809Sdab if (!(diagnostic & TD_OPTIONS)) 49146809Sdab return; 49246809Sdab 49346809Sdab if (direction) { 49446809Sdab sprintf(nfrontp, "td: %s suboption ", 49546809Sdab direction == '<' ? "recv" : "send"); 49644364Sborman nfrontp += strlen(nfrontp); 49744364Sborman if (length >= 3) { 49844364Sborman register int j; 49944364Sborman 50044364Sborman i = pointer[length-2]; 50144364Sborman j = pointer[length-1]; 50244364Sborman 50344364Sborman if (i != IAC || j != SE) { 50444364Sborman sprintf(nfrontp, "(terminated by "); 50544364Sborman nfrontp += strlen(nfrontp); 50644364Sborman if (TELOPT_OK(i)) 50744364Sborman sprintf(nfrontp, "%s ", TELOPT(i)); 50844364Sborman else if (TELCMD_OK(i)) 50944364Sborman sprintf(nfrontp, "%s ", TELCMD(i)); 51044364Sborman else 51144364Sborman sprintf(nfrontp, "%d ", i); 51244364Sborman nfrontp += strlen(nfrontp); 51344364Sborman if (TELOPT_OK(j)) 51444364Sborman sprintf(nfrontp, "%s", TELOPT(j)); 51544364Sborman else if (TELCMD_OK(j)) 51644364Sborman sprintf(nfrontp, "%s", TELCMD(j)); 51744364Sborman else 51844364Sborman sprintf(nfrontp, "%d", j); 51944364Sborman nfrontp += strlen(nfrontp); 52044364Sborman sprintf(nfrontp, ", not IAC SE!) "); 52144364Sborman nfrontp += strlen(nfrontp); 52244364Sborman } 52344364Sborman } 52444364Sborman length -= 2; 52544364Sborman } 52644364Sborman if (length < 1) { 52744364Sborman sprintf(nfrontp, "(Empty suboption???)"); 52844364Sborman nfrontp += strlen(nfrontp); 52944364Sborman return; 53044364Sborman } 53144364Sborman switch (pointer[0]) { 53244364Sborman case TELOPT_TTYPE: 53344364Sborman sprintf(nfrontp, "TERMINAL-TYPE "); 53444364Sborman nfrontp += strlen(nfrontp); 53544364Sborman switch (pointer[1]) { 53644364Sborman case TELQUAL_IS: 53744364Sborman sprintf(nfrontp, "IS \"%.*s\"", length-2, (char *)pointer+2); 53844364Sborman break; 53944364Sborman case TELQUAL_SEND: 54044364Sborman sprintf(nfrontp, "SEND"); 54144364Sborman break; 54244364Sborman default: 54344364Sborman sprintf(nfrontp, 54444364Sborman "- unknown qualifier %d (0x%x).", 54544364Sborman pointer[1], pointer[1]); 54644364Sborman } 54744364Sborman nfrontp += strlen(nfrontp); 54844364Sborman break; 54944364Sborman case TELOPT_TSPEED: 55044364Sborman sprintf(nfrontp, "TERMINAL-SPEED"); 55144364Sborman nfrontp += strlen(nfrontp); 55244364Sborman if (length < 2) { 55344364Sborman sprintf(nfrontp, " (empty suboption???)"); 55444364Sborman nfrontp += strlen(nfrontp); 55544364Sborman break; 55644364Sborman } 55744364Sborman switch (pointer[1]) { 55844364Sborman case TELQUAL_IS: 55944364Sborman sprintf(nfrontp, " IS %.*s", length-2, (char *)pointer+2); 56044364Sborman nfrontp += strlen(nfrontp); 56144364Sborman break; 56244364Sborman default: 56344364Sborman if (pointer[1] == 1) 56444364Sborman sprintf(nfrontp, " SEND"); 56544364Sborman else 56644364Sborman sprintf(nfrontp, " %d (unknown)", pointer[1]); 56744364Sborman nfrontp += strlen(nfrontp); 56844364Sborman for (i = 2; i < length; i++) { 56944364Sborman sprintf(nfrontp, " ?%d?", pointer[i]); 57044364Sborman nfrontp += strlen(nfrontp); 57144364Sborman } 57244364Sborman break; 57344364Sborman } 57444364Sborman break; 57544364Sborman 57644364Sborman case TELOPT_LFLOW: 57744364Sborman sprintf(nfrontp, "TOGGLE-FLOW-CONTROL"); 57844364Sborman nfrontp += strlen(nfrontp); 57944364Sborman if (length < 2) { 58044364Sborman sprintf(nfrontp, " (empty suboption???)"); 58144364Sborman nfrontp += strlen(nfrontp); 58244364Sborman break; 58344364Sborman } 58444364Sborman switch (pointer[1]) { 58544364Sborman case 0: 58644364Sborman sprintf(nfrontp, " OFF"); break; 58744364Sborman case 1: 58844364Sborman sprintf(nfrontp, " ON"); break; 58944364Sborman default: 59044364Sborman sprintf(nfrontp, " %d (unknown)", pointer[1]); 59144364Sborman } 59244364Sborman nfrontp += strlen(nfrontp); 59344364Sborman for (i = 2; i < length; i++) { 59444364Sborman sprintf(nfrontp, " ?%d?", pointer[i]); 59544364Sborman nfrontp += strlen(nfrontp); 59644364Sborman } 59744364Sborman break; 59844364Sborman 59944364Sborman case TELOPT_NAWS: 60044364Sborman sprintf(nfrontp, "NAWS"); 60144364Sborman nfrontp += strlen(nfrontp); 60244364Sborman if (length < 2) { 60344364Sborman sprintf(nfrontp, " (empty suboption???)"); 60444364Sborman nfrontp += strlen(nfrontp); 60544364Sborman break; 60644364Sborman } 60744364Sborman if (length == 2) { 60844364Sborman sprintf(nfrontp, " ?%d?", pointer[1]); 60944364Sborman nfrontp += strlen(nfrontp); 61044364Sborman break; 61144364Sborman } 61244364Sborman sprintf(nfrontp, " %d %d (%d)", 61344364Sborman pointer[1], pointer[2], 61444364Sborman (int)((((unsigned int)pointer[1])<<8)|((unsigned int)pointer[2]))); 61544364Sborman nfrontp += strlen(nfrontp); 61644364Sborman if (length == 4) { 61744364Sborman sprintf(nfrontp, " ?%d?", pointer[3]); 61844364Sborman nfrontp += strlen(nfrontp); 61944364Sborman break; 62044364Sborman } 62144364Sborman sprintf(nfrontp, " %d %d (%d)", 62244364Sborman pointer[3], pointer[4], 62344364Sborman (int)((((unsigned int)pointer[3])<<8)|((unsigned int)pointer[4]))); 62444364Sborman nfrontp += strlen(nfrontp); 62544364Sborman for (i = 5; i < length; i++) { 62644364Sborman sprintf(nfrontp, " ?%d?", pointer[i]); 62744364Sborman nfrontp += strlen(nfrontp); 62844364Sborman } 62944364Sborman break; 63044364Sborman 63144364Sborman case TELOPT_LINEMODE: 63244364Sborman sprintf(nfrontp, "LINEMODE "); 63344364Sborman nfrontp += strlen(nfrontp); 63444364Sborman if (length < 2) { 63544364Sborman sprintf(nfrontp, " (empty suboption???)"); 63644364Sborman nfrontp += strlen(nfrontp); 63744364Sborman break; 63844364Sborman } 63944364Sborman switch (pointer[1]) { 64044364Sborman case WILL: 64144364Sborman sprintf(nfrontp, "WILL "); 64244364Sborman goto common; 64344364Sborman case WONT: 64444364Sborman sprintf(nfrontp, "WONT "); 64544364Sborman goto common; 64644364Sborman case DO: 64744364Sborman sprintf(nfrontp, "DO "); 64844364Sborman goto common; 64944364Sborman case DONT: 65044364Sborman sprintf(nfrontp, "DONT "); 65144364Sborman common: 65244364Sborman nfrontp += strlen(nfrontp); 65344364Sborman if (length < 3) { 65444364Sborman sprintf(nfrontp, "(no option???)"); 65544364Sborman nfrontp += strlen(nfrontp); 65644364Sborman break; 65744364Sborman } 65844364Sborman switch (pointer[2]) { 65944364Sborman case LM_FORWARDMASK: 66044364Sborman sprintf(nfrontp, "Forward Mask"); 66144364Sborman nfrontp += strlen(nfrontp); 66244364Sborman for (i = 3; i < length; i++) { 66344364Sborman sprintf(nfrontp, " %x", pointer[i]); 66444364Sborman nfrontp += strlen(nfrontp); 66544364Sborman } 66644364Sborman break; 66744364Sborman default: 66844364Sborman sprintf(nfrontp, "%d (unknown)", pointer[2]); 66944364Sborman nfrontp += strlen(nfrontp); 67044364Sborman for (i = 3; i < length; i++) { 67144364Sborman sprintf(nfrontp, " %d", pointer[i]); 67244364Sborman nfrontp += strlen(nfrontp); 67344364Sborman } 67444364Sborman break; 67544364Sborman } 67644364Sborman break; 67744364Sborman 67844364Sborman case LM_SLC: 67944364Sborman sprintf(nfrontp, "SLC"); 68044364Sborman nfrontp += strlen(nfrontp); 68144364Sborman for (i = 2; i < length - 2; i += 3) { 68246809Sdab if (SLC_NAME_OK(pointer[i+SLC_FUNC])) 68346809Sdab sprintf(nfrontp, " %s", SLC_NAME(pointer[i+SLC_FUNC])); 68444364Sborman else 68544364Sborman sprintf(nfrontp, " %d", pointer[i+SLC_FUNC]); 68644364Sborman nfrontp += strlen(nfrontp); 68744364Sborman switch (pointer[i+SLC_FLAGS]&SLC_LEVELBITS) { 68844364Sborman case SLC_NOSUPPORT: 68944364Sborman sprintf(nfrontp, " NOSUPPORT"); break; 69044364Sborman case SLC_CANTCHANGE: 69144364Sborman sprintf(nfrontp, " CANTCHANGE"); break; 69244364Sborman case SLC_VARIABLE: 69344364Sborman sprintf(nfrontp, " VARIABLE"); break; 69444364Sborman case SLC_DEFAULT: 69544364Sborman sprintf(nfrontp, " DEFAULT"); break; 69644364Sborman } 69744364Sborman nfrontp += strlen(nfrontp); 69844364Sborman sprintf(nfrontp, "%s%s%s", 69944364Sborman pointer[i+SLC_FLAGS]&SLC_ACK ? "|ACK" : "", 70044364Sborman pointer[i+SLC_FLAGS]&SLC_FLUSHIN ? "|FLUSHIN" : "", 70144364Sborman pointer[i+SLC_FLAGS]&SLC_FLUSHOUT ? "|FLUSHOUT" : ""); 70244364Sborman nfrontp += strlen(nfrontp); 70344364Sborman if (pointer[i+SLC_FLAGS]& ~(SLC_ACK|SLC_FLUSHIN| 70444364Sborman SLC_FLUSHOUT| SLC_LEVELBITS)) { 70544364Sborman sprintf(nfrontp, "(0x%x)", pointer[i+SLC_FLAGS]); 70644364Sborman nfrontp += strlen(nfrontp); 70744364Sborman } 70844364Sborman sprintf(nfrontp, " %d;", pointer[i+SLC_VALUE]); 70944364Sborman nfrontp += strlen(nfrontp); 71044364Sborman if ((pointer[i+SLC_VALUE] == IAC) && 71144364Sborman (pointer[i+SLC_VALUE+1] == IAC)) 71244364Sborman i++; 71344364Sborman } 71444364Sborman for (; i < length; i++) { 71544364Sborman sprintf(nfrontp, " ?%d?", pointer[i]); 71644364Sborman nfrontp += strlen(nfrontp); 71744364Sborman } 71844364Sborman break; 71944364Sborman 72044364Sborman case LM_MODE: 72144364Sborman sprintf(nfrontp, "MODE "); 72244364Sborman nfrontp += strlen(nfrontp); 72344364Sborman if (length < 3) { 72444364Sborman sprintf(nfrontp, "(no mode???)"); 72544364Sborman nfrontp += strlen(nfrontp); 72644364Sborman break; 72744364Sborman } 72844364Sborman { 72944364Sborman char tbuf[32]; 73044364Sborman sprintf(tbuf, "%s%s%s%s%s", 73144364Sborman pointer[2]&MODE_EDIT ? "|EDIT" : "", 73244364Sborman pointer[2]&MODE_TRAPSIG ? "|TRAPSIG" : "", 73344364Sborman pointer[2]&MODE_SOFT_TAB ? "|SOFT_TAB" : "", 73444364Sborman pointer[2]&MODE_LIT_ECHO ? "|LIT_ECHO" : "", 73544364Sborman pointer[2]&MODE_ACK ? "|ACK" : ""); 73644364Sborman sprintf(nfrontp, "%s", tbuf[1] ? &tbuf[1] : "0"); 73744364Sborman nfrontp += strlen(nfrontp); 73844364Sborman } 73944364Sborman if (pointer[2]&~(MODE_EDIT|MODE_TRAPSIG|MODE_ACK)) { 74044364Sborman sprintf(nfrontp, " (0x%x)", pointer[2]); 74144364Sborman nfrontp += strlen(nfrontp); 74244364Sborman } 74344364Sborman for (i = 3; i < length; i++) { 74444364Sborman sprintf(nfrontp, " ?0x%x?", pointer[i]); 74544364Sborman nfrontp += strlen(nfrontp); 74644364Sborman } 74744364Sborman break; 74844364Sborman default: 74944364Sborman sprintf(nfrontp, "%d (unknown)", pointer[1]); 75044364Sborman nfrontp += strlen(nfrontp); 75144364Sborman for (i = 2; i < length; i++) { 75244364Sborman sprintf(nfrontp, " %d", pointer[i]); 75344364Sborman nfrontp += strlen(nfrontp); 75444364Sborman } 75544364Sborman } 75644364Sborman break; 75744364Sborman 75844364Sborman case TELOPT_STATUS: { 75944364Sborman register char *cp; 76044364Sborman register int j, k; 76144364Sborman 76244364Sborman sprintf(nfrontp, "STATUS"); 76344364Sborman nfrontp += strlen(nfrontp); 76444364Sborman 76544364Sborman switch (pointer[1]) { 76644364Sborman default: 76744364Sborman if (pointer[1] == TELQUAL_SEND) 76844364Sborman sprintf(nfrontp, " SEND"); 76944364Sborman else 77044364Sborman sprintf(nfrontp, " %d (unknown)", pointer[1]); 77144364Sborman nfrontp += strlen(nfrontp); 77244364Sborman for (i = 2; i < length; i++) { 77344364Sborman sprintf(nfrontp, " ?%d?", pointer[i]); 77444364Sborman nfrontp += strlen(nfrontp); 77544364Sborman } 77644364Sborman break; 77744364Sborman case TELQUAL_IS: 77844364Sborman sprintf(nfrontp, " IS\r\n"); 77944364Sborman nfrontp += strlen(nfrontp); 78044364Sborman 78144364Sborman for (i = 2; i < length; i++) { 78244364Sborman switch(pointer[i]) { 78344364Sborman case DO: cp = "DO"; goto common2; 78444364Sborman case DONT: cp = "DONT"; goto common2; 78544364Sborman case WILL: cp = "WILL"; goto common2; 78644364Sborman case WONT: cp = "WONT"; goto common2; 78744364Sborman common2: 78844364Sborman i++; 78944364Sborman if (TELOPT_OK((int)pointer[i])) 79044364Sborman sprintf(nfrontp, " %s %s", cp, TELOPT(pointer[i])); 79144364Sborman else 79244364Sborman sprintf(nfrontp, " %s %d", cp, pointer[i]); 79344364Sborman nfrontp += strlen(nfrontp); 79444364Sborman 79544364Sborman sprintf(nfrontp, "\r\n"); 79644364Sborman nfrontp += strlen(nfrontp); 79744364Sborman break; 79844364Sborman 79944364Sborman case SB: 80044364Sborman sprintf(nfrontp, " SB "); 80144364Sborman nfrontp += strlen(nfrontp); 80244364Sborman i++; 80344364Sborman j = k = i; 80444364Sborman while (j < length) { 80544364Sborman if (pointer[j] == SE) { 80644364Sborman if (j+1 == length) 80744364Sborman break; 80844364Sborman if (pointer[j+1] == SE) 80944364Sborman j++; 81044364Sborman else 81144364Sborman break; 81244364Sborman } 81344364Sborman pointer[k++] = pointer[j++]; 81444364Sborman } 81544364Sborman printsub(0, &pointer[i], k - i); 81644364Sborman if (i < length) { 81744364Sborman sprintf(nfrontp, " SE"); 81844364Sborman nfrontp += strlen(nfrontp); 81944364Sborman i = j; 82044364Sborman } else 82144364Sborman i = j - 1; 82244364Sborman 82344364Sborman sprintf(nfrontp, "\r\n"); 82444364Sborman nfrontp += strlen(nfrontp); 82544364Sborman 82644364Sborman break; 82744364Sborman 82844364Sborman default: 82944364Sborman sprintf(nfrontp, " %d", pointer[i]); 83044364Sborman nfrontp += strlen(nfrontp); 83144364Sborman break; 83244364Sborman } 83344364Sborman } 83444364Sborman break; 83544364Sborman } 83644364Sborman break; 83744364Sborman } 83844364Sborman 83944364Sborman case TELOPT_XDISPLOC: 84044364Sborman sprintf(nfrontp, "X-DISPLAY-LOCATION "); 84144364Sborman nfrontp += strlen(nfrontp); 84244364Sborman switch (pointer[1]) { 84344364Sborman case TELQUAL_IS: 84444364Sborman sprintf(nfrontp, "IS \"%.*s\"", length-2, (char *)pointer+2); 84544364Sborman break; 84644364Sborman case TELQUAL_SEND: 84744364Sborman sprintf(nfrontp, "SEND"); 84844364Sborman break; 84944364Sborman default: 85044364Sborman sprintf(nfrontp, "- unknown qualifier %d (0x%x).", 85144364Sborman pointer[1], pointer[1]); 85244364Sborman } 85344364Sborman nfrontp += strlen(nfrontp); 85444364Sborman break; 85544364Sborman 85644364Sborman case TELOPT_ENVIRON: 85744364Sborman sprintf(nfrontp, "ENVIRON "); 85844364Sborman nfrontp += strlen(nfrontp); 85944364Sborman switch (pointer[1]) { 86044364Sborman case TELQUAL_IS: 86144364Sborman sprintf(nfrontp, "IS "); 86244364Sborman goto env_common; 86344364Sborman case TELQUAL_SEND: 86444364Sborman sprintf(nfrontp, "SEND "); 86544364Sborman goto env_common; 86644364Sborman case TELQUAL_INFO: 86744364Sborman sprintf(nfrontp, "INFO "); 86844364Sborman env_common: 86944364Sborman nfrontp += strlen(nfrontp); 87044364Sborman { 87144364Sborman register int noquote = 2; 87244364Sborman for (i = 2; i < length; i++ ) { 87344364Sborman switch (pointer[i]) { 87444364Sborman case ENV_VAR: 87544364Sborman if (pointer[1] == TELQUAL_SEND) 87644364Sborman goto def_case; 87744364Sborman sprintf(nfrontp, "\" VAR " + noquote); 87844364Sborman nfrontp += strlen(nfrontp); 87944364Sborman noquote = 2; 88044364Sborman break; 88144364Sborman 88244364Sborman case ENV_VALUE: 88344364Sborman sprintf(nfrontp, "\" VALUE " + noquote); 88444364Sborman nfrontp += strlen(nfrontp); 88544364Sborman noquote = 2; 88644364Sborman break; 88744364Sborman 88844364Sborman case ENV_ESC: 88944364Sborman sprintf(nfrontp, "\" ESC " + noquote); 89044364Sborman nfrontp += strlen(nfrontp); 89144364Sborman noquote = 2; 89244364Sborman break; 89344364Sborman 89444364Sborman default: 89544364Sborman def_case: 89644364Sborman if (isprint(pointer[i]) && pointer[i] != '"') { 89744364Sborman if (noquote) { 89844364Sborman *nfrontp++ = '"'; 89944364Sborman noquote = 0; 90044364Sborman } 90144364Sborman *nfrontp++ = pointer[i]; 90244364Sborman } else { 90344364Sborman sprintf(nfrontp, "\" %03o " + noquote, 90444364Sborman pointer[i]); 90544364Sborman nfrontp += strlen(nfrontp); 90644364Sborman noquote = 2; 90744364Sborman } 90844364Sborman break; 90944364Sborman } 91044364Sborman } 91144364Sborman if (!noquote) 91244364Sborman *nfrontp++ = '"'; 91344364Sborman break; 91444364Sborman } 91544364Sborman } 91644364Sborman break; 91744364Sborman 91846809Sdab #if defined(AUTHENTICATE) 91946809Sdab case TELOPT_AUTHENTICATION: 92046809Sdab sprintf(nfrontp, "AUTHENTICATION"); 92146809Sdab nfrontp += strlen(nfrontp); 92246809Sdab 92346809Sdab if (length < 2) { 92446809Sdab sprintf(nfrontp, " (empty suboption???)"); 92546809Sdab nfrontp += strlen(nfrontp); 92646809Sdab break; 92746809Sdab } 92846809Sdab switch (pointer[1]) { 92946809Sdab case TELQUAL_REPLY: 93046809Sdab case TELQUAL_IS: 93146809Sdab sprintf(nfrontp, " %s ", (pointer[1] == TELQUAL_IS) ? 93246809Sdab "IS" : "REPLY"); 93346809Sdab nfrontp += strlen(nfrontp); 93446809Sdab if (AUTHTYPE_NAME_OK(pointer[2])) 93546809Sdab sprintf(nfrontp, "%s ", AUTHTYPE_NAME(pointer[2])); 93646809Sdab else 93746809Sdab sprintf(nfrontp, "%d ", pointer[2]); 93846809Sdab nfrontp += strlen(nfrontp); 93946809Sdab if (length < 3) { 94046809Sdab sprintf(nfrontp, "(partial suboption???)"); 94146809Sdab nfrontp += strlen(nfrontp); 94246809Sdab break; 94346809Sdab } 94446809Sdab sprintf(nfrontp, "%s|%s", 945*47611Sdab ((pointer[3] & AUTH_WHO_MASK) == AUTH_WHO_CLIENT) ? 94646809Sdab "CLIENT" : "SERVER", 947*47611Sdab ((pointer[3] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) ? 94846809Sdab "MUTUAL" : "ONE-WAY"); 94946809Sdab nfrontp += strlen(nfrontp); 95046809Sdab 95146809Sdab auth_printsub(&pointer[1], length - 1, buf, sizeof(buf)); 95246809Sdab sprintf(nfrontp, "%s", buf); 95346809Sdab nfrontp += strlen(nfrontp); 95446809Sdab break; 95546809Sdab 95646809Sdab case TELQUAL_SEND: 95746809Sdab i = 2; 95846809Sdab sprintf(nfrontp, " SEND "); 95946809Sdab nfrontp += strlen(nfrontp); 96046809Sdab while (i < length) { 96146809Sdab if (AUTHTYPE_NAME_OK(pointer[i])) 96246809Sdab sprintf(nfrontp, "%s ", AUTHTYPE_NAME(pointer[i])); 96346809Sdab else 96446809Sdab sprintf(nfrontp, "%d ", pointer[i]); 96546809Sdab nfrontp += strlen(nfrontp); 96646809Sdab if (++i >= length) { 96746809Sdab sprintf(nfrontp, "(partial suboption???)"); 96846809Sdab nfrontp += strlen(nfrontp); 96946809Sdab break; 97046809Sdab } 97146809Sdab sprintf(nfrontp, "%s|%s ", 972*47611Sdab ((pointer[i] & AUTH_WHO_MASK) == AUTH_WHO_CLIENT) ? 97346809Sdab "CLIENT" : "SERVER", 974*47611Sdab ((pointer[i] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) ? 97546809Sdab "MUTUAL" : "ONE-WAY"); 97646809Sdab nfrontp += strlen(nfrontp); 97746809Sdab ++i; 97846809Sdab } 97946809Sdab break; 98046809Sdab 981*47611Sdab case TELQUAL_NAME: 982*47611Sdab i = 2; 983*47611Sdab sprintf(nfrontp, " NAME \""); 984*47611Sdab nfrontp += strlen(nfrontp); 985*47611Sdab while (i < length) 986*47611Sdab *nfrontp += pointer[i++]; 987*47611Sdab *nfrontp += '"'; 988*47611Sdab break; 989*47611Sdab 99046809Sdab default: 99146809Sdab for (i = 2; i < length; i++) { 99246809Sdab sprintf(nfrontp, " ?%d?", pointer[i]); 99346809Sdab nfrontp += strlen(nfrontp); 99446809Sdab } 99546809Sdab break; 99646809Sdab } 99746809Sdab break; 99846809Sdab #endif 99946809Sdab 100046809Sdab #if defined(ENCRYPT) 100146809Sdab case TELOPT_ENCRYPT: 100246809Sdab sprintf(nfrontp, "ENCRYPT"); 100346809Sdab nfrontp += strlen(nfrontp); 100446809Sdab if (length < 2) { 100546809Sdab sprintf(nfrontp, " (empty suboption???)"); 100646809Sdab nfrontp += strlen(nfrontp); 100746809Sdab break; 100846809Sdab } 100946809Sdab switch (pointer[1]) { 101046809Sdab case ENCRYPT_START: 101146809Sdab sprintf(nfrontp, " START"); 101246809Sdab nfrontp += strlen(nfrontp); 101346809Sdab break; 101446809Sdab 101546809Sdab case ENCRYPT_END: 101646809Sdab sprintf(nfrontp, " END"); 101746809Sdab nfrontp += strlen(nfrontp); 101846809Sdab break; 101946809Sdab 102046809Sdab case ENCRYPT_REQSTART: 102146809Sdab sprintf(nfrontp, " REQUEST-START"); 102246809Sdab nfrontp += strlen(nfrontp); 102346809Sdab break; 102446809Sdab 102546809Sdab case ENCRYPT_REQEND: 102646809Sdab sprintf(nfrontp, " REQUEST-END"); 102746809Sdab nfrontp += strlen(nfrontp); 102846809Sdab break; 102946809Sdab 103046809Sdab case ENCRYPT_IS: 103146809Sdab case ENCRYPT_REPLY: 103246809Sdab sprintf(nfrontp, " %s ", (pointer[1] == ENCRYPT_IS) ? 103346809Sdab "IS" : "REPLY"); 103446809Sdab nfrontp += strlen(nfrontp); 103546809Sdab if (length < 3) { 103646809Sdab sprintf(nfrontp, " (partial suboption???)"); 103746809Sdab nfrontp += strlen(nfrontp); 103846809Sdab break; 103946809Sdab } 104046809Sdab if (ENCTYPE_NAME_OK(pointer[2])) 104146809Sdab sprintf(nfrontp, "%s ", ENCTYPE_NAME(pointer[2])); 104246809Sdab else 104346809Sdab sprintf(nfrontp, " %d (unknown)", pointer[2]); 104446809Sdab nfrontp += strlen(nfrontp); 104546809Sdab 104646809Sdab encrypt_printsub(&pointer[1], length - 1, buf, sizeof(buf)); 104746809Sdab sprintf(nfrontp, "%s", buf); 104846809Sdab nfrontp += strlen(nfrontp); 104946809Sdab break; 105046809Sdab 105146809Sdab case ENCRYPT_SUPPORT: 105246809Sdab i = 2; 105346809Sdab sprintf(nfrontp, " SUPPORT "); 105446809Sdab nfrontp += strlen(nfrontp); 105546809Sdab while (i < length) { 105646809Sdab if (ENCTYPE_NAME_OK(pointer[i])) 105746809Sdab sprintf(nfrontp, "%s ", ENCTYPE_NAME(pointer[i])); 105846809Sdab else 105946809Sdab sprintf(nfrontp, "%d ", pointer[i]); 106046809Sdab nfrontp += strlen(nfrontp); 106146809Sdab i++; 106246809Sdab } 106346809Sdab break; 106446809Sdab 1065*47611Sdab case ENCRYPT_ENC_KEYID: 1066*47611Sdab sprintf(nfrontp, " ENC_KEYID", pointer[1]); 1067*47611Sdab nfrontp += strlen(nfrontp); 1068*47611Sdab goto encommon; 1069*47611Sdab 1070*47611Sdab case ENCRYPT_DEC_KEYID: 1071*47611Sdab sprintf(nfrontp, " DEC_KEYID", pointer[1]); 1072*47611Sdab nfrontp += strlen(nfrontp); 1073*47611Sdab goto encommon; 1074*47611Sdab 107546809Sdab default: 1076*47611Sdab sprintf(nfrontp, " %d (unknown)", pointer[1]); 107746809Sdab nfrontp += strlen(nfrontp); 1078*47611Sdab encommon: 107946809Sdab for (i = 2; i < length; i++) { 108046809Sdab sprintf(nfrontp, " %d", pointer[i]); 108146809Sdab nfrontp += strlen(nfrontp); 108246809Sdab } 108346809Sdab break; 108446809Sdab } 108546809Sdab break; 108646809Sdab #endif 108746809Sdab 108844364Sborman default: 108946809Sdab if (TELOPT_OK(pointer[0])) 109046809Sdab sprintf(nfrontp, "%s (unknown)", TELOPT(pointer[0])); 109146809Sdab else 109246809Sdab sprintf(nfrontp, "%d (unknown)", pointer[i]); 109344364Sborman nfrontp += strlen(nfrontp); 109446809Sdab for (i = 1; i < length; i++) { 109544364Sborman sprintf(nfrontp, " %d", pointer[i]); 109644364Sborman nfrontp += strlen(nfrontp); 109744364Sborman } 109844364Sborman break; 109944364Sborman } 110044364Sborman sprintf(nfrontp, "\r\n"); 110144364Sborman nfrontp += strlen(nfrontp); 110244364Sborman } 110344364Sborman 110444364Sborman /* 110544364Sborman * Dump a data buffer in hex and ascii to the output data stream. 110644364Sborman */ 110746809Sdab void 110844364Sborman printdata(tag, ptr, cnt) 110946809Sdab register char *tag; 111046809Sdab register char *ptr; 111146809Sdab register int cnt; 111244364Sborman { 111346809Sdab register int i; 111446809Sdab char xbuf[30]; 111544364Sborman 111644364Sborman while (cnt) { 111744364Sborman /* flush net output buffer if no room for new data) */ 111844364Sborman if ((&netobuf[BUFSIZ] - nfrontp) < 80) { 111944364Sborman netflush(); 112044364Sborman } 112144364Sborman 112244364Sborman /* add a line of output */ 112344364Sborman sprintf(nfrontp, "%s: ", tag); 112444364Sborman nfrontp += strlen(nfrontp); 112544364Sborman for (i = 0; i < 20 && cnt; i++) { 112644364Sborman sprintf(nfrontp, "%02x", *ptr); 112744364Sborman nfrontp += strlen(nfrontp); 112844364Sborman if (isprint(*ptr)) { 112944364Sborman xbuf[i] = *ptr; 113044364Sborman } else { 113144364Sborman xbuf[i] = '.'; 113244364Sborman } 113344364Sborman if (i % 2) { 113444364Sborman *nfrontp = ' '; 113544364Sborman nfrontp++; 113644364Sborman } 113744364Sborman cnt--; 113844364Sborman ptr++; 113944364Sborman } 114044364Sborman xbuf[i] = '\0'; 114144364Sborman sprintf(nfrontp, " %s\r\n", xbuf ); 114244364Sborman nfrontp += strlen(nfrontp); 114344364Sborman } 114444364Sborman } 114544364Sborman #endif /* DIAGNOSTICS */ 1146