132146Sminshall #include <sys/types.h> 232146Sminshall #include <sys/socket.h> 332146Sminshall #include <sys/time.h> 432146Sminshall 532146Sminshall #include <errno.h> 632146Sminshall 732146Sminshall #include <arpa/telnet.h> 832146Sminshall 932381Sminshall #include "ring.h" 1032381Sminshall 1132146Sminshall #include "defines.h" 1232146Sminshall #include "externs.h" 1332146Sminshall 1432381Sminshall Ring netoring; 1532381Sminshall char netobuf[2*BUFSIZ]; 1632146Sminshall 1732146Sminshall /* 1832146Sminshall * Initialize internal network data structures. 1932146Sminshall */ 2032146Sminshall 2132146Sminshall init_network() 2232146Sminshall { 2332381Sminshall ring_init(&netoring, netobuf, sizeof netobuf); 2432146Sminshall NetTrace = stdout; 2532146Sminshall } 2632146Sminshall 2732146Sminshall 2832146Sminshall /* 2932146Sminshall * Check to see if any out-of-band data exists on a socket (for 3032146Sminshall * Telnet "synch" processing). 3132146Sminshall */ 3232146Sminshall 3332146Sminshall int 3432146Sminshall stilloob(s) 3532146Sminshall int s; /* socket number */ 3632146Sminshall { 3732146Sminshall static struct timeval timeout = { 0 }; 3832146Sminshall fd_set excepts; 3932146Sminshall int value; 4032146Sminshall 4132146Sminshall do { 4232146Sminshall FD_ZERO(&excepts); 4332146Sminshall FD_SET(s, &excepts); 4432146Sminshall value = select(s+1, (fd_set *)0, (fd_set *)0, &excepts, &timeout); 4532146Sminshall } while ((value == -1) && (errno == EINTR)); 4632146Sminshall 4732146Sminshall if (value < 0) { 4832146Sminshall perror("select"); 4932146Sminshall quit(); 5032146Sminshall } 5132146Sminshall if (FD_ISSET(s, &excepts)) { 5232146Sminshall return 1; 5332146Sminshall } else { 5432146Sminshall return 0; 5532146Sminshall } 5632146Sminshall } 5732146Sminshall 5832146Sminshall 5932146Sminshall /* 6032257Sminshall * setneturg() 6132257Sminshall * 6232257Sminshall * Sets "neturg" to the current location. 6332257Sminshall */ 6432257Sminshall 6532257Sminshall void 6632257Sminshall setneturg() 6732257Sminshall { 6832381Sminshall ring_mark(&netoring); 6932257Sminshall } 7032257Sminshall 7132257Sminshall 7232257Sminshall /* 7332146Sminshall * netflush 7432146Sminshall * Send as much data as possible to the network, 7532146Sminshall * handling requests for urgent data. 7632146Sminshall * 7732146Sminshall * The return value indicates whether we did any 7832146Sminshall * useful work. 7932146Sminshall */ 8032146Sminshall 8132146Sminshall 8232146Sminshall int 8332146Sminshall netflush() 8432146Sminshall { 8532146Sminshall int n; 8632146Sminshall 87*32528Sminshall if ((n = ring_full_consecutive(&netoring)) > 0) { 8832381Sminshall if (!ring_at_mark(&netoring)) { 89*32528Sminshall n = send(net, netoring.consume, n, 0); /* normal write */ 9032146Sminshall } else { 9132146Sminshall /* 9232146Sminshall * In 4.2 (and 4.3) systems, there is some question about 9332146Sminshall * what byte in a sendOOB operation is the "OOB" data. 9432146Sminshall * To make ourselves compatible, we only send ONE byte 9532146Sminshall * out of band, the one WE THINK should be OOB (though 9632146Sminshall * we really have more the TCP philosophy of urgent data 9732146Sminshall * rather than the Unix philosophy of OOB data). 9832146Sminshall */ 99*32528Sminshall n = send(net, netoring.consume, 1, MSG_OOB);/* URGENT data */ 10032146Sminshall } 10132146Sminshall } 10232146Sminshall if (n < 0) { 10332146Sminshall if (errno != ENOBUFS && errno != EWOULDBLOCK) { 10432146Sminshall setcommandmode(); 10532146Sminshall perror(hostname); 10632146Sminshall NetClose(net); 10732381Sminshall ring_clear_mark(&netoring); 10832146Sminshall longjmp(peerdied, -1); 10932146Sminshall /*NOTREACHED*/ 11032146Sminshall } 11132146Sminshall n = 0; 11232146Sminshall } 11332146Sminshall if (netdata && n) { 114*32528Sminshall Dump('>', netoring.consume, n); 11532146Sminshall } 116*32528Sminshall ring_consumed(&netoring, n); 11732146Sminshall return n > 0; 11832146Sminshall } 11932146Sminshall 12032146Sminshall /* 12132146Sminshall * nextitem() 12232146Sminshall * 12332146Sminshall * Return the address of the next "item" in the TELNET data 12432146Sminshall * stream. This will be the address of the next character if 12532146Sminshall * the current address is a user data character, or it will 12632146Sminshall * be the address of the character following the TELNET command 12732146Sminshall * if the current address is a TELNET IAC ("I Am a Command") 12832146Sminshall * character. 12932146Sminshall */ 13032146Sminshall 13132146Sminshall static char * 13232146Sminshall nextitem(current) 13332146Sminshall char *current; 13432146Sminshall { 13532146Sminshall if ((*current&0xff) != IAC) { 13632146Sminshall return current+1; 13732146Sminshall } 13832146Sminshall switch (*(current+1)&0xff) { 13932146Sminshall case DO: 14032146Sminshall case DONT: 14132146Sminshall case WILL: 14232146Sminshall case WONT: 14332146Sminshall return current+3; 14432146Sminshall case SB: /* loop forever looking for the SE */ 14532146Sminshall { 14632146Sminshall register char *look = current+2; 14732146Sminshall 14832146Sminshall for (;;) { 14932146Sminshall if ((*look++&0xff) == IAC) { 15032146Sminshall if ((*look++&0xff) == SE) { 15132146Sminshall return look; 15232146Sminshall } 15332146Sminshall } 15432146Sminshall } 15532146Sminshall } 15632146Sminshall default: 15732146Sminshall return current+2; 15832146Sminshall } 15932146Sminshall } 16032381Sminshall 16132146Sminshall /* 16232146Sminshall * netclear() 16332146Sminshall * 16432146Sminshall * We are about to do a TELNET SYNCH operation. Clear 16532146Sminshall * the path to the network. 16632146Sminshall * 16732146Sminshall * Things are a bit tricky since we may have sent the first 16832146Sminshall * byte or so of a previous TELNET command into the network. 16932146Sminshall * So, we have to scan the network buffer from the beginning 17032146Sminshall * until we are up to where we want to be. 17132146Sminshall * 17232146Sminshall * A side effect of what we do, just to keep things 17332146Sminshall * simple, is to clear the urgent data pointer. The principal 17432146Sminshall * caller should be setting the urgent data pointer AFTER calling 17532146Sminshall * us in any case. 17632146Sminshall */ 17732146Sminshall 17832257Sminshall void 17932146Sminshall netclear() 18032146Sminshall { 18132381Sminshall #if 0 /* XXX */ 18232146Sminshall register char *thisitem, *next; 18332146Sminshall char *good; 18432146Sminshall #define wewant(p) ((nfrontp > p) && ((*p&0xff) == IAC) && \ 18532146Sminshall ((*(p+1)&0xff) != EC) && ((*(p+1)&0xff) != EL)) 18632146Sminshall 18732146Sminshall thisitem = netobuf; 18832146Sminshall 18932381Sminshall while ((next = nextitem(thisitem)) <= netobuf.send) { 19032146Sminshall thisitem = next; 19132146Sminshall } 19232146Sminshall 19332146Sminshall /* Now, thisitem is first before/at boundary. */ 19432146Sminshall 19532146Sminshall good = netobuf; /* where the good bytes go */ 19632146Sminshall 19732381Sminshall while (netoring.add > thisitem) { 19832146Sminshall if (wewant(thisitem)) { 19932146Sminshall int length; 20032146Sminshall 20132146Sminshall next = thisitem; 20232146Sminshall do { 20332146Sminshall next = nextitem(next); 20432146Sminshall } while (wewant(next) && (nfrontp > next)); 20532146Sminshall length = next-thisitem; 20632146Sminshall memcpy(good, thisitem, length); 20732146Sminshall good += length; 20832146Sminshall thisitem = next; 20932146Sminshall } else { 21032146Sminshall thisitem = nextitem(thisitem); 21132146Sminshall } 21232146Sminshall } 21332146Sminshall 21432381Sminshall #endif /* 0 */ 21532381Sminshall ring_init(&netoring, netobuf, sizeof netobuf); 21632146Sminshall } 21732381Sminshall 21832381Sminshall #include <varargs.h> 21932381Sminshall 22032381Sminshall void 22132381Sminshall netoprint(va_alist) 22232381Sminshall va_dcl 22332381Sminshall { 22432381Sminshall va_list ap; 22532381Sminshall char buffer[100]; /* where things go */ 22632382Sminshall char *ptr; 22732381Sminshall char *format; 22832382Sminshall char *string; 22932381Sminshall int i; 23032381Sminshall 23132381Sminshall va_start(ap); 23232381Sminshall 23332381Sminshall format = va_arg(ap, char *); 23432382Sminshall ptr = buffer; 23532381Sminshall 23632381Sminshall while ((i = *format++) != 0) { 23732381Sminshall if (i == '%') { 23832381Sminshall i = *format++; 23932381Sminshall switch (i) { 24032381Sminshall case 'c': 24132382Sminshall *ptr++ = va_arg(ap, int); 24232381Sminshall break; 24332382Sminshall case 's': 24432382Sminshall string = va_arg(ap, char *); 245*32528Sminshall ring_supply_data(&netoring, buffer, ptr-buffer); 246*32528Sminshall ring_supply_data(&netoring, string, strlen(string)); 24732382Sminshall ptr = buffer; 24832382Sminshall break; 24932381Sminshall case 0: 25032382Sminshall ExitString("netoprint: trailing %%.\n", 1); 25132381Sminshall /*NOTREACHED*/ 25232381Sminshall default: 25332381Sminshall ExitString("netoprint: unknown format character.\n", 1); 25432381Sminshall /*NOTREACHED*/ 25532381Sminshall } 25632381Sminshall } else { 25732381Sminshall *ptr++ = i; 25832381Sminshall } 25932381Sminshall } 260*32528Sminshall ring_supply_data(&netoring, buffer, ptr-buffer); 26132381Sminshall } 262