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
SRecvfrom(int sfd,char * const buf,size_t size,int fl,struct sockaddr_in * const fromAddr,int tlen)11 SRecvfrom(int sfd, char *const buf, size_t size, int fl, struct sockaddr_in *const fromAddr, int tlen)
12 {
13 	int nread, tleft;
14 	vsio_sigproc_t sigalrm, sigpipe;
15 	time_t done, now;
16 	int alen;
17 
18 	if (SSetjmp(gNetTimeoutJmp) != 0) {
19 		alarm(0);
20 		(void) SSignal(SIGALRM, (sio_sigproc_t) sigalrm);
21 		(void) SSignal(SIGPIPE, (sio_sigproc_t) sigpipe);
22 		errno = ETIMEDOUT;
23 		return (kTimeoutErr);
24 	}
25 
26 	if (SSetjmp(gPipeJmp) != 0) {
27 		alarm(0);
28 		(void) SSignal(SIGALRM, (sio_sigproc_t) sigalrm);
29 		(void) SSignal(SIGPIPE, (sio_sigproc_t) sigpipe);
30 		errno = EPIPE;
31 		return (kBrokenPipeErr);
32 	}
33 
34 	sigalrm = (vsio_sigproc_t) SSignal(SIGALRM, SIOHandler);
35 	sigpipe = (vsio_sigproc_t) SSignal(SIGPIPE, SIOHandler);
36 
37 	time(&now);
38 	done = now + tlen;
39 	tleft = (int) (done - now);
40 	forever {
41 		alen = sizeof(struct sockaddr_in);
42 		(void) alarm((unsigned int) tleft);
43 		nread = recvfrom(sfd, buf, size, fl,
44 			(struct sockaddr *) fromAddr, &alen);
45 		(void) alarm(0);
46 		if (nread >= 0)
47 			break;
48 		if (errno != EINTR)
49 			break;		/* Fatal error. */
50 		errno = 0;
51 		time(&now);
52 		tleft = (int) (done - now);
53 		if (tleft < 1) {
54 			nread = kTimeoutErr;
55 			errno = ETIMEDOUT;
56 			break;
57 		}
58 	}
59 
60 	(void) SSignal(SIGALRM, (sio_sigproc_t) sigalrm);
61 	(void) SSignal(SIGPIPE, (sio_sigproc_t) sigpipe);
62 
63 	return (nread);
64 }	/* SRecvfrom */
65 
66 #else
67 
68 int
SRecvfrom(int sfd,char * const buf,size_t size,int fl,struct sockaddr_in * const fromAddr,int tlen)69 SRecvfrom(int sfd, char *const buf, size_t size, int fl, struct sockaddr_in *const fromAddr, int tlen)
70 {
71 	int nread, tleft;
72 	fd_set ss;
73 	struct timeval tv;
74 	int result;
75 	time_t done, now;
76 	int alen;
77 
78 	time(&now);
79 	done = now + tlen;
80 	tleft = (int) (done - now);
81 	nread = 0;
82 	forever {
83 		alen = sizeof(struct sockaddr_in);
84 
85 		forever {
86 			errno = 0;
87 			FD_ZERO(&ss);
88 			FD_SET(sfd, &ss);
89 			tv.tv_sec = tleft;
90 			tv.tv_usec = 0;
91 			result = select(sfd + 1, SELECT_TYPE_ARG234 &ss, NULL, NULL, SELECT_TYPE_ARG5 &tv);
92 			if (result == 1) {
93 				/* ready */
94 				break;
95 			} else if (result == 0) {
96 				/* timeout */
97 				errno = ETIMEDOUT;
98 				SETWSATIMEOUTERR
99 				return (kTimeoutErr);
100 			} else if (errno != EINTR) {
101 				return (-1);
102 			}
103 		}
104 
105 		nread = recvfrom(sfd, buf, size, fl,
106 			(struct sockaddr *) fromAddr, &alen);
107 
108 		if (nread >= 0)
109 			break;
110 		if (errno != EINTR)
111 			break;		/* Fatal error. */
112 		errno = 0;
113 		time(&now);
114 		tleft = (int) (done - now);
115 		if (tleft < 1) {
116 			nread = kTimeoutErr;
117 			errno = ETIMEDOUT;
118 			SETWSATIMEOUTERR
119 			break;
120 		}
121 	}
122 
123 	return (nread);
124 }	/* SRecvfrom */
125 
126 #endif
127 
128