1 /* this file is intentionally ugly */
2 #ifndef __sio_h
3 #define __sio_h
4 
5 #include "config.h"
6 
7 /* synchronized I/O */
8 #ifdef HAVE_POLL
9 #include <sys/types.h>
10 #include <sys/poll.h>
11 #else
12 #include <sys/time.h>
13 #include <sys/types.h>
14 #include <unistd.h>
15 #endif
16 
17 #include "bin.h"
18 
19 #define sio_read	1
20 #define sio_write	2
21 #define sio_infinite	-1
22 #define sio_infinity sio_infinite
23 
sio_test(bin_t b,int fd)24 int inline sio_test(bin_t b, int fd)
25 {
26 	register int op;
27 #ifdef HAVE_POLL
28 	struct pollfd *pf;
29 	register int i;
30 	int pfnum;
31 
32 	pf = (struct pollfd *)caddr(b);
33 	if (!pf)
34 		return 0;
35 
36 	pfnum = (bin_len(b)) / sizeof(struct pollfd);
37 	for (i = 0; i < pfnum; i++) {
38 		if (pf[i].fd == fd) {
39 			op = 0;
40 			if (pf[i].revents & (POLLIN|POLLPRI|POLLHUP))
41 				op |= sio_read;
42 			if (pf[i].revents & POLLOUT)
43 				op |= sio_write;
44 			return op;
45 		}
46 	}
47 	return 0;
48 #else
49 	fd_set *r, *w;
50 
51 	if (caddr(b) == 0)
52 		return 0;
53 
54 	bin_need(b, sizeof(fd_set) * 2);
55 	r = (fd_set *)(caddr(b));
56 	w = (fd_set *)(((char *)caddr(b)) + sizeof(fd_set));
57 
58 	op = 0;
59 	if (FD_ISSET(fd, r))
60 		op |= sio_read;
61 	if (FD_ISSET(fd, w))
62 		op |= sio_write;
63 
64 	return op;
65 #endif
66 }
67 
sio_block(bin_t b,int timeout)68 int inline sio_block(bin_t b, int timeout)
69 {
70 #ifdef HAVE_POLL
71 	struct pollfd *pf;
72 	int pfnum;
73 
74 	pf = (struct pollfd *)caddr(b);
75 	if (!pf)
76 		return 0;
77 
78 	pfnum = (bin_len(b)) / sizeof(struct pollfd);
79 
80 	return poll(pf, pfnum, timeout);
81 #else
82 	fd_set *r, *w;
83 	struct timeval tv;
84 	int high;
85 
86 	if (caddr(b) == 0)
87 		return 0;
88 
89 	bin_need(b, sizeof(fd_set) * 2);
90 	r = (fd_set *)(caddr(b));
91 	w = (fd_set *)(((char *)caddr(b)) + sizeof(fd_set));
92 	high = *(int *)(((char *)caddr(b)) + (sizeof(fd_set)+sizeof(fd_set)));
93 
94 	if (timeout < 0) {
95 		return select(high+1, r, w, 0, 0);
96 	} else {
97 		tv.tv_sec = 0;
98 		tv.tv_usec = timeout;
99 		return select(high+1, r, w, 0, &tv);
100 	}
101 #endif
102 }
sio_remove(bin_t b,int fd)103 void inline sio_remove(bin_t b, int fd)
104 {
105 #ifdef HAVE_POLL
106 	struct pollfd *pf;
107 	register int i;
108 	int pfnum;
109 
110 	pf = (struct pollfd *)caddr(b);
111 	if (pf) {
112 		pfnum = (bin_len(b)) / sizeof(struct pollfd);
113 
114 		for (i = 0; i < pfnum; i++) {
115 			if (fd == -1 || pf[i].fd == fd) {
116 				pf[i].fd = -1;
117 				pf[i].events = 0;
118 				pf[i].revents = 0;
119 				if (fd != -1)
120 					break;
121 			}
122 		}
123 	}
124 #else
125 	fd_set *r, *w;
126 	register int i;
127 	int *high;
128 
129 	i = (caddr(b) == 0) ? 1 : 0;
130 	bin_need(b, (sizeof(fd_set) * 2) + sizeof(int));
131 	r = (fd_set *)(caddr(b));
132 	w = (fd_set *)(((char *)caddr(b)) + sizeof(fd_set));
133 	high = (int *)(((char *)caddr(b)) + (sizeof(fd_set)+sizeof(fd_set)));
134 
135 	if (i || fd == -1) {
136 		FD_ZERO(r); FD_ZERO(w);
137 		*high = 0;
138 	} else {
139 		FD_CLR(fd, r);
140 		FD_CLR(fd, w);
141 	}
142 #endif
143 }
sio_flush(bin_t b)144 void inline sio_flush(bin_t b)
145 {
146 	sio_remove(b, -1);
147 }
sio_add(bin_t b,int fd,int ops)148 void inline sio_add(bin_t b, int fd, int ops)
149 {
150 #ifdef HAVE_POLL
151 	struct pollfd *pf;
152 	register int i;
153 	int pfnum;
154 
155 	if (fd == -1)
156 		return;
157 
158 	/* search for a -1 */
159 	pf = (struct pollfd *)caddr(b);
160 	if (!pf) {
161 		i = pfnum = 0;
162 	} else {
163 		pfnum = (bin_len(b)) / sizeof(struct pollfd);
164 
165 		for (i = 0; i < pfnum; i++) {
166 			if (pf[i].fd == -1)
167 				break;
168 		}
169 	}
170 	if (i == pfnum) {
171 		bin_needplus(b, sizeof(struct pollfd));
172 		clen(b) = bin_len(b); /* update length */
173 		pf = (struct pollfd *)caddr(b);
174 	}
175 	pf[i].fd = fd;
176 	pf[i].events = 0;
177 	pf[i].revents = 0;
178 	if (ops & sio_read)
179 		pf[i].events |= (POLLIN|POLLPRI);
180 	if (ops & sio_write)
181 		pf[i].events |= POLLOUT;
182 #else
183 	fd_set *r, *w;
184 	register int i;
185 	int *high;
186 
187 	if (fd == -1)
188 		return;
189 
190 	i = (caddr(b) == 0) ? 1 : 0;
191 	bin_need(b, (sizeof(fd_set) * 2) + sizeof(int));
192 	r = (fd_set *)(caddr(b));
193 	w = (fd_set *)(((char *)caddr(b)) + sizeof(fd_set));
194 	high = (int *)(((char *)caddr(b)) + (sizeof(fd_set)+sizeof(fd_set)));
195 
196 	if (i) {
197 		FD_ZERO(r); FD_ZERO(w);
198 		*high = fd;
199 	} else if (fd > *high)
200 		*high = fd;
201 
202 	if (ops & sio_read)
203 		FD_SET(fd, r);
204 	if (ops & sio_write)
205 		FD_SET(fd, w);
206 #endif
207 }
208 
209 #endif
210