xref: /csrg-svn/usr.bin/telnet/network.c (revision 32667)
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"
13*32667Sminshall #include "fdset.h"
1432146Sminshall 
1532531Sminshall Ring	netoring, netiring;
1632531Sminshall char	netobuf[2*BUFSIZ], netibuf[BUFSIZ];
1732146Sminshall 
1832146Sminshall /*
1932146Sminshall  * Initialize internal network data structures.
2032146Sminshall  */
2132146Sminshall 
2232146Sminshall init_network()
2332146Sminshall {
2432381Sminshall     ring_init(&netoring, netobuf, sizeof netobuf);
2532531Sminshall     ring_init(&netiring, netibuf, sizeof netibuf);
2632146Sminshall     NetTrace = stdout;
2732146Sminshall }
2832146Sminshall 
2932146Sminshall 
3032146Sminshall /*
3132146Sminshall  * Check to see if any out-of-band data exists on a socket (for
3232146Sminshall  * Telnet "synch" processing).
3332146Sminshall  */
3432146Sminshall 
3532146Sminshall int
3632552Sminshall stilloob()
3732146Sminshall {
3832146Sminshall     static struct timeval timeout = { 0 };
3932146Sminshall     fd_set	excepts;
4032146Sminshall     int value;
4132146Sminshall 
4232146Sminshall     do {
4332146Sminshall 	FD_ZERO(&excepts);
4432552Sminshall 	FD_SET(net, &excepts);
4532552Sminshall 	value = select(net+1, (fd_set *)0, (fd_set *)0, &excepts, &timeout);
4632146Sminshall     } while ((value == -1) && (errno == EINTR));
4732146Sminshall 
4832146Sminshall     if (value < 0) {
4932146Sminshall 	perror("select");
5032146Sminshall 	quit();
5132146Sminshall     }
5232552Sminshall     if (FD_ISSET(net, &excepts)) {
5332146Sminshall 	return 1;
5432146Sminshall     } else {
5532146Sminshall 	return 0;
5632146Sminshall     }
5732146Sminshall }
5832146Sminshall 
5932146Sminshall 
6032146Sminshall /*
6132257Sminshall  *  setneturg()
6232257Sminshall  *
6332257Sminshall  *	Sets "neturg" to the current location.
6432257Sminshall  */
6532257Sminshall 
6632257Sminshall void
6732257Sminshall setneturg()
6832257Sminshall {
6932381Sminshall     ring_mark(&netoring);
7032257Sminshall }
7132257Sminshall 
7232257Sminshall 
7332257Sminshall /*
7432146Sminshall  *  netflush
7532146Sminshall  *		Send as much data as possible to the network,
7632146Sminshall  *	handling requests for urgent data.
7732146Sminshall  *
7832146Sminshall  *		The return value indicates whether we did any
7932146Sminshall  *	useful work.
8032146Sminshall  */
8132146Sminshall 
8232146Sminshall 
8332146Sminshall int
8432146Sminshall netflush()
8532146Sminshall {
86*32667Sminshall     register int n, n0, n1;
8732146Sminshall 
88*32667Sminshall     n0 = ring_full_count(&netoring);
89*32667Sminshall     if ((n1 = n = ring_full_consecutive(&netoring)) > 0) {
9032381Sminshall 	if (!ring_at_mark(&netoring)) {
9132528Sminshall 	    n = send(net, netoring.consume, n, 0);	/* normal write */
9232146Sminshall 	} else {
9332146Sminshall 	    /*
9432146Sminshall 	     * In 4.2 (and 4.3) systems, there is some question about
9532146Sminshall 	     * what byte in a sendOOB operation is the "OOB" data.
9632146Sminshall 	     * To make ourselves compatible, we only send ONE byte
9732146Sminshall 	     * out of band, the one WE THINK should be OOB (though
9832146Sminshall 	     * we really have more the TCP philosophy of urgent data
9932146Sminshall 	     * rather than the Unix philosophy of OOB data).
10032146Sminshall 	     */
10132528Sminshall 	    n = send(net, netoring.consume, 1, MSG_OOB);/* URGENT data */
10232146Sminshall 	}
10332146Sminshall     }
10432146Sminshall     if (n < 0) {
10532146Sminshall 	if (errno != ENOBUFS && errno != EWOULDBLOCK) {
106*32667Sminshall 	abortit:
10732146Sminshall 	    setcommandmode();
10832146Sminshall 	    perror(hostname);
10932146Sminshall 	    NetClose(net);
11032381Sminshall 	    ring_clear_mark(&netoring);
11132146Sminshall 	    longjmp(peerdied, -1);
11232146Sminshall 	    /*NOTREACHED*/
11332146Sminshall 	}
11432146Sminshall 	n = 0;
11532146Sminshall     }
11632146Sminshall     if (netdata && n) {
11732528Sminshall 	Dump('>', netoring.consume, n);
11832146Sminshall     }
119*32667Sminshall     if (n) {
120*32667Sminshall 	if (n1 == n && n0 > n && !ring_at_mark(&netoring)) {
121*32667Sminshall 	    n1 = send(net, netoring.bottom, n0 - n, 0);
122*32667Sminshall 	    if (n1 < 0) {
123*32667Sminshall 		if (errno != ENOBUFS && errno != EWOULDBLOCK) {
124*32667Sminshall 		    goto abortit;
125*32667Sminshall 		}
126*32667Sminshall 	    }
127*32667Sminshall 	    if (netdata && n1) {
128*32667Sminshall 		Dump('>', netoring.bottom, n1);
129*32667Sminshall 	    }
130*32667Sminshall 	    n += n1;
131*32667Sminshall 	}
132*32667Sminshall 	ring_consumed(&netoring, n);
133*32667Sminshall     }
13432146Sminshall     return n > 0;
13532146Sminshall }
136