xref: /original-bsd/usr.bin/telnet/network.c (revision b7261a4b)
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	1.14 (Berkeley) 06/01/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     }
67     if (FD_ISSET(net, &excepts)) {
68 	return 1;
69     } else {
70 	return 0;
71     }
72 }
73 
74 
75 /*
76  *  setneturg()
77  *
78  *	Sets "neturg" to the current location.
79  */
80 
81 void
82 setneturg()
83 {
84     ring_mark(&netoring);
85 }
86 
87 
88 /*
89  *  netflush
90  *		Send as much data as possible to the network,
91  *	handling requests for urgent data.
92  *
93  *		The return value indicates whether we did any
94  *	useful work.
95  */
96 
97 
98 int
99 netflush()
100 {
101     register int n, n1;
102 
103     if ((n1 = n = ring_full_consecutive(&netoring)) > 0) {
104 	if (!ring_at_mark(&netoring)) {
105 	    n = send(net, netoring.consume, n, 0);	/* normal write */
106 	} else {
107 	    /*
108 	     * In 4.2 (and 4.3) systems, there is some question about
109 	     * what byte in a sendOOB operation is the "OOB" data.
110 	     * To make ourselves compatible, we only send ONE byte
111 	     * out of band, the one WE THINK should be OOB (though
112 	     * we really have more the TCP philosophy of urgent data
113 	     * rather than the Unix philosophy of OOB data).
114 	     */
115 	    n = send(net, netoring.consume, 1, MSG_OOB);/* URGENT data */
116 	}
117     }
118     if (n < 0) {
119 	if (errno != ENOBUFS && errno != EWOULDBLOCK) {
120 	    setcommandmode();
121 	    perror(hostname);
122 	    NetClose(net);
123 	    ring_clear_mark(&netoring);
124 	    longjmp(peerdied, -1);
125 	    /*NOTREACHED*/
126 	}
127 	n = 0;
128     }
129     if (netdata && n) {
130 	Dump('>', netoring.consume, n);
131     }
132     if (n) {
133 	ring_consumed(&netoring, n);
134 	/*
135 	 * If we sent all, and more to send, then recurse to pick
136 	 * up the other half.
137 	 */
138 	if ((n1 == n) && ring_full_consecutive(&netoring)) {
139 	    (void) netflush();
140 	}
141 	return 1;
142     } else {
143 	return 0;
144     }
145 }
146