xref: /NextBSD/usr.sbin/asl/syslogd.c (revision 33da5adc555b3bc29986eeadca03829e4ad06b1e)
1 /*
2  * Copyright (c) 2004-2012 Apple Inc. All rights reserved.
3  *
4  * @APPLE_LICENSE_HEADER_START@
5  *
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.
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,
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.
20  *
21  * @APPLE_LICENSE_HEADER_END@
22  */
23 
24 #include <TargetConditionals.h>
25 
26 #include <assert.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <unistd.h>
30 #include <string.h>
31 #include <mach/mach.h>
32 #include <mach/mach_error.h>
33 #include <mach/mach_time.h>
34 #include <servers/bootstrap.h>
35 #include <sys/types.h>
36 #include <sys/socket.h>
37 #include <sys/sysctl.h>
38 #include <sys/stat.h>
39 #include <sys/fcntl.h>
40 #include <sys/errno.h>
41 #include <sys/queue.h>
42 #include <sys/time.h>
43 #include <sys/un.h>
44 #include <pthread.h>
45 #include <dirent.h>
46 #include <dlfcn.h>
47 #include <libgen.h>
48 #include <notify.h>
49 // XXX #include <notify_keys.h>
50 #include <utmpx.h>
51 #include <vproc_priv.h>
52 #include <asl_private.h>
53 #if !TARGET_OS_IPHONE
54 // XXX #include <quarantine.h>
55 #endif
56 #include "daemon.h"
57 
58 #define SERVICE_NAME "com.apple.system.logger"
59 #define SERVER_STATUS_ERROR -1
60 #define SERVER_STATUS_INACTIVE 0
61 #define SERVER_STATUS_ACTIVE 1
62 #define SERVER_STATUS_ON_DEMAND 2
63 
64 #define BILLION 1000000000
65 
66 #define NOTIFY_DELAY 1
67 
68 #define forever for(;;)
69 
70 #if 0
71 extern int _malloc_no_asl_log;
72 #endif
73 
74 #if TARGET_IPHONE_SIMULATOR
75 const char *_path_pidfile;
76 const char *_path_syslogd_log;
77 #endif
78 
79 /* global */
80 struct global_s global;
81 
82 #if !TARGET_IPHONE_SIMULATOR
83 /* Input Modules */
84 int klog_in_init(void);
85 int klog_in_reset(void);
86 int klog_in_close(void);
87 static int activate_klog_in = 1;
88 #endif
89 
90 int bsd_in_init(void);
91 int bsd_in_reset(void);
92 int bsd_in_close(void);
93 static int activate_bsd_in = 1;
94 
95 #if !TARGET_IPHONE_SIMULATOR
96 int udp_in_init(void);
97 int udp_in_reset(void);
98 int udp_in_close(void);
99 static int activate_udp_in = 1;
100 
101 /* Output Modules */
102 int bsd_out_init(void);
103 int bsd_out_reset(void);
104 int bsd_out_close(void);
105 static int activate_bsd_out = 1;
106 #endif
107 
108 int asl_action_init(void);
109 int asl_action_reset(void);
110 int asl_action_close(void);
111 static int activate_asl_action = 1;
112 
113 #if !TARGET_IPHONE_SIMULATOR
114 /* Interactive Module */
115 int remote_init(void);
116 int remote_reset(void);
117 int remote_close(void);
118 static int remote_enabled = 0;
119 #endif
120 
121 extern void database_server();
122 
123 static void
init_modules()124 init_modules()
125 {
126 #if !TARGET_IPHONE_SIMULATOR
127 	module_t *m_klog_in, *m_bsd_out, *m_udp_in, *m_remote;
128 #endif
129 	module_t *m_asl, *m_bsd_in;
130 	int m = 0;
131 
132 	/* ASL module (configured by /etc/asl.conf) */
133 	m_asl = (module_t *)calloc(1, sizeof(module_t));
134 	if (m_asl == NULL)
135 	{
136 		asldebug("alloc failed (init_modules asl_action)\n");
137 		exit(1);
138 	}
139 
140 	m_asl->name = "asl_action";
141 	m_asl->enabled = activate_asl_action;
142 	m_asl->init = asl_action_init;
143 	m_asl->reset = asl_action_reset;
144 	m_asl->close = asl_action_close;
145 
146 	if (m_asl->enabled) m_asl->init();
147 
148 #if !TARGET_IPHONE_SIMULATOR
149 	/* BSD output module (configured by /etc/syslog.conf) */
150 	m_bsd_out = (module_t *)calloc(1, sizeof(module_t));
151 	if (m_bsd_out == NULL)
152 	{
153 		asldebug("alloc failed (init_modules bsd_out)\n");
154 		exit(1);
155 	}
156 
157 	m_bsd_out->name = "bsd_out";
158 	m_bsd_out->enabled = activate_bsd_out;
159 	m_bsd_out->init = bsd_out_init;
160 	m_bsd_out->reset = bsd_out_reset;
161 	m_bsd_out->close = bsd_out_close;
162 
163 	if (m_bsd_out->enabled)
164 	{
165 		m_bsd_out->init();
166 		global.bsd_out_enabled = 1;
167 	}
168 
169 	/* kernel input module */
170 	m_klog_in = (module_t *)calloc(1, sizeof(module_t));
171 	if (m_klog_in == NULL)
172 	{
173 		asldebug("alloc failed (init_modules klog_in)\n");
174 		exit(1);
175 	}
176 
177 	m_klog_in->name = "klog_in";
178 	m_klog_in->enabled = activate_klog_in;
179 	m_klog_in->init = klog_in_init;
180 	m_klog_in->reset = klog_in_reset;
181 	m_klog_in->close = klog_in_close;
182 
183 	if (m_klog_in->enabled) m_klog_in->init();
184 #endif
185 
186 	/* BSD (UNIX domain socket) input module */
187 	m_bsd_in = (module_t *)calloc(1, sizeof(module_t));
188 	if (m_bsd_in == NULL)
189 	{
190 		asldebug("alloc failed (init_modules bsd_in)\n");
191 		exit(1);
192 	}
193 
194 	m_bsd_in->name = "bsd_in";
195 	m_bsd_in->enabled = activate_bsd_in;
196 	m_bsd_in->init = bsd_in_init;
197 	m_bsd_in->reset = bsd_in_reset;
198 	m_bsd_in->close = bsd_in_close;
199 
200 	if (m_bsd_in->enabled) m_bsd_in->init();
201 
202 #if !TARGET_IPHONE_SIMULATOR
203 	/* network (syslog protocol) input module */
204 	m_udp_in = (module_t *)calloc(1, sizeof(module_t));
205 	if (m_udp_in == NULL)
206 	{
207 		asldebug("alloc failed (init_modules udp_in)\n");
208 		exit(1);
209 	}
210 
211 	m_udp_in->name = "udp_in";
212 	m_udp_in->enabled = activate_udp_in;
213 	m_udp_in->init = udp_in_init;
214 	m_udp_in->reset = udp_in_reset;
215 	m_udp_in->close = udp_in_close;
216 
217 	if (m_udp_in->enabled) m_udp_in->init();
218 
219 	/* remote (iOS support) module */
220 	m_remote = (module_t *)calloc(1, sizeof(module_t));
221 	if (m_remote == NULL)
222 	{
223 		asldebug("alloc failed (init_modules remote)\n");
224 		exit(1);
225 	}
226 
227 	m_remote->name = "remote";
228 	m_remote->enabled = remote_enabled;
229 	m_remote->init = remote_init;
230 	m_remote->reset = remote_reset;
231 	m_remote->close = remote_close;
232 
233 	if (m_remote->enabled) m_remote->init();
234 #endif /* TARGET_IPHONE_SIMULATOR */
235 
236 	/* save modules in global.module array */
237 #if TARGET_IPHONE_SIMULATOR
238 	global.module_count = 2;
239 #else
240 	global.module_count = 6;
241 #endif
242 	global.module = (module_t **)calloc(global.module_count, sizeof(module_t *));
243 	if (global.module == NULL)
244 	{
245 		asldebug("alloc failed (init_modules)\n");
246 		exit(1);
247 	}
248 
249 	global.module[m++] = m_asl;
250 	global.module[m++] = m_bsd_in;
251 #if !TARGET_IPHONE_SIMULATOR
252 	global.module[m++] = m_bsd_out;
253 	global.module[m++] = m_klog_in;
254 	global.module[m++] = m_udp_in;
255 	global.module[m++] = m_remote;
256 #endif
257 }
258 
259 static void
writepid(int * first)260 writepid(int *first)
261 {
262 	struct stat sb;
263 	FILE *fp;
264 
265 	if (first != NULL)
266 	{
267 		*first = 1;
268 		memset(&sb, 0, sizeof(struct stat));
269 		if (stat(_PATH_PIDFILE, &sb) == 0)
270 		{
271 			if (S_ISREG(sb.st_mode)) *first = 0;
272 		}
273 	}
274 
275 	fp = fopen(_PATH_PIDFILE, "w");
276 	if (fp != NULL)
277 	{
278 		fprintf(fp, "%d\n", global.pid);
279 		fclose(fp);
280 	}
281 }
282 
283 void
launch_config()284 launch_config()
285 {
286 	launch_data_t tmp, pdict;
287 	kern_return_t status;
288 
289 	tmp = launch_data_new_string(LAUNCH_KEY_CHECKIN);
290 	global.launch_dict = launch_msg(tmp);
291 	launch_data_free(tmp);
292 
293 	if (global.launch_dict == NULL)
294 	{
295 		asldebug("%d launchd checkin failed\n", global.pid);
296 		exit(1);
297 	}
298 
299 	tmp = launch_data_dict_lookup(global.launch_dict, LAUNCH_JOBKEY_MACHSERVICES);
300 	if (tmp == NULL)
301 	{
302 		asldebug("%d launchd lookup of LAUNCH_JOBKEY_MACHSERVICES failed\n", global.pid);
303 		exit(1);
304 	}
305 
306 	pdict = launch_data_dict_lookup(tmp, SERVICE_NAME);
307 	if (pdict == NULL)
308 	{
309 		asldebug("%d launchd lookup of SERVICE_NAME failed\n", global.pid);
310 		exit(1);
311 	}
312 
313 	global.server_port = launch_data_get_machport(pdict);
314 
315 	/* port for receiving MACH_NOTIFY_DEAD_NAME notifications */
316 	status = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &(global.dead_session_port));
317 	if (status != KERN_SUCCESS)
318 	{
319 		asldebug("mach_port_allocate dead_session_port failed: %d", status);
320 		exit(1);
321 	}
322 
323 	status = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_PORT_SET, &(global.listen_set));
324 	if (status != KERN_SUCCESS)
325 	{
326 		asldebug("mach_port_allocate listen_set failed: %d", status);
327 		exit(1);
328 	}
329 
330 	status = mach_port_move_member(mach_task_self(), global.server_port, global.listen_set);
331 	if (status != KERN_SUCCESS)
332 	{
333 		asldebug("mach_port_move_member server_port failed: %d", status);
334 		exit(1);
335 	}
336 
337 	status = mach_port_move_member(mach_task_self(), global.dead_session_port, global.listen_set);
338 	if (status != KERN_SUCCESS)
339 	{
340 		asldebug("mach_port_move_member dead_session_port failed (%u)", status);
341 		exit(1);
342 	}
343 }
344 
345 void
config_debug(int enable,const char * path)346 config_debug(int enable, const char *path)
347 {
348 	OSSpinLockLock(&global.lock);
349 
350 	global.debug = enable;
351 	free(global.debug_file);
352 	global.debug_file = NULL;
353 	if (path != NULL) global.debug_file = strdup(path);
354 
355 	OSSpinLockUnlock(&global.lock);
356 }
357 
358 void
config_data_store(int type,uint32_t file_max,uint32_t memory_max,uint32_t str_memory_max)359 config_data_store(int type, uint32_t file_max, uint32_t memory_max, uint32_t str_memory_max)
360 {
361 	pthread_mutex_lock(global.db_lock);
362 
363 	if (global.dbtype & DB_TYPE_FILE)
364 	{
365 		asl_store_close(global.file_db);
366 		global.file_db = NULL;
367 	}
368 
369 	if (global.dbtype & DB_TYPE_MEMORY)
370 	{
371 		asl_memory_close(global.memory_db);
372 		global.memory_db = NULL;
373 	}
374 
375 	global.dbtype = type;
376 	global.db_file_max = file_max;
377 	global.db_memory_max = memory_max;
378 	global.db_memory_str_max = str_memory_max;
379 
380 	pthread_mutex_unlock(global.db_lock);
381 }
382 
383 void
write_boot_log(int first)384 write_boot_log(int first)
385 {
386 	int mib[2] = {CTL_KERN, KERN_BOOTTIME};
387 	size_t len;
388 	asl_msg_t *msg;
389 	char buf[256];
390 	struct utmpx utx;
391 
392 	if (first == 0)
393 	{
394 		/* syslogd restart */
395 		msg = asl_msg_new(ASL_TYPE_MSG);
396 		if (msg == NULL) return;
397 
398 		asl_msg_set_key_val(msg, ASL_KEY_SENDER, "syslogd");
399 		asl_msg_set_key_val(msg, ASL_KEY_FACILITY, "daemon");
400 		asl_msg_set_key_val(msg, ASL_KEY_LEVEL, "Notice");
401 		asl_msg_set_key_val(msg, ASL_KEY_UID, "0");
402 		asl_msg_set_key_val(msg, ASL_KEY_GID, "0");
403 		snprintf(buf, sizeof(buf), "%u", global.pid);
404 		asl_msg_set_key_val(msg, ASL_KEY_PID, buf);
405 		asl_msg_set_key_val(msg, ASL_KEY_MSG, "--- syslogd restarted ---");
406 		process_message(msg, SOURCE_INTERNAL);
407 		return;
408 	}
409 
410 	bzero(&utx, sizeof(utx));
411 	utx.ut_type = BOOT_TIME;
412 	utx.ut_pid = 1;
413 
414 	/* get the boot time */
415 	len = sizeof(struct timeval);
416 	if (sysctl(mib, 2, &utx.ut_tv, &len, NULL, 0) < 0)
417 	{
418 		gettimeofday(&utx.ut_tv, NULL);
419 	}
420 
421 	pututxline(&utx);
422 
423 	msg = asl_msg_new(ASL_TYPE_MSG);
424 	if (msg == NULL) return;
425 
426 	asl_msg_set_key_val(msg, ASL_KEY_SENDER, "bootlog");
427 	asl_msg_set_key_val(msg, ASL_KEY_FACILITY, "com.apple.system.utmpx");
428 	asl_msg_set_key_val(msg, ASL_KEY_LEVEL, "Notice");
429 	asl_msg_set_key_val(msg, ASL_KEY_UID, "0");
430 	asl_msg_set_key_val(msg, ASL_KEY_GID, "0");
431 	asl_msg_set_key_val(msg, ASL_KEY_PID, "0");
432 	snprintf(buf, sizeof(buf), "BOOT_TIME %lu %u", (unsigned long)utx.ut_tv.tv_sec, (unsigned int)utx.ut_tv.tv_usec);
433 	asl_msg_set_key_val(msg, ASL_KEY_MSG, buf);
434 	asl_msg_set_key_val(msg, "ut_id", "0x00 0x00 0x00 0x00");
435 	asl_msg_set_key_val(msg, "ut_pid", "1");
436 	asl_msg_set_key_val(msg, "ut_type", "2");
437 	snprintf(buf, sizeof(buf), "%lu", (unsigned long)utx.ut_tv.tv_sec);
438 	asl_msg_set_key_val(msg, ASL_KEY_TIME, buf);
439 	asl_msg_set_key_val(msg, "ut_tv.tv_sec", buf);
440 	snprintf(buf, sizeof(buf), "%u", (unsigned int)utx.ut_tv.tv_usec);
441 	asl_msg_set_key_val(msg, "ut_tv.tv_usec", buf);
442 	snprintf(buf, sizeof(buf), "%u%s", (unsigned int)utx.ut_tv.tv_usec, (utx.ut_tv.tv_usec == 0) ? "" : "000");
443 	asl_msg_set_key_val(msg, ASL_KEY_TIME_NSEC, buf);
444 
445 	process_message(msg, SOURCE_INTERNAL);
446 }
447 
448 int
main(int argc,const char * argv[])449 main(int argc, const char *argv[])
450 {
451 	int32_t i;
452 #if !TARGET_IPHONE_SIMULATOR
453 	int network_change_token;
454 #endif
455 	int quota_file_token, asl_db_token;
456 	char tstr[32], *notify_key;
457 	time_t now;
458 	int first_syslogd_start = 1;
459 
460 #if TARGET_IPHONE_SIMULATOR
461 	const char *sim_log_dir = getenv("SIMULATOR_LOG_ROOT");
462 	const char *sim_resource_dir = getenv("SIMULATOR_SHARED_RESOURCES_DIRECTORY");
463 	char *p;
464 
465 	/* assert is evil */
466 	assert(sim_log_dir && sim_resource_dir);
467 
468 	asprintf((char **)&_path_syslogd_log, "%s/syslogd.log", sim_log_dir);
469 	asprintf((char **)&_path_pidfile, "%s/var/run/syslog.pid", sim_resource_dir);
470 
471 	if (_path_syslogd_log == NULL) _path_syslogd_log = "/tmp/syslogd.log";
472 	else mkpath_np(sim_log_dir, 0755);
473 
474 	if (_path_pidfile == NULL)
475 	{
476 		_path_pidfile = "/tmp/syslog.pid";
477 	}
478 	else
479 	{
480 		p = strrchr(_path_pidfile, '/');
481 		*p = '\0';
482 		mkpath_np(_path_pidfile, 0755);
483 		*p = '/';
484 	}
485 #endif
486 
487 #if TARGET_OS_IPHONE
488 	/*
489 	 * Reset owner, group, and permissions in /var/mobile/Library/Logs
490 	 * in case something created them incorrectly.  syslogd was
491 	 * guilty of this in the past, creating them with owner root.
492 	 */
493 
494 	asl_secure_chown_chmod_dir("/private/var/mobile/Library/Logs", 501, 501, 0755);
495 	asl_secure_chown_chmod_dir("/private/var/mobile/Library/Logs/CrashReporter", 501, 501, 0755);
496 	asl_secure_chown_chmod_dir("/private/var/mobile/Library/Logs/CrashReporter/DiagnosticLogs", 501, 501, 0755);
497 #endif
498 
499 	/* Set I/O policy */
500 	// XXX setiopolicy_np(IOPOL_TYPE_DISK, IOPOL_SCOPE_PROCESS, IOPOL_PASSIVE);
501 
502 #if !TARGET_OS_IPHONE
503 #if 0
504 	/* Set Quarantine */
505 	qtn_proc_t qp = qtn_proc_alloc();
506 	qtn_proc_set_identifier(qp, "com.apple.syslogd");
507 	qtn_proc_set_flags(qp, QTN_FLAG_SANDBOX | QTN_FLAG_HARD);
508 	qtn_proc_apply_to_self(qp);
509 	qtn_proc_free(qp);
510 #endif
511 #endif
512 
513 	memset(&global, 0, sizeof(struct global_s));
514 
515 	global.db_lock = (pthread_mutex_t *)calloc(1, sizeof(pthread_mutex_t));
516 	pthread_mutex_init(global.db_lock, NULL);
517 
518 	/*
519 	 * Create work queue, but suspend until output modules are initialized.
520 	 */
521 	global.work_queue = dispatch_queue_create("Work Queue", NULL);
522 	dispatch_suspend(global.work_queue);
523 
524 	init_globals();
525 
526 #if TARGET_OS_EMBEDDED
527 	remote_enabled = 1;
528 	activate_bsd_out = 0;
529 #endif
530 
531 #if 0
532 	/* prevent malloc from calling ASL on error */
533 	_malloc_no_asl_log = 1;
534 #endif
535 
536 	/* first pass sets up default configurations */
537 	for (i = 1; i < argc; i++)
538 	{
539 		if (streq(argv[i], "-config"))
540 		{
541 			if (((i + 1) < argc) && (argv[i+1][0] != '-'))
542 			{
543 				i++;
544 				if (streq(argv[i], "mac"))
545 				{
546 					global.dbtype = DB_TYPE_FILE;
547 					global.db_file_max = 25600000;
548 				}
549 				else if (streq(argv[i], "appletv"))
550 				{
551 					global.dbtype = DB_TYPE_FILE;
552 					global.db_file_max = 10240000;
553 				}
554 				else if (streq(argv[i], "iphone"))
555 				{
556 #if TARGET_IPHONE_SIMULATOR
557 					global.dbtype = DB_TYPE_FILE;
558 					global.db_file_max = 25600000;
559 #else
560 					global.dbtype = DB_TYPE_MEMORY;
561 					remote_enabled = 1;
562 #endif
563 				}
564 			}
565 		}
566 	}
567 
568 	for (i = 1; i < argc; i++)
569 	{
570 		if (streq(argv[i], "-d"))
571 		{
572 			global.debug = 1;
573 			if (((i+1) < argc) && (argv[i+1][0] != '-')) global.debug_file = strdup(argv[++i]);
574 		}
575 		else if (streq(argv[i], "-db"))
576 		{
577 			if (((i + 1) < argc) && (argv[i+1][0] != '-'))
578 			{
579 				i++;
580 				if (streq(argv[i], "file"))
581 				{
582 					global.dbtype |= DB_TYPE_FILE;
583 					if (((i + 1) < argc) && (argv[i+1][0] != '-')) global.db_file_max = atol(argv[++i]);
584 				}
585 				else if (streq(argv[i], "memory"))
586 				{
587 					global.dbtype |= DB_TYPE_MEMORY;
588 					if (((i + 1) < argc) && (argv[i+1][0] != '-')) global.db_memory_max = atol(argv[++i]);
589 				}
590 			}
591 		}
592 		else if (streq(argv[i], "-m"))
593 		{
594 			if ((i + 1) < argc) global.mark_time = 60 * atoll(argv[++i]);
595 		}
596 		else if (streq(argv[i], "-utmp_ttl"))
597 		{
598 			if ((i + 1) < argc) global.utmp_ttl = atol(argv[++i]);
599 		}
600 		else if (streq(argv[i], "-mps_limit"))
601 		{
602 			if ((i + 1) < argc) global.mps_limit = atol(argv[++i]);
603 		}
604 		else if (streq(argv[i], "-dup_delay"))
605 		{
606 			if ((i + 1) < argc) global.bsd_max_dup_time = atoll(argv[++i]);
607 		}
608 #if !TARGET_IPHONE_SIMULATOR
609 		else if (streq(argv[i], "-klog_in"))
610 		{
611 			if ((i + 1) < argc) activate_klog_in = atoi(argv[++i]);
612 		}
613 		else if (streq(argv[i], "-bsd_in"))
614 		{
615 			if ((i + 1) < argc) activate_bsd_in = atoi(argv[++i]);
616 		}
617 		else if (streq(argv[i], "-udp_in"))
618 		{
619 			if ((i + 1) < argc) activate_udp_in = atoi(argv[++i]);
620 		}
621 #endif
622 		else if (streq(argv[i], "-launchd_in"))
623 		{
624 			if ((i + 1) < argc) global.launchd_enabled = atoi(argv[++i]);
625 		}
626 #if !TARGET_IPHONE_SIMULATOR
627 		else if (streq(argv[i], "-bsd_out"))
628 		{
629 			if ((i + 1) < argc) activate_bsd_out = atoi(argv[++i]);
630 		}
631 		else if (streq(argv[i], "-remote"))
632 		{
633 			if ((i + 1) < argc) remote_enabled = atoi(argv[++i]);
634 		}
635 #endif
636 	}
637 
638 	if (global.dbtype == 0)
639 	{
640 		global.dbtype = DB_TYPE_FILE;
641 		global.db_file_max = 25600000;
642 	}
643 
644 	signal(SIGHUP, SIG_IGN);
645 
646 	memset(tstr, 0, sizeof(tstr));
647 	now = time(NULL);
648 	ctime_r(&now, tstr);
649 	tstr[19] = '\0';
650 	asldebug("\n%s syslogd PID %d starting\n", tstr, global.pid);
651 
652 	writepid(&first_syslogd_start);
653 
654 	/*
655 	 * Log UTMPX boot time record
656 	 */
657 	write_boot_log(first_syslogd_start);
658 
659 	asldebug("reading launch plist\n");
660 	launch_config();
661 
662 	asldebug("initializing modules\n");
663 	init_modules();
664 
665 #if !TARGET_IPHONE_SIMULATOR
666 	asldebug("setting up network change notification handler\n");
667 
668 	/* network change notification resets UDP and BSD modules */
669 #if 0
670 XXX
671 	notify_register_dispatch(kNotifySCNetworkChange, &network_change_token, global.work_queue, ^(int x){
672 		if (activate_udp_in != 0) udp_in_reset();
673 		if (activate_bsd_out != 0) bsd_out_reset();
674 	});
675 #endif
676 #endif
677 
678 	asldebug("setting up quota notification handler\n");
679 
680 	notify_key = NULL;
681 	asprintf(&notify_key, "%s%s", NOTIFY_PATH_SERVICE, NOQUOTA_FILE_PATH);
682 	if (notify_key != NULL)
683 	{
684 		int status;
685 
686 		status = notify_register_dispatch(notify_key, &quota_file_token, dispatch_get_main_queue(), ^(int t){
687 			struct stat sb;
688 			memset(&sb, 0, sizeof(sb));
689 			if (stat(NOQUOTA_FILE_PATH, &sb) == 0)
690 			{
691 				char *str = NULL;
692 				asprintf(&str, "[Sender syslogd] [Level 2] [PID %u] [Facility syslog] [Message *** MESSAGE QUOTAS DISABLED FOR ALL PROCESSES ***]", global.pid);
693 				internal_log_message(str);
694 				free(str);
695 			}
696 			else
697 			{
698 				char *str = NULL;
699 				asprintf(&str, "[Sender syslogd] [Level 2] [PID %u] [Facility syslog] [Message *** MESSAGE QUOTAS ENABLED ***]", global.pid);
700 				internal_log_message(str);
701 				free(str);
702 			}
703 		});
704 
705 		free(notify_key);
706 	}
707 
708 	/* SIGHUP resets all modules */
709 	global.sig_hup_src = dispatch_source_create(DISPATCH_SOURCE_TYPE_SIGNAL, (uintptr_t)SIGHUP, 0, dispatch_get_main_queue());
710 	dispatch_source_set_event_handler(global.sig_hup_src, ^{
711 		dispatch_async(global.work_queue, ^{
712 			int i;
713 
714 			asldebug("SIGHUP reset\n");
715 			for (i = 0; i < global.module_count; i++)
716 			{
717 				if (global.module[i]->enabled != 0) global.module[i]->reset();
718 			}
719 		});
720 	});
721 
722 	dispatch_resume(global.sig_hup_src);
723 
724 	/* register for DB notification (posted by dbserver) for performance */
725 	// XXX notify_register_plain(kNotifyASLDBUpdate, &asl_db_token);
726 
727 	/* timer for MARK facility */
728 	if (global.mark_time > 0)
729 	{
730 		global.mark_timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_main_queue());
731 		dispatch_source_set_event_handler(global.mark_timer, ^{
732 			asl_mark();
733 		});
734 		dispatch_source_set_timer(global.mark_timer, dispatch_time(DISPATCH_TIME_NOW, global.mark_time * NSEC_PER_SEC), global.mark_time * NSEC_PER_SEC, 0);
735 		dispatch_resume(global.mark_timer);
736 	}
737 
738 #if !TARGET_IPHONE_SIMULATOR
739 	asldebug("starting launchd input channel\n");
740 	/*
741 	 * Start launchd service
742 	 * This pins a thread in _vprocmgr_log_drain.  Eventually we will either
743 	 * remove the whole stderr/stdout -> ASL mechanism entirely, or come up
744 	 * with a communication channel that we can trigger with a dispatch source.
745 	 */
746 	dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
747 		for(;;) {
748 			_vprocmgr_log_drain(NULL, NULL, launchd_callback);
749 			sleep(1);
750 		}
751 	});
752 #endif
753 
754 	asldebug("starting mach service\n");
755 	/*
756 	 * Start mach server
757 	 * Parks a thread in database_server.  In notifyd, we found that the overhead of
758 	 * a dispatch source for mach calls was too high, especially on iOS.
759 	 */
760 	dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
761 		database_server();
762 	});
763 
764 	/* go to work */
765 	asldebug("starting work queue\n");
766 	dispatch_resume(global.work_queue);
767 	dispatch_main();
768 
769 	/* NOTREACHED */
770 	return 0;
771 }
772