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
SSend(int sfd,char * buf0,size_t size,int fl,int tlen)11 SSend(int sfd, char *buf0, size_t size, int fl, int tlen)
12 {
13 	volatile int nleft;
14 	char *volatile buf = buf0;
15 	int nwrote, tleft;
16 	vsio_sigproc_t sigalrm, sigpipe;
17 	time_t done, now;
18 
19 	if (SSetjmp(gNetTimeoutJmp) != 0) {
20 		alarm(0);
21 		(void) SSignal(SIGALRM, (sio_sigproc_t) sigalrm);
22 		(void) SSignal(SIGPIPE, (sio_sigproc_t) sigpipe);
23 		nwrote = size - nleft;
24 		if (nwrote > 0)
25 			return (nwrote);
26 		errno = ETIMEDOUT;
27 		return (kTimeoutErr);
28 	}
29 
30 	if (SSetjmp(gPipeJmp) != 0) {
31 		alarm(0);
32 		(void) SSignal(SIGALRM, (sio_sigproc_t) sigalrm);
33 		(void) SSignal(SIGPIPE, (sio_sigproc_t) sigpipe);
34 		nwrote = size - nleft;
35 		if (nwrote > 0)
36 			return (nwrote);
37 		errno = EPIPE;
38 		return (kBrokenPipeErr);
39 	}
40 
41 	sigalrm = (vsio_sigproc_t) SSignal(SIGALRM, SIOHandler);
42 	sigpipe = (vsio_sigproc_t) SSignal(SIGPIPE, SIOHandler);
43 
44 	nleft = (int) size;
45 	time(&now);
46 	done = now + tlen;
47 	forever {
48 		tleft = (int) (done - now);
49 		if (tleft < 1) {
50 			nwrote = size - nleft;
51 			if (nwrote == 0) {
52 				nwrote = kTimeoutErr;
53 				errno = ETIMEDOUT;
54 			}
55 			goto done;
56 		}
57 		(void) alarm((unsigned int) tleft);
58 		nwrote = send(sfd, buf, size, fl);
59 		(void) alarm(0);
60 		if (nwrote < 0) {
61 			if (errno != EINTR) {
62 				nwrote = size - nleft;
63 				if (nwrote == 0)
64 					nwrote = -1;
65 				goto done;
66 			} else {
67 				errno = 0;
68 				nwrote = 0;
69 				/* Try again. */
70 			}
71 		}
72 		nleft -= nwrote;
73 		if (nleft <= 0)
74 			break;
75 		buf += nwrote;
76 		time(&now);
77 	}
78 	nwrote = size - nleft;
79 
80 done:
81 	(void) SSignal(SIGALRM, (sio_sigproc_t) sigalrm);
82 	(void) SSignal(SIGPIPE, (sio_sigproc_t) sigpipe);
83 
84 	return (nwrote);
85 }	/* SSend */
86 
87 #else
88 
89 int
SSend(int sfd,char * buf0,size_t size,int fl,int tlen)90 SSend(int sfd, char *buf0, size_t size, int fl, int tlen)
91 {
92 	int nleft;
93 	char *buf = buf0;
94 	int nwrote, tleft;
95 	time_t done, now;
96 	fd_set ss;
97 	struct timeval tv;
98 	int result;
99 
100 	nleft = (int) size;
101 	time(&now);
102 	done = now + tlen;
103 	forever {
104 		tleft = (int) (done - now);
105 		if (tleft < 1) {
106 			nwrote = size - nleft;
107 			if (nwrote == 0) {
108 				nwrote = kTimeoutErr;
109 				errno = ETIMEDOUT;
110 				SETWSATIMEOUTERR
111 			}
112 			goto done;
113 		}
114 
115 
116 		/* Unfortunately this doesn't help when the
117 		 * send buffer fills during the time we're
118 		 * writing to it, so you could still be
119 		 * blocked after breaking this loop and starting
120 		 * the write.
121 		 */
122 
123 		forever {
124 			errno = 0;
125 			FD_ZERO(&ss);
126 			FD_SET(sfd, &ss);
127 			tv.tv_sec = tlen;
128 			tv.tv_usec = 0;
129 			result = select(sfd + 1, NULL, SELECT_TYPE_ARG234 &ss, NULL, SELECT_TYPE_ARG5 &tv);
130 			if (result == 1) {
131 				/* ready */
132 				break;
133 			} else if (result == 0) {
134 				/* timeout */
135 				nwrote = size - nleft;
136 				if (nwrote > 0)
137 					return (nwrote);
138 				errno = ETIMEDOUT;
139 				SETWSATIMEOUTERR
140 				return (kTimeoutErr);
141 			} else if (errno != EINTR) {
142 				return (-1);
143 			}
144 		}
145 
146 		nwrote = send(sfd, buf, size, fl);
147 
148 		if (nwrote < 0) {
149 			if (errno != EINTR) {
150 				nwrote = size - nleft;
151 				if (nwrote == 0)
152 					nwrote = -1;
153 				goto done;
154 			} else {
155 				errno = 0;
156 				nwrote = 0;
157 				/* Try again. */
158 			}
159 		}
160 		nleft -= nwrote;
161 		if (nleft <= 0)
162 			break;
163 		buf += nwrote;
164 		time(&now);
165 	}
166 	nwrote = size - nleft;
167 
168 done:
169 	return (nwrote);
170 }	/* SSend */
171 
172 #endif
173