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 634898Sbostic * provided that the above copyright notice and this paragraph are 734898Sbostic * duplicated in all such forms and that any documentation, 834898Sbostic * advertising materials, and other materials related to such 934898Sbostic * distribution and use acknowledge that the software was developed 1034898Sbostic * by the University of California, Berkeley. The name of the 1134898Sbostic * University may not be used to endorse or promote products derived 1234898Sbostic * from this software without specific prior written permission. 1334898Sbostic * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 1434898Sbostic * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 1534898Sbostic * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1633685Sbostic */ 1733685Sbostic 1833685Sbostic #ifndef lint 19*38208Sminshall static char sccsid[] = "@(#)sys_bsd.c 1.18 (Berkeley) 05/30/89"; 2033685Sbostic #endif /* not lint */ 2133685Sbostic 2233685Sbostic /* 2332147Sminshall * The following routines try to encapsulate what is system dependent 2432147Sminshall * (at least between 4.x and dos) which is used in telnet.c. 2532147Sminshall */ 2632147Sminshall 2732147Sminshall #if defined(unix) 2832147Sminshall 2936274Sminshall #include <fcntl.h> 3032147Sminshall #include <sys/ioctl.h> 3132381Sminshall #include <sys/types.h> 3232147Sminshall #include <sys/time.h> 3332531Sminshall #include <sys/socket.h> 3432147Sminshall #include <signal.h> 3532531Sminshall #include <errno.h> 3632147Sminshall 3732381Sminshall #include "ring.h" 3832381Sminshall 3932657Sminshall #include "fdset.h" 4032657Sminshall 4132147Sminshall #include "defines.h" 4232147Sminshall #include "externs.h" 4332147Sminshall #include "types.h" 4432147Sminshall 4532147Sminshall int 4632531Sminshall tout, /* Output file descriptor */ 4732531Sminshall tin, /* Input file descriptor */ 4836242Sminshall net; 4932147Sminshall 5032147Sminshall static struct tchars otc = { 0 }, ntc = { 0 }; 5132147Sminshall static struct ltchars oltc = { 0 }, nltc = { 0 }; 5232147Sminshall static struct sgttyb ottyb = { 0 }, nttyb = { 0 }; 5332147Sminshall 5432531Sminshall static fd_set ibits, obits, xbits; 5532147Sminshall 5632531Sminshall 5732531Sminshall init_sys() 5832531Sminshall { 5932531Sminshall tout = fileno(stdout); 6032531Sminshall tin = fileno(stdin); 6132531Sminshall FD_ZERO(&ibits); 6232531Sminshall FD_ZERO(&obits); 6332531Sminshall FD_ZERO(&xbits); 6432531Sminshall 6532531Sminshall errno = 0; 6632531Sminshall } 6732531Sminshall 6832531Sminshall 6933286Sminshall TerminalWrite(buf, n) 7032147Sminshall char *buf; 7132147Sminshall int n; 7232147Sminshall { 7333286Sminshall return write(tout, buf, n); 7432147Sminshall } 7532147Sminshall 7633286Sminshall TerminalRead(buf, n) 7732147Sminshall char *buf; 7832147Sminshall int n; 7932147Sminshall { 8033286Sminshall return read(tin, buf, n); 8132147Sminshall } 8232147Sminshall 8332147Sminshall /* 8432147Sminshall * 8532147Sminshall */ 8632147Sminshall 8732147Sminshall int 8832553Sminshall TerminalAutoFlush() 8932147Sminshall { 9032147Sminshall #if defined(LNOFLSH) 9132147Sminshall int flush; 9232147Sminshall 9332147Sminshall ioctl(0, TIOCLGET, (char *)&flush); 9432147Sminshall return !(flush&LNOFLSH); /* if LNOFLSH, no autoflush */ 9532147Sminshall #else /* LNOFLSH */ 9632147Sminshall return 1; 9732147Sminshall #endif /* LNOFLSH */ 9832147Sminshall } 9932147Sminshall 10032147Sminshall /* 10132147Sminshall * TerminalSpecialChars() 10232147Sminshall * 10332147Sminshall * Look at an input character to see if it is a special character 10432147Sminshall * and decide what to do. 10532147Sminshall * 10632147Sminshall * Output: 10732147Sminshall * 10832147Sminshall * 0 Don't add this character. 10932147Sminshall * 1 Do add this character 11032147Sminshall */ 11132147Sminshall 11232147Sminshall int 11332553Sminshall TerminalSpecialChars(c) 11432147Sminshall int c; 11532147Sminshall { 11632553Sminshall void xmitAO(), xmitEL(), xmitEC(), intp(), sendbrk(); 11732147Sminshall 11832147Sminshall if (c == ntc.t_intrc) { 11932147Sminshall intp(); 12032147Sminshall return 0; 12132147Sminshall } else if (c == ntc.t_quitc) { 12232147Sminshall sendbrk(); 12332147Sminshall return 0; 12432147Sminshall } else if (c == nltc.t_flushc) { 12532147Sminshall xmitAO(); /* Transmit Abort Output */ 12632147Sminshall return 0; 12732147Sminshall } else if (!MODE_LOCAL_CHARS(globalmode)) { 12832147Sminshall if (c == nttyb.sg_kill) { 12932147Sminshall xmitEL(); 13032147Sminshall return 0; 13132147Sminshall } else if (c == nttyb.sg_erase) { 13232147Sminshall xmitEC(); /* Transmit Erase Character */ 13332147Sminshall return 0; 13432147Sminshall } 13532147Sminshall } 13632147Sminshall return 1; 13732147Sminshall } 13832147Sminshall 13932147Sminshall 14032147Sminshall /* 14132147Sminshall * Flush output to the terminal 14232147Sminshall */ 14332147Sminshall 14432147Sminshall void 14532553Sminshall TerminalFlushOutput() 14632147Sminshall { 14732147Sminshall (void) ioctl(fileno(stdout), TIOCFLUSH, (char *) 0); 14832147Sminshall } 14932147Sminshall 15032147Sminshall void 15132553Sminshall TerminalSaveState() 15232147Sminshall { 15332147Sminshall ioctl(0, TIOCGETP, (char *)&ottyb); 15432147Sminshall ioctl(0, TIOCGETC, (char *)&otc); 15532147Sminshall ioctl(0, TIOCGLTC, (char *)&oltc); 15632147Sminshall 15732147Sminshall ntc = otc; 15832147Sminshall nltc = oltc; 15932147Sminshall nttyb = ottyb; 16032254Sminshall 16132254Sminshall termEofChar = ntc.t_eofc; 16232254Sminshall termEraseChar = nttyb.sg_erase; 16332254Sminshall termFlushChar = nltc.t_flushc; 16432254Sminshall termIntChar = ntc.t_intrc; 16532254Sminshall termKillChar = nttyb.sg_kill; 16632254Sminshall termQuitChar = ntc.t_quitc; 16732147Sminshall } 16832147Sminshall 16932147Sminshall void 17032553Sminshall TerminalRestoreState() 17132147Sminshall { 17232147Sminshall } 17332147Sminshall 17432147Sminshall /* 17532147Sminshall * TerminalNewMode - set up terminal to a specific mode. 17632147Sminshall */ 17732147Sminshall 17832147Sminshall 17932147Sminshall void 18033286Sminshall TerminalNewMode(f) 18132147Sminshall register int f; 18232147Sminshall { 18332147Sminshall static int prevmode = 0; 18432147Sminshall struct tchars *tc; 18532147Sminshall struct tchars tc3; 18632147Sminshall struct ltchars *ltc; 18732147Sminshall struct sgttyb sb; 18832147Sminshall int onoff; 18932147Sminshall int old; 19032147Sminshall struct tchars notc2; 19132147Sminshall struct ltchars noltc2; 19232147Sminshall static struct tchars notc = { -1, -1, -1, -1, -1, -1 }; 19332147Sminshall static struct ltchars noltc = { -1, -1, -1, -1, -1, -1 }; 19432147Sminshall 19532147Sminshall globalmode = f; 19632147Sminshall if (prevmode == f) 19732147Sminshall return; 19832147Sminshall old = prevmode; 19932147Sminshall prevmode = f; 20032147Sminshall sb = nttyb; 20132147Sminshall 20232147Sminshall switch (f) { 20332147Sminshall 20432147Sminshall case 0: 20532147Sminshall onoff = 0; 20632147Sminshall tc = &otc; 20732147Sminshall ltc = &oltc; 20832147Sminshall break; 20932147Sminshall 21032147Sminshall case 1: /* remote character processing, remote echo */ 21132147Sminshall case 2: /* remote character processing, local echo */ 21232147Sminshall case 6: /* 3270 mode - like 1, but with xon/xoff local */ 21332147Sminshall /* (might be nice to have "6" in telnet also...) */ 21432147Sminshall sb.sg_flags |= CBREAK; 21532147Sminshall if ((f == 1) || (f == 6)) { 21632147Sminshall sb.sg_flags &= ~(ECHO|CRMOD); 21732147Sminshall } else { 21832147Sminshall sb.sg_flags |= ECHO|CRMOD; 21932147Sminshall } 22032147Sminshall sb.sg_erase = sb.sg_kill = -1; 22137219Sminshall if (localflow || (f == 6)) { 22232147Sminshall tc = &tc3; 22332147Sminshall tc3 = notc; 22432147Sminshall /* get XON, XOFF characters */ 22532147Sminshall tc3.t_startc = otc.t_startc; 22632147Sminshall tc3.t_stopc = otc.t_stopc; 22732147Sminshall } else { 22832147Sminshall /* 22932147Sminshall * If user hasn't specified one way or the other, 23032147Sminshall * then default to not trapping signals. 23132147Sminshall */ 23232147Sminshall if (!donelclchars) { 23332147Sminshall localchars = 0; 23432147Sminshall } 23532147Sminshall if (localchars) { 23632147Sminshall notc2 = notc; 23732147Sminshall notc2.t_intrc = ntc.t_intrc; 23832147Sminshall notc2.t_quitc = ntc.t_quitc; 23932147Sminshall tc = ¬c2; 24032147Sminshall } else { 24132147Sminshall tc = ¬c; 24232147Sminshall } 24332147Sminshall } 24432147Sminshall ltc = &noltc; 24532147Sminshall onoff = 1; 24632147Sminshall break; 24732147Sminshall case 3: /* local character processing, remote echo */ 24832147Sminshall case 4: /* local character processing, local echo */ 24932147Sminshall case 5: /* local character processing, no echo */ 25032147Sminshall sb.sg_flags &= ~CBREAK; 25132147Sminshall sb.sg_flags |= CRMOD; 25232147Sminshall if (f == 4) 25332147Sminshall sb.sg_flags |= ECHO; 25432147Sminshall else 25532147Sminshall sb.sg_flags &= ~ECHO; 25632147Sminshall notc2 = ntc; 25732147Sminshall tc = ¬c2; 25832147Sminshall noltc2 = oltc; 25932147Sminshall ltc = &noltc2; 26032147Sminshall /* 26132147Sminshall * If user hasn't specified one way or the other, 26232147Sminshall * then default to trapping signals. 26332147Sminshall */ 26432147Sminshall if (!donelclchars) { 26532147Sminshall localchars = 1; 26632147Sminshall } 26732147Sminshall if (localchars) { 26832147Sminshall notc2.t_brkc = nltc.t_flushc; 26932147Sminshall noltc2.t_flushc = -1; 27032147Sminshall } else { 27132147Sminshall notc2.t_intrc = notc2.t_quitc = -1; 27232147Sminshall } 27332147Sminshall noltc2.t_suspc = escape; 27432147Sminshall noltc2.t_dsuspc = -1; 27532147Sminshall onoff = 1; 27632147Sminshall break; 27732147Sminshall 27832147Sminshall default: 27932147Sminshall return; 28032147Sminshall } 28133286Sminshall ioctl(tin, TIOCSLTC, (char *)ltc); 28233286Sminshall ioctl(tin, TIOCSETC, (char *)tc); 28333286Sminshall ioctl(tin, TIOCSETP, (char *)&sb); 28432147Sminshall #if (!defined(TN3270)) || ((!defined(NOT43)) || defined(PUTCHAR)) 28533286Sminshall ioctl(tin, FIONBIO, (char *)&onoff); 28633286Sminshall ioctl(tout, FIONBIO, (char *)&onoff); 28732147Sminshall #endif /* (!defined(TN3270)) || ((!defined(NOT43)) || defined(PUTCHAR)) */ 28832147Sminshall #if defined(TN3270) 28936242Sminshall if (noasynchtty == 0) { 29033286Sminshall ioctl(tin, FIOASYNC, (char *)&onoff); 29132147Sminshall } 29232147Sminshall #endif /* defined(TN3270) */ 29332147Sminshall 29432147Sminshall if (MODE_LINE(f)) { 29532147Sminshall void doescape(); 29632147Sminshall 29734849Sminshall (void) signal(SIGTSTP, (int (*)())doescape); 29832147Sminshall } else if (MODE_LINE(old)) { 29934849Sminshall (void) signal(SIGTSTP, SIG_DFL); 30032147Sminshall sigsetmask(sigblock(0) & ~(1<<(SIGTSTP-1))); 30132147Sminshall } 30232147Sminshall } 30332147Sminshall 30437219Sminshall void 30537219Sminshall TerminalSpeeds(ispeed, ospeed) 30637219Sminshall long *ispeed; 30737219Sminshall long *ospeed; 30837219Sminshall { 30937219Sminshall /* 31037219Sminshall * The order here is important. The index of each speed needs to 31137219Sminshall * correspond with the sgtty structure value for that speed. 31237219Sminshall * 31337219Sminshall * Additionally, the search algorithm assumes the table is in 31437219Sminshall * ascending sequence. 31537219Sminshall */ 31637219Sminshall static int ttyspeeds[] = { 31737219Sminshall 0, 50, 75, 110, 134, 150, 200, 300, 31837219Sminshall 600, 1200, 1800, 2400, 4800, 9600, 19200, 38400 }; 31937219Sminshall #define NUMSPEEDS sizeof ttyspeeds/sizeof ttyspeeds[0] 32032147Sminshall 32137219Sminshall if ((ottyb.sg_ospeed < 0) || (ottyb.sg_ospeed > NUMSPEEDS) || 32237219Sminshall (ottyb.sg_ispeed < 0) || (ottyb.sg_ispeed > NUMSPEEDS)) { 32337219Sminshall ExitString("Invalid terminal speed."); 32437219Sminshall /*NOTREACHED*/ 32537219Sminshall } else { 32637219Sminshall *ispeed = ttyspeeds[ottyb.sg_ispeed]; 32737219Sminshall *ospeed = ttyspeeds[ottyb.sg_ospeed]; 32837219Sminshall } 32937219Sminshall } 33037219Sminshall 33132147Sminshall int 33237219Sminshall TerminalWindowSize(rows, cols) 33337219Sminshall long *rows, *cols; 33437219Sminshall { 33537219Sminshall struct winsize ws; 33637219Sminshall 33737219Sminshall if (ioctl(fileno(stdin), TIOCGWINSZ, (char *)&ws) < 0) { 33837219Sminshall return 0; 33937219Sminshall } 34037219Sminshall *rows = ws.ws_row; 34137219Sminshall *cols = ws.ws_col; 34237219Sminshall return 1; 34337219Sminshall } 34437219Sminshall 34537219Sminshall int 34635417Sminshall NetClose(fd) 34735417Sminshall int fd; 34832147Sminshall { 34935417Sminshall return close(fd); 35032147Sminshall } 35132147Sminshall 35232147Sminshall 35332147Sminshall void 35432553Sminshall NetNonblockingIO(fd, onoff) 35532147Sminshall int 35632147Sminshall fd, 35732147Sminshall onoff; 35832147Sminshall { 35932147Sminshall ioctl(fd, FIONBIO, (char *)&onoff); 36032147Sminshall } 36132147Sminshall 36234849Sminshall #if defined(TN3270) 36332147Sminshall void 36432553Sminshall NetSigIO(fd, onoff) 36532147Sminshall int 36632147Sminshall fd, 36732147Sminshall onoff; 36832147Sminshall { 36932147Sminshall ioctl(fd, FIOASYNC, (char *)&onoff); /* hear about input */ 37032147Sminshall } 37132147Sminshall 37232147Sminshall void 37332553Sminshall NetSetPgrp(fd) 37432147Sminshall int fd; 37532147Sminshall { 37632147Sminshall int myPid; 37732147Sminshall 37832147Sminshall myPid = getpid(); 37936274Sminshall fcntl(fd, F_SETOWN, myPid); 38032147Sminshall } 38134849Sminshall #endif /*defined(TN3270)*/ 38232553Sminshall 38332553Sminshall /* 38432553Sminshall * Various signal handling routines. 38532553Sminshall */ 38632147Sminshall 38733286Sminshall static void 38832553Sminshall deadpeer() 38932553Sminshall { 39032553Sminshall setcommandmode(); 39132553Sminshall longjmp(peerdied, -1); 39232553Sminshall } 39332147Sminshall 39433286Sminshall static void 39532553Sminshall intr() 39632553Sminshall { 39732553Sminshall if (localchars) { 39832553Sminshall intp(); 39932553Sminshall return; 40032553Sminshall } 40132553Sminshall setcommandmode(); 40232553Sminshall longjmp(toplevel, -1); 40332553Sminshall } 40432553Sminshall 40533286Sminshall static void 40632553Sminshall intr2() 40732553Sminshall { 40832553Sminshall if (localchars) { 40932553Sminshall sendbrk(); 41032553Sminshall return; 41132553Sminshall } 41232553Sminshall } 41332553Sminshall 41433286Sminshall static void 41537219Sminshall sendwin() 41637219Sminshall { 41737219Sminshall if (connected) { 41837219Sminshall sendnaws(); 41937219Sminshall } 42037219Sminshall } 42137219Sminshall 42237219Sminshall static void 42332553Sminshall doescape() 42432553Sminshall { 42532553Sminshall command(0); 42632553Sminshall } 42732553Sminshall 42832553Sminshall void 42932531Sminshall sys_telnet_init() 43032531Sminshall { 43134849Sminshall (void) signal(SIGINT, (int (*)())intr); 43234849Sminshall (void) signal(SIGQUIT, (int (*)())intr2); 43334849Sminshall (void) signal(SIGPIPE, (int (*)())deadpeer); 43437219Sminshall (void) signal(SIGWINCH, (int (*)())sendwin); 43532553Sminshall 43632531Sminshall setconnmode(); 43732531Sminshall 43832531Sminshall NetNonblockingIO(net, 1); 43932531Sminshall 44032531Sminshall #if defined(TN3270) 44136242Sminshall if (noasynchnet == 0) { /* DBX can't handle! */ 44232531Sminshall NetSigIO(net, 1); 44332531Sminshall NetSetPgrp(net); 44432531Sminshall } 44532531Sminshall #endif /* defined(TN3270) */ 44632531Sminshall 44732531Sminshall #if defined(SO_OOBINLINE) 44834849Sminshall if (SetSockOpt(net, SOL_SOCKET, SO_OOBINLINE, 1) == -1) { 44934849Sminshall perror("SetSockOpt"); 45034849Sminshall } 45132531Sminshall #endif /* defined(SO_OOBINLINE) */ 45232531Sminshall } 45332531Sminshall 45432531Sminshall /* 45532531Sminshall * Process rings - 45632531Sminshall * 45732531Sminshall * This routine tries to fill up/empty our various rings. 45832531Sminshall * 45932531Sminshall * The parameter specifies whether this is a poll operation, 46032531Sminshall * or a block-until-something-happens operation. 46132531Sminshall * 46232531Sminshall * The return value is 1 if something happened, 0 if not. 46332531Sminshall */ 46432531Sminshall 46532531Sminshall int 46632531Sminshall process_rings(netin, netout, netex, ttyin, ttyout, poll) 46732531Sminshall int poll; /* If 0, then block until something to do */ 46832531Sminshall { 46932531Sminshall register int c; 47032531Sminshall /* One wants to be a bit careful about setting returnValue 47132531Sminshall * to one, since a one implies we did some useful work, 47232531Sminshall * and therefore probably won't be called to block next 47332531Sminshall * time (TN3270 mode only). 47432531Sminshall */ 47532531Sminshall int returnValue = 0; 47632531Sminshall static struct timeval TimeValue = { 0 }; 47732531Sminshall 47832531Sminshall if (netout) { 47932531Sminshall FD_SET(net, &obits); 48032531Sminshall } 48132531Sminshall if (ttyout) { 48232531Sminshall FD_SET(tout, &obits); 48332531Sminshall } 48432531Sminshall #if defined(TN3270) 48532531Sminshall if (ttyin) { 48632531Sminshall FD_SET(tin, &ibits); 48732531Sminshall } 48832531Sminshall #else /* defined(TN3270) */ 48932531Sminshall if (ttyin) { 49032531Sminshall FD_SET(tin, &ibits); 49132531Sminshall } 49232531Sminshall #endif /* defined(TN3270) */ 49332531Sminshall #if defined(TN3270) 49432531Sminshall if (netin) { 49532531Sminshall FD_SET(net, &ibits); 49632531Sminshall } 49732531Sminshall # else /* !defined(TN3270) */ 49832531Sminshall if (netin) { 49932531Sminshall FD_SET(net, &ibits); 50032531Sminshall } 50132531Sminshall # endif /* !defined(TN3270) */ 50232531Sminshall if (netex) { 50332531Sminshall FD_SET(net, &xbits); 50432531Sminshall } 50532531Sminshall if ((c = select(16, &ibits, &obits, &xbits, 50632531Sminshall (poll == 0)? (struct timeval *)0 : &TimeValue)) < 0) { 50732531Sminshall if (c == -1) { 50832531Sminshall /* 50932531Sminshall * we can get EINTR if we are in line mode, 51032531Sminshall * and the user does an escape (TSTP), or 51132531Sminshall * some other signal generator. 51232531Sminshall */ 51332531Sminshall if (errno == EINTR) { 51432531Sminshall return 0; 51532531Sminshall } 51632531Sminshall # if defined(TN3270) 51732531Sminshall /* 51832531Sminshall * we can get EBADF if we were in transparent 51932531Sminshall * mode, and the transcom process died. 52032531Sminshall */ 52132531Sminshall if (errno == EBADF) { 52232531Sminshall /* 52332531Sminshall * zero the bits (even though kernel does it) 52432531Sminshall * to make sure we are selecting on the right 52532531Sminshall * ones. 52632531Sminshall */ 52732531Sminshall FD_ZERO(&ibits); 52832531Sminshall FD_ZERO(&obits); 52932531Sminshall FD_ZERO(&xbits); 53032531Sminshall return 0; 53132531Sminshall } 53232531Sminshall # endif /* defined(TN3270) */ 53332531Sminshall /* I don't like this, does it ever happen? */ 53432531Sminshall printf("sleep(5) from telnet, after select\r\n"); 53532531Sminshall sleep(5); 53632531Sminshall } 53732531Sminshall return 0; 53832531Sminshall } 53932531Sminshall 54032531Sminshall /* 54132531Sminshall * Any urgent data? 54232531Sminshall */ 54332531Sminshall if (FD_ISSET(net, &xbits)) { 54432531Sminshall FD_CLR(net, &xbits); 54532531Sminshall SYNCHing = 1; 54632531Sminshall ttyflush(1); /* flush already enqueued data */ 54732531Sminshall } 54832531Sminshall 54932531Sminshall /* 55032531Sminshall * Something to read from the network... 55132531Sminshall */ 55232531Sminshall if (FD_ISSET(net, &ibits)) { 55332531Sminshall int canread; 55432531Sminshall 55532531Sminshall FD_CLR(net, &ibits); 55632531Sminshall canread = ring_empty_consecutive(&netiring); 55732531Sminshall #if !defined(SO_OOBINLINE) 55832531Sminshall /* 55932531Sminshall * In 4.2 (and some early 4.3) systems, the 56032531Sminshall * OOB indication and data handling in the kernel 56132531Sminshall * is such that if two separate TCP Urgent requests 56232531Sminshall * come in, one byte of TCP data will be overlaid. 56332531Sminshall * This is fatal for Telnet, but we try to live 56432531Sminshall * with it. 56532531Sminshall * 56632531Sminshall * In addition, in 4.2 (and...), a special protocol 56732531Sminshall * is needed to pick up the TCP Urgent data in 56832531Sminshall * the correct sequence. 56932531Sminshall * 57032531Sminshall * What we do is: if we think we are in urgent 57132531Sminshall * mode, we look to see if we are "at the mark". 57232531Sminshall * If we are, we do an OOB receive. If we run 57332531Sminshall * this twice, we will do the OOB receive twice, 57432531Sminshall * but the second will fail, since the second 57532531Sminshall * time we were "at the mark", but there wasn't 57632531Sminshall * any data there (the kernel doesn't reset 57732531Sminshall * "at the mark" until we do a normal read). 57832531Sminshall * Once we've read the OOB data, we go ahead 57932531Sminshall * and do normal reads. 58032531Sminshall * 58132531Sminshall * There is also another problem, which is that 58232531Sminshall * since the OOB byte we read doesn't put us 58332531Sminshall * out of OOB state, and since that byte is most 58432531Sminshall * likely the TELNET DM (data mark), we would 58532531Sminshall * stay in the TELNET SYNCH (SYNCHing) state. 58632531Sminshall * So, clocks to the rescue. If we've "just" 58732531Sminshall * received a DM, then we test for the 58832531Sminshall * presence of OOB data when the receive OOB 58932531Sminshall * fails (and AFTER we did the normal mode read 59032531Sminshall * to clear "at the mark"). 59132531Sminshall */ 59232531Sminshall if (SYNCHing) { 59332531Sminshall int atmark; 59432531Sminshall 59532531Sminshall ioctl(net, SIOCATMARK, (char *)&atmark); 59632531Sminshall if (atmark) { 59732531Sminshall c = recv(net, netiring.supply, canread, MSG_OOB); 59832531Sminshall if ((c == -1) && (errno == EINVAL)) { 59932531Sminshall c = recv(net, netiring.supply, canread, 0); 60032531Sminshall if (clocks.didnetreceive < clocks.gotDM) { 60132531Sminshall SYNCHing = stilloob(net); 60232531Sminshall } 60332531Sminshall } 60432531Sminshall } else { 60532531Sminshall c = recv(net, netiring.supply, canread, 0); 60632531Sminshall } 60732531Sminshall } else { 60832531Sminshall c = recv(net, netiring.supply, canread, 0); 60932531Sminshall } 61032531Sminshall settimer(didnetreceive); 61132531Sminshall #else /* !defined(SO_OOBINLINE) */ 61232531Sminshall c = recv(net, netiring.supply, canread, 0); 61332531Sminshall #endif /* !defined(SO_OOBINLINE) */ 61432531Sminshall if (c < 0 && errno == EWOULDBLOCK) { 61532531Sminshall c = 0; 61632531Sminshall } else if (c <= 0) { 61732531Sminshall return -1; 61832531Sminshall } 61932531Sminshall if (netdata) { 62032531Sminshall Dump('<', netiring.supply, c); 62132531Sminshall } 62232667Sminshall if (c) 62332667Sminshall ring_supplied(&netiring, c); 62432531Sminshall returnValue = 1; 62532531Sminshall } 62632531Sminshall 62732531Sminshall /* 62832531Sminshall * Something to read from the tty... 62932531Sminshall */ 63032531Sminshall if (FD_ISSET(tin, &ibits)) { 63132531Sminshall FD_CLR(tin, &ibits); 63233286Sminshall c = TerminalRead(ttyiring.supply, ring_empty_consecutive(&ttyiring)); 63332531Sminshall if (c < 0 && errno == EWOULDBLOCK) { 63432531Sminshall c = 0; 63532531Sminshall } else { 63632531Sminshall /* EOF detection for line mode!!!! */ 63733281Sminshall if ((c == 0) && MODE_LOCAL_CHARS(globalmode) && isatty(tin)) { 63832531Sminshall /* must be an EOF... */ 63932531Sminshall *ttyiring.supply = termEofChar; 64032531Sminshall c = 1; 64132531Sminshall } 64232531Sminshall if (c <= 0) { 64332531Sminshall return -1; 64432531Sminshall } 645*38208Sminshall if (termdata) { 646*38208Sminshall Dump('<', ttyiring.supply, c); 647*38208Sminshall } 64832667Sminshall ring_supplied(&ttyiring, c); 64932531Sminshall } 65032531Sminshall returnValue = 1; /* did something useful */ 65132531Sminshall } 65232531Sminshall 65332531Sminshall if (FD_ISSET(net, &obits)) { 65432531Sminshall FD_CLR(net, &obits); 65532531Sminshall returnValue |= netflush(); 65632531Sminshall } 65732531Sminshall if (FD_ISSET(tout, &obits)) { 65832531Sminshall FD_CLR(tout, &obits); 65932531Sminshall returnValue |= ttyflush(SYNCHing|flushout); 66032531Sminshall } 66132531Sminshall 66232531Sminshall return returnValue; 66332531Sminshall } 66432531Sminshall #endif /* defined(unix) */ 665