/*
- * Copyright (c) 2007-2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2007-2015 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
- *
+ *
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
- *
+ *
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
- *
+ *
* @APPLE_LICENSE_HEADER_END@
*/
-#include <stdio.h>
-#include <dirent.h>
-#include <string.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <stdint.h>
-#include <errno.h>
-#include <time.h>
-#include <sys/time.h>
-#include <sys/stat.h>
#include <asl.h>
-#include <asl_private.h>
-#include <asl_core.h>
-#include <asl_file.h>
+#include <asl_msg.h>
+#include <asl_msg_list.h>
#include <asl_store.h>
+#include <errno.h>
+#include <vproc_priv.h>
-#define SECONDS_PER_DAY 86400
-#define DEFAULT_MAX_SIZE 51200000
-#define DEFAULT_TTL 2
+#include "asl_common.h"
+#include "daemon.h"
+#include "cache_delete.h"
-typedef struct name_list_s
-{
- char *name;
- size_t size;
- struct name_list_s *next;
-} name_list_t;
+/* global */
+bool dryrun;
+uint32_t debug;
+FILE *debugfp;
+dispatch_queue_t work_queue;
-void
-mgr_exit(const char *store, int status)
-{
- char *s;
+static dispatch_queue_t server_queue;
+static time_t module_ttl;
+static xpc_connection_t listener;
+static bool main_task_enqueued;
+static bool initial_main_task = true;
+static dispatch_source_t sig_term_src;
- if (store == NULL) exit(status);
+/* wait 5 minutes to run main task after being invoked by XPC */
+#define MAIN_TASK_INITIAL_DELAY 300
- s = NULL;
- asprintf(&s, "%s/%s", store, FILE_ASL_STORE_SWEEP_SEMAPHORE);
- if (s != NULL)
- {
- unlink(s);
- free(s);
- }
- else exit(1);
+/*
+ * Used to set config parameters.
+ * Line format "= name value"
+ */
+static void
+_aslmanager_set_param(asl_out_dst_data_t *dst, char *s)
+{
+ char **l;
+ uint32_t count;
- exit(status);
-}
+ if (s == NULL) return;
+ if (s[0] == '\0') return;
-name_list_t *
-add_to_list(name_list_t *l, const char *name, size_t size)
-{
- name_list_t *e, *x;
+ /* skip '=' and whitespace */
+ if (*s == '=') s++;
+ while ((*s == ' ') || (*s == '\t')) s++;
- if (name == NULL) return l;
+ l = explode(s, " \t");
+ if (l == NULL) return;
- e = (name_list_t *)calloc(1, sizeof(name_list_t));
- if (e == NULL) return NULL;
+ for (count = 0; l[count] != NULL; count++);
- e->name = strdup(name);
- if (e->name == NULL)
+ /* name is required */
+ if (count == 0)
{
- free(e);
- return NULL;
+ free_string_list(l);
+ return;
}
- e->size = size;
-
- /* list is sorted by name (i.e. primarily by timestamp) */
- if (l == NULL) return e;
+ /* value is required */
+ if (count == 1)
+ {
+ free_string_list(l);
+ return;
+ }
- if (strcmp(e->name, l->name) <= 0)
+ if (!strcasecmp(l[0], "aslmanager_debug"))
+ {
+ /* = debug level */
+ set_debug(DEBUG_ASL, l[1]);
+ }
+ else if (!strcasecmp(l[0], "store_ttl"))
{
- e->next = l;
- return e;
+ /* = store_ttl days */
+ dst->ttl[LEVEL_ALL] = asl_core_str_to_time(l[1], SECONDS_PER_DAY);
}
+ else if (!strcasecmp(l[0], "module_ttl"))
+ {
+ /* = module_ttl days */
+ module_ttl = asl_core_str_to_time(l[1], SECONDS_PER_DAY);
+ }
+ else if (!strcasecmp(l[0], "max_store_size"))
+ {
+ /* = max_file_size bytes */
+ dst->all_max = asl_core_str_to_size(l[1]);
+ }
+ else if (!strcasecmp(l[0], "archive"))
+ {
+ free(dst->rotate_dir);
+ dst->rotate_dir = NULL;
- for (x = l; (x->next != NULL) && (strcmp(e->name, x->next->name) > 0) ; x = x->next);
+ /* = archive {0|1} path */
+ if (!strcmp(l[1], "1"))
+ {
+ if (l[2] == NULL) dst->rotate_dir = strdup(PATH_ASL_ARCHIVE);
+ else dst->rotate_dir = strdup(l[2]);
+ }
+ }
+ else if (!strcasecmp(l[0], "store_path"))
+ {
+ /* = archive path */
+ free(dst->path);
+ dst->path = strdup(l[1]);
+ }
+ else if (!strcasecmp(l[0], "archive_mode"))
+ {
+ dst->mode = strtol(l[1], NULL, 0);
+ if ((dst->mode == 0) && (errno == EINVAL)) dst->mode = 0400;
+ }
- e->next = x->next;
- x->next = e;
- return l;
+ free_string_list(l);
}
-void
-free_list(name_list_t *l)
+int
+cli_main(int argc, char *argv[])
{
- name_list_t *e;
-
- while (l != NULL)
+ int i, work;
+ asl_out_module_t *mod, *m;
+ asl_out_rule_t *r;
+ asl_out_dst_data_t store, opts, *asl_store_dst = NULL;
+ const char *mname = NULL;
+ char *path = NULL;
+ bool quiet = false;
+ bool cache_delete = false;
+ bool cache_delete_query = false;
+
+#if !TARGET_OS_SIMULATOR
+ if (geteuid() != 0)
{
- e = l;
- l = l->next;
- free(e->name);
- free(e);
+ if (argc == 0) debug = DEBUG_ASL;
+ else debug = DEBUG_STDERR;
+
+ debug_log(ASL_LEVEL_ERR, "aslmanager must be run by root\n");
+ exit(1);
}
+#endif
- free(l);
-}
+ module_ttl = DEFAULT_TTL;
-uint32_t
-do_match(const char *infile, const char *outfile, int do_ttl, time_t expire_time)
-{
- asl_search_result_t q, *query, *res;
- asl_msg_t *m, *qm[1];
- asl_file_t *in, *out;
- uint32_t status, i;
- char str[64];
- uint64_t mid;
-
- if (infile == NULL) return ASL_STATUS_INVALID_ARG;
- if (outfile == NULL) return ASL_STATUS_INVALID_ARG;
-
- in = NULL;
- status = asl_file_open_read(infile, &in);
- if (status != ASL_STATUS_OK) return status;
-
- query = NULL;
- q.count = 1;
- q.curr = 0;
- q.msg = qm;
- qm[0] = NULL;
- m = NULL;
-
- if (do_ttl == 1)
+ /* cobble up a dst_data with defaults and parameter settings */
+ memset(&store, 0, sizeof(store));
+ store.ttl[LEVEL_ALL] = DEFAULT_TTL;
+ store.all_max = DEFAULT_MAX_SIZE;
+
+ memset(&opts, 0, sizeof(opts));
+ opts.ttl[LEVEL_ALL] = DEFAULT_TTL;
+ opts.all_max = DEFAULT_MAX_SIZE;
+
+ for (i = 1; i < argc; i++)
{
- query = &q;
- m = asl_new(ASL_TYPE_QUERY);
- if (m == NULL)
+ if (!strcmp(argv[i], "-q"))
{
- asl_file_close(in);
- return ASL_STATUS_NO_MEMORY;
+ quiet = true;
}
-
- qm[0] = m;
-
- if (expire_time != 0)
+ else if (!strcmp(argv[i], "-dd"))
{
- snprintf(str, sizeof(str), "%llu", (long long unsigned int)expire_time);
- if (asl_set_query(m, ASL_KEY_EXPIRE_TIME, str, ASL_QUERY_OP_NUMERIC | ASL_QUERY_OP_GREATER_EQUAL) != 0)
- {
- asl_file_close(in);
- asl_free(m);
- return ASL_STATUS_NO_MEMORY;
- }
+ quiet = true;
}
- else
+ else if (!strcmp(argv[i], "-s"))
{
- if (asl_set_query(m, ASL_KEY_EXPIRE_TIME, NULL, ASL_QUERY_OP_TRUE) != 0)
+ if (((i + 1) < argc) && (argv[i + 1][0] != '-'))
{
- asl_file_close(in);
- asl_free(m);
- return ASL_STATUS_NO_MEMORY;
+ store.path = strdup(argv[++i]);
+ asl_store_dst = &store;
}
}
}
- res = NULL;
- mid = 0;
- status = asl_file_match(in, query, &res, &mid, 0, 0, 1);
- if (m != NULL) asl_free(m);
- asl_file_close(in);
+ if (!quiet)
+ {
+ int status = asl_make_database_dir(NULL, NULL);
+ if (status == 0) status = asl_make_database_dir(ASL_INTERNAL_LOGS_DIR, &path);
+ if (status == 0)
+ {
+ char tstamp[32], *str = NULL;
- if (status != ASL_STATUS_OK) return status;
+ asl_make_timestamp(time(NULL), MODULE_NAME_STYLE_STAMP_LCL_B, tstamp, sizeof(tstamp));
+ asprintf(&str, "%s/aslmanager.%s", path, tstamp);
- /*
- * N.B. "ASL_STATUS_NOT_FOUND" is never returned by asl_file_match.
- * We use it here to signal the caller that no records were found by the match.
- */
- if (res == NULL) return ASL_STATUS_NOT_FOUND;
- if (res->count == 0)
- {
- aslresponse_free(res);
- return ASL_STATUS_NOT_FOUND;
+ if (str != NULL)
+ {
+ if (status == 0) debugfp = fopen(str, "w");
+ if (debugfp != NULL) debug |= DEBUG_FILE;
+ free(str);
+ }
+ }
}
- out = NULL;
- status = asl_file_open_write(outfile, 0644, -1, -1, &out);
- if (status != ASL_STATUS_OK) return status;
-
- out->flags = ASL_FILE_FLAG_UNLIMITED_CACHE | ASL_FILE_FLAG_PRESERVE_MSG_ID;
+ /* get parameters from asl.conf */
+ mod = asl_out_module_init();
- for (i = 0; i < res->count; i++)
+ if (mod != NULL)
{
- mid = 0;
- status = asl_file_save(out, res->msg[i], &mid);
- if (status != ASL_STATUS_OK) break;
- }
+ for (r = mod->ruleset; (r != NULL) && (asl_store_dst == NULL); r = r->next)
+ {
+ if ((r->dst != NULL) && (r->action == ACTION_OUT_DEST) && (!strcmp(r->dst->path, PATH_ASL_STORE)))
+ asl_store_dst = r->dst;
+ }
- asl_file_close(out);
- return status;
-}
+ for (r = mod->ruleset; r != NULL; r = r->next)
+ {
+ if (r->action == ACTION_SET_PARAM)
+ {
+ if (r->query == NULL) _aslmanager_set_param(asl_store_dst, r->options);
+ }
+ }
+ }
-int
-main(int argc, const char *argv[])
-{
- int i, bbstrlen, debug;
- const char *archive, *store_dir;
- time_t now, best_before, ttl;
- struct tm ctm;
- char bbstr[32], *str, *p;
- DIR *dp;
- struct dirent *dent;
- name_list_t *list, *e;
- uint32_t status;
- size_t file_size, store_size, max_size;
- struct stat sb;
-
- list = NULL;
-
- archive = NULL;
- store_dir = PATH_ASL_STORE;
- ttl = DEFAULT_TTL * SECONDS_PER_DAY;
- max_size = DEFAULT_MAX_SIZE;
- store_size = 0;
- debug = 0;
+ work = DO_ASLDB | DO_MODULE;
for (i = 1; i < argc; i++)
{
if (!strcmp(argv[i], "-a"))
{
- if (((i + 1) < argc) && (argv[i + 1][0] != '-')) archive = argv[++i];
- else archive = PATH_ASL_ARCHIVE;
+ if (asl_store_dst == NULL) asl_store_dst = &store;
+
+ if (((i + 1) < argc) && (argv[i + 1][0] != '-')) asl_store_dst->rotate_dir = strdup(argv[++i]);
+ else asl_store_dst->rotate_dir = strdup(PATH_ASL_ARCHIVE);
+ asl_store_dst->mode = 0400;
}
- else if (!strcmp(argv[i], "-s"))
+ else if (!strcmp(argv[i], "-store_ttl"))
{
- if (((i + 1) < argc) && (argv[i + 1][0] != '-')) store_dir = argv[++i];
+ if (((i + 1) < argc) && (argv[i + 1][0] != '-'))
+ {
+ if (asl_store_dst == NULL) asl_store_dst = &store;
+ asl_store_dst->ttl[LEVEL_ALL] = asl_core_str_to_time(argv[++i], SECONDS_PER_DAY);
+ }
+ }
+ else if (!strcmp(argv[i], "-module_ttl"))
+ {
+ if (((i + 1) < argc) && (argv[i + 1][0] != '-')) module_ttl = asl_core_str_to_time(argv[++i], SECONDS_PER_DAY);
}
else if (!strcmp(argv[i], "-ttl"))
{
- if (((i + 1) < argc) && (argv[i + 1][0] != '-')) ttl = atoi(argv[++i]) * SECONDS_PER_DAY;
+ if (((i + 1) < argc) && (argv[i + 1][0] != '-'))
+ {
+ opts.ttl[LEVEL_ALL] = asl_core_str_to_time(argv[++i], SECONDS_PER_DAY);
+
+ if (asl_store_dst == NULL) asl_store_dst = &store;
+ asl_store_dst->ttl[LEVEL_ALL] = opts.ttl[LEVEL_ALL];
+
+ module_ttl = opts.ttl[LEVEL_ALL];
+ }
}
else if (!strcmp(argv[i], "-size"))
{
- if (((i + 1) < argc) && (argv[i + 1][0] != '-')) max_size = atoi(argv[++i]);
+ if (((i + 1) < argc) && (argv[i + 1][0] != '-'))
+ {
+ opts.all_max = asl_core_str_to_size(argv[++i]);
+
+ if (asl_store_dst == NULL) asl_store_dst = &store;
+ asl_store_dst->all_max = opts.all_max;
+ }
+ }
+ else if (!strcmp(argv[i], "-checkpoint"))
+ {
+ work |= DO_CHECKPT;
+ }
+ else if (!strcmp(argv[i], "-cache_delete"))
+ {
+ cache_delete = true;
+ if (((i + 1) < argc) && (argv[i + 1][0] == 'q')) cache_delete_query = true;
+ }
+ else if (!strcmp(argv[i], "-module"))
+ {
+ work &= ~DO_ASLDB;
+
+ /* optional name follows -module */
+ if ((i +1) < argc)
+ {
+ if (argv[i + 1][0] != '-') mname = argv[++i];
+ }
+ }
+ else if (!strcmp(argv[i], "-asldb"))
+ {
+ work = DO_ASLDB;
}
else if (!strcmp(argv[i], "-d"))
{
- debug = 1;
+ if (((i + i) < argc) && (argv[i+1][0] != '-')) set_debug(DEBUG_STDERR, argv[++i]);
+ else set_debug(DEBUG_STDERR, NULL);
+ }
+ else if (!strcmp(argv[i], "-dd"))
+ {
+ dryrun = true;
+
+ if (((i + i) < argc) && (argv[i+1][0] != '-')) set_debug(DEBUG_STDERR, argv[++i]);
+ else set_debug(DEBUG_STDERR, "l7");
}
}
- /* check archive */
- if (archive != NULL)
+ if (asl_store_dst->path == NULL) asl_store_dst->path = strdup(PATH_ASL_STORE);
+
+ debug_log(ASL_LEVEL_ERR, "aslmanager starting%s\n", dryrun ? " dryrun" : "");
+
+ if (cache_delete)
{
- memset(&sb, 0, sizeof(struct stat));
- if (stat(archive, &sb) == 0)
+ size_t curr_size = 0;
+
+ if (cache_delete_task(true, &curr_size) != 0)
{
- /* must be a directory */
- if ((sb.st_mode & S_IFDIR) == 0)
- {
- fprintf(stderr, "aslmanager error: archive %s is not a directory", archive);
- return -1;
- }
+ debug_log(ASL_LEVEL_NOTICE, "cache_delete_process failed - can't determine current size\n");
}
else
{
- if (errno == ENOENT)
+ debug_log(ASL_LEVEL_NOTICE, "cache delete current size = %lu\n", curr_size);
+
+ if (!cache_delete_query)
{
- /* archive doesn't exist - create it */
- if (mkdir(archive, 0755) != 0)
+ size_t new_size = curr_size - opts.all_max;
+
+ if (cache_delete_task(false, &new_size) != 0)
{
- fprintf(stderr, "aslmanager error: can't create archive %s: %s\n", archive, strerror(errno));
- return -1;
- }
- }
- else
- {
- /* stat failed for some other reason */
- fprintf(stderr, "aslmanager error: can't stat archive %s: %s\n", archive, strerror(errno));
- return -1;
+ debug_log(ASL_LEVEL_NOTICE, "cache_delete_process failed - delete failed\n");
+ }
+ else
+ {
+ debug_log(ASL_LEVEL_NOTICE, "cache delete new size = %lu\n", new_size);
+ }
}
}
- }
- chdir(store_dir);
+ asl_out_module_free(mod);
- /* determine current time and time TTL ago */
- now = time(NULL);
- best_before = 0;
- if (ttl > 0) best_before = now - ttl;
+ debug_log(ASL_LEVEL_NOTICE, "----------------------------------------\n");
+ debug_log(ASL_LEVEL_ERR, "aslmanager finished%s\n", dryrun ? " dryrun" : "");
+ debug_close();
- /* construct best before date as YYYY.MM.DD */
- memset(&ctm, 0, sizeof(struct tm));
- if (localtime_r((const time_t *)&best_before, &ctm) == NULL) mgr_exit(store_dir, 1);
+ return 0;
+ }
- snprintf(bbstr, sizeof(bbstr), "%d.%02d.%02d.", ctm.tm_year + 1900, ctm.tm_mon + 1, ctm.tm_mday);
- bbstrlen = strlen(bbstr);
+ if (work & DO_ASLDB) process_asl_data_store(asl_store_dst, &opts);
- if (debug == 1) printf("Best Before Date %s\n", bbstr);
+ if (work & DO_MODULE)
+ {
+ if (work & DO_CHECKPT) checkpoint(mname);
- dp = opendir(store_dir);
- if (dp == NULL) mgr_exit(store_dir, 1);
+ if (mod != NULL)
+ {
+ for (m = mod; m != NULL; m = m->next)
+ {
+ if (mname == NULL)
+ {
+ process_module(m, NULL);
+ }
+ else if ((m->name != NULL) && (!strcmp(m->name, mname)))
+ {
+ process_module(m, &opts);
+ }
+ }
+ }
+ }
- /* gather a list of files for dates before the best before date */
+ asl_out_module_free(mod);
- while ((dent = readdir(dp)) != NULL)
- {
- if ((dent->d_name[0] < '0') || (dent->d_name[0] > '9')) continue;
+ debug_log(ASL_LEVEL_NOTICE, "----------------------------------------\n");
+ debug_log(ASL_LEVEL_ERR, "aslmanager finished%s\n", dryrun ? " dryrun" : "");
+ debug_close();
- memset(&sb, 0, sizeof(struct stat));
- file_size = 0;
- if (stat(dent->d_name, &sb) == 0) file_size = sb.st_size;
- store_size += file_size;
+ return 0;
+}
- list = add_to_list(list, dent->d_name, file_size);
- }
+/* dispatched on server_queue, dispatches to work_queue */
+void
+main_task(void)
+{
+ /* if main task is already running or queued, do nothing */
+ if (main_task_enqueued) return;
- closedir(dp);
+ main_task_enqueued = true;
+ xpc_transaction_begin();
- if (debug == 1)
+ if (initial_main_task)
{
- printf("\nData Store Size = %lu\n", store_size);
- printf("\nData Store Files\n");
- for (e = list; e != NULL; e = e->next) printf(" %s %lu\n", e->name, e->size);
+ initial_main_task = false;
+ dispatch_time_t delay = dispatch_walltime(NULL, MAIN_TASK_INITIAL_DELAY * NSEC_PER_SEC);
+
+ dispatch_after(delay, work_queue, ^{
+ cli_main(0, NULL);
+ main_task_enqueued = false;
+ xpc_transaction_end();
+ });
}
-
- /* copy messages in each expired file with ASLExpireTime values to LongTTL files */
- if (debug == 1) printf("\nStart Scan\n");
-
- e = list;
- while (e != NULL)
+ else
{
- if ((store_size <= max_size) && (strncmp(e->name, bbstr, bbstrlen) >= 0)) break;
-
- /* find '.' after year */
- p = strchr(e->name, '.');
- if (p == NULL) continue;
-
- /* find '.' after month */
- p++;
- p = strchr(p, '.');
- if (p == NULL) continue;
-
- /* find '.' after day */
- p++;
- p = strchr(p, '.');
- if (p == NULL) continue;
+ dispatch_async(work_queue, ^{
+ cli_main(0, NULL);
+ main_task_enqueued = false;
+ xpc_transaction_end();
+ });
+ }
+}
- str = NULL;
- asprintf(&str, "LongTTL%s", p);
- if (str == NULL) mgr_exit(store_dir, 1);
+static void
+accept_connection(xpc_connection_t peer)
+{
+ xpc_connection_set_event_handler(peer, ^(xpc_object_t request) {
+ if (xpc_get_type(request) == XPC_TYPE_DICTIONARY)
+ {
+ uid_t uid = xpc_connection_get_euid(peer);
- /* syslog -x [str] -db [e->name] -k ASLExpireTime */
- if (debug == 1) printf(" scan %s ---> %s\n", e->name, str);
- else status = do_match(e->name, str, 1, 0);
+ /* send a reply immediately */
+ xpc_object_t reply = xpc_dictionary_create_reply(request);
+ xpc_connection_send_message(peer, reply);
+ xpc_release(reply);
- free(str);
- str = NULL;
+ /*
+ * Some day, we may use the dictionary to pass parameters
+ * to aslmanager, but for now, we ignore the input.
+ */
- if (archive != NULL)
+ if (uid == geteuid())
+ {
+ main_task();
+ }
+ }
+ else if (xpc_get_type(request) == XPC_TYPE_ERROR)
{
- str = NULL;
- asprintf(&str, "%s/%s", archive, e->name);
- if (str == NULL) mgr_exit(store_dir, 1);
-
- /* syslog -x [str] -db [e->name] */
- if (debug == 1) printf(" copy %s ---> %s\n", e->name, str);
- else status = do_match(e->name, str, 0, 0);
- free(str);
+ /* disconnect */
}
+ });
- if (debug == 1) printf(" unlink %s\n", e->name);
- else unlink(e->name);
-
- store_size -= e->size;
- e->size = 0;
-
- e = e->next;
- }
-
- if (debug == 1)
- {
- printf("Finished Scan\n");
- printf("\nData Store Size = %lu\n", store_size);
- }
+ xpc_connection_resume(peer);
+}
- free_list(list);
- list = NULL;
+int
+main(int argc, char *argv[])
+{
+ int64_t is_managed = 0;
- dp = opendir(PATH_ASL_STORE);
- if (dp == NULL) mgr_exit(store_dir, 1);
+ vproc_swap_integer(NULL, VPROC_GSK_IS_MANAGED, NULL, &is_managed);
- /* gather a list of LongTTL files */
+ if (is_managed == 0) return cli_main(argc, argv);
- while ((dent = readdir(dp)) != NULL)
- {
- if (!strncmp(dent->d_name, "LongTTL.", 8)) list = add_to_list(list, dent->d_name, 0);
- }
+ /* Set I/O policy */
+ setiopolicy_np(IOPOL_TYPE_DISK, IOPOL_SCOPE_PROCESS, IOPOL_THROTTLE);
- closedir(dp);
+ /* XPC server */
+ server_queue = dispatch_queue_create("aslmanager", NULL);
- if (debug == 1)
- {
- printf("\nData Store LongTTL Files\n");
- for (e = list; e != NULL; e = e->next) printf(" %s\n", e->name);
- }
+ work_queue = dispatch_queue_create("work queue", NULL);
- if (debug == 1) printf("\nScan for expired messages\n");
+ /* Exit on SIGTERM */
+ signal(SIGTERM, SIG_IGN);
+ sig_term_src = dispatch_source_create(DISPATCH_SOURCE_TYPE_SIGNAL, (uintptr_t)SIGTERM, 0, dispatch_get_main_queue());
+ dispatch_source_set_event_handler(sig_term_src, ^{
+ debug_log(ASL_LEVEL_NOTICE, "SIGTERM exit\n");
+ exit(0);
+ });
- e = list;
- while (e != NULL)
- {
- /* syslog -x LongTTL.new -db [e->name] -k ASLExpireTime Nge [now] */
- if (debug == 1)
- {
- printf(" %s\n", e->name);
- }
- else
- {
- status = do_match(e->name, "LongTTL.new", 1, now);
- unlink(e->name);
- if (status == ASL_STATUS_OK) rename("LongTTL.new", e->name);
- }
+ dispatch_resume(sig_term_src);
- e = e->next;
- }
-
- if (debug == 1) printf("Finished scan for expired messages\n");
+ /* Handle incoming messages. */
+ listener = xpc_connection_create_mach_service("com.apple.aslmanager", server_queue, XPC_CONNECTION_MACH_SERVICE_LISTENER);
+ xpc_connection_set_event_handler(listener, ^(xpc_object_t peer) {
+ if (xpc_get_type(peer) == XPC_TYPE_CONNECTION) accept_connection(peer);
+ });
+ xpc_connection_resume(listener);
- free_list(list);
- list = NULL;
+ cache_delete_register();
- mgr_exit(store_dir, 0);
- /* UNREACHED */
- return 0;
+ dispatch_main();
}
-