132147Sminshall /* 232147Sminshall * The following routines try to encapsulate what is system dependent 332147Sminshall * (at least between 4.x and dos) which is used in telnet.c. 432147Sminshall */ 532147Sminshall 632147Sminshall #if defined(unix) 732147Sminshall 832147Sminshall #include <sys/ioctl.h> 932381Sminshall #include <sys/types.h> 1032147Sminshall #include <sys/time.h> 11*32531Sminshall #include <sys/socket.h> 1232147Sminshall #include <signal.h> 13*32531Sminshall #include <errno.h> 1432147Sminshall 1532381Sminshall #include "ring.h" 1632381Sminshall 1732147Sminshall #include "defines.h" 1832147Sminshall #include "externs.h" 1932147Sminshall #include "types.h" 2032147Sminshall 21*32531Sminshall #ifndef FD_SETSIZE 22*32531Sminshall /* 23*32531Sminshall * The following is defined just in case someone should want to run 24*32531Sminshall * this telnet on a 4.2 system. 25*32531Sminshall * 26*32531Sminshall */ 27*32531Sminshall 28*32531Sminshall #define FD_SET(n, p) ((p)->fds_bits[0] |= (1<<(n))) 29*32531Sminshall #define FD_CLR(n, p) ((p)->fds_bits[0] &= ~(1<<(n))) 30*32531Sminshall #define FD_ISSET(n, p) ((p)->fds_bits[0] & (1<<(n))) 31*32531Sminshall #define FD_ZERO(p) ((p)->fds_bits[0] = 0) 32*32531Sminshall 33*32531Sminshall #endif 34*32531Sminshall 3532147Sminshall int 36*32531Sminshall tout, /* Output file descriptor */ 37*32531Sminshall tin, /* Input file descriptor */ 38*32531Sminshall net, 3932147Sminshall HaveInput; /* There is input available to scan */ 4032147Sminshall 4132147Sminshall #if defined(TN3270) 4232147Sminshall static char tline[200]; 4332147Sminshall char *transcom = 0; /* transparent mode command (default: none) */ 4432147Sminshall #endif /* defined(TN3270) */ 4532147Sminshall 4632147Sminshall static struct tchars otc = { 0 }, ntc = { 0 }; 4732147Sminshall static struct ltchars oltc = { 0 }, nltc = { 0 }; 4832147Sminshall static struct sgttyb ottyb = { 0 }, nttyb = { 0 }; 4932147Sminshall 50*32531Sminshall static fd_set ibits, obits, xbits; 5132147Sminshall 52*32531Sminshall 53*32531Sminshall init_sys() 54*32531Sminshall { 55*32531Sminshall tout = fileno(stdout); 56*32531Sminshall tin = fileno(stdin); 57*32531Sminshall FD_ZERO(&ibits); 58*32531Sminshall FD_ZERO(&obits); 59*32531Sminshall FD_ZERO(&xbits); 60*32531Sminshall 61*32531Sminshall errno = 0; 62*32531Sminshall } 63*32531Sminshall 64*32531Sminshall 6532147Sminshall TerminalWrite(fd, buf, n) 6632147Sminshall int fd; 6732147Sminshall char *buf; 6832147Sminshall int n; 6932147Sminshall { 7032147Sminshall return write(fd, buf, n); 7132147Sminshall } 7232147Sminshall 7332147Sminshall TerminalRead(fd, buf, n) 7432147Sminshall int fd; 7532147Sminshall char *buf; 7632147Sminshall int n; 7732147Sminshall { 7832147Sminshall return read(fd, buf, n); 7932147Sminshall } 8032147Sminshall 8132147Sminshall /* 8232147Sminshall * 8332147Sminshall */ 8432147Sminshall 8532147Sminshall int 8632147Sminshall TerminalAutoFlush() /* unix */ 8732147Sminshall { 8832147Sminshall #if defined(LNOFLSH) 8932147Sminshall int flush; 9032147Sminshall 9132147Sminshall ioctl(0, TIOCLGET, (char *)&flush); 9232147Sminshall return !(flush&LNOFLSH); /* if LNOFLSH, no autoflush */ 9332147Sminshall #else /* LNOFLSH */ 9432147Sminshall return 1; 9532147Sminshall #endif /* LNOFLSH */ 9632147Sminshall } 9732147Sminshall 9832147Sminshall /* 9932147Sminshall * TerminalSpecialChars() 10032147Sminshall * 10132147Sminshall * Look at an input character to see if it is a special character 10232147Sminshall * and decide what to do. 10332147Sminshall * 10432147Sminshall * Output: 10532147Sminshall * 10632147Sminshall * 0 Don't add this character. 10732147Sminshall * 1 Do add this character 10832147Sminshall */ 10932147Sminshall 11032147Sminshall int 11132147Sminshall TerminalSpecialChars(c) /* unix */ 11232147Sminshall int c; 11332147Sminshall { 11432147Sminshall void doflush(), intp(), sendbrk(); 11532147Sminshall 11632147Sminshall if (c == ntc.t_intrc) { 11732147Sminshall intp(); 11832147Sminshall return 0; 11932147Sminshall } else if (c == ntc.t_quitc) { 12032147Sminshall sendbrk(); 12132147Sminshall return 0; 12232147Sminshall } else if (c == nltc.t_flushc) { 12332147Sminshall xmitAO(); /* Transmit Abort Output */ 12432147Sminshall return 0; 12532147Sminshall } else if (!MODE_LOCAL_CHARS(globalmode)) { 12632147Sminshall if (c == nttyb.sg_kill) { 12732147Sminshall xmitEL(); 12832147Sminshall return 0; 12932147Sminshall } else if (c == nttyb.sg_erase) { 13032147Sminshall xmitEC(); /* Transmit Erase Character */ 13132147Sminshall return 0; 13232147Sminshall } 13332147Sminshall } 13432147Sminshall return 1; 13532147Sminshall } 13632147Sminshall 13732147Sminshall 13832147Sminshall /* 13932147Sminshall * Flush output to the terminal 14032147Sminshall */ 14132147Sminshall 14232147Sminshall void 14332147Sminshall TerminalFlushOutput() /* unix */ 14432147Sminshall { 14532147Sminshall (void) ioctl(fileno(stdout), TIOCFLUSH, (char *) 0); 14632147Sminshall } 14732147Sminshall 14832147Sminshall void 14932147Sminshall TerminalSaveState() /* unix */ 15032147Sminshall { 15132147Sminshall ioctl(0, TIOCGETP, (char *)&ottyb); 15232147Sminshall ioctl(0, TIOCGETC, (char *)&otc); 15332147Sminshall ioctl(0, TIOCGLTC, (char *)&oltc); 15432147Sminshall 15532147Sminshall ntc = otc; 15632147Sminshall nltc = oltc; 15732147Sminshall nttyb = ottyb; 15832254Sminshall 15932254Sminshall termEofChar = ntc.t_eofc; 16032254Sminshall termEraseChar = nttyb.sg_erase; 16132254Sminshall termFlushChar = nltc.t_flushc; 16232254Sminshall termIntChar = ntc.t_intrc; 16332254Sminshall termKillChar = nttyb.sg_kill; 16432254Sminshall termQuitChar = ntc.t_quitc; 16532147Sminshall } 16632147Sminshall 16732147Sminshall void 16832147Sminshall TerminalRestoreState() /* unix */ 16932147Sminshall { 17032147Sminshall } 17132147Sminshall 17232147Sminshall /* 17332147Sminshall * TerminalNewMode - set up terminal to a specific mode. 17432147Sminshall */ 17532147Sminshall 17632147Sminshall 17732147Sminshall void 17832147Sminshall TerminalNewMode(fd_in, fd_out, f) /* unix */ 17932147Sminshall int fd_in, fd_out; /* File descriptor */ 18032147Sminshall register int f; 18132147Sminshall { 18232147Sminshall static int prevmode = 0; 18332147Sminshall struct tchars *tc; 18432147Sminshall struct tchars tc3; 18532147Sminshall struct ltchars *ltc; 18632147Sminshall struct sgttyb sb; 18732147Sminshall int onoff; 18832147Sminshall int old; 18932147Sminshall struct tchars notc2; 19032147Sminshall struct ltchars noltc2; 19132147Sminshall static struct tchars notc = { -1, -1, -1, -1, -1, -1 }; 19232147Sminshall static struct ltchars noltc = { -1, -1, -1, -1, -1, -1 }; 19332147Sminshall 19432147Sminshall globalmode = f; 19532147Sminshall if (prevmode == f) 19632147Sminshall return; 19732147Sminshall old = prevmode; 19832147Sminshall prevmode = f; 19932147Sminshall sb = nttyb; 20032147Sminshall 20132147Sminshall switch (f) { 20232147Sminshall 20332147Sminshall case 0: 20432147Sminshall onoff = 0; 20532147Sminshall tc = &otc; 20632147Sminshall ltc = &oltc; 20732147Sminshall break; 20832147Sminshall 20932147Sminshall case 1: /* remote character processing, remote echo */ 21032147Sminshall case 2: /* remote character processing, local echo */ 21132147Sminshall case 6: /* 3270 mode - like 1, but with xon/xoff local */ 21232147Sminshall /* (might be nice to have "6" in telnet also...) */ 21332147Sminshall sb.sg_flags |= CBREAK; 21432147Sminshall if ((f == 1) || (f == 6)) { 21532147Sminshall sb.sg_flags &= ~(ECHO|CRMOD); 21632147Sminshall } else { 21732147Sminshall sb.sg_flags |= ECHO|CRMOD; 21832147Sminshall } 21932147Sminshall sb.sg_erase = sb.sg_kill = -1; 22032147Sminshall if (f == 6) { 22132147Sminshall tc = &tc3; 22232147Sminshall tc3 = notc; 22332147Sminshall /* get XON, XOFF characters */ 22432147Sminshall tc3.t_startc = otc.t_startc; 22532147Sminshall tc3.t_stopc = otc.t_stopc; 22632147Sminshall } else { 22732147Sminshall /* 22832147Sminshall * If user hasn't specified one way or the other, 22932147Sminshall * then default to not trapping signals. 23032147Sminshall */ 23132147Sminshall if (!donelclchars) { 23232147Sminshall localchars = 0; 23332147Sminshall } 23432147Sminshall if (localchars) { 23532147Sminshall notc2 = notc; 23632147Sminshall notc2.t_intrc = ntc.t_intrc; 23732147Sminshall notc2.t_quitc = ntc.t_quitc; 23832147Sminshall tc = ¬c2; 23932147Sminshall } else { 24032147Sminshall tc = ¬c; 24132147Sminshall } 24232147Sminshall } 24332147Sminshall ltc = &noltc; 24432147Sminshall onoff = 1; 24532147Sminshall break; 24632147Sminshall case 3: /* local character processing, remote echo */ 24732147Sminshall case 4: /* local character processing, local echo */ 24832147Sminshall case 5: /* local character processing, no echo */ 24932147Sminshall sb.sg_flags &= ~CBREAK; 25032147Sminshall sb.sg_flags |= CRMOD; 25132147Sminshall if (f == 4) 25232147Sminshall sb.sg_flags |= ECHO; 25332147Sminshall else 25432147Sminshall sb.sg_flags &= ~ECHO; 25532147Sminshall notc2 = ntc; 25632147Sminshall tc = ¬c2; 25732147Sminshall noltc2 = oltc; 25832147Sminshall ltc = &noltc2; 25932147Sminshall /* 26032147Sminshall * If user hasn't specified one way or the other, 26132147Sminshall * then default to trapping signals. 26232147Sminshall */ 26332147Sminshall if (!donelclchars) { 26432147Sminshall localchars = 1; 26532147Sminshall } 26632147Sminshall if (localchars) { 26732147Sminshall notc2.t_brkc = nltc.t_flushc; 26832147Sminshall noltc2.t_flushc = -1; 26932147Sminshall } else { 27032147Sminshall notc2.t_intrc = notc2.t_quitc = -1; 27132147Sminshall } 27232147Sminshall noltc2.t_suspc = escape; 27332147Sminshall noltc2.t_dsuspc = -1; 27432147Sminshall onoff = 1; 27532147Sminshall break; 27632147Sminshall 27732147Sminshall default: 27832147Sminshall return; 27932147Sminshall } 28032147Sminshall ioctl(fd_in, TIOCSLTC, (char *)ltc); 28132147Sminshall ioctl(fd_in, TIOCSETC, (char *)tc); 28232147Sminshall ioctl(fd_in, TIOCSETP, (char *)&sb); 28332147Sminshall #if (!defined(TN3270)) || ((!defined(NOT43)) || defined(PUTCHAR)) 28432147Sminshall ioctl(fd_in, FIONBIO, (char *)&onoff); 28532147Sminshall ioctl(fd_out, FIONBIO, (char *)&onoff); 28632147Sminshall #endif /* (!defined(TN3270)) || ((!defined(NOT43)) || defined(PUTCHAR)) */ 28732147Sminshall #if defined(TN3270) 28832147Sminshall if (noasynch == 0) { 28932147Sminshall ioctl(fd_in, FIOASYNC, (char *)&onoff); 29032147Sminshall } 29132147Sminshall #endif /* defined(TN3270) */ 29232147Sminshall 29332147Sminshall if (MODE_LINE(f)) { 29432147Sminshall void doescape(); 29532147Sminshall 29632147Sminshall signal(SIGTSTP, doescape); 29732147Sminshall } else if (MODE_LINE(old)) { 29832147Sminshall signal(SIGTSTP, SIG_DFL); 29932147Sminshall sigsetmask(sigblock(0) & ~(1<<(SIGTSTP-1))); 30032147Sminshall } 30132147Sminshall } 30232147Sminshall 30332147Sminshall 30432147Sminshall int 30532147Sminshall NetClose(net) 30632147Sminshall int net; 30732147Sminshall { 30832147Sminshall return close(net); 30932147Sminshall } 31032147Sminshall 31132147Sminshall 31232147Sminshall void 31332147Sminshall NetNonblockingIO(fd, onoff) /* unix */ 31432147Sminshall int 31532147Sminshall fd, 31632147Sminshall onoff; 31732147Sminshall { 31832147Sminshall ioctl(fd, FIONBIO, (char *)&onoff); 31932147Sminshall } 32032147Sminshall 32132147Sminshall void 32232147Sminshall NetSigIO(fd, onoff) /* unix */ 32332147Sminshall int 32432147Sminshall fd, 32532147Sminshall onoff; 32632147Sminshall { 32732147Sminshall ioctl(fd, FIOASYNC, (char *)&onoff); /* hear about input */ 32832147Sminshall } 32932147Sminshall 33032147Sminshall void 33132147Sminshall NetSetPgrp(fd) /* unix */ 33232147Sminshall int fd; 33332147Sminshall { 33432147Sminshall int myPid; 33532147Sminshall 33632147Sminshall myPid = getpid(); 33732147Sminshall #if defined(NOT43) 33832147Sminshall myPid = -myPid; 33932147Sminshall #endif /* defined(NOT43) */ 34032147Sminshall ioctl(fd, SIOCSPGRP, (char *)&myPid); /* set my pid */ 34132147Sminshall } 34232147Sminshall 34332147Sminshall 344*32531Sminshall void 345*32531Sminshall sys_telnet_init() 346*32531Sminshall { 347*32531Sminshall #if defined(TN3270) && defined(unix) 348*32531Sminshall int myPid; 349*32531Sminshall #endif /* defined(TN3270) */ 350*32531Sminshall 351*32531Sminshall setconnmode(); 352*32531Sminshall 353*32531Sminshall NetNonblockingIO(net, 1); 354*32531Sminshall 355*32531Sminshall #if defined(TN3270) 356*32531Sminshall if (noasynch == 0) { /* DBX can't handle! */ 357*32531Sminshall NetSigIO(net, 1); 358*32531Sminshall NetSetPgrp(net); 359*32531Sminshall } 360*32531Sminshall #endif /* defined(TN3270) */ 361*32531Sminshall 362*32531Sminshall #if defined(SO_OOBINLINE) 363*32531Sminshall SetSockOpt(net, SOL_SOCKET, SO_OOBINLINE, 1); 364*32531Sminshall #endif /* defined(SO_OOBINLINE) */ 365*32531Sminshall } 366*32531Sminshall 367*32531Sminshall /* 368*32531Sminshall * Process rings - 369*32531Sminshall * 370*32531Sminshall * This routine tries to fill up/empty our various rings. 371*32531Sminshall * 372*32531Sminshall * The parameter specifies whether this is a poll operation, 373*32531Sminshall * or a block-until-something-happens operation. 374*32531Sminshall * 375*32531Sminshall * The return value is 1 if something happened, 0 if not. 376*32531Sminshall */ 377*32531Sminshall 378*32531Sminshall int 379*32531Sminshall process_rings(netin, netout, netex, ttyin, ttyout, poll) 380*32531Sminshall int poll; /* If 0, then block until something to do */ 381*32531Sminshall { 382*32531Sminshall register int c; 383*32531Sminshall /* One wants to be a bit careful about setting returnValue 384*32531Sminshall * to one, since a one implies we did some useful work, 385*32531Sminshall * and therefore probably won't be called to block next 386*32531Sminshall * time (TN3270 mode only). 387*32531Sminshall */ 388*32531Sminshall int returnValue = 0; 389*32531Sminshall static struct timeval TimeValue = { 0 }; 390*32531Sminshall 391*32531Sminshall if (netout) { 392*32531Sminshall FD_SET(net, &obits); 393*32531Sminshall } 394*32531Sminshall if (ttyout) { 395*32531Sminshall FD_SET(tout, &obits); 396*32531Sminshall } 397*32531Sminshall #if defined(TN3270) 398*32531Sminshall if (ttyin) { 399*32531Sminshall FD_SET(tin, &ibits); 400*32531Sminshall } 401*32531Sminshall #else /* defined(TN3270) */ 402*32531Sminshall if (ttyin) { 403*32531Sminshall FD_SET(tin, &ibits); 404*32531Sminshall } 405*32531Sminshall #endif /* defined(TN3270) */ 406*32531Sminshall #if defined(TN3270) 407*32531Sminshall if (netin) { 408*32531Sminshall FD_SET(net, &ibits); 409*32531Sminshall } 410*32531Sminshall # else /* !defined(TN3270) */ 411*32531Sminshall if (netin) { 412*32531Sminshall FD_SET(net, &ibits); 413*32531Sminshall } 414*32531Sminshall # endif /* !defined(TN3270) */ 415*32531Sminshall if (netex) { 416*32531Sminshall FD_SET(net, &xbits); 417*32531Sminshall } 418*32531Sminshall if ((c = select(16, &ibits, &obits, &xbits, 419*32531Sminshall (poll == 0)? (struct timeval *)0 : &TimeValue)) < 0) { 420*32531Sminshall if (c == -1) { 421*32531Sminshall /* 422*32531Sminshall * we can get EINTR if we are in line mode, 423*32531Sminshall * and the user does an escape (TSTP), or 424*32531Sminshall * some other signal generator. 425*32531Sminshall */ 426*32531Sminshall if (errno == EINTR) { 427*32531Sminshall return 0; 428*32531Sminshall } 429*32531Sminshall # if defined(TN3270) 430*32531Sminshall /* 431*32531Sminshall * we can get EBADF if we were in transparent 432*32531Sminshall * mode, and the transcom process died. 433*32531Sminshall */ 434*32531Sminshall if (errno == EBADF) { 435*32531Sminshall /* 436*32531Sminshall * zero the bits (even though kernel does it) 437*32531Sminshall * to make sure we are selecting on the right 438*32531Sminshall * ones. 439*32531Sminshall */ 440*32531Sminshall FD_ZERO(&ibits); 441*32531Sminshall FD_ZERO(&obits); 442*32531Sminshall FD_ZERO(&xbits); 443*32531Sminshall return 0; 444*32531Sminshall } 445*32531Sminshall # endif /* defined(TN3270) */ 446*32531Sminshall /* I don't like this, does it ever happen? */ 447*32531Sminshall printf("sleep(5) from telnet, after select\r\n"); 448*32531Sminshall #if defined(unix) 449*32531Sminshall sleep(5); 45032147Sminshall #endif /* defined(unix) */ 451*32531Sminshall } 452*32531Sminshall return 0; 453*32531Sminshall } 454*32531Sminshall 455*32531Sminshall /* 456*32531Sminshall * Any urgent data? 457*32531Sminshall */ 458*32531Sminshall if (FD_ISSET(net, &xbits)) { 459*32531Sminshall FD_CLR(net, &xbits); 460*32531Sminshall SYNCHing = 1; 461*32531Sminshall ttyflush(1); /* flush already enqueued data */ 462*32531Sminshall } 463*32531Sminshall 464*32531Sminshall /* 465*32531Sminshall * Something to read from the network... 466*32531Sminshall */ 467*32531Sminshall if (FD_ISSET(net, &ibits)) { 468*32531Sminshall int canread; 469*32531Sminshall 470*32531Sminshall FD_CLR(net, &ibits); 471*32531Sminshall canread = ring_empty_consecutive(&netiring); 472*32531Sminshall #if !defined(SO_OOBINLINE) 473*32531Sminshall /* 474*32531Sminshall * In 4.2 (and some early 4.3) systems, the 475*32531Sminshall * OOB indication and data handling in the kernel 476*32531Sminshall * is such that if two separate TCP Urgent requests 477*32531Sminshall * come in, one byte of TCP data will be overlaid. 478*32531Sminshall * This is fatal for Telnet, but we try to live 479*32531Sminshall * with it. 480*32531Sminshall * 481*32531Sminshall * In addition, in 4.2 (and...), a special protocol 482*32531Sminshall * is needed to pick up the TCP Urgent data in 483*32531Sminshall * the correct sequence. 484*32531Sminshall * 485*32531Sminshall * What we do is: if we think we are in urgent 486*32531Sminshall * mode, we look to see if we are "at the mark". 487*32531Sminshall * If we are, we do an OOB receive. If we run 488*32531Sminshall * this twice, we will do the OOB receive twice, 489*32531Sminshall * but the second will fail, since the second 490*32531Sminshall * time we were "at the mark", but there wasn't 491*32531Sminshall * any data there (the kernel doesn't reset 492*32531Sminshall * "at the mark" until we do a normal read). 493*32531Sminshall * Once we've read the OOB data, we go ahead 494*32531Sminshall * and do normal reads. 495*32531Sminshall * 496*32531Sminshall * There is also another problem, which is that 497*32531Sminshall * since the OOB byte we read doesn't put us 498*32531Sminshall * out of OOB state, and since that byte is most 499*32531Sminshall * likely the TELNET DM (data mark), we would 500*32531Sminshall * stay in the TELNET SYNCH (SYNCHing) state. 501*32531Sminshall * So, clocks to the rescue. If we've "just" 502*32531Sminshall * received a DM, then we test for the 503*32531Sminshall * presence of OOB data when the receive OOB 504*32531Sminshall * fails (and AFTER we did the normal mode read 505*32531Sminshall * to clear "at the mark"). 506*32531Sminshall */ 507*32531Sminshall if (SYNCHing) { 508*32531Sminshall int atmark; 509*32531Sminshall 510*32531Sminshall ioctl(net, SIOCATMARK, (char *)&atmark); 511*32531Sminshall if (atmark) { 512*32531Sminshall c = recv(net, netiring.supply, canread, MSG_OOB); 513*32531Sminshall if ((c == -1) && (errno == EINVAL)) { 514*32531Sminshall c = recv(net, netiring.supply, canread, 0); 515*32531Sminshall if (clocks.didnetreceive < clocks.gotDM) { 516*32531Sminshall SYNCHing = stilloob(net); 517*32531Sminshall } 518*32531Sminshall } 519*32531Sminshall } else { 520*32531Sminshall c = recv(net, netiring.supply, canread, 0); 521*32531Sminshall } 522*32531Sminshall } else { 523*32531Sminshall c = recv(net, netiring.supply, canread, 0); 524*32531Sminshall } 525*32531Sminshall settimer(didnetreceive); 526*32531Sminshall #else /* !defined(SO_OOBINLINE) */ 527*32531Sminshall c = recv(net, netiring.supply, canread, 0); 528*32531Sminshall #endif /* !defined(SO_OOBINLINE) */ 529*32531Sminshall if (c < 0 && errno == EWOULDBLOCK) { 530*32531Sminshall c = 0; 531*32531Sminshall } else if (c <= 0) { 532*32531Sminshall return -1; 533*32531Sminshall } 534*32531Sminshall if (netdata) { 535*32531Sminshall Dump('<', netiring.supply, c); 536*32531Sminshall } 537*32531Sminshall ring_supplied(&netiring, c); 538*32531Sminshall returnValue = 1; 539*32531Sminshall } 540*32531Sminshall 541*32531Sminshall /* 542*32531Sminshall * Something to read from the tty... 543*32531Sminshall */ 544*32531Sminshall if (FD_ISSET(tin, &ibits)) { 545*32531Sminshall FD_CLR(tin, &ibits); 546*32531Sminshall c = TerminalRead(tin, ttyiring.supply, 547*32531Sminshall ring_empty_consecutive(&ttyiring)); 548*32531Sminshall if (c < 0 && errno == EWOULDBLOCK) { 549*32531Sminshall c = 0; 550*32531Sminshall } else { 551*32531Sminshall #if defined(unix) 552*32531Sminshall /* EOF detection for line mode!!!! */ 553*32531Sminshall if (c == 0 && MODE_LOCAL_CHARS(globalmode)) { 554*32531Sminshall /* must be an EOF... */ 555*32531Sminshall *ttyiring.supply = termEofChar; 556*32531Sminshall c = 1; 557*32531Sminshall } 558*32531Sminshall #endif /* defined(unix) */ 559*32531Sminshall if (c <= 0) { 560*32531Sminshall return -1; 561*32531Sminshall } 562*32531Sminshall } 563*32531Sminshall ring_supplied(&ttyiring, c); 564*32531Sminshall returnValue = 1; /* did something useful */ 565*32531Sminshall } 566*32531Sminshall 567*32531Sminshall if (FD_ISSET(net, &obits)) { 568*32531Sminshall FD_CLR(net, &obits); 569*32531Sminshall returnValue |= netflush(); 570*32531Sminshall } 571*32531Sminshall if (FD_ISSET(tout, &obits)) { 572*32531Sminshall FD_CLR(tout, &obits); 573*32531Sminshall returnValue |= ttyflush(SYNCHing|flushout); 574*32531Sminshall } 575*32531Sminshall 576*32531Sminshall return returnValue; 577*32531Sminshall } 578*32531Sminshall #endif /* defined(unix) */ 579