]> git.saurik.com Git - apple/syslog.git/blame - syslogd.tproj/syslogd.c
syslog-69.0.4.tar.gz
[apple/syslog.git] / syslogd.tproj / syslogd.c
CommitLineData
b16a592a 1/*
57b0aad2 2 * Copyright (c) 2004-2008 Apple Inc. All rights reserved.
b16a592a
A
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
5dd30d76
A
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
b16a592a
A
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
5dd30d76
A
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
b16a592a
A
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24#include <stdio.h>
25#include <stdlib.h>
26#include <unistd.h>
27#include <string.h>
28#include <signal.h>
5dd30d76
A
29#include <mach/mach.h>
30#include <mach/mach_error.h>
31#include <mach/mach_time.h>
32#include <servers/bootstrap.h>
b16a592a
A
33#include <sys/types.h>
34#include <sys/socket.h>
35#include <sys/fcntl.h>
36#include <sys/queue.h>
37#include <sys/time.h>
5dd30d76 38#include <pthread.h>
b16a592a
A
39#include <dirent.h>
40#include <dlfcn.h>
41#include <libgen.h>
42#include <notify.h>
43#include "daemon.h"
44
5dd30d76
A
45#define SERVICE_NAME "com.apple.system.logger"
46#define SERVER_STATUS_ERROR -1
47#define SERVER_STATUS_INACTIVE 0
48#define SERVER_STATUS_ACTIVE 1
49#define SERVER_STATUS_ON_DEMAND 2
50
b16a592a 51#define DEFAULT_MARK_SEC 0
5dd30d76
A
52#define DEFAULT_UTMP_TTL_SEC 31622400
53#define DEFAULT_FS_TTL_SEC 31622400
5dd30d76
A
54#define DEFAULT_BSD_MAX_DUP_SEC 30
55#define BILLION 1000000000
b16a592a
A
56
57#define NOTIFY_DELAY 1
58
5dd30d76
A
59#define NETWORK_CHANGE_NOTIFICATION "com.apple.system.config.network_change"
60
b16a592a
A
61#define streq(A,B) (strcmp(A,B)==0)
62#define forever for(;;)
63
b16a592a 64static int reset = 0;
57b0aad2
A
65static uint64_t time_start = 0;
66static uint64_t mark_last = 0;
67static uint64_t mark_time = 0;
68static uint64_t time_last = 0;
b16a592a
A
69
70extern int __notify_78945668_info__;
5dd30d76
A
71extern int _malloc_no_asl_log;
72
57b0aad2
A
73static TAILQ_HEAD(ml, module_list) Moduleq;
74
75/* global */
76struct global_s global;
5dd30d76 77
b16a592a
A
78/* Static Modules */
79int asl_in_init();
80int asl_in_reset();
81int asl_in_close();
82static int activate_asl_in = 1;
83
84int asl_action_init();
85int asl_action_reset();
86int asl_action_close();
87static int activate_asl_action = 1;
88
89int klog_in_init();
90int klog_in_reset();
91int klog_in_close();
92static int activate_klog_in = 1;
93
94int bsd_in_init();
95int bsd_in_reset();
96int bsd_in_close();
97static int activate_bsd_in = 1;
98
99int bsd_out_init();
100int bsd_out_reset();
101int bsd_out_close();
102static int activate_bsd_out = 1;
103
57b0aad2
A
104int remote_init();
105int remote_reset();
106int remote_close();
107static int activate_remote = 0;
108
b16a592a
A
109int udp_in_init();
110int udp_in_reset();
111int udp_in_close();
5dd30d76
A
112static int activate_udp_in = 1;
113
114extern void database_server();
115extern void db_worker();
116extern void launchd_drain();
57b0aad2 117extern void bsd_flush_duplicates(time_t now);
b16a592a
A
118
119/*
120 * Module approach: only one type of module. This module may implement
121 * the set of functions necessary for any of the functions (input, output,
122 * etc.) Prior to using the modules, dlsym() is consulted to see what it
123 * implements.
124 */
125
126static int
127static_modules()
128{
129 struct module_list *tmp;
130
5dd30d76
A
131 /*
132 * The order of these initializations is important.
133 * When messages are sent to output modules, they are
134 * sent in the same order as these initializations.
135 * asl_action may add modify messages, for example to
136 * add access controls, so it must come first.
137 */
138 if (activate_asl_action != 0)
b16a592a
A
139 {
140 tmp = calloc(1, sizeof(struct module_list));
141 if (tmp == NULL) return 1;
5dd30d76
A
142
143 tmp->name = strdup("asl_action");
144 if (tmp->name == NULL)
145 {
146 free(tmp);
147 return 1;
148 }
149
b16a592a 150 tmp->module = NULL;
5dd30d76
A
151 tmp->init = asl_action_init;
152 tmp->reset = asl_action_reset;
153 tmp->close = asl_action_close;
b16a592a
A
154 TAILQ_INSERT_TAIL(&Moduleq, tmp, entries);
155 }
156
5dd30d76 157 if (activate_asl_in != 0)
b16a592a
A
158 {
159 tmp = calloc(1, sizeof(struct module_list));
160 if (tmp == NULL) return 1;
5dd30d76
A
161
162 tmp->name = strdup("asl_in");
163 if (tmp->name == NULL)
164 {
165 free(tmp);
166 return 1;
167 }
168
b16a592a 169 tmp->module = NULL;
5dd30d76
A
170 tmp->init = asl_in_init;
171 tmp->reset = asl_in_reset;
172 tmp->close = asl_in_close;
b16a592a
A
173 TAILQ_INSERT_TAIL(&Moduleq, tmp, entries);
174 }
175
176 if (activate_klog_in != 0)
177 {
178 tmp = calloc(1, sizeof(struct module_list));
179 if (tmp == NULL) return 1;
5dd30d76 180
b16a592a 181 tmp->name = strdup("klog_in");
5dd30d76
A
182 if (tmp->name == NULL)
183 {
184 free(tmp);
185 return 1;
186 }
187
b16a592a
A
188 tmp->module = NULL;
189 tmp->init = klog_in_init;
190 tmp->reset = klog_in_reset;
191 tmp->close = klog_in_close;
192 TAILQ_INSERT_TAIL(&Moduleq, tmp, entries);
193 }
194
195 if (activate_bsd_in != 0)
196 {
197 tmp = calloc(1, sizeof(struct module_list));
198 if (tmp == NULL) return 1;
5dd30d76 199
b16a592a 200 tmp->name = strdup("bsd_in");
5dd30d76
A
201 if (tmp->name == NULL)
202 {
203 free(tmp);
204 return 1;
205 }
206
b16a592a
A
207 tmp->module = NULL;
208 tmp->init = bsd_in_init;
209 tmp->reset = bsd_in_reset;
210 tmp->close = bsd_in_close;
211 TAILQ_INSERT_TAIL(&Moduleq, tmp, entries);
212 }
213
214 if (activate_bsd_out != 0)
215 {
216 tmp = calloc(1, sizeof(struct module_list));
217 if (tmp == NULL) return 1;
5dd30d76 218
b16a592a 219 tmp->name = strdup("bsd_out");
5dd30d76
A
220 if (tmp->name == NULL)
221 {
222 free(tmp);
223 return 1;
224 }
225
b16a592a
A
226 tmp->module = NULL;
227 tmp->init = bsd_out_init;
228 tmp->reset = bsd_out_reset;
229 tmp->close = bsd_out_close;
230 TAILQ_INSERT_TAIL(&Moduleq, tmp, entries);
231 }
232
57b0aad2
A
233 if (activate_remote != 0)
234 {
235 tmp = calloc(1, sizeof(struct module_list));
236 if (tmp == NULL) return 1;
237
238 tmp->name = strdup("remote");
239 if (tmp->name == NULL)
240 {
241 free(tmp);
242 return 1;
243 }
244
245 tmp->module = NULL;
246 tmp->init = remote_init;
247 tmp->reset = remote_reset;
248 tmp->close = remote_close;
249 TAILQ_INSERT_TAIL(&Moduleq, tmp, entries);
250 }
251
b16a592a
A
252 if (activate_udp_in != 0)
253 {
254 tmp = calloc(1, sizeof(struct module_list));
255 if (tmp == NULL) return 1;
5dd30d76 256
b16a592a 257 tmp->name = strdup("udp_in");
5dd30d76
A
258 if (tmp->name == NULL)
259 {
260 free(tmp);
261 return 1;
262 }
263
b16a592a
A
264 tmp->module = NULL;
265 tmp->init = udp_in_init;
266 tmp->reset = udp_in_reset;
267 tmp->close = udp_in_close;
268 TAILQ_INSERT_TAIL(&Moduleq, tmp, entries);
269 }
270
271 return 0;
272}
273
274/*
275 * Loads all the modules. This DOES NOT call the modules initializer
276 * functions. It simply scans the modules directory looking for modules
277 * and loads them. This does not mean the module will be used.
278 */
279static int
5dd30d76 280load_modules(const char *mp)
b16a592a
A
281{
282 DIR *d;
283 struct dirent *de;
284 struct module_list *tmp;
285 void *c, *bn;
286 char *modulepath = NULL;
287
288 d = opendir(mp);
289 if (d == NULL) return -1;
290
291 while (NULL != (de = readdir(d)))
292 {
293 if (de->d_name[0] == '.') continue;
294
295 /* Must have ".so" in the name" */
296 if (!strstr(de->d_name, ".so")) continue;
297
298 asprintf(&modulepath, "%s/%s", mp, de->d_name);
299 if (!modulepath) continue;
300
301 c = dlopen(modulepath, RTLD_LOCAL);
302 if (c == NULL)
303 {
304 free(modulepath);
305 continue;
306 }
307
308 tmp = calloc(1, sizeof(struct module_list));
309 if (tmp == NULL)
310 {
311 free(modulepath);
312 dlclose(c);
313 continue;
314 }
315
316 bn = basename(modulepath);
317 tmp->name = strdup(bn);
5dd30d76
A
318 if (tmp->name == NULL)
319 {
320 free(tmp);
321 return 1;
322 }
323
b16a592a
A
324 tmp->module = c;
325 TAILQ_INSERT_TAIL(&Moduleq, tmp, entries);
326
327 tmp->init = dlsym(tmp->module, "aslmod_init");
328 tmp->reset = dlsym(tmp->module, "aslmod_reset");
329 tmp->close = dlsym(tmp->module, "aslmod_close");
330
331 free(modulepath);
332 }
333
334 closedir(d);
335
336 return 0;
337}
338
339static void
340writepid(void)
341{
342 FILE *fp;
343
344 fp = fopen(_PATH_PIDFILE, "w");
345 if (fp != NULL)
346 {
347 fprintf(fp, "%d\n", getpid());
348 fclose(fp);
349 }
350}
351
352static void
353closeall(void)
354{
355 int i;
356
357 for (i = getdtablesize() - 1; i >= 0; i--) close(i);
358
359 open("/dev/null", O_RDWR, 0);
360 dup(0);
361 dup(0);
362}
363
364static void
365detach(void)
366{
367 signal(SIGINT, SIG_IGN);
368 signal(SIGPIPE, SIG_IGN);
369 setsid();
370}
371
372static void
373catch_sighup(int x)
374{
375 reset = 1;
376}
377
b16a592a
A
378static void
379send_reset(void)
380{
381 struct module_list *mod;
382
383 for (mod = Moduleq.tqh_first; mod != NULL; mod = mod->entries.tqe_next)
384 {
385 if (mod->reset != NULL) mod->reset();
386 }
387}
388
5dd30d76
A
389/*
390 * perform timed activities and set next run-loop timeout
391 */
392static void
393timed_events(struct timeval **run)
394{
57b0aad2 395 uint64_t now, delta, t;
5dd30d76 396 static struct timeval next;
5dd30d76 397
57b0aad2 398 now = time(NULL);
5dd30d76
A
399
400 *run = NULL;
401 next.tv_sec = 0;
402 next.tv_usec = 0;
403
404 if (time_start == 0)
405 {
406 /* startup */
407 time_start = now;
408 time_last = now;
409 mark_last = now;
5dd30d76
A
410 }
411
412 /*
413 * At startup, we try sending a notification once a second.
414 * Once it succeeds, we set the Libc global __notify_78945668_info__ to 0
415 * which lets Libc's localtime calculations use notifyd to invalidate
416 * cached timezones. This prevents a deadlock in localtime.
417 */
418 if (__notify_78945668_info__ < 0)
419 {
420 if (notify_post("com.apple.system.syslogd") == NOTIFY_STATUS_OK) __notify_78945668_info__ = 0;
421 else next.tv_sec = 1;
422 }
423
424 if (time_last > now)
425 {
426 /*
427 * Despite Albert Einstein's assurance, time has gone backward.
428 * Reset "last" times to current time.
429 */
430 time_last = now;
5dd30d76
A
431 mark_last = now;
432 }
433
434 /*
57b0aad2 435 * Tickle bsd_out module to flush duplicates.
5dd30d76 436 */
57b0aad2 437 if (global.bsd_flush_time > 0)
5dd30d76 438 {
57b0aad2
A
439 bsd_flush_duplicates(now);
440 if (global.bsd_flush_time > 0)
5dd30d76 441 {
57b0aad2
A
442 if (next.tv_sec == 0) next.tv_sec = global.bsd_flush_time;
443 else if (global.bsd_flush_time < next.tv_sec) next.tv_sec = global.bsd_flush_time;
5dd30d76 444 }
5dd30d76
A
445 }
446
447 /*
57b0aad2 448 * Tickle asl_store
5dd30d76 449 */
57b0aad2 450 if (global.asl_store_ping_time > 0)
5dd30d76 451 {
57b0aad2
A
452 db_ping_store(now);
453 if (global.asl_store_ping_time > 0)
5dd30d76 454 {
57b0aad2
A
455 if (next.tv_sec == 0) next.tv_sec = global.asl_store_ping_time;
456 else if (global.asl_store_ping_time < next.tv_sec) next.tv_sec = global.asl_store_ping_time;
5dd30d76
A
457 }
458 }
459
460 /*
461 * Send MARK
462 */
463 if (mark_time > 0)
464 {
465 delta = now - mark_last;
466 if (delta >= mark_time)
467 {
468 asl_mark();
469 mark_last = now;
470 t = mark_time;
471 }
472 else
473 {
474 t = mark_time - delta;
475 }
476
477 if (next.tv_sec == 0) next.tv_sec = t;
478 else if (t < next.tv_sec) next.tv_sec = t;
479 }
480
481 /*
482 * set output timeout parameter if runloop needs to have a timer
483 */
484 if (next.tv_sec > 0) *run = &next;
485
486 time_last = now;
487}
488
489void
490init_config()
491{
492 launch_data_t tmp, pdict;
493 kern_return_t status;
494
495 tmp = launch_data_new_string(LAUNCH_KEY_CHECKIN);
57b0aad2 496 global.launch_dict = launch_msg(tmp);
5dd30d76
A
497 launch_data_free(tmp);
498
57b0aad2 499 if (global.launch_dict == NULL)
5dd30d76
A
500 {
501 fprintf(stderr, "%d launchd checkin failed\n", getpid());
502 exit(1);
503 }
504
57b0aad2 505 tmp = launch_data_dict_lookup(global.launch_dict, LAUNCH_JOBKEY_MACHSERVICES);
5dd30d76
A
506 if (tmp == NULL)
507 {
508 fprintf(stderr, "%d launchd lookup of LAUNCH_JOBKEY_MACHSERVICES failed\n", getpid());
509 exit(1);
510 }
511
512 pdict = launch_data_dict_lookup(tmp, SERVICE_NAME);
513 if (pdict == NULL)
514 {
515 fprintf(stderr, "%d launchd lookup of SERVICE_NAME failed\n", getpid());
516 exit(1);
517 }
518
57b0aad2 519 global.server_port = launch_data_get_machport(pdict);
5dd30d76 520
57b0aad2 521 status = mach_port_insert_right(mach_task_self(), global.server_port, global.server_port, MACH_MSG_TYPE_MAKE_SEND);
5dd30d76
A
522 if (status != KERN_SUCCESS) fprintf(stderr, "Warning! Can't make send right for server_port: %x\n", status);
523}
524
b16a592a 525int
5dd30d76 526main(int argc, const char *argv[])
b16a592a
A
527{
528 struct module_list *mod;
d7fa0660 529 fd_set rd, wr, ex, kern;
5dd30d76
A
530 int32_t fd, i, max, status, daemonize;
531 const char *mp;
532 struct timeval *runloop_timer, zto;
533 pthread_attr_t attr;
534 pthread_t t;
535 int nctoken;
5dd30d76
A
536 char tstr[32];
537 time_t now;
b16a592a 538
57b0aad2
A
539 memset(&global, 0, sizeof(struct global_s));
540
541 global.asl_log_filter = ASL_FILTER_MASK_UPTO(ASL_LEVEL_NOTICE);
542 global.db_file_max = 16384000;
543 global.db_memory_max = 8192;
544 global.db_mini_max = 256;
545 global.bsd_max_dup_time = DEFAULT_BSD_MAX_DUP_SEC;
546 global.utmp_ttl = DEFAULT_UTMP_TTL_SEC;
547 global.fs_ttl = DEFAULT_FS_TTL_SEC;
548 global.kfd = -1;
549
550#ifdef CONFIG_MAC
551 global.dbtype = DB_TYPE_FILE;
552 global.db_file_max = 25600000;
553 global.asl_store_ping_time = 150;
554#endif
555
556#ifdef CONFIG_APPLETV
557 global.dbtype = DB_TYPE_FILE;
558 global.db_file_max = 10240000;
559#endif
560
561#ifdef CONFIG_IPHONE
562 global.dbtype = DB_TYPE_MINI;
563 activate_remote = 1;
564 activate_bsd_out = 0;
565#endif
566
b16a592a 567 mp = _PATH_MODULE_LIB;
b16a592a
A
568 daemonize = 0;
569 __notify_78945668_info__ = -1;
d7fa0660
A
570 zto.tv_sec = 0;
571 zto.tv_usec = 0;
572 FD_ZERO(&kern);
5dd30d76 573
57b0aad2
A
574 /* prevent malloc from calling ASL on error */
575 _malloc_no_asl_log = 1;
5dd30d76 576
57b0aad2
A
577 /* first pass sets up default configurations */
578 for (i = 1; i < argc; i++)
579 {
580 if (streq(argv[i], "-config"))
581 {
582 if (((i + 1) < argc) && (argv[i+1][0] != '-'))
583 {
584 i++;
585 if (streq(argv[i], "mac"))
586 {
587 global.dbtype = DB_TYPE_FILE;
588 global.db_file_max = 25600000;
589 }
590 else if (streq(argv[i], "appletv"))
591 {
592 global.dbtype = DB_TYPE_FILE;
593 global.db_file_max = 10240000;
594 }
595 else if (streq(argv[i], "iphone"))
596 {
597 global.dbtype = DB_TYPE_MINI;
598 activate_remote = 1;
599 }
600 }
601 }
602 }
b16a592a
A
603
604 for (i = 1; i < argc; i++)
605 {
606 if (streq(argv[i], "-d"))
607 {
57b0aad2
A
608 global.debug = 1;
609 if (((i+1) < argc) && (argv[i+1][0] != '-')) global.debug_file = argv[++i];
5dd30d76
A
610 memset(tstr, 0, sizeof(tstr));
611 now = time(NULL);
612 ctime_r(&now, tstr);
613 tstr[19] = '\0';
614 asldebug("%s syslogd[%d]: Start\n", tstr, getpid());
b16a592a 615 }
57b0aad2
A
616 else if (streq(argv[i], "-db"))
617 {
618 if (((i + 1) < argc) && (argv[i+1][0] != '-'))
619 {
620 i++;
621 if (streq(argv[i], "file"))
622 {
623 global.dbtype |= DB_TYPE_FILE;
624 if (((i + 1) < argc) && (argv[i+1][0] != '-')) global.db_file_max = atol(argv[++i]);
625 }
626 else if (streq(argv[i], "memory"))
627 {
628 global.dbtype |= DB_TYPE_MEMORY;
629 if (((i + 1) < argc) && (argv[i+1][0] != '-')) global.db_memory_max = atol(argv[++i]);
630 }
631 else if (streq(argv[i], "mini"))
632 {
633 global.dbtype |= DB_TYPE_MINI;
634 if (((i + 1) < argc) && (argv[i+1][0] != '-')) global.db_mini_max = atol(argv[++i]);
635 }
636 }
637 }
5dd30d76 638 else if (streq(argv[i], "-D"))
b16a592a
A
639 {
640 daemonize = 1;
641 }
5dd30d76 642 else if (streq(argv[i], "-m"))
b16a592a 643 {
5dd30d76 644 if ((i + 1) < argc) mark_time = 60 * atoll(argv[++i]);
b16a592a 645 }
5dd30d76 646 else if (streq(argv[i], "-utmp_ttl"))
b16a592a 647 {
57b0aad2 648 if ((i + 1) < argc) global.utmp_ttl = atol(argv[++i]);
b16a592a 649 }
5dd30d76 650 else if (streq(argv[i], "-fs_ttl"))
b16a592a 651 {
57b0aad2 652 if ((i + 1) < argc) global.fs_ttl = atol(argv[++i]);
b16a592a
A
653 }
654 else if (streq(argv[i], "-l"))
655 {
656 if ((i + 1) < argc) mp = argv[++i];
657 }
658 else if (streq(argv[i], "-c"))
659 {
660 if ((i + 1) < argc)
661 {
662 i++;
57b0aad2 663 if ((argv[i][0] >= '0') && (argv[i][0] <= '7') && (argv[i][1] == '\0')) global.asl_log_filter = ASL_FILTER_MASK_UPTO(atoi(argv[i]));
b16a592a
A
664 }
665 }
5dd30d76
A
666 else if (streq(argv[i], "-dup_delay"))
667 {
57b0aad2 668 if ((i + 1) < argc) global.bsd_max_dup_time = atoll(argv[++i]);
5dd30d76 669 }
b16a592a
A
670 else if (streq(argv[i], "-asl_in"))
671 {
672 if ((i + 1) < argc) activate_asl_in = atoi(argv[++i]);
673 }
674 else if (streq(argv[i], "-asl_action"))
675 {
676 if ((i + 1) < argc) activate_asl_action = atoi(argv[++i]);
677 }
678 else if (streq(argv[i], "-klog_in"))
679 {
680 if ((i + 1) < argc) activate_klog_in = atoi(argv[++i]);
681 }
682 else if (streq(argv[i], "-bsd_in"))
683 {
684 if ((i + 1) < argc) activate_bsd_in = atoi(argv[++i]);
685 }
686 else if (streq(argv[i], "-bsd_out"))
687 {
688 if ((i + 1) < argc) activate_bsd_out = atoi(argv[++i]);
689 }
57b0aad2
A
690 else if (streq(argv[i], "-remote"))
691 {
692 if ((i + 1) < argc) activate_remote = atoi(argv[++i]);
693 }
b16a592a
A
694 else if (streq(argv[i], "-udp_in"))
695 {
696 if ((i + 1) < argc) activate_udp_in = atoi(argv[++i]);
697 }
698 }
699
57b0aad2 700 if (global.dbtype == 0) global.dbtype = DB_TYPE_FILE;
5dd30d76 701
b16a592a
A
702 TAILQ_INIT(&Moduleq);
703 static_modules();
704 load_modules(mp);
705 aslevent_init();
706
57b0aad2 707 if (global.debug == 0)
b16a592a
A
708 {
709 if (daemonize != 0)
710 {
711 if (fork() != 0) exit(0);
d7fa0660 712
b16a592a
A
713 detach();
714 closeall();
715 }
716
717 writepid();
718 }
719
5dd30d76
A
720 init_config();
721
b16a592a 722 signal(SIGHUP, catch_sighup);
b16a592a 723
5dd30d76
A
724 nctoken = -1;
725 notify_register_signal(NETWORK_CHANGE_NOTIFICATION, SIGHUP, &nctoken);
b16a592a
A
726
727 for (mod = Moduleq.tqh_first; mod != NULL; mod = mod->entries.tqe_next)
728 {
729 fd = mod->init();
730 if (fd < 0) continue;
731 }
732
5dd30d76
A
733 /*
734 * Start database server thread
735 */
736 pthread_attr_init(&attr);
737 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
738 pthread_create(&t, &attr, (void *(*)(void *))database_server, NULL);
739 pthread_attr_destroy(&attr);
b16a592a 740
5dd30d76
A
741 /*
742 * Start database worker thread
743 */
744 pthread_attr_init(&attr);
745 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
746 pthread_create(&t, &attr, (void *(*)(void *))db_worker, NULL);
747 pthread_attr_destroy(&attr);
b16a592a 748
5dd30d76
A
749 FD_ZERO(&rd);
750 FD_ZERO(&wr);
751 FD_ZERO(&ex);
d7fa0660
A
752
753 /*
754 * drain /dev/klog first
755 */
57b0aad2 756 if (global.kfd >= 0)
d7fa0660 757 {
57b0aad2 758 max = global.kfd + 1;
d7fa0660
A
759 while (select(max, &kern, NULL, NULL, &zto) > 0)
760 {
5dd30d76 761 aslevent_handleevent(&kern, &wr, &ex);
d7fa0660
A
762 }
763 }
5dd30d76
A
764
765 /*
766 * Start launchd drain thread
767 */
768 pthread_attr_init(&attr);
769 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
770 pthread_create(&t, &attr, (void *(*)(void *))launchd_drain, NULL);
771 pthread_attr_destroy(&attr);
772
773 runloop_timer = NULL;
774 timed_events(&runloop_timer);
775
b16a592a
A
776 forever
777 {
d7fa0660 778 max = aslevent_fdsets(&rd, &wr, &ex) + 1;
b16a592a 779
5dd30d76 780 status = select(max, &rd, &wr, &ex, runloop_timer);
57b0aad2 781 if ((global.kfd >= 0) && FD_ISSET(global.kfd, &rd))
d7fa0660 782 {
5dd30d76 783 /* drain /dev/klog */
57b0aad2 784 max = global.kfd + 1;
d7fa0660
A
785
786 while (select(max, &kern, NULL, NULL, &zto) > 0)
787 {
5dd30d76 788 aslevent_handleevent(&kern, &wr, &ex);
d7fa0660
A
789 }
790 }
b16a592a
A
791
792 if (reset != 0)
793 {
794 send_reset();
795 reset = 0;
796 }
797
5dd30d76 798 if (status != 0) aslevent_handleevent(&rd, &wr, &ex);
b16a592a 799
5dd30d76 800 timed_events(&runloop_timer);
b16a592a
A
801 }
802}