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