]> git.saurik.com Git - apple/syslog.git/blame - aslmanager.tproj/aslmanager.c
syslog-385.tar.gz
[apple/syslog.git] / aslmanager.tproj / aslmanager.c
CommitLineData
57b0aad2 1/*
5222c21d 2 * Copyright (c) 2007-2015 Apple Inc. All rights reserved.
57b0aad2
A
3 *
4 * @APPLE_LICENSE_HEADER_START@
5222c21d
A
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 */
81582353 23
5222c21d
A
24#include <asl.h>
25#include <asl_msg.h>
26#include <asl_msg_list.h>
27#include <asl_store.h>
28#include <errno.h>
29#include <vproc_priv.h>
86a8bcf5 30#include <os/transaction_private.h>
57b0aad2 31
5222c21d
A
32#include "asl_common.h"
33#include "daemon.h"
57b0aad2 34
5222c21d
A
35/* global */
36bool dryrun;
37uint32_t debug;
38FILE *debugfp;
39dispatch_queue_t work_queue;
81582353 40
5222c21d
A
41static dispatch_queue_t server_queue;
42static time_t module_ttl;
43static xpc_connection_t listener;
44static bool main_task_enqueued;
45static bool initial_main_task = true;
46static dispatch_source_t sig_term_src;
81582353 47
5222c21d
A
48/* wait 5 minutes to run main task after being invoked by XPC */
49#define MAIN_TASK_INITIAL_DELAY 300
81582353 50
5222c21d
A
51/*
52 * Used to set config parameters.
53 * Line format "= name value"
54 */
55static void
56_aslmanager_set_param(asl_out_dst_data_t *dst, char *s)
81582353 57{
5222c21d
A
58 char **l;
59 uint32_t count;
81582353 60
5222c21d
A
61 if (s == NULL) return;
62 if (s[0] == '\0') return;
81582353 63
5222c21d
A
64 /* skip '=' and whitespace */
65 if (*s == '=') s++;
66 while ((*s == ' ') || (*s == '\t')) s++;
81582353 67
5222c21d
A
68 l = explode(s, " \t");
69 if (l == NULL) return;
81582353 70
5222c21d 71 for (count = 0; l[count] != NULL; count++);
81582353 72
5222c21d
A
73 /* name is required */
74 if (count == 0)
81582353 75 {
5222c21d
A
76 free_string_list(l);
77 return;
81582353
A
78 }
79
5222c21d
A
80 /* value is required */
81 if (count == 1)
81582353 82 {
5222c21d
A
83 free_string_list(l);
84 return;
81582353 85 }
57b0aad2 86
5222c21d 87 if (!strcasecmp(l[0], "aslmanager_debug"))
f3df4c03 88 {
5222c21d
A
89 /* = debug level */
90 set_debug(DEBUG_ASL, l[1]);
f3df4c03 91 }
5222c21d 92 else if (!strcasecmp(l[0], "store_ttl"))
81582353 93 {
5222c21d
A
94 /* = store_ttl days */
95 dst->ttl[LEVEL_ALL] = asl_core_str_to_time(l[1], SECONDS_PER_DAY);
57b0aad2 96 }
5222c21d 97 else if (!strcasecmp(l[0], "module_ttl"))
81582353 98 {
5222c21d
A
99 /* = module_ttl days */
100 module_ttl = asl_core_str_to_time(l[1], SECONDS_PER_DAY);
81582353 101 }
5222c21d 102 else if (!strcasecmp(l[0], "max_store_size"))
81582353 103 {
5222c21d
A
104 /* = max_file_size bytes */
105 dst->all_max = asl_core_str_to_size(l[1]);
81582353 106 }
5222c21d 107 else if (!strcasecmp(l[0], "archive"))
81582353 108 {
5222c21d
A
109 free(dst->rotate_dir);
110 dst->rotate_dir = NULL;
81582353 111
5222c21d
A
112 /* = archive {0|1} path */
113 if (!strcmp(l[1], "1"))
114 {
115 if (l[2] == NULL) dst->rotate_dir = strdup(PATH_ASL_ARCHIVE);
116 else dst->rotate_dir = strdup(l[2]);
57b0aad2 117 }
81582353 118 }
5222c21d 119 else if (!strcasecmp(l[0], "store_path"))
81582353 120 {
5222c21d
A
121 /* = archive path */
122 free(dst->path);
123 dst->path = strdup(l[1]);
81582353 124 }
5222c21d 125 else if (!strcasecmp(l[0], "archive_mode"))
c4fdb7d1 126 {
5222c21d
A
127 dst->mode = strtol(l[1], NULL, 0);
128 if ((dst->mode == 0) && (errno == EINVAL)) dst->mode = 0400;
c4fdb7d1 129 }
57b0aad2 130
5222c21d 131 free_string_list(l);
57b0aad2
A
132}
133
81582353
A
134int
135cli_main(int argc, char *argv[])
136{
137 int i, work;
138 asl_out_module_t *mod, *m;
139 asl_out_rule_t *r;
5222c21d 140 asl_out_dst_data_t store, opts, *asl_store_dst = NULL;
81582353 141 const char *mname = NULL;
5222c21d 142 bool quiet = false;
81582353 143
5222c21d 144#if !TARGET_OS_SIMULATOR
81582353
A
145 if (geteuid() != 0)
146 {
147 if (argc == 0) debug = DEBUG_ASL;
148 else debug = DEBUG_STDERR;
149
150 debug_log(ASL_LEVEL_ERR, "aslmanager must be run by root\n");
151 exit(1);
152 }
5222c21d 153#endif
81582353
A
154
155 module_ttl = DEFAULT_TTL;
156
f3df4c03 157 /* cobble up a dst_data with defaults and parameter settings */
81582353 158 memset(&store, 0, sizeof(store));
f3df4c03 159 store.ttl[LEVEL_ALL] = DEFAULT_TTL;
81582353
A
160 store.all_max = DEFAULT_MAX_SIZE;
161
5222c21d
A
162 memset(&opts, 0, sizeof(opts));
163 opts.ttl[LEVEL_ALL] = DEFAULT_TTL;
164 opts.all_max = DEFAULT_MAX_SIZE;
165
f3df4c03
A
166 for (i = 1; i < argc; i++)
167 {
5222c21d
A
168 if (!strcmp(argv[i], "-q"))
169 {
170 quiet = true;
171 }
172 else if (!strcmp(argv[i], "-dd"))
173 {
174 quiet = true;
175 }
176 else if (!strcmp(argv[i], "-s"))
f3df4c03
A
177 {
178 if (((i + 1) < argc) && (argv[i + 1][0] != '-'))
179 {
180 store.path = strdup(argv[++i]);
181 asl_store_dst = &store;
182 }
183 }
184 }
185
5222c21d
A
186 if (!quiet)
187 {
af7d442c 188 char *path = NULL;
5222c21d
A
189 int status = asl_make_database_dir(NULL, NULL);
190 if (status == 0) status = asl_make_database_dir(ASL_INTERNAL_LOGS_DIR, &path);
191 if (status == 0)
192 {
193 char tstamp[32], *str = NULL;
194
195 asl_make_timestamp(time(NULL), MODULE_NAME_STYLE_STAMP_LCL_B, tstamp, sizeof(tstamp));
196 asprintf(&str, "%s/aslmanager.%s", path, tstamp);
197
198 if (str != NULL)
199 {
200 if (status == 0) debugfp = fopen(str, "w");
201 if (debugfp != NULL) debug |= DEBUG_FILE;
202 free(str);
203 }
204 }
af7d442c 205 free(path);
5222c21d
A
206 }
207
81582353
A
208 /* get parameters from asl.conf */
209 mod = asl_out_module_init();
210
211 if (mod != NULL)
212 {
5222c21d 213 for (r = mod->ruleset; (r != NULL) && (asl_store_dst == NULL); r = r->next)
f3df4c03 214 {
5222c21d 215 if ((r->dst != NULL) && (r->action == ACTION_OUT_DEST) && (!strcmp(r->dst->path, PATH_ASL_STORE)))
f3df4c03
A
216 asl_store_dst = r->dst;
217 }
218
81582353
A
219 for (r = mod->ruleset; r != NULL; r = r->next)
220 {
221 if (r->action == ACTION_SET_PARAM)
222 {
f3df4c03 223 if (r->query == NULL) _aslmanager_set_param(asl_store_dst, r->options);
81582353
A
224 }
225 }
226 }
227
228 work = DO_ASLDB | DO_MODULE;
229
230 for (i = 1; i < argc; i++)
231 {
232 if (!strcmp(argv[i], "-a"))
233 {
5222c21d
A
234 if (asl_store_dst == NULL) asl_store_dst = &store;
235
f3df4c03
A
236 if (((i + 1) < argc) && (argv[i + 1][0] != '-')) asl_store_dst->rotate_dir = strdup(argv[++i]);
237 else asl_store_dst->rotate_dir = strdup(PATH_ASL_ARCHIVE);
238 asl_store_dst->mode = 0400;
81582353
A
239 }
240 else if (!strcmp(argv[i], "-store_ttl"))
241 {
5222c21d
A
242 if (((i + 1) < argc) && (argv[i + 1][0] != '-'))
243 {
244 if (asl_store_dst == NULL) asl_store_dst = &store;
245 asl_store_dst->ttl[LEVEL_ALL] = asl_core_str_to_time(argv[++i], SECONDS_PER_DAY);
246 }
81582353
A
247 }
248 else if (!strcmp(argv[i], "-module_ttl"))
249 {
5222c21d 250 if (((i + 1) < argc) && (argv[i + 1][0] != '-')) module_ttl = asl_core_str_to_time(argv[++i], SECONDS_PER_DAY);
81582353
A
251 }
252 else if (!strcmp(argv[i], "-ttl"))
253 {
5222c21d
A
254 if (((i + 1) < argc) && (argv[i + 1][0] != '-'))
255 {
256 opts.ttl[LEVEL_ALL] = asl_core_str_to_time(argv[++i], SECONDS_PER_DAY);
257
258 if (asl_store_dst == NULL) asl_store_dst = &store;
259 asl_store_dst->ttl[LEVEL_ALL] = opts.ttl[LEVEL_ALL];
260
261 module_ttl = opts.ttl[LEVEL_ALL];
262 }
81582353
A
263 }
264 else if (!strcmp(argv[i], "-size"))
265 {
5222c21d
A
266 if (((i + 1) < argc) && (argv[i + 1][0] != '-'))
267 {
268 opts.all_max = asl_core_str_to_size(argv[++i]);
269
270 if (asl_store_dst == NULL) asl_store_dst = &store;
271 asl_store_dst->all_max = opts.all_max;
272 }
81582353
A
273 }
274 else if (!strcmp(argv[i], "-checkpoint"))
275 {
276 work |= DO_CHECKPT;
277 }
278 else if (!strcmp(argv[i], "-module"))
279 {
280 work &= ~DO_ASLDB;
281
282 /* optional name follows -module */
283 if ((i +1) < argc)
284 {
285 if (argv[i + 1][0] != '-') mname = argv[++i];
286 }
287 }
288 else if (!strcmp(argv[i], "-asldb"))
289 {
290 work = DO_ASLDB;
291 }
292 else if (!strcmp(argv[i], "-d"))
293 {
294 if (((i + i) < argc) && (argv[i+1][0] != '-')) set_debug(DEBUG_STDERR, argv[++i]);
295 else set_debug(DEBUG_STDERR, NULL);
296 }
297 else if (!strcmp(argv[i], "-dd"))
298 {
5222c21d 299 dryrun = true;
81582353
A
300
301 if (((i + i) < argc) && (argv[i+1][0] != '-')) set_debug(DEBUG_STDERR, argv[++i]);
5222c21d 302 else set_debug(DEBUG_STDERR, "l7");
81582353
A
303 }
304 }
305
af7d442c 306 if (asl_store_dst != NULL && asl_store_dst->path == NULL) asl_store_dst->path = strdup(PATH_ASL_STORE);
81582353 307
5222c21d
A
308 debug_log(ASL_LEVEL_ERR, "aslmanager starting%s\n", dryrun ? " dryrun" : "");
309
5222c21d 310 if (work & DO_ASLDB) process_asl_data_store(asl_store_dst, &opts);
81582353
A
311
312 if (work & DO_MODULE)
313 {
314 if (work & DO_CHECKPT) checkpoint(mname);
315
316 if (mod != NULL)
317 {
318 for (m = mod; m != NULL; m = m->next)
319 {
5222c21d 320 if (mname == NULL)
81582353 321 {
5222c21d
A
322 process_module(m, NULL);
323 }
324 else if ((m->name != NULL) && (!strcmp(m->name, mname)))
325 {
326 process_module(m, &opts);
81582353
A
327 }
328 }
329 }
330 }
331
332 asl_out_module_free(mod);
333
334 debug_log(ASL_LEVEL_NOTICE, "----------------------------------------\n");
5222c21d
A
335 debug_log(ASL_LEVEL_ERR, "aslmanager finished%s\n", dryrun ? " dryrun" : "");
336 debug_close();
81582353
A
337
338 return 0;
339}
340
5222c21d
A
341/* dispatched on server_queue, dispatches to work_queue */
342void
343main_task(void)
344{
345 /* if main task is already running or queued, do nothing */
346 if (main_task_enqueued) return;
347
348 main_task_enqueued = true;
86a8bcf5
A
349
350 os_transaction_t transaction = os_transaction_create("com.apple.aslmanager");
5222c21d
A
351
352 if (initial_main_task)
353 {
354 initial_main_task = false;
355 dispatch_time_t delay = dispatch_walltime(NULL, MAIN_TASK_INITIAL_DELAY * NSEC_PER_SEC);
356
357 dispatch_after(delay, work_queue, ^{
358 cli_main(0, NULL);
359 main_task_enqueued = false;
86a8bcf5 360 os_release(transaction);
5222c21d
A
361 });
362 }
363 else
364 {
365 dispatch_async(work_queue, ^{
366 cli_main(0, NULL);
367 main_task_enqueued = false;
86a8bcf5 368 os_release(transaction);
5222c21d
A
369 });
370 }
371}
372
81582353
A
373static void
374accept_connection(xpc_connection_t peer)
375{
376 xpc_connection_set_event_handler(peer, ^(xpc_object_t request) {
377 if (xpc_get_type(request) == XPC_TYPE_DICTIONARY)
378 {
379 uid_t uid = xpc_connection_get_euid(peer);
380
381 /* send a reply immediately */
382 xpc_object_t reply = xpc_dictionary_create_reply(request);
86a8bcf5
A
383 if (reply != NULL)
384 {
385 xpc_connection_send_message(peer, reply);
386 xpc_release(reply);
387 }
81582353
A
388
389 /*
390 * Some day, we may use the dictionary to pass parameters
391 * to aslmanager, but for now, we ignore the input.
392 */
5222c21d
A
393
394 if (uid == geteuid())
395 {
396 main_task();
397 }
81582353
A
398 }
399 else if (xpc_get_type(request) == XPC_TYPE_ERROR)
400 {
401 /* disconnect */
402 }
81582353
A
403 });
404
405 xpc_connection_resume(peer);
406}
407
408int
409main(int argc, char *argv[])
410{
411 int64_t is_managed = 0;
412
413 vproc_swap_integer(NULL, VPROC_GSK_IS_MANAGED, NULL, &is_managed);
414
415 if (is_managed == 0) return cli_main(argc, argv);
416
5222c21d
A
417 /* Set I/O policy */
418 setiopolicy_np(IOPOL_TYPE_DISK, IOPOL_SCOPE_PROCESS, IOPOL_THROTTLE);
419
81582353 420 /* XPC server */
5222c21d
A
421 server_queue = dispatch_queue_create("aslmanager", NULL);
422
423 work_queue = dispatch_queue_create("work queue", NULL);
424
425 /* Exit on SIGTERM */
426 signal(SIGTERM, SIG_IGN);
427 sig_term_src = dispatch_source_create(DISPATCH_SOURCE_TYPE_SIGNAL, (uintptr_t)SIGTERM, 0, dispatch_get_main_queue());
428 dispatch_source_set_event_handler(sig_term_src, ^{
429 debug_log(ASL_LEVEL_NOTICE, "SIGTERM exit\n");
430 exit(0);
431 });
432
433 dispatch_resume(sig_term_src);
81582353
A
434
435 /* Handle incoming messages. */
5222c21d 436 listener = xpc_connection_create_mach_service("com.apple.aslmanager", server_queue, XPC_CONNECTION_MACH_SERVICE_LISTENER);
81582353
A
437 xpc_connection_set_event_handler(listener, ^(xpc_object_t peer) {
438 if (xpc_get_type(peer) == XPC_TYPE_CONNECTION) accept_connection(peer);
439 });
440 xpc_connection_resume(listener);
441
442 dispatch_main();
443}