xref: /csrg-svn/usr.bin/telnet/network.c (revision 32528)
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