dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / cmd / cmd-inet / usr.bin / telnet / sys_bsd.c
blob7aeff0cc1fd2e9f23367c33994e6f4a6602db64d
1 /*
2 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
3 * Use is subject to license terms.
4 */
6 /*
7 * Copyright (c) 1988, 1990, 1993
8 * The Regents of the University of California. All rights reserved.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the University of
21 * California, Berkeley and its contributors.
22 * 4. Neither the name of the University nor the names of its contributors
23 * may be used to endorse or promote products derived from this software
24 * without specific prior written permission.
26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * SUCH DAMAGE.
40 static char sccsid[] = "@(#)sys_bsd.c 8.1 (Berkeley) 6/6/93";
43 * The following routines try to encapsulate what is system dependent
44 * (at least between 4.x and dos) which is used in telnet.c.
48 #include <fcntl.h>
49 #include <sys/types.h>
50 #include <sys/time.h>
51 #include <sys/socket.h>
52 #include <sys/uio.h>
53 #include <signal.h>
54 #include <errno.h>
55 #include <arpa/telnet.h>
57 #include "ring.h"
59 #include "defines.h"
60 #include "externs.h"
61 #include "types.h"
63 #define SIG_FUNC_RET void
65 int tout; /* Output file descriptor */
66 static int tin; /* Input file descriptor */
67 int net = -1;
70 #ifndef USE_TERMIO
71 struct tchars otc = { 0 }, ntc = { 0 };
72 struct ltchars oltc = { 0 }, nltc = { 0 };
73 struct sgttyb ottyb = { 0 }, nttyb = { 0 };
74 int olmode = 0;
75 #define cfgetispeed(ptr) (ptr)->sg_ispeed
76 #define cfgetospeed(ptr) (ptr)->sg_ospeed
77 #define old_tc ottyb
79 #else /* USE_TERMIO */
80 static struct termio old_tc = { 0 };
81 extern struct termio new_tc;
82 #endif /* USE_TERMIO */
84 static fd_set ibits, obits, xbits;
86 static SIG_FUNC_RET susp(int);
87 void fatal_tty_error(char *doing_what);
90 void
91 init_sys()
93 tout = fileno(stdout);
94 tin = fileno(stdin);
95 FD_ZERO(&ibits);
96 FD_ZERO(&obits);
97 FD_ZERO(&xbits);
99 errno = 0;
104 TerminalWrite(buf, n)
105 char *buf;
106 int n;
108 return (write(tout, buf, n));
111 static int
112 TerminalRead(buf, n)
113 char *buf;
114 int n;
116 return (read(tin, buf, n));
119 #ifdef KLUDGELINEMODE
120 extern int kludgelinemode;
121 #endif
123 * TerminalSpecialChars()
125 * Look at an input character to see if it is a special character
126 * and decide what to do.
128 * Output:
130 * 0 Don't add this character.
131 * 1 Do add this character
134 TerminalSpecialChars(c)
135 int c;
138 * Don't check for signal characters here. If MODE_TRAPSIG is on,
139 * then the various signal handlers will catch the characters. If
140 * the character in question gets here, then it must have been LNEXTed
142 if (c == termQuitChar) {
143 #ifdef KLUDGELINEMODE
144 if (kludgelinemode) {
145 if (sendbrk() == -1) {
146 /* This won't return. */
147 fatal_tty_error("write");
149 return (0);
151 #endif
152 } else if (c == termFlushChar) {
153 /* Transmit Abort Output */
154 if (xmitAO() == -1) {
155 /* This won't return. */
156 fatal_tty_error("write");
158 return (0);
159 } else if (!MODE_LOCAL_CHARS(globalmode)) {
160 if (c == termKillChar) {
161 xmitEL();
162 return (0);
163 } else if (c == termEraseChar) {
164 xmitEC(); /* Transmit Erase Character */
165 return (0);
168 return (1);
173 * Flush output to the terminal
176 void
177 TerminalFlushOutput()
179 if (isatty(fileno(stdout))) {
180 (void) ioctl(fileno(stdout), TIOCFLUSH, NULL);
184 void
185 TerminalSaveState()
187 #ifndef USE_TERMIO
188 (void) ioctl(0, TIOCGETP, &ottyb);
189 (void) ioctl(0, TIOCGETC, &otc);
190 (void) ioctl(0, TIOCGLTC, &oltc);
191 (void) ioctl(0, TIOCLGET, &olmode);
193 ntc = otc;
194 nltc = oltc;
195 nttyb = ottyb;
197 #else /* USE_TERMIO */
198 (void) tcgetattr(0, &old_tc);
200 new_tc = old_tc;
201 termAytChar = CONTROL('T');
202 #endif /* USE_TERMIO */
205 cc_t *
206 tcval(func)
207 register int func;
209 switch (func) {
210 case SLC_IP: return (&termIntChar);
211 case SLC_ABORT: return (&termQuitChar);
212 case SLC_EOF: return (&termEofChar);
213 case SLC_EC: return (&termEraseChar);
214 case SLC_EL: return (&termKillChar);
215 case SLC_XON: return (&termStartChar);
216 case SLC_XOFF: return (&termStopChar);
217 case SLC_FORW1: return (&termForw1Char);
218 #ifdef USE_TERMIO
219 case SLC_FORW2: return (&termForw2Char);
220 case SLC_AO: return (&termFlushChar);
221 case SLC_SUSP: return (&termSuspChar);
222 case SLC_EW: return (&termWerasChar);
223 case SLC_RP: return (&termRprntChar);
224 case SLC_LNEXT: return (&termLiteralNextChar);
225 #endif
227 case SLC_SYNCH:
228 case SLC_BRK:
229 case SLC_EOR:
230 default:
231 return ((cc_t *)0);
235 void
236 TerminalDefaultChars()
238 #ifndef USE_TERMIO
239 ntc = otc;
240 nltc = oltc;
241 nttyb.sg_kill = ottyb.sg_kill;
242 nttyb.sg_erase = ottyb.sg_erase;
243 #else /* USE_TERMIO */
244 (void) memcpy(new_tc.c_cc, old_tc.c_cc, sizeof (old_tc.c_cc));
245 termAytChar = CONTROL('T');
246 #endif /* USE_TERMIO */
250 * TerminalNewMode - set up terminal to a specific mode.
251 * MODE_ECHO: do local terminal echo
252 * MODE_FLOW: do local flow control
253 * MODE_TRAPSIG: do local mapping to TELNET IAC sequences
254 * MODE_EDIT: do local line editing
256 * Command mode:
257 * MODE_ECHO|MODE_EDIT|MODE_FLOW|MODE_TRAPSIG
258 * local echo
259 * local editing
260 * local xon/xoff
261 * local signal mapping
263 * Linemode:
264 * local/no editing
265 * Both Linemode and Single Character mode:
266 * local/remote echo
267 * local/no xon/xoff
268 * local/no signal mapping
272 void
273 TerminalNewMode(f)
274 register int f;
276 static int prevmode = -2; /* guaranteed unique */
277 #ifndef USE_TERMIO
278 struct tchars tc;
279 struct ltchars ltc;
280 struct sgttyb sb;
281 int lmode;
282 #else /* USE_TERMIO */
283 struct termio tmp_tc;
284 #endif /* USE_TERMIO */
285 int onoff;
286 int old;
287 cc_t esc;
288 sigset_t nset;
290 globalmode = f&~MODE_FORCE;
291 if (prevmode == f)
292 return;
295 * Write any outstanding data before switching modes
296 * ttyflush() returns 0 only when there was no data
297 * to write out; it returns -1 if it couldn't do
298 * anything at all, returns -2 if there was a write
299 * error (other than EWOULDBLOCK), and otherwise it
300 * returns 1 + the number of characters left to write.
302 #ifndef USE_TERMIO
304 * We would really like ask the kernel to wait for the output
305 * to drain, like we can do with the TCSADRAIN, but we don't have
306 * that option. The only ioctl that waits for the output to
307 * drain, TIOCSETP, also flushes the input queue, which is NOT
308 * what we want(TIOCSETP is like TCSADFLUSH).
310 #endif
311 old = ttyflush(SYNCHing|flushout);
312 if (old == -1 || old > 1) {
313 #ifdef USE_TERMIO
314 (void) tcgetattr(tin, &tmp_tc);
315 #endif /* USE_TERMIO */
316 do {
318 * Wait for data to drain, then flush again.
320 #ifdef USE_TERMIO
321 (void) tcsetattr(tin, TCSADRAIN, &tmp_tc);
322 #endif /* USE_TERMIO */
323 old = ttyflush(SYNCHing|flushout);
324 } while (old == -1 || old > 1);
327 old = prevmode;
328 prevmode = f&~MODE_FORCE;
329 #ifndef USE_TERMIO
330 sb = nttyb;
331 tc = ntc;
332 ltc = nltc;
333 lmode = olmode;
334 #else
335 tmp_tc = new_tc;
336 #endif
338 if (f&MODE_ECHO) {
339 #ifndef USE_TERMIO
340 sb.sg_flags |= ECHO;
341 #else
342 tmp_tc.c_lflag |= ECHO;
343 tmp_tc.c_oflag |= ONLCR;
344 if (crlf)
345 tmp_tc.c_iflag |= ICRNL;
346 #endif
347 } else {
348 #ifndef USE_TERMIO
349 sb.sg_flags &= ~ECHO;
350 #else
351 tmp_tc.c_lflag &= ~ECHO;
352 tmp_tc.c_oflag &= ~ONLCR;
353 #ifdef notdef
354 if (crlf)
355 tmp_tc.c_iflag &= ~ICRNL;
356 #endif
357 #endif
360 if ((f&MODE_FLOW) == 0) {
361 #ifndef USE_TERMIO
362 tc.t_startc = _POSIX_VDISABLE;
363 tc.t_stopc = _POSIX_VDISABLE;
364 #else
365 tmp_tc.c_iflag &= ~(IXOFF|IXON); /* Leave the IXANY bit alone */
366 } else {
367 if (restartany < 0) {
368 /* Leave the IXANY bit alone */
369 tmp_tc.c_iflag |= IXOFF|IXON;
370 } else if (restartany > 0) {
371 tmp_tc.c_iflag |= IXOFF|IXON|IXANY;
372 } else {
373 tmp_tc.c_iflag |= IXOFF|IXON;
374 tmp_tc.c_iflag &= ~IXANY;
376 #endif
379 if ((f&MODE_TRAPSIG) == 0) {
380 #ifndef USE_TERMIO
381 tc.t_intrc = _POSIX_VDISABLE;
382 tc.t_quitc = _POSIX_VDISABLE;
383 tc.t_eofc = _POSIX_VDISABLE;
384 ltc.t_suspc = _POSIX_VDISABLE;
385 ltc.t_dsuspc = _POSIX_VDISABLE;
386 #else
387 tmp_tc.c_lflag &= ~ISIG;
388 #endif
389 localchars = 0;
390 } else {
391 #ifdef USE_TERMIO
392 tmp_tc.c_lflag |= ISIG;
393 #endif
394 localchars = 1;
397 if (f&MODE_EDIT) {
398 #ifndef USE_TERMIO
399 sb.sg_flags &= ~CBREAK;
400 sb.sg_flags |= CRMOD;
401 #else
402 tmp_tc.c_lflag |= ICANON;
403 #endif
404 } else {
405 #ifndef USE_TERMIO
406 sb.sg_flags |= CBREAK;
407 if (f&MODE_ECHO)
408 sb.sg_flags |= CRMOD;
409 else
410 sb.sg_flags &= ~CRMOD;
411 #else
412 tmp_tc.c_lflag &= ~ICANON;
413 tmp_tc.c_iflag &= ~ICRNL;
414 tmp_tc.c_cc[VMIN] = 1;
415 tmp_tc.c_cc[VTIME] = 0;
416 #endif
419 if ((f&(MODE_EDIT|MODE_TRAPSIG)) == 0) {
420 #ifndef USE_TERMIO
421 ltc.t_lnextc = _POSIX_VDISABLE;
422 #else
423 tmp_tc.c_cc[VLNEXT] = (cc_t)(_POSIX_VDISABLE);
424 #endif
427 if (f&MODE_SOFT_TAB) {
428 #ifndef USE_TERMIO
429 sb.sg_flags |= XTABS;
430 #else
431 tmp_tc.c_oflag &= ~TABDLY;
432 tmp_tc.c_oflag |= TAB3;
433 #endif
434 } else {
435 #ifndef USE_TERMIO
436 sb.sg_flags &= ~XTABS;
437 #else
438 tmp_tc.c_oflag &= ~TABDLY;
439 #endif
442 if (f&MODE_LIT_ECHO) {
443 #ifndef USE_TERMIO
444 lmode &= ~LCTLECH;
445 #else
446 tmp_tc.c_lflag &= ~ECHOCTL;
447 #endif
448 } else {
449 #ifndef USE_TERMIO
450 lmode |= LCTLECH;
451 #else
452 tmp_tc.c_lflag |= ECHOCTL;
453 #endif
456 if (f == -1) {
457 onoff = 0;
458 } else {
459 #ifndef USE_TERMIO
460 if (f & MODE_OUTBIN)
461 lmode |= LLITOUT;
462 else
463 lmode &= ~LLITOUT;
464 #else
465 if (f & MODE_OUTBIN) {
466 tmp_tc.c_cflag &= ~(CSIZE|PARENB);
467 tmp_tc.c_cflag |= CS8;
468 tmp_tc.c_oflag &= ~OPOST;
469 } else {
470 tmp_tc.c_cflag &= ~(CSIZE|PARENB);
471 tmp_tc.c_cflag |= old_tc.c_cflag & (CSIZE|PARENB);
472 tmp_tc.c_oflag |= OPOST;
474 #endif
475 onoff = 1;
478 if (f != -1) {
480 (void) signal(SIGTSTP, susp);
482 #if defined(USE_TERMIO) && defined(NOKERNINFO)
483 tmp_tc.c_lflag |= NOKERNINFO;
484 #endif
486 * We don't want to process ^Y here. It's just another
487 * character that we'll pass on to the back end. It has
488 * to process it because it will be processed when the
489 * user attempts to read it, not when we send it.
491 #ifndef USE_TERMIO
492 ltc.t_dsuspc = _POSIX_VDISABLE;
493 #else
494 tmp_tc.c_cc[VDSUSP] = (cc_t)(_POSIX_VDISABLE);
495 #endif
496 #ifdef USE_TERMIO
498 * If the VEOL character is already set, then use VEOL2,
499 * otherwise use VEOL.
501 esc = (rlogin != _POSIX_VDISABLE) ? rlogin : escape;
502 if ((tmp_tc.c_cc[VEOL] != esc)
503 /* XXX */ &&
504 (tmp_tc.c_cc[VEOL2] != esc)
505 /* XXX */) {
506 if (tmp_tc.c_cc[VEOL] == (cc_t)(_POSIX_VDISABLE))
507 tmp_tc.c_cc[VEOL] = esc;
508 else if (tmp_tc.c_cc[VEOL2] == (cc_t)(_POSIX_VDISABLE))
509 tmp_tc.c_cc[VEOL2] = esc;
511 #else
512 if (tc.t_brkc == (cc_t)(_POSIX_VDISABLE))
513 tc.t_brkc = esc;
514 #endif
515 } else {
516 (void) signal(SIGTSTP, SIG_DFL);
517 (void) sigemptyset(&nset);
518 (void) sigaddset(&nset, SIGTSTP);
519 (void) sigprocmask(SIG_UNBLOCK, &nset, 0);
520 #ifndef USE_TERMIO
521 ltc = oltc;
522 tc = otc;
523 sb = ottyb;
524 lmode = olmode;
525 #else
526 tmp_tc = old_tc;
527 #endif
529 if (isatty(tin)) {
530 #ifndef USE_TERMIO
531 (void) ioctl(tin, TIOCLSET, &lmode);
532 (void) ioctl(tin, TIOCSLTC, &ltc);
533 (void) ioctl(tin, TIOCSETC, &tc);
534 (void) ioctl(tin, TIOCSETN, &sb);
535 #else
536 if (tcsetattr(tin, TCSADRAIN, &tmp_tc) < 0)
537 (void) tcsetattr(tin, TCSANOW, &tmp_tc);
538 #endif
539 (void) ioctl(tin, FIONBIO, &onoff);
540 (void) ioctl(tout, FIONBIO, &onoff);
546 * This code assumes that the values B0, B50, B75...
547 * are in ascending order. They do not have to be
548 * contiguous.
550 static struct termspeeds {
551 int speed;
552 int value;
553 } termspeeds[] = {
554 { 0, B0 }, { 50, B50 }, { 75, B75 },
555 { 110, B110 }, { 134, B134 }, { 150, B150 },
556 { 200, B200 }, { 300, B300 }, { 600, B600 },
557 { 1200, B1200 }, { 1800, B1800 }, { 2400, B2400 },
558 { 4800, B4800 }, { 9600, B9600 }, { 19200, B19200 },
559 { 38400, B38400 }, { 57600, B57600 }, { 76800, B76800 },
560 { 115200, B115200 }, { 153600, B153600 }, { 230400, B230400 },
561 { 307200, B307200 }, { 460800, B460800 }, { 921600, B921600 },
562 { -1, B0 }
565 void
566 TerminalSpeeds(ispeed, ospeed)
567 int *ispeed;
568 int *ospeed;
570 register struct termspeeds *tp;
571 register int in, out;
573 out = cfgetospeed(&old_tc);
574 in = cfgetispeed(&old_tc);
575 if (in == 0)
576 in = out;
578 tp = termspeeds;
579 while ((tp->speed != -1) && (tp->value < in)) {
580 tp++;
582 if (tp->speed == -1)
583 tp--; /* back up to fastest defined speed */
584 *ispeed = tp->speed;
586 tp = termspeeds;
587 while ((tp->speed != -1) && (tp->value < out)) {
588 tp++;
590 if (tp->speed == -1)
591 tp--;
592 *ospeed = tp->speed;
596 TerminalWindowSize(rows, cols)
597 unsigned short *rows, *cols;
599 struct winsize ws;
601 if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) >= 0) {
602 *rows = ws.ws_row;
603 *cols = ws.ws_col;
604 return (1);
606 return (0);
609 static void
610 NetNonblockingIO(fd, onoff)
611 int fd;
612 int onoff;
614 (void) ioctl(fd, FIONBIO, &onoff);
618 * Various signal handling routines.
621 /* ARGSUSED */
622 static SIG_FUNC_RET
623 deadpeer(sig)
624 int sig;
627 * Once is all we should catch SIGPIPE. If we get it again,
628 * it means we tried to put still more data out to a pipe
629 * which has disappeared. In that case, telnet will exit.
631 (void) signal(SIGPIPE, SIG_IGN);
632 flushout = 1;
633 setcommandmode();
634 longjmp(peerdied, -1);
637 boolean_t intr_happened = B_FALSE;
638 boolean_t intr_waiting = B_FALSE;
640 /* ARGSUSED */
641 static SIG_FUNC_RET
642 intr(sig)
643 int sig;
645 if (intr_waiting) {
646 intr_happened = 1;
647 return;
649 (void) signal(SIGINT, intr);
650 if (localchars) {
651 intp();
652 return;
654 setcommandmode();
655 longjmp(toplevel, -1);
658 /* ARGSUSED */
659 static SIG_FUNC_RET
660 intr2(sig)
661 int sig;
663 (void) signal(SIGQUIT, intr2);
664 if (localchars) {
666 * Ignore return to the next two function calls
667 * since we're doing SIGQUIT
669 #ifdef KLUDGELINEMODE
670 if (kludgelinemode) {
671 (void) sendbrk();
673 else
674 #endif
675 sendabort();
676 return;
680 /* ARGSUSED */
681 static SIG_FUNC_RET
682 susp(sig)
683 int sig;
685 (void) signal(SIGTSTP, susp);
686 if ((rlogin != _POSIX_VDISABLE) && rlogin_susp())
687 return;
688 if (localchars)
689 sendsusp();
692 /* ARGSUSED */
693 static SIG_FUNC_RET
694 sendwin(sig)
695 int sig;
697 (void) signal(SIGWINCH, sendwin);
698 if (connected) {
699 sendnaws();
703 void
704 sys_telnet_init()
706 (void) signal(SIGINT, intr);
707 (void) signal(SIGQUIT, intr2);
708 (void) signal(SIGPIPE, deadpeer);
709 (void) signal(SIGWINCH, sendwin);
710 (void) signal(SIGTSTP, susp);
712 setconnmode(0);
714 NetNonblockingIO(net, 1);
716 if (SetSockOpt(net, SOL_SOCKET, SO_OOBINLINE, 1) == -1) {
717 perror("SetSockOpt");
723 * fatal_tty_error -
724 * Handle case where there is an unrecoverable error on the tty
725 * connections. Print an error, reset the terminal settings
726 * and get out as painlessly as possible.
728 void
729 fatal_tty_error(char *doing_what)
731 TerminalNewMode(-1);
732 (void) fprintf(stderr, "Error processing %s: %s\n", doing_what,
733 strerror(errno));
734 exit(1);
739 * Process rings -
741 * This routine tries to fill up/empty our various rings.
743 * The parameter specifies whether this is a poll operation,
744 * or a block-until-something-happens operation.
746 * The return value is 1 if something happened, 0 if not.
750 process_rings(netin, netout, netex, ttyin, ttyout, poll)
751 int poll; /* If 0, then block until something to do */
753 register int c;
755 * One wants to be a bit careful about setting returnValue
756 * to one, since a one implies we did some useful work,
757 * and therefore probably won't be called to block next
758 * time (TN3270 mode only).
760 int returnValue = 0;
761 static struct timeval TimeValue = { 0 };
762 int i;
764 if (netout) {
765 FD_SET(net, &obits);
767 if (ttyout) {
768 FD_SET(tout, &obits);
770 if (ttyin) {
771 FD_SET(tin, &ibits);
773 if (netin) {
774 FD_SET(net, &ibits);
776 if (netex) {
777 FD_SET(net, &xbits);
779 if ((c = select(16, &ibits, &obits, &xbits,
780 (poll == 0) ? NULL : &TimeValue)) < 0) {
781 if (c == -1) {
783 * we can get EINTR if we are in line mode,
784 * and the user does an escape (TSTP), or
785 * some other signal generator.
787 if (errno == EINTR) {
788 return (0);
790 /* I don't like this, does it ever happen? */
791 (void) printf("sleep(5) from telnet, after select\r\n");
792 (void) sleep(5);
794 return (0);
798 * Any urgent data?
800 if (FD_ISSET(net, &xbits)) {
801 FD_CLR(net, &xbits);
802 SYNCHing = 1;
804 /* flush any data that is already enqueued */
805 i = ttyflush(1);
806 if (i == -2) {
807 /* This will not return. */
808 fatal_tty_error("write");
813 * Something to read from the network...
815 if (FD_ISSET(net, &ibits)) {
816 int canread;
818 FD_CLR(net, &ibits);
819 canread = ring_empty_consecutive(&netiring);
820 c = recv(net, netiring.supply, canread, 0);
821 if (c < 0 && errno == EWOULDBLOCK) {
822 c = 0;
823 } else if (c <= 0) {
824 return (-1);
826 if (netdata) {
827 Dump('<', netiring.supply, c);
829 if (c)
830 ring_supplied(&netiring, c);
831 returnValue = 1;
835 * Something to read from the tty...
837 if (FD_ISSET(tin, &ibits)) {
838 FD_CLR(tin, &ibits);
839 c = TerminalRead((char *)ttyiring.supply,
840 ring_empty_consecutive(&ttyiring));
841 if (c < 0) {
842 if (errno != EWOULDBLOCK) {
843 /* This will not return. */
844 fatal_tty_error("read");
846 c = 0;
847 } else {
848 /* EOF detection for line mode!!!! */
849 if ((c == 0) && MODE_LOCAL_CHARS(globalmode) &&
850 isatty(tin)) {
851 /* must be an EOF... */
852 eof_pending = 1;
853 return (1);
855 if (c <= 0) {
856 returnValue = -1;
857 goto next;
859 if (termdata) {
860 Dump('<', ttyiring.supply, c);
862 ring_supplied(&ttyiring, c);
864 returnValue = 1; /* did something useful */
867 next:
868 if (FD_ISSET(net, &obits)) {
869 FD_CLR(net, &obits);
870 returnValue |= netflush();
872 if (FD_ISSET(tout, &obits)) {
873 FD_CLR(tout, &obits);
874 i = ttyflush(SYNCHing|flushout);
875 if (i == -2) {
876 /* This will not return. */
877 fatal_tty_error("write");
879 returnValue |= (i > 0);
882 return (returnValue);