must nullify the type to keep getnewbuf from looking for VBLK
[unix-history] / usr / src / usr.bin / telnet / sys_bsd.c
CommitLineData
897ce52e
KB
1/*
2 * Copyright (c) 1988 Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms are permitted
b36fc510
KB
6 * provided that the above copyright notice and this paragraph are
7 * duplicated in all such forms and that any documentation,
8 * advertising materials, and other materials related to such
9 * distribution and use acknowledge that the software was developed
10 * by the University of California, Berkeley. The name of the
11 * University may not be used to endorse or promote products derived
12 * from this software without specific prior written permission.
13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
897ce52e
KB
16 */
17
18#ifndef lint
6055a9f6 19static char sccsid[] = "@(#)sys_bsd.c 1.19 (Berkeley) %G%";
897ce52e
KB
20#endif /* not lint */
21
e767b7ab
GM
22/*
23 * The following routines try to encapsulate what is system dependent
24 * (at least between 4.x and dos) which is used in telnet.c.
25 */
26
27#if defined(unix)
28
344def17 29#include <fcntl.h>
115a5494 30#include <sys/types.h>
e767b7ab 31#include <sys/time.h>
b307f09e 32#include <sys/socket.h>
e767b7ab 33#include <signal.h>
b307f09e 34#include <errno.h>
6055a9f6 35#include <arpa/telnet.h>
e767b7ab 36
115a5494
GM
37#include "ring.h"
38
807a3a7d
GM
39#include "fdset.h"
40
e767b7ab
GM
41#include "defines.h"
42#include "externs.h"
43#include "types.h"
44
45int
b307f09e
GM
46 tout, /* Output file descriptor */
47 tin, /* Input file descriptor */
4ad36dea 48 net;
e767b7ab 49
6055a9f6
PB
50#ifndef USE_TERMIO
51struct tchars otc = { 0 }, ntc = { 0 };
52struct ltchars oltc = { 0 }, nltc = { 0 };
53struct sgttyb ottyb = { 0 }, nttyb = { 0 };
54
55#define ISPEED ottyb.sg_ispeed
56#define OSPEED ottyb.sg_ospeed
57#else /* USE_TERMIO */
58struct termio old_tc = { 0 };
59extern struct termio new_tc;
60
61#define ISPEED (old_tc.c_cflag&CBAUD)
62#define OSPEED ISPEED
63#endif /* USE_TERMIO */
e767b7ab 64
b307f09e
GM
65static fd_set ibits, obits, xbits;
66
67
68init_sys()
69{
70 tout = fileno(stdout);
71 tin = fileno(stdin);
72 FD_ZERO(&ibits);
73 FD_ZERO(&obits);
74 FD_ZERO(&xbits);
75
76 errno = 0;
77}
78
e767b7ab 79
448f9c06 80TerminalWrite(buf, n)
e767b7ab
GM
81char *buf;
82int n;
83{
448f9c06 84 return write(tout, buf, n);
e767b7ab
GM
85}
86
448f9c06 87TerminalRead(buf, n)
e767b7ab
GM
88char *buf;
89int n;
90{
448f9c06 91 return read(tin, buf, n);
e767b7ab
GM
92}
93
94/*
95 *
96 */
97
98int
310e7d0b 99TerminalAutoFlush()
e767b7ab
GM
100{
101#if defined(LNOFLSH)
102 int flush;
103
104 ioctl(0, TIOCLGET, (char *)&flush);
105 return !(flush&LNOFLSH); /* if LNOFLSH, no autoflush */
106#else /* LNOFLSH */
107 return 1;
108#endif /* LNOFLSH */
109}
110
6055a9f6
PB
111#ifdef KLUDGELINEMODE
112extern int kludgelinemode;
113#endif
e767b7ab
GM
114/*
115 * TerminalSpecialChars()
116 *
117 * Look at an input character to see if it is a special character
118 * and decide what to do.
119 *
120 * Output:
121 *
122 * 0 Don't add this character.
123 * 1 Do add this character
124 */
125
126int
310e7d0b 127TerminalSpecialChars(c)
e767b7ab
GM
128int c;
129{
310e7d0b 130 void xmitAO(), xmitEL(), xmitEC(), intp(), sendbrk();
e767b7ab 131
6055a9f6 132 if (c == termIntChar) {
e767b7ab
GM
133 intp();
134 return 0;
6055a9f6
PB
135 } else if (c == termQuitChar) {
136#ifdef KLUDGELINEMODE
137 if (kludgelinemode)
138 sendbrk();
139 else
140#endif
141 sendabort();
e767b7ab 142 return 0;
6055a9f6
PB
143 } else if (c == termEofChar) {
144 if (my_want_state_is_will(TELOPT_LINEMODE)) {
145 sendeof();
146 return 0;
147 }
148 return 1;
149 } else if (c == termSuspChar) {
150 sendsusp();
151 return(0);
152 } else if (c == termFlushChar) {
e767b7ab
GM
153 xmitAO(); /* Transmit Abort Output */
154 return 0;
155 } else if (!MODE_LOCAL_CHARS(globalmode)) {
6055a9f6 156 if (c == termKillChar) {
e767b7ab
GM
157 xmitEL();
158 return 0;
6055a9f6 159 } else if (c == termEraseChar) {
e767b7ab
GM
160 xmitEC(); /* Transmit Erase Character */
161 return 0;
162 }
163 }
164 return 1;
165}
166
167
168/*
169 * Flush output to the terminal
170 */
171
172void
310e7d0b 173TerminalFlushOutput()
e767b7ab 174{
6055a9f6 175#ifndef USE_TERMIO
e767b7ab 176 (void) ioctl(fileno(stdout), TIOCFLUSH, (char *) 0);
6055a9f6
PB
177#else
178 (void) ioctl(fileno(stdout), TCFLSH, (char *) 0);
179#endif
e767b7ab
GM
180}
181
182void
310e7d0b 183TerminalSaveState()
e767b7ab 184{
6055a9f6 185#ifndef USE_TERMIO
e767b7ab
GM
186 ioctl(0, TIOCGETP, (char *)&ottyb);
187 ioctl(0, TIOCGETC, (char *)&otc);
188 ioctl(0, TIOCGLTC, (char *)&oltc);
189
190 ntc = otc;
191 nltc = oltc;
192 nttyb = ottyb;
0e29050b 193
6055a9f6
PB
194#else /* USE_TERMIO */
195 ioctl(0, TCGETA, &old_tc);
196
197 new_tc = old_tc;
198
199 termFlushChar = 'O'&0x37;
200 termWerasChar = 'W'&0x37;
201 termRprntChar = 'R'&0x37;
202 termLiteralNextChar = 'V'&0x37;
203 termStartChar = 'Q'&0x37;
204 termStopChar = 'S'&0x37;
205#endif /* USE_TERMIO */
206}
207
208char *
209tcval(func)
210register int func;
211{
212 switch(func) {
213 case SLC_IP: return(&termIntChar);
214 case SLC_ABORT: return(&termQuitChar);
215 case SLC_EOF: return(&termEofChar);
216 case SLC_EC: return(&termEraseChar);
217 case SLC_EL: return(&termKillChar);
218 case SLC_XON: return(&termStartChar);
219 case SLC_XOFF: return(&termStopChar);
220#ifndef CRAY
221 case SLC_AO: return(&termFlushChar);
222 case SLC_SUSP: return(&termSuspChar);
223 case SLC_EW: return(&termWerasChar);
224 case SLC_RP: return(&termRprntChar);
225 case SLC_LNEXT: return(&termLiteralNextChar);
226#endif CRAY
227
228 case SLC_SYNCH:
229 case SLC_BRK:
230 case SLC_AYT:
231 case SLC_EOR:
232 case SLC_FORW1:
233 case SLC_FORW2:
234 default:
235 return((char *)0);
236 }
237}
238
239void
240TerminalDefaultChars()
241{
242#ifndef USE_TERMIO
243 ntc = otc;
244 nltc = oltc;
245 nttyb.sg_kill = ottyb.sg_kill;
246 nttyb.sg_erase = ottyb.sg_erase;
247#else /* USE_TERMIO */
248 memcpy(new_tc.c_cc, old_tc.c_cc, sizeof(old_tc.c_cc));
249 termFlushChar = 'O'&0x37;
250 termWerasChar = 'W'&0x37;
251 termRprntChar = 'R'&0x37;
252 termLiteralNextChar = 'V'&0x37;
253 termStartChar = 'Q'&0x37;
254 termStopChar = 'S'&0x37;
255#endif /* USE_TERMIO */
e767b7ab
GM
256}
257
258void
310e7d0b 259TerminalRestoreState()
e767b7ab
GM
260{
261}
262
263/*
264 * TerminalNewMode - set up terminal to a specific mode.
6055a9f6
PB
265 * MODE_ECHO: do local terminal echo
266 * MODE_FLOW: do local flow control
267 * MODE_TRAPSIG: do local mapping to TELNET IAC sequences
268 * MODE_EDIT: do local line editing
269 *
270 * Command mode:
271 * MODE_ECHO|MODE_EDIT|MODE_FLOW|MODE_TRAPSIG
272 * local echo
273 * local editing
274 * local xon/xoff
275 * local signal mapping
276 *
277 * Linemode:
278 * local/no editing
279 * Both Linemode and Single Character mode:
280 * local/remote echo
281 * local/no xon/xoff
282 * local/no signal mapping
e767b7ab
GM
283 */
284
285
286void
448f9c06 287TerminalNewMode(f)
e767b7ab
GM
288register int f;
289{
290 static int prevmode = 0;
6055a9f6
PB
291#ifndef USE_TERMIO
292 struct tchars tc;
293 struct ltchars ltc;
e767b7ab 294 struct sgttyb sb;
6055a9f6
PB
295#else /* USE_TERMIO */
296 struct termio tmp_tc;
297#endif /* USE_TERMIO */
e767b7ab
GM
298 int onoff;
299 int old;
e767b7ab 300
6055a9f6 301 globalmode = f&~MODE_FORCE;
e767b7ab
GM
302 if (prevmode == f)
303 return;
6055a9f6
PB
304
305 /*
306 * Write any outstanding data before switching modes
307 * ttyflush() returns 0 only when there is no more data
308 * left to write out, it returns -1 if it couldn't do
309 * anything at all, otherwise it returns 1 + the number
310 * of characters left to write.
311 */
312 old = ttyflush(SYNCHing|flushout);
313 if (old < 0 || old > 1) {
314#ifndef USE_TERMIO
315 ioctl(tin, TIOCGETP, (char *)&sb);
316#else /* USE_TERMIO */
317 ioctl(tin, TCGETA, (char *)&tmp_tc);
318#endif /* USE_TERMIO */
319 do {
320 /*
321 * Wait for data to drain, then flush again.
322 */
323#ifndef USE_TERMIO
324 ioctl(tin, TIOCSETP, (char *)&sb);
325#else /* USE_TERMIO */
326 ioctl(tin, TCSETAW, (char *)&tmp_tc);
327#endif /* USE_TERMIO */
328 old = ttyflush(SYNCHing|flushout);
329 } while (old < 0 || old > 1);
330 }
331
e767b7ab 332 old = prevmode;
6055a9f6
PB
333 prevmode = f&~MODE_FORCE;
334#ifndef USE_TERMIO
e767b7ab 335 sb = nttyb;
6055a9f6
PB
336 tc = ntc;
337 ltc = nltc;
338#else
339 tmp_tc = new_tc;
340#endif
341
342 if (f&MODE_ECHO) {
343#ifndef USE_TERMIO
344 sb.sg_flags |= ECHO;
345#else
346 tmp_tc.c_lflag |= ECHO;
347 tmp_tc.c_oflag |= ONLCR;
348 tmp_tc.c_iflag |= ICRNL;
349#endif
350 } else {
351#ifndef USE_TERMIO
352 sb.sg_flags &= ~ECHO;
353#else
354 tmp_tc.c_lflag &= ~ECHO;
355 tmp_tc.c_oflag &= ~ONLCR;
356 tmp_tc.c_iflag &= ~ICRNL;
357#endif
358 }
e767b7ab 359
6055a9f6
PB
360 if ((f&MODE_FLOW) == 0) {
361#ifndef USE_TERMIO
362 tc.t_startc = -1;
363 tc.t_stopc = -1;
364#else
365 tmp_tc.c_iflag &= ~(IXANY|IXOFF|IXON);
366 } else {
367 tmp_tc.c_iflag |= IXANY|IXOFF|IXON;
368#endif
369 }
e767b7ab 370
6055a9f6
PB
371 if ((f&MODE_TRAPSIG) == 0) {
372#ifndef USE_TERMIO
373 tc.t_intrc = -1;
374 tc.t_quitc = -1;
375 tc.t_eofc = -1;
376 ltc.t_suspc = -1;
377 ltc.t_dsuspc = -1;
378#else
379 tmp_tc.c_lflag &= ~ISIG;
380#endif
381 localchars = 0;
382 } else {
383#ifdef USE_TERMIO
384 tmp_tc.c_lflag |= ISIG;
385#endif
386 localchars = 1;
387 }
388
389 if (f&MODE_EDIT) {
390#ifndef USE_TERMIO
391 sb.sg_flags &= ~CBREAK;
392 sb.sg_flags |= CRMOD;
393#else
394 tmp_tc.c_lflag |= ICANON;
395#endif
396 } else {
397#ifndef USE_TERMIO
398 sb.sg_flags |= CBREAK;
399 if (f&MODE_ECHO)
e767b7ab 400 sb.sg_flags |= CRMOD;
6055a9f6
PB
401 else
402 sb.sg_flags &= ~CRMOD;
403#else
404 tmp_tc.c_lflag &= ~ICANON;
405 tmp_tc.c_iflag &= ~ICRNL;
406 tmp_tc.c_cc[VMIN] = 1;
407 tmp_tc.c_cc[VTIME] = 0;
408#endif
409 }
e767b7ab 410
6055a9f6
PB
411 if (f == -1) {
412 onoff = 0;
413 } else {
414 onoff = 1;
415 }
416
417#ifndef USE_TERMIO
418 if (f != -1) {
419 if (f&MODE_EDIT) {
420 void doescape();
421
422 ltc.t_suspc = escape;
423 (void) signal(SIGTSTP, (int (*)())doescape);
424 } else if (old&MODE_EDIT) {
425 (void) signal(SIGTSTP, SIG_DFL);
426 sigsetmask(sigblock(0) & ~(1<<(SIGTSTP-1)));
427 }
428 ioctl(tin, TIOCSLTC, (char *)&ltc);
429 ioctl(tin, TIOCSETC, (char *)&tc);
430 ioctl(tin, TIOCSETP, (char *)&sb);
431 } else {
432 (void) signal(SIGTSTP, SIG_DFL);
433 sigsetmask(sigblock(0) & ~(1<<(SIGTSTP-1)));
434 ioctl(tin, TIOCSLTC, (char *)&oltc);
435 ioctl(tin, TIOCSETC, (char *)&otc);
436 ioctl(tin, TIOCSETP, (char *)&ottyb);
e767b7ab 437 }
e767b7ab 438#if (!defined(TN3270)) || ((!defined(NOT43)) || defined(PUTCHAR))
448f9c06
GM
439 ioctl(tin, FIONBIO, (char *)&onoff);
440 ioctl(tout, FIONBIO, (char *)&onoff);
e767b7ab
GM
441#endif /* (!defined(TN3270)) || ((!defined(NOT43)) || defined(PUTCHAR)) */
442#if defined(TN3270)
4ad36dea 443 if (noasynchtty == 0) {
448f9c06 444 ioctl(tin, FIOASYNC, (char *)&onoff);
e767b7ab
GM
445 }
446#endif /* defined(TN3270) */
6055a9f6
PB
447#else /* USE_TERMIO */
448 if (ioctl(tin, TCSETAW, &tmp_tc) < 0)
449 ioctl(tin, TCSETA, &tmp_tc);
450#endif /* USE_TERMIO */
e767b7ab
GM
451}
452
445e62ba
GM
453void
454TerminalSpeeds(ispeed, ospeed)
455long *ispeed;
456long *ospeed;
457{
458 /*
459 * The order here is important. The index of each speed needs to
460 * correspond with the sgtty structure value for that speed.
461 *
462 * Additionally, the search algorithm assumes the table is in
463 * ascending sequence.
464 */
465 static int ttyspeeds[] = {
466 0, 50, 75, 110, 134, 150, 200, 300,
467 600, 1200, 1800, 2400, 4800, 9600, 19200, 38400 };
468#define NUMSPEEDS sizeof ttyspeeds/sizeof ttyspeeds[0]
469
6055a9f6
PB
470 if ((OSPEED < 0) || (OSPEED > NUMSPEEDS) ||
471 (ISPEED < 0) || (ISPEED > NUMSPEEDS)) {
445e62ba
GM
472 ExitString("Invalid terminal speed.");
473 /*NOTREACHED*/
474 } else {
6055a9f6
PB
475 *ispeed = ttyspeeds[ISPEED];
476 *ospeed = ttyspeeds[OSPEED];
445e62ba
GM
477 }
478}
479
480int
481TerminalWindowSize(rows, cols)
482long *rows, *cols;
483{
6055a9f6 484#ifdef TIOCGWINSZ
445e62ba
GM
485 struct winsize ws;
486
6055a9f6
PB
487 if (ioctl(fileno(stdin), TIOCGWINSZ, (char *)&ws) >= 0) {
488 *rows = ws.ws_row;
489 *cols = ws.ws_col;
490 return 1;
445e62ba 491 }
6055a9f6
PB
492#endif TIOCGWINSZ
493 return 0;
445e62ba 494}
e767b7ab
GM
495
496int
0ea35455
GM
497NetClose(fd)
498int fd;
e767b7ab 499{
0ea35455 500 return close(fd);
e767b7ab
GM
501}
502
503
504void
310e7d0b 505NetNonblockingIO(fd, onoff)
e767b7ab
GM
506int
507 fd,
508 onoff;
509{
510 ioctl(fd, FIONBIO, (char *)&onoff);
511}
512
80a47e22 513#if defined(TN3270)
e767b7ab 514void
310e7d0b 515NetSigIO(fd, onoff)
e767b7ab
GM
516int
517 fd,
518 onoff;
519{
520 ioctl(fd, FIOASYNC, (char *)&onoff); /* hear about input */
521}
522
523void
310e7d0b 524NetSetPgrp(fd)
e767b7ab
GM
525int fd;
526{
527 int myPid;
528
529 myPid = getpid();
344def17 530 fcntl(fd, F_SETOWN, myPid);
e767b7ab 531}
80a47e22 532#endif /*defined(TN3270)*/
310e7d0b
GM
533\f
534/*
535 * Various signal handling routines.
536 */
537
448f9c06 538static void
310e7d0b
GM
539deadpeer()
540{
541 setcommandmode();
542 longjmp(peerdied, -1);
543}
544
448f9c06 545static void
310e7d0b
GM
546intr()
547{
548 if (localchars) {
549 intp();
550 return;
551 }
552 setcommandmode();
553 longjmp(toplevel, -1);
554}
e767b7ab 555
448f9c06 556static void
310e7d0b
GM
557intr2()
558{
559 if (localchars) {
6055a9f6
PB
560#ifdef KLUDGELINEMODE
561 if (kludgelinemode)
562 sendbrk();
563 else
564#endif
565 sendabort();
310e7d0b
GM
566 return;
567 }
568}
e767b7ab 569
445e62ba
GM
570static void
571sendwin()
572{
573 if (connected) {
574 sendnaws();
575 }
576}
577
448f9c06 578static void
310e7d0b
GM
579doescape()
580{
6055a9f6 581 command(0, 0, 0);
310e7d0b
GM
582}
583\f
b307f09e
GM
584void
585sys_telnet_init()
586{
6055a9f6 587#ifndef CRAY
80a47e22
GM
588 (void) signal(SIGINT, (int (*)())intr);
589 (void) signal(SIGQUIT, (int (*)())intr2);
590 (void) signal(SIGPIPE, (int (*)())deadpeer);
6055a9f6
PB
591#else
592 (void) signal(SIGINT, (void (*)())intr);
593 (void) signal(SIGQUIT, (void (*)())intr2);
594 (void) signal(SIGPIPE, (void (*)())deadpeer);
595#endif
596#ifdef SIGWINCH
445e62ba 597 (void) signal(SIGWINCH, (int (*)())sendwin);
6055a9f6 598#endif
310e7d0b 599
6055a9f6 600 setconnmode(0);
b307f09e
GM
601
602 NetNonblockingIO(net, 1);
603
604#if defined(TN3270)
4ad36dea 605 if (noasynchnet == 0) { /* DBX can't handle! */
b307f09e
GM
606 NetSigIO(net, 1);
607 NetSetPgrp(net);
608 }
609#endif /* defined(TN3270) */
610
611#if defined(SO_OOBINLINE)
80a47e22
GM
612 if (SetSockOpt(net, SOL_SOCKET, SO_OOBINLINE, 1) == -1) {
613 perror("SetSockOpt");
614 }
b307f09e
GM
615#endif /* defined(SO_OOBINLINE) */
616}
617
618/*
619 * Process rings -
620 *
621 * This routine tries to fill up/empty our various rings.
622 *
623 * The parameter specifies whether this is a poll operation,
624 * or a block-until-something-happens operation.
625 *
626 * The return value is 1 if something happened, 0 if not.
627 */
628
629int
630process_rings(netin, netout, netex, ttyin, ttyout, poll)
631int poll; /* If 0, then block until something to do */
632{
633 register int c;
634 /* One wants to be a bit careful about setting returnValue
635 * to one, since a one implies we did some useful work,
636 * and therefore probably won't be called to block next
637 * time (TN3270 mode only).
638 */
639 int returnValue = 0;
640 static struct timeval TimeValue = { 0 };
641
642 if (netout) {
643 FD_SET(net, &obits);
644 }
645 if (ttyout) {
646 FD_SET(tout, &obits);
647 }
648#if defined(TN3270)
649 if (ttyin) {
650 FD_SET(tin, &ibits);
651 }
652#else /* defined(TN3270) */
653 if (ttyin) {
654 FD_SET(tin, &ibits);
655 }
656#endif /* defined(TN3270) */
657#if defined(TN3270)
658 if (netin) {
659 FD_SET(net, &ibits);
660 }
661# else /* !defined(TN3270) */
662 if (netin) {
663 FD_SET(net, &ibits);
664 }
665# endif /* !defined(TN3270) */
666 if (netex) {
667 FD_SET(net, &xbits);
668 }
669 if ((c = select(16, &ibits, &obits, &xbits,
670 (poll == 0)? (struct timeval *)0 : &TimeValue)) < 0) {
671 if (c == -1) {
672 /*
673 * we can get EINTR if we are in line mode,
674 * and the user does an escape (TSTP), or
675 * some other signal generator.
676 */
677 if (errno == EINTR) {
678 return 0;
679 }
680# if defined(TN3270)
681 /*
682 * we can get EBADF if we were in transparent
683 * mode, and the transcom process died.
684 */
685 if (errno == EBADF) {
686 /*
687 * zero the bits (even though kernel does it)
688 * to make sure we are selecting on the right
689 * ones.
690 */
691 FD_ZERO(&ibits);
692 FD_ZERO(&obits);
693 FD_ZERO(&xbits);
694 return 0;
695 }
696# endif /* defined(TN3270) */
697 /* I don't like this, does it ever happen? */
698 printf("sleep(5) from telnet, after select\r\n");
b307f09e 699 sleep(5);
b307f09e
GM
700 }
701 return 0;
702 }
703
704 /*
705 * Any urgent data?
706 */
707 if (FD_ISSET(net, &xbits)) {
708 FD_CLR(net, &xbits);
709 SYNCHing = 1;
710 ttyflush(1); /* flush already enqueued data */
711 }
712
713 /*
714 * Something to read from the network...
715 */
716 if (FD_ISSET(net, &ibits)) {
717 int canread;
718
719 FD_CLR(net, &ibits);
720 canread = ring_empty_consecutive(&netiring);
721#if !defined(SO_OOBINLINE)
722 /*
723 * In 4.2 (and some early 4.3) systems, the
724 * OOB indication and data handling in the kernel
725 * is such that if two separate TCP Urgent requests
726 * come in, one byte of TCP data will be overlaid.
727 * This is fatal for Telnet, but we try to live
728 * with it.
729 *
730 * In addition, in 4.2 (and...), a special protocol
731 * is needed to pick up the TCP Urgent data in
732 * the correct sequence.
733 *
734 * What we do is: if we think we are in urgent
735 * mode, we look to see if we are "at the mark".
736 * If we are, we do an OOB receive. If we run
737 * this twice, we will do the OOB receive twice,
738 * but the second will fail, since the second
739 * time we were "at the mark", but there wasn't
740 * any data there (the kernel doesn't reset
741 * "at the mark" until we do a normal read).
742 * Once we've read the OOB data, we go ahead
743 * and do normal reads.
744 *
745 * There is also another problem, which is that
746 * since the OOB byte we read doesn't put us
747 * out of OOB state, and since that byte is most
748 * likely the TELNET DM (data mark), we would
749 * stay in the TELNET SYNCH (SYNCHing) state.
750 * So, clocks to the rescue. If we've "just"
751 * received a DM, then we test for the
752 * presence of OOB data when the receive OOB
753 * fails (and AFTER we did the normal mode read
754 * to clear "at the mark").
755 */
756 if (SYNCHing) {
757 int atmark;
758
759 ioctl(net, SIOCATMARK, (char *)&atmark);
760 if (atmark) {
761 c = recv(net, netiring.supply, canread, MSG_OOB);
762 if ((c == -1) && (errno == EINVAL)) {
763 c = recv(net, netiring.supply, canread, 0);
764 if (clocks.didnetreceive < clocks.gotDM) {
765 SYNCHing = stilloob(net);
766 }
767 }
768 } else {
769 c = recv(net, netiring.supply, canread, 0);
770 }
771 } else {
772 c = recv(net, netiring.supply, canread, 0);
773 }
774 settimer(didnetreceive);
775#else /* !defined(SO_OOBINLINE) */
776 c = recv(net, netiring.supply, canread, 0);
777#endif /* !defined(SO_OOBINLINE) */
778 if (c < 0 && errno == EWOULDBLOCK) {
779 c = 0;
780 } else if (c <= 0) {
781 return -1;
782 }
783 if (netdata) {
784 Dump('<', netiring.supply, c);
785 }
ad1c581e
GM
786 if (c)
787 ring_supplied(&netiring, c);
b307f09e
GM
788 returnValue = 1;
789 }
790
791 /*
792 * Something to read from the tty...
793 */
794 if (FD_ISSET(tin, &ibits)) {
795 FD_CLR(tin, &ibits);
448f9c06 796 c = TerminalRead(ttyiring.supply, ring_empty_consecutive(&ttyiring));
b307f09e
GM
797 if (c < 0 && errno == EWOULDBLOCK) {
798 c = 0;
799 } else {
b307f09e 800 /* EOF detection for line mode!!!! */
75ec5474 801 if ((c == 0) && MODE_LOCAL_CHARS(globalmode) && isatty(tin)) {
b307f09e
GM
802 /* must be an EOF... */
803 *ttyiring.supply = termEofChar;
804 c = 1;
805 }
b307f09e
GM
806 if (c <= 0) {
807 return -1;
808 }
40cc3fc2
GM
809 if (termdata) {
810 Dump('<', ttyiring.supply, c);
811 }
ad1c581e 812 ring_supplied(&ttyiring, c);
b307f09e 813 }
b307f09e
GM
814 returnValue = 1; /* did something useful */
815 }
816
817 if (FD_ISSET(net, &obits)) {
818 FD_CLR(net, &obits);
819 returnValue |= netflush();
820 }
821 if (FD_ISSET(tout, &obits)) {
822 FD_CLR(tout, &obits);
6055a9f6 823 returnValue |= (ttyflush(SYNCHing|flushout) > 0);
b307f09e
GM
824 }
825
826 return returnValue;
827}
e767b7ab 828#endif /* defined(unix) */