2 * Copyright (c) 2004-2010 Apple Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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,
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.
21 * @APPLE_LICENSE_HEADER_END@
29 #include <mach/mach.h>
30 #include <mach/mach_error.h>
31 #include <mach/mach_time.h>
32 #include <servers/bootstrap.h>
33 #include <sys/types.h>
34 #include <sys/socket.h>
35 #include <sys/sysctl.h>
37 #include <sys/fcntl.h>
38 #include <sys/errno.h>
39 #include <sys/queue.h>
50 #define SERVICE_NAME "com.apple.system.logger"
51 #define SERVER_STATUS_ERROR -1
52 #define SERVER_STATUS_INACTIVE 0
53 #define SERVER_STATUS_ACTIVE 1
54 #define SERVER_STATUS_ON_DEMAND 2
56 #define DEFAULT_MARK_SEC 0
57 #define DEFAULT_UTMP_TTL_SEC 31622400
58 #define DEFAULT_FS_TTL_SEC 31622400
59 #define DEFAULT_BSD_MAX_DUP_SEC 30
60 #define DEFAULT_MPS_LIMIT 500
61 #define BILLION 1000000000
63 #define NOTIFY_DELAY 1
65 #define NETWORK_CHANGE_NOTIFICATION "com.apple.system.config.network_change"
67 #define streq(A,B) (strcmp(A,B)==0)
68 #define forever for(;;)
70 static uint64_t time_start
= 0;
71 static uint64_t mark_last
= 0;
72 static uint64_t ping_last
= 0;
73 static uint64_t time_last
= 0;
75 extern int __notify_78945668_info__
;
76 extern int _malloc_no_asl_log
;
78 static TAILQ_HEAD(ml
, module_list
) Moduleq
;
81 struct global_s global
;
87 static int activate_asl_in
= 1;
89 int asl_action_init();
90 int asl_action_reset();
91 int asl_action_close();
92 static int activate_asl_action
= 1;
97 static int activate_klog_in
= 1;
102 static int activate_bsd_in
= 1;
107 static int activate_bsd_out
= 1;
112 static int activate_remote
= 0;
117 static int activate_udp_in
= 1;
119 extern void database_server();
120 extern void output_worker();
121 extern void launchd_drain();
122 extern void bsd_flush_duplicates(time_t now
);
123 extern void bsd_close_idle_files(time_t now
);
126 * Module approach: only one type of module. This module may implement
127 * the set of functions necessary for any of the functions (input, output,
128 * etc.) Prior to using the modules, dlsym() is consulted to see what it
135 struct module_list
*tmp
;
138 * The order of these initializations is important.
139 * When messages are sent to output modules, they are
140 * sent in the same order as these initializations.
141 * asl_action may add modify messages, for example to
142 * add access controls, so it must come first.
144 if (activate_asl_action
!= 0)
146 tmp
= calloc(1, sizeof(struct module_list
));
147 if (tmp
== NULL
) return 1;
149 tmp
->name
= strdup("asl_action");
150 if (tmp
->name
== NULL
)
157 tmp
->init
= asl_action_init
;
158 tmp
->reset
= asl_action_reset
;
159 tmp
->close
= asl_action_close
;
160 TAILQ_INSERT_TAIL(&Moduleq
, tmp
, entries
);
163 if (activate_asl_in
!= 0)
165 tmp
= calloc(1, sizeof(struct module_list
));
166 if (tmp
== NULL
) return 1;
168 tmp
->name
= strdup("asl_in");
169 if (tmp
->name
== NULL
)
176 tmp
->init
= asl_in_init
;
177 tmp
->reset
= asl_in_reset
;
178 tmp
->close
= asl_in_close
;
179 TAILQ_INSERT_TAIL(&Moduleq
, tmp
, entries
);
182 if (activate_klog_in
!= 0)
184 tmp
= calloc(1, sizeof(struct module_list
));
185 if (tmp
== NULL
) return 1;
187 tmp
->name
= strdup("klog_in");
188 if (tmp
->name
== NULL
)
195 tmp
->init
= klog_in_init
;
196 tmp
->reset
= klog_in_reset
;
197 tmp
->close
= klog_in_close
;
198 TAILQ_INSERT_TAIL(&Moduleq
, tmp
, entries
);
201 if (activate_bsd_in
!= 0)
203 tmp
= calloc(1, sizeof(struct module_list
));
204 if (tmp
== NULL
) return 1;
206 tmp
->name
= strdup("bsd_in");
207 if (tmp
->name
== NULL
)
214 tmp
->init
= bsd_in_init
;
215 tmp
->reset
= bsd_in_reset
;
216 tmp
->close
= bsd_in_close
;
217 TAILQ_INSERT_TAIL(&Moduleq
, tmp
, entries
);
220 if (activate_bsd_out
!= 0)
222 tmp
= calloc(1, sizeof(struct module_list
));
223 if (tmp
== NULL
) return 1;
225 tmp
->name
= strdup("bsd_out");
226 if (tmp
->name
== NULL
)
233 tmp
->init
= bsd_out_init
;
234 tmp
->reset
= bsd_out_reset
;
235 tmp
->close
= bsd_out_close
;
236 TAILQ_INSERT_TAIL(&Moduleq
, tmp
, entries
);
239 if (activate_remote
!= 0)
241 tmp
= calloc(1, sizeof(struct module_list
));
242 if (tmp
== NULL
) return 1;
244 tmp
->name
= strdup("remote");
245 if (tmp
->name
== NULL
)
252 tmp
->init
= remote_init
;
253 tmp
->reset
= remote_reset
;
254 tmp
->close
= remote_close
;
255 TAILQ_INSERT_TAIL(&Moduleq
, tmp
, entries
);
258 if (activate_udp_in
!= 0)
260 tmp
= calloc(1, sizeof(struct module_list
));
261 if (tmp
== NULL
) return 1;
263 tmp
->name
= strdup("udp_in");
264 if (tmp
->name
== NULL
)
271 tmp
->init
= udp_in_init
;
272 tmp
->reset
= udp_in_reset
;
273 tmp
->close
= udp_in_close
;
274 TAILQ_INSERT_TAIL(&Moduleq
, tmp
, entries
);
281 * Loads all the modules. This DOES NOT call the modules initializer
282 * functions. It simply scans the modules directory looking for modules
283 * and loads them. This does not mean the module will be used.
286 load_modules(const char *mp
)
290 struct module_list
*tmp
;
292 char *modulepath
= NULL
;
295 if (d
== NULL
) return -1;
297 while (NULL
!= (de
= readdir(d
)))
299 if (de
->d_name
[0] == '.') continue;
301 /* Must have ".so" in the name" */
302 if (!strstr(de
->d_name
, ".so")) continue;
304 asprintf(&modulepath
, "%s/%s", mp
, de
->d_name
);
305 if (!modulepath
) continue;
307 c
= dlopen(modulepath
, RTLD_LOCAL
);
314 tmp
= calloc(1, sizeof(struct module_list
));
322 bn
= basename(modulepath
);
323 tmp
->name
= strdup(bn
);
324 if (tmp
->name
== NULL
)
331 TAILQ_INSERT_TAIL(&Moduleq
, tmp
, entries
);
333 tmp
->init
= dlsym(tmp
->module, "aslmod_init");
334 tmp
->reset
= dlsym(tmp
->module, "aslmod_reset");
335 tmp
->close
= dlsym(tmp
->module, "aslmod_close");
354 memset(&sb
, 0, sizeof(struct stat
));
355 if (stat(_PATH_PIDFILE
, &sb
) == 0)
357 if (S_ISREG(sb
.st_mode
)) *first
= 0;
361 fp
= fopen(_PATH_PIDFILE
, "w");
364 fprintf(fp
, "%d\n", getpid());
374 for (i
= getdtablesize() - 1; i
>= 0; i
--) close(i
);
376 open("/dev/null", O_RDWR
, 0);
384 signal(SIGINT
, SIG_IGN
);
385 signal(SIGPIPE
, SIG_IGN
);
392 global
.reset
= RESET_CONFIG
;
398 global
.reset
= RESET_NETWORK
;
404 struct module_list
*mod
;
406 for (mod
= Moduleq
.tqh_first
; mod
!= NULL
; mod
= mod
->entries
.tqe_next
)
408 if (mod
->reset
!= NULL
) mod
->reset();
413 * perform timed activities and set next run-loop timeout
416 timed_events(struct timeval
**run
)
418 time_t now
, delta
, t
;
419 static struct timeval next
;
437 * At startup, we try sending a notification once a second.
438 * Once it succeeds, we set the Libc global __notify_78945668_info__ to 0
439 * which lets Libc's localtime calculations use notifyd to invalidate
440 * cached timezones. This prevents a deadlock in localtime.
442 if (__notify_78945668_info__
< 0)
444 if (notify_post("com.apple.system.syslogd") == NOTIFY_STATUS_OK
) __notify_78945668_info__
= 0;
445 else next
.tv_sec
= 1;
451 * Despite Albert Einstein's assurance, time has gone backward.
452 * Reset "last" times to current time.
460 * Tickle bsd_out module to flush duplicates.
462 if (global
.bsd_flush_time
> 0)
464 bsd_flush_duplicates(now
);
465 bsd_close_idle_files(now
);
466 if (global
.bsd_flush_time
> 0)
468 if (next
.tv_sec
== 0) next
.tv_sec
= global
.bsd_flush_time
;
469 else if (global
.bsd_flush_time
< next
.tv_sec
) next
.tv_sec
= global
.bsd_flush_time
;
474 * Tickle asl_store to sweep file cache
476 if (global
.asl_store_ping_time
> 0)
478 delta
= now
- ping_last
;
479 if (delta
>= global
.asl_store_ping_time
)
482 bsd_close_idle_files(now
);
484 t
= global
.asl_store_ping_time
;
488 t
= global
.asl_store_ping_time
- delta
;
491 if (next
.tv_sec
== 0) next
.tv_sec
= t
;
492 else if (t
< next
.tv_sec
) next
.tv_sec
= t
;
498 if (global
.mark_time
> 0)
500 delta
= now
- mark_last
;
501 if (delta
>= global
.mark_time
)
505 t
= global
.mark_time
;
509 t
= global
.mark_time
- delta
;
512 if (next
.tv_sec
== 0) next
.tv_sec
= t
;
513 else if (t
< next
.tv_sec
) next
.tv_sec
= t
;
517 * set output timeout parameter if runloop needs to have a timer
519 if (next
.tv_sec
> 0) *run
= &next
;
527 launch_data_t tmp
, pdict
;
528 kern_return_t status
;
530 tmp
= launch_data_new_string(LAUNCH_KEY_CHECKIN
);
531 global
.launch_dict
= launch_msg(tmp
);
532 launch_data_free(tmp
);
534 if (global
.launch_dict
== NULL
)
536 fprintf(stderr
, "%d launchd checkin failed\n", getpid());
540 tmp
= launch_data_dict_lookup(global
.launch_dict
, LAUNCH_JOBKEY_MACHSERVICES
);
543 fprintf(stderr
, "%d launchd lookup of LAUNCH_JOBKEY_MACHSERVICES failed\n", getpid());
547 pdict
= launch_data_dict_lookup(tmp
, SERVICE_NAME
);
550 fprintf(stderr
, "%d launchd lookup of SERVICE_NAME failed\n", getpid());
554 global
.server_port
= launch_data_get_machport(pdict
);
556 /* port for receiving internal messages */
557 status
= mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE
, &(global
.self_port
));
558 if (status
!= KERN_SUCCESS
)
560 fprintf(stderr
, "mach_port_allocate self_port failed: %d", status
);
564 status
= mach_port_insert_right(mach_task_self(), global
.self_port
, global
.self_port
, MACH_MSG_TYPE_MAKE_SEND
);
565 if (status
!= KERN_SUCCESS
)
567 fprintf(stderr
, "Can't make send right for self_port: %d\n", status
);
571 /* port for receiving MACH_NOTIFY_DEAD_NAME notifications */
572 status
= mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE
, &(global
.dead_session_port
));
573 if (status
!= KERN_SUCCESS
)
575 fprintf(stderr
, "mach_port_allocate dead_session_port failed: %d", status
);
579 status
= mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_PORT_SET
, &(global
.listen_set
));
580 if (status
!= KERN_SUCCESS
)
582 fprintf(stderr
, "mach_port_allocate listen_set failed: %d", status
);
586 status
= mach_port_move_member(mach_task_self(), global
.server_port
, global
.listen_set
);
587 if (status
!= KERN_SUCCESS
)
589 fprintf(stderr
, "mach_port_move_member server_port failed: %d", status
);
593 status
= mach_port_move_member(mach_task_self(), global
.self_port
, global
.listen_set
);
594 if (status
!= KERN_SUCCESS
)
596 fprintf(stderr
, "mach_port_move_member self_port failed: %d", status
);
600 status
= mach_port_move_member(mach_task_self(), global
.dead_session_port
, global
.listen_set
);
601 if (status
!= KERN_SUCCESS
)
603 fprintf(stderr
, "mach_port_move_member dead_session_port failed (%u)", status
);
609 config_debug(int enable
, const char *path
)
611 OSSpinLockLock(&global
.lock
);
613 global
.debug
= enable
;
614 if (global
.debug_file
!= NULL
) free(global
.debug_file
);
615 global
.debug_file
= NULL
;
616 if (path
!= NULL
) global
.debug_file
= strdup(path
);
618 OSSpinLockUnlock(&global
.lock
);
622 config_data_store(int type
, uint32_t file_max
, uint32_t memory_max
, uint32_t mini_max
)
624 pthread_mutex_lock(global
.db_lock
);
626 if (global
.dbtype
& DB_TYPE_FILE
)
628 asl_store_close(global
.file_db
);
629 global
.file_db
= NULL
;
632 if (global
.dbtype
& DB_TYPE_MEMORY
)
634 asl_memory_close(global
.memory_db
);
635 global
.memory_db
= NULL
;
638 if (global
.dbtype
& DB_TYPE_MINI
)
640 asl_mini_memory_close(global
.mini_db
);
641 global
.mini_db
= NULL
;
644 global
.dbtype
= type
;
645 global
.db_file_max
= file_max
;
646 global
.db_memory_max
= memory_max
;
647 global
.db_mini_max
= mini_max
;
649 pthread_mutex_unlock(global
.db_lock
);
653 write_boot_log(int first
)
655 int mib
[2] = {CTL_KERN
, KERN_BOOTTIME
};
663 /* syslogd restart */
664 msg
= asl_new(ASL_TYPE_MSG
);
665 if (msg
== NULL
) return;
667 asl_set(msg
, ASL_KEY_SENDER
, "syslogd");
668 asl_set(msg
, ASL_KEY_FACILITY
, "daemon");
669 asl_set(msg
, ASL_KEY_LEVEL
, "Notice");
670 asl_set(msg
, ASL_KEY_UID
, "0");
671 asl_set(msg
, ASL_KEY_GID
, "0");
672 snprintf(buf
, sizeof(buf
), "%u", getpid());
673 asl_set(msg
, ASL_KEY_PID
, buf
);
674 asl_set(msg
, ASL_KEY_MSG
, "--- syslogd restarted ---");
675 asl_enqueue_message(SOURCE_INTERNAL
, NULL
, msg
);
679 bzero(&utx
, sizeof(utx
));
680 utx
.ut_type
= BOOT_TIME
;
683 /* get the boot time */
684 len
= sizeof(struct timeval
);
685 if (sysctl(mib
, 2, &utx
.ut_tv
, &len
, NULL
, 0) < 0)
687 gettimeofday(&utx
.ut_tv
, NULL
);
692 msg
= asl_new(ASL_TYPE_MSG
);
693 if (msg
== NULL
) return;
695 asl_set(msg
, ASL_KEY_SENDER
, "bootlog");
696 asl_set(msg
, ASL_KEY_FACILITY
, "com.apple.system.utmpx");
697 asl_set(msg
, ASL_KEY_LEVEL
, "Notice");
698 asl_set(msg
, ASL_KEY_UID
, "0");
699 asl_set(msg
, ASL_KEY_GID
, "0");
700 asl_set(msg
, ASL_KEY_PID
, "0");
701 snprintf(buf
, sizeof(buf
), "BOOT_TIME %lu %u", (unsigned long)utx
.ut_tv
.tv_sec
, (unsigned int)utx
.ut_tv
.tv_usec
);
702 asl_set(msg
, ASL_KEY_MSG
, buf
);
703 asl_set(msg
, "ut_id", "0x00 0x00 0x00 0x00");
704 asl_set(msg
, "ut_pid", "1");
705 asl_set(msg
, "ut_type", "2");
706 snprintf(buf
, sizeof(buf
), "%lu", (unsigned long)utx
.ut_tv
.tv_sec
);
707 asl_set(msg
, ASL_KEY_TIME
, buf
);
708 asl_set(msg
, "ut_tv.tv_sec", buf
);
709 snprintf(buf
, sizeof(buf
), "%u", (unsigned int)utx
.ut_tv
.tv_usec
);
710 asl_set(msg
, "ut_tv.tv_usec", buf
);
711 snprintf(buf
, sizeof(buf
), "%u%s", (unsigned int)utx
.ut_tv
.tv_usec
, (utx
.ut_tv
.tv_usec
== 0) ? "" : "000");
712 asl_set(msg
, ASL_KEY_TIME_NSEC
, buf
);
714 asl_enqueue_message(SOURCE_INTERNAL
, NULL
, msg
);
718 main(int argc
, const char *argv
[])
720 struct module_list
*mod
;
721 fd_set rd
, wr
, ex
, kern
;
722 int32_t fd
, i
, max
, status
, daemonize
;
724 struct timeval
*runloop_timer
, zto
;
727 int network_change_token
;
730 int first_syslogs_start
= 1;
733 setiopolicy_np(IOPOL_TYPE_DISK
, IOPOL_SCOPE_PROCESS
, IOPOL_PASSIVE
);
735 memset(&global
, 0, sizeof(struct global_s
));
737 global
.db_lock
= (pthread_mutex_t
*)calloc(1, sizeof(pthread_mutex_t
));
738 pthread_mutex_init(global
.db_lock
, NULL
);
740 global
.work_queue_lock
= (pthread_mutex_t
*)calloc(1, sizeof(pthread_mutex_t
));
741 pthread_mutex_init(global
.work_queue_lock
, NULL
);
743 pthread_cond_init(&global
.work_queue_cond
, NULL
);
745 global
.work_queue
= (asl_search_result_t
*)calloc(1, sizeof(asl_search_result_t
));
747 global
.asl_log_filter
= ASL_FILTER_MASK_UPTO(ASL_LEVEL_DEBUG
);
748 global
.db_file_max
= 16384000;
749 global
.db_memory_max
= 8192;
750 global
.db_mini_max
= 256;
751 global
.bsd_max_dup_time
= DEFAULT_BSD_MAX_DUP_SEC
;
752 global
.utmp_ttl
= DEFAULT_UTMP_TTL_SEC
;
753 global
.fs_ttl
= DEFAULT_FS_TTL_SEC
;
754 global
.mps_limit
= DEFAULT_MPS_LIMIT
;
756 global
.lockdown_session_fd
= -1;
759 global
.dbtype
= DB_TYPE_FILE
;
760 global
.db_file_max
= 25600000;
761 global
.asl_store_ping_time
= 150;
765 global
.dbtype
= DB_TYPE_MINI
;
767 activate_bsd_out
= 0;
770 mp
= _PATH_MODULE_LIB
;
772 __notify_78945668_info__
= 0xf0000000;
776 /* prevent malloc from calling ASL on error */
777 _malloc_no_asl_log
= 1;
779 /* first pass sets up default configurations */
780 for (i
= 1; i
< argc
; i
++)
782 if (streq(argv
[i
], "-config"))
784 if (((i
+ 1) < argc
) && (argv
[i
+1][0] != '-'))
787 if (streq(argv
[i
], "mac"))
789 global
.dbtype
= DB_TYPE_FILE
;
790 global
.db_file_max
= 25600000;
792 else if (streq(argv
[i
], "appletv"))
794 global
.dbtype
= DB_TYPE_FILE
;
795 global
.db_file_max
= 10240000;
797 else if (streq(argv
[i
], "iphone"))
799 global
.dbtype
= DB_TYPE_MINI
;
806 for (i
= 1; i
< argc
; i
++)
808 if (streq(argv
[i
], "-d"))
811 if (((i
+1) < argc
) && (argv
[i
+1][0] != '-')) global
.debug_file
= strdup(argv
[++i
]);
812 memset(tstr
, 0, sizeof(tstr
));
816 asldebug("%s syslogd[%d]: Start\n", tstr
, getpid());
818 else if (streq(argv
[i
], "-db"))
820 if (((i
+ 1) < argc
) && (argv
[i
+1][0] != '-'))
823 if (streq(argv
[i
], "file"))
825 global
.dbtype
|= DB_TYPE_FILE
;
826 if (((i
+ 1) < argc
) && (argv
[i
+1][0] != '-')) global
.db_file_max
= atol(argv
[++i
]);
828 else if (streq(argv
[i
], "memory"))
830 global
.dbtype
|= DB_TYPE_MEMORY
;
831 if (((i
+ 1) < argc
) && (argv
[i
+1][0] != '-')) global
.db_memory_max
= atol(argv
[++i
]);
833 else if (streq(argv
[i
], "mini"))
835 global
.dbtype
|= DB_TYPE_MINI
;
836 if (((i
+ 1) < argc
) && (argv
[i
+1][0] != '-')) global
.db_mini_max
= atol(argv
[++i
]);
840 else if (streq(argv
[i
], "-D"))
844 else if (streq(argv
[i
], "-m"))
846 if ((i
+ 1) < argc
) global
.mark_time
= 60 * atoll(argv
[++i
]);
848 else if (streq(argv
[i
], "-utmp_ttl"))
850 if ((i
+ 1) < argc
) global
.utmp_ttl
= atol(argv
[++i
]);
852 else if (streq(argv
[i
], "-fs_ttl"))
854 if ((i
+ 1) < argc
) global
.fs_ttl
= atol(argv
[++i
]);
856 else if (streq(argv
[i
], "-mps_limit"))
858 if ((i
+ 1) < argc
) global
.mps_limit
= atol(argv
[++i
]);
860 else if (streq(argv
[i
], "-l"))
862 if ((i
+ 1) < argc
) mp
= argv
[++i
];
864 else if (streq(argv
[i
], "-c"))
869 if ((argv
[i
][0] >= '0') && (argv
[i
][0] <= '7') && (argv
[i
][1] == '\0')) global
.asl_log_filter
= ASL_FILTER_MASK_UPTO(atoi(argv
[i
]));
872 else if (streq(argv
[i
], "-dup_delay"))
874 if ((i
+ 1) < argc
) global
.bsd_max_dup_time
= atoll(argv
[++i
]);
876 else if (streq(argv
[i
], "-asl_in"))
878 if ((i
+ 1) < argc
) activate_asl_in
= atoi(argv
[++i
]);
880 else if (streq(argv
[i
], "-asl_action"))
882 if ((i
+ 1) < argc
) activate_asl_action
= atoi(argv
[++i
]);
884 else if (streq(argv
[i
], "-klog_in"))
886 if ((i
+ 1) < argc
) activate_klog_in
= atoi(argv
[++i
]);
888 else if (streq(argv
[i
], "-bsd_in"))
890 if ((i
+ 1) < argc
) activate_bsd_in
= atoi(argv
[++i
]);
892 else if (streq(argv
[i
], "-bsd_out"))
894 if ((i
+ 1) < argc
) activate_bsd_out
= atoi(argv
[++i
]);
896 else if (streq(argv
[i
], "-remote"))
898 if ((i
+ 1) < argc
) activate_remote
= atoi(argv
[++i
]);
900 else if (streq(argv
[i
], "-udp_in"))
902 if ((i
+ 1) < argc
) activate_udp_in
= atoi(argv
[++i
]);
906 if (global
.dbtype
== 0)
908 global
.dbtype
= DB_TYPE_FILE
;
909 global
.db_file_max
= 25600000;
910 global
.asl_store_ping_time
= 150;
913 TAILQ_INIT(&Moduleq
);
918 if (global
.debug
== 0)
922 if (fork() != 0) exit(0);
928 writepid(&first_syslogs_start
);
933 signal(SIGHUP
, catch_sighup
);
934 signal(SIGINFO
, catch_siginfo
);
936 /* register for network change notifications if the udp_in module is active */
937 network_change_token
= -1;
938 if (activate_udp_in
!= 0) notify_register_signal(NETWORK_CHANGE_NOTIFICATION
, SIGINFO
, &network_change_token
);
940 for (mod
= Moduleq
.tqh_first
; mod
!= NULL
; mod
= mod
->entries
.tqe_next
)
943 if (fd
< 0) continue;
947 * Start database server thread
949 pthread_attr_init(&attr
);
950 pthread_attr_setdetachstate(&attr
, PTHREAD_CREATE_DETACHED
);
951 pthread_create(&t
, &attr
, (void *(*)(void *))database_server
, NULL
);
952 pthread_attr_destroy(&attr
);
955 * Start output worker thread
957 pthread_attr_init(&attr
);
958 pthread_attr_setdetachstate(&attr
, PTHREAD_CREATE_DETACHED
);
959 pthread_create(&t
, &attr
, (void *(*)(void *))output_worker
, NULL
);
960 pthread_attr_destroy(&attr
);
967 * Log UTMPX boot time record
969 write_boot_log(first_syslogs_start
);
972 * drain /dev/klog first
977 FD_SET(global
.kfd
, &kern
);
978 max
= global
.kfd
+ 1;
979 while (select(max
, &kern
, NULL
, NULL
, &zto
) > 0)
981 aslevent_handleevent(&kern
, &wr
, &ex
);
986 * Start launchd drain thread
988 pthread_attr_init(&attr
);
989 pthread_attr_setdetachstate(&attr
, PTHREAD_CREATE_DETACHED
);
990 pthread_create(&t
, &attr
, (void *(*)(void *))launchd_drain
, NULL
);
991 pthread_attr_destroy(&attr
);
993 runloop_timer
= NULL
;
994 timed_events(&runloop_timer
);
998 /* aslevent_fdsets clears the fdsets, then sets any non-zero fds from the aslevent list */
999 max
= aslevent_fdsets(&rd
, &wr
, &ex
) + 1;
1001 status
= select(max
, &rd
, &wr
, &ex
, runloop_timer
);
1002 if ((status
< 0) && (errno
== EBADF
))
1004 /* Catastrophic error! */
1009 if ((global
.kfd
>= 0) && FD_ISSET(global
.kfd
, &rd
))
1011 /* drain /dev/klog */
1013 FD_SET(global
.kfd
, &kern
);
1014 max
= global
.kfd
+ 1;
1016 while (select(max
, &kern
, NULL
, NULL
, &zto
) > 0)
1018 aslevent_handleevent(&kern
, &wr
, &ex
);
1022 if (status
> 0) aslevent_handleevent(&rd
, &wr
, &ex
);
1024 if ((global
.reset
!= RESET_NONE
) || (status
< 0))
1027 global
.reset
= RESET_NONE
;
1030 timed_events(&runloop_timer
);