]>
Commit | Line | Data |
---|---|---|
61b844bf TL |
1 | /* dispatch.c |
2 | ||
3 | I/O dispatcher. */ | |
4 | ||
5 | /* | |
49733f31 TL |
6 | * Copyright (c) 1999-2000 Internet Software Consortium. |
7 | * All rights reserved. | |
61b844bf | 8 | * |
49733f31 TL |
9 | * Redistribution and use in source and binary forms, with or without |
10 | * modification, are permitted provided that the following conditions | |
11 | * are met: | |
61b844bf | 12 | * |
49733f31 TL |
13 | * 1. Redistributions of source code must retain the above copyright |
14 | * notice, this list of conditions and the following disclaimer. | |
15 | * 2. Redistributions in binary form must reproduce the above copyright | |
16 | * notice, this list of conditions and the following disclaimer in the | |
17 | * documentation and/or other materials provided with the distribution. | |
18 | * 3. Neither the name of The Internet Software Consortium nor the names | |
19 | * of its contributors may be used to endorse or promote products derived | |
20 | * from this software without specific prior written permission. | |
61b844bf | 21 | * |
49733f31 TL |
22 | * THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND |
23 | * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, | |
24 | * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | |
25 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |
26 | * DISCLAIMED. IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR | |
27 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
28 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
29 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF | |
30 | * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
31 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | |
32 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT | |
33 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
34 | * SUCH DAMAGE. | |
35 | * | |
36 | * This software has been written for the Internet Software Consortium | |
37 | * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc. | |
38 | * To learn more about the Internet Software Consortium, see | |
39 | * ``http://www.isc.org/''. To learn more about Vixie Enterprises, | |
40 | * see ``http://www.vix.com''. To learn more about Nominum, Inc., see | |
41 | * ``http://www.nominum.com''. | |
61b844bf TL |
42 | */ |
43 | ||
6a4c4be8 | 44 | #include <omapip/omapip_p.h> |
61b844bf TL |
45 | |
46 | static omapi_io_object_t omapi_io_states; | |
47 | u_int32_t cur_time; | |
48 | ||
20916cae TL |
49 | OMAPI_OBJECT_ALLOC (omapi_io, |
50 | omapi_io_object_t, omapi_type_io_object) | |
51 | OMAPI_OBJECT_ALLOC (omapi_waiter, | |
52 | omapi_waiter_object_t, omapi_type_waiter) | |
53 | ||
61b844bf TL |
54 | /* Register an I/O handle so that we can do asynchronous I/O on it. */ |
55 | ||
56 | isc_result_t omapi_register_io_object (omapi_object_t *h, | |
57 | int (*readfd) (omapi_object_t *), | |
58 | int (*writefd) (omapi_object_t *), | |
59 | isc_result_t (*reader) | |
60 | (omapi_object_t *), | |
61 | isc_result_t (*writer) | |
62 | (omapi_object_t *), | |
63 | isc_result_t (*reaper) | |
64 | (omapi_object_t *)) | |
65 | { | |
66 | isc_result_t status; | |
67 | omapi_io_object_t *obj, *p; | |
68 | ||
69 | /* omapi_io_states is a static object. If its reference count | |
70 | is zero, this is the first I/O handle to be registered, so | |
71 | we need to initialize it. Because there is no inner or outer | |
72 | pointer on this object, and we're setting its refcnt to 1, it | |
73 | will never be freed. */ | |
74 | if (!omapi_io_states.refcnt) { | |
75 | omapi_io_states.refcnt = 1; | |
76 | omapi_io_states.type = omapi_type_io_object; | |
77 | } | |
78 | ||
20916cae TL |
79 | obj = (omapi_io_object_t *)0; |
80 | status = omapi_io_allocate (&obj, MDL); | |
81 | if (status != ISC_R_SUCCESS) | |
82 | return status; | |
61b844bf | 83 | |
4bd8800e | 84 | status = omapi_object_reference (&obj -> inner, h, MDL); |
61b844bf | 85 | if (status != ISC_R_SUCCESS) { |
20916cae | 86 | omapi_io_dereference (&obj, MDL); |
61b844bf TL |
87 | return status; |
88 | } | |
89 | ||
4bd8800e TL |
90 | status = omapi_object_reference (&h -> outer, |
91 | (omapi_object_t *)obj, MDL); | |
61b844bf | 92 | if (status != ISC_R_SUCCESS) { |
20916cae | 93 | omapi_io_dereference (&obj, MDL); |
61b844bf TL |
94 | return status; |
95 | } | |
96 | ||
97 | /* Find the last I/O state, if there are any. */ | |
98 | for (p = omapi_io_states.next; | |
99 | p && p -> next; p = p -> next) | |
100 | ; | |
101 | if (p) | |
20916cae | 102 | omapi_io_reference (&p -> next, obj, MDL); |
61b844bf | 103 | else |
20916cae | 104 | omapi_io_reference (&omapi_io_states.next, obj, MDL); |
61b844bf TL |
105 | |
106 | obj -> readfd = readfd; | |
107 | obj -> writefd = writefd; | |
108 | obj -> reader = reader; | |
109 | obj -> writer = writer; | |
110 | obj -> reaper = reaper; | |
111 | return ISC_R_SUCCESS; | |
112 | } | |
113 | ||
b6237fb2 TL |
114 | isc_result_t omapi_unregister_io_object (omapi_object_t *h) |
115 | { | |
20916cae | 116 | omapi_io_object_t *p, *obj, *last, *ph; |
b6237fb2 | 117 | |
20916cae TL |
118 | if (!h -> outer || h -> outer -> type != omapi_type_io_object) |
119 | return ISC_R_INVALIDARG; | |
b6237fb2 | 120 | obj = (omapi_io_object_t *)h -> outer; |
20916cae TL |
121 | ph = (omapi_io_object_t *)0; |
122 | omapi_io_reference (&ph, obj, MDL); | |
b6237fb2 TL |
123 | |
124 | /* remove from the list of I/O states */ | |
c3064fe0 | 125 | last = &omapi_io_states; |
b6237fb2 | 126 | for (p = omapi_io_states.next; p; p = p -> next) { |
20916cae TL |
127 | if (p == obj) { |
128 | omapi_io_dereference (&last -> next, MDL); | |
129 | omapi_io_reference (&last -> next, p -> next, MDL); | |
b6237fb2 TL |
130 | break; |
131 | } | |
132 | last = p; | |
133 | } | |
134 | if (obj -> next) | |
20916cae TL |
135 | omapi_io_dereference (&obj -> next, MDL); |
136 | ||
b6237fb2 TL |
137 | if (obj -> outer) { |
138 | if (obj -> outer -> inner == (omapi_object_t *)obj) | |
139 | omapi_object_dereference (&obj -> outer -> inner, | |
140 | MDL); | |
141 | omapi_object_dereference (&obj -> outer, MDL); | |
142 | } | |
143 | omapi_object_dereference (&obj -> inner, MDL); | |
144 | omapi_object_dereference (&h -> outer, MDL); | |
20916cae | 145 | omapi_io_dereference (&ph, MDL); |
b6237fb2 TL |
146 | return ISC_R_SUCCESS; |
147 | } | |
148 | ||
61b844bf TL |
149 | isc_result_t omapi_dispatch (struct timeval *t) |
150 | { | |
151 | return omapi_wait_for_completion ((omapi_object_t *)&omapi_io_states, | |
152 | t); | |
153 | } | |
154 | ||
155 | isc_result_t omapi_wait_for_completion (omapi_object_t *object, | |
156 | struct timeval *t) | |
157 | { | |
158 | isc_result_t status; | |
159 | omapi_waiter_object_t *waiter; | |
160 | omapi_object_t *inner; | |
161 | ||
162 | if (object) { | |
20916cae TL |
163 | waiter = (omapi_waiter_object_t *)0; |
164 | status = omapi_waiter_allocate (&waiter, MDL); | |
165 | if (status != ISC_R_SUCCESS) | |
166 | return status; | |
61b844bf TL |
167 | |
168 | /* Paste the waiter object onto the inner object we're | |
169 | waiting on. */ | |
170 | for (inner = object; inner -> inner; inner = inner -> inner) | |
171 | ; | |
172 | ||
4bd8800e | 173 | status = omapi_object_reference (&waiter -> outer, inner, MDL); |
61b844bf | 174 | if (status != ISC_R_SUCCESS) { |
20916cae | 175 | omapi_waiter_dereference (&waiter, MDL); |
61b844bf TL |
176 | return status; |
177 | } | |
178 | ||
179 | status = omapi_object_reference (&inner -> inner, | |
180 | (omapi_object_t *)waiter, | |
4bd8800e | 181 | MDL); |
61b844bf | 182 | if (status != ISC_R_SUCCESS) { |
20916cae | 183 | omapi_waiter_dereference (&waiter, MDL); |
61b844bf TL |
184 | return status; |
185 | } | |
186 | } else | |
187 | waiter = (omapi_waiter_object_t *)0; | |
188 | ||
189 | do { | |
6a4c4be8 | 190 | status = omapi_one_dispatch ((omapi_object_t *)waiter, t); |
61b844bf TL |
191 | if (status != ISC_R_SUCCESS) |
192 | return status; | |
193 | } while (!waiter || !waiter -> ready); | |
194 | ||
727ebc3a TL |
195 | if (waiter -> outer) { |
196 | if (waiter -> outer -> inner) { | |
197 | omapi_object_dereference (&waiter -> outer -> inner, | |
4bd8800e | 198 | MDL); |
727ebc3a TL |
199 | if (waiter -> inner) |
200 | omapi_object_reference | |
201 | (&waiter -> outer -> inner, | |
4bd8800e | 202 | waiter -> inner, MDL); |
727ebc3a | 203 | } |
4bd8800e | 204 | omapi_object_dereference (&waiter -> outer, MDL); |
727ebc3a TL |
205 | } |
206 | if (waiter -> inner) | |
4bd8800e | 207 | omapi_object_dereference (&waiter -> inner, MDL); |
727ebc3a | 208 | |
20916cae | 209 | omapi_waiter_dereference (&waiter, MDL); |
61b844bf TL |
210 | return ISC_R_SUCCESS; |
211 | } | |
212 | ||
6a4c4be8 | 213 | isc_result_t omapi_one_dispatch (omapi_object_t *wo, |
61b844bf TL |
214 | struct timeval *t) |
215 | { | |
216 | fd_set r, w, x; | |
217 | int max = 0; | |
218 | int count; | |
219 | int desc; | |
220 | struct timeval now, to; | |
221 | omapi_io_object_t *io, *prev; | |
222 | isc_result_t status; | |
6a4c4be8 | 223 | omapi_waiter_object_t *waiter; |
b6237fb2 | 224 | omapi_object_t *tmp = (omapi_object_t *)0; |
6a4c4be8 TL |
225 | |
226 | if (!wo || wo -> type != omapi_type_waiter) | |
227 | waiter = (omapi_waiter_object_t *)0; | |
228 | else | |
229 | waiter = (omapi_waiter_object_t *)wo; | |
61b844bf TL |
230 | |
231 | FD_ZERO (&x); | |
232 | ||
233 | /* First, see if the timeout has expired, and if so return. */ | |
234 | if (t) { | |
235 | gettimeofday (&now, (struct timezone *)0); | |
236 | cur_time = now.tv_sec; | |
237 | if (now.tv_sec > t -> tv_sec || | |
238 | (now.tv_sec == t -> tv_sec && now.tv_usec >= t -> tv_usec)) | |
239 | return ISC_R_TIMEDOUT; | |
240 | ||
241 | /* We didn't time out, so figure out how long until | |
242 | we do. */ | |
243 | to.tv_sec = t -> tv_sec - now.tv_sec; | |
244 | to.tv_usec = t -> tv_usec - now.tv_usec; | |
245 | if (to.tv_usec < 0) { | |
246 | to.tv_usec += 1000000; | |
247 | to.tv_sec--; | |
248 | } | |
249 | } | |
250 | ||
251 | /* If the object we're waiting on has reached completion, | |
252 | return now. */ | |
253 | if (waiter && waiter -> ready) | |
254 | return ISC_R_SUCCESS; | |
255 | ||
cfb3f45d | 256 | again: |
61b844bf TL |
257 | /* If we have no I/O state, we can't proceed. */ |
258 | if (!(io = omapi_io_states.next)) | |
259 | return ISC_R_NOMORE; | |
260 | ||
261 | /* Set up the read and write masks. */ | |
262 | FD_ZERO (&r); | |
263 | FD_ZERO (&w); | |
264 | ||
265 | for (; io; io = io -> next) { | |
266 | /* Check for a read socket. If we shouldn't be | |
267 | trying to read for this I/O object, either there | |
268 | won't be a readfd function, or it'll return -1. */ | |
d8c46740 | 269 | if (io -> readfd && io -> inner && |
61b844bf TL |
270 | (desc = (*(io -> readfd)) (io -> inner)) >= 0) { |
271 | FD_SET (desc, &r); | |
272 | if (desc > max) | |
273 | max = desc; | |
274 | } | |
275 | ||
276 | /* Same deal for write fdets. */ | |
d8c46740 | 277 | if (io -> writefd && io -> inner && |
61b844bf TL |
278 | (desc = (*(io -> writefd)) (io -> inner)) >= 0) { |
279 | FD_SET (desc, &w); | |
280 | if (desc > max) | |
281 | max = desc; | |
282 | } | |
283 | } | |
284 | ||
285 | /* Wait for a packet or a timeout... XXX */ | |
edbb7667 | 286 | #if 0 |
cfb3f45d TL |
287 | #if defined (__linux__) |
288 | #define fds_bits __fds_bits | |
289 | #endif | |
477e97dd TL |
290 | log_error ("dispatch: %d %lx %lx", max, |
291 | (unsigned long)r.fds_bits [0], | |
292 | (unsigned long)w.fds_bits [0]); | |
edbb7667 | 293 | #endif |
61b844bf TL |
294 | count = select (max + 1, &r, &w, &x, t ? &to : (struct timeval *)0); |
295 | ||
296 | /* Get the current time... */ | |
297 | gettimeofday (&now, (struct timezone *)0); | |
298 | cur_time = now.tv_sec; | |
299 | ||
cfb3f45d TL |
300 | /* We probably have a bad file descriptor. Figure out which one. |
301 | When we find it, call the reaper function on it, which will | |
302 | maybe make it go away, and then try again. */ | |
303 | if (count < 0) { | |
304 | struct timeval t0; | |
305 | ||
306 | for (io = omapi_io_states.next; io; io = io -> next) { | |
307 | omapi_object_t *obj; | |
308 | FD_ZERO (&r); | |
309 | FD_ZERO (&w); | |
310 | t0.tv_sec = t0.tv_usec = 0; | |
311 | ||
312 | if (io -> readfd && io -> inner && | |
313 | (desc = (*(io -> readfd)) (io -> inner)) >= 0) { | |
314 | FD_SET (desc, &r); | |
edbb7667 | 315 | #if 0 |
477e97dd TL |
316 | log_error ("read check: %d %lx %lx", max, |
317 | (unsigned long)r.fds_bits [0], | |
318 | (unsigned long)w.fds_bits [0]); | |
edbb7667 | 319 | #endif |
cfb3f45d TL |
320 | count = select (desc + 1, &r, &w, &x, &t0); |
321 | bogon: | |
322 | if (count < 0) { | |
323 | log_error ("Bad descriptor %d.", desc); | |
324 | for (obj = (omapi_object_t *)io; | |
325 | obj -> outer; | |
326 | obj = obj -> outer) | |
327 | ; | |
328 | for (; obj; obj = obj -> inner) | |
329 | log_error ("Object %lx %s", | |
330 | (unsigned long)obj, | |
331 | obj -> type -> name); | |
332 | status = (*(io -> reaper)) (io -> inner); | |
333 | goto again; | |
334 | } | |
335 | } | |
336 | ||
337 | FD_ZERO (&r); | |
338 | FD_ZERO (&w); | |
339 | t0.tv_sec = t0.tv_usec = 0; | |
340 | ||
341 | /* Same deal for write fdets. */ | |
342 | if (io -> writefd && io -> inner && | |
343 | (desc = (*(io -> writefd)) (io -> inner)) >= 0) { | |
344 | FD_SET (desc, &w); | |
edbb7667 | 345 | #if 0 |
477e97dd TL |
346 | log_error ("write check: %d %lx %lx", max, |
347 | (unsigned long)r.fds_bits [0], | |
348 | (unsigned long)w.fds_bits [0]); | |
edbb7667 | 349 | #endif |
cfb3f45d TL |
350 | count = select (desc + 1, &r, &w, &x, &t0); |
351 | if (count < 0) | |
352 | goto bogon; | |
353 | } | |
354 | } | |
355 | } | |
61b844bf TL |
356 | |
357 | for (io = omapi_io_states.next; io; io = io -> next) { | |
d8c46740 TL |
358 | if (!io -> inner) |
359 | continue; | |
b6237fb2 | 360 | omapi_object_reference (&tmp, io -> inner, MDL); |
61b844bf TL |
361 | /* Check for a read descriptor, and if there is one, |
362 | see if we got input on that socket. */ | |
363 | if (io -> readfd && | |
b6237fb2 | 364 | (desc = (*(io -> readfd)) (tmp)) >= 0) { |
61b844bf | 365 | if (FD_ISSET (desc, &r)) |
b6237fb2 | 366 | status = ((*(io -> reader)) (tmp)); |
61b844bf TL |
367 | /* XXX what to do with status? */ |
368 | } | |
369 | ||
370 | /* Same deal for write descriptors. */ | |
371 | if (io -> writefd && | |
b6237fb2 | 372 | (desc = (*(io -> writefd)) (tmp)) >= 0) |
61b844bf TL |
373 | { |
374 | if (FD_ISSET (desc, &w)) | |
b6237fb2 | 375 | status = ((*(io -> writer)) (tmp)); |
61b844bf TL |
376 | /* XXX what to do with status? */ |
377 | } | |
b6237fb2 | 378 | omapi_object_dereference (&tmp, MDL); |
61b844bf TL |
379 | } |
380 | ||
381 | /* Now check for I/O handles that are no longer valid, | |
382 | and remove them from the list. */ | |
383 | prev = (omapi_io_object_t *)0; | |
384 | for (io = omapi_io_states.next; io; io = io -> next) { | |
385 | if (io -> reaper) { | |
d8c46740 TL |
386 | if (io -> inner) |
387 | status = (*(io -> reaper)) (io -> inner); | |
388 | if (!io -> inner || status != ISC_R_SUCCESS) { | |
61b844bf TL |
389 | omapi_io_object_t *tmp = |
390 | (omapi_io_object_t *)0; | |
391 | /* Save a reference to the next | |
392 | pointer, if there is one. */ | |
393 | if (io -> next) | |
20916cae TL |
394 | omapi_io_reference (&tmp, |
395 | io -> next, MDL); | |
61b844bf | 396 | if (prev) { |
20916cae TL |
397 | omapi_io_dereference (&prev -> next, |
398 | MDL); | |
61b844bf | 399 | if (tmp) |
20916cae TL |
400 | omapi_io_reference |
401 | (&prev -> next, | |
402 | tmp, MDL); | |
61b844bf | 403 | } else { |
20916cae TL |
404 | omapi_io_dereference |
405 | (&omapi_io_states.next, MDL); | |
61b844bf | 406 | if (tmp) |
20916cae TL |
407 | omapi_io_reference |
408 | (&omapi_io_states.next, | |
409 | tmp, MDL); | |
61b844bf TL |
410 | else |
411 | omapi_signal_in | |
412 | ((omapi_object_t *) | |
413 | &omapi_io_states, | |
414 | "ready"); | |
415 | } | |
416 | if (tmp) | |
20916cae | 417 | omapi_io_dereference (&tmp, MDL); |
61b844bf TL |
418 | } |
419 | } | |
420 | prev = io; | |
421 | } | |
422 | ||
423 | return ISC_R_SUCCESS; | |
424 | } | |
425 | ||
426 | isc_result_t omapi_io_set_value (omapi_object_t *h, | |
427 | omapi_object_t *id, | |
428 | omapi_data_string_t *name, | |
429 | omapi_typed_data_t *value) | |
430 | { | |
431 | if (h -> type != omapi_type_io_object) | |
432 | return ISC_R_INVALIDARG; | |
433 | ||
434 | if (h -> inner && h -> inner -> type -> set_value) | |
435 | return (*(h -> inner -> type -> set_value)) | |
436 | (h -> inner, id, name, value); | |
437 | return ISC_R_NOTFOUND; | |
438 | } | |
439 | ||
440 | isc_result_t omapi_io_get_value (omapi_object_t *h, | |
441 | omapi_object_t *id, | |
442 | omapi_data_string_t *name, | |
443 | omapi_value_t **value) | |
444 | { | |
445 | if (h -> type != omapi_type_io_object) | |
446 | return ISC_R_INVALIDARG; | |
447 | ||
448 | if (h -> inner && h -> inner -> type -> get_value) | |
449 | return (*(h -> inner -> type -> get_value)) | |
450 | (h -> inner, id, name, value); | |
451 | return ISC_R_NOTFOUND; | |
452 | } | |
453 | ||
4bd8800e | 454 | isc_result_t omapi_io_destroy (omapi_object_t *h, const char *file, int line) |
61b844bf | 455 | { |
bdcaf7b9 TL |
456 | omapi_io_object_t *obj, *p, *last; |
457 | ||
61b844bf TL |
458 | if (h -> type != omapi_type_io_object) |
459 | return ISC_R_INVALIDARG; | |
bdcaf7b9 TL |
460 | |
461 | obj = (omapi_io_object_t *)h; | |
462 | ||
b6237fb2 TL |
463 | /* remove from the list of I/O states */ |
464 | for (p = omapi_io_states.next; p; p = p -> next) { | |
465 | if (p == obj) { | |
20916cae TL |
466 | omapi_io_dereference (&last -> next, MDL); |
467 | omapi_io_reference (&last -> next, p -> next, MDL); | |
468 | omapi_io_dereference (&p, MDL); | |
b6237fb2 | 469 | break; |
bdcaf7b9 | 470 | } |
b6237fb2 | 471 | last = p; |
bdcaf7b9 | 472 | } |
b6237fb2 | 473 | |
61b844bf TL |
474 | return ISC_R_SUCCESS; |
475 | } | |
476 | ||
477 | isc_result_t omapi_io_signal_handler (omapi_object_t *h, | |
b1b7b521 | 478 | const char *name, va_list ap) |
61b844bf TL |
479 | { |
480 | if (h -> type != omapi_type_io_object) | |
481 | return ISC_R_INVALIDARG; | |
482 | ||
483 | if (h -> inner && h -> inner -> type -> signal_handler) | |
484 | return (*(h -> inner -> type -> signal_handler)) (h -> inner, | |
485 | name, ap); | |
486 | return ISC_R_NOTFOUND; | |
487 | } | |
488 | ||
489 | isc_result_t omapi_io_stuff_values (omapi_object_t *c, | |
490 | omapi_object_t *id, | |
491 | omapi_object_t *i) | |
492 | { | |
493 | if (i -> type != omapi_type_io_object) | |
494 | return ISC_R_INVALIDARG; | |
495 | ||
496 | if (i -> inner && i -> inner -> type -> stuff_values) | |
497 | return (*(i -> inner -> type -> stuff_values)) (c, id, | |
498 | i -> inner); | |
499 | return ISC_R_SUCCESS; | |
500 | } | |
501 | ||
502 | isc_result_t omapi_waiter_signal_handler (omapi_object_t *h, | |
b1b7b521 | 503 | const char *name, va_list ap) |
61b844bf TL |
504 | { |
505 | omapi_waiter_object_t *waiter; | |
506 | ||
507 | if (h -> type != omapi_type_waiter) | |
508 | return ISC_R_INVALIDARG; | |
509 | ||
510 | if (!strcmp (name, "ready")) { | |
511 | waiter = (omapi_waiter_object_t *)h; | |
512 | waiter -> ready = 1; | |
513 | return ISC_R_SUCCESS; | |
514 | } | |
515 | ||
516 | if (h -> inner && h -> inner -> type -> signal_handler) | |
517 | return (*(h -> inner -> type -> signal_handler)) (h -> inner, | |
518 | name, ap); | |
519 | return ISC_R_NOTFOUND; | |
520 | } | |
521 |