1 |
|
|
2 |
/* Copyright (C) 1999 Beau Kuiper |
/* Copyright (C) 1999 Beau Kuiper |
3 |
|
|
4 |
This program is free software; you can redistribute it and/or modify |
This program is free software; you can redistribute it and/or modify |
19 |
|
|
20 |
/* Note that i may one day replace all this with the poll funcutions */ |
/* Note that i may one day replace all this with the poll funcutions */ |
21 |
|
|
22 |
#define MAXFDNUM 16 /* Set startup maximum file descriptor number */ |
#define MAXFDNUM 16 /* Set startup maximum file descriptor number */ |
23 |
|
|
24 |
/* Creates a new select structure */ |
/* Creates a new select structure */ |
25 |
|
|
26 |
extern int signumber; |
extern int signumber; |
28 |
SELECTER *select_new(void) |
SELECTER *select_new(void) |
29 |
{ |
{ |
30 |
SELECTER *new = mallocwrapper(sizeof(SELECTER)); |
SELECTER *new = mallocwrapper(sizeof(SELECTER)); |
31 |
|
|
32 |
debuglog("select_new - starting new select structure"); |
debuglog("select_new - starting new select structure"); |
33 |
|
|
34 |
new->fdtable = mallocwrapper(sizeof(struct selectorobj *) * (MAXFDNUM + 1)); |
new->fdtable = |
35 |
|
mallocwrapper(sizeof(struct selectorobj *) * (MAXFDNUM + 1)); |
36 |
memset(new->fdtable, 0, sizeof(struct selectorobj *) * (MAXFDNUM + 1)); |
memset(new->fdtable, 0, sizeof(struct selectorobj *) * (MAXFDNUM + 1)); |
37 |
new->maxfds = MAXFDNUM; |
new->maxfds = MAXFDNUM; |
38 |
new->firstfd = -1; |
new->firstfd = -1; |
39 |
new->smax = 0; |
new->smax = 0; |
40 |
return(new); |
return (new); |
41 |
} |
} |
42 |
|
|
43 |
/* The following adds a FD to the fdtable. If the table is too small, |
/* The following adds a FD to the fdtable. If the table is too small, |
44 |
then increase it. Favours long running times */ |
then increase it. Favours long running times */ |
45 |
|
|
46 |
void select_addfd(SELECTER *sel, int newport) |
void select_addfd(SELECTER * sel, |
47 |
|
int newport) |
48 |
{ |
{ |
49 |
debuglog("select_addfd - adding fd %d", newport); |
debuglog("select_addfd - adding fd %d", newport); |
50 |
|
|
51 |
if (newport > sel->maxfds) |
if (newport > sel->maxfds) |
52 |
{ |
{ |
53 |
int temp = newport + 32; /* give some breathing space */ |
int temp = newport + 32; /* give some breathing space */ |
54 |
reallocwrapper(sizeof(struct selectorobj *) * (temp + 1), (void *)&(sel->fdtable)); |
reallocwrapper(sizeof(struct selectorobj *) * (temp + 1), |
55 |
memset(&(sel->fdtable[sel->maxfds + 1]), 0, sizeof(struct selectorobj *) * (temp - sel->maxfds)); |
(void *) &(sel->fdtable)); |
56 |
|
memset(&(sel->fdtable[sel->maxfds + 1]), 0, |
57 |
|
sizeof(struct selectorobj *) * (temp - sel->maxfds)); |
58 |
sel->maxfds = temp; |
sel->maxfds = temp; |
59 |
} |
} |
60 |
if (sel->fdtable[newport] != NULL) |
if (sel->fdtable[newport] != NULL) |
61 |
errormsg("select.c: select_addfd - trying to add a file descriptor already in table.", __FILE__, __LINE__); |
errormsg |
62 |
|
("select.c: select_addfd - trying to add a file descriptor already in table.", |
63 |
|
__FILE__, __LINE__); |
64 |
else |
else |
65 |
{ |
{ |
66 |
struct selectorobj *temp = mallocwrapper(sizeof(struct selectorobj)); |
struct selectorobj *temp = mallocwrapper(sizeof(struct selectorobj)); |
67 |
|
|
68 |
temp->readsockopt = NULL; |
temp->readsockopt = NULL; |
69 |
temp->writesockopt = NULL; |
temp->writesockopt = NULL; |
70 |
temp->readdata = NULL; |
temp->readdata = NULL; |
78 |
} |
} |
79 |
} |
} |
80 |
|
|
81 |
void select_delfd(SELECTER *sel, int deadport) |
void select_delfd(SELECTER * sel, |
82 |
|
int deadport) |
83 |
{ |
{ |
84 |
int result; |
int result; |
85 |
struct selectorobj *temp = sel->fdtable[deadport]; |
struct selectorobj *temp = sel->fdtable[deadport]; |
86 |
|
|
87 |
debuglog("select_delfd - removing fd %d", deadport); |
debuglog("select_delfd - removing fd %d", deadport); |
88 |
|
|
89 |
result = close(deadport); /* make sure the port is closed :) */ |
result = close(deadport); /* make sure the port is closed :) */ |
90 |
|
|
91 |
/* if (result == -1) |
/* if (result == -1) |
92 |
errormsg(strerror(errno), __FILE__, __LINE__); |
errormsg(strerror(errno), __FILE__, __LINE__); |
93 |
*/ |
*/ |
94 |
select_takeread(sel, deadport); |
select_takeread(sel, deadport); |
95 |
select_takewrite(sel, deadport); |
select_takewrite(sel, deadport); |
96 |
|
|
97 |
if (sel->firstfd == deadport) |
if (sel->firstfd == deadport) |
98 |
{ |
{ |
99 |
sel->firstfd = temp->next; |
sel->firstfd = temp->next; |
110 |
freewrapper(temp); |
freewrapper(temp); |
111 |
sel->fdtable[deadport] = NULL; |
sel->fdtable[deadport] = NULL; |
112 |
} |
} |
113 |
|
|
114 |
void select_addread(SELECTER *sel, int port, int (* proc)(SELECTER *, int, void *), void *dat) |
void select_addread(SELECTER * sel, |
115 |
|
int port, |
116 |
|
int (*proc) (SELECTER *, |
117 |
|
int, |
118 |
|
void *), |
119 |
|
void *dat) |
120 |
{ |
{ |
121 |
debuglog("select_addread - fd %d", port); |
debuglog("select_addread - fd %d", port); |
122 |
|
|
123 |
sel->fdtable[port]->readsockopt = proc; |
sel->fdtable[port]->readsockopt = proc; |
124 |
sel->fdtable[port]->readdata = dat; |
sel->fdtable[port]->readdata = dat; |
125 |
|
|
126 |
sel->smax = MAXIMUM(sel->smax, port); |
sel->smax = MAXIMUM(sel->smax, port); |
127 |
} |
} |
128 |
|
|
129 |
void select_addwrite(SELECTER *sel, int port, int (* proc)(SELECTER *, int, void *), void *dat) |
void select_addwrite(SELECTER * sel, |
130 |
|
int port, |
131 |
|
int (*proc) (SELECTER *, |
132 |
|
int, |
133 |
|
void *), |
134 |
|
void *dat) |
135 |
{ |
{ |
136 |
debuglog("select_addwrite - fd %d", port); |
debuglog("select_addwrite - fd %d", port); |
137 |
|
|
141 |
sel->smax = MAXIMUM(sel->smax, port); |
sel->smax = MAXIMUM(sel->smax, port); |
142 |
} |
} |
143 |
|
|
144 |
void select_takeread(SELECTER *sel, int port) |
void select_takeread(SELECTER * sel, |
145 |
|
int port) |
146 |
{ |
{ |
147 |
debuglog("select_takeread - fd %d", port); |
debuglog("select_takeread - fd %d", port); |
148 |
|
|
149 |
sel->fdtable[port]->readsockopt = NULL; |
sel->fdtable[port]->readsockopt = NULL; |
150 |
sel->fdtable[port]->readdata = NULL; |
sel->fdtable[port]->readdata = NULL; |
151 |
|
|
152 |
/* FD_CLR(port, &(sel->readset)); */ |
/* FD_CLR(port, &(sel->readset)); */ |
153 |
} |
} |
154 |
|
|
155 |
void select_takewrite(SELECTER *sel, int port) |
void select_takewrite(SELECTER * sel, |
156 |
|
int port) |
157 |
{ |
{ |
158 |
debuglog("select_takewrite - fd %d", port); |
debuglog("select_takewrite - fd %d", port); |
159 |
|
|
160 |
sel->fdtable[port]->writesockopt = NULL; |
sel->fdtable[port]->writesockopt = NULL; |
161 |
sel->fdtable[port]->writedata = NULL; |
sel->fdtable[port]->writedata = NULL; |
162 |
|
|
163 |
/* FD_CLR(port, &(sel->writeset)); */ |
/* FD_CLR(port, &(sel->writeset)); */ |
164 |
} |
} |
165 |
|
|
166 |
int select_do(SELECTER *sel, int *signum, int timeout) |
int select_do(SELECTER * sel, |
167 |
|
int *signum, |
168 |
|
int timeout) |
169 |
{ |
{ |
170 |
fd_set readset, writeset; |
fd_set readset, writeset; |
171 |
struct timeval tv, *tv2; |
struct timeval tv, *tv2; |
176 |
|
|
177 |
debuglog("do_select - waiting on fd's"); |
debuglog("do_select - waiting on fd's"); |
178 |
|
|
179 |
*signum = 0; signumber = 0; |
*signum = 0; |
180 |
|
signumber = 0; |
181 |
while (result == 0) |
while (result == 0) |
182 |
{ |
{ |
183 |
int pos = sel->firstfd; |
int pos = sel->firstfd; |
184 |
|
|
185 |
while(pos != -1) |
while (pos != -1) |
186 |
{ |
{ |
187 |
struct selectorobj *temp = sel->fdtable[pos]; |
struct selectorobj *temp = sel->fdtable[pos]; |
188 |
|
|
189 |
if (temp->readsockopt) |
if (temp->readsockopt) |
190 |
FD_SET(pos, &readset); |
FD_SET(pos, &readset); |
191 |
if (temp->writesockopt) |
if (temp->writesockopt) |
192 |
FD_SET(pos, &writeset); |
FD_SET(pos, &writeset); |
193 |
|
|
194 |
pos = temp->next; |
pos = temp->next; |
195 |
} |
} |
196 |
|
|
197 |
if (timeout != -1) |
if (timeout != -1) |
202 |
} |
} |
203 |
else |
else |
204 |
tv2 = NULL; |
tv2 = NULL; |
205 |
|
|
206 |
if (signumber != 0) |
if (signumber != 0) |
207 |
{ |
{ |
208 |
*signum = signumber; |
*signum = signumber; |
209 |
return(-1); |
return (-1); |
210 |
} |
} |
211 |
|
|
212 |
result = select(sel->smax + 1, &readset, &writeset, NULL, tv2); |
result = select(sel->smax + 1, &readset, &writeset, NULL, tv2); |
213 |
|
|
214 |
if (result == 0) |
if (result == 0) |
215 |
return(0); |
return (0); |
216 |
else if (result == -1) |
else if (result == -1) |
217 |
{ |
{ |
218 |
if (errno == EINTR) |
if (errno == EINTR) |
219 |
{ |
{ |
220 |
*signum = signumber; |
*signum = signumber; |
221 |
|
|
222 |
return(-1); |
return (-1); |
223 |
} |
} |
224 |
else |
else |
225 |
{ |
{ |
226 |
errormsg(strerror(errno), __FILE__, __LINE__); |
errormsg(strerror(errno), __FILE__, __LINE__); |
227 |
return(-1); |
return (-1); |
228 |
} |
} |
229 |
} |
} |
230 |
else |
else |
231 |
{ |
{ |
232 |
pos = sel->firstfd; |
pos = sel->firstfd; |
233 |
result = 0; |
result = 0; |
234 |
while((pos != -1) && (result == 0)) |
while ((pos != -1) && (result == 0)) |
235 |
{ |
{ |
236 |
struct selectorobj *temp = sel->fdtable[pos]; |
struct selectorobj *temp = sel->fdtable[pos]; |
237 |
|
|
238 |
if (temp->readsockopt) |
if (temp->readsockopt) |
239 |
if (FD_ISSET(pos, &readset)) |
if (FD_ISSET(pos, &readset)) |
240 |
result = temp->readsockopt(sel, pos, temp->readdata); |
result = temp->readsockopt(sel, pos, temp->readdata); |
241 |
if ((temp->writesockopt) && (result == 0)) |
if ((temp->writesockopt) && (result == 0)) |
242 |
if (FD_ISSET(pos, &writeset)) |
if (FD_ISSET(pos, &writeset)) |
243 |
result = temp->writesockopt(sel, pos, temp->writedata); |
result = |
244 |
|
temp->writesockopt(sel, pos, temp->writedata); |
245 |
|
|
246 |
FD_CLR(pos, &writeset); |
FD_CLR(pos, &writeset); |
247 |
FD_CLR(pos, &readset); |
FD_CLR(pos, &readset); |
248 |
|
|
249 |
if (result == 2) |
if (result == 2) |
250 |
{ |
{ |
251 |
int pos2 = temp->next; |
int pos2 = temp->next; |
252 |
|
|
253 |
select_delfd(sel, pos); |
select_delfd(sel, pos); |
254 |
result = 0; |
result = 0; |
255 |
pos = pos2; |
pos = pos2; |
256 |
} |
} |
257 |
else |
else |
258 |
pos = temp->next; |
pos = temp->next; |
259 |
|
|
260 |
} |
} |
261 |
} |
} |
262 |
} |
} |
263 |
|
|
264 |
return(result); |
return (result); |
265 |
} |
} |
266 |
|
|
267 |
void select_shutdown(SELECTER *sel) |
void select_shutdown(SELECTER * sel) |
268 |
{ |
{ |
269 |
int count; |
int count; |
270 |
|
|
271 |
for (count = 0; count < sel->maxfds; count++) |
for (count = 0; count < sel->maxfds; count++) |
272 |
if (sel->fdtable[count]) |
if (sel->fdtable[count]) |
273 |
select_delfd(sel, count); |
select_delfd(sel, count); |
274 |
|
|
275 |
freewrapper(sel->fdtable); |
freewrapper(sel->fdtable); |
276 |
freewrapper(sel); |
freewrapper(sel); |