xref: /original-bsd/usr.bin/telnet/network.c (revision 96caf292)
1 /*
2  * Copyright (c) 1988 Regents of the University of California.
3  * All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  */
7 
8 #ifndef lint
9 static char sccsid[] = "@(#)network.c	5.1 (Berkeley) 09/14/90";
10 #endif /* not lint */
11 
12 #include <sys/types.h>
13 #include <sys/socket.h>
14 #include <sys/time.h>
15 
16 #include <errno.h>
17 
18 #include <arpa/telnet.h>
19 
20 #include "ring.h"
21 
22 #include "defines.h"
23 #include "externs.h"
24 #include "fdset.h"
25 
26 Ring	netoring, netiring;
27 char	netobuf[2*BUFSIZ], netibuf[BUFSIZ];
28 
29 /*
30  * Initialize internal network data structures.
31  */
32 
33 init_network()
34 {
35     if (ring_init(&netoring, netobuf, sizeof netobuf) != 1) {
36 	exit(1);
37     }
38     if (ring_init(&netiring, netibuf, sizeof netibuf) != 1) {
39 	exit(1);
40     }
41     NetTrace = stdout;
42 }
43 
44 
45 /*
46  * Check to see if any out-of-band data exists on a socket (for
47  * Telnet "synch" processing).
48  */
49 
50 int
51 stilloob()
52 {
53     static struct timeval timeout = { 0 };
54     fd_set	excepts;
55     int value;
56 
57     do {
58 	FD_ZERO(&excepts);
59 	FD_SET(net, &excepts);
60 	value = select(net+1, (fd_set *)0, (fd_set *)0, &excepts, &timeout);
61     } while ((value == -1) && (errno == EINTR));
62 
63     if (value < 0) {
64 	perror("select");
65 	(void) quit();
66 	/* NOTREACHED */
67     }
68     if (FD_ISSET(net, &excepts)) {
69 	return 1;
70     } else {
71 	return 0;
72     }
73 }
74 
75 
76 /*
77  *  setneturg()
78  *
79  *	Sets "neturg" to the current location.
80  */
81 
82 void
83 setneturg()
84 {
85     ring_mark(&netoring);
86 }
87 
88 
89 /*
90  *  netflush
91  *		Send as much data as possible to the network,
92  *	handling requests for urgent data.
93  *
94  *		The return value indicates whether we did any
95  *	useful work.
96  */
97 
98 
99 int
100 netflush()
101 {
102     register int n, n1;
103 
104     if ((n1 = n = ring_full_consecutive(&netoring)) > 0) {
105 	if (!ring_at_mark(&netoring)) {
106 	    n = send(net, netoring.consume, n, 0);	/* normal write */
107 	} else {
108 	    /*
109 	     * In 4.2 (and 4.3) systems, there is some question about
110 	     * what byte in a sendOOB operation is the "OOB" data.
111 	     * To make ourselves compatible, we only send ONE byte
112 	     * out of band, the one WE THINK should be OOB (though
113 	     * we really have more the TCP philosophy of urgent data
114 	     * rather than the Unix philosophy of OOB data).
115 	     */
116 	    n = send(net, netoring.consume, 1, MSG_OOB);/* URGENT data */
117 	}
118     }
119     if (n < 0) {
120 	if (errno != ENOBUFS && errno != EWOULDBLOCK) {
121 	    setcommandmode();
122 	    perror(hostname);
123 	    (void)NetClose(net);
124 	    ring_clear_mark(&netoring);
125 	    longjmp(peerdied, -1);
126 	    /*NOTREACHED*/
127 	}
128 	n = 0;
129     }
130     if (netdata && n) {
131 	Dump('>', netoring.consume, n);
132     }
133     if (n) {
134 	ring_consumed(&netoring, n);
135 	/*
136 	 * If we sent all, and more to send, then recurse to pick
137 	 * up the other half.
138 	 */
139 	if ((n1 == n) && ring_full_consecutive(&netoring)) {
140 	    (void) netflush();
141 	}
142 	return 1;
143     } else {
144 	return 0;
145     }
146 }
147