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> 1132531Sminshall #include <sys/socket.h> 1232147Sminshall #include <signal.h> 1332531Sminshall #include <errno.h> 1432147Sminshall 1532381Sminshall #include "ring.h" 1632381Sminshall 17*32657Sminshall #include "fdset.h" 18*32657Sminshall 1932147Sminshall #include "defines.h" 2032147Sminshall #include "externs.h" 2132147Sminshall #include "types.h" 2232147Sminshall 2332147Sminshall int 2432531Sminshall tout, /* Output file descriptor */ 2532531Sminshall tin, /* Input file descriptor */ 2632531Sminshall net, 2732147Sminshall HaveInput; /* There is input available to scan */ 2832147Sminshall 2932147Sminshall #if defined(TN3270) 3032147Sminshall static char tline[200]; 3132147Sminshall char *transcom = 0; /* transparent mode command (default: none) */ 3232147Sminshall #endif /* defined(TN3270) */ 3332147Sminshall 3432147Sminshall static struct tchars otc = { 0 }, ntc = { 0 }; 3532147Sminshall static struct ltchars oltc = { 0 }, nltc = { 0 }; 3632147Sminshall static struct sgttyb ottyb = { 0 }, nttyb = { 0 }; 3732147Sminshall 3832531Sminshall static fd_set ibits, obits, xbits; 3932147Sminshall 4032531Sminshall 4132531Sminshall init_sys() 4232531Sminshall { 4332531Sminshall tout = fileno(stdout); 4432531Sminshall tin = fileno(stdin); 4532531Sminshall FD_ZERO(&ibits); 4632531Sminshall FD_ZERO(&obits); 4732531Sminshall FD_ZERO(&xbits); 4832531Sminshall 4932531Sminshall errno = 0; 5032531Sminshall } 5132531Sminshall 5232531Sminshall 5332147Sminshall TerminalWrite(fd, buf, n) 5432147Sminshall int fd; 5532147Sminshall char *buf; 5632147Sminshall int n; 5732147Sminshall { 5832147Sminshall return write(fd, buf, n); 5932147Sminshall } 6032147Sminshall 6132147Sminshall TerminalRead(fd, buf, n) 6232147Sminshall int fd; 6332147Sminshall char *buf; 6432147Sminshall int n; 6532147Sminshall { 6632147Sminshall return read(fd, buf, n); 6732147Sminshall } 6832147Sminshall 6932147Sminshall /* 7032147Sminshall * 7132147Sminshall */ 7232147Sminshall 7332147Sminshall int 7432553Sminshall TerminalAutoFlush() 7532147Sminshall { 7632147Sminshall #if defined(LNOFLSH) 7732147Sminshall int flush; 7832147Sminshall 7932147Sminshall ioctl(0, TIOCLGET, (char *)&flush); 8032147Sminshall return !(flush&LNOFLSH); /* if LNOFLSH, no autoflush */ 8132147Sminshall #else /* LNOFLSH */ 8232147Sminshall return 1; 8332147Sminshall #endif /* LNOFLSH */ 8432147Sminshall } 8532147Sminshall 8632147Sminshall /* 8732147Sminshall * TerminalSpecialChars() 8832147Sminshall * 8932147Sminshall * Look at an input character to see if it is a special character 9032147Sminshall * and decide what to do. 9132147Sminshall * 9232147Sminshall * Output: 9332147Sminshall * 9432147Sminshall * 0 Don't add this character. 9532147Sminshall * 1 Do add this character 9632147Sminshall */ 9732147Sminshall 9832147Sminshall int 9932553Sminshall TerminalSpecialChars(c) 10032147Sminshall int c; 10132147Sminshall { 10232553Sminshall void xmitAO(), xmitEL(), xmitEC(), intp(), sendbrk(); 10332147Sminshall 10432147Sminshall if (c == ntc.t_intrc) { 10532147Sminshall intp(); 10632147Sminshall return 0; 10732147Sminshall } else if (c == ntc.t_quitc) { 10832147Sminshall sendbrk(); 10932147Sminshall return 0; 11032147Sminshall } else if (c == nltc.t_flushc) { 11132147Sminshall xmitAO(); /* Transmit Abort Output */ 11232147Sminshall return 0; 11332147Sminshall } else if (!MODE_LOCAL_CHARS(globalmode)) { 11432147Sminshall if (c == nttyb.sg_kill) { 11532147Sminshall xmitEL(); 11632147Sminshall return 0; 11732147Sminshall } else if (c == nttyb.sg_erase) { 11832147Sminshall xmitEC(); /* Transmit Erase Character */ 11932147Sminshall return 0; 12032147Sminshall } 12132147Sminshall } 12232147Sminshall return 1; 12332147Sminshall } 12432147Sminshall 12532147Sminshall 12632147Sminshall /* 12732147Sminshall * Flush output to the terminal 12832147Sminshall */ 12932147Sminshall 13032147Sminshall void 13132553Sminshall TerminalFlushOutput() 13232147Sminshall { 13332147Sminshall (void) ioctl(fileno(stdout), TIOCFLUSH, (char *) 0); 13432147Sminshall } 13532147Sminshall 13632147Sminshall void 13732553Sminshall TerminalSaveState() 13832147Sminshall { 13932147Sminshall ioctl(0, TIOCGETP, (char *)&ottyb); 14032147Sminshall ioctl(0, TIOCGETC, (char *)&otc); 14132147Sminshall ioctl(0, TIOCGLTC, (char *)&oltc); 14232147Sminshall 14332147Sminshall ntc = otc; 14432147Sminshall nltc = oltc; 14532147Sminshall nttyb = ottyb; 14632254Sminshall 14732254Sminshall termEofChar = ntc.t_eofc; 14832254Sminshall termEraseChar = nttyb.sg_erase; 14932254Sminshall termFlushChar = nltc.t_flushc; 15032254Sminshall termIntChar = ntc.t_intrc; 15132254Sminshall termKillChar = nttyb.sg_kill; 15232254Sminshall termQuitChar = ntc.t_quitc; 15332147Sminshall } 15432147Sminshall 15532147Sminshall void 15632553Sminshall TerminalRestoreState() 15732147Sminshall { 15832147Sminshall } 15932147Sminshall 16032147Sminshall /* 16132147Sminshall * TerminalNewMode - set up terminal to a specific mode. 16232147Sminshall */ 16332147Sminshall 16432147Sminshall 16532147Sminshall void 16632553Sminshall TerminalNewMode(fd_in, fd_out, f) 16732147Sminshall int fd_in, fd_out; /* File descriptor */ 16832147Sminshall register int f; 16932147Sminshall { 17032147Sminshall static int prevmode = 0; 17132147Sminshall struct tchars *tc; 17232147Sminshall struct tchars tc3; 17332147Sminshall struct ltchars *ltc; 17432147Sminshall struct sgttyb sb; 17532147Sminshall int onoff; 17632147Sminshall int old; 17732147Sminshall struct tchars notc2; 17832147Sminshall struct ltchars noltc2; 17932147Sminshall static struct tchars notc = { -1, -1, -1, -1, -1, -1 }; 18032147Sminshall static struct ltchars noltc = { -1, -1, -1, -1, -1, -1 }; 18132147Sminshall 18232147Sminshall globalmode = f; 18332147Sminshall if (prevmode == f) 18432147Sminshall return; 18532147Sminshall old = prevmode; 18632147Sminshall prevmode = f; 18732147Sminshall sb = nttyb; 18832147Sminshall 18932147Sminshall switch (f) { 19032147Sminshall 19132147Sminshall case 0: 19232147Sminshall onoff = 0; 19332147Sminshall tc = &otc; 19432147Sminshall ltc = &oltc; 19532147Sminshall break; 19632147Sminshall 19732147Sminshall case 1: /* remote character processing, remote echo */ 19832147Sminshall case 2: /* remote character processing, local echo */ 19932147Sminshall case 6: /* 3270 mode - like 1, but with xon/xoff local */ 20032147Sminshall /* (might be nice to have "6" in telnet also...) */ 20132147Sminshall sb.sg_flags |= CBREAK; 20232147Sminshall if ((f == 1) || (f == 6)) { 20332147Sminshall sb.sg_flags &= ~(ECHO|CRMOD); 20432147Sminshall } else { 20532147Sminshall sb.sg_flags |= ECHO|CRMOD; 20632147Sminshall } 20732147Sminshall sb.sg_erase = sb.sg_kill = -1; 20832147Sminshall if (f == 6) { 20932147Sminshall tc = &tc3; 21032147Sminshall tc3 = notc; 21132147Sminshall /* get XON, XOFF characters */ 21232147Sminshall tc3.t_startc = otc.t_startc; 21332147Sminshall tc3.t_stopc = otc.t_stopc; 21432147Sminshall } else { 21532147Sminshall /* 21632147Sminshall * If user hasn't specified one way or the other, 21732147Sminshall * then default to not trapping signals. 21832147Sminshall */ 21932147Sminshall if (!donelclchars) { 22032147Sminshall localchars = 0; 22132147Sminshall } 22232147Sminshall if (localchars) { 22332147Sminshall notc2 = notc; 22432147Sminshall notc2.t_intrc = ntc.t_intrc; 22532147Sminshall notc2.t_quitc = ntc.t_quitc; 22632147Sminshall tc = ¬c2; 22732147Sminshall } else { 22832147Sminshall tc = ¬c; 22932147Sminshall } 23032147Sminshall } 23132147Sminshall ltc = &noltc; 23232147Sminshall onoff = 1; 23332147Sminshall break; 23432147Sminshall case 3: /* local character processing, remote echo */ 23532147Sminshall case 4: /* local character processing, local echo */ 23632147Sminshall case 5: /* local character processing, no echo */ 23732147Sminshall sb.sg_flags &= ~CBREAK; 23832147Sminshall sb.sg_flags |= CRMOD; 23932147Sminshall if (f == 4) 24032147Sminshall sb.sg_flags |= ECHO; 24132147Sminshall else 24232147Sminshall sb.sg_flags &= ~ECHO; 24332147Sminshall notc2 = ntc; 24432147Sminshall tc = ¬c2; 24532147Sminshall noltc2 = oltc; 24632147Sminshall ltc = &noltc2; 24732147Sminshall /* 24832147Sminshall * If user hasn't specified one way or the other, 24932147Sminshall * then default to trapping signals. 25032147Sminshall */ 25132147Sminshall if (!donelclchars) { 25232147Sminshall localchars = 1; 25332147Sminshall } 25432147Sminshall if (localchars) { 25532147Sminshall notc2.t_brkc = nltc.t_flushc; 25632147Sminshall noltc2.t_flushc = -1; 25732147Sminshall } else { 25832147Sminshall notc2.t_intrc = notc2.t_quitc = -1; 25932147Sminshall } 26032147Sminshall noltc2.t_suspc = escape; 26132147Sminshall noltc2.t_dsuspc = -1; 26232147Sminshall onoff = 1; 26332147Sminshall break; 26432147Sminshall 26532147Sminshall default: 26632147Sminshall return; 26732147Sminshall } 26832147Sminshall ioctl(fd_in, TIOCSLTC, (char *)ltc); 26932147Sminshall ioctl(fd_in, TIOCSETC, (char *)tc); 27032147Sminshall ioctl(fd_in, TIOCSETP, (char *)&sb); 27132147Sminshall #if (!defined(TN3270)) || ((!defined(NOT43)) || defined(PUTCHAR)) 27232147Sminshall ioctl(fd_in, FIONBIO, (char *)&onoff); 27332147Sminshall ioctl(fd_out, FIONBIO, (char *)&onoff); 27432147Sminshall #endif /* (!defined(TN3270)) || ((!defined(NOT43)) || defined(PUTCHAR)) */ 27532147Sminshall #if defined(TN3270) 27632147Sminshall if (noasynch == 0) { 27732147Sminshall ioctl(fd_in, FIOASYNC, (char *)&onoff); 27832147Sminshall } 27932147Sminshall #endif /* defined(TN3270) */ 28032147Sminshall 28132147Sminshall if (MODE_LINE(f)) { 28232147Sminshall void doescape(); 28332147Sminshall 28432147Sminshall signal(SIGTSTP, doescape); 28532147Sminshall } else if (MODE_LINE(old)) { 28632147Sminshall signal(SIGTSTP, SIG_DFL); 28732147Sminshall sigsetmask(sigblock(0) & ~(1<<(SIGTSTP-1))); 28832147Sminshall } 28932147Sminshall } 29032147Sminshall 29132147Sminshall 29232147Sminshall int 29332147Sminshall NetClose(net) 29432147Sminshall int net; 29532147Sminshall { 29632147Sminshall return close(net); 29732147Sminshall } 29832147Sminshall 29932147Sminshall 30032147Sminshall void 30132553Sminshall NetNonblockingIO(fd, onoff) 30232147Sminshall int 30332147Sminshall fd, 30432147Sminshall onoff; 30532147Sminshall { 30632147Sminshall ioctl(fd, FIONBIO, (char *)&onoff); 30732147Sminshall } 30832147Sminshall 30932147Sminshall void 31032553Sminshall NetSigIO(fd, onoff) 31132147Sminshall int 31232147Sminshall fd, 31332147Sminshall onoff; 31432147Sminshall { 31532147Sminshall ioctl(fd, FIOASYNC, (char *)&onoff); /* hear about input */ 31632147Sminshall } 31732147Sminshall 31832147Sminshall void 31932553Sminshall NetSetPgrp(fd) 32032147Sminshall int fd; 32132147Sminshall { 32232147Sminshall int myPid; 32332147Sminshall 32432147Sminshall myPid = getpid(); 32532147Sminshall #if defined(NOT43) 32632147Sminshall myPid = -myPid; 32732147Sminshall #endif /* defined(NOT43) */ 32832147Sminshall ioctl(fd, SIOCSPGRP, (char *)&myPid); /* set my pid */ 32932147Sminshall } 33032553Sminshall 33132553Sminshall /* 33232553Sminshall * Various signal handling routines. 33332553Sminshall */ 33432147Sminshall 33532553Sminshall void 33632553Sminshall deadpeer() 33732553Sminshall { 33832553Sminshall setcommandmode(); 33932553Sminshall longjmp(peerdied, -1); 34032553Sminshall } 34132147Sminshall 34232531Sminshall void 34332553Sminshall intr() 34432553Sminshall { 34532553Sminshall if (localchars) { 34632553Sminshall intp(); 34732553Sminshall return; 34832553Sminshall } 34932553Sminshall setcommandmode(); 35032553Sminshall longjmp(toplevel, -1); 35132553Sminshall } 35232553Sminshall 35332553Sminshall void 35432553Sminshall intr2() 35532553Sminshall { 35632553Sminshall if (localchars) { 35732553Sminshall sendbrk(); 35832553Sminshall return; 35932553Sminshall } 36032553Sminshall } 36132553Sminshall 36232553Sminshall void 36332553Sminshall doescape() 36432553Sminshall { 36532553Sminshall command(0); 36632553Sminshall } 36732553Sminshall 36832553Sminshall void 36932531Sminshall sys_telnet_init() 37032531Sminshall { 37132553Sminshall #if defined(TN3270) 37232531Sminshall int myPid; 37332531Sminshall #endif /* defined(TN3270) */ 37432531Sminshall 37532553Sminshall signal(SIGINT, intr); 37632553Sminshall signal(SIGQUIT, intr2); 37732553Sminshall signal(SIGPIPE, deadpeer); 37832553Sminshall 37932531Sminshall setconnmode(); 38032531Sminshall 38132531Sminshall NetNonblockingIO(net, 1); 38232531Sminshall 38332531Sminshall #if defined(TN3270) 38432531Sminshall if (noasynch == 0) { /* DBX can't handle! */ 38532531Sminshall NetSigIO(net, 1); 38632531Sminshall NetSetPgrp(net); 38732531Sminshall } 38832531Sminshall #endif /* defined(TN3270) */ 38932531Sminshall 39032531Sminshall #if defined(SO_OOBINLINE) 39132531Sminshall SetSockOpt(net, SOL_SOCKET, SO_OOBINLINE, 1); 39232531Sminshall #endif /* defined(SO_OOBINLINE) */ 39332531Sminshall } 39432531Sminshall 39532531Sminshall /* 39632531Sminshall * Process rings - 39732531Sminshall * 39832531Sminshall * This routine tries to fill up/empty our various rings. 39932531Sminshall * 40032531Sminshall * The parameter specifies whether this is a poll operation, 40132531Sminshall * or a block-until-something-happens operation. 40232531Sminshall * 40332531Sminshall * The return value is 1 if something happened, 0 if not. 40432531Sminshall */ 40532531Sminshall 40632531Sminshall int 40732531Sminshall process_rings(netin, netout, netex, ttyin, ttyout, poll) 40832531Sminshall int poll; /* If 0, then block until something to do */ 40932531Sminshall { 41032531Sminshall register int c; 41132531Sminshall /* One wants to be a bit careful about setting returnValue 41232531Sminshall * to one, since a one implies we did some useful work, 41332531Sminshall * and therefore probably won't be called to block next 41432531Sminshall * time (TN3270 mode only). 41532531Sminshall */ 41632531Sminshall int returnValue = 0; 41732531Sminshall static struct timeval TimeValue = { 0 }; 41832531Sminshall 41932531Sminshall if (netout) { 42032531Sminshall FD_SET(net, &obits); 42132531Sminshall } 42232531Sminshall if (ttyout) { 42332531Sminshall FD_SET(tout, &obits); 42432531Sminshall } 42532531Sminshall #if defined(TN3270) 42632531Sminshall if (ttyin) { 42732531Sminshall FD_SET(tin, &ibits); 42832531Sminshall } 42932531Sminshall #else /* defined(TN3270) */ 43032531Sminshall if (ttyin) { 43132531Sminshall FD_SET(tin, &ibits); 43232531Sminshall } 43332531Sminshall #endif /* defined(TN3270) */ 43432531Sminshall #if defined(TN3270) 43532531Sminshall if (netin) { 43632531Sminshall FD_SET(net, &ibits); 43732531Sminshall } 43832531Sminshall # else /* !defined(TN3270) */ 43932531Sminshall if (netin) { 44032531Sminshall FD_SET(net, &ibits); 44132531Sminshall } 44232531Sminshall # endif /* !defined(TN3270) */ 44332531Sminshall if (netex) { 44432531Sminshall FD_SET(net, &xbits); 44532531Sminshall } 44632531Sminshall if ((c = select(16, &ibits, &obits, &xbits, 44732531Sminshall (poll == 0)? (struct timeval *)0 : &TimeValue)) < 0) { 44832531Sminshall if (c == -1) { 44932531Sminshall /* 45032531Sminshall * we can get EINTR if we are in line mode, 45132531Sminshall * and the user does an escape (TSTP), or 45232531Sminshall * some other signal generator. 45332531Sminshall */ 45432531Sminshall if (errno == EINTR) { 45532531Sminshall return 0; 45632531Sminshall } 45732531Sminshall # if defined(TN3270) 45832531Sminshall /* 45932531Sminshall * we can get EBADF if we were in transparent 46032531Sminshall * mode, and the transcom process died. 46132531Sminshall */ 46232531Sminshall if (errno == EBADF) { 46332531Sminshall /* 46432531Sminshall * zero the bits (even though kernel does it) 46532531Sminshall * to make sure we are selecting on the right 46632531Sminshall * ones. 46732531Sminshall */ 46832531Sminshall FD_ZERO(&ibits); 46932531Sminshall FD_ZERO(&obits); 47032531Sminshall FD_ZERO(&xbits); 47132531Sminshall return 0; 47232531Sminshall } 47332531Sminshall # endif /* defined(TN3270) */ 47432531Sminshall /* I don't like this, does it ever happen? */ 47532531Sminshall printf("sleep(5) from telnet, after select\r\n"); 47632531Sminshall sleep(5); 47732531Sminshall } 47832531Sminshall return 0; 47932531Sminshall } 48032531Sminshall 48132531Sminshall /* 48232531Sminshall * Any urgent data? 48332531Sminshall */ 48432531Sminshall if (FD_ISSET(net, &xbits)) { 48532531Sminshall FD_CLR(net, &xbits); 48632531Sminshall SYNCHing = 1; 48732531Sminshall ttyflush(1); /* flush already enqueued data */ 48832531Sminshall } 48932531Sminshall 49032531Sminshall /* 49132531Sminshall * Something to read from the network... 49232531Sminshall */ 49332531Sminshall if (FD_ISSET(net, &ibits)) { 49432531Sminshall int canread; 49532531Sminshall 49632531Sminshall FD_CLR(net, &ibits); 49732531Sminshall canread = ring_empty_consecutive(&netiring); 49832531Sminshall #if !defined(SO_OOBINLINE) 49932531Sminshall /* 50032531Sminshall * In 4.2 (and some early 4.3) systems, the 50132531Sminshall * OOB indication and data handling in the kernel 50232531Sminshall * is such that if two separate TCP Urgent requests 50332531Sminshall * come in, one byte of TCP data will be overlaid. 50432531Sminshall * This is fatal for Telnet, but we try to live 50532531Sminshall * with it. 50632531Sminshall * 50732531Sminshall * In addition, in 4.2 (and...), a special protocol 50832531Sminshall * is needed to pick up the TCP Urgent data in 50932531Sminshall * the correct sequence. 51032531Sminshall * 51132531Sminshall * What we do is: if we think we are in urgent 51232531Sminshall * mode, we look to see if we are "at the mark". 51332531Sminshall * If we are, we do an OOB receive. If we run 51432531Sminshall * this twice, we will do the OOB receive twice, 51532531Sminshall * but the second will fail, since the second 51632531Sminshall * time we were "at the mark", but there wasn't 51732531Sminshall * any data there (the kernel doesn't reset 51832531Sminshall * "at the mark" until we do a normal read). 51932531Sminshall * Once we've read the OOB data, we go ahead 52032531Sminshall * and do normal reads. 52132531Sminshall * 52232531Sminshall * There is also another problem, which is that 52332531Sminshall * since the OOB byte we read doesn't put us 52432531Sminshall * out of OOB state, and since that byte is most 52532531Sminshall * likely the TELNET DM (data mark), we would 52632531Sminshall * stay in the TELNET SYNCH (SYNCHing) state. 52732531Sminshall * So, clocks to the rescue. If we've "just" 52832531Sminshall * received a DM, then we test for the 52932531Sminshall * presence of OOB data when the receive OOB 53032531Sminshall * fails (and AFTER we did the normal mode read 53132531Sminshall * to clear "at the mark"). 53232531Sminshall */ 53332531Sminshall if (SYNCHing) { 53432531Sminshall int atmark; 53532531Sminshall 53632531Sminshall ioctl(net, SIOCATMARK, (char *)&atmark); 53732531Sminshall if (atmark) { 53832531Sminshall c = recv(net, netiring.supply, canread, MSG_OOB); 53932531Sminshall if ((c == -1) && (errno == EINVAL)) { 54032531Sminshall c = recv(net, netiring.supply, canread, 0); 54132531Sminshall if (clocks.didnetreceive < clocks.gotDM) { 54232531Sminshall SYNCHing = stilloob(net); 54332531Sminshall } 54432531Sminshall } 54532531Sminshall } else { 54632531Sminshall c = recv(net, netiring.supply, canread, 0); 54732531Sminshall } 54832531Sminshall } else { 54932531Sminshall c = recv(net, netiring.supply, canread, 0); 55032531Sminshall } 55132531Sminshall settimer(didnetreceive); 55232531Sminshall #else /* !defined(SO_OOBINLINE) */ 55332531Sminshall c = recv(net, netiring.supply, canread, 0); 55432531Sminshall #endif /* !defined(SO_OOBINLINE) */ 55532531Sminshall if (c < 0 && errno == EWOULDBLOCK) { 55632531Sminshall c = 0; 55732531Sminshall } else if (c <= 0) { 55832531Sminshall return -1; 55932531Sminshall } 56032531Sminshall if (netdata) { 56132531Sminshall Dump('<', netiring.supply, c); 56232531Sminshall } 56332531Sminshall ring_supplied(&netiring, c); 56432531Sminshall returnValue = 1; 56532531Sminshall } 56632531Sminshall 56732531Sminshall /* 56832531Sminshall * Something to read from the tty... 56932531Sminshall */ 57032531Sminshall if (FD_ISSET(tin, &ibits)) { 57132531Sminshall FD_CLR(tin, &ibits); 57232531Sminshall c = TerminalRead(tin, ttyiring.supply, 57332531Sminshall ring_empty_consecutive(&ttyiring)); 57432531Sminshall if (c < 0 && errno == EWOULDBLOCK) { 57532531Sminshall c = 0; 57632531Sminshall } else { 57732531Sminshall /* EOF detection for line mode!!!! */ 57832531Sminshall if (c == 0 && MODE_LOCAL_CHARS(globalmode)) { 57932531Sminshall /* must be an EOF... */ 58032531Sminshall *ttyiring.supply = termEofChar; 58132531Sminshall c = 1; 58232531Sminshall } 58332531Sminshall if (c <= 0) { 58432531Sminshall return -1; 58532531Sminshall } 58632531Sminshall } 58732531Sminshall ring_supplied(&ttyiring, c); 58832531Sminshall returnValue = 1; /* did something useful */ 58932531Sminshall } 59032531Sminshall 59132531Sminshall if (FD_ISSET(net, &obits)) { 59232531Sminshall FD_CLR(net, &obits); 59332531Sminshall returnValue |= netflush(); 59432531Sminshall } 59532531Sminshall if (FD_ISSET(tout, &obits)) { 59632531Sminshall FD_CLR(tout, &obits); 59732531Sminshall returnValue |= ttyflush(SYNCHing|flushout); 59832531Sminshall } 59932531Sminshall 60032531Sminshall return returnValue; 60132531Sminshall } 60232531Sminshall #endif /* defined(unix) */ 603