]> git.saurik.com Git - apple/syslog.git/blame - aslmanager.tproj/aslmanager.c
syslog-217.1.4.tar.gz
[apple/syslog.git] / aslmanager.tproj / aslmanager.c
CommitLineData
57b0aad2 1/*
c4fdb7d1 2 * Copyright (c) 2007-2009 Apple Inc. All rights reserved.
57b0aad2
A
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 <stdio.h>
25#include <dirent.h>
26#include <string.h>
27#include <stdlib.h>
28#include <unistd.h>
29#include <stdint.h>
30#include <errno.h>
31#include <time.h>
32#include <sys/time.h>
33#include <sys/stat.h>
81582353
A
34#include <sys/param.h>
35#include <servers/bootstrap.h>
36#include <bootstrap_priv.h>
37#include <mach/mach.h>
a83ff38a 38#include <copyfile.h>
81582353
A
39#include <fcntl.h>
40#include <zlib.h>
41#include <xpc/xpc.h>
42#include <xpc/private.h>
43#include <os/assumes.h>
44#include <vproc_priv.h>
57b0aad2
A
45#include <asl.h>
46#include <asl_private.h>
47#include <asl_core.h>
48#include <asl_file.h>
49#include <asl_store.h>
81582353 50#include "asl_common.h"
57b0aad2 51
c4fdb7d1 52#define DEFAULT_MAX_SIZE 150000000
81582353
A
53#define IOBUFSIZE 4096
54
55#define DO_ASLDB 0x00000001
56#define DO_MODULE 0x00000002
57#define DO_CHECKPT 0x00000004
58
59#define DEBUG_FLAG_MASK 0xfffffff0
60#define DEBUG_LEVEL_MASK 0x0000000f
61#define DEBUG_STDERR 0x00000010
62#define DEBUG_ASL 0x00000020
63
64extern kern_return_t _asl_server_query
65(
66 mach_port_t server,
67 caddr_t request,
68 mach_msg_type_number_t requestCnt,
69 uint64_t startid,
70 int count,
71 int flags,
72 caddr_t *reply,
73 mach_msg_type_number_t *replyCnt,
74 uint64_t *lastid,
75 int *status,
76 security_token_t *token
77);
c4fdb7d1
A
78
79/* global */
81582353
A
80static time_t module_ttl;
81static uint32_t debug;
82static int dryrun;
83static int asl_aux_fd = -1;
84static aslclient aslc;
85static mach_port_t asl_server_port;
86static xpc_connection_t listener;
87static dispatch_queue_t serverq;
94194072 88
57b0aad2
A
89typedef struct name_list_s
90{
91 char *name;
92 size_t size;
93 struct name_list_s *next;
94} name_list_t;
95
81582353
A
96void
97set_debug(int flag, const char *str)
98{
99 int level, x;
100
101 if (str == NULL) x = ASL_LEVEL_ERR;
102 else if (((str[0] == 'L') || (str[0] == 'l')) && ((str[1] >= '0') && (str[1] <= '7')) && (str[2] == '\0')) x = atoi(str+1);
103 else if ((str[0] >= '0') && (str[0] <= '7') && (str[1] == '\0')) x = ASL_LEVEL_CRIT + atoi(str);
104 else x = ASL_LEVEL_ERR;
105
106 if (x <= 0) x = 0;
107 else if (x > 7) x = 7;
108
109 level = debug & DEBUG_LEVEL_MASK;
110 if (x > level) level = x;
111
112 debug = debug & DEBUG_FLAG_MASK;
113 debug |= flag;
114 debug |= level;
115}
116
117void
118debug_log(int level, const char *str, ...)
119{
120 va_list v;
121
122 if ((debug & DEBUG_STDERR) && (level <= (debug & DEBUG_LEVEL_MASK)))
123 {
124 va_start(v, str);
125 vfprintf(stderr, str, v);
126 va_end(v);
127 }
128
129 if (debug & DEBUG_ASL)
130 {
131 char *line = NULL;
132
133 if (aslc == NULL)
134 {
135 aslc = asl_open("aslmanager", "syslog", 0);
136 aslmsg msg = asl_new(ASL_TYPE_MSG);
137
138 asl_set(msg, ASL_KEY_MSG, "Status Report");
139 asl_set(msg, ASL_KEY_LEVEL, ASL_STRING_NOTICE);
140 asl_create_auxiliary_file(msg, "Status Report", "public.text", &asl_aux_fd);
141 asl_free(msg);
142 }
143
144 va_start(v, str);
145 vasprintf(&line, str, v);
146 va_end(v);
147
148 if (line != NULL) write(asl_aux_fd, line, strlen(line));
149 free(line);
150 }
151}
152
153__attribute__((noreturn)) static void
154xpc_server_exit(int status)
155{
156 xpc_connection_cancel(listener);
157 xpc_release(listener);
158 dispatch_release(serverq);
159 exit(status);
160}
161
57b0aad2 162name_list_t *
81582353 163add_to_name_list(name_list_t *l, const char *name, size_t size)
57b0aad2
A
164{
165 name_list_t *e, *x;
166
167 if (name == NULL) return l;
168
169 e = (name_list_t *)calloc(1, sizeof(name_list_t));
170 if (e == NULL) return NULL;
171
172 e->name = strdup(name);
173 if (e->name == NULL)
174 {
175 free(e);
176 return NULL;
177 }
178
179 e->size = size;
180
181 /* list is sorted by name (i.e. primarily by timestamp) */
182 if (l == NULL) return e;
183
184 if (strcmp(e->name, l->name) <= 0)
185 {
186 e->next = l;
187 return e;
188 }
189
190 for (x = l; (x->next != NULL) && (strcmp(e->name, x->next->name) > 0) ; x = x->next);
191
192 e->next = x->next;
193 x->next = e;
194 return l;
195}
196
197void
81582353 198free_name_list(name_list_t *l)
57b0aad2
A
199{
200 name_list_t *e;
201
202 while (l != NULL)
203 {
204 e = l;
205 l = l->next;
206 free(e->name);
207 free(e);
208 }
209
210 free(l);
211}
212
81582353
A
213/*
214 * Copy ASL files by reading and writing each record.
215 * Setting ASL_FILE_FLAG_UNLIMITED_CACHE when copying optimizes tring uniquing.
216 */
57b0aad2 217uint32_t
81582353 218copy_asl_file(const char *src, const char *dst, mode_t mode)
57b0aad2 219{
c4fdb7d1
A
220 asl_search_result_t *res;
221 asl_file_t *f;
57b0aad2 222 uint32_t status, i;
57b0aad2
A
223 uint64_t mid;
224
81582353
A
225 if (src == NULL) return ASL_STATUS_INVALID_ARG;
226 if (dst == NULL) return ASL_STATUS_INVALID_ARG;
57b0aad2 227
c4fdb7d1 228 f = NULL;
81582353 229 status = asl_file_open_read(src, &f);
57b0aad2
A
230 if (status != ASL_STATUS_OK) return status;
231
c4fdb7d1
A
232 res = NULL;
233 mid = 0;
57b0aad2 234
c4fdb7d1
A
235 status = asl_file_match(f, NULL, &res, &mid, 0, 0, 1);
236 asl_file_close(f);
237
238 if (status != ASL_STATUS_OK) return status;
81582353 239 if (res == NULL) return ASL_STATUS_OK;
c4fdb7d1
A
240 if (res->count == 0)
241 {
242 aslresponse_free(res);
243 return ASL_STATUS_OK;
244 }
245
246 f = NULL;
81582353 247 status = asl_file_open_write(dst, mode, -1, -1, &f);
c4fdb7d1
A
248 if (status != ASL_STATUS_OK) return status;
249 if (f == ASL_STATUS_OK) return ASL_STATUS_FAILED;
250
251 f->flags = ASL_FILE_FLAG_UNLIMITED_CACHE | ASL_FILE_FLAG_PRESERVE_MSG_ID;
252
253 for (i = 0; i < res->count; i++)
57b0aad2 254 {
c4fdb7d1 255 mid = 0;
a83ff38a 256 status = asl_file_save(f, (aslmsg)(res->msg[i]), &mid);
c4fdb7d1
A
257 if (status != ASL_STATUS_OK) break;
258 }
259
260 asl_file_close(f);
261 return status;
262}
263
a83ff38a 264int
81582353 265copy_compress_file(asl_out_dst_data_t *asldst, const char *src, const char *dst)
a83ff38a 266{
81582353
A
267 int in, out;
268 size_t n;
269 gzFile gz;
270 char buf[IOBUFSIZE];
a83ff38a 271
81582353
A
272 in = open(src, O_RDONLY, 0);
273 if (in < 0) return -1;
a83ff38a 274
81582353
A
275 out = open(dst, O_WRONLY | O_CREAT, asldst->mode);
276 if (out >= 0) out = asl_out_dst_set_access(out, asldst);
277 if (out < 0)
278 {
279 close(in);
280 return -1;
281 }
a83ff38a 282
81582353
A
283 gz = gzdopen(out, "w");
284 if (gz == NULL)
a83ff38a 285 {
81582353
A
286 close(in);
287 close(out);
288 return -1;
a83ff38a
A
289 }
290
81582353
A
291 do {
292 n = read(in, buf, sizeof(buf));
293 if (n > 0) gzwrite(gz, buf, n);
294 } while (n == IOBUFSIZE);
a83ff38a 295
81582353
A
296 gzclose(gz);
297 close(in);
298 close(out);
a83ff38a 299
81582353
A
300 return 0;
301}
a83ff38a 302
81582353
A
303int32_t
304filesystem_copy(asl_out_dst_data_t *asldst, const char *src, const char *dst, uint32_t flags)
c4fdb7d1 305{
81582353 306 char *dot;
c4fdb7d1 307
81582353 308 if ((src == NULL) || (dst == NULL)) return 0;
c4fdb7d1 309
81582353
A
310 dot = strrchr(src, '.');
311 if ((dot != NULL) && (!strcmp(dot, ".gz"))) flags &= ~MODULE_FLAG_COMPRESS;
57b0aad2 312
81582353 313 if (((flags & MODULE_FLAG_COMPRESS) == 0) && (!strcmp(src, dst))) return 0;
c4fdb7d1 314
81582353
A
315 if (flags & MODULE_FLAG_TYPE_ASL) debug_log(ASL_LEVEL_NOTICE, " copy asl %s ---> %s\n", src, dst);
316 else if (flags & MODULE_FLAG_COMPRESS) debug_log(ASL_LEVEL_NOTICE, " copy compress %s ---> %s.gz\n", src, dst);
317 else debug_log(ASL_LEVEL_NOTICE, " copy %s ---> %s\n", src, dst);
c4fdb7d1 318
81582353 319 if (dryrun == 1) return 0;
57b0aad2 320
81582353 321 if (flags & MODULE_FLAG_TYPE_ASL)
c4fdb7d1 322 {
81582353
A
323 uint32_t status = copy_asl_file(src, dst, asldst->mode);
324 if (status != 0)
57b0aad2 325 {
81582353
A
326 debug_log(ASL_LEVEL_ERR, " FAILED status %u [%s] asl copy %s ---> %s\n", status, asl_core_error(status), src, dst);
327 return 0;
57b0aad2 328 }
c4fdb7d1 329 }
81582353
A
330 else if (flags & MODULE_FLAG_COMPRESS)
331 {
332 char gzdst[MAXPATHLEN];
c4fdb7d1 333
81582353 334 snprintf(gzdst, sizeof(gzdst), "%s.gz", dst);
c4fdb7d1 335
81582353
A
336 int status = copy_compress_file(asldst, src, gzdst);
337 if (status != 0)
338 {
339 debug_log(ASL_LEVEL_ERR, " FAILED status %d errno %d [%s] copy & compress %s ---> %s\n", status, errno, strerror(errno), src, dst);
340 return 0;
341 }
342 }
343 else
344 {
345 int status = copyfile(src, dst, NULL, COPYFILE_ALL | COPYFILE_RECURSIVE);
346 if (status != 0)
347 {
348 debug_log(ASL_LEVEL_ERR, " FAILED status %d errno %d [%s] copy %s ---> %s\n", status, errno, strerror(errno), src, dst);
349 return 0;
350 }
351 }
352
353 return 1;
c4fdb7d1
A
354}
355
81582353
A
356void
357filesystem_rename(const char *src, const char *dst)
c4fdb7d1 358{
81582353 359 int status = 0;
c4fdb7d1 360
81582353
A
361 debug_log(ASL_LEVEL_NOTICE, " rename %s ---> %s\n", src, dst);
362 if (dryrun == 1) return;
c4fdb7d1 363
81582353
A
364 status = rename(src, dst);
365 if (status != 0) debug_log(ASL_LEVEL_ERR, " FAILED status %d errno %d [%s] rename %s ---> %s\n", status, errno, strerror(errno), src, dst);
366}
c4fdb7d1 367
81582353
A
368void
369filesystem_unlink(const char *path)
370{
371 int status = 0;
c4fdb7d1 372
81582353
A
373 debug_log(ASL_LEVEL_NOTICE, " remove %s\n", path);
374 if (dryrun == 1) return;
57b0aad2 375
81582353
A
376 status = unlink(path);
377 if (status != 0) debug_log(ASL_LEVEL_ERR, " FAILED status %d errno %d [%s] unlink %s\n", status, errno, strerror(errno), path);
c4fdb7d1 378}
57b0aad2 379
c4fdb7d1 380void
81582353 381filesystem_rmdir(const char *path)
c4fdb7d1 382{
81582353 383 int status = 0;
57b0aad2 384
81582353
A
385 debug_log(ASL_LEVEL_NOTICE, " remove directory %s\n", path);
386 if (dryrun == 1) return;
387
388 status = rmdir(path);
389 if (status != 0) debug_log(ASL_LEVEL_ERR, " FAILED status %d errno %d [%s] rmdir %s\n", status, errno, strerror(errno), path);
390}
391
392int
393remove_directory(const char *path)
394{
395 DIR *dp;
396 struct dirent *dent;
397 char *str;
398
399 dp = opendir(path);
400 if (dp == NULL) return 0;
401
402 while ((dent = readdir(dp)) != NULL)
403 {
404 if ((!strcmp(dent->d_name, ".")) || (!strcmp(dent->d_name, ".."))) continue;
405 asprintf(&str, "%s/%s", path, dent->d_name);
406 if (str != NULL)
407 {
408 filesystem_unlink(str);
409 free(str);
410 str = NULL;
411 }
412 }
413
414 closedir(dp);
415 filesystem_rmdir(path);
416
417 return 0;
c4fdb7d1
A
418}
419
420/*
81582353 421 * Used to set config parameters.
c4fdb7d1
A
422 * Line format "= name value"
423 */
424static void
81582353 425_aslmanager_set_param(asl_out_dst_data_t *dst, char *s)
c4fdb7d1
A
426{
427 char **l;
428 uint32_t count;
429
430 if (s == NULL) return;
431 if (s[0] == '\0') return;
432
433 /* skip '=' and whitespace */
81582353 434 if (*s == '=') s++;
c4fdb7d1
A
435 while ((*s == ' ') || (*s == '\t')) s++;
436
437 l = explode(s, " \t");
438 if (l == NULL) return;
439
440 for (count = 0; l[count] != NULL; count++);
441
442 /* name is required */
443 if (count == 0)
57b0aad2 444 {
81582353 445 free_string_list(l);
c4fdb7d1 446 return;
57b0aad2
A
447 }
448
c4fdb7d1
A
449 /* value is required */
450 if (count == 1)
451 {
81582353 452 free_string_list(l);
c4fdb7d1
A
453 return;
454 }
57b0aad2 455
c4fdb7d1
A
456 if (!strcasecmp(l[0], "aslmanager_debug"))
457 {
81582353
A
458 /* = debug level */
459 set_debug(DEBUG_ASL, l[1]);
c4fdb7d1
A
460 }
461 else if (!strcasecmp(l[0], "store_ttl"))
462 {
463 /* = store_ttl days */
81582353
A
464 dst->ttl = (time_t)atoll(l[1]);
465 }
466 else if (!strcasecmp(l[0], "module_ttl"))
467 {
468 /* = module_ttl days */
469 module_ttl = (time_t)atoll(l[1]);
c4fdb7d1
A
470 }
471 else if (!strcasecmp(l[0], "max_store_size"))
472 {
473 /* = max_file_size bytes */
81582353 474 dst->all_max = atoi(l[1]);
c4fdb7d1
A
475 }
476 else if (!strcasecmp(l[0], "archive"))
477 {
81582353
A
478 free(dst->rotate_dir);
479 dst->rotate_dir = NULL;
480
c4fdb7d1
A
481 /* = archive {0|1} path */
482 if (!strcmp(l[1], "1"))
483 {
81582353
A
484 if (l[2] == NULL) dst->rotate_dir = strdup(PATH_ASL_ARCHIVE);
485 else dst->rotate_dir = strdup(l[2]);
c4fdb7d1 486 }
c4fdb7d1
A
487 }
488 else if (!strcasecmp(l[0], "store_path"))
489 {
490 /* = archive path */
81582353
A
491 free(dst->path);
492 dst->path = strdup(l[1]);
c4fdb7d1
A
493 }
494 else if (!strcasecmp(l[0], "archive_mode"))
495 {
81582353
A
496 dst->mode = strtol(l[1], NULL, 0);
497 if ((dst->mode == 0) && (errno == EINVAL)) dst->mode = 0400;
c4fdb7d1 498 }
57b0aad2 499
81582353 500 free_string_list(l);
57b0aad2
A
501}
502
a83ff38a
A
503size_t
504directory_size(const char *path)
505{
506 DIR *dp;
507 struct dirent *dent;
508 struct stat sb;
509 size_t size;
510 char *str;
511
512 dp = opendir(path);
513 if (dp == NULL) return 0;
514
515 size = 0;
516 while ((dent = readdir(dp)) != NULL)
517 {
518 if ((!strcmp(dent->d_name, ".")) || (!strcmp(dent->d_name, ".."))) continue;
519
520 memset(&sb, 0, sizeof(struct stat));
521 str = NULL;
522 asprintf(&str, "%s/%s", path, dent->d_name);
523
524 if ((str != NULL) && (stat(str, &sb) == 0) && S_ISREG(sb.st_mode))
525 {
526 size += sb.st_size;
527 free(str);
528 }
529 }
530
531 closedir(dp);
532 return size;
533}
534
81582353
A
535static int
536process_asl_data_store(asl_out_dst_data_t *dst)
57b0aad2 537{
81582353
A
538 int32_t today_ymd_stringlen, expire_ymd_stringlen;
539 time_t now, ttl, ymd_expire;
57b0aad2 540 struct tm ctm;
c4fdb7d1 541 char today_ymd_string[32], expire_ymd_string[32], *str;
57b0aad2
A
542 DIR *dp;
543 struct dirent *dent;
a83ff38a 544 name_list_t *ymd_list, *bb_list, *aux_list, *bb_aux_list, *e;
c4fdb7d1 545 size_t file_size, store_size;
57b0aad2
A
546 struct stat sb;
547
c4fdb7d1
A
548 ymd_list = NULL;
549 bb_list = NULL;
a83ff38a
A
550 aux_list = NULL;
551 bb_aux_list = NULL;
57b0aad2 552 store_size = 0;
57b0aad2 553
81582353
A
554 if (dst == NULL) return 0;
555 if (dst->path == NULL) return 0;
c4fdb7d1 556
81582353
A
557 debug_log(ASL_LEVEL_NOTICE, "----------------------------------------\n");
558 debug_log(ASL_LEVEL_NOTICE, "Processing data store %s\n", dst->path);
c4fdb7d1 559
81582353 560 if (dst->rotate_dir != NULL)
57b0aad2 561 {
81582353 562 /* check archive */
57b0aad2 563 memset(&sb, 0, sizeof(struct stat));
81582353 564 if (stat(dst->rotate_dir, &sb) == 0)
57b0aad2
A
565 {
566 /* must be a directory */
a83ff38a 567 if (!S_ISDIR(sb.st_mode))
57b0aad2 568 {
81582353 569 debug_log(ASL_LEVEL_ERR, "aslmanager error: archive %s is not a directory", dst->rotate_dir);
57b0aad2
A
570 return -1;
571 }
572 }
573 else
574 {
575 if (errno == ENOENT)
576 {
577 /* archive doesn't exist - create it */
81582353 578 if (mkdir(dst->rotate_dir, 0755) != 0)
57b0aad2 579 {
81582353 580 debug_log(ASL_LEVEL_ERR, "aslmanager error: can't create archive %s: %s\n", dst->rotate_dir, strerror(errno));
57b0aad2 581 return -1;
c4fdb7d1 582 }
57b0aad2
A
583 }
584 else
585 {
586 /* stat failed for some other reason */
81582353 587 debug_log(ASL_LEVEL_ERR, "aslmanager error: can't stat archive %s: %s\n", dst->rotate_dir, strerror(errno));
57b0aad2
A
588 return -1;
589 }
590 }
591 }
592
81582353 593 chdir(dst->path);
57b0aad2 594
c4fdb7d1 595 /* determine current time */
57b0aad2 596 now = time(NULL);
57b0aad2 597
c4fdb7d1
A
598 /* ttl 0 means files never expire */
599 ymd_expire = 0;
81582353
A
600 ttl = dst->ttl * SECONDS_PER_DAY;
601
602 if ((ttl > 0) && (ttl <= now)) ymd_expire = now - ttl;
c4fdb7d1
A
603
604 /* construct today's date as YYYY.MM.DD */
57b0aad2 605 memset(&ctm, 0, sizeof(struct tm));
c4fdb7d1 606 if (localtime_r((const time_t *)&now, &ctm) == NULL) return -1;
57b0aad2 607
c4fdb7d1
A
608 snprintf(today_ymd_string, sizeof(today_ymd_string), "%d.%02d.%02d.", ctm.tm_year + 1900, ctm.tm_mon + 1, ctm.tm_mday);
609 today_ymd_stringlen = strlen(today_ymd_string);
57b0aad2 610
c4fdb7d1
A
611 /* construct regular file expiry date as YYYY.MM.DD */
612 memset(&ctm, 0, sizeof(struct tm));
613 if (localtime_r((const time_t *)&ymd_expire, &ctm) == NULL) return -1;
57b0aad2 614
c4fdb7d1
A
615 snprintf(expire_ymd_string, sizeof(expire_ymd_string), "%d.%02d.%02d.", ctm.tm_year + 1900, ctm.tm_mon + 1, ctm.tm_mday);
616 expire_ymd_stringlen = strlen(expire_ymd_string);
57b0aad2 617
81582353 618 debug_log(ASL_LEVEL_NOTICE, "Expiry Date %s\n", expire_ymd_string);
57b0aad2 619
81582353 620 dp = opendir(dst->path);
c4fdb7d1
A
621 if (dp == NULL) return -1;
622
a83ff38a 623 /* gather a list of YMD files, AUX dirs, BB.AUX dirs, and BB files */
57b0aad2
A
624 while ((dent = readdir(dp)) != NULL)
625 {
57b0aad2
A
626 memset(&sb, 0, sizeof(struct stat));
627 file_size = 0;
628 if (stat(dent->d_name, &sb) == 0) file_size = sb.st_size;
57b0aad2 629
c4fdb7d1
A
630 if ((dent->d_name[0] >= '0') && (dent->d_name[0] <= '9'))
631 {
81582353 632 ymd_list = add_to_name_list(ymd_list, dent->d_name, file_size);
c4fdb7d1
A
633 store_size += file_size;
634 }
a83ff38a
A
635 else if (!strncmp(dent->d_name, "AUX.", 4) && (dent->d_name[4] >= '0') && (dent->d_name[4] <= '9') && S_ISDIR(sb.st_mode))
636 {
637 file_size = directory_size(dent->d_name);
81582353 638 aux_list = add_to_name_list(aux_list, dent->d_name, file_size);
a83ff38a
A
639 store_size += file_size;
640 }
641 else if (!strncmp(dent->d_name, "BB.AUX.", 7) && (dent->d_name[7] >= '0') && (dent->d_name[7] <= '9') && S_ISDIR(sb.st_mode))
642 {
643 file_size = directory_size(dent->d_name);
81582353 644 bb_aux_list = add_to_name_list(bb_aux_list, dent->d_name, file_size);
a83ff38a
A
645 store_size += file_size;
646 }
c4fdb7d1
A
647 else if (!strncmp(dent->d_name, "BB.", 3) && (dent->d_name[3] >= '0') && (dent->d_name[3] <= '9'))
648 {
81582353 649 bb_list = add_to_name_list(bb_list, dent->d_name, file_size);
c4fdb7d1
A
650 store_size += file_size;
651 }
652 else if ((!strcmp(dent->d_name, ".")) || (!strcmp(dent->d_name, "..")))
653 {}
654 else if ((!strcmp(dent->d_name, "StoreData")) || (!strcmp(dent->d_name, "SweepStore")))
655 {}
656 else
657 {
81582353 658 debug_log(ASL_LEVEL_ERR, "aslmanager: unexpected file %s in ASL data store\n", dent->d_name);
c4fdb7d1 659 }
57b0aad2
A
660 }
661
662 closedir(dp);
663
81582353
A
664 debug_log(ASL_LEVEL_NOTICE, "Data Store Size = %lu\n", store_size);
665 debug_log(ASL_LEVEL_NOTICE, "Data Store YMD Files\n");
666 for (e = ymd_list; e != NULL; e = e->next) debug_log(ASL_LEVEL_NOTICE, " %s %lu\n", e->name, e->size);
667 debug_log(ASL_LEVEL_NOTICE, "Data Store AUX Directories\n");
668 for (e = aux_list; e != NULL; e = e->next) debug_log(ASL_LEVEL_NOTICE, " %s %lu\n", e->name, e->size);
669 debug_log(ASL_LEVEL_NOTICE, "Data Store BB.AUX Directories\n");
670 for (e = bb_aux_list; e != NULL; e = e->next) debug_log(ASL_LEVEL_NOTICE, " %s %lu\n", e->name, e->size);
671 debug_log(ASL_LEVEL_NOTICE, "Data Store BB Files\n");
672 for (e = bb_list; e != NULL; e = e->next) debug_log(ASL_LEVEL_NOTICE, " %s %lu\n", e->name, e->size);
57b0aad2 673
c4fdb7d1 674 /* Delete/achive expired YMD files */
81582353 675 debug_log(ASL_LEVEL_NOTICE, "Start YMD File Scan\n");
57b0aad2 676
c4fdb7d1 677 e = ymd_list;
57b0aad2
A
678 while (e != NULL)
679 {
c4fdb7d1
A
680 /* stop when a file name/date is after the expire date */
681 if (strncmp(e->name, expire_ymd_string, expire_ymd_stringlen) > 0) break;
57b0aad2 682
81582353 683 if (dst->rotate_dir != NULL)
c4fdb7d1
A
684 {
685 str = NULL;
81582353 686 asprintf(&str, "%s/%s", dst->rotate_dir, e->name);
c4fdb7d1 687 if (str == NULL) return -1;
57b0aad2 688
81582353 689 filesystem_copy(dst, e->name, str, 0);
c4fdb7d1
A
690 free(str);
691 }
692
81582353 693 filesystem_unlink(e->name);
c4fdb7d1
A
694 store_size -= e->size;
695 e->size = 0;
57b0aad2 696
c4fdb7d1
A
697 e = e->next;
698 }
57b0aad2 699
81582353 700 debug_log(ASL_LEVEL_NOTICE, "Finished YMD File Scan\n");
a83ff38a
A
701
702 /* Delete/achive expired YMD AUX directories */
81582353 703 debug_log(ASL_LEVEL_NOTICE, "Start AUX Directory Scan\n");
a83ff38a
A
704
705 e = aux_list;
706 while (e != NULL)
707 {
708 /* stop when a file name/date is after the expire date */
709 if (strncmp(e->name + 4, expire_ymd_string, expire_ymd_stringlen) > 0) break;
710
81582353 711 if (dst->rotate_dir != NULL)
a83ff38a
A
712 {
713 str = NULL;
81582353 714 asprintf(&str, "%s/%s", dst->rotate_dir, e->name);
a83ff38a
A
715 if (str == NULL) return -1;
716
81582353 717 filesystem_copy(dst, e->name, str, 0);
a83ff38a
A
718 free(str);
719 }
720
a83ff38a 721 remove_directory(e->name);
a83ff38a
A
722 store_size -= e->size;
723 e->size = 0;
724
725 e = e->next;
726 }
727
81582353 728 debug_log(ASL_LEVEL_NOTICE, "Finished AUX Directory Scan\n");
a83ff38a
A
729
730 /* Delete/achive expired BB.AUX directories */
81582353 731 debug_log(ASL_LEVEL_NOTICE, "Start BB.AUX Directory Scan\n");
a83ff38a
A
732
733 e = bb_aux_list;
734 while (e != NULL)
735 {
736 /* stop when a file name/date is after the expire date */
737 if (strncmp(e->name + 7, today_ymd_string, today_ymd_stringlen) > 0) break;
738
81582353 739 if (dst->rotate_dir != NULL)
a83ff38a
A
740 {
741 str = NULL;
81582353 742 asprintf(&str, "%s/%s", dst->rotate_dir, e->name);
a83ff38a
A
743 if (str == NULL) return -1;
744
81582353 745 filesystem_copy(dst, e->name, str, 0);
a83ff38a
A
746 free(str);
747 }
748
a83ff38a 749 remove_directory(e->name);
a83ff38a
A
750 store_size -= e->size;
751 e->size = 0;
752
753 e = e->next;
754 }
755
81582353 756 debug_log(ASL_LEVEL_NOTICE, "Finished BB.AUX Directory Scan\n");
57b0aad2 757
c4fdb7d1 758 /* Delete/achive expired BB files */
81582353 759 debug_log(ASL_LEVEL_NOTICE, "Start BB Scan\n");
57b0aad2 760
c4fdb7d1
A
761 e = bb_list;
762 while (e != NULL)
763 {
764 /* stop when a file name/date is after the expire date */
765 if (strncmp(e->name + 3, today_ymd_string, today_ymd_stringlen) > 0) break;
57b0aad2 766
81582353 767 if (dst->rotate_dir != NULL)
57b0aad2
A
768 {
769 str = NULL;
81582353 770 asprintf(&str, "%s/%s", dst->rotate_dir, e->name);
c4fdb7d1 771 if (str == NULL) return -1;
57b0aad2 772
c4fdb7d1 773 /* syslog -x [str] -f [e->name] */
81582353 774 filesystem_copy(dst, e->name, str, 0);
57b0aad2
A
775 free(str);
776 }
777
81582353 778 filesystem_unlink(e->name);
57b0aad2
A
779 store_size -= e->size;
780 e->size = 0;
781
782 e = e->next;
783 }
784
81582353 785 debug_log(ASL_LEVEL_NOTICE, "Finished BB Scan\n");
57b0aad2 786
81582353
A
787 if (dst->all_max > 0)
788 {
789 /* if data store is over max_size, delete/archive more YMD files */
790 if (store_size > dst->all_max) debug_log(ASL_LEVEL_NOTICE, "Additional YMD Scan\n");
a83ff38a 791
81582353
A
792 e = ymd_list;
793 while ((e != NULL) && (store_size > dst->all_max))
794 {
795 if (e->size != 0)
796 {
797 /* stop when we get to today's files */
798 if (strncmp(e->name, today_ymd_string, today_ymd_stringlen) == 0) break;
799
800 if (dst->rotate_dir != NULL)
801 {
802 str = NULL;
803 asprintf(&str, "%s/%s", dst->rotate_dir, e->name);
804 if (str == NULL) return -1;
805
806 /* syslog -x [str] -f [e->name] */
807 filesystem_copy(dst, e->name, str, 0);
808 free(str);
809 }
810
811 filesystem_unlink(e->name);
812 store_size -= e->size;
813 e->size = 0;
814 }
815
816 e = e->next;
817 }
818
819 /* if data store is over dst->all_max, delete/archive more BB files */
820 if (store_size > dst->all_max) debug_log(ASL_LEVEL_NOTICE, "Additional BB Scan\n");
821
822 e = bb_list;
823 while ((e != NULL) && (store_size > dst->all_max))
824 {
825 if (e->size != 0)
826 {
827 if (dst->rotate_dir != NULL)
828 {
829 str = NULL;
830 asprintf(&str, "%s/%s", dst->rotate_dir, e->name);
831 if (str == NULL) return -1;
832
833 /* syslog -x [str] -f [e->name] */
834 filesystem_copy(dst, e->name, str, 0);
835 free(str);
836 }
837
838 filesystem_unlink(e->name);
839 store_size -= e->size;
840 e->size = 0;
841 }
842
843 e = e->next;
844 }
845 }
846
847 free_name_list(ymd_list);
848 free_name_list(bb_list);
849 free_name_list(aux_list);
850 free_name_list(bb_aux_list);
851
852 debug_log(ASL_LEVEL_NOTICE, "Data Store Size = %lu\n", store_size);
853
854 return 0;
855}
856
857/* move sequenced source files to dst dir, renaming as we go */
858static int
859module_copy_rename(asl_out_dst_data_t *dst)
860{
861 asl_out_file_list_t *src_list, *dst_list, *f, *dst_last;
862 char *base, *dst_dir;
863 char fpathsrc[MAXPATHLEN], fpathdst[MAXPATHLEN];
864 uint32_t src_count, dst_count;
865 int32_t x, moved;
866
867 if (dst == NULL) return -1;
868 if (dst->path == NULL) return -1;
869
870 base = strrchr(dst->path, '/');
871 if (base == NULL) return -1;
872
873 src_list = asl_list_src_files(dst);
874 if (src_list == 0)
c4fdb7d1 875 {
81582353
A
876 debug_log(ASL_LEVEL_INFO, " no src files\n");
877 return 0;
878 }
879
880 debug_log(ASL_LEVEL_INFO, " src files\n");
881
882 src_count = 0;
883 for (f = src_list; f != NULL; f = f->next)
884 {
885 debug_log(ASL_LEVEL_INFO, " %s\n", f->name);
886 src_count++;
887 }
888
889 dst_list = asl_list_dst_files(dst);
890
891 *base = '\0';
892 base++;
893
894 dst_dir = dst->rotate_dir;
895 if (dst_dir == NULL) dst_dir = dst->path;
896
897 dst_count = 0;
898 dst_last = dst_list;
899
900 if (dst_list == NULL) debug_log(ASL_LEVEL_INFO, " no dst files\n");
901 else debug_log(ASL_LEVEL_INFO, " dst files\n");
902
903 for (f = dst_list; f != NULL; f = f->next)
904 {
905 debug_log(ASL_LEVEL_INFO, " %s\n", f->name);
906 dst_last = f;
907 dst_count++;
908 }
909
910 if (dst->flags & MODULE_FLAG_STYLE_SEQ)
911 {
912 for (f = dst_last; f != NULL; f = f->prev)
c4fdb7d1 913 {
81582353
A
914 int is_gz = 0;
915 char *dot = strrchr(f->name, '.');
916 if ((dot != NULL) && (!strcmp(dot, ".gz"))) is_gz = 1;
917
918 snprintf(fpathsrc, sizeof(fpathsrc), "%s/%s", dst_dir, f->name);
919 snprintf(fpathdst, sizeof(fpathdst), "%s/%s.%d%s", dst_dir, base, f->seq+src_count, (is_gz == 1) ? ".gz" : "");
920 filesystem_rename(fpathsrc, fpathdst);
921 }
57b0aad2 922
81582353
A
923 for (f = src_list, x = 0; f != NULL; f = f->next, x++)
924 {
925 snprintf(fpathsrc, sizeof(fpathsrc), "%s/%s", dst->path, f->name);
926 snprintf(fpathdst, sizeof(fpathdst), "%s/%s.%d", dst_dir, base, x);
927 moved = filesystem_copy(dst, fpathsrc, fpathdst, dst->flags);
928 if (moved != 0) filesystem_unlink(fpathsrc);
929 }
930 }
931 else
932 {
933 for (f = src_list; f != NULL; f = f->next)
934 {
935 /* final / active base stamped file looks like a checkpointed file - ignore it */
936 if ((dst->flags & MODULE_FLAG_BASESTAMP) && (f->next == NULL)) break;
937
938 snprintf(fpathsrc, sizeof(fpathsrc), "%s/%s", dst->path, f->name);
939
940 /* MODULE_FLAG_EXTERNAL files are not decorated with a timestamp */
941 if (dst->flags & MODULE_FLAG_EXTERNAL)
c4fdb7d1 942 {
81582353
A
943 char tstamp[32];
944
945 asl_make_timestamp(f->ftime, dst->flags, tstamp, sizeof(tstamp));
946 snprintf(fpathdst, sizeof(fpathdst), "%s/%s.%s", dst_dir, base, tstamp);
947 }
948 else
949 {
950 snprintf(fpathdst, sizeof(fpathdst), "%s/%s", dst_dir, f->name);
c4fdb7d1 951 }
57b0aad2 952
81582353
A
953 moved = filesystem_copy(dst, fpathsrc, fpathdst, dst->flags);
954 if (moved != 0) filesystem_unlink(fpathsrc);
955 }
956 }
57b0aad2 957
81582353
A
958 asl_out_file_list_free(src_list);
959 asl_out_file_list_free(dst_list);
960
961 if (base != NULL) *--base = '/';
962
963 return 0;
964}
965
966/* delete expired files */
967static int
968module_expire(asl_out_dst_data_t *dst)
969{
970 asl_out_file_list_t *dst_list, *f;
971 char *base, *dst_dir, fpath[MAXPATHLEN];
972 time_t now, ttl, cutoff;
973
974 if (dst == NULL) return -1;
975 if (dst->path == NULL) return -1;
976 if (dst->ttl == 0) return 0;
977
978 ttl = 0;
979 if (module_ttl > 0) ttl = module_ttl;
980 else ttl = dst->ttl;
981
982 ttl *= SECONDS_PER_DAY;
983
984 now = time(NULL);
985 if (ttl > now) return 0;
986
987 cutoff = now - ttl;
988
989 base = strrchr(dst->path, '/');
990 if (base == NULL) return -1;
991
992 dst_list = asl_list_dst_files(dst);
993
994 *base = '\0';
995
996 dst_dir = dst->rotate_dir;
997 if (dst_dir == NULL) dst_dir = dst->path;
998
999 if (dst_list == NULL)
1000 {
1001 debug_log(ASL_LEVEL_INFO, " no dst files\n");
1002 }
1003 else
1004 {
1005 debug_log(ASL_LEVEL_INFO, " dst files\n");
1006 for (f = dst_list; f != NULL; f = f->next) debug_log(ASL_LEVEL_INFO, " %s\n", f->name);
1007 }
1008
1009 for (f = dst_list; f != NULL; f = f->next)
1010 {
1011 if (f->ftime <= cutoff)
1012 {
1013 snprintf(fpath, sizeof(fpath), "%s/%s", dst_dir, f->name);
1014 filesystem_unlink(fpath);
c4fdb7d1 1015 }
81582353 1016 }
57b0aad2 1017
81582353
A
1018 asl_out_file_list_free(dst_list);
1019
1020 if (base != NULL) *base = '/';
1021
1022 return 0;
1023}
1024
1025/* check all_max size and delete files (oldest first) to stay within size limit */
1026static int
1027module_check_size(asl_out_dst_data_t *dst)
1028{
1029 asl_out_file_list_t *dst_list, *f;
1030 char *base, *dst_dir, fpath[MAXPATHLEN];
1031 size_t total;
1032
1033 if (dst == NULL) return -1;
1034 if (dst->path == NULL) return -1;
1035
1036 if (dst->all_max == 0) return 0;
1037
1038 base = NULL;
1039 dst_dir = dst->rotate_dir;
1040 if (dst_dir == NULL)
1041 {
1042 dst_dir = dst->path;
1043 base = strrchr(dst->path, '/');
1044 if (base == NULL) return -1;
1045 *base = '\0';
57b0aad2
A
1046 }
1047
81582353 1048 dst_list = asl_list_dst_files(dst);
57b0aad2 1049
81582353 1050 if (dst_list == NULL)
57b0aad2 1051 {
81582353
A
1052 debug_log(ASL_LEVEL_INFO, " no dst files\n");
1053 }
1054 else
1055 {
1056 debug_log(ASL_LEVEL_INFO, " dst files\n");
1057 for (f = dst_list; f != NULL; f = f->next) debug_log(ASL_LEVEL_INFO, " %s size %lu\n", f->name, f->size);
1058 }
1059
1060 total = 0;
1061 for (f = dst_list; f != NULL; f = f->next) total += f->size;
1062
1063 for (f = dst_list; (total > dst->all_max) && (f != NULL); f = f->next)
1064 {
1065 snprintf(fpath, sizeof(fpath), "%s/%s", dst_dir, f->name);
1066 filesystem_unlink(fpath);
1067 total -= f->size;
1068 }
1069
1070 asl_out_file_list_free(dst_list);
1071
1072 if (base != NULL) *base = '/';
1073
1074 return 0;
1075}
1076
1077
1078static int
1079process_module(asl_out_module_t *mod)
1080{
1081 asl_out_rule_t *r;
1082
1083 if (mod == NULL) return -1;
1084
1085 debug_log(ASL_LEVEL_NOTICE, "----------------------------------------\n");
1086 debug_log(ASL_LEVEL_NOTICE, "Processing module %s\n", (mod->name == NULL) ? "asl.conf" : mod->name);
1087
1088 for (r = mod->ruleset; r != NULL; r = r->next)
1089 {
1090 if (r->action == ACTION_OUT_DEST)
57b0aad2 1091 {
81582353 1092 if (r->dst == NULL)
c4fdb7d1 1093 {
81582353 1094 debug_log(ASL_LEVEL_NOTICE, "NULL dst data for output rule - skipped\n");
c4fdb7d1 1095 }
81582353
A
1096 else if (r->dst->flags & MODULE_FLAG_ROTATE)
1097 {
1098 debug_log(ASL_LEVEL_NOTICE, "Checking file %s\n", r->dst->path);
1099 debug_log(ASL_LEVEL_NOTICE, "- Rename, move to destination directory, and compress as required\n");
c4fdb7d1 1100
81582353 1101 module_copy_rename(r->dst);
c4fdb7d1 1102
81582353
A
1103 if (r->dst->ttl > 0)
1104 {
1105 debug_log(ASL_LEVEL_NOTICE, "- Check for expired files - TTL = %d days\n", r->dst->ttl);
1106 module_expire(r->dst);
1107 }
1108
1109 if (r->dst->all_max > 0)
1110 {
1111 debug_log(ASL_LEVEL_NOTICE, "- Check total storage used - MAX = %lu\n", r->dst->all_max);
1112 module_check_size(r->dst);
1113 }
1114 }
1115 else if ((r->dst->flags & MODULE_FLAG_TYPE_ASL_DIR) && (r->dst->ttl > 0))
1116 {
1117 process_asl_data_store(r->dst);
1118 }
57b0aad2 1119 }
81582353 1120 }
57b0aad2 1121
81582353
A
1122 debug_log(ASL_LEVEL_NOTICE, "Finished processing module %s\n", (mod->name == NULL) ? "asl.conf" : mod->name);
1123 return 0;
1124}
1125
1126aslresponse
1127control_query(aslmsg a)
1128{
1129 asl_search_result_t *out;
1130 char *qstr, *str, *res;
1131 uint32_t len, reslen, status;
1132 uint64_t cmax, qmin;
1133 kern_return_t kstatus;
1134 caddr_t vmstr;
1135 security_token_t sec;
1136
1137 if (asl_server_port == MACH_PORT_NULL)
1138 {
1139 bootstrap_look_up2(bootstrap_port, ASL_SERVICE_NAME, &asl_server_port, 0, BOOTSTRAP_PRIVILEGED_SERVER);
1140 if (asl_server_port == MACH_PORT_NULL) return NULL;
57b0aad2
A
1141 }
1142
81582353 1143 qstr = asl_msg_to_string((asl_msg_t *)a, &len);
57b0aad2 1144
81582353
A
1145 str = NULL;
1146 if (qstr == NULL)
1147 {
1148 asprintf(&str, "1\nQ [= ASLOption control]\n");
1149 }
1150 else
c4fdb7d1 1151 {
81582353
A
1152 asprintf(&str, "1\n%s [= ASLOption control]\n", qstr);
1153 free(qstr);
c4fdb7d1 1154 }
57b0aad2 1155
81582353
A
1156 if (str == NULL) return NULL;
1157
1158 /* length includes trailing nul */
1159 len = strlen(str) + 1;
1160 out = NULL;
1161 qmin = 0;
1162 cmax = 0;
1163 sec.val[0] = -1;
1164 sec.val[1] = -1;
1165
1166 res = NULL;
1167 reslen = 0;
1168 status = ASL_STATUS_OK;
1169
1170 kstatus = vm_allocate(mach_task_self(), (vm_address_t *)&vmstr, len, TRUE);
1171 if (kstatus != KERN_SUCCESS) return NULL;
1172
1173 memmove(vmstr, str, len);
1174 free(str);
1175
1176 status = 0;
1177 kstatus = _asl_server_query(asl_server_port, vmstr, len, qmin, 1, 0, (caddr_t *)&res, &reslen, &cmax, (int *)&status, &sec);
1178 if (kstatus != KERN_SUCCESS) return NULL;
1179
1180 if (res == NULL) return NULL;
1181
1182 out = asl_list_from_string(res);
1183 vm_deallocate(mach_task_self(), (vm_address_t)res, reslen);
1184
1185 return out;
1186}
1187
1188int
1189checkpoint(const char *name)
1190{
1191 /* send checkpoint message to syslogd */
1192 debug_log(ASL_LEVEL_NOTICE, "Checkpoint module %s\n", (name == NULL) ? "*" : name);
1193 if (dryrun != 0) return 0;
1194
1195 aslmsg qmsg = asl_new(ASL_TYPE_QUERY);
1196 char *tmp = NULL;
1197 aslresponse res;
1198
1199 asprintf(&tmp, "%s checkpoint", (name == NULL) ? "*" : name);
1200 asl_set_query(qmsg, "action", tmp, ASL_QUERY_OP_EQUAL);
1201 free(tmp);
1202
1203 res = control_query(qmsg);
1204
1205 aslresponse_free(res);
57b0aad2
A
1206 return 0;
1207}
1208
81582353
A
1209int
1210cli_main(int argc, char *argv[])
1211{
1212 int i, work;
1213 asl_out_module_t *mod, *m;
1214 asl_out_rule_t *r;
1215 asl_out_dst_data_t store;
1216 const char *mname = NULL;
1217
1218 if (geteuid() != 0)
1219 {
1220 if (argc == 0) debug = DEBUG_ASL;
1221 else debug = DEBUG_STDERR;
1222
1223 debug_log(ASL_LEVEL_ERR, "aslmanager must be run by root\n");
1224 exit(1);
1225 }
1226
1227 module_ttl = DEFAULT_TTL;
1228
1229 /* cobble up a dst_data for the main asl_store */
1230 memset(&store, 0, sizeof(store));
1231 store.ttl = DEFAULT_TTL;
1232 store.all_max = DEFAULT_MAX_SIZE;
1233
1234 /* get parameters from asl.conf */
1235 mod = asl_out_module_init();
1236
1237 if (mod != NULL)
1238 {
1239 for (r = mod->ruleset; r != NULL; r = r->next)
1240 {
1241 if (r->action == ACTION_SET_PARAM)
1242 {
1243 if (r->query == NULL) _aslmanager_set_param(&store, r->options);
1244 }
1245 }
1246 }
1247
1248 work = DO_ASLDB | DO_MODULE;
1249
1250 for (i = 1; i < argc; i++)
1251 {
1252 if (!strcmp(argv[i], "-a"))
1253 {
1254 if (((i + 1) < argc) && (argv[i + 1][0] != '-')) store.rotate_dir = strdup(argv[++i]);
1255 else store.rotate_dir = strdup(PATH_ASL_ARCHIVE);
1256 store.mode = 0400;
1257 }
1258 else if (!strcmp(argv[i], "-s"))
1259 {
1260 if (((i + 1) < argc) && (argv[i + 1][0] != '-')) store.path = strdup(argv[++i]);
1261 }
1262 else if (!strcmp(argv[i], "-store_ttl"))
1263 {
1264 if (((i + 1) < argc) && (argv[i + 1][0] != '-')) store.ttl = atoi(argv[++i]);
1265 }
1266 else if (!strcmp(argv[i], "-module_ttl"))
1267 {
1268 if (((i + 1) < argc) && (argv[i + 1][0] != '-')) module_ttl = atoi(argv[++i]);
1269 }
1270 else if (!strcmp(argv[i], "-ttl"))
1271 {
1272 if (((i + 1) < argc) && (argv[i + 1][0] != '-')) module_ttl = store.ttl = atoi(argv[++i]);
1273 }
1274 else if (!strcmp(argv[i], "-size"))
1275 {
1276 if (((i + 1) < argc) && (argv[i + 1][0] != '-')) store.all_max = asl_str_to_size(argv[++i]);
1277 }
1278 else if (!strcmp(argv[i], "-checkpoint"))
1279 {
1280 work |= DO_CHECKPT;
1281 }
1282 else if (!strcmp(argv[i], "-module"))
1283 {
1284 work &= ~DO_ASLDB;
1285
1286 /* optional name follows -module */
1287 if ((i +1) < argc)
1288 {
1289 if (argv[i + 1][0] != '-') mname = argv[++i];
1290 }
1291 }
1292 else if (!strcmp(argv[i], "-asldb"))
1293 {
1294 work = DO_ASLDB;
1295 }
1296 else if (!strcmp(argv[i], "-d"))
1297 {
1298 if (((i + i) < argc) && (argv[i+1][0] != '-')) set_debug(DEBUG_STDERR, argv[++i]);
1299 else set_debug(DEBUG_STDERR, NULL);
1300 }
1301 else if (!strcmp(argv[i], "-dd"))
1302 {
1303 dryrun = 1;
1304
1305 if (((i + i) < argc) && (argv[i+1][0] != '-')) set_debug(DEBUG_STDERR, argv[++i]);
1306 else set_debug(DEBUG_STDERR, NULL);
1307 }
1308 }
1309
1310 if (store.path == NULL) store.path = strdup(PATH_ASL_STORE);
1311
1312 debug_log(ASL_LEVEL_ERR, "aslmanager starting%s\n", (dryrun == 1) ? " dryrun" : "");
1313
1314 if (work & DO_ASLDB) process_asl_data_store(&store);
1315
1316 free(store.path);
1317 free(store.rotate_dir);
1318
1319 if (work & DO_MODULE)
1320 {
1321 if (work & DO_CHECKPT) checkpoint(mname);
1322
1323 if (mod != NULL)
1324 {
1325 for (m = mod; m != NULL; m = m->next)
1326 {
1327 if ((mname == NULL) || ((m->name != NULL) && (!strcmp(m->name, mname))))
1328 {
1329 process_module(m);
1330 }
1331 }
1332 }
1333 }
1334
1335 asl_out_module_free(mod);
1336
1337 debug_log(ASL_LEVEL_NOTICE, "----------------------------------------\n");
1338 debug_log(ASL_LEVEL_ERR, "aslmanager finished%s\n", (dryrun == 1) ? " dryrun" : "");
1339 if (asl_aux_fd >= 0) asl_close_auxiliary_file(asl_aux_fd);
1340
1341 return 0;
1342}
1343
1344static void
1345accept_connection(xpc_connection_t peer)
1346{
1347 xpc_connection_set_event_handler(peer, ^(xpc_object_t request) {
1348 if (xpc_get_type(request) == XPC_TYPE_DICTIONARY)
1349 {
1350 uid_t uid = xpc_connection_get_euid(peer);
1351
1352 /* send a reply immediately */
1353 xpc_object_t reply = xpc_dictionary_create_reply(request);
1354 xpc_connection_send_message(peer, reply);
1355 xpc_release(reply);
1356
1357 /*
1358 * Some day, we may use the dictionary to pass parameters
1359 * to aslmanager, but for now, we ignore the input.
1360 */
1361 if (uid == 0) cli_main(0, NULL);
1362 }
1363 else if (xpc_get_type(request) == XPC_TYPE_ERROR)
1364 {
1365 /* disconnect */
1366 }
1367
1368 dispatch_async(serverq, ^__attribute__((noreturn)) { xpc_server_exit(0); });
1369 });
1370
1371 xpc_connection_resume(peer);
1372}
1373
1374int
1375main(int argc, char *argv[])
1376{
1377 int64_t is_managed = 0;
1378
1379 vproc_swap_integer(NULL, VPROC_GSK_IS_MANAGED, NULL, &is_managed);
1380
1381 if (is_managed == 0) return cli_main(argc, argv);
1382
1383 /* XPC server */
1384 serverq = dispatch_queue_create("aslmanager", NULL);
1385 xpc_track_activity();
1386
1387 /* Handle incoming messages. */
1388 listener = xpc_connection_create_mach_service("com.apple.aslmanager", serverq, XPC_CONNECTION_MACH_SERVICE_LISTENER);
1389 xpc_connection_set_event_handler(listener, ^(xpc_object_t peer) {
1390 if (xpc_get_type(peer) == XPC_TYPE_CONNECTION) accept_connection(peer);
1391 });
1392 xpc_connection_resume(listener);
1393
1394 dispatch_main();
1395}