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
SRecvmsg(int sfd,void * const msg,int fl,int tlen)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
SRecvmsg(int sfd,void * const msg,int fl,int tlen)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