]> git.saurik.com Git - apple/syslog.git/blame - syslogd.tproj/syslogd.c
syslog-100.2.tar.gz
[apple/syslog.git] / syslogd.tproj / syslogd.c
CommitLineData
b16a592a 1/*
c4fdb7d1 2 * Copyright (c) 2004-2009 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 54#define DEFAULT_BSD_MAX_DUP_SEC 30
c4fdb7d1 55#define DEFAULT_MPS_LIMIT 500
5dd30d76 56#define BILLION 1000000000
b16a592a
A
57
58#define NOTIFY_DELAY 1
59
5dd30d76
A
60#define NETWORK_CHANGE_NOTIFICATION "com.apple.system.config.network_change"
61
b16a592a
A
62#define streq(A,B) (strcmp(A,B)==0)
63#define forever for(;;)
64
57b0aad2
A
65static uint64_t time_start = 0;
66static uint64_t mark_last = 0;
c4fdb7d1 67static uint64_t ping_last = 0;
57b0aad2 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();
c4fdb7d1 115extern void output_worker();
5dd30d76 116extern void launchd_drain();
57b0aad2 117extern void bsd_flush_duplicates(time_t now);
c4fdb7d1 118extern void bsd_close_idle_files(time_t now);
b16a592a
A
119
120/*
121 * Module approach: only one type of module. This module may implement
122 * the set of functions necessary for any of the functions (input, output,
123 * etc.) Prior to using the modules, dlsym() is consulted to see what it
124 * implements.
125 */
126
127static int
128static_modules()
129{
130 struct module_list *tmp;
131
5dd30d76
A
132 /*
133 * The order of these initializations is important.
134 * When messages are sent to output modules, they are
135 * sent in the same order as these initializations.
136 * asl_action may add modify messages, for example to
137 * add access controls, so it must come first.
138 */
139 if (activate_asl_action != 0)
b16a592a
A
140 {
141 tmp = calloc(1, sizeof(struct module_list));
142 if (tmp == NULL) return 1;
5dd30d76
A
143
144 tmp->name = strdup("asl_action");
145 if (tmp->name == NULL)
146 {
147 free(tmp);
148 return 1;
149 }
150
b16a592a 151 tmp->module = NULL;
5dd30d76
A
152 tmp->init = asl_action_init;
153 tmp->reset = asl_action_reset;
154 tmp->close = asl_action_close;
b16a592a
A
155 TAILQ_INSERT_TAIL(&Moduleq, tmp, entries);
156 }
157
5dd30d76 158 if (activate_asl_in != 0)
b16a592a
A
159 {
160 tmp = calloc(1, sizeof(struct module_list));
161 if (tmp == NULL) return 1;
5dd30d76
A
162
163 tmp->name = strdup("asl_in");
164 if (tmp->name == NULL)
165 {
166 free(tmp);
167 return 1;
168 }
169
b16a592a 170 tmp->module = NULL;
5dd30d76
A
171 tmp->init = asl_in_init;
172 tmp->reset = asl_in_reset;
173 tmp->close = asl_in_close;
b16a592a
A
174 TAILQ_INSERT_TAIL(&Moduleq, tmp, entries);
175 }
176
177 if (activate_klog_in != 0)
178 {
179 tmp = calloc(1, sizeof(struct module_list));
180 if (tmp == NULL) return 1;
5dd30d76 181
b16a592a 182 tmp->name = strdup("klog_in");
5dd30d76
A
183 if (tmp->name == NULL)
184 {
185 free(tmp);
186 return 1;
187 }
188
b16a592a
A
189 tmp->module = NULL;
190 tmp->init = klog_in_init;
191 tmp->reset = klog_in_reset;
192 tmp->close = klog_in_close;
193 TAILQ_INSERT_TAIL(&Moduleq, tmp, entries);
194 }
195
196 if (activate_bsd_in != 0)
197 {
198 tmp = calloc(1, sizeof(struct module_list));
199 if (tmp == NULL) return 1;
5dd30d76 200
b16a592a 201 tmp->name = strdup("bsd_in");
5dd30d76
A
202 if (tmp->name == NULL)
203 {
204 free(tmp);
205 return 1;
206 }
207
b16a592a
A
208 tmp->module = NULL;
209 tmp->init = bsd_in_init;
210 tmp->reset = bsd_in_reset;
211 tmp->close = bsd_in_close;
212 TAILQ_INSERT_TAIL(&Moduleq, tmp, entries);
213 }
214
215 if (activate_bsd_out != 0)
216 {
217 tmp = calloc(1, sizeof(struct module_list));
218 if (tmp == NULL) return 1;
5dd30d76 219
b16a592a 220 tmp->name = strdup("bsd_out");
5dd30d76
A
221 if (tmp->name == NULL)
222 {
223 free(tmp);
224 return 1;
225 }
226
b16a592a
A
227 tmp->module = NULL;
228 tmp->init = bsd_out_init;
229 tmp->reset = bsd_out_reset;
230 tmp->close = bsd_out_close;
231 TAILQ_INSERT_TAIL(&Moduleq, tmp, entries);
232 }
233
57b0aad2
A
234 if (activate_remote != 0)
235 {
236 tmp = calloc(1, sizeof(struct module_list));
237 if (tmp == NULL) return 1;
238
239 tmp->name = strdup("remote");
240 if (tmp->name == NULL)
241 {
242 free(tmp);
243 return 1;
244 }
245
246 tmp->module = NULL;
247 tmp->init = remote_init;
248 tmp->reset = remote_reset;
249 tmp->close = remote_close;
250 TAILQ_INSERT_TAIL(&Moduleq, tmp, entries);
251 }
252
b16a592a
A
253 if (activate_udp_in != 0)
254 {
255 tmp = calloc(1, sizeof(struct module_list));
256 if (tmp == NULL) return 1;
5dd30d76 257
b16a592a 258 tmp->name = strdup("udp_in");
5dd30d76
A
259 if (tmp->name == NULL)
260 {
261 free(tmp);
262 return 1;
263 }
264
b16a592a
A
265 tmp->module = NULL;
266 tmp->init = udp_in_init;
267 tmp->reset = udp_in_reset;
268 tmp->close = udp_in_close;
269 TAILQ_INSERT_TAIL(&Moduleq, tmp, entries);
270 }
271
272 return 0;
273}
274
275/*
276 * Loads all the modules. This DOES NOT call the modules initializer
277 * functions. It simply scans the modules directory looking for modules
278 * and loads them. This does not mean the module will be used.
279 */
280static int
5dd30d76 281load_modules(const char *mp)
b16a592a
A
282{
283 DIR *d;
284 struct dirent *de;
285 struct module_list *tmp;
286 void *c, *bn;
287 char *modulepath = NULL;
288
289 d = opendir(mp);
290 if (d == NULL) return -1;
291
292 while (NULL != (de = readdir(d)))
293 {
294 if (de->d_name[0] == '.') continue;
295
296 /* Must have ".so" in the name" */
297 if (!strstr(de->d_name, ".so")) continue;
298
299 asprintf(&modulepath, "%s/%s", mp, de->d_name);
300 if (!modulepath) continue;
301
302 c = dlopen(modulepath, RTLD_LOCAL);
303 if (c == NULL)
304 {
305 free(modulepath);
306 continue;
307 }
308
309 tmp = calloc(1, sizeof(struct module_list));
310 if (tmp == NULL)
311 {
312 free(modulepath);
313 dlclose(c);
314 continue;
315 }
316
317 bn = basename(modulepath);
318 tmp->name = strdup(bn);
5dd30d76
A
319 if (tmp->name == NULL)
320 {
321 free(tmp);
322 return 1;
323 }
324
b16a592a
A
325 tmp->module = c;
326 TAILQ_INSERT_TAIL(&Moduleq, tmp, entries);
327
328 tmp->init = dlsym(tmp->module, "aslmod_init");
329 tmp->reset = dlsym(tmp->module, "aslmod_reset");
330 tmp->close = dlsym(tmp->module, "aslmod_close");
331
332 free(modulepath);
333 }
334
335 closedir(d);
336
337 return 0;
338}
339
340static void
341writepid(void)
342{
343 FILE *fp;
344
345 fp = fopen(_PATH_PIDFILE, "w");
346 if (fp != NULL)
347 {
348 fprintf(fp, "%d\n", getpid());
349 fclose(fp);
350 }
351}
352
353static void
354closeall(void)
355{
356 int i;
357
358 for (i = getdtablesize() - 1; i >= 0; i--) close(i);
359
360 open("/dev/null", O_RDWR, 0);
361 dup(0);
362 dup(0);
363}
364
365static void
366detach(void)
367{
368 signal(SIGINT, SIG_IGN);
369 signal(SIGPIPE, SIG_IGN);
370 setsid();
371}
372
373static void
374catch_sighup(int x)
375{
c4fdb7d1
A
376 global.reset = RESET_CONFIG;
377}
378
379static void
380catch_siginfo(int x)
381{
382 global.reset = RESET_NETWORK;
b16a592a
A
383}
384
b16a592a
A
385static void
386send_reset(void)
387{
388 struct module_list *mod;
389
390 for (mod = Moduleq.tqh_first; mod != NULL; mod = mod->entries.tqe_next)
391 {
392 if (mod->reset != NULL) mod->reset();
393 }
394}
395
5dd30d76
A
396/*
397 * perform timed activities and set next run-loop timeout
398 */
399static void
400timed_events(struct timeval **run)
401{
c4fdb7d1 402 time_t now, delta, t;
5dd30d76 403 static struct timeval next;
5dd30d76 404
57b0aad2 405 now = time(NULL);
5dd30d76
A
406
407 *run = NULL;
408 next.tv_sec = 0;
409 next.tv_usec = 0;
410
411 if (time_start == 0)
412 {
413 /* startup */
414 time_start = now;
415 time_last = now;
416 mark_last = now;
c4fdb7d1 417 ping_last = now;
5dd30d76
A
418 }
419
420 /*
421 * At startup, we try sending a notification once a second.
422 * Once it succeeds, we set the Libc global __notify_78945668_info__ to 0
423 * which lets Libc's localtime calculations use notifyd to invalidate
424 * cached timezones. This prevents a deadlock in localtime.
425 */
426 if (__notify_78945668_info__ < 0)
427 {
428 if (notify_post("com.apple.system.syslogd") == NOTIFY_STATUS_OK) __notify_78945668_info__ = 0;
429 else next.tv_sec = 1;
430 }
431
432 if (time_last > now)
433 {
434 /*
435 * Despite Albert Einstein's assurance, time has gone backward.
436 * Reset "last" times to current time.
437 */
438 time_last = now;
5dd30d76 439 mark_last = now;
c4fdb7d1 440 ping_last = now;
5dd30d76
A
441 }
442
443 /*
57b0aad2 444 * Tickle bsd_out module to flush duplicates.
5dd30d76 445 */
57b0aad2 446 if (global.bsd_flush_time > 0)
5dd30d76 447 {
57b0aad2 448 bsd_flush_duplicates(now);
c4fdb7d1 449 bsd_close_idle_files(now);
57b0aad2 450 if (global.bsd_flush_time > 0)
5dd30d76 451 {
57b0aad2
A
452 if (next.tv_sec == 0) next.tv_sec = global.bsd_flush_time;
453 else if (global.bsd_flush_time < next.tv_sec) next.tv_sec = global.bsd_flush_time;
5dd30d76 454 }
5dd30d76
A
455 }
456
457 /*
c4fdb7d1 458 * Tickle asl_store to sweep file cache
5dd30d76 459 */
57b0aad2 460 if (global.asl_store_ping_time > 0)
5dd30d76 461 {
c4fdb7d1
A
462 delta = now - ping_last;
463 if (delta >= global.asl_store_ping_time)
5dd30d76 464 {
c4fdb7d1
A
465 db_ping_store();
466 bsd_close_idle_files(now);
467 ping_last = now;
468 t = global.asl_store_ping_time;
5dd30d76 469 }
c4fdb7d1
A
470 else
471 {
472 t = global.asl_store_ping_time - delta;
473 }
474
475 if (next.tv_sec == 0) next.tv_sec = t;
476 else if (t < next.tv_sec) next.tv_sec = t;
5dd30d76
A
477 }
478
479 /*
480 * Send MARK
481 */
c4fdb7d1 482 if (global.mark_time > 0)
5dd30d76
A
483 {
484 delta = now - mark_last;
c4fdb7d1 485 if (delta >= global.mark_time)
5dd30d76
A
486 {
487 asl_mark();
488 mark_last = now;
c4fdb7d1 489 t = global.mark_time;
5dd30d76
A
490 }
491 else
492 {
c4fdb7d1 493 t = global.mark_time - delta;
5dd30d76
A
494 }
495
496 if (next.tv_sec == 0) next.tv_sec = t;
497 else if (t < next.tv_sec) next.tv_sec = t;
498 }
499
500 /*
501 * set output timeout parameter if runloop needs to have a timer
502 */
503 if (next.tv_sec > 0) *run = &next;
504
505 time_last = now;
506}
507
508void
509init_config()
510{
511 launch_data_t tmp, pdict;
512 kern_return_t status;
513
514 tmp = launch_data_new_string(LAUNCH_KEY_CHECKIN);
57b0aad2 515 global.launch_dict = launch_msg(tmp);
5dd30d76
A
516 launch_data_free(tmp);
517
57b0aad2 518 if (global.launch_dict == NULL)
5dd30d76
A
519 {
520 fprintf(stderr, "%d launchd checkin failed\n", getpid());
521 exit(1);
522 }
523
57b0aad2 524 tmp = launch_data_dict_lookup(global.launch_dict, LAUNCH_JOBKEY_MACHSERVICES);
5dd30d76
A
525 if (tmp == NULL)
526 {
527 fprintf(stderr, "%d launchd lookup of LAUNCH_JOBKEY_MACHSERVICES failed\n", getpid());
528 exit(1);
529 }
530
531 pdict = launch_data_dict_lookup(tmp, SERVICE_NAME);
532 if (pdict == NULL)
533 {
534 fprintf(stderr, "%d launchd lookup of SERVICE_NAME failed\n", getpid());
535 exit(1);
536 }
537
57b0aad2 538 global.server_port = launch_data_get_machport(pdict);
5dd30d76 539
c4fdb7d1
A
540 /* port for receiving internal messages */
541 status = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &(global.self_port));
542 if (status != KERN_SUCCESS)
543 {
544 fprintf(stderr, "mach_port_allocate self_port failed: %d", status);
545 exit(1);
546 }
547
548 status = mach_port_insert_right(mach_task_self(), global.self_port, global.self_port, MACH_MSG_TYPE_MAKE_SEND);
549 if (status != KERN_SUCCESS)
550 {
551 fprintf(stderr, "Can't make send right for self_port: %d\n", status);
552 exit(1);
553 }
554
555 /* port for receiving MACH_NOTIFY_DEAD_NAME notifications */
556 status = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &(global.dead_session_port));
557 if (status != KERN_SUCCESS)
558 {
559 fprintf(stderr, "mach_port_allocate dead_session_port failed: %d", status);
560 exit(1);
561 }
562
563 status = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_PORT_SET, &(global.listen_set));
564 if (status != KERN_SUCCESS)
565 {
566 fprintf(stderr, "mach_port_allocate listen_set failed: %d", status);
567 exit(1);
568 }
569
570 status = mach_port_move_member(mach_task_self(), global.server_port, global.listen_set);
571 if (status != KERN_SUCCESS)
572 {
573 fprintf(stderr, "mach_port_move_member server_port failed: %d", status);
574 exit(1);
575 }
576
577 status = mach_port_move_member(mach_task_self(), global.self_port, global.listen_set);
578 if (status != KERN_SUCCESS)
579 {
580 fprintf(stderr, "mach_port_move_member self_port failed: %d", status);
581 exit(1);
582 }
583
584 status = mach_port_move_member(mach_task_self(), global.dead_session_port, global.listen_set);
585 if (status != KERN_SUCCESS)
586 {
587 fprintf(stderr, "mach_port_move_member dead_session_port failed (%u)", status);
588 exit(1);
589 }
590}
591
592void
593config_debug(int enable, const char *path)
594{
595 OSSpinLockLock(&global.lock);
596
597 global.debug = enable;
598 if (global.debug_file != NULL) free(global.debug_file);
599 global.debug_file = strdup(path);
600
601 OSSpinLockUnlock(&global.lock);
602}
603
604void
605config_data_store(int type, uint32_t file_max, uint32_t memory_max, uint32_t mini_max)
606{
607 pthread_mutex_lock(global.db_lock);
608
609 if (global.dbtype & DB_TYPE_FILE)
610 {
611 asl_store_close(global.file_db);
612 global.file_db = NULL;
613 }
614
615 if (global.dbtype & DB_TYPE_MEMORY)
616 {
617 asl_memory_close(global.memory_db);
618 global.memory_db = NULL;
619 }
620
621 if (global.dbtype & DB_TYPE_MINI)
622 {
623 asl_mini_memory_close(global.mini_db);
624 global.mini_db = NULL;
625 }
626
627 global.dbtype = type;
628 global.db_file_max = file_max;
629 global.db_memory_max = memory_max;
630 global.db_mini_max = mini_max;
631
632 pthread_mutex_unlock(global.db_lock);
5dd30d76
A
633}
634
b16a592a 635int
5dd30d76 636main(int argc, const char *argv[])
b16a592a
A
637{
638 struct module_list *mod;
d7fa0660 639 fd_set rd, wr, ex, kern;
5dd30d76
A
640 int32_t fd, i, max, status, daemonize;
641 const char *mp;
642 struct timeval *runloop_timer, zto;
643 pthread_attr_t attr;
644 pthread_t t;
c4fdb7d1 645 int network_change_token;
5dd30d76
A
646 char tstr[32];
647 time_t now;
b16a592a 648
57b0aad2
A
649 memset(&global, 0, sizeof(struct global_s));
650
c4fdb7d1
A
651 global.db_lock = (pthread_mutex_t *)calloc(1, sizeof(pthread_mutex_t));
652 pthread_mutex_init(global.db_lock, NULL);
653
654 global.work_queue_lock = (pthread_mutex_t *)calloc(1, sizeof(pthread_mutex_t));
655 pthread_mutex_init(global.work_queue_lock, NULL);
656
657 pthread_cond_init(&global.work_queue_cond, NULL);
658
659 global.work_queue = (asl_search_result_t *)calloc(1, sizeof(asl_search_result_t));
660
661 global.asl_log_filter = ASL_FILTER_MASK_UPTO(ASL_LEVEL_DEBUG);
57b0aad2
A
662 global.db_file_max = 16384000;
663 global.db_memory_max = 8192;
664 global.db_mini_max = 256;
665 global.bsd_max_dup_time = DEFAULT_BSD_MAX_DUP_SEC;
666 global.utmp_ttl = DEFAULT_UTMP_TTL_SEC;
667 global.fs_ttl = DEFAULT_FS_TTL_SEC;
c4fdb7d1 668 global.mps_limit = DEFAULT_MPS_LIMIT;
57b0aad2
A
669 global.kfd = -1;
670
671#ifdef CONFIG_MAC
672 global.dbtype = DB_TYPE_FILE;
673 global.db_file_max = 25600000;
674 global.asl_store_ping_time = 150;
675#endif
c4fdb7d1 676
57b0aad2
A
677#ifdef CONFIG_APPLETV
678 global.dbtype = DB_TYPE_FILE;
679 global.db_file_max = 10240000;
c4fdb7d1 680 global.asl_store_ping_time = 150;
57b0aad2
A
681#endif
682
683#ifdef CONFIG_IPHONE
684 global.dbtype = DB_TYPE_MINI;
685 activate_remote = 1;
686 activate_bsd_out = 0;
687#endif
c4fdb7d1 688
b16a592a 689 mp = _PATH_MODULE_LIB;
b16a592a 690 daemonize = 0;
c4fdb7d1 691 __notify_78945668_info__ = 0xf0000000;
d7fa0660
A
692 zto.tv_sec = 0;
693 zto.tv_usec = 0;
5dd30d76 694
57b0aad2
A
695 /* prevent malloc from calling ASL on error */
696 _malloc_no_asl_log = 1;
5dd30d76 697
57b0aad2
A
698 /* first pass sets up default configurations */
699 for (i = 1; i < argc; i++)
700 {
701 if (streq(argv[i], "-config"))
702 {
703 if (((i + 1) < argc) && (argv[i+1][0] != '-'))
704 {
705 i++;
706 if (streq(argv[i], "mac"))
707 {
708 global.dbtype = DB_TYPE_FILE;
709 global.db_file_max = 25600000;
710 }
711 else if (streq(argv[i], "appletv"))
712 {
713 global.dbtype = DB_TYPE_FILE;
714 global.db_file_max = 10240000;
715 }
716 else if (streq(argv[i], "iphone"))
717 {
718 global.dbtype = DB_TYPE_MINI;
719 activate_remote = 1;
720 }
721 }
722 }
723 }
b16a592a
A
724
725 for (i = 1; i < argc; i++)
726 {
727 if (streq(argv[i], "-d"))
728 {
57b0aad2 729 global.debug = 1;
c4fdb7d1 730 if (((i+1) < argc) && (argv[i+1][0] != '-')) global.debug_file = strdup(argv[++i]);
5dd30d76
A
731 memset(tstr, 0, sizeof(tstr));
732 now = time(NULL);
733 ctime_r(&now, tstr);
734 tstr[19] = '\0';
735 asldebug("%s syslogd[%d]: Start\n", tstr, getpid());
b16a592a 736 }
57b0aad2
A
737 else if (streq(argv[i], "-db"))
738 {
739 if (((i + 1) < argc) && (argv[i+1][0] != '-'))
740 {
741 i++;
742 if (streq(argv[i], "file"))
743 {
744 global.dbtype |= DB_TYPE_FILE;
745 if (((i + 1) < argc) && (argv[i+1][0] != '-')) global.db_file_max = atol(argv[++i]);
746 }
747 else if (streq(argv[i], "memory"))
748 {
749 global.dbtype |= DB_TYPE_MEMORY;
750 if (((i + 1) < argc) && (argv[i+1][0] != '-')) global.db_memory_max = atol(argv[++i]);
751 }
752 else if (streq(argv[i], "mini"))
753 {
754 global.dbtype |= DB_TYPE_MINI;
755 if (((i + 1) < argc) && (argv[i+1][0] != '-')) global.db_mini_max = atol(argv[++i]);
756 }
757 }
758 }
5dd30d76 759 else if (streq(argv[i], "-D"))
b16a592a
A
760 {
761 daemonize = 1;
762 }
5dd30d76 763 else if (streq(argv[i], "-m"))
b16a592a 764 {
c4fdb7d1 765 if ((i + 1) < argc) global.mark_time = 60 * atoll(argv[++i]);
b16a592a 766 }
5dd30d76 767 else if (streq(argv[i], "-utmp_ttl"))
b16a592a 768 {
57b0aad2 769 if ((i + 1) < argc) global.utmp_ttl = atol(argv[++i]);
b16a592a 770 }
5dd30d76 771 else if (streq(argv[i], "-fs_ttl"))
b16a592a 772 {
57b0aad2 773 if ((i + 1) < argc) global.fs_ttl = atol(argv[++i]);
b16a592a 774 }
c4fdb7d1
A
775 else if (streq(argv[i], "-mps_limit"))
776 {
777 if ((i + 1) < argc) global.mps_limit = atol(argv[++i]);
778 }
b16a592a
A
779 else if (streq(argv[i], "-l"))
780 {
781 if ((i + 1) < argc) mp = argv[++i];
782 }
783 else if (streq(argv[i], "-c"))
784 {
785 if ((i + 1) < argc)
786 {
787 i++;
57b0aad2 788 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
789 }
790 }
5dd30d76
A
791 else if (streq(argv[i], "-dup_delay"))
792 {
57b0aad2 793 if ((i + 1) < argc) global.bsd_max_dup_time = atoll(argv[++i]);
5dd30d76 794 }
b16a592a
A
795 else if (streq(argv[i], "-asl_in"))
796 {
797 if ((i + 1) < argc) activate_asl_in = atoi(argv[++i]);
798 }
799 else if (streq(argv[i], "-asl_action"))
800 {
801 if ((i + 1) < argc) activate_asl_action = atoi(argv[++i]);
802 }
803 else if (streq(argv[i], "-klog_in"))
804 {
805 if ((i + 1) < argc) activate_klog_in = atoi(argv[++i]);
806 }
807 else if (streq(argv[i], "-bsd_in"))
808 {
809 if ((i + 1) < argc) activate_bsd_in = atoi(argv[++i]);
810 }
811 else if (streq(argv[i], "-bsd_out"))
812 {
813 if ((i + 1) < argc) activate_bsd_out = atoi(argv[++i]);
814 }
57b0aad2
A
815 else if (streq(argv[i], "-remote"))
816 {
817 if ((i + 1) < argc) activate_remote = atoi(argv[++i]);
818 }
b16a592a
A
819 else if (streq(argv[i], "-udp_in"))
820 {
821 if ((i + 1) < argc) activate_udp_in = atoi(argv[++i]);
822 }
823 }
824
c4fdb7d1
A
825 if (global.dbtype == 0)
826 {
827 global.dbtype = DB_TYPE_FILE;
828 global.db_file_max = 25600000;
829 global.asl_store_ping_time = 150;
830 }
5dd30d76 831
b16a592a
A
832 TAILQ_INIT(&Moduleq);
833 static_modules();
834 load_modules(mp);
835 aslevent_init();
836
57b0aad2 837 if (global.debug == 0)
b16a592a
A
838 {
839 if (daemonize != 0)
840 {
841 if (fork() != 0) exit(0);
d7fa0660 842
b16a592a
A
843 detach();
844 closeall();
845 }
846
847 writepid();
848 }
849
5dd30d76
A
850 init_config();
851
b16a592a 852 signal(SIGHUP, catch_sighup);
c4fdb7d1 853 signal(SIGINFO, catch_siginfo);
b16a592a 854
c4fdb7d1
A
855 /* register for network change notifications if the udp_in module is active */
856 network_change_token = -1;
857 if (activate_udp_in != 0) notify_register_signal(NETWORK_CHANGE_NOTIFICATION, SIGINFO, &network_change_token);
b16a592a
A
858
859 for (mod = Moduleq.tqh_first; mod != NULL; mod = mod->entries.tqe_next)
860 {
861 fd = mod->init();
862 if (fd < 0) continue;
863 }
864
5dd30d76
A
865 /*
866 * Start database server thread
867 */
868 pthread_attr_init(&attr);
869 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
870 pthread_create(&t, &attr, (void *(*)(void *))database_server, NULL);
871 pthread_attr_destroy(&attr);
b16a592a 872
5dd30d76 873 /*
c4fdb7d1 874 * Start output worker thread
5dd30d76
A
875 */
876 pthread_attr_init(&attr);
877 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
c4fdb7d1 878 pthread_create(&t, &attr, (void *(*)(void *))output_worker, NULL);
5dd30d76 879 pthread_attr_destroy(&attr);
b16a592a 880
5dd30d76
A
881 FD_ZERO(&rd);
882 FD_ZERO(&wr);
883 FD_ZERO(&ex);
d7fa0660
A
884
885 /*
886 * drain /dev/klog first
887 */
57b0aad2 888 if (global.kfd >= 0)
d7fa0660 889 {
c4fdb7d1
A
890 FD_ZERO(&kern);
891 FD_SET(global.kfd, &kern);
57b0aad2 892 max = global.kfd + 1;
d7fa0660
A
893 while (select(max, &kern, NULL, NULL, &zto) > 0)
894 {
5dd30d76 895 aslevent_handleevent(&kern, &wr, &ex);
d7fa0660
A
896 }
897 }
5dd30d76
A
898
899 /*
900 * Start launchd drain thread
901 */
902 pthread_attr_init(&attr);
903 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
904 pthread_create(&t, &attr, (void *(*)(void *))launchd_drain, NULL);
905 pthread_attr_destroy(&attr);
906
907 runloop_timer = NULL;
908 timed_events(&runloop_timer);
909
b16a592a
A
910 forever
911 {
d7fa0660 912 max = aslevent_fdsets(&rd, &wr, &ex) + 1;
b16a592a 913
5dd30d76 914 status = select(max, &rd, &wr, &ex, runloop_timer);
57b0aad2 915 if ((global.kfd >= 0) && FD_ISSET(global.kfd, &rd))
d7fa0660 916 {
5dd30d76 917 /* drain /dev/klog */
c4fdb7d1
A
918 FD_ZERO(&kern);
919 FD_SET(global.kfd, &kern);
57b0aad2 920 max = global.kfd + 1;
d7fa0660
A
921
922 while (select(max, &kern, NULL, NULL, &zto) > 0)
923 {
5dd30d76 924 aslevent_handleevent(&kern, &wr, &ex);
d7fa0660
A
925 }
926 }
b16a592a 927
c4fdb7d1 928 if (global.reset != RESET_NONE)
b16a592a
A
929 {
930 send_reset();
c4fdb7d1 931 global.reset = RESET_NONE;
b16a592a
A
932 }
933
5dd30d76 934 if (status != 0) aslevent_handleevent(&rd, &wr, &ex);
b16a592a 935
5dd30d76 936 timed_events(&runloop_timer);
b16a592a
A
937 }
938}