Commit | Line | Data |
---|---|---|
897ce52e | 1 | /* |
5faa1e35 KB |
2 | * Copyright (c) 1988, 1990, 1993 |
3 | * The Regents of the University of California. All rights reserved. | |
897ce52e | 4 | * |
cb956e54 | 5 | * %sccs.include.redist.c% |
897ce52e KB |
6 | */ |
7 | ||
8 | #ifndef lint | |
402755df | 9 | static char sccsid[] = "@(#)sys_bsd.c 8.3 (Berkeley) %G%"; |
897ce52e KB |
10 | #endif /* not lint */ |
11 | ||
e767b7ab GM |
12 | /* |
13 | * The following routines try to encapsulate what is system dependent | |
14 | * (at least between 4.x and dos) which is used in telnet.c. | |
15 | */ | |
16 | ||
e767b7ab | 17 | |
344def17 | 18 | #include <fcntl.h> |
115a5494 | 19 | #include <sys/types.h> |
e767b7ab | 20 | #include <sys/time.h> |
b307f09e | 21 | #include <sys/socket.h> |
e767b7ab | 22 | #include <signal.h> |
b307f09e | 23 | #include <errno.h> |
6055a9f6 | 24 | #include <arpa/telnet.h> |
e767b7ab | 25 | |
115a5494 GM |
26 | #include "ring.h" |
27 | ||
807a3a7d GM |
28 | #include "fdset.h" |
29 | ||
e767b7ab GM |
30 | #include "defines.h" |
31 | #include "externs.h" | |
32 | #include "types.h" | |
33 | ||
7a26b73d | 34 | #if defined(CRAY) || (defined(USE_TERMIO) && !defined(SYSV_TERMIO)) |
87b60187 PB |
35 | #define SIG_FUNC_RET void |
36 | #else | |
37 | #define SIG_FUNC_RET int | |
38 | #endif | |
39 | ||
3c2dafdd DB |
40 | #ifdef SIGINFO |
41 | extern SIG_FUNC_RET ayt_status(); | |
64331ba6 | 42 | #endif |
3c2dafdd | 43 | |
e767b7ab | 44 | int |
b307f09e GM |
45 | tout, /* Output file descriptor */ |
46 | tin, /* Input file descriptor */ | |
4ad36dea | 47 | net; |
e767b7ab | 48 | |
6055a9f6 PB |
49 | #ifndef USE_TERMIO |
50 | struct tchars otc = { 0 }, ntc = { 0 }; | |
51 | struct ltchars oltc = { 0 }, nltc = { 0 }; | |
52 | struct sgttyb ottyb = { 0 }, nttyb = { 0 }; | |
6570c863 | 53 | int olmode = 0; |
7a26b73d PB |
54 | # define cfgetispeed(ptr) (ptr)->sg_ispeed |
55 | # define cfgetospeed(ptr) (ptr)->sg_ospeed | |
56 | # define old_tc ottyb | |
6055a9f6 | 57 | |
6055a9f6 PB |
58 | #else /* USE_TERMIO */ |
59 | struct termio old_tc = { 0 }; | |
60 | extern struct termio new_tc; | |
61 | ||
7a26b73d PB |
62 | # ifndef TCSANOW |
63 | # ifdef TCSETS | |
64 | # define TCSANOW TCSETS | |
65 | # define TCSADRAIN TCSETSW | |
15d31b7e | 66 | # define tcgetattr(f, t) ioctl(f, TCGETS, (char *)t) |
7a26b73d PB |
67 | # else |
68 | # ifdef TCSETA | |
69 | # define TCSANOW TCSETA | |
70 | # define TCSADRAIN TCSETAW | |
15d31b7e | 71 | # define tcgetattr(f, t) ioctl(f, TCGETA, (char *)t) |
7a26b73d PB |
72 | # else |
73 | # define TCSANOW TIOCSETA | |
74 | # define TCSADRAIN TIOCSETAW | |
15d31b7e | 75 | # define tcgetattr(f, t) ioctl(f, TIOCGETA, (char *)t) |
7a26b73d PB |
76 | # endif |
77 | # endif | |
15d31b7e | 78 | # define tcsetattr(f, a, t) ioctl(f, a, (char *)t) |
7a26b73d PB |
79 | # define cfgetospeed(ptr) ((ptr)->c_cflag&CBAUD) |
80 | # ifdef CIBAUD | |
81 | # define cfgetispeed(ptr) (((ptr)->c_cflag&CIBAUD) >> IBSHIFT) | |
82 | # else | |
83 | # define cfgetispeed(ptr) cfgetospeed(ptr) | |
84 | # endif | |
85 | # endif /* TCSANOW */ | |
8832c633 DB |
86 | # ifdef sysV88 |
87 | # define TIOCFLUSH TC_PX_DRAIN | |
88 | # endif | |
6055a9f6 | 89 | #endif /* USE_TERMIO */ |
e767b7ab | 90 | |
b307f09e GM |
91 | static fd_set ibits, obits, xbits; |
92 | ||
93 | ||
15d31b7e | 94 | void |
b307f09e GM |
95 | init_sys() |
96 | { | |
97 | tout = fileno(stdout); | |
98 | tin = fileno(stdin); | |
99 | FD_ZERO(&ibits); | |
100 | FD_ZERO(&obits); | |
101 | FD_ZERO(&xbits); | |
102 | ||
103 | errno = 0; | |
104 | } | |
105 | ||
e767b7ab | 106 | |
15d31b7e | 107 | int |
448f9c06 | 108 | TerminalWrite(buf, n) |
15d31b7e DB |
109 | char *buf; |
110 | int n; | |
e767b7ab | 111 | { |
448f9c06 | 112 | return write(tout, buf, n); |
e767b7ab GM |
113 | } |
114 | ||
15d31b7e | 115 | int |
448f9c06 | 116 | TerminalRead(buf, n) |
15d31b7e DB |
117 | char *buf; |
118 | int n; | |
e767b7ab | 119 | { |
448f9c06 | 120 | return read(tin, buf, n); |
e767b7ab GM |
121 | } |
122 | ||
123 | /* | |
124 | * | |
125 | */ | |
126 | ||
15d31b7e | 127 | int |
310e7d0b | 128 | TerminalAutoFlush() |
e767b7ab GM |
129 | { |
130 | #if defined(LNOFLSH) | |
131 | int flush; | |
132 | ||
133 | ioctl(0, TIOCLGET, (char *)&flush); | |
134 | return !(flush&LNOFLSH); /* if LNOFLSH, no autoflush */ | |
135 | #else /* LNOFLSH */ | |
136 | return 1; | |
137 | #endif /* LNOFLSH */ | |
138 | } | |
139 | ||
6055a9f6 PB |
140 | #ifdef KLUDGELINEMODE |
141 | extern int kludgelinemode; | |
142 | #endif | |
e767b7ab GM |
143 | /* |
144 | * TerminalSpecialChars() | |
145 | * | |
146 | * Look at an input character to see if it is a special character | |
147 | * and decide what to do. | |
148 | * | |
149 | * Output: | |
150 | * | |
151 | * 0 Don't add this character. | |
152 | * 1 Do add this character | |
153 | */ | |
154 | ||
3c2dafdd DB |
155 | extern void xmitAO(), xmitEL(), xmitEC(), intp(), sendbrk(); |
156 | ||
15d31b7e | 157 | int |
310e7d0b | 158 | TerminalSpecialChars(c) |
15d31b7e | 159 | int c; |
e767b7ab | 160 | { |
6055a9f6 | 161 | if (c == termIntChar) { |
e767b7ab GM |
162 | intp(); |
163 | return 0; | |
6055a9f6 PB |
164 | } else if (c == termQuitChar) { |
165 | #ifdef KLUDGELINEMODE | |
166 | if (kludgelinemode) | |
167 | sendbrk(); | |
168 | else | |
169 | #endif | |
170 | sendabort(); | |
e767b7ab | 171 | return 0; |
6055a9f6 PB |
172 | } else if (c == termEofChar) { |
173 | if (my_want_state_is_will(TELOPT_LINEMODE)) { | |
174 | sendeof(); | |
175 | return 0; | |
176 | } | |
177 | return 1; | |
178 | } else if (c == termSuspChar) { | |
179 | sendsusp(); | |
180 | return(0); | |
181 | } else if (c == termFlushChar) { | |
e767b7ab GM |
182 | xmitAO(); /* Transmit Abort Output */ |
183 | return 0; | |
184 | } else if (!MODE_LOCAL_CHARS(globalmode)) { | |
6055a9f6 | 185 | if (c == termKillChar) { |
e767b7ab GM |
186 | xmitEL(); |
187 | return 0; | |
6055a9f6 | 188 | } else if (c == termEraseChar) { |
e767b7ab GM |
189 | xmitEC(); /* Transmit Erase Character */ |
190 | return 0; | |
191 | } | |
192 | } | |
193 | return 1; | |
194 | } | |
195 | ||
196 | ||
197 | /* | |
198 | * Flush output to the terminal | |
199 | */ | |
200 | ||
15d31b7e | 201 | void |
310e7d0b | 202 | TerminalFlushOutput() |
e767b7ab | 203 | { |
7daa10bf | 204 | #ifdef TIOCFLUSH |
e767b7ab | 205 | (void) ioctl(fileno(stdout), TIOCFLUSH, (char *) 0); |
6055a9f6 PB |
206 | #else |
207 | (void) ioctl(fileno(stdout), TCFLSH, (char *) 0); | |
208 | #endif | |
e767b7ab GM |
209 | } |
210 | ||
15d31b7e | 211 | void |
310e7d0b | 212 | TerminalSaveState() |
e767b7ab | 213 | { |
6055a9f6 | 214 | #ifndef USE_TERMIO |
e767b7ab GM |
215 | ioctl(0, TIOCGETP, (char *)&ottyb); |
216 | ioctl(0, TIOCGETC, (char *)&otc); | |
217 | ioctl(0, TIOCGLTC, (char *)&oltc); | |
6570c863 | 218 | ioctl(0, TIOCLGET, (char *)&olmode); |
e767b7ab GM |
219 | |
220 | ntc = otc; | |
221 | nltc = oltc; | |
222 | nttyb = ottyb; | |
0e29050b | 223 | |
6055a9f6 | 224 | #else /* USE_TERMIO */ |
7a26b73d | 225 | tcgetattr(0, &old_tc); |
6055a9f6 PB |
226 | |
227 | new_tc = old_tc; | |
228 | ||
7a26b73d | 229 | #ifndef VDISCARD |
4a8a7128 | 230 | termFlushChar = CONTROL('O'); |
7a26b73d PB |
231 | #endif |
232 | #ifndef VWERASE | |
4a8a7128 | 233 | termWerasChar = CONTROL('W'); |
7a26b73d PB |
234 | #endif |
235 | #ifndef VREPRINT | |
4a8a7128 | 236 | termRprntChar = CONTROL('R'); |
7a26b73d PB |
237 | #endif |
238 | #ifndef VLNEXT | |
4a8a7128 | 239 | termLiteralNextChar = CONTROL('V'); |
7a26b73d PB |
240 | #endif |
241 | #ifndef VSTART | |
4a8a7128 | 242 | termStartChar = CONTROL('Q'); |
7a26b73d PB |
243 | #endif |
244 | #ifndef VSTOP | |
4a8a7128 | 245 | termStopChar = CONTROL('S'); |
7a26b73d PB |
246 | #endif |
247 | #ifndef VSTATUS | |
248 | termAytChar = CONTROL('T'); | |
249 | #endif | |
6055a9f6 PB |
250 | #endif /* USE_TERMIO */ |
251 | } | |
252 | ||
15d31b7e | 253 | cc_t * |
6055a9f6 | 254 | tcval(func) |
15d31b7e | 255 | register int func; |
6055a9f6 PB |
256 | { |
257 | switch(func) { | |
87b60187 PB |
258 | case SLC_IP: return(&termIntChar); |
259 | case SLC_ABORT: return(&termQuitChar); | |
260 | case SLC_EOF: return(&termEofChar); | |
261 | case SLC_EC: return(&termEraseChar); | |
262 | case SLC_EL: return(&termKillChar); | |
263 | case SLC_XON: return(&termStartChar); | |
264 | case SLC_XOFF: return(&termStopChar); | |
4a8a7128 | 265 | case SLC_FORW1: return(&termForw1Char); |
7a26b73d PB |
266 | #ifdef USE_TERMIO |
267 | case SLC_FORW2: return(&termForw2Char); | |
268 | # ifdef VDISCARD | |
87b60187 | 269 | case SLC_AO: return(&termFlushChar); |
7a26b73d PB |
270 | # endif |
271 | # ifdef VSUSP | |
87b60187 | 272 | case SLC_SUSP: return(&termSuspChar); |
7a26b73d PB |
273 | # endif |
274 | # ifdef VWERASE | |
87b60187 | 275 | case SLC_EW: return(&termWerasChar); |
7a26b73d PB |
276 | # endif |
277 | # ifdef VREPRINT | |
87b60187 | 278 | case SLC_RP: return(&termRprntChar); |
7a26b73d PB |
279 | # endif |
280 | # ifdef VLNEXT | |
87b60187 | 281 | case SLC_LNEXT: return(&termLiteralNextChar); |
7a26b73d PB |
282 | # endif |
283 | # ifdef VSTATUS | |
284 | case SLC_AYT: return(&termAytChar); | |
285 | # endif | |
4a8a7128 | 286 | #endif |
6055a9f6 PB |
287 | |
288 | case SLC_SYNCH: | |
289 | case SLC_BRK: | |
6055a9f6 | 290 | case SLC_EOR: |
6055a9f6 | 291 | default: |
87b60187 | 292 | return((cc_t *)0); |
6055a9f6 PB |
293 | } |
294 | } | |
295 | ||
15d31b7e | 296 | void |
6055a9f6 PB |
297 | TerminalDefaultChars() |
298 | { | |
299 | #ifndef USE_TERMIO | |
300 | ntc = otc; | |
301 | nltc = oltc; | |
302 | nttyb.sg_kill = ottyb.sg_kill; | |
303 | nttyb.sg_erase = ottyb.sg_erase; | |
304 | #else /* USE_TERMIO */ | |
305 | memcpy(new_tc.c_cc, old_tc.c_cc, sizeof(old_tc.c_cc)); | |
7a26b73d | 306 | # ifndef VDISCARD |
4a8a7128 | 307 | termFlushChar = CONTROL('O'); |
7daa10bf PB |
308 | # endif |
309 | # ifndef VWERASE | |
4a8a7128 | 310 | termWerasChar = CONTROL('W'); |
7daa10bf PB |
311 | # endif |
312 | # ifndef VREPRINT | |
4a8a7128 | 313 | termRprntChar = CONTROL('R'); |
7daa10bf PB |
314 | # endif |
315 | # ifndef VLNEXT | |
4a8a7128 | 316 | termLiteralNextChar = CONTROL('V'); |
7daa10bf PB |
317 | # endif |
318 | # ifndef VSTART | |
4a8a7128 | 319 | termStartChar = CONTROL('Q'); |
7daa10bf PB |
320 | # endif |
321 | # ifndef VSTOP | |
4a8a7128 | 322 | termStopChar = CONTROL('S'); |
7daa10bf | 323 | # endif |
7a26b73d PB |
324 | # ifndef VSTATUS |
325 | termAytChar = CONTROL('T'); | |
326 | # endif | |
6055a9f6 | 327 | #endif /* USE_TERMIO */ |
e767b7ab GM |
328 | } |
329 | ||
4a8a7128 | 330 | #ifdef notdef |
e767b7ab | 331 | void |
310e7d0b | 332 | TerminalRestoreState() |
e767b7ab GM |
333 | { |
334 | } | |
4a8a7128 | 335 | #endif |
e767b7ab GM |
336 | |
337 | /* | |
338 | * TerminalNewMode - set up terminal to a specific mode. | |
6055a9f6 PB |
339 | * MODE_ECHO: do local terminal echo |
340 | * MODE_FLOW: do local flow control | |
341 | * MODE_TRAPSIG: do local mapping to TELNET IAC sequences | |
342 | * MODE_EDIT: do local line editing | |
343 | * | |
344 | * Command mode: | |
345 | * MODE_ECHO|MODE_EDIT|MODE_FLOW|MODE_TRAPSIG | |
346 | * local echo | |
347 | * local editing | |
348 | * local xon/xoff | |
349 | * local signal mapping | |
350 | * | |
351 | * Linemode: | |
352 | * local/no editing | |
353 | * Both Linemode and Single Character mode: | |
354 | * local/remote echo | |
355 | * local/no xon/xoff | |
356 | * local/no signal mapping | |
e767b7ab GM |
357 | */ |
358 | ||
359 | ||
15d31b7e | 360 | void |
448f9c06 | 361 | TerminalNewMode(f) |
15d31b7e | 362 | register int f; |
e767b7ab GM |
363 | { |
364 | static int prevmode = 0; | |
6055a9f6 PB |
365 | #ifndef USE_TERMIO |
366 | struct tchars tc; | |
367 | struct ltchars ltc; | |
e767b7ab | 368 | struct sgttyb sb; |
6570c863 | 369 | int lmode; |
6055a9f6 PB |
370 | #else /* USE_TERMIO */ |
371 | struct termio tmp_tc; | |
372 | #endif /* USE_TERMIO */ | |
e767b7ab GM |
373 | int onoff; |
374 | int old; | |
15d31b7e | 375 | cc_t esc; |
e767b7ab | 376 | |
6055a9f6 | 377 | globalmode = f&~MODE_FORCE; |
e767b7ab GM |
378 | if (prevmode == f) |
379 | return; | |
6055a9f6 PB |
380 | |
381 | /* | |
382 | * Write any outstanding data before switching modes | |
383 | * ttyflush() returns 0 only when there is no more data | |
384 | * left to write out, it returns -1 if it couldn't do | |
385 | * anything at all, otherwise it returns 1 + the number | |
386 | * of characters left to write. | |
7a26b73d PB |
387 | #ifndef USE_TERMIO |
388 | * We would really like ask the kernel to wait for the output | |
389 | * to drain, like we can do with the TCSADRAIN, but we don't have | |
390 | * that option. The only ioctl that waits for the output to | |
391 | * drain, TIOCSETP, also flushes the input queue, which is NOT | |
392 | * what we want (TIOCSETP is like TCSADFLUSH). | |
393 | #endif | |
6055a9f6 PB |
394 | */ |
395 | old = ttyflush(SYNCHing|flushout); | |
396 | if (old < 0 || old > 1) { | |
7a26b73d | 397 | #ifdef USE_TERMIO |
15d31b7e | 398 | tcgetattr(tin, &tmp_tc); |
6055a9f6 PB |
399 | #endif /* USE_TERMIO */ |
400 | do { | |
401 | /* | |
402 | * Wait for data to drain, then flush again. | |
403 | */ | |
7a26b73d | 404 | #ifdef USE_TERMIO |
15d31b7e | 405 | tcsetattr(tin, TCSADRAIN, &tmp_tc); |
6055a9f6 PB |
406 | #endif /* USE_TERMIO */ |
407 | old = ttyflush(SYNCHing|flushout); | |
408 | } while (old < 0 || old > 1); | |
409 | } | |
410 | ||
e767b7ab | 411 | old = prevmode; |
6055a9f6 PB |
412 | prevmode = f&~MODE_FORCE; |
413 | #ifndef USE_TERMIO | |
e767b7ab | 414 | sb = nttyb; |
6055a9f6 PB |
415 | tc = ntc; |
416 | ltc = nltc; | |
6570c863 | 417 | lmode = olmode; |
6055a9f6 PB |
418 | #else |
419 | tmp_tc = new_tc; | |
420 | #endif | |
421 | ||
422 | if (f&MODE_ECHO) { | |
423 | #ifndef USE_TERMIO | |
424 | sb.sg_flags |= ECHO; | |
425 | #else | |
426 | tmp_tc.c_lflag |= ECHO; | |
427 | tmp_tc.c_oflag |= ONLCR; | |
15d31b7e DB |
428 | if (crlf) |
429 | tmp_tc.c_iflag |= ICRNL; | |
6055a9f6 PB |
430 | #endif |
431 | } else { | |
432 | #ifndef USE_TERMIO | |
433 | sb.sg_flags &= ~ECHO; | |
434 | #else | |
435 | tmp_tc.c_lflag &= ~ECHO; | |
436 | tmp_tc.c_oflag &= ~ONLCR; | |
7daa10bf | 437 | # ifdef notdef |
15d31b7e DB |
438 | if (crlf) |
439 | tmp_tc.c_iflag &= ~ICRNL; | |
7daa10bf | 440 | # endif |
6055a9f6 PB |
441 | #endif |
442 | } | |
e767b7ab | 443 | |
6055a9f6 PB |
444 | if ((f&MODE_FLOW) == 0) { |
445 | #ifndef USE_TERMIO | |
7a26b73d PB |
446 | tc.t_startc = _POSIX_VDISABLE; |
447 | tc.t_stopc = _POSIX_VDISABLE; | |
6055a9f6 | 448 | #else |
8832c633 | 449 | tmp_tc.c_iflag &= ~(IXOFF|IXON); /* Leave the IXANY bit alone */ |
6055a9f6 | 450 | } else { |
8832c633 DB |
451 | if (restartany < 0) { |
452 | tmp_tc.c_iflag |= IXOFF|IXON; /* Leave the IXANY bit alone */ | |
453 | } else if (restartany > 0) { | |
454 | tmp_tc.c_iflag |= IXOFF|IXON|IXANY; | |
455 | } else { | |
456 | tmp_tc.c_iflag |= IXOFF|IXON; | |
457 | tmp_tc.c_iflag &= ~IXANY; | |
458 | } | |
6055a9f6 PB |
459 | #endif |
460 | } | |
e767b7ab | 461 | |
6055a9f6 PB |
462 | if ((f&MODE_TRAPSIG) == 0) { |
463 | #ifndef USE_TERMIO | |
7a26b73d PB |
464 | tc.t_intrc = _POSIX_VDISABLE; |
465 | tc.t_quitc = _POSIX_VDISABLE; | |
466 | tc.t_eofc = _POSIX_VDISABLE; | |
467 | ltc.t_suspc = _POSIX_VDISABLE; | |
468 | ltc.t_dsuspc = _POSIX_VDISABLE; | |
6055a9f6 PB |
469 | #else |
470 | tmp_tc.c_lflag &= ~ISIG; | |
471 | #endif | |
472 | localchars = 0; | |
473 | } else { | |
474 | #ifdef USE_TERMIO | |
475 | tmp_tc.c_lflag |= ISIG; | |
476 | #endif | |
477 | localchars = 1; | |
478 | } | |
479 | ||
480 | if (f&MODE_EDIT) { | |
481 | #ifndef USE_TERMIO | |
482 | sb.sg_flags &= ~CBREAK; | |
483 | sb.sg_flags |= CRMOD; | |
484 | #else | |
485 | tmp_tc.c_lflag |= ICANON; | |
486 | #endif | |
487 | } else { | |
488 | #ifndef USE_TERMIO | |
489 | sb.sg_flags |= CBREAK; | |
490 | if (f&MODE_ECHO) | |
e767b7ab | 491 | sb.sg_flags |= CRMOD; |
6055a9f6 PB |
492 | else |
493 | sb.sg_flags &= ~CRMOD; | |
494 | #else | |
495 | tmp_tc.c_lflag &= ~ICANON; | |
496 | tmp_tc.c_iflag &= ~ICRNL; | |
497 | tmp_tc.c_cc[VMIN] = 1; | |
498 | tmp_tc.c_cc[VTIME] = 0; | |
499 | #endif | |
500 | } | |
e767b7ab | 501 | |
4a8a7128 PB |
502 | if ((f&(MODE_EDIT|MODE_TRAPSIG)) == 0) { |
503 | #ifndef USE_TERMIO | |
7a26b73d | 504 | ltc.t_lnextc = _POSIX_VDISABLE; |
4a8a7128 PB |
505 | #else |
506 | # ifdef VLNEXT | |
7a26b73d | 507 | tmp_tc.c_cc[VLNEXT] = (cc_t)(_POSIX_VDISABLE); |
4a8a7128 PB |
508 | # endif |
509 | #endif | |
510 | } | |
511 | ||
512 | if (f&MODE_SOFT_TAB) { | |
513 | #ifndef USE_TERMIO | |
514 | sb.sg_flags |= XTABS; | |
515 | #else | |
516 | # ifdef OXTABS | |
517 | tmp_tc.c_oflag |= OXTABS; | |
518 | # endif | |
519 | # ifdef TABDLY | |
520 | tmp_tc.c_oflag &= ~TABDLY; | |
521 | tmp_tc.c_oflag |= TAB3; | |
522 | # endif | |
523 | #endif | |
524 | } else { | |
525 | #ifndef USE_TERMIO | |
526 | sb.sg_flags &= ~XTABS; | |
527 | #else | |
528 | # ifdef OXTABS | |
529 | tmp_tc.c_oflag &= ~OXTABS; | |
530 | # endif | |
531 | # ifdef TABDLY | |
532 | tmp_tc.c_oflag &= ~TABDLY; | |
533 | # endif | |
534 | #endif | |
535 | } | |
536 | ||
537 | if (f&MODE_LIT_ECHO) { | |
538 | #ifndef USE_TERMIO | |
15d31b7e | 539 | lmode &= ~LCTLECH; |
4a8a7128 PB |
540 | #else |
541 | # ifdef ECHOCTL | |
542 | tmp_tc.c_lflag &= ~ECHOCTL; | |
543 | # endif | |
544 | #endif | |
545 | } else { | |
546 | #ifndef USE_TERMIO | |
15d31b7e | 547 | lmode |= LCTLECH; |
4a8a7128 PB |
548 | #else |
549 | # ifdef ECHOCTL | |
550 | tmp_tc.c_lflag |= ECHOCTL; | |
551 | # endif | |
552 | #endif | |
553 | } | |
554 | ||
6055a9f6 PB |
555 | if (f == -1) { |
556 | onoff = 0; | |
557 | } else { | |
6570c863 | 558 | #ifndef USE_TERMIO |
7daa10bf | 559 | if (f & MODE_OUTBIN) |
6570c863 PB |
560 | lmode |= LLITOUT; |
561 | else | |
562 | lmode &= ~LLITOUT; | |
7daa10bf PB |
563 | |
564 | if (f & MODE_INBIN) | |
6570c863 PB |
565 | lmode |= LPASS8; |
566 | else | |
567 | lmode &= ~LPASS8; | |
568 | #else | |
7a26b73d PB |
569 | if (f & MODE_INBIN) |
570 | tmp_tc.c_iflag &= ~ISTRIP; | |
6570c863 | 571 | else |
7a26b73d PB |
572 | tmp_tc.c_iflag |= ISTRIP; |
573 | if (f & MODE_OUTBIN) { | |
7daa10bf PB |
574 | tmp_tc.c_cflag &= ~(CSIZE|PARENB); |
575 | tmp_tc.c_cflag |= CS8; | |
7a26b73d | 576 | tmp_tc.c_oflag &= ~OPOST; |
7daa10bf | 577 | } else { |
7a26b73d PB |
578 | tmp_tc.c_cflag &= ~(CSIZE|PARENB); |
579 | tmp_tc.c_cflag |= old_tc.c_cflag & (CSIZE|PARENB); | |
580 | tmp_tc.c_oflag |= OPOST; | |
7daa10bf | 581 | } |
6570c863 | 582 | #endif |
6055a9f6 PB |
583 | onoff = 1; |
584 | } | |
585 | ||
6055a9f6 | 586 | if (f != -1) { |
7daa10bf | 587 | #ifdef SIGTSTP |
64331ba6 | 588 | SIG_FUNC_RET susp(); |
7a26b73d PB |
589 | #endif /* SIGTSTP */ |
590 | #ifdef SIGINFO | |
64331ba6 DB |
591 | SIG_FUNC_RET ayt(); |
592 | #endif | |
6055a9f6 | 593 | |
7a26b73d PB |
594 | #ifdef SIGTSTP |
595 | (void) signal(SIGTSTP, susp); | |
7daa10bf | 596 | #endif /* SIGTSTP */ |
7a26b73d PB |
597 | #ifdef SIGINFO |
598 | (void) signal(SIGINFO, ayt); | |
64331ba6 | 599 | #endif |
7a26b73d PB |
600 | #if defined(USE_TERMIO) && defined(NOKERNINFO) |
601 | tmp_tc.c_lflag |= NOKERNINFO; | |
602 | #endif | |
4a8a7128 PB |
603 | /* |
604 | * We don't want to process ^Y here. It's just another | |
605 | * character that we'll pass on to the back end. It has | |
606 | * to process it because it will be processed when the | |
607 | * user attempts to read it, not when we send it. | |
608 | */ | |
609 | #ifndef USE_TERMIO | |
7a26b73d | 610 | ltc.t_dsuspc = _POSIX_VDISABLE; |
4a8a7128 PB |
611 | #else |
612 | # ifdef VDSUSP | |
7a26b73d | 613 | tmp_tc.c_cc[VDSUSP] = (cc_t)(_POSIX_VDISABLE); |
f12a5902 TH |
614 | # endif |
615 | #endif | |
87b60187 | 616 | #ifdef USE_TERMIO |
87b60187 PB |
617 | /* |
618 | * If the VEOL character is already set, then use VEOL2, | |
619 | * otherwise use VEOL. | |
620 | */ | |
15d31b7e DB |
621 | esc = (rlogin != _POSIX_VDISABLE) ? rlogin : escape; |
622 | if ((tmp_tc.c_cc[VEOL] != esc) | |
7a26b73d | 623 | # ifdef VEOL2 |
15d31b7e | 624 | && (tmp_tc.c_cc[VEOL2] != esc) |
7a26b73d | 625 | # endif |
15d31b7e | 626 | ) { |
7a26b73d | 627 | if (tmp_tc.c_cc[VEOL] == (cc_t)(_POSIX_VDISABLE)) |
15d31b7e | 628 | tmp_tc.c_cc[VEOL] = esc; |
4a8a7128 | 629 | # ifdef VEOL2 |
7a26b73d | 630 | else if (tmp_tc.c_cc[VEOL2] == (cc_t)(_POSIX_VDISABLE)) |
15d31b7e | 631 | tmp_tc.c_cc[VEOL2] = esc; |
4a8a7128 | 632 | # endif |
7a26b73d | 633 | } |
87b60187 | 634 | #else |
7a26b73d | 635 | if (tc.t_brkc == (cc_t)(_POSIX_VDISABLE)) |
15d31b7e | 636 | tc.t_brkc = esc; |
87b60187 | 637 | #endif |
6055a9f6 | 638 | } else { |
7a26b73d | 639 | #ifdef SIGINFO |
84ee7b62 DB |
640 | SIG_FUNC_RET ayt_status(); |
641 | ||
7a26b73d | 642 | (void) signal(SIGINFO, ayt_status); |
64331ba6 | 643 | #endif |
7daa10bf | 644 | #ifdef SIGTSTP |
6055a9f6 | 645 | (void) signal(SIGTSTP, SIG_DFL); |
4a8a7128 | 646 | (void) sigsetmask(sigblock(0) & ~(1<<(SIGTSTP-1))); |
7daa10bf PB |
647 | #endif /* SIGTSTP */ |
648 | #ifndef USE_TERMIO | |
649 | ltc = oltc; | |
650 | tc = otc; | |
651 | sb = ottyb; | |
4a8a7128 PB |
652 | lmode = olmode; |
653 | #else | |
654 | tmp_tc = old_tc; | |
7daa10bf | 655 | #endif |
e767b7ab | 656 | } |
7daa10bf PB |
657 | #ifndef USE_TERMIO |
658 | ioctl(tin, TIOCLSET, (char *)&lmode); | |
659 | ioctl(tin, TIOCSLTC, (char *)<c); | |
660 | ioctl(tin, TIOCSETC, (char *)&tc); | |
7a26b73d | 661 | ioctl(tin, TIOCSETN, (char *)&sb); |
7daa10bf | 662 | #else |
7a26b73d PB |
663 | if (tcsetattr(tin, TCSADRAIN, &tmp_tc) < 0) |
664 | tcsetattr(tin, TCSANOW, &tmp_tc); | |
7daa10bf PB |
665 | #endif |
666 | ||
e767b7ab | 667 | #if (!defined(TN3270)) || ((!defined(NOT43)) || defined(PUTCHAR)) |
8832c633 | 668 | # if !defined(sysV88) |
448f9c06 GM |
669 | ioctl(tin, FIONBIO, (char *)&onoff); |
670 | ioctl(tout, FIONBIO, (char *)&onoff); | |
8832c633 | 671 | # endif |
e767b7ab GM |
672 | #endif /* (!defined(TN3270)) || ((!defined(NOT43)) || defined(PUTCHAR)) */ |
673 | #if defined(TN3270) | |
4ad36dea | 674 | if (noasynchtty == 0) { |
448f9c06 | 675 | ioctl(tin, FIOASYNC, (char *)&onoff); |
e767b7ab GM |
676 | } |
677 | #endif /* defined(TN3270) */ | |
15d31b7e | 678 | |
e767b7ab GM |
679 | } |
680 | ||
402755df DB |
681 | /* |
682 | * Try to guess whether speeds are "encoded" (4.2BSD) or just numeric (4.4BSD). | |
683 | */ | |
684 | #if B4800 != 4800 | |
685 | #define DECODE_BAUD | |
686 | #endif | |
687 | ||
688 | #ifdef DECODE_BAUD | |
689 | #ifndef B7200 | |
690 | #define B7200 B4800 | |
691 | #endif | |
692 | ||
693 | #ifndef B14400 | |
694 | #define B14400 B9600 | |
695 | #endif | |
696 | ||
7daa10bf | 697 | #ifndef B19200 |
402755df DB |
698 | # define B19200 B14400 |
699 | #endif | |
700 | ||
701 | #ifndef B28800 | |
702 | #define B28800 B19200 | |
7daa10bf PB |
703 | #endif |
704 | ||
705 | #ifndef B38400 | |
402755df | 706 | # define B38400 B28800 |
7daa10bf PB |
707 | #endif |
708 | ||
402755df DB |
709 | #ifndef B57600 |
710 | #define B57600 B38400 | |
711 | #endif | |
712 | ||
713 | #ifndef B76800 | |
714 | #define B76800 B57600 | |
715 | #endif | |
716 | ||
717 | #ifndef B115200 | |
718 | #define B115200 B76800 | |
719 | #endif | |
720 | ||
721 | #ifndef B230400 | |
722 | #define B230400 B115200 | |
723 | #endif | |
724 | ||
725 | ||
7daa10bf PB |
726 | /* |
727 | * This code assumes that the values B0, B50, B75... | |
728 | * are in ascending order. They do not have to be | |
729 | * contiguous. | |
730 | */ | |
731 | struct termspeeds { | |
732 | long speed; | |
733 | long value; | |
734 | } termspeeds[] = { | |
402755df DB |
735 | { 0, B0 }, { 50, B50 }, { 75, B75 }, |
736 | { 110, B110 }, { 134, B134 }, { 150, B150 }, | |
737 | { 200, B200 }, { 300, B300 }, { 600, B600 }, | |
738 | { 1200, B1200 }, { 1800, B1800 }, { 2400, B2400 }, | |
739 | { 4800, B4800 }, { 7200, B7200 }, { 9600, B9600 }, | |
740 | { 14400, B14400 }, { 19200, B19200 }, { 28800, B28800 }, | |
741 | { 38400, B38400 }, { 57600, B57600 }, { 115200, B115200 }, | |
742 | { 230400, B230400 }, { -1, B230400 } | |
7daa10bf | 743 | }; |
402755df | 744 | #endif /* DECODE_BAUD */ |
7daa10bf | 745 | |
15d31b7e | 746 | void |
445e62ba | 747 | TerminalSpeeds(ispeed, ospeed) |
15d31b7e DB |
748 | long *ispeed; |
749 | long *ospeed; | |
445e62ba | 750 | { |
402755df | 751 | #ifdef DECODE_BAUD |
7daa10bf | 752 | register struct termspeeds *tp; |
402755df | 753 | #endif /* DECODE_BAUD */ |
7a26b73d PB |
754 | register long in, out; |
755 | ||
7a26b73d | 756 | out = cfgetospeed(&old_tc); |
15d31b7e DB |
757 | in = cfgetispeed(&old_tc); |
758 | if (in == 0) | |
759 | in = out; | |
7daa10bf | 760 | |
402755df | 761 | #ifdef DECODE_BAUD |
7daa10bf | 762 | tp = termspeeds; |
7a26b73d | 763 | while ((tp->speed != -1) && (tp->value < in)) |
7daa10bf PB |
764 | tp++; |
765 | *ispeed = tp->speed; | |
766 | ||
767 | tp = termspeeds; | |
7a26b73d | 768 | while ((tp->speed != -1) && (tp->value < out)) |
7daa10bf PB |
769 | tp++; |
770 | *ospeed = tp->speed; | |
402755df DB |
771 | #else /* DECODE_BAUD */ |
772 | *ispeed = in; | |
773 | *ospeed = out; | |
774 | #endif /* DECODE_BAUD */ | |
445e62ba GM |
775 | } |
776 | ||
15d31b7e | 777 | int |
445e62ba | 778 | TerminalWindowSize(rows, cols) |
15d31b7e | 779 | long *rows, *cols; |
445e62ba | 780 | { |
6055a9f6 | 781 | #ifdef TIOCGWINSZ |
445e62ba GM |
782 | struct winsize ws; |
783 | ||
6055a9f6 PB |
784 | if (ioctl(fileno(stdin), TIOCGWINSZ, (char *)&ws) >= 0) { |
785 | *rows = ws.ws_row; | |
786 | *cols = ws.ws_col; | |
787 | return 1; | |
445e62ba | 788 | } |
3942e0c3 | 789 | #endif /* TIOCGWINSZ */ |
6055a9f6 | 790 | return 0; |
445e62ba | 791 | } |
e767b7ab | 792 | |
15d31b7e | 793 | int |
0ea35455 | 794 | NetClose(fd) |
15d31b7e | 795 | int fd; |
e767b7ab | 796 | { |
0ea35455 | 797 | return close(fd); |
e767b7ab GM |
798 | } |
799 | ||
800 | ||
15d31b7e | 801 | void |
310e7d0b | 802 | NetNonblockingIO(fd, onoff) |
15d31b7e DB |
803 | int fd; |
804 | int onoff; | |
e767b7ab GM |
805 | { |
806 | ioctl(fd, FIONBIO, (char *)&onoff); | |
807 | } | |
808 | ||
80a47e22 | 809 | #if defined(TN3270) |
15d31b7e | 810 | void |
310e7d0b | 811 | NetSigIO(fd, onoff) |
15d31b7e DB |
812 | int fd; |
813 | int onoff; | |
e767b7ab GM |
814 | { |
815 | ioctl(fd, FIOASYNC, (char *)&onoff); /* hear about input */ | |
816 | } | |
817 | ||
15d31b7e | 818 | void |
310e7d0b | 819 | NetSetPgrp(fd) |
15d31b7e | 820 | int fd; |
e767b7ab GM |
821 | { |
822 | int myPid; | |
823 | ||
824 | myPid = getpid(); | |
344def17 | 825 | fcntl(fd, F_SETOWN, myPid); |
e767b7ab | 826 | } |
80a47e22 | 827 | #endif /*defined(TN3270)*/ |
310e7d0b GM |
828 | \f |
829 | /* | |
830 | * Various signal handling routines. | |
831 | */ | |
832 | ||
15d31b7e | 833 | /* ARGSUSED */ |
64331ba6 | 834 | SIG_FUNC_RET |
7a26b73d | 835 | deadpeer(sig) |
15d31b7e | 836 | int sig; |
310e7d0b GM |
837 | { |
838 | setcommandmode(); | |
839 | longjmp(peerdied, -1); | |
840 | } | |
841 | ||
15d31b7e | 842 | /* ARGSUSED */ |
64331ba6 | 843 | SIG_FUNC_RET |
7a26b73d | 844 | intr(sig) |
15d31b7e | 845 | int sig; |
310e7d0b GM |
846 | { |
847 | if (localchars) { | |
848 | intp(); | |
849 | return; | |
850 | } | |
851 | setcommandmode(); | |
852 | longjmp(toplevel, -1); | |
853 | } | |
e767b7ab | 854 | |
15d31b7e | 855 | /* ARGSUSED */ |
64331ba6 | 856 | SIG_FUNC_RET |
7a26b73d | 857 | intr2(sig) |
15d31b7e | 858 | int sig; |
310e7d0b GM |
859 | { |
860 | if (localchars) { | |
6055a9f6 PB |
861 | #ifdef KLUDGELINEMODE |
862 | if (kludgelinemode) | |
863 | sendbrk(); | |
864 | else | |
865 | #endif | |
866 | sendabort(); | |
310e7d0b GM |
867 | return; |
868 | } | |
869 | } | |
e767b7ab | 870 | |
7a26b73d | 871 | #ifdef SIGTSTP |
15d31b7e | 872 | /* ARGSUSED */ |
64331ba6 | 873 | SIG_FUNC_RET |
7a26b73d | 874 | susp(sig) |
15d31b7e | 875 | int sig; |
87b60187 | 876 | { |
15d31b7e DB |
877 | if ((rlogin != _POSIX_VDISABLE) && rlogin_susp()) |
878 | return; | |
87b60187 PB |
879 | if (localchars) |
880 | sendsusp(); | |
881 | } | |
7a26b73d | 882 | #endif |
87b60187 | 883 | |
7a26b73d | 884 | #ifdef SIGWINCH |
15d31b7e | 885 | /* ARGSUSED */ |
64331ba6 | 886 | SIG_FUNC_RET |
7a26b73d | 887 | sendwin(sig) |
15d31b7e | 888 | int sig; |
445e62ba GM |
889 | { |
890 | if (connected) { | |
891 | sendnaws(); | |
892 | } | |
893 | } | |
7a26b73d PB |
894 | #endif |
895 | ||
896 | #ifdef SIGINFO | |
15d31b7e | 897 | /* ARGSUSED */ |
64331ba6 | 898 | SIG_FUNC_RET |
7a26b73d | 899 | ayt(sig) |
15d31b7e | 900 | int sig; |
7a26b73d PB |
901 | { |
902 | if (connected) | |
903 | sendayt(); | |
904 | else | |
905 | ayt_status(); | |
906 | } | |
907 | #endif | |
445e62ba | 908 | |
310e7d0b | 909 | \f |
15d31b7e | 910 | void |
b307f09e GM |
911 | sys_telnet_init() |
912 | { | |
7a26b73d PB |
913 | (void) signal(SIGINT, intr); |
914 | (void) signal(SIGQUIT, intr2); | |
915 | (void) signal(SIGPIPE, deadpeer); | |
6055a9f6 | 916 | #ifdef SIGWINCH |
7a26b73d | 917 | (void) signal(SIGWINCH, sendwin); |
87b60187 PB |
918 | #endif |
919 | #ifdef SIGTSTP | |
7a26b73d PB |
920 | (void) signal(SIGTSTP, susp); |
921 | #endif | |
922 | #ifdef SIGINFO | |
923 | (void) signal(SIGINFO, ayt); | |
6055a9f6 | 924 | #endif |
310e7d0b | 925 | |
6055a9f6 | 926 | setconnmode(0); |
b307f09e GM |
927 | |
928 | NetNonblockingIO(net, 1); | |
929 | ||
930 | #if defined(TN3270) | |
4ad36dea | 931 | if (noasynchnet == 0) { /* DBX can't handle! */ |
b307f09e GM |
932 | NetSigIO(net, 1); |
933 | NetSetPgrp(net); | |
934 | } | |
935 | #endif /* defined(TN3270) */ | |
936 | ||
937 | #if defined(SO_OOBINLINE) | |
80a47e22 GM |
938 | if (SetSockOpt(net, SOL_SOCKET, SO_OOBINLINE, 1) == -1) { |
939 | perror("SetSockOpt"); | |
940 | } | |
b307f09e GM |
941 | #endif /* defined(SO_OOBINLINE) */ |
942 | } | |
943 | ||
944 | /* | |
945 | * Process rings - | |
946 | * | |
947 | * This routine tries to fill up/empty our various rings. | |
948 | * | |
949 | * The parameter specifies whether this is a poll operation, | |
950 | * or a block-until-something-happens operation. | |
951 | * | |
952 | * The return value is 1 if something happened, 0 if not. | |
953 | */ | |
954 | ||
15d31b7e | 955 | int |
b307f09e | 956 | process_rings(netin, netout, netex, ttyin, ttyout, poll) |
15d31b7e | 957 | int poll; /* If 0, then block until something to do */ |
b307f09e GM |
958 | { |
959 | register int c; | |
960 | /* One wants to be a bit careful about setting returnValue | |
961 | * to one, since a one implies we did some useful work, | |
962 | * and therefore probably won't be called to block next | |
963 | * time (TN3270 mode only). | |
964 | */ | |
965 | int returnValue = 0; | |
966 | static struct timeval TimeValue = { 0 }; | |
967 | ||
968 | if (netout) { | |
969 | FD_SET(net, &obits); | |
970 | } | |
971 | if (ttyout) { | |
972 | FD_SET(tout, &obits); | |
973 | } | |
974 | #if defined(TN3270) | |
975 | if (ttyin) { | |
976 | FD_SET(tin, &ibits); | |
977 | } | |
978 | #else /* defined(TN3270) */ | |
979 | if (ttyin) { | |
980 | FD_SET(tin, &ibits); | |
981 | } | |
982 | #endif /* defined(TN3270) */ | |
983 | #if defined(TN3270) | |
984 | if (netin) { | |
985 | FD_SET(net, &ibits); | |
986 | } | |
987 | # else /* !defined(TN3270) */ | |
988 | if (netin) { | |
989 | FD_SET(net, &ibits); | |
990 | } | |
991 | # endif /* !defined(TN3270) */ | |
992 | if (netex) { | |
993 | FD_SET(net, &xbits); | |
994 | } | |
995 | if ((c = select(16, &ibits, &obits, &xbits, | |
996 | (poll == 0)? (struct timeval *)0 : &TimeValue)) < 0) { | |
997 | if (c == -1) { | |
998 | /* | |
999 | * we can get EINTR if we are in line mode, | |
1000 | * and the user does an escape (TSTP), or | |
1001 | * some other signal generator. | |
1002 | */ | |
1003 | if (errno == EINTR) { | |
1004 | return 0; | |
1005 | } | |
1006 | # if defined(TN3270) | |
1007 | /* | |
1008 | * we can get EBADF if we were in transparent | |
1009 | * mode, and the transcom process died. | |
1010 | */ | |
1011 | if (errno == EBADF) { | |
1012 | /* | |
1013 | * zero the bits (even though kernel does it) | |
1014 | * to make sure we are selecting on the right | |
1015 | * ones. | |
1016 | */ | |
1017 | FD_ZERO(&ibits); | |
1018 | FD_ZERO(&obits); | |
1019 | FD_ZERO(&xbits); | |
1020 | return 0; | |
1021 | } | |
1022 | # endif /* defined(TN3270) */ | |
1023 | /* I don't like this, does it ever happen? */ | |
1024 | printf("sleep(5) from telnet, after select\r\n"); | |
b307f09e | 1025 | sleep(5); |
b307f09e GM |
1026 | } |
1027 | return 0; | |
1028 | } | |
1029 | ||
1030 | /* | |
1031 | * Any urgent data? | |
1032 | */ | |
1033 | if (FD_ISSET(net, &xbits)) { | |
1034 | FD_CLR(net, &xbits); | |
1035 | SYNCHing = 1; | |
4a8a7128 | 1036 | (void) ttyflush(1); /* flush already enqueued data */ |
b307f09e GM |
1037 | } |
1038 | ||
1039 | /* | |
1040 | * Something to read from the network... | |
1041 | */ | |
1042 | if (FD_ISSET(net, &ibits)) { | |
1043 | int canread; | |
1044 | ||
1045 | FD_CLR(net, &ibits); | |
1046 | canread = ring_empty_consecutive(&netiring); | |
1047 | #if !defined(SO_OOBINLINE) | |
1048 | /* | |
1049 | * In 4.2 (and some early 4.3) systems, the | |
1050 | * OOB indication and data handling in the kernel | |
1051 | * is such that if two separate TCP Urgent requests | |
1052 | * come in, one byte of TCP data will be overlaid. | |
1053 | * This is fatal for Telnet, but we try to live | |
1054 | * with it. | |
1055 | * | |
1056 | * In addition, in 4.2 (and...), a special protocol | |
1057 | * is needed to pick up the TCP Urgent data in | |
1058 | * the correct sequence. | |
1059 | * | |
1060 | * What we do is: if we think we are in urgent | |
1061 | * mode, we look to see if we are "at the mark". | |
1062 | * If we are, we do an OOB receive. If we run | |
1063 | * this twice, we will do the OOB receive twice, | |
1064 | * but the second will fail, since the second | |
1065 | * time we were "at the mark", but there wasn't | |
1066 | * any data there (the kernel doesn't reset | |
1067 | * "at the mark" until we do a normal read). | |
1068 | * Once we've read the OOB data, we go ahead | |
1069 | * and do normal reads. | |
1070 | * | |
1071 | * There is also another problem, which is that | |
1072 | * since the OOB byte we read doesn't put us | |
1073 | * out of OOB state, and since that byte is most | |
1074 | * likely the TELNET DM (data mark), we would | |
1075 | * stay in the TELNET SYNCH (SYNCHing) state. | |
1076 | * So, clocks to the rescue. If we've "just" | |
1077 | * received a DM, then we test for the | |
1078 | * presence of OOB data when the receive OOB | |
1079 | * fails (and AFTER we did the normal mode read | |
1080 | * to clear "at the mark"). | |
1081 | */ | |
1082 | if (SYNCHing) { | |
1083 | int atmark; | |
49e7660e | 1084 | static int bogus_oob = 0, first = 1; |
b307f09e GM |
1085 | |
1086 | ioctl(net, SIOCATMARK, (char *)&atmark); | |
1087 | if (atmark) { | |
1088 | c = recv(net, netiring.supply, canread, MSG_OOB); | |
1089 | if ((c == -1) && (errno == EINVAL)) { | |
1090 | c = recv(net, netiring.supply, canread, 0); | |
1091 | if (clocks.didnetreceive < clocks.gotDM) { | |
1092 | SYNCHing = stilloob(net); | |
1093 | } | |
49e7660e PB |
1094 | } else if (first && c > 0) { |
1095 | /* | |
1096 | * Bogosity check. Systems based on 4.2BSD | |
1097 | * do not return an error if you do a second | |
1098 | * recv(MSG_OOB). So, we do one. If it | |
1099 | * succeeds and returns exactly the same | |
1100 | * data, then assume that we are running | |
1101 | * on a broken system and set the bogus_oob | |
1102 | * flag. (If the data was different, then | |
1103 | * we probably got some valid new data, so | |
1104 | * increment the count...) | |
1105 | */ | |
1106 | int i; | |
1107 | i = recv(net, netiring.supply + c, canread - c, MSG_OOB); | |
1108 | if (i == c && | |
1109 | bcmp(netiring.supply, netiring.supply + c, i) == 0) { | |
1110 | bogus_oob = 1; | |
1111 | first = 0; | |
1112 | } else if (i < 0) { | |
1113 | bogus_oob = 0; | |
1114 | first = 0; | |
1115 | } else | |
1116 | c += i; | |
1117 | } | |
1118 | if (bogus_oob && c > 0) { | |
1119 | int i; | |
1120 | /* | |
1121 | * Bogosity. We have to do the read | |
1122 | * to clear the atmark to get out of | |
1123 | * an infinate loop. | |
1124 | */ | |
1125 | i = read(net, netiring.supply + c, canread - c); | |
1126 | if (i > 0) | |
1127 | c += i; | |
b307f09e GM |
1128 | } |
1129 | } else { | |
1130 | c = recv(net, netiring.supply, canread, 0); | |
1131 | } | |
1132 | } else { | |
1133 | c = recv(net, netiring.supply, canread, 0); | |
1134 | } | |
1135 | settimer(didnetreceive); | |
1136 | #else /* !defined(SO_OOBINLINE) */ | |
64331ba6 | 1137 | c = recv(net, (char *)netiring.supply, canread, 0); |
b307f09e GM |
1138 | #endif /* !defined(SO_OOBINLINE) */ |
1139 | if (c < 0 && errno == EWOULDBLOCK) { | |
1140 | c = 0; | |
1141 | } else if (c <= 0) { | |
1142 | return -1; | |
1143 | } | |
1144 | if (netdata) { | |
1145 | Dump('<', netiring.supply, c); | |
1146 | } | |
ad1c581e GM |
1147 | if (c) |
1148 | ring_supplied(&netiring, c); | |
b307f09e GM |
1149 | returnValue = 1; |
1150 | } | |
1151 | ||
1152 | /* | |
1153 | * Something to read from the tty... | |
1154 | */ | |
1155 | if (FD_ISSET(tin, &ibits)) { | |
1156 | FD_CLR(tin, &ibits); | |
448f9c06 | 1157 | c = TerminalRead(ttyiring.supply, ring_empty_consecutive(&ttyiring)); |
402755df DB |
1158 | if (c < 0 && errno == EIO) |
1159 | c = 0; | |
b307f09e GM |
1160 | if (c < 0 && errno == EWOULDBLOCK) { |
1161 | c = 0; | |
1162 | } else { | |
b307f09e | 1163 | /* EOF detection for line mode!!!! */ |
75ec5474 | 1164 | if ((c == 0) && MODE_LOCAL_CHARS(globalmode) && isatty(tin)) { |
b307f09e GM |
1165 | /* must be an EOF... */ |
1166 | *ttyiring.supply = termEofChar; | |
1167 | c = 1; | |
1168 | } | |
b307f09e GM |
1169 | if (c <= 0) { |
1170 | return -1; | |
1171 | } | |
40cc3fc2 GM |
1172 | if (termdata) { |
1173 | Dump('<', ttyiring.supply, c); | |
1174 | } | |
ad1c581e | 1175 | ring_supplied(&ttyiring, c); |
b307f09e | 1176 | } |
b307f09e GM |
1177 | returnValue = 1; /* did something useful */ |
1178 | } | |
1179 | ||
1180 | if (FD_ISSET(net, &obits)) { | |
1181 | FD_CLR(net, &obits); | |
1182 | returnValue |= netflush(); | |
1183 | } | |
1184 | if (FD_ISSET(tout, &obits)) { | |
1185 | FD_CLR(tout, &obits); | |
6055a9f6 | 1186 | returnValue |= (ttyflush(SYNCHing|flushout) > 0); |
b307f09e GM |
1187 | } |
1188 | ||
1189 | return returnValue; | |
1190 | } |