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