Default kdump's data limit to 64 bytes and document how it can be disabled.
[dragonfly.git] / contrib / wpa_supplicant-0.4.9 / eloop.c
1 /*
2  * Event loop based on select() loop
3  * Copyright (c) 2002-2005, Jouni Malinen <jkmaline@cc.hut.fi>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation.
8  *
9  * Alternatively, this software may be distributed under the terms of BSD
10  * license.
11  *
12  * See README and COPYING for more details.
13  */
14
15 #include <stdlib.h>
16 #include <stdio.h>
17 #include <string.h>
18 #include <sys/time.h>
19 #include <sys/types.h>
20 #include <unistd.h>
21 #include <errno.h>
22 #include <signal.h>
23
24 #ifdef CONFIG_NATIVE_WINDOWS
25 #include "common.h"
26 #endif /* CONFIG_NATIVE_WINDOWS */
27
28 #include "eloop.h"
29
30
31 struct eloop_sock {
32         int sock;
33         void *eloop_data;
34         void *user_data;
35         void (*handler)(int sock, void *eloop_ctx, void *sock_ctx);
36 };
37
38 struct eloop_timeout {
39         struct timeval time;
40         void *eloop_data;
41         void *user_data;
42         void (*handler)(void *eloop_ctx, void *sock_ctx);
43         struct eloop_timeout *next;
44 };
45
46 struct eloop_signal {
47         int sig;
48         void *user_data;
49         void (*handler)(int sig, void *eloop_ctx, void *signal_ctx);
50         int signaled;
51 };
52
53 struct eloop_data {
54         void *user_data;
55
56         int max_sock, reader_count;
57         struct eloop_sock *readers;
58
59         struct eloop_timeout *timeout;
60
61         int signal_count;
62         struct eloop_signal *signals;
63         int signaled;
64         int pending_terminate;
65
66         int terminate;
67         int reader_table_changed;
68 };
69
70 static struct eloop_data eloop;
71
72
73 void eloop_init(void *user_data)
74 {
75         memset(&eloop, 0, sizeof(eloop));
76         eloop.user_data = user_data;
77 }
78
79
80 int eloop_register_read_sock(int sock,
81                              void (*handler)(int sock, void *eloop_ctx,
82                                              void *sock_ctx),
83                              void *eloop_data, void *user_data)
84 {
85         struct eloop_sock *tmp;
86
87         tmp = (struct eloop_sock *)
88                 realloc(eloop.readers,
89                         (eloop.reader_count + 1) * sizeof(struct eloop_sock));
90         if (tmp == NULL)
91                 return -1;
92
93         tmp[eloop.reader_count].sock = sock;
94         tmp[eloop.reader_count].eloop_data = eloop_data;
95         tmp[eloop.reader_count].user_data = user_data;
96         tmp[eloop.reader_count].handler = handler;
97         eloop.reader_count++;
98         eloop.readers = tmp;
99         if (sock > eloop.max_sock)
100                 eloop.max_sock = sock;
101         eloop.reader_table_changed = 1;
102
103         return 0;
104 }
105
106
107 void eloop_unregister_read_sock(int sock)
108 {
109         int i;
110
111         if (eloop.readers == NULL || eloop.reader_count == 0)
112                 return;
113
114         for (i = 0; i < eloop.reader_count; i++) {
115                 if (eloop.readers[i].sock == sock)
116                         break;
117         }
118         if (i == eloop.reader_count)
119                 return;
120         if (i != eloop.reader_count - 1) {
121                 memmove(&eloop.readers[i], &eloop.readers[i + 1],
122                         (eloop.reader_count - i - 1) *
123                         sizeof(struct eloop_sock));
124         }
125         eloop.reader_count--;
126         eloop.reader_table_changed = 1;
127 }
128
129
130 int eloop_register_timeout(unsigned int secs, unsigned int usecs,
131                            void (*handler)(void *eloop_ctx, void *timeout_ctx),
132                            void *eloop_data, void *user_data)
133 {
134         struct eloop_timeout *timeout, *tmp, *prev;
135
136         timeout = (struct eloop_timeout *) malloc(sizeof(*timeout));
137         if (timeout == NULL)
138                 return -1;
139         gettimeofday(&timeout->time, NULL);
140         timeout->time.tv_sec += secs;
141         timeout->time.tv_usec += usecs;
142         while (timeout->time.tv_usec >= 1000000) {
143                 timeout->time.tv_sec++;
144                 timeout->time.tv_usec -= 1000000;
145         }
146         timeout->eloop_data = eloop_data;
147         timeout->user_data = user_data;
148         timeout->handler = handler;
149         timeout->next = NULL;
150
151         if (eloop.timeout == NULL) {
152                 eloop.timeout = timeout;
153                 return 0;
154         }
155
156         prev = NULL;
157         tmp = eloop.timeout;
158         while (tmp != NULL) {
159                 if (timercmp(&timeout->time, &tmp->time, <))
160                         break;
161                 prev = tmp;
162                 tmp = tmp->next;
163         }
164
165         if (prev == NULL) {
166                 timeout->next = eloop.timeout;
167                 eloop.timeout = timeout;
168         } else {
169                 timeout->next = prev->next;
170                 prev->next = timeout;
171         }
172
173         return 0;
174 }
175
176
177 int eloop_cancel_timeout(void (*handler)(void *eloop_ctx, void *sock_ctx),
178                          void *eloop_data, void *user_data)
179 {
180         struct eloop_timeout *timeout, *prev, *next;
181         int removed = 0;
182
183         prev = NULL;
184         timeout = eloop.timeout;
185         while (timeout != NULL) {
186                 next = timeout->next;
187
188                 if (timeout->handler == handler &&
189                     (timeout->eloop_data == eloop_data ||
190                      eloop_data == ELOOP_ALL_CTX) &&
191                     (timeout->user_data == user_data ||
192                      user_data == ELOOP_ALL_CTX)) {
193                         if (prev == NULL)
194                                 eloop.timeout = next;
195                         else
196                                 prev->next = next;
197                         free(timeout);
198                         removed++;
199                 } else
200                         prev = timeout;
201
202                 timeout = next;
203         }
204
205         return removed;
206 }
207
208
209 #ifndef CONFIG_NATIVE_WINDOWS
210 static void eloop_handle_alarm(int sig)
211 {
212         fprintf(stderr, "eloop: could not process SIGINT or SIGTERM in two "
213                 "seconds. Looks like there\n"
214                 "is a bug that ends up in a busy loop that "
215                 "prevents clean shutdown.\n"
216                 "Killing program forcefully.\n");
217         exit(1);
218 }
219 #endif /* CONFIG_NATIVE_WINDOWS */
220
221
222 static void eloop_handle_signal(int sig)
223 {
224         int i;
225
226 #ifndef CONFIG_NATIVE_WINDOWS
227         if ((sig == SIGINT || sig == SIGTERM) && !eloop.pending_terminate) {
228                 /* Use SIGALRM to break out from potential busy loops that
229                  * would not allow the program to be killed. */
230                 eloop.pending_terminate = 1;
231                 signal(SIGALRM, eloop_handle_alarm);
232                 alarm(2);
233         }
234 #endif /* CONFIG_NATIVE_WINDOWS */
235
236         eloop.signaled++;
237         for (i = 0; i < eloop.signal_count; i++) {
238                 if (eloop.signals[i].sig == sig) {
239                         eloop.signals[i].signaled++;
240                         break;
241                 }
242         }
243 }
244
245
246 static void eloop_process_pending_signals(void)
247 {
248         int i;
249
250         if (eloop.signaled == 0)
251                 return;
252         eloop.signaled = 0;
253
254         if (eloop.pending_terminate) {
255 #ifndef CONFIG_NATIVE_WINDOWS
256                 alarm(0);
257 #endif /* CONFIG_NATIVE_WINDOWS */
258                 eloop.pending_terminate = 0;
259         }
260
261         for (i = 0; i < eloop.signal_count; i++) {
262                 if (eloop.signals[i].signaled) {
263                         eloop.signals[i].signaled = 0;
264                         eloop.signals[i].handler(eloop.signals[i].sig,
265                                                  eloop.user_data,
266                                                  eloop.signals[i].user_data);
267                 }
268         }
269 }
270
271
272 int eloop_register_signal(int sig,
273                           void (*handler)(int sig, void *eloop_ctx,
274                                           void *signal_ctx),
275                           void *user_data)
276 {
277         struct eloop_signal *tmp;
278
279         tmp = (struct eloop_signal *)
280                 realloc(eloop.signals,
281                         (eloop.signal_count + 1) *
282                         sizeof(struct eloop_signal));
283         if (tmp == NULL)
284                 return -1;
285
286         tmp[eloop.signal_count].sig = sig;
287         tmp[eloop.signal_count].user_data = user_data;
288         tmp[eloop.signal_count].handler = handler;
289         tmp[eloop.signal_count].signaled = 0;
290         eloop.signal_count++;
291         eloop.signals = tmp;
292         signal(sig, eloop_handle_signal);
293
294         return 0;
295 }
296
297
298 void eloop_run(void)
299 {
300         fd_set *rfds;
301         int i, res;
302         struct timeval tv, now;
303
304         rfds = malloc(sizeof(*rfds));
305         if (rfds == NULL) {
306                 printf("eloop_run - malloc failed\n");
307                 return;
308         }
309
310         while (!eloop.terminate &&
311                 (eloop.timeout || eloop.reader_count > 0)) {
312                 if (eloop.timeout) {
313                         gettimeofday(&now, NULL);
314                         if (timercmp(&now, &eloop.timeout->time, <))
315                                 timersub(&eloop.timeout->time, &now, &tv);
316                         else
317                                 tv.tv_sec = tv.tv_usec = 0;
318 #if 0
319                         printf("next timeout in %lu.%06lu sec\n",
320                                tv.tv_sec, tv.tv_usec);
321 #endif
322                 }
323
324                 FD_ZERO(rfds);
325                 for (i = 0; i < eloop.reader_count; i++)
326                         FD_SET(eloop.readers[i].sock, rfds);
327                 res = select(eloop.max_sock + 1, rfds, NULL, NULL,
328                              eloop.timeout ? &tv : NULL);
329                 if (res < 0 && errno != EINTR) {
330                         perror("select");
331                         free(rfds);
332                         return;
333                 }
334                 eloop_process_pending_signals();
335
336                 /* check if some registered timeouts have occurred */
337                 if (eloop.timeout) {
338                         struct eloop_timeout *tmp;
339
340                         gettimeofday(&now, NULL);
341                         if (!timercmp(&now, &eloop.timeout->time, <)) {
342                                 tmp = eloop.timeout;
343                                 eloop.timeout = eloop.timeout->next;
344                                 tmp->handler(tmp->eloop_data,
345                                              tmp->user_data);
346                                 free(tmp);
347                         }
348
349                 }
350
351                 if (res <= 0)
352                         continue;
353
354                 eloop.reader_table_changed = 0;
355                 for (i = 0; i < eloop.reader_count; i++) {
356                         if (FD_ISSET(eloop.readers[i].sock, rfds)) {
357                                 eloop.readers[i].handler(
358                                         eloop.readers[i].sock,
359                                         eloop.readers[i].eloop_data,
360                                         eloop.readers[i].user_data);
361                                 if (eloop.reader_table_changed)
362                                         break;
363                         }
364                 }
365         }
366
367         free(rfds);
368 }
369
370
371 void eloop_terminate(void)
372 {
373         eloop.terminate = 1;
374 }
375
376
377 void eloop_destroy(void)
378 {
379         struct eloop_timeout *timeout, *prev;
380
381         timeout = eloop.timeout;
382         while (timeout != NULL) {
383                 prev = timeout;
384                 timeout = timeout->next;
385                 free(prev);
386         }
387         free(eloop.readers);
388         free(eloop.signals);
389 }
390
391
392 int eloop_terminated(void)
393 {
394         return eloop.terminate;
395 }