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