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