Try to move system dependent stuff to system dependent files.
[unix-history] / usr / src / usr.bin / telnet / network.c
CommitLineData
8bca9c52
GM
1#include <sys/types.h>
2#include <sys/socket.h>
3#include <sys/time.h>
4
5#include <errno.h>
6
7#include <arpa/telnet.h>
8
115a5494
GM
9#include "ring.h"
10
8bca9c52
GM
11#include "defines.h"
12#include "externs.h"
13
b307f09e
GM
14Ring netoring, netiring;
15char netobuf[2*BUFSIZ], netibuf[BUFSIZ];
8bca9c52
GM
16
17/*
18 * Initialize internal network data structures.
19 */
20
21init_network()
22{
115a5494 23 ring_init(&netoring, netobuf, sizeof netobuf);
b307f09e 24 ring_init(&netiring, netibuf, sizeof netibuf);
8bca9c52
GM
25 NetTrace = stdout;
26}
27
28
29/*
30 * Check to see if any out-of-band data exists on a socket (for
31 * Telnet "synch" processing).
32 */
33
34int
35stilloob(s)
36int s; /* socket number */
37{
38 static struct timeval timeout = { 0 };
39 fd_set excepts;
40 int value;
41
42 do {
43 FD_ZERO(&excepts);
44 FD_SET(s, &excepts);
45 value = select(s+1, (fd_set *)0, (fd_set *)0, &excepts, &timeout);
46 } while ((value == -1) && (errno == EINTR));
47
48 if (value < 0) {
49 perror("select");
50 quit();
51 }
52 if (FD_ISSET(s, &excepts)) {
53 return 1;
54 } else {
55 return 0;
56 }
57}
58
59
d732be39
GM
60/*
61 * setneturg()
62 *
63 * Sets "neturg" to the current location.
64 */
65
66void
67setneturg()
68{
115a5494 69 ring_mark(&netoring);
d732be39
GM
70}
71
72
8bca9c52
GM
73/*
74 * netflush
75 * Send as much data as possible to the network,
76 * handling requests for urgent data.
77 *
78 * The return value indicates whether we did any
79 * useful work.
80 */
81
82
83int
84netflush()
85{
86 int n;
87
8b6750f5 88 if ((n = ring_full_consecutive(&netoring)) > 0) {
115a5494 89 if (!ring_at_mark(&netoring)) {
8b6750f5 90 n = send(net, netoring.consume, n, 0); /* normal write */
8bca9c52 91 } else {
8bca9c52
GM
92 /*
93 * In 4.2 (and 4.3) systems, there is some question about
94 * what byte in a sendOOB operation is the "OOB" data.
95 * To make ourselves compatible, we only send ONE byte
96 * out of band, the one WE THINK should be OOB (though
97 * we really have more the TCP philosophy of urgent data
98 * rather than the Unix philosophy of OOB data).
99 */
8b6750f5 100 n = send(net, netoring.consume, 1, MSG_OOB);/* URGENT data */
8bca9c52
GM
101 }
102 }
103 if (n < 0) {
104 if (errno != ENOBUFS && errno != EWOULDBLOCK) {
105 setcommandmode();
106 perror(hostname);
107 NetClose(net);
115a5494 108 ring_clear_mark(&netoring);
8bca9c52
GM
109 longjmp(peerdied, -1);
110 /*NOTREACHED*/
111 }
112 n = 0;
113 }
114 if (netdata && n) {
8b6750f5 115 Dump('>', netoring.consume, n);
8bca9c52 116 }
8b6750f5 117 ring_consumed(&netoring, n);
8bca9c52
GM
118 return n > 0;
119}
120\f
121/*
122 * nextitem()
123 *
124 * Return the address of the next "item" in the TELNET data
125 * stream. This will be the address of the next character if
126 * the current address is a user data character, or it will
127 * be the address of the character following the TELNET command
128 * if the current address is a TELNET IAC ("I Am a Command")
129 * character.
130 */
131
132static char *
133nextitem(current)
134char *current;
135{
136 if ((*current&0xff) != IAC) {
137 return current+1;
138 }
139 switch (*(current+1)&0xff) {
140 case DO:
141 case DONT:
142 case WILL:
143 case WONT:
144 return current+3;
145 case SB: /* loop forever looking for the SE */
146 {
147 register char *look = current+2;
148
149 for (;;) {
150 if ((*look++&0xff) == IAC) {
151 if ((*look++&0xff) == SE) {
152 return look;
153 }
154 }
155 }
156 }
157 default:
158 return current+2;
159 }
160}
115a5494 161
8bca9c52
GM
162/*
163 * netclear()
164 *
165 * We are about to do a TELNET SYNCH operation. Clear
166 * the path to the network.
167 *
168 * Things are a bit tricky since we may have sent the first
169 * byte or so of a previous TELNET command into the network.
170 * So, we have to scan the network buffer from the beginning
171 * until we are up to where we want to be.
172 *
173 * A side effect of what we do, just to keep things
174 * simple, is to clear the urgent data pointer. The principal
175 * caller should be setting the urgent data pointer AFTER calling
176 * us in any case.
177 */
178
d732be39 179void
8bca9c52
GM
180netclear()
181{
115a5494 182#if 0 /* XXX */
8bca9c52
GM
183 register char *thisitem, *next;
184 char *good;
185#define wewant(p) ((nfrontp > p) && ((*p&0xff) == IAC) && \
186 ((*(p+1)&0xff) != EC) && ((*(p+1)&0xff) != EL))
187
188 thisitem = netobuf;
189
115a5494 190 while ((next = nextitem(thisitem)) <= netobuf.send) {
8bca9c52
GM
191 thisitem = next;
192 }
193
194 /* Now, thisitem is first before/at boundary. */
195
196 good = netobuf; /* where the good bytes go */
197
115a5494 198 while (netoring.add > thisitem) {
8bca9c52
GM
199 if (wewant(thisitem)) {
200 int length;
201
202 next = thisitem;
203 do {
204 next = nextitem(next);
205 } while (wewant(next) && (nfrontp > next));
206 length = next-thisitem;
207 memcpy(good, thisitem, length);
208 good += length;
209 thisitem = next;
210 } else {
211 thisitem = nextitem(thisitem);
212 }
213 }
214
115a5494
GM
215#endif /* 0 */
216 ring_init(&netoring, netobuf, sizeof netobuf);
217}
218
219#include <varargs.h>
220
221void
222netoprint(va_alist)
223va_dcl
224{
225 va_list ap;
226 char buffer[100]; /* where things go */
88517e1e 227 char *ptr;
115a5494 228 char *format;
88517e1e 229 char *string;
115a5494
GM
230 int i;
231
232 va_start(ap);
233
234 format = va_arg(ap, char *);
88517e1e 235 ptr = buffer;
115a5494
GM
236
237 while ((i = *format++) != 0) {
238 if (i == '%') {
239 i = *format++;
240 switch (i) {
241 case 'c':
88517e1e
GM
242 *ptr++ = va_arg(ap, int);
243 break;
244 case 's':
245 string = va_arg(ap, char *);
8b6750f5
GM
246 ring_supply_data(&netoring, buffer, ptr-buffer);
247 ring_supply_data(&netoring, string, strlen(string));
88517e1e 248 ptr = buffer;
115a5494
GM
249 break;
250 case 0:
88517e1e 251 ExitString("netoprint: trailing %%.\n", 1);
115a5494
GM
252 /*NOTREACHED*/
253 default:
254 ExitString("netoprint: unknown format character.\n", 1);
255 /*NOTREACHED*/
256 }
257 } else {
258 *ptr++ = i;
259 }
260 }
8b6750f5 261 ring_supply_data(&netoring, buffer, ptr-buffer);
8bca9c52 262}