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