Commit | Line | Data |
---|---|---|
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 |
14 | Ring netoring, netiring; |
15 | char netobuf[2*BUFSIZ], netibuf[BUFSIZ]; | |
8bca9c52 GM |
16 | |
17 | /* | |
18 | * Initialize internal network data structures. | |
19 | */ | |
20 | ||
21 | init_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 | ||
34 | int | |
35 | stilloob(s) | |
36 | int 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 | ||
66 | void | |
67 | setneturg() | |
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 | ||
83 | int | |
84 | netflush() | |
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 | ||
132 | static char * | |
133 | nextitem(current) | |
134 | char *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 | 179 | void |
8bca9c52 GM |
180 | netclear() |
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 | ||
221 | void | |
222 | netoprint(va_alist) | |
223 | va_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 | } |