diff options
Diffstat (limited to 'lib/libc/rpc')
-rw-r--r-- | lib/libc/rpc/clnt_tcp.c | 54 | ||||
-rw-r--r-- | lib/libc/rpc/clnt_udp.c | 114 | ||||
-rw-r--r-- | lib/libc/rpc/pmap_rmt.c | 49 | ||||
-rw-r--r-- | lib/libc/rpc/svc.c | 59 | ||||
-rw-r--r-- | lib/libc/rpc/svc_run.c | 21 | ||||
-rw-r--r-- | lib/libc/rpc/svc_tcp.c | 49 |
6 files changed, 233 insertions, 113 deletions
diff --git a/lib/libc/rpc/clnt_tcp.c b/lib/libc/rpc/clnt_tcp.c index 1f9279fb0ad..daa893f3ed2 100644 --- a/lib/libc/rpc/clnt_tcp.c +++ b/lib/libc/rpc/clnt_tcp.c @@ -1,4 +1,4 @@ -/* $OpenBSD: clnt_tcp.c,v 1.4 1996/07/20 06:12:24 deraadt Exp $ */ +/* $OpenBSD: clnt_tcp.c,v 1.5 1996/08/15 07:27:47 deraadt Exp $ */ /* $NetBSD: clnt_tcp.c,v 1.4 1995/02/25 03:01:41 cgd Exp $ */ /* @@ -33,7 +33,7 @@ #if defined(LIBC_SCCS) && !defined(lint) /*static char *sccsid = "from: @(#)clnt_tcp.c 1.37 87/10/05 Copyr 1984 Sun Micro";*/ /*static char *sccsid = "from: @(#)clnt_tcp.c 2.2 88/08/01 4.0 RPCSRC";*/ -static char *rcsid = "$OpenBSD: clnt_tcp.c,v 1.4 1996/07/20 06:12:24 deraadt Exp $"; +static char *rcsid = "$OpenBSD: clnt_tcp.c,v 1.5 1996/08/15 07:27:47 deraadt Exp $"; #endif /* @@ -404,39 +404,65 @@ readtcp(ct, buf, len) caddr_t buf; register int len; { - fd_set mask; - fd_set readfds; + fd_set *fds, readfds; + struct timeval start, after, duration, delta, tmp; + int r, save_errno; if (len == 0) return (0); - FD_ZERO(&mask); - FD_SET(ct->ct_sock, &mask); + + if (ct->ct_sock+1 > FD_SETSIZE) { + fds = (fd_set *)malloc(howmany(ct->ct_sock+1, NBBY)); + if (fds == NULL) + return (-1); + memset(fds, '\0', howmany(ct->ct_sock+1, NBBY)); + } else { + fds = &readfds; + FD_ZERO(fds); + } + + gettimeofday(&start, NULL); + delta = ct->ct_wait; while (TRUE) { - readfds = mask; - switch (select(ct->ct_sock+1, &readfds, NULL, NULL, - &(ct->ct_wait))) { + /* XXX we know the other bits are still clear */ + FD_SET(ct->ct_sock, fds); + r = select(ct->ct_sock+1, fds, NULL, NULL, &delta); + save_errno = errno; + + gettimeofday(&after, NULL); + timersub(&start, &after, &duration); + timersub(&delta, &duration, &tmp); + delta = tmp; + if (delta.tv_sec < 0 || !timerisset(&delta)) + r = 0; + + switch (r) { case 0: ct->ct_error.re_status = RPC_TIMEDOUT; + if (fds != &readfds) + free(fds); return (-1); - case -1: - if (errno == EINTR) + if (errno == EINTR); continue; ct->ct_error.re_status = RPC_CANTRECV; - ct->ct_error.re_errno = errno; + ct->ct_error.re_errno = save_errno; + if (fds != &readfds) + free(fds); return (-1); } break; } - switch (len = read(ct->ct_sock, buf, len)) { + if (fds != &readfds) + free(fds); + switch (len = read(ct->ct_sock, buf, len)) { case 0: /* premature eof */ ct->ct_error.re_errno = ECONNRESET; ct->ct_error.re_status = RPC_CANTRECV; len = -1; /* it's really an error */ break; - case -1: ct->ct_error.re_errno = errno; ct->ct_error.re_status = RPC_CANTRECV; diff --git a/lib/libc/rpc/clnt_udp.c b/lib/libc/rpc/clnt_udp.c index d7fea262431..fadb7707d54 100644 --- a/lib/libc/rpc/clnt_udp.c +++ b/lib/libc/rpc/clnt_udp.c @@ -1,4 +1,4 @@ -/* $OpenBSD: clnt_udp.c,v 1.4 1996/07/20 06:12:25 deraadt Exp $ */ +/* $OpenBSD: clnt_udp.c,v 1.5 1996/08/15 07:27:48 deraadt Exp $ */ /* $NetBSD: clnt_udp.c,v 1.4 1995/02/25 03:01:42 cgd Exp $ */ /* @@ -33,7 +33,7 @@ #if defined(LIBC_SCCS) && !defined(lint) /*static char *sccsid = "from: @(#)clnt_udp.c 1.39 87/08/11 Copyr 1984 Sun Micro";*/ /*static char *sccsid = "from: @(#)clnt_udp.c 2.2 88/08/01 4.0 RPCSRC";*/ -static char *rcsid = "$OpenBSD: clnt_udp.c,v 1.4 1996/07/20 06:12:25 deraadt Exp $"; +static char *rcsid = "$OpenBSD: clnt_udp.c,v 1.5 1996/08/15 07:27:48 deraadt Exp $"; #endif /* @@ -224,24 +224,31 @@ clntudp_call(cl, proc, xargs, argsp, xresults, resultsp, utimeout) register int outlen; register int inlen; int fromlen; - fd_set readfds; - fd_set mask; + fd_set *fds, readfds; struct sockaddr_in from; struct rpc_msg reply_msg; XDR reply_xdrs; - struct timeval time_waited; + struct timeval time_waited, start, after, tmp1, tmp2; bool_t ok; int nrefreshes = 2; /* number of times to refresh cred */ struct timeval timeout; - if (cu->cu_total.tv_usec == -1) { + if (cu->cu_total.tv_usec == -1) timeout = utimeout; /* use supplied timeout */ - } else { + else timeout = cu->cu_total; /* use default timeout */ + + if (cu->cu_sock+1 > FD_SETSIZE) { + fds = (fd_set *)malloc(howmany(cu->cu_sock+1, NBBY)); + if (fds == NULL) + return (cu->cu_error.re_status = RPC_CANTSEND); + memset(fds, '\0', howmany(cu->cu_sock+1, NBBY)); + } else { + fds = &readfds; + FD_ZERO(fds); } - time_waited.tv_sec = 0; - time_waited.tv_usec = 0; + timerclear(&time_waited); call_again: xdrs = &(cu->cu_outxdrs); xdrs->x_op = XDR_ENCODE; @@ -250,26 +257,33 @@ call_again: * the transaction is the first thing in the out buffer */ (*(u_short *)(cu->cu_outbuf))++; - if ((! XDR_PUTLONG(xdrs, (long *)&proc)) || - (! AUTH_MARSHALL(cl->cl_auth, xdrs)) || - (! (*xargs)(xdrs, argsp))) + if (!XDR_PUTLONG(xdrs, (long *)&proc) || + !AUTH_MARSHALL(cl->cl_auth, xdrs) || + !(*xargs)(xdrs, argsp)) { + if (fds != &readfds) + free(fds); return (cu->cu_error.re_status = RPC_CANTENCODEARGS); + } outlen = (int)XDR_GETPOS(xdrs); send_again: if (sendto(cu->cu_sock, cu->cu_outbuf, outlen, 0, - (struct sockaddr *)&(cu->cu_raddr), cu->cu_rlen) - != outlen) { + (struct sockaddr *)&(cu->cu_raddr), cu->cu_rlen) != outlen) { cu->cu_error.re_errno = errno; + if (fds != &readfds) + free(fds); return (cu->cu_error.re_status = RPC_CANTSEND); } /* * Hack to provide rpc-based message passing */ - if (timeout.tv_sec == 0 && timeout.tv_usec == 0) { + if (!timerisset(&timeout)) { + if (fds != &readfds) + free(fds); return (cu->cu_error.re_status = RPC_TIMEDOUT); } + /* * sub-optimal code appears here because we have * some clock time to spare while the packets are in flight. @@ -278,46 +292,50 @@ send_again: reply_msg.acpted_rply.ar_verf = _null_auth; reply_msg.acpted_rply.ar_results.where = resultsp; reply_msg.acpted_rply.ar_results.proc = xresults; - FD_ZERO(&mask); - FD_SET(cu->cu_sock, &mask); - for (;;) { - readfds = mask; - switch (select(cu->cu_sock+1, &readfds, NULL, - NULL, &(cu->cu_wait))) { + gettimeofday(&start, NULL); + for (;;) { + /* XXX we know the other bits are still clear */ + FD_SET(cu->cu_sock, fds); + switch (select(cu->cu_sock+1, fds, NULL, NULL, &cu->cu_wait)) { case 0: - time_waited.tv_sec += cu->cu_wait.tv_sec; - time_waited.tv_usec += cu->cu_wait.tv_usec; - while (time_waited.tv_usec >= 1000000) { - time_waited.tv_sec++; - time_waited.tv_usec -= 1000000; - } - if ((time_waited.tv_sec < timeout.tv_sec) || - ((time_waited.tv_sec == timeout.tv_sec) && - (time_waited.tv_usec < timeout.tv_usec))) - goto send_again; + timeradd(&time_waited, &cu->cu_wait, &tmp1); + time_waited = tmp1; + if (timercmp(&time_waited, &timeout, <)) + goto send_again; + if (fds != &readfds) + free(fds); return (cu->cu_error.re_status = RPC_TIMEDOUT); - - /* - * buggy in other cases because time_waited is not being - * updated. - */ case -1: - if (errno == EINTR) - continue; + if (errno == EINTR) { + gettimeofday(&after, NULL); + timersub(&after, &start, &tmp1); + timeradd(&time_waited, &tmp1, &tmp2); + time_waited = tmp2; + if (timercmp(&time_waited, &timeout, <)) + continue; + if (fds != &readfds) + free(fds); + return (cu->cu_error.re_status = RPC_TIMEDOUT); + } cu->cu_error.re_errno = errno; + if (fds != &readfds) + free(fds); return (cu->cu_error.re_status = RPC_CANTRECV); } + do { fromlen = sizeof(struct sockaddr); inlen = recvfrom(cu->cu_sock, cu->cu_inbuf, - (int) cu->cu_recvsz, 0, - (struct sockaddr *)&from, &fromlen); + (int) cu->cu_recvsz, 0, + (struct sockaddr *)&from, &fromlen); } while (inlen < 0 && errno == EINTR); if (inlen < 0) { if (errno == EWOULDBLOCK) - continue; + continue; cu->cu_error.re_errno = errno; + if (fds != &readfds) + free(fds); return (cu->cu_error.re_status = RPC_CANTRECV); } if (inlen < sizeof(u_int32_t)) @@ -339,7 +357,7 @@ send_again: _seterr_reply(&reply_msg, &(cu->cu_error)); if (cu->cu_error.re_status == RPC_SUCCESS) { if (! AUTH_VALIDATE(cl->cl_auth, - &reply_msg.acpted_rply.ar_verf)) { + &reply_msg.acpted_rply.ar_verf)) { cu->cu_error.re_status = RPC_AUTHERROR; cu->cu_error.re_why = AUTH_INVALIDRESP; } @@ -348,18 +366,18 @@ send_again: (void)xdr_opaque_auth(xdrs, &(reply_msg.acpted_rply.ar_verf)); } - } /* end successful completion */ - else { + } else { /* maybe our credentials need to be refreshed ... */ if (nrefreshes > 0 && AUTH_REFRESH(cl->cl_auth)) { nrefreshes--; goto call_again; } - } /* end of unsuccessful completion */ - } /* end of valid reply message */ - else { + } + } else cu->cu_error.re_status = RPC_CANTDECODERES; - } + + if (fds != &readfds) + free(fds); return (cu->cu_error.re_status); } diff --git a/lib/libc/rpc/pmap_rmt.c b/lib/libc/rpc/pmap_rmt.c index 1ed82e39b84..a4e9b0b57aa 100644 --- a/lib/libc/rpc/pmap_rmt.c +++ b/lib/libc/rpc/pmap_rmt.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pmap_rmt.c,v 1.5 1996/08/10 05:12:09 deraadt Exp $ */ +/* $OpenBSD: pmap_rmt.c,v 1.6 1996/08/15 07:27:49 deraadt Exp $ */ /* $NetBSD: pmap_rmt.c,v 1.6 1995/06/03 22:37:25 mycroft Exp $ */ /* @@ -33,7 +33,7 @@ #if defined(LIBC_SCCS) && !defined(lint) /*static char *sccsid = "from: @(#)pmap_rmt.c 1.21 87/08/27 Copyr 1984 Sun Micro";*/ /*static char *sccsid = "from: @(#)pmap_rmt.c 2.2 88/08/01 4.0 RPCSRC";*/ -static char *rcsid = "$OpenBSD: pmap_rmt.c,v 1.5 1996/08/10 05:12:09 deraadt Exp $"; +static char *rcsid = "$OpenBSD: pmap_rmt.c,v 1.6 1996/08/15 07:27:49 deraadt Exp $"; #endif /* @@ -186,7 +186,7 @@ getbroadcastnets(addrs, sock, buf) #define size(p) max((p).sa_len, sizeof(p)) cplim = buf + ifc.ifc_len; /*skip over if's with big ifr_addr's */ for (cp = buf; cp < cplim; - cp += sizeof (ifr->ifr_name) + size(ifr->ifr_addr)) { + cp += sizeof (ifr->ifr_name) + size(ifr->ifr_addr)) { ifr = (struct ifreq *)cp; if (ifr->ifr_addr.sa_family != AF_INET) continue; @@ -198,7 +198,6 @@ getbroadcastnets(addrs, sock, buf) if ((ifreq.ifr_flags & IFF_BROADCAST) && (ifreq.ifr_flags & IFF_UP)) { sin = (struct sockaddr_in *)&ifr->ifr_addr; -#ifdef SIOCGIFBRDADDR /* 4.3BSD */ if (ioctl(sock, SIOCGIFBRDADDR, (char *)&ifreq) < 0) { addrs[i++] = inet_makeaddr(inet_netof(sin->sin_addr), @@ -207,10 +206,6 @@ getbroadcastnets(addrs, sock, buf) addrs[i++] = ((struct sockaddr_in*) &ifreq.ifr_addr)->sin_addr; } -#else /* 4.2 BSD */ - addrs[i++] = inet_makeaddr(inet_netof(sin->sin_addr), - INADDR_ANY); -#endif } } return (i); @@ -236,8 +231,7 @@ clnt_broadcast(prog, vers, proc, xargs, argsp, xresults, resultsp, eachresult) int outlen, inlen, fromlen, nets; register int sock; int on = 1; - fd_set mask; - fd_set readfds; + fd_set *fds, readfds; register int i; bool_t done = FALSE; register u_long xid; @@ -266,8 +260,19 @@ clnt_broadcast(prog, vers, proc, xargs, argsp, xresults, resultsp, eachresult) goto done_broad; } #endif /* def SO_BROADCAST */ - FD_ZERO(&mask); - FD_SET(sock, &mask); + + if (sock+1 > FD_SETSIZE) { + fds = (fd_set *)malloc(howmany(sock+1, NBBY)); + if (fds == NULL) { + stat = RPC_CANTSEND; + goto done_broad; + } + memset(fds, '\0', howmany(sock+1, NBBY)); + } else { + fds = &readfds; + FD_ZERO(fds); + } + nets = getbroadcastnets(addrs, sock, inbuf); memset(&baddr, 0, sizeof (baddr)); baddr.sin_len = sizeof(struct sockaddr_in); @@ -303,6 +308,12 @@ clnt_broadcast(prog, vers, proc, xargs, argsp, xresults, resultsp, eachresult) /* * Basic loop: broadcast a packet and wait a while for response(s). * The response timeout grows larger per iteration. + * + * XXX This will loop about 5 times the stop. If there are + * lots of signals being received by the process it will quit + * send them all in one quick burst, not paying attention to + * the intended function of sending them slowly over half a + * minute or so */ for (t.tv_sec = 4; t.tv_sec <= 14; t.tv_sec += 2) { for (i = 0; i < nets; i++) { @@ -323,21 +334,20 @@ clnt_broadcast(prog, vers, proc, xargs, argsp, xresults, resultsp, eachresult) msg.acpted_rply.ar_verf = _null_auth; msg.acpted_rply.ar_results.where = (caddr_t)&r; msg.acpted_rply.ar_results.proc = xdr_rmtcallres; - readfds = mask; - switch (select(sock+1, &readfds, NULL, NULL, &t)) { + /* XXX we know the other bits are still clear */ + FD_SET(sock, fds); + switch (select(sock+1, fds, NULL, NULL, &t)) { case 0: /* timed out */ stat = RPC_TIMEDOUT; continue; - case -1: /* some kind of error */ if (errno == EINTR) goto recv_again; perror("Broadcast select problem"); stat = RPC_CANTRECV; goto done_broad; - - } /* end of select results switch */ + } try_again: fromlen = sizeof(struct sockaddr); inlen = recvfrom(sock, inbuf, UDPMSGSIZE, 0, @@ -378,7 +388,10 @@ clnt_broadcast(prog, vers, proc, xargs, argsp, xresults, resultsp, eachresult) } } done_broad: - (void)close(sock); + if (fds != &readfds) + free(fds); + if (sock >= 0) + (void)close(sock); AUTH_DESTROY(unix_auth); return (stat); } diff --git a/lib/libc/rpc/svc.c b/lib/libc/rpc/svc.c index 86897f4e550..a9c1775476d 100644 --- a/lib/libc/rpc/svc.c +++ b/lib/libc/rpc/svc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: svc.c,v 1.4 1996/07/20 06:12:40 deraadt Exp $ */ +/* $OpenBSD: svc.c,v 1.5 1996/08/15 07:27:49 deraadt Exp $ */ /* $NetBSD: svc.c,v 1.9 1996/05/17 00:32:22 jtc Exp $ */ /* @@ -33,7 +33,7 @@ #if defined(LIBC_SCCS) && !defined(lint) /*static char *sccsid = "from: @(#)svc.c 1.44 88/02/08 Copyr 1984 Sun Micro";*/ /*static char *sccsid = "from: @(#)svc.c 2.4 88/08/11 4.0 RPCSRC";*/ -static char *rcsid = "$OpenBSD: svc.c,v 1.4 1996/07/20 06:12:40 deraadt Exp $"; +static char *rcsid = "$OpenBSD: svc.c,v 1.5 1996/08/15 07:27:49 deraadt Exp $"; #endif /* @@ -75,6 +75,9 @@ static struct svc_callout { static struct svc_callout *svc_find(); +int __svc_fdsetsize; +fd_set *__svc_fdset; + /* *************** SVCXPRT related stuff **************** */ /* @@ -87,15 +90,30 @@ xprt_register(xprt) register int sock = xprt->xp_sock; if (xports == NULL) { - xports = (SVCXPRT **) - mem_alloc(FD_SETSIZE * sizeof(SVCXPRT *)); - memset(xports, 0, FD_SETSIZE * sizeof(SVCXPRT *)); + xports = (SVCXPRT **)mem_alloc(FD_SETSIZE * + sizeof(SVCXPRT *)); + memset(xports, '\0', FD_SETSIZE * sizeof(SVCXPRT *)); } - if (sock < FD_SETSIZE) { - xports[sock] = xprt; - FD_SET(sock, &svc_fdset); - svc_maxfd = max(svc_maxfd, sock); + + if (sock+1 > __svc_fdsetsize) { + fd_set *fds; + + fds = (fd_set *)malloc(howmany(sock+1, NBBY)); + memset(fds, '\0', howmany(sock+1, NBBY)); + if (__svc_fdset) { + memcpy(fds, __svc_fdset, + howmany(__svc_fdsetsize, NBBY)); + free(__svc_fdset); + } + __svc_fdset = fds; + __svc_fdsetsize = sock+1; } + + if (sock < FD_SETSIZE) + FD_SET(sock, &svc_fdset); + FD_SET(sock, __svc_fdset); + xports[sock] = xprt; + svc_maxfd = max(svc_maxfd, sock); } /* @@ -107,14 +125,20 @@ xprt_unregister(xprt) { register int sock = xprt->xp_sock; - if ((sock < FD_SETSIZE) && (xports[sock] == xprt)) { + if (xports[sock] == xprt) { xports[sock] = (SVCXPRT *)0; - FD_CLR(sock, &svc_fdset); + if (sock < FD_SETSIZE) + FD_CLR(sock, &svc_fdset); + FD_CLR(sock, __svc_fdset); if (sock == svc_maxfd) { for (svc_maxfd--; svc_maxfd>=0; svc_maxfd--) if (xports[svc_maxfd]) break; } + /* + * XXX could use svc_maxfd as a hint to + * decrease the size of __svc_fdset + */ } } @@ -369,10 +393,20 @@ svc_getreq(rdfds) svc_getreqset(&readfds); } +void svc_getreqset2 __P((fd_set *, int)); + void svc_getreqset(readfds) fd_set *readfds; { + svc_getreqset2(readfds, FD_SETSIZE); +} + +void +svc_getreqset2(readfds, width) + fd_set *readfds; + int width; +{ enum xprt_stat stat; struct rpc_msg msg; int prog_found; @@ -388,9 +422,8 @@ svc_getreqset(readfds) msg.rm_call.cb_verf.oa_base = &(cred_area[MAX_AUTH_BYTES]); r.rq_clntcred = &(cred_area[2*MAX_AUTH_BYTES]); - maskp = readfds->fds_bits; - for (sock = 0; sock < FD_SETSIZE; sock += NFDBITS) { + for (sock = 0; sock < width; sock += NFDBITS) { for (mask = *maskp++; bit = ffs(mask); mask ^= (1 << (bit - 1))) { /* sock has input waiting */ xprt = xports[sock + bit - 1]; diff --git a/lib/libc/rpc/svc_run.c b/lib/libc/rpc/svc_run.c index 68edcaf2188..27b4c0e02fd 100644 --- a/lib/libc/rpc/svc_run.c +++ b/lib/libc/rpc/svc_run.c @@ -1,4 +1,4 @@ -/* $OpenBSD: svc_run.c,v 1.3 1996/07/20 06:12:43 deraadt Exp $ */ +/* $OpenBSD: svc_run.c,v 1.4 1996/08/15 07:27:50 deraadt Exp $ */ /* $NetBSD: svc_run.c,v 1.6 1995/02/25 03:02:00 cgd Exp $ */ /* @@ -33,7 +33,7 @@ #if defined(LIBC_SCCS) && !defined(lint) /*static char *sccsid = "from: @(#)svc_run.c 1.1 87/10/13 Copyr 1984 Sun Micro";*/ /*static char *sccsid = "from: @(#)svc_run.c 2.1 88/07/29 4.0 RPCSRC";*/ -static char *rcsid = "$OpenBSD: svc_run.c,v 1.3 1996/07/20 06:12:43 deraadt Exp $"; +static char *rcsid = "$OpenBSD: svc_run.c,v 1.4 1996/08/15 07:27:50 deraadt Exp $"; #endif /* @@ -44,25 +44,32 @@ static char *rcsid = "$OpenBSD: svc_run.c,v 1.3 1996/07/20 06:12:43 deraadt Exp #include <sys/errno.h> #include <unistd.h> +extern int __svc_fdsetsize; +extern fd_set *__svc_fdset; + void svc_run() { - fd_set readfds; + fd_set *fds; for (;;) { - readfds = svc_fdset; - switch (select(svc_maxfd+1, &readfds, 0, 0, - (struct timeval *)0)) { + fds = (fd_set *)malloc(howmany(__svc_fdsetsize, NBBY)); + memcpy(fds, __svc_fdset, howmany(__svc_fdsetsize, NBBY)); + switch (select(svc_maxfd+1, fds, 0, 0, (struct timeval *)0)) { case -1: if (errno == EINTR) { + free(fds); continue; } perror("svc_run: - select failed"); + free(fds); return; case 0: + free(fds); continue; default: - svc_getreqset(&readfds); + svc_getreqset2(fds, svc_maxfd+1); + free(fds); } } } diff --git a/lib/libc/rpc/svc_tcp.c b/lib/libc/rpc/svc_tcp.c index c03659b4520..cb35f3330d5 100644 --- a/lib/libc/rpc/svc_tcp.c +++ b/lib/libc/rpc/svc_tcp.c @@ -1,4 +1,4 @@ -/* $OpenBSD: svc_tcp.c,v 1.4 1996/08/05 00:34:28 deraadt Exp $ */ +/* $OpenBSD: svc_tcp.c,v 1.5 1996/08/15 07:27:50 deraadt Exp $ */ /* $NetBSD: svc_tcp.c,v 1.6 1995/06/03 22:37:27 mycroft Exp $ */ /* @@ -33,7 +33,7 @@ #if defined(LIBC_SCCS) && !defined(lint) /*static char *sccsid = "from: @(#)svc_tcp.c 1.21 87/08/11 Copyr 1984 Sun Micro";*/ /*static char *sccsid = "from: @(#)svc_tcp.c 2.2 88/08/01 4.0 RPCSRC";*/ -static char *rcsid = "$OpenBSD: svc_tcp.c,v 1.4 1996/08/05 00:34:28 deraadt Exp $"; +static char *rcsid = "$OpenBSD: svc_tcp.c,v 1.5 1996/08/15 07:27:50 deraadt Exp $"; #endif /* @@ -307,26 +307,49 @@ readtcp(xprt, buf, len) register int len; { register int sock = xprt->xp_sock; - fd_set mask; - fd_set readfds; + struct timeval start, delta; + struct timeval tmp1, tmp2; + fd_set *fds, readfds; - FD_ZERO(&mask); - FD_SET(sock, &mask); + if (sock+1 > FD_SETSIZE) { + fds = (fd_set *)malloc(howmany(sock+1, NBBY)); + if (fds == NULL) + goto fatal_err; + memset(fds, '\0', howmany(sock+1, NBBY)); + } else { + fds = &readfds; + FD_ZERO(fds); + } + + delta = wait_per_try; + gettimeofday(&start, NULL); do { - readfds = mask; - if (select(sock+1, &readfds, NULL, NULL, - &wait_per_try) <= 0) { - if (errno == EINTR) { - continue; - } + /* XXX we know the other bits are still clear */ + FD_SET(sock, fds); + switch (select(sock+1, fds, NULL, NULL, &delta)) { + case -1: + if (errno != EINTR) + goto fatal_err; + gettimeofday(&tmp1, NULL); + timersub(&tmp1, &start, &tmp2); + timersub(&delta, &tmp2, &tmp1); + if (tmp1.tv_sec < 0 || !timerisset(&tmp1)) + goto fatal_err; + delta = tmp1; + continue; + case 0: goto fatal_err; } - } while (!FD_ISSET(sock, &readfds)); + } while (!FD_ISSET(sock, fds)); if ((len = read(sock, buf, len)) > 0) { + if (fds != &readfds) + free(fds); return (len); } fatal_err: ((struct tcp_conn *)(xprt->xp_p1))->strm_stat = XPRT_DIED; + if (fds != &readfds) + free(fds); return (-1); } |