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 SSendtoByName(int sfd, const char *const buf, size_t size, int fl, const char *const toAddrStr, int tlen)
12 {
13 	int nwrote, tleft, result;
14 	vsio_sigproc_t sigalrm, sigpipe;
15 	time_t done, now;
16 	struct sockaddr_in toAddr;
17 
18 	if ((result = AddrStrToAddr(toAddrStr, &toAddr, -1)) < 0) {
19 		return (result);
20 	}
21 
22 	if (SSetjmp(gNetTimeoutJmp) != 0) {
23 		alarm(0);
24 		(void) SSignal(SIGALRM, (sio_sigproc_t) sigalrm);
25 		(void) SSignal(SIGPIPE, (sio_sigproc_t) sigpipe);
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 		errno = EPIPE;
35 		return (kBrokenPipeErr);
36 	}
37 
38 	sigalrm = (vsio_sigproc_t) SSignal(SIGALRM, SIOHandler);
39 	sigpipe = (vsio_sigproc_t) SSignal(SIGPIPE, SIOHandler);
40 
41 	time(&now);
42 	done = now + tlen;
43 	tleft = (int) (done - now);
44 	forever {
45 		(void) alarm((unsigned int) tleft);
46 		nwrote = sendto(sfd, buf, size, fl,
47 				(struct sockaddr *) &toAddr,
48 				(int) sizeof(struct sockaddr_in));
49 		(void) alarm(0);
50 		if (nwrote >= 0)
51 			break;
52 		if (errno != EINTR)
53 			break;		/* Fatal error. */
54 		errno = 0;
55 		time(&now);
56 		tleft = (int) (done - now);
57 		if (tleft < 1) {
58 			nwrote = kTimeoutErr;
59 			errno = ETIMEDOUT;
60 			break;
61 		}
62 	}
63 
64 	(void) SSignal(SIGALRM, (sio_sigproc_t) sigalrm);
65 	(void) SSignal(SIGPIPE, (sio_sigproc_t) sigpipe);
66 
67 	return (nwrote);
68 }	/* SSendtoByName */
69 
70 #else
71 
72 int
73 SSendtoByName(int sfd, const char *const buf, size_t size, int fl, const char *const toAddrStr, int tlen)
74 {
75 	int nwrote, tleft;
76 	time_t done, now;
77 	fd_set ss;
78 	struct timeval tv;
79 	int result;
80 	struct sockaddr_in toAddr;
81 
82 	if ((result = AddrStrToAddr(toAddrStr, &toAddr, -1)) < 0) {
83 		return (result);
84 	}
85 
86 	time(&now);
87 	done = now + tlen;
88 	nwrote = 0;
89 	forever {
90 		forever {
91 			if (now >= done) {
92 				errno = ETIMEDOUT;
93 				return (kTimeoutErr);
94 			}
95 			tleft = (int) (done - now);
96 			errno = 0;
97 			FD_ZERO(&ss);
98 			FD_SET(sfd, &ss);
99 			tv.tv_sec = tleft;
100 			tv.tv_usec = 0;
101 			result = select(sfd + 1, NULL, SELECT_TYPE_ARG234 &ss, NULL, SELECT_TYPE_ARG5 &tv);
102 			if (result == 1) {
103 				/* ready */
104 				break;
105 			} else if (result == 0) {
106 				/* timeout */
107 				errno = ETIMEDOUT;
108 				return (kTimeoutErr);
109 			} else if (errno != EINTR) {
110 				return (-1);
111 			}
112 			time(&now);
113 		}
114 
115 		nwrote = sendto(sfd, buf, size, fl,
116 			(struct sockaddr *) &toAddr,
117 			(int) sizeof(struct sockaddr_in));
118 
119 		if (nwrote >= 0)
120 			break;
121 		if (errno != EINTR)
122 			break;		/* Fatal error. */
123 	}
124 
125 	return (nwrote);
126 }	/* SSendto */
127 
128 #endif
129 
130 
131 
132 int
133 SendtoByName(int sfd, const char *const buf, size_t size, const char *const toAddrStr)
134 {
135 	int result;
136 	struct sockaddr_in toAddr;
137 
138 	if ((result = AddrStrToAddr(toAddrStr, &toAddr, -1)) < 0) {
139 		return (result);
140 	}
141 
142 	do {
143 		result = sendto(sfd, buf, size, 0,
144 				(struct sockaddr *) &toAddr,
145 				(int) sizeof(struct sockaddr_in));
146 	} while ((result < 0) && (errno == EINTR));
147 
148 	return (result);
149 }	/* SendtoByName */
150