1*c2c66affSColin Finck #include "syshdrs.h"
2*c2c66affSColin Finck 
3*c2c66affSColin Finck #ifndef NO_SIGNALS
4*c2c66affSColin Finck extern volatile Sjmp_buf gNetTimeoutJmp;
5*c2c66affSColin Finck extern volatile Sjmp_buf gPipeJmp;
6*c2c66affSColin Finck #endif
7*c2c66affSColin Finck 
8*c2c66affSColin Finck #ifndef NO_SIGNALS
9*c2c66affSColin Finck 
10*c2c66affSColin Finck int
SRecvmsg(int sfd,void * const msg,int fl,int tlen)11*c2c66affSColin Finck SRecvmsg(int sfd, void *const msg, int fl, int tlen)
12*c2c66affSColin Finck {
13*c2c66affSColin Finck 	int nread, tleft;
14*c2c66affSColin Finck 	vsio_sigproc_t sigalrm, sigpipe;
15*c2c66affSColin Finck 	time_t done, now;
16*c2c66affSColin Finck 
17*c2c66affSColin Finck 	if (tlen < 0) {
18*c2c66affSColin Finck 		errno = 0;
19*c2c66affSColin Finck 		for (;;) {
20*c2c66affSColin Finck 			nread = recvmsg(sfd, (struct msghdr *) msg, fl);
21*c2c66affSColin Finck 			if ((nread >= 0) || (errno != EINTR))
22*c2c66affSColin Finck 				return (nread);
23*c2c66affSColin Finck 		}
24*c2c66affSColin Finck 	}
25*c2c66affSColin Finck 
26*c2c66affSColin Finck 	if (SSetjmp(gNetTimeoutJmp) != 0) {
27*c2c66affSColin Finck 		alarm(0);
28*c2c66affSColin Finck 		(void) SSignal(SIGALRM, (sio_sigproc_t) sigalrm);
29*c2c66affSColin Finck 		(void) SSignal(SIGPIPE, (sio_sigproc_t) sigpipe);
30*c2c66affSColin Finck 		errno = ETIMEDOUT;
31*c2c66affSColin Finck 		return (kTimeoutErr);
32*c2c66affSColin Finck 	}
33*c2c66affSColin Finck 
34*c2c66affSColin Finck 	if (SSetjmp(gPipeJmp) != 0) {
35*c2c66affSColin Finck 		alarm(0);
36*c2c66affSColin Finck 		(void) SSignal(SIGALRM, (sio_sigproc_t) sigalrm);
37*c2c66affSColin Finck 		(void) SSignal(SIGPIPE, (sio_sigproc_t) sigpipe);
38*c2c66affSColin Finck 		errno = EPIPE;
39*c2c66affSColin Finck 		return (kBrokenPipeErr);
40*c2c66affSColin Finck 	}
41*c2c66affSColin Finck 
42*c2c66affSColin Finck 	sigalrm = (vsio_sigproc_t) SSignal(SIGALRM, SIOHandler);
43*c2c66affSColin Finck 	sigpipe = (vsio_sigproc_t) SSignal(SIGPIPE, SIOHandler);
44*c2c66affSColin Finck 
45*c2c66affSColin Finck 	time(&now);
46*c2c66affSColin Finck 	done = now + tlen;
47*c2c66affSColin Finck 	tleft = (int) (done - now);
48*c2c66affSColin Finck 	forever {
49*c2c66affSColin Finck 		(void) alarm((unsigned int) tleft);
50*c2c66affSColin Finck 		nread = recvmsg(sfd, (struct msghdr *) msg, fl);
51*c2c66affSColin Finck 		(void) alarm(0);
52*c2c66affSColin Finck 		if (nread >= 0)
53*c2c66affSColin Finck 			break;
54*c2c66affSColin Finck 		if (errno != EINTR)
55*c2c66affSColin Finck 			break;		/* Fatal error. */
56*c2c66affSColin Finck 		errno = 0;
57*c2c66affSColin Finck 		time(&now);
58*c2c66affSColin Finck 		tleft = (int) (done - now);
59*c2c66affSColin Finck 		if (tleft < 1) {
60*c2c66affSColin Finck 			nread = kTimeoutErr;
61*c2c66affSColin Finck 			errno = ETIMEDOUT;
62*c2c66affSColin Finck 			break;
63*c2c66affSColin Finck 		}
64*c2c66affSColin Finck 	}
65*c2c66affSColin Finck 
66*c2c66affSColin Finck 	(void) SSignal(SIGALRM, (sio_sigproc_t) sigalrm);
67*c2c66affSColin Finck 	(void) SSignal(SIGPIPE, (sio_sigproc_t) sigpipe);
68*c2c66affSColin Finck 
69*c2c66affSColin Finck 	return (nread);
70*c2c66affSColin Finck }	/* SRecvmsg */
71*c2c66affSColin Finck 
72*c2c66affSColin Finck #elif defined(HAVE_RECVMSG)
73*c2c66affSColin Finck 
74*c2c66affSColin Finck int
SRecvmsg(int sfd,void * const msg,int fl,int tlen)75*c2c66affSColin Finck SRecvmsg(int sfd, void *const msg, int fl, int tlen)
76*c2c66affSColin Finck {
77*c2c66affSColin Finck 	int nread, tleft;
78*c2c66affSColin Finck 	time_t done, now;
79*c2c66affSColin Finck 	fd_set ss;
80*c2c66affSColin Finck 	struct timeval tv;
81*c2c66affSColin Finck 	int result;
82*c2c66affSColin Finck 
83*c2c66affSColin Finck 	if (tlen < 0) {
84*c2c66affSColin Finck 		errno = 0;
85*c2c66affSColin Finck 		for (;;) {
86*c2c66affSColin Finck 			nread = recvmsg(sfd, (struct msghdr *) msg, fl);
87*c2c66affSColin Finck 			if ((nread >= 0) || (errno != EINTR))
88*c2c66affSColin Finck 				return (nread);
89*c2c66affSColin Finck 		}
90*c2c66affSColin Finck 	}
91*c2c66affSColin Finck 
92*c2c66affSColin Finck 	time(&now);
93*c2c66affSColin Finck 	done = now + tlen;
94*c2c66affSColin Finck 	tleft = (int) (done - now);
95*c2c66affSColin Finck 	forever {
96*c2c66affSColin Finck 
97*c2c66affSColin Finck 		for (;;) {
98*c2c66affSColin Finck 			errno = 0;
99*c2c66affSColin Finck 			FD_ZERO(&ss);
100*c2c66affSColin Finck 			FD_SET(sfd, &ss);
101*c2c66affSColin Finck 			tv.tv_sec = tleft;
102*c2c66affSColin Finck 			tv.tv_usec = 0;
103*c2c66affSColin Finck 			result = select(sfd + 1, SELECT_TYPE_ARG234 &ss, NULL, NULL, SELECT_TYPE_ARG5 &tv);
104*c2c66affSColin Finck 			if (result == 1) {
105*c2c66affSColin Finck 				/* ready */
106*c2c66affSColin Finck 				break;
107*c2c66affSColin Finck 			} else if (result == 0) {
108*c2c66affSColin Finck 				/* timeout */
109*c2c66affSColin Finck 				errno = ETIMEDOUT;
110*c2c66affSColin Finck 				SETWSATIMEOUTERR
111*c2c66affSColin Finck 				return (kTimeoutErr);
112*c2c66affSColin Finck 			} else if (errno != EINTR) {
113*c2c66affSColin Finck 				return (-1);
114*c2c66affSColin Finck 			}
115*c2c66affSColin Finck 		}
116*c2c66affSColin Finck 
117*c2c66affSColin Finck 		nread = recvmsg(sfd, (struct msghdr *) msg, fl);
118*c2c66affSColin Finck 
119*c2c66affSColin Finck 		if (nread >= 0)
120*c2c66affSColin Finck 			break;
121*c2c66affSColin Finck 		if (errno != EINTR)
122*c2c66affSColin Finck 			break;		/* Fatal error. */
123*c2c66affSColin Finck 		errno = 0;
124*c2c66affSColin Finck 		time(&now);
125*c2c66affSColin Finck 		tleft = (int) (done - now);
126*c2c66affSColin Finck 		if (tleft < 1) {
127*c2c66affSColin Finck 			nread = kTimeoutErr;
128*c2c66affSColin Finck 			errno = ETIMEDOUT;
129*c2c66affSColin Finck 			SETWSATIMEOUTERR
130*c2c66affSColin Finck 			break;
131*c2c66affSColin Finck 		}
132*c2c66affSColin Finck 	}
133*c2c66affSColin Finck 
134*c2c66affSColin Finck 	return (nread);
135*c2c66affSColin Finck }	/* SRecvmsg */
136*c2c66affSColin Finck 
137*c2c66affSColin Finck #endif
138