version 1.15, 2013/04/21 09:51:24 |
version 1.16, 2014/07/19 23:50:38 |
|
|
#define TELNET_FD_NET 2 |
#define TELNET_FD_NET 2 |
#define TELNET_FD_NUM 3 |
#define TELNET_FD_NUM 3 |
|
|
#ifndef USE_TERMIO |
|
struct tchars otc = { 0 }, ntc = { 0 }; |
|
struct ltchars oltc = { 0 }, nltc = { 0 }; |
|
struct sgttyb ottyb = { 0 }, nttyb = { 0 }; |
|
int olmode = 0; |
|
# define cfgetispeed(ptr) (ptr)->sg_ispeed |
|
# define cfgetospeed(ptr) (ptr)->sg_ospeed |
|
# define old_tc ottyb |
|
|
|
#else /* USE_TERMIO */ |
|
struct termios old_tc = { 0 }; |
struct termios old_tc = { 0 }; |
extern struct termios new_tc; |
extern struct termios new_tc; |
|
|
# ifndef TCSANOW |
|
# ifdef TCSETS |
|
# define TCSANOW TCSETS |
|
# define TCSADRAIN TCSETSW |
|
# define tcgetattr(f, t) ioctl(f, TCGETS, (char *)t) |
|
# else |
|
# ifdef TCSETA |
|
# define TCSANOW TCSETA |
|
# define TCSADRAIN TCSETAW |
|
# define tcgetattr(f, t) ioctl(f, TCGETA, (char *)t) |
|
# else |
|
# define TCSANOW TIOCSETA |
|
# define TCSADRAIN TIOCSETAW |
|
# define tcgetattr(f, t) ioctl(f, TIOCGETA, (char *)t) |
|
# endif |
|
# endif |
|
# define tcsetattr(f, a, t) ioctl(f, a, (char *)t) |
|
# define cfgetospeed(ptr) ((ptr)->c_cflag&CBAUD) |
|
# ifdef CIBAUD |
|
# define cfgetispeed(ptr) (((ptr)->c_cflag&CIBAUD) >> IBSHIFT) |
|
# else |
|
# define cfgetispeed(ptr) cfgetospeed(ptr) |
|
# endif |
|
# endif /* TCSANOW */ |
|
# ifdef sysV88 |
|
# define TIOCFLUSH TC_PX_DRAIN |
|
# endif |
|
#endif /* USE_TERMIO */ |
|
|
|
void |
void |
init_sys() |
init_sys() |
{ |
{ |
|
|
void |
void |
TerminalSaveState() |
TerminalSaveState() |
{ |
{ |
#ifndef USE_TERMIO |
|
ioctl(0, TIOCGETP, (char *)&ottyb); |
|
ioctl(0, TIOCGETC, (char *)&otc); |
|
ioctl(0, TIOCGLTC, (char *)&oltc); |
|
ioctl(0, TIOCLGET, (char *)&olmode); |
|
|
|
ntc = otc; |
|
nltc = oltc; |
|
nttyb = ottyb; |
|
|
|
#else /* USE_TERMIO */ |
|
tcgetattr(0, &old_tc); |
tcgetattr(0, &old_tc); |
|
|
new_tc = old_tc; |
new_tc = old_tc; |
|
|
#ifndef VSTATUS |
#ifndef VSTATUS |
termAytChar = CONTROL('T'); |
termAytChar = CONTROL('T'); |
#endif |
#endif |
#endif /* USE_TERMIO */ |
|
} |
} |
|
|
cc_t * |
cc_t * |
|
|
case SLC_XON: return(&termStartChar); |
case SLC_XON: return(&termStartChar); |
case SLC_XOFF: return(&termStopChar); |
case SLC_XOFF: return(&termStopChar); |
case SLC_FORW1: return(&termForw1Char); |
case SLC_FORW1: return(&termForw1Char); |
#ifdef USE_TERMIO |
|
case SLC_FORW2: return(&termForw2Char); |
case SLC_FORW2: return(&termForw2Char); |
# ifdef VDISCARD |
# ifdef VDISCARD |
case SLC_AO: return(&termFlushChar); |
case SLC_AO: return(&termFlushChar); |
|
|
# ifdef VSTATUS |
# ifdef VSTATUS |
case SLC_AYT: return(&termAytChar); |
case SLC_AYT: return(&termAytChar); |
# endif |
# endif |
#endif |
|
|
|
case SLC_SYNCH: |
case SLC_SYNCH: |
case SLC_BRK: |
case SLC_BRK: |
|
|
void |
void |
TerminalDefaultChars() |
TerminalDefaultChars() |
{ |
{ |
#ifndef USE_TERMIO |
|
ntc = otc; |
|
nltc = oltc; |
|
nttyb.sg_kill = ottyb.sg_kill; |
|
nttyb.sg_erase = ottyb.sg_erase; |
|
#else /* USE_TERMIO */ |
|
memmove(new_tc.c_cc, old_tc.c_cc, sizeof(old_tc.c_cc)); |
memmove(new_tc.c_cc, old_tc.c_cc, sizeof(old_tc.c_cc)); |
# ifndef VDISCARD |
# ifndef VDISCARD |
termFlushChar = CONTROL('O'); |
termFlushChar = CONTROL('O'); |
|
|
# ifndef VSTATUS |
# ifndef VSTATUS |
termAytChar = CONTROL('T'); |
termAytChar = CONTROL('T'); |
# endif |
# endif |
#endif /* USE_TERMIO */ |
|
} |
} |
|
|
#ifdef notdef |
|
void |
|
TerminalRestoreState() |
|
{ |
|
} |
|
#endif |
|
|
|
/* |
/* |
* TerminalNewMode - set up terminal to a specific mode. |
* TerminalNewMode - set up terminal to a specific mode. |
* MODE_ECHO: do local terminal echo |
* MODE_ECHO: do local terminal echo |
|
|
int f; |
int f; |
{ |
{ |
static int prevmode = 0; |
static int prevmode = 0; |
#ifndef USE_TERMIO |
|
struct tchars tc; |
|
struct ltchars ltc; |
|
struct sgttyb sb; |
|
int lmode; |
|
#else /* USE_TERMIO */ |
|
struct termios tmp_tc; |
struct termios tmp_tc; |
#endif /* USE_TERMIO */ |
|
int onoff; |
int onoff; |
int old; |
int old; |
cc_t esc; |
cc_t esc; |
|
|
* left to write out, it returns -1 if it couldn't do |
* left to write out, it returns -1 if it couldn't do |
* anything at all, otherwise it returns 1 + the number |
* anything at all, otherwise it returns 1 + the number |
* of characters left to write. |
* of characters left to write. |
#ifndef USE_TERMIO |
|
* We would really like ask the kernel to wait for the output |
|
* to drain, like we can do with the TCSADRAIN, but we don't have |
|
* that option. The only ioctl that waits for the output to |
|
* drain, TIOCSETP, also flushes the input queue, which is NOT |
|
* what we want (TIOCSETP is like TCSADFLUSH). |
|
#endif |
|
*/ |
*/ |
old = ttyflush(SYNCHing|flushout); |
old = ttyflush(SYNCHing|flushout); |
if (old < 0 || old > 1) { |
if (old < 0 || old > 1) { |
#ifdef USE_TERMIO |
|
tcgetattr(tin, &tmp_tc); |
tcgetattr(tin, &tmp_tc); |
#endif /* USE_TERMIO */ |
|
do { |
do { |
/* |
/* |
* Wait for data to drain, then flush again. |
* Wait for data to drain, then flush again. |
*/ |
*/ |
#ifdef USE_TERMIO |
|
tcsetattr(tin, TCSADRAIN, &tmp_tc); |
tcsetattr(tin, TCSADRAIN, &tmp_tc); |
#endif /* USE_TERMIO */ |
|
old = ttyflush(SYNCHing|flushout); |
old = ttyflush(SYNCHing|flushout); |
} while (old < 0 || old > 1); |
} while (old < 0 || old > 1); |
} |
} |
|
|
old = prevmode; |
old = prevmode; |
prevmode = f&~MODE_FORCE; |
prevmode = f&~MODE_FORCE; |
#ifndef USE_TERMIO |
|
sb = nttyb; |
|
tc = ntc; |
|
ltc = nltc; |
|
lmode = olmode; |
|
#else |
|
tmp_tc = new_tc; |
tmp_tc = new_tc; |
#endif |
|
|
|
if (f&MODE_ECHO) { |
if (f&MODE_ECHO) { |
#ifndef USE_TERMIO |
|
sb.sg_flags |= ECHO; |
|
#else |
|
tmp_tc.c_lflag |= ECHO; |
tmp_tc.c_lflag |= ECHO; |
tmp_tc.c_oflag |= ONLCR; |
tmp_tc.c_oflag |= ONLCR; |
if (crlf) |
if (crlf) |
tmp_tc.c_iflag |= ICRNL; |
tmp_tc.c_iflag |= ICRNL; |
#endif |
|
} else { |
} else { |
#ifndef USE_TERMIO |
|
sb.sg_flags &= ~ECHO; |
|
#else |
|
tmp_tc.c_lflag &= ~ECHO; |
tmp_tc.c_lflag &= ~ECHO; |
tmp_tc.c_oflag &= ~ONLCR; |
tmp_tc.c_oflag &= ~ONLCR; |
# ifdef notdef |
|
if (crlf) |
|
tmp_tc.c_iflag &= ~ICRNL; |
|
# endif |
|
#endif |
|
} |
} |
|
|
if ((f&MODE_FLOW) == 0) { |
if ((f&MODE_FLOW) == 0) { |
#ifndef USE_TERMIO |
|
tc.t_startc = _POSIX_VDISABLE; |
|
tc.t_stopc = _POSIX_VDISABLE; |
|
#else |
|
tmp_tc.c_iflag &= ~(IXOFF|IXON); /* Leave the IXANY bit alone */ |
tmp_tc.c_iflag &= ~(IXOFF|IXON); /* Leave the IXANY bit alone */ |
} else { |
} else { |
if (restartany < 0) { |
if (restartany < 0) { |
|
|
tmp_tc.c_iflag |= IXOFF|IXON; |
tmp_tc.c_iflag |= IXOFF|IXON; |
tmp_tc.c_iflag &= ~IXANY; |
tmp_tc.c_iflag &= ~IXANY; |
} |
} |
#endif |
|
} |
} |
|
|
if ((f&MODE_TRAPSIG) == 0) { |
if ((f&MODE_TRAPSIG) == 0) { |
#ifndef USE_TERMIO |
|
tc.t_intrc = _POSIX_VDISABLE; |
|
tc.t_quitc = _POSIX_VDISABLE; |
|
tc.t_eofc = _POSIX_VDISABLE; |
|
ltc.t_suspc = _POSIX_VDISABLE; |
|
ltc.t_dsuspc = _POSIX_VDISABLE; |
|
#else |
|
tmp_tc.c_lflag &= ~ISIG; |
tmp_tc.c_lflag &= ~ISIG; |
#endif |
|
localchars = 0; |
localchars = 0; |
} else { |
} else { |
#ifdef USE_TERMIO |
|
tmp_tc.c_lflag |= ISIG; |
tmp_tc.c_lflag |= ISIG; |
#endif |
|
localchars = 1; |
localchars = 1; |
} |
} |
|
|
if (f&MODE_EDIT) { |
if (f&MODE_EDIT) { |
#ifndef USE_TERMIO |
|
sb.sg_flags &= ~CBREAK; |
|
sb.sg_flags |= CRMOD; |
|
#else |
|
tmp_tc.c_lflag |= ICANON; |
tmp_tc.c_lflag |= ICANON; |
#endif |
|
} else { |
} else { |
#ifndef USE_TERMIO |
|
sb.sg_flags |= CBREAK; |
|
if (f&MODE_ECHO) |
|
sb.sg_flags |= CRMOD; |
|
else |
|
sb.sg_flags &= ~CRMOD; |
|
#else |
|
tmp_tc.c_lflag &= ~ICANON; |
tmp_tc.c_lflag &= ~ICANON; |
tmp_tc.c_iflag &= ~ICRNL; |
tmp_tc.c_iflag &= ~ICRNL; |
tmp_tc.c_cc[VMIN] = 1; |
tmp_tc.c_cc[VMIN] = 1; |
tmp_tc.c_cc[VTIME] = 0; |
tmp_tc.c_cc[VTIME] = 0; |
#endif |
|
} |
} |
|
|
if ((f&(MODE_EDIT|MODE_TRAPSIG)) == 0) { |
if ((f&(MODE_EDIT|MODE_TRAPSIG)) == 0) { |
#ifndef USE_TERMIO |
|
ltc.t_lnextc = _POSIX_VDISABLE; |
|
#else |
|
tmp_tc.c_lflag &= ~IEXTEN; |
tmp_tc.c_lflag &= ~IEXTEN; |
#endif |
|
} |
} |
|
|
if (f&MODE_SOFT_TAB) { |
if (f&MODE_SOFT_TAB) { |
#ifndef USE_TERMIO |
|
sb.sg_flags |= XTABS; |
|
#else |
|
# ifdef OXTABS |
# ifdef OXTABS |
tmp_tc.c_oflag |= OXTABS; |
tmp_tc.c_oflag |= OXTABS; |
# endif |
# endif |
|
|
tmp_tc.c_oflag &= ~TABDLY; |
tmp_tc.c_oflag &= ~TABDLY; |
tmp_tc.c_oflag |= TAB3; |
tmp_tc.c_oflag |= TAB3; |
# endif |
# endif |
#endif |
|
} else { |
} else { |
#ifndef USE_TERMIO |
|
sb.sg_flags &= ~XTABS; |
|
#else |
|
# ifdef OXTABS |
# ifdef OXTABS |
tmp_tc.c_oflag &= ~OXTABS; |
tmp_tc.c_oflag &= ~OXTABS; |
# endif |
# endif |
# ifdef TABDLY |
# ifdef TABDLY |
tmp_tc.c_oflag &= ~TABDLY; |
tmp_tc.c_oflag &= ~TABDLY; |
# endif |
# endif |
#endif |
|
} |
} |
|
|
if (f&MODE_LIT_ECHO) { |
if (f&MODE_LIT_ECHO) { |
#ifndef USE_TERMIO |
|
lmode &= ~LCTLECH; |
|
#else |
|
# ifdef ECHOCTL |
# ifdef ECHOCTL |
tmp_tc.c_lflag &= ~ECHOCTL; |
tmp_tc.c_lflag &= ~ECHOCTL; |
# endif |
# endif |
#endif |
|
} else { |
} else { |
#ifndef USE_TERMIO |
|
lmode |= LCTLECH; |
|
#else |
|
# ifdef ECHOCTL |
# ifdef ECHOCTL |
tmp_tc.c_lflag |= ECHOCTL; |
tmp_tc.c_lflag |= ECHOCTL; |
# endif |
# endif |
#endif |
|
} |
} |
|
|
if (f == -1) { |
if (f == -1) { |
onoff = 0; |
onoff = 0; |
} else { |
} else { |
#ifndef USE_TERMIO |
|
if (f & MODE_OUTBIN) |
|
lmode |= LLITOUT; |
|
else |
|
lmode &= ~LLITOUT; |
|
|
|
if (f & MODE_INBIN) |
if (f & MODE_INBIN) |
lmode |= LPASS8; |
|
else |
|
lmode &= ~LPASS8; |
|
#else |
|
if (f & MODE_INBIN) |
|
tmp_tc.c_iflag &= ~ISTRIP; |
tmp_tc.c_iflag &= ~ISTRIP; |
else |
else |
tmp_tc.c_iflag |= ISTRIP; |
tmp_tc.c_iflag |= ISTRIP; |
|
|
tmp_tc.c_cflag |= old_tc.c_cflag & (CSIZE|PARENB); |
tmp_tc.c_cflag |= old_tc.c_cflag & (CSIZE|PARENB); |
tmp_tc.c_oflag |= OPOST; |
tmp_tc.c_oflag |= OPOST; |
} |
} |
#endif |
|
onoff = 1; |
onoff = 1; |
} |
} |
|
|
|
|
#ifdef SIGINFO |
#ifdef SIGINFO |
(void) signal(SIGINFO, ayt); |
(void) signal(SIGINFO, ayt); |
#endif |
#endif |
#if defined(USE_TERMIO) && defined(NOKERNINFO) |
#if defined(NOKERNINFO) |
tmp_tc.c_lflag |= NOKERNINFO; |
tmp_tc.c_lflag |= NOKERNINFO; |
#endif |
#endif |
/* |
/* |
|
|
* to process it because it will be processed when the |
* to process it because it will be processed when the |
* user attempts to read it, not when we send it. |
* user attempts to read it, not when we send it. |
*/ |
*/ |
#ifndef USE_TERMIO |
|
ltc.t_dsuspc = _POSIX_VDISABLE; |
|
#else |
|
# ifdef VDSUSP |
# ifdef VDSUSP |
tmp_tc.c_cc[VDSUSP] = (cc_t)(_POSIX_VDISABLE); |
tmp_tc.c_cc[VDSUSP] = (cc_t)(_POSIX_VDISABLE); |
# endif |
# endif |
#endif |
|
#ifdef USE_TERMIO |
|
/* |
/* |
* If the VEOL character is already set, then use VEOL2, |
* If the VEOL character is already set, then use VEOL2, |
* otherwise use VEOL. |
* otherwise use VEOL. |
|
|
tmp_tc.c_cc[VEOL2] = esc; |
tmp_tc.c_cc[VEOL2] = esc; |
# endif |
# endif |
} |
} |
#else |
|
if (tc.t_brkc == (cc_t)(_POSIX_VDISABLE)) |
|
tc.t_brkc = esc; |
|
#endif |
|
} else { |
} else { |
#ifdef SIGTSTP |
#ifdef SIGTSTP |
sigset_t mask; |
sigset_t mask; |
|
|
sigaddset(&mask, SIGTSTP); |
sigaddset(&mask, SIGTSTP); |
sigprocmask(SIG_UNBLOCK, &mask, NULL); |
sigprocmask(SIG_UNBLOCK, &mask, NULL); |
#endif /* SIGTSTP */ |
#endif /* SIGTSTP */ |
#ifndef USE_TERMIO |
|
ltc = oltc; |
|
tc = otc; |
|
sb = ottyb; |
|
lmode = olmode; |
|
#else |
|
tmp_tc = old_tc; |
tmp_tc = old_tc; |
#endif |
|
} |
} |
#ifndef USE_TERMIO |
|
ioctl(tin, TIOCLSET, (char *)&lmode); |
|
ioctl(tin, TIOCSLTC, (char *)<c); |
|
ioctl(tin, TIOCSETC, (char *)&tc); |
|
ioctl(tin, TIOCSETN, (char *)&sb); |
|
#else |
|
if (tcsetattr(tin, TCSADRAIN, &tmp_tc) < 0) |
if (tcsetattr(tin, TCSADRAIN, &tmp_tc) < 0) |
tcsetattr(tin, TCSANOW, &tmp_tc); |
tcsetattr(tin, TCSANOW, &tmp_tc); |
#endif |
|
|
|
#if (!defined(TN3270)) || ((!defined(NOT43)) || defined(PUTCHAR)) |
|
# if !defined(sysV88) |
|
ioctl(tin, FIONBIO, (char *)&onoff); |
ioctl(tin, FIONBIO, (char *)&onoff); |
ioctl(tout, FIONBIO, (char *)&onoff); |
ioctl(tout, FIONBIO, (char *)&onoff); |
# endif |
|
#endif /* (!defined(TN3270)) || ((!defined(NOT43)) || defined(PUTCHAR)) */ |
|
#if defined(TN3270) |
|
if (noasynchtty == 0) { |
|
ioctl(tin, FIOASYNC, (char *)&onoff); |
|
} |
|
#endif /* defined(TN3270) */ |
|
|
|
} |
} |
|
|
/* |
/* |
|
|
ioctl(fd, FIONBIO, (char *)&onoff); |
ioctl(fd, FIONBIO, (char *)&onoff); |
} |
} |
|
|
#if defined(TN3270) |
|
void |
|
NetSigIO(fd, onoff) |
|
int fd; |
|
int onoff; |
|
{ |
|
ioctl(fd, FIOASYNC, (char *)&onoff); /* hear about input */ |
|
} |
|
|
|
void |
|
NetSetPgrp(fd) |
|
int fd; |
|
{ |
|
pid_t myPid; |
|
|
|
myPid = getpid(); |
|
fcntl(fd, F_SETOWN, myPid); |
|
} |
|
#endif /*defined(TN3270)*/ |
|
|
|
/* |
/* |
* Various signal handling routines. |
* Various signal handling routines. |
|
|
void |
void |
sys_telnet_init() |
sys_telnet_init() |
{ |
{ |
|
int one = 1; |
|
|
(void) signal(SIGINT, intr); |
(void) signal(SIGINT, intr); |
(void) signal(SIGQUIT, intr2); |
(void) signal(SIGQUIT, intr2); |
(void) signal(SIGPIPE, deadpeer); |
(void) signal(SIGPIPE, deadpeer); |
|
|
|
|
NetNonblockingIO(net, 1); |
NetNonblockingIO(net, 1); |
|
|
#if defined(TN3270) |
if (setsockopt(net, SOL_SOCKET, SO_OOBINLINE, &one, sizeof(one)) == -1) { |
if (noasynchnet == 0) { /* DBX can't handle! */ |
perror("setsockopt"); |
NetSigIO(net, 1); |
|
NetSetPgrp(net); |
|
} |
} |
#endif /* defined(TN3270) */ |
|
|
|
#if defined(SO_OOBINLINE) |
|
if (SetSockOpt(net, SOL_SOCKET, SO_OOBINLINE, 1) == -1) { |
|
perror("SetSockOpt"); |
|
} |
|
#endif /* defined(SO_OOBINLINE) */ |
|
} |
} |
|
|
/* |
/* |
|
|
if (errno == EINTR) { |
if (errno == EINTR) { |
return 0; |
return 0; |
} |
} |
# if defined(TN3270) |
|
/* |
|
* we can get EBADF if we were in transparent |
|
* mode, and the transcom process died. |
|
*/ |
|
if (errno == EBADF) { |
|
return 0; |
|
} |
|
# endif /* defined(TN3270) */ |
|
/* I don't like this, does it ever happen? */ |
/* I don't like this, does it ever happen? */ |
printf("sleep(5) from telnet, after poll\r\n"); |
printf("sleep(5) from telnet, after poll\r\n"); |
sleep(5); |
sleep(5); |
|
|
int canread; |
int canread; |
|
|
canread = ring_empty_consecutive(&netiring); |
canread = ring_empty_consecutive(&netiring); |
#if !defined(SO_OOBINLINE) |
|
/* |
|
* In 4.2 (and some early 4.3) systems, the |
|
* OOB indication and data handling in the kernel |
|
* is such that if two separate TCP Urgent requests |
|
* come in, one byte of TCP data will be overlaid. |
|
* This is fatal for Telnet, but we try to live |
|
* with it. |
|
* |
|
* In addition, in 4.2 (and...), a special protocol |
|
* is needed to pick up the TCP Urgent data in |
|
* the correct sequence. |
|
* |
|
* What we do is: if we think we are in urgent |
|
* mode, we look to see if we are "at the mark". |
|
* If we are, we do an OOB receive. If we run |
|
* this twice, we will do the OOB receive twice, |
|
* but the second will fail, since the second |
|
* time we were "at the mark", but there wasn't |
|
* any data there (the kernel doesn't reset |
|
* "at the mark" until we do a normal read). |
|
* Once we've read the OOB data, we go ahead |
|
* and do normal reads. |
|
* |
|
* There is also another problem, which is that |
|
* since the OOB byte we read doesn't put us |
|
* out of OOB state, and since that byte is most |
|
* likely the TELNET DM (data mark), we would |
|
* stay in the TELNET SYNCH (SYNCHing) state. |
|
* So, clocks to the rescue. If we've "just" |
|
* received a DM, then we test for the |
|
* presence of OOB data when the receive OOB |
|
* fails (and AFTER we did the normal mode read |
|
* to clear "at the mark"). |
|
*/ |
|
if (SYNCHing) { |
|
int atmark; |
|
static int bogus_oob = 0, first = 1; |
|
|
|
ioctl(net, SIOCATMARK, (char *)&atmark); |
|
if (atmark) { |
|
c = recv(net, netiring.supply, canread, MSG_OOB); |
|
if ((c == -1) && (errno == EINVAL)) { |
|
c = recv(net, netiring.supply, canread, 0); |
|
if (clocks.didnetreceive < clocks.gotDM) { |
|
SYNCHing = stilloob(net); |
|
} |
|
} else if (first && c > 0) { |
|
/* |
|
* Bogosity check. Systems based on 4.2BSD |
|
* do not return an error if you do a second |
|
* recv(MSG_OOB). So, we do one. If it |
|
* succeeds and returns exactly the same |
|
* data, then assume that we are running |
|
* on a broken system and set the bogus_oob |
|
* flag. (If the data was different, then |
|
* we probably got some valid new data, so |
|
* increment the count...) |
|
*/ |
|
int i; |
|
i = recv(net, netiring.supply + c, canread - c, MSG_OOB); |
|
if (i == c && |
|
memcmp(netiring.supply, netiring.supply + c, i) == 0) { |
|
bogus_oob = 1; |
|
first = 0; |
|
} else if (i < 0) { |
|
bogus_oob = 0; |
|
first = 0; |
|
} else |
|
c += i; |
|
} |
|
if (bogus_oob && c > 0) { |
|
int i; |
|
/* |
|
* Bogosity. We have to do the read |
|
* to clear the atmark to get out of |
|
* an infinate loop. |
|
*/ |
|
i = read(net, netiring.supply + c, canread - c); |
|
if (i > 0) |
|
c += i; |
|
} |
|
} else { |
|
c = recv(net, netiring.supply, canread, 0); |
|
} |
|
} else { |
|
c = recv(net, netiring.supply, canread, 0); |
|
} |
|
settimer(didnetreceive); |
|
#else /* !defined(SO_OOBINLINE) */ |
|
c = recv(net, (char *)netiring.supply, canread, 0); |
c = recv(net, (char *)netiring.supply, canread, 0); |
#endif /* !defined(SO_OOBINLINE) */ |
|
if (c < 0 && errno == EWOULDBLOCK) { |
if (c < 0 && errno == EWOULDBLOCK) { |
c = 0; |
c = 0; |
} else if (c <= 0) { |
} else if (c <= 0) { |