132147Sminshall /* 233685Sbostic * Copyright (c) 1988 Regents of the University of California. 333685Sbostic * All rights reserved. 433685Sbostic * 533685Sbostic * Redistribution and use in source and binary forms are permitted 633685Sbostic * provided that this notice is preserved and that due credit is given 733685Sbostic * to the University of California at Berkeley. The name of the University 833685Sbostic * may not be used to endorse or promote products derived from this 933685Sbostic * software without specific prior written permission. This software 1033685Sbostic * is provided ``as is'' without express or implied warranty. 1133685Sbostic */ 1233685Sbostic 1333685Sbostic #ifndef lint 14*34849Sminshall static char sccsid[] = "@(#)sys_bsd.c 1.12 (Berkeley) 06/27/88"; 1533685Sbostic #endif /* not lint */ 1633685Sbostic 1733685Sbostic /* 1832147Sminshall * The following routines try to encapsulate what is system dependent 1932147Sminshall * (at least between 4.x and dos) which is used in telnet.c. 2032147Sminshall */ 2132147Sminshall 2232147Sminshall #if defined(unix) 2332147Sminshall 2432147Sminshall #include <sys/ioctl.h> 2532381Sminshall #include <sys/types.h> 2632147Sminshall #include <sys/time.h> 2732531Sminshall #include <sys/socket.h> 2832147Sminshall #include <signal.h> 2932531Sminshall #include <errno.h> 3032147Sminshall 3132381Sminshall #include "ring.h" 3232381Sminshall 3332657Sminshall #include "fdset.h" 3432657Sminshall 3532147Sminshall #include "defines.h" 3632147Sminshall #include "externs.h" 3732147Sminshall #include "types.h" 3832147Sminshall 3932147Sminshall int 4032531Sminshall tout, /* Output file descriptor */ 4132531Sminshall tin, /* Input file descriptor */ 4232531Sminshall net, 4332147Sminshall HaveInput; /* There is input available to scan */ 4432147Sminshall 4532147Sminshall static struct tchars otc = { 0 }, ntc = { 0 }; 4632147Sminshall static struct ltchars oltc = { 0 }, nltc = { 0 }; 4732147Sminshall static struct sgttyb ottyb = { 0 }, nttyb = { 0 }; 4832147Sminshall 4932531Sminshall static fd_set ibits, obits, xbits; 5032147Sminshall 5132531Sminshall 5232531Sminshall init_sys() 5332531Sminshall { 5432531Sminshall tout = fileno(stdout); 5532531Sminshall tin = fileno(stdin); 5632531Sminshall FD_ZERO(&ibits); 5732531Sminshall FD_ZERO(&obits); 5832531Sminshall FD_ZERO(&xbits); 5932531Sminshall 6032531Sminshall errno = 0; 6132531Sminshall } 6232531Sminshall 6332531Sminshall 6433286Sminshall TerminalWrite(buf, n) 6532147Sminshall char *buf; 6632147Sminshall int n; 6732147Sminshall { 6833286Sminshall return write(tout, buf, n); 6932147Sminshall } 7032147Sminshall 7133286Sminshall TerminalRead(buf, n) 7232147Sminshall char *buf; 7332147Sminshall int n; 7432147Sminshall { 7533286Sminshall return read(tin, buf, n); 7632147Sminshall } 7732147Sminshall 7832147Sminshall /* 7932147Sminshall * 8032147Sminshall */ 8132147Sminshall 8232147Sminshall int 8332553Sminshall TerminalAutoFlush() 8432147Sminshall { 8532147Sminshall #if defined(LNOFLSH) 8632147Sminshall int flush; 8732147Sminshall 8832147Sminshall ioctl(0, TIOCLGET, (char *)&flush); 8932147Sminshall return !(flush&LNOFLSH); /* if LNOFLSH, no autoflush */ 9032147Sminshall #else /* LNOFLSH */ 9132147Sminshall return 1; 9232147Sminshall #endif /* LNOFLSH */ 9332147Sminshall } 9432147Sminshall 9532147Sminshall /* 9632147Sminshall * TerminalSpecialChars() 9732147Sminshall * 9832147Sminshall * Look at an input character to see if it is a special character 9932147Sminshall * and decide what to do. 10032147Sminshall * 10132147Sminshall * Output: 10232147Sminshall * 10332147Sminshall * 0 Don't add this character. 10432147Sminshall * 1 Do add this character 10532147Sminshall */ 10632147Sminshall 10732147Sminshall int 10832553Sminshall TerminalSpecialChars(c) 10932147Sminshall int c; 11032147Sminshall { 11132553Sminshall void xmitAO(), xmitEL(), xmitEC(), intp(), sendbrk(); 11232147Sminshall 11332147Sminshall if (c == ntc.t_intrc) { 11432147Sminshall intp(); 11532147Sminshall return 0; 11632147Sminshall } else if (c == ntc.t_quitc) { 11732147Sminshall sendbrk(); 11832147Sminshall return 0; 11932147Sminshall } else if (c == nltc.t_flushc) { 12032147Sminshall xmitAO(); /* Transmit Abort Output */ 12132147Sminshall return 0; 12232147Sminshall } else if (!MODE_LOCAL_CHARS(globalmode)) { 12332147Sminshall if (c == nttyb.sg_kill) { 12432147Sminshall xmitEL(); 12532147Sminshall return 0; 12632147Sminshall } else if (c == nttyb.sg_erase) { 12732147Sminshall xmitEC(); /* Transmit Erase Character */ 12832147Sminshall return 0; 12932147Sminshall } 13032147Sminshall } 13132147Sminshall return 1; 13232147Sminshall } 13332147Sminshall 13432147Sminshall 13532147Sminshall /* 13632147Sminshall * Flush output to the terminal 13732147Sminshall */ 13832147Sminshall 13932147Sminshall void 14032553Sminshall TerminalFlushOutput() 14132147Sminshall { 14232147Sminshall (void) ioctl(fileno(stdout), TIOCFLUSH, (char *) 0); 14332147Sminshall } 14432147Sminshall 14532147Sminshall void 14632553Sminshall TerminalSaveState() 14732147Sminshall { 14832147Sminshall ioctl(0, TIOCGETP, (char *)&ottyb); 14932147Sminshall ioctl(0, TIOCGETC, (char *)&otc); 15032147Sminshall ioctl(0, TIOCGLTC, (char *)&oltc); 15132147Sminshall 15232147Sminshall ntc = otc; 15332147Sminshall nltc = oltc; 15432147Sminshall nttyb = ottyb; 15532254Sminshall 15632254Sminshall termEofChar = ntc.t_eofc; 15732254Sminshall termEraseChar = nttyb.sg_erase; 15832254Sminshall termFlushChar = nltc.t_flushc; 15932254Sminshall termIntChar = ntc.t_intrc; 16032254Sminshall termKillChar = nttyb.sg_kill; 16132254Sminshall termQuitChar = ntc.t_quitc; 16232147Sminshall } 16332147Sminshall 16432147Sminshall void 16532553Sminshall TerminalRestoreState() 16632147Sminshall { 16732147Sminshall } 16832147Sminshall 16932147Sminshall /* 17032147Sminshall * TerminalNewMode - set up terminal to a specific mode. 17132147Sminshall */ 17232147Sminshall 17332147Sminshall 17432147Sminshall void 17533286Sminshall TerminalNewMode(f) 17632147Sminshall register int f; 17732147Sminshall { 17832147Sminshall static int prevmode = 0; 17932147Sminshall struct tchars *tc; 18032147Sminshall struct tchars tc3; 18132147Sminshall struct ltchars *ltc; 18232147Sminshall struct sgttyb sb; 18332147Sminshall int onoff; 18432147Sminshall int old; 18532147Sminshall struct tchars notc2; 18632147Sminshall struct ltchars noltc2; 18732147Sminshall static struct tchars notc = { -1, -1, -1, -1, -1, -1 }; 18832147Sminshall static struct ltchars noltc = { -1, -1, -1, -1, -1, -1 }; 18932147Sminshall 19032147Sminshall globalmode = f; 19132147Sminshall if (prevmode == f) 19232147Sminshall return; 19332147Sminshall old = prevmode; 19432147Sminshall prevmode = f; 19532147Sminshall sb = nttyb; 19632147Sminshall 19732147Sminshall switch (f) { 19832147Sminshall 19932147Sminshall case 0: 20032147Sminshall onoff = 0; 20132147Sminshall tc = &otc; 20232147Sminshall ltc = &oltc; 20332147Sminshall break; 20432147Sminshall 20532147Sminshall case 1: /* remote character processing, remote echo */ 20632147Sminshall case 2: /* remote character processing, local echo */ 20732147Sminshall case 6: /* 3270 mode - like 1, but with xon/xoff local */ 20832147Sminshall /* (might be nice to have "6" in telnet also...) */ 20932147Sminshall sb.sg_flags |= CBREAK; 21032147Sminshall if ((f == 1) || (f == 6)) { 21132147Sminshall sb.sg_flags &= ~(ECHO|CRMOD); 21232147Sminshall } else { 21332147Sminshall sb.sg_flags |= ECHO|CRMOD; 21432147Sminshall } 21532147Sminshall sb.sg_erase = sb.sg_kill = -1; 21632147Sminshall if (f == 6) { 21732147Sminshall tc = &tc3; 21832147Sminshall tc3 = notc; 21932147Sminshall /* get XON, XOFF characters */ 22032147Sminshall tc3.t_startc = otc.t_startc; 22132147Sminshall tc3.t_stopc = otc.t_stopc; 22232147Sminshall } else { 22332147Sminshall /* 22432147Sminshall * If user hasn't specified one way or the other, 22532147Sminshall * then default to not trapping signals. 22632147Sminshall */ 22732147Sminshall if (!donelclchars) { 22832147Sminshall localchars = 0; 22932147Sminshall } 23032147Sminshall if (localchars) { 23132147Sminshall notc2 = notc; 23232147Sminshall notc2.t_intrc = ntc.t_intrc; 23332147Sminshall notc2.t_quitc = ntc.t_quitc; 23432147Sminshall tc = ¬c2; 23532147Sminshall } else { 23632147Sminshall tc = ¬c; 23732147Sminshall } 23832147Sminshall } 23932147Sminshall ltc = &noltc; 24032147Sminshall onoff = 1; 24132147Sminshall break; 24232147Sminshall case 3: /* local character processing, remote echo */ 24332147Sminshall case 4: /* local character processing, local echo */ 24432147Sminshall case 5: /* local character processing, no echo */ 24532147Sminshall sb.sg_flags &= ~CBREAK; 24632147Sminshall sb.sg_flags |= CRMOD; 24732147Sminshall if (f == 4) 24832147Sminshall sb.sg_flags |= ECHO; 24932147Sminshall else 25032147Sminshall sb.sg_flags &= ~ECHO; 25132147Sminshall notc2 = ntc; 25232147Sminshall tc = ¬c2; 25332147Sminshall noltc2 = oltc; 25432147Sminshall ltc = &noltc2; 25532147Sminshall /* 25632147Sminshall * If user hasn't specified one way or the other, 25732147Sminshall * then default to trapping signals. 25832147Sminshall */ 25932147Sminshall if (!donelclchars) { 26032147Sminshall localchars = 1; 26132147Sminshall } 26232147Sminshall if (localchars) { 26332147Sminshall notc2.t_brkc = nltc.t_flushc; 26432147Sminshall noltc2.t_flushc = -1; 26532147Sminshall } else { 26632147Sminshall notc2.t_intrc = notc2.t_quitc = -1; 26732147Sminshall } 26832147Sminshall noltc2.t_suspc = escape; 26932147Sminshall noltc2.t_dsuspc = -1; 27032147Sminshall onoff = 1; 27132147Sminshall break; 27232147Sminshall 27332147Sminshall default: 27432147Sminshall return; 27532147Sminshall } 27633286Sminshall ioctl(tin, TIOCSLTC, (char *)ltc); 27733286Sminshall ioctl(tin, TIOCSETC, (char *)tc); 27833286Sminshall ioctl(tin, TIOCSETP, (char *)&sb); 27932147Sminshall #if (!defined(TN3270)) || ((!defined(NOT43)) || defined(PUTCHAR)) 28033286Sminshall ioctl(tin, FIONBIO, (char *)&onoff); 28133286Sminshall ioctl(tout, FIONBIO, (char *)&onoff); 28232147Sminshall #endif /* (!defined(TN3270)) || ((!defined(NOT43)) || defined(PUTCHAR)) */ 28332147Sminshall #if defined(TN3270) 28432147Sminshall if (noasynch == 0) { 28533286Sminshall ioctl(tin, FIOASYNC, (char *)&onoff); 28632147Sminshall } 28732147Sminshall #endif /* defined(TN3270) */ 28832147Sminshall 28932147Sminshall if (MODE_LINE(f)) { 29032147Sminshall void doescape(); 29132147Sminshall 292*34849Sminshall (void) signal(SIGTSTP, (int (*)())doescape); 29332147Sminshall } else if (MODE_LINE(old)) { 294*34849Sminshall (void) signal(SIGTSTP, SIG_DFL); 29532147Sminshall sigsetmask(sigblock(0) & ~(1<<(SIGTSTP-1))); 29632147Sminshall } 29732147Sminshall } 29832147Sminshall 29932147Sminshall 30032147Sminshall int 30132147Sminshall NetClose(net) 30232147Sminshall int net; 30332147Sminshall { 30432147Sminshall return close(net); 30532147Sminshall } 30632147Sminshall 30732147Sminshall 30832147Sminshall void 30932553Sminshall NetNonblockingIO(fd, onoff) 31032147Sminshall int 31132147Sminshall fd, 31232147Sminshall onoff; 31332147Sminshall { 31432147Sminshall ioctl(fd, FIONBIO, (char *)&onoff); 31532147Sminshall } 31632147Sminshall 317*34849Sminshall #if defined(TN3270) 31832147Sminshall void 31932553Sminshall NetSigIO(fd, onoff) 32032147Sminshall int 32132147Sminshall fd, 32232147Sminshall onoff; 32332147Sminshall { 32432147Sminshall ioctl(fd, FIOASYNC, (char *)&onoff); /* hear about input */ 32532147Sminshall } 32632147Sminshall 32732147Sminshall void 32832553Sminshall NetSetPgrp(fd) 32932147Sminshall int fd; 33032147Sminshall { 33132147Sminshall int myPid; 33232147Sminshall 33332147Sminshall myPid = getpid(); 33432147Sminshall #if defined(NOT43) 33532147Sminshall myPid = -myPid; 33632147Sminshall #endif /* defined(NOT43) */ 33732147Sminshall ioctl(fd, SIOCSPGRP, (char *)&myPid); /* set my pid */ 33832147Sminshall } 339*34849Sminshall #endif /*defined(TN3270)*/ 34032553Sminshall 34132553Sminshall /* 34232553Sminshall * Various signal handling routines. 34332553Sminshall */ 34432147Sminshall 34533286Sminshall static void 34632553Sminshall deadpeer() 34732553Sminshall { 34832553Sminshall setcommandmode(); 34932553Sminshall longjmp(peerdied, -1); 35032553Sminshall } 35132147Sminshall 35233286Sminshall static void 35332553Sminshall intr() 35432553Sminshall { 35532553Sminshall if (localchars) { 35632553Sminshall intp(); 35732553Sminshall return; 35832553Sminshall } 35932553Sminshall setcommandmode(); 36032553Sminshall longjmp(toplevel, -1); 36132553Sminshall } 36232553Sminshall 36333286Sminshall static void 36432553Sminshall intr2() 36532553Sminshall { 36632553Sminshall if (localchars) { 36732553Sminshall sendbrk(); 36832553Sminshall return; 36932553Sminshall } 37032553Sminshall } 37132553Sminshall 37233286Sminshall static void 37332553Sminshall doescape() 37432553Sminshall { 37532553Sminshall command(0); 37632553Sminshall } 37732553Sminshall 37832553Sminshall void 37932531Sminshall sys_telnet_init() 38032531Sminshall { 38132553Sminshall #if defined(TN3270) 38232531Sminshall int myPid; 38332531Sminshall #endif /* defined(TN3270) */ 38432531Sminshall 385*34849Sminshall (void) signal(SIGINT, (int (*)())intr); 386*34849Sminshall (void) signal(SIGQUIT, (int (*)())intr2); 387*34849Sminshall (void) signal(SIGPIPE, (int (*)())deadpeer); 38832553Sminshall 38932531Sminshall setconnmode(); 39032531Sminshall 39132531Sminshall NetNonblockingIO(net, 1); 39232531Sminshall 39332531Sminshall #if defined(TN3270) 39432531Sminshall if (noasynch == 0) { /* DBX can't handle! */ 39532531Sminshall NetSigIO(net, 1); 39632531Sminshall NetSetPgrp(net); 39732531Sminshall } 39832531Sminshall #endif /* defined(TN3270) */ 39932531Sminshall 40032531Sminshall #if defined(SO_OOBINLINE) 401*34849Sminshall if (SetSockOpt(net, SOL_SOCKET, SO_OOBINLINE, 1) == -1) { 402*34849Sminshall perror("SetSockOpt"); 403*34849Sminshall } 40432531Sminshall #endif /* defined(SO_OOBINLINE) */ 40532531Sminshall } 40632531Sminshall 40732531Sminshall /* 40832531Sminshall * Process rings - 40932531Sminshall * 41032531Sminshall * This routine tries to fill up/empty our various rings. 41132531Sminshall * 41232531Sminshall * The parameter specifies whether this is a poll operation, 41332531Sminshall * or a block-until-something-happens operation. 41432531Sminshall * 41532531Sminshall * The return value is 1 if something happened, 0 if not. 41632531Sminshall */ 41732531Sminshall 41832531Sminshall int 41932531Sminshall process_rings(netin, netout, netex, ttyin, ttyout, poll) 42032531Sminshall int poll; /* If 0, then block until something to do */ 42132531Sminshall { 42232531Sminshall register int c; 42332531Sminshall /* One wants to be a bit careful about setting returnValue 42432531Sminshall * to one, since a one implies we did some useful work, 42532531Sminshall * and therefore probably won't be called to block next 42632531Sminshall * time (TN3270 mode only). 42732531Sminshall */ 42832531Sminshall int returnValue = 0; 42932531Sminshall static struct timeval TimeValue = { 0 }; 43032531Sminshall 43132531Sminshall if (netout) { 43232531Sminshall FD_SET(net, &obits); 43332531Sminshall } 43432531Sminshall if (ttyout) { 43532531Sminshall FD_SET(tout, &obits); 43632531Sminshall } 43732531Sminshall #if defined(TN3270) 43832531Sminshall if (ttyin) { 43932531Sminshall FD_SET(tin, &ibits); 44032531Sminshall } 44132531Sminshall #else /* defined(TN3270) */ 44232531Sminshall if (ttyin) { 44332531Sminshall FD_SET(tin, &ibits); 44432531Sminshall } 44532531Sminshall #endif /* defined(TN3270) */ 44632531Sminshall #if defined(TN3270) 44732531Sminshall if (netin) { 44832531Sminshall FD_SET(net, &ibits); 44932531Sminshall } 45032531Sminshall # else /* !defined(TN3270) */ 45132531Sminshall if (netin) { 45232531Sminshall FD_SET(net, &ibits); 45332531Sminshall } 45432531Sminshall # endif /* !defined(TN3270) */ 45532531Sminshall if (netex) { 45632531Sminshall FD_SET(net, &xbits); 45732531Sminshall } 45832531Sminshall if ((c = select(16, &ibits, &obits, &xbits, 45932531Sminshall (poll == 0)? (struct timeval *)0 : &TimeValue)) < 0) { 46032531Sminshall if (c == -1) { 46132531Sminshall /* 46232531Sminshall * we can get EINTR if we are in line mode, 46332531Sminshall * and the user does an escape (TSTP), or 46432531Sminshall * some other signal generator. 46532531Sminshall */ 46632531Sminshall if (errno == EINTR) { 46732531Sminshall return 0; 46832531Sminshall } 46932531Sminshall # if defined(TN3270) 47032531Sminshall /* 47132531Sminshall * we can get EBADF if we were in transparent 47232531Sminshall * mode, and the transcom process died. 47332531Sminshall */ 47432531Sminshall if (errno == EBADF) { 47532531Sminshall /* 47632531Sminshall * zero the bits (even though kernel does it) 47732531Sminshall * to make sure we are selecting on the right 47832531Sminshall * ones. 47932531Sminshall */ 48032531Sminshall FD_ZERO(&ibits); 48132531Sminshall FD_ZERO(&obits); 48232531Sminshall FD_ZERO(&xbits); 48332531Sminshall return 0; 48432531Sminshall } 48532531Sminshall # endif /* defined(TN3270) */ 48632531Sminshall /* I don't like this, does it ever happen? */ 48732531Sminshall printf("sleep(5) from telnet, after select\r\n"); 48832531Sminshall sleep(5); 48932531Sminshall } 49032531Sminshall return 0; 49132531Sminshall } 49232531Sminshall 49332531Sminshall /* 49432531Sminshall * Any urgent data? 49532531Sminshall */ 49632531Sminshall if (FD_ISSET(net, &xbits)) { 49732531Sminshall FD_CLR(net, &xbits); 49832531Sminshall SYNCHing = 1; 49932531Sminshall ttyflush(1); /* flush already enqueued data */ 50032531Sminshall } 50132531Sminshall 50232531Sminshall /* 50332531Sminshall * Something to read from the network... 50432531Sminshall */ 50532531Sminshall if (FD_ISSET(net, &ibits)) { 50632531Sminshall int canread; 50732531Sminshall 50832531Sminshall FD_CLR(net, &ibits); 50932531Sminshall canread = ring_empty_consecutive(&netiring); 51032531Sminshall #if !defined(SO_OOBINLINE) 51132531Sminshall /* 51232531Sminshall * In 4.2 (and some early 4.3) systems, the 51332531Sminshall * OOB indication and data handling in the kernel 51432531Sminshall * is such that if two separate TCP Urgent requests 51532531Sminshall * come in, one byte of TCP data will be overlaid. 51632531Sminshall * This is fatal for Telnet, but we try to live 51732531Sminshall * with it. 51832531Sminshall * 51932531Sminshall * In addition, in 4.2 (and...), a special protocol 52032531Sminshall * is needed to pick up the TCP Urgent data in 52132531Sminshall * the correct sequence. 52232531Sminshall * 52332531Sminshall * What we do is: if we think we are in urgent 52432531Sminshall * mode, we look to see if we are "at the mark". 52532531Sminshall * If we are, we do an OOB receive. If we run 52632531Sminshall * this twice, we will do the OOB receive twice, 52732531Sminshall * but the second will fail, since the second 52832531Sminshall * time we were "at the mark", but there wasn't 52932531Sminshall * any data there (the kernel doesn't reset 53032531Sminshall * "at the mark" until we do a normal read). 53132531Sminshall * Once we've read the OOB data, we go ahead 53232531Sminshall * and do normal reads. 53332531Sminshall * 53432531Sminshall * There is also another problem, which is that 53532531Sminshall * since the OOB byte we read doesn't put us 53632531Sminshall * out of OOB state, and since that byte is most 53732531Sminshall * likely the TELNET DM (data mark), we would 53832531Sminshall * stay in the TELNET SYNCH (SYNCHing) state. 53932531Sminshall * So, clocks to the rescue. If we've "just" 54032531Sminshall * received a DM, then we test for the 54132531Sminshall * presence of OOB data when the receive OOB 54232531Sminshall * fails (and AFTER we did the normal mode read 54332531Sminshall * to clear "at the mark"). 54432531Sminshall */ 54532531Sminshall if (SYNCHing) { 54632531Sminshall int atmark; 54732531Sminshall 54832531Sminshall ioctl(net, SIOCATMARK, (char *)&atmark); 54932531Sminshall if (atmark) { 55032531Sminshall c = recv(net, netiring.supply, canread, MSG_OOB); 55132531Sminshall if ((c == -1) && (errno == EINVAL)) { 55232531Sminshall c = recv(net, netiring.supply, canread, 0); 55332531Sminshall if (clocks.didnetreceive < clocks.gotDM) { 55432531Sminshall SYNCHing = stilloob(net); 55532531Sminshall } 55632531Sminshall } 55732531Sminshall } else { 55832531Sminshall c = recv(net, netiring.supply, canread, 0); 55932531Sminshall } 56032531Sminshall } else { 56132531Sminshall c = recv(net, netiring.supply, canread, 0); 56232531Sminshall } 56332531Sminshall settimer(didnetreceive); 56432531Sminshall #else /* !defined(SO_OOBINLINE) */ 56532531Sminshall c = recv(net, netiring.supply, canread, 0); 56632531Sminshall #endif /* !defined(SO_OOBINLINE) */ 56732531Sminshall if (c < 0 && errno == EWOULDBLOCK) { 56832531Sminshall c = 0; 56932531Sminshall } else if (c <= 0) { 57032531Sminshall return -1; 57132531Sminshall } 57232531Sminshall if (netdata) { 57332531Sminshall Dump('<', netiring.supply, c); 57432531Sminshall } 57532667Sminshall if (c) 57632667Sminshall ring_supplied(&netiring, c); 57732531Sminshall returnValue = 1; 57832531Sminshall } 57932531Sminshall 58032531Sminshall /* 58132531Sminshall * Something to read from the tty... 58232531Sminshall */ 58332531Sminshall if (FD_ISSET(tin, &ibits)) { 58432531Sminshall FD_CLR(tin, &ibits); 58533286Sminshall c = TerminalRead(ttyiring.supply, ring_empty_consecutive(&ttyiring)); 58632531Sminshall if (c < 0 && errno == EWOULDBLOCK) { 58732531Sminshall c = 0; 58832531Sminshall } else { 58932531Sminshall /* EOF detection for line mode!!!! */ 59033281Sminshall if ((c == 0) && MODE_LOCAL_CHARS(globalmode) && isatty(tin)) { 59132531Sminshall /* must be an EOF... */ 59232531Sminshall *ttyiring.supply = termEofChar; 59332531Sminshall c = 1; 59432531Sminshall } 59532531Sminshall if (c <= 0) { 59632531Sminshall return -1; 59732531Sminshall } 59832667Sminshall ring_supplied(&ttyiring, c); 59932531Sminshall } 60032531Sminshall returnValue = 1; /* did something useful */ 60132531Sminshall } 60232531Sminshall 60332531Sminshall if (FD_ISSET(net, &obits)) { 60432531Sminshall FD_CLR(net, &obits); 60532531Sminshall returnValue |= netflush(); 60632531Sminshall } 60732531Sminshall if (FD_ISSET(tout, &obits)) { 60832531Sminshall FD_CLR(tout, &obits); 60932531Sminshall returnValue |= ttyflush(SYNCHing|flushout); 61032531Sminshall } 61132531Sminshall 61232531Sminshall return returnValue; 61332531Sminshall } 61432531Sminshall #endif /* defined(unix) */ 615