#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/uio.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <netdb.h>
#include <notify.h>
#include <pthread.h>
#include <asl_core.h>
#include "daemon.h"
#define _PATH_WALL "/usr/bin/wall"
#define _PATH_ASL_CONF "/etc/asl.conf"
#define MY_ID "asl_action"
#define ACTION_NONE 0
#define ACTION_IGNORE 1
#define ACTION_NOTIFY 2
#define ACTION_BROADCAST 3
#define ACTION_ACCESS 4
#define ACTION_STORE 5
#define ACTION_STORE_DIR 6
#define ACTION_FORWARD 7
#define forever for(;;)
#define ACT_STORE_FLAG_STAY_OPEN 0x00000001
#define ACT_STORE_FLAG_CONTINUE 0x00000002
static asl_msg_t *query = NULL;
static int reset = RESET_NONE;
static pthread_mutex_t reset_lock = PTHREAD_MUTEX_INITIALIZER;
typedef struct action_rule_s
{
asl_msg_t *query;
int action;
char *options;
void *data;
struct action_rule_s *next;
} action_rule_t;
struct store_data
{
asl_file_t *store;
FILE *storedata;
char *dir;
char *path;
mode_t mode;
uid_t uid;
gid_t gid;
uint64_t next_id;
uint32_t flags;
uint32_t p_year;
uint32_t p_month;
uint32_t p_day;
};
static action_rule_t *asl_action_rule = NULL;
static action_rule_t *asl_datastore_rule = NULL;
static int filter_token = -1;
int asl_action_close();
static int _parse_config_file(const char *);
extern void db_save_message(aslmsg m);
static char *
_next_word(char **s)
{
char *a, *p, *e, *out;
int quote, len;
if (s == NULL) return NULL;
if (*s == NULL) return NULL;
quote = 0;
p = *s;
a = p;
e = p;
while (*p != '\0')
{
if (*p == '\\')
{
p++;
e = p;
if (*p == '\0')
{
p--;
break;
}
p++;
e = p;
continue;
}
if (*p == '"')
{
if (quote == 0) quote = 1;
else quote = 0;
}
if (((*p == ' ') || (*p == '\t')) && (quote == 0))
{
e = p + 1;
break;
}
p++;
e = p;
}
*s = e;
len = p - a;
if (len == 0) return NULL;
out = malloc(len + 1);
if (out == NULL) return NULL;
memcpy(out, a, len);
out[len] = '\0';
return out;
}
static void
_do_reset(void)
{
pthread_mutex_lock(&reset_lock);
if (reset == RESET_CONFIG)
{
asl_action_close();
_parse_config_file(_PATH_ASL_CONF);
}
reset = RESET_NONE;
pthread_mutex_unlock(&reset_lock);
}
static char *
_find_action(char *s)
{
char *p;
p = s;
if (p == NULL) return NULL;
if ((*p != 'Q') && (*p != '?') && (*p != '*')) return NULL;
p++;
forever
{
while ((*p == ' ') || (*p == '\t')) p++;
if (*p == '\0') return NULL;
if (*p != '[') return p;
while (*p != ']')
{
p++;
if (*p == '\\')
{
p++;
if (*p == ']') p++;
}
}
if (*p == ']') p++;
}
return NULL;
}
static int
_parse_query_action(char *s)
{
char *act, *p;
action_rule_t *out, *rule;
act = _find_action(s);
if (act == NULL) return -1;
out = (action_rule_t *)calloc(1, sizeof(action_rule_t));
if (out == NULL) return -1;
p = strchr(act, ' ');
if (p != NULL) *p = '\0';
if (!strcasecmp(act, "ignore")) out->action = ACTION_IGNORE;
else if (!strcasecmp(act, "notify")) out->action = ACTION_NOTIFY;
else if (!strcasecmp(act, "broadcast")) out->action = ACTION_BROADCAST;
else if (!strcasecmp(act, "access")) out->action = ACTION_ACCESS;
else if (!strcasecmp(act, "store")) out->action = ACTION_STORE;
else if (!strcasecmp(act, "save")) out->action = ACTION_STORE;
else if (!strcasecmp(act, "store_directory")) out->action = ACTION_STORE_DIR;
else if (!strcasecmp(act, "store_dir")) out->action = ACTION_STORE_DIR;
else if (!strcasecmp(act, "forward")) out->action = ACTION_FORWARD;
if (p != NULL)
{
out->options = strdup(p+1);
if (out->options == NULL)
{
free(out);
return -1;
}
}
p = act - 1;
*p = '\0';
if (s[0] == '*') out->query = asl_msg_new(ASL_TYPE_QUERY);
else
{
s[0] = 'Q';
out->query = asl_msg_from_string(s);
}
if (out->query == NULL)
{
asldebug("out->query is NULL (ERROR)\n");
free(out->options);
free(out);
return -1;
}
if ((out->action == ACTION_STORE) && (out->options == NULL))
{
asldebug("action = ACTION_STORE options = NULL\n");
if (asl_datastore_rule == NULL) asl_datastore_rule = out;
else
{
for (rule = asl_datastore_rule; rule->next != NULL; rule = rule->next);
rule->next = out;
}
}
else
{
asldebug("action = %d options = %s\n", out->action, out->options);
if (asl_action_rule == NULL) asl_action_rule = out;
else
{
for (rule = asl_action_rule; rule->next != NULL; rule = rule->next);
rule->next = out;
}
}
return 0;
}
static int
_parse_set_param(char *s)
{
char **l;
uint32_t intval, count, v32a, v32b, v32c;
if (s == NULL) return -1;
if (s[0] == '\0') return 0;
s++;
while ((*s == ' ') || (*s == '\t')) s++;
l = explode(s, " \t");
if (l == NULL) return -1;
for (count = 0; l[count] != NULL; count++);
if (count == 0)
{
freeList(l);
return -1;
}
if (count == 1)
{
freeList(l);
return -1;
}
if (!strcasecmp(l[0], "debug"))
{
intval = atoi(l[1]);
config_debug(intval, l[2]);
}
else if (!strcasecmp(l[0], "cutoff"))
{
intval = atoi(l[1]);
if (intval > ASL_LEVEL_DEBUG) intval = ASL_LEVEL_DEBUG;
global.asl_log_filter = ASL_FILTER_MASK_UPTO(intval);
}
else if (!strcasecmp(l[0], "mark_time"))
{
OSSpinLockLock(&global.lock);
global.mark_time = atoll(l[1]);
OSSpinLockUnlock(&global.lock);
}
else if (!strcasecmp(l[0], "dup_delay"))
{
OSSpinLockLock(&global.lock);
global.bsd_max_dup_time = atoll(l[1]);
OSSpinLockUnlock(&global.lock);
}
else if (!strcasecmp(l[0], "asl_store_ping_time"))
{
OSSpinLockLock(&global.lock);
global.asl_store_ping_time = atoll(l[1]);
OSSpinLockUnlock(&global.lock);
}
else if (!strcasecmp(l[0], "utmp_ttl"))
{
OSSpinLockLock(&global.lock);
global.utmp_ttl = (time_t)atoll(l[1]);
OSSpinLockUnlock(&global.lock);
}
else if (!strcasecmp(l[0], "fs_ttl"))
{
OSSpinLockLock(&global.lock);
global.fs_ttl = (time_t)atoll(l[1]);
OSSpinLockUnlock(&global.lock);
}
else if (!strcasecmp(l[0], "mps_limit"))
{
OSSpinLockLock(&global.lock);
global.mps_limit = (uint32_t)atol(l[1]);
OSSpinLockUnlock(&global.lock);
}
else if (!strcasecmp(l[0], "max_file_size"))
{
pthread_mutex_lock(global.db_lock);
if (global.dbtype & DB_TYPE_FILE)
{
asl_store_close(global.file_db);
global.file_db = NULL;
global.db_file_max = atoi(l[1]);
}
pthread_mutex_unlock(global.db_lock);
}
else if ((!strcasecmp(l[0], "db")) || (!strcasecmp(l[0], "database")) || (!strcasecmp(l[0], "datastore")))
{
v32a = 0;
v32b = 0;
v32c = 0;
if ((l[1][0] >= '0') && (l[1][0] <= '9'))
{
intval = atoi(l[1]);
if ((count >= 3) && (strcmp(l[2], "-"))) v32a = atoi(l[2]);
if ((count >= 4) && (strcmp(l[3], "-"))) v32b = atoi(l[3]);
if ((count >= 5) && (strcmp(l[4], "-"))) v32c = atoi(l[4]);
}
else if (!strcasecmp(l[1], "file"))
{
intval = DB_TYPE_FILE;
if ((count >= 3) && (strcmp(l[2], "-"))) v32a = atoi(l[2]);
}
else if (!strncasecmp(l[1], "mem", 3))
{
intval = DB_TYPE_MEMORY;
if ((count >= 3) && (strcmp(l[2], "-"))) v32b = atoi(l[2]);
}
else if (!strncasecmp(l[1], "min", 3))
{
intval = DB_TYPE_MINI;
if ((count >= 3) && (strcmp(l[2], "-"))) v32c = atoi(l[2]);
}
else
{
freeList(l);
return -1;
}
if (v32a == 0) v32a = global.db_file_max;
if (v32b == 0) v32b = global.db_memory_max;
if (v32c == 0) v32c = global.db_mini_max;
config_data_store(intval, v32a, v32b, v32c);
}
freeList(l);
return 0;
}
static int
_parse_line(char *s)
{
char *str;
int status;
if (s == NULL) return -1;
while ((*s == ' ') || (*s == '\t')) s++;
switch (*s)
{
case '\0':
case '#':
{
return 0;
}
case 'Q':
case '?':
case '*':
{
status = _parse_query_action(s);
break;
}
case '=':
{
status = _parse_set_param(s);
break;
}
default:
{
status = -1;
break;
}
}
if (status != 0)
{
str = NULL;
asprintf(&str, "[%s syslogd] [%s %u] [%s %u] [%s Ignoring unrecognized entry in %s: %s] [%s 0] [%s 0] [Facility syslog]",
ASL_KEY_SENDER,
ASL_KEY_LEVEL, ASL_LEVEL_ERR,
ASL_KEY_PID, getpid(),
ASL_KEY_MSG, _PATH_ASL_CONF, s,
ASL_KEY_UID, ASL_KEY_GID);
asl_log_string(str);
free(str);
}
return status;
}
static void
_act_notify(action_rule_t *r)
{
if (r == NULL) return;
if (r->options == NULL) return;
notify_post(r->options);
}
static void
_act_broadcast(action_rule_t *r, aslmsg msg)
{
#ifndef CONFIG_IPHONE
FILE *pw;
const char *val;
if (r == NULL) return;
if (msg == NULL) return;
val = r->options;
if (val == NULL) val = asl_get(msg, ASL_KEY_MSG);
if (val == NULL) return;
pw = popen(_PATH_WALL, "w");
if (pw < 0)
{
asldebug("%s: error sending wall message: %s\n", MY_ID, strerror(errno));
return;
}
fprintf(pw, "%s", val);
pclose(pw);
#endif
}
static void
_act_access_control(action_rule_t *r, aslmsg msg)
{
int32_t ruid, rgid;
char *p;
ruid = atoi(r->options);
rgid = -1;
p = strchr(r->options, ' ');
if (p == NULL) p = strchr(r->options, '\t');
if (p != NULL)
{
*p = '\0';
p++;
rgid = atoi(p);
}
if (ruid != -1) asl_set(msg, ASL_KEY_READ_UID, r->options);
if (p != NULL)
{
if (rgid != -1) asl_set(msg, ASL_KEY_READ_GID, p);
p--;
*p = ' ';
}
}
static uint32_t
_act_store_file_setup(struct store_data *sd)
{
uint32_t status;
if (sd == NULL) return ASL_STATUS_INVALID_STORE;
if (sd->store == NULL) return ASL_STATUS_INVALID_STORE;
if (sd->store->store == NULL) return ASL_STATUS_INVALID_STORE;
status = asl_file_read_set_position(sd->store, ASL_FILE_POSITION_LAST);
if (status != ASL_STATUS_OK) return status;
sd->next_id = sd->store->cursor_xid + 1;
if (fseek(sd->store->store, 0, SEEK_END) != 0) return ASL_STATUS_ACCESS_DENIED;
return ASL_STATUS_OK;
}
static uint32_t
_act_store_dir_setup(struct store_data *sd, time_t tick)
{
struct tm ctm;
char *path;
struct stat sb;
uint64_t xid;
int status;
mode_t mask;
if (sd == NULL) return ASL_STATUS_INVALID_STORE;
if (sd->dir == NULL) return ASL_STATUS_INVALID_STORE;
xid = 0;
if (sd->storedata == NULL)
{
memset(&sb, 0, sizeof(struct stat));
status = stat(sd->dir, &sb);
if (status == 0)
{
if (!S_ISDIR(sb.st_mode)) return ASL_STATUS_INVALID_STORE;
}
else if (errno == ENOENT)
{
mask = umask(0);
status = mkdir(sd->dir, sd->mode);
umask(mask);
if (status != 0) return ASL_STATUS_WRITE_FAILED;
if ((sd->uid != 0) || (sd->gid != 0))
{
if (chown(sd->dir, sd->uid, sd->gid) != 0) return ASL_STATUS_WRITE_FAILED;
}
}
else
{
return ASL_STATUS_FAILED;
}
path = NULL;
asprintf(&path, "%s/%s", sd->dir, FILE_ASL_STORE_DATA);
if (path == NULL) return ASL_STATUS_NO_MEMORY;
memset(&sb, 0, sizeof(struct stat));
status = stat(path, &sb);
if (status == 0)
{
sd->storedata = fopen(path, "r+");
if (sd->storedata == NULL)
{
free(path);
return ASL_STATUS_FAILED;
}
if (fread(&xid, sizeof(uint64_t), 1, sd->storedata) != 1)
{
free(path);
fclose(sd->storedata);
sd->storedata = NULL;
return ASL_STATUS_READ_FAILED;
}
}
else if (errno == ENOENT)
{
sd->storedata = fopen(path, "w");
if (sd->storedata == NULL)
{
free(path);
return ASL_STATUS_FAILED;
}
if ((sd->uid != 0) || (sd->gid != 0))
{
if (chown(path, sd->uid, sd->gid) != 0)
{
free(path);
return ASL_STATUS_WRITE_FAILED;
}
}
}
else
{
free(path);
return ASL_STATUS_FAILED;
}
free(path);
}
else
{
rewind(sd->storedata);
if (fread(&xid, sizeof(uint64_t), 1, sd->storedata) != 1)
{
fclose(sd->storedata);
sd->storedata = NULL;
return ASL_STATUS_READ_FAILED;
}
}
xid = asl_core_ntohq(xid);
xid++;
sd->next_id = xid;
xid = asl_core_htonq(xid);
rewind(sd->storedata);
status = fwrite(&xid, sizeof(uint64_t), 1, sd->storedata);
if (status != 1)
{
fclose(sd->storedata);
sd->storedata = NULL;
return ASL_STATUS_WRITE_FAILED;
}
if ((sd->flags & ACT_STORE_FLAG_STAY_OPEN) == 0)
{
fclose(sd->storedata);
sd->storedata = NULL;
}
memset(&ctm, 0, sizeof(struct tm));
if (localtime_r((const time_t *)&tick, &ctm) == NULL) return ASL_STATUS_FAILED;
if ((sd->p_year == ctm.tm_year) && (sd->p_month == ctm.tm_mon) && (sd->p_day == ctm.tm_mday) && (sd->path != NULL)) return ASL_STATUS_OK;
if (sd->store != NULL) asl_file_close(sd->store);
sd->p_year = 0;
sd->p_month = 0;
sd->p_day = 0;
free(sd->path);
sd->path = NULL;
asprintf(&(sd->path), "%s/%d.%02d.%02d.asl", sd->dir, ctm.tm_year + 1900, ctm.tm_mon + 1, ctm.tm_mday);
if (sd->path == NULL) return ASL_STATUS_NO_MEMORY;
sd->p_year = ctm.tm_year;
sd->p_month = ctm.tm_mon;
sd->p_day = ctm.tm_mday;
return ASL_STATUS_OK;
}
static void
_act_store(action_rule_t *r, aslmsg msg)
{
struct store_data *sd;
asl_file_t *s;
uint8_t x;
uint32_t status;
uint64_t mid;
mode_t tmp_mode, mask;
char *str, *opts, *p;
const char *val;
time_t tick;
s = NULL;
if (r->options == NULL) return;
if (r->data == NULL)
{
sd = (struct store_data *)calloc(1, sizeof(struct store_data));
if (sd == NULL) return;
opts = r->options;
sd->store = NULL;
if (r->action == ACTION_STORE)
{
sd->path = _next_word(&opts);
if ((sd->path == NULL) || (sd->path[0] != '/'))
{
str = NULL;
asprintf(&str, "[%s syslogd] [%s %u] [%s %u] [Facility syslog] [%s Invalid path for \"store\" action: %s]",
ASL_KEY_SENDER,
ASL_KEY_LEVEL, ASL_LEVEL_ERR,
ASL_KEY_PID, getpid(),
ASL_KEY_MSG, (sd->path == NULL) ? "no path specified" : sd->path);
asl_log_string(str);
free(str);
free(sd);
r->action = ACTION_NONE;
return;
}
}
else if (r->action == ACTION_STORE_DIR)
{
sd->dir = _next_word(&opts);
if ((sd->dir == NULL) || (sd->dir[0] != '/'))
{
str = NULL;
asprintf(&str, "[%s syslogd] [%s %u] [%s %u] [Facility syslog] [%s Invalid path for \"store_directory\" action: %s]",
ASL_KEY_SENDER,
ASL_KEY_LEVEL, ASL_LEVEL_ERR,
ASL_KEY_PID, getpid(),
ASL_KEY_MSG, (sd->dir == NULL) ? "no path specified" : sd->dir);
asl_log_string(str);
free(str);
free(sd);
r->action = ACTION_NONE;
return;
}
}
sd->mode = 0755;
sd->next_id = 0;
sd->uid = 0;
sd->gid = 0;
sd->flags = 0;
while (NULL != (p = _next_word(&opts)))
{
if (!strcmp(p, "stayopen"))
{
sd->flags |= ACT_STORE_FLAG_STAY_OPEN;
}
else if (!strcmp(p, "continue"))
{
sd->flags |= ACT_STORE_FLAG_CONTINUE;
}
else if (!strncmp(p, "mode=0", 6))
{
sd->mode = 0;
x = *(p + 6);
if ((x < '0') || (x > '7'))
{
free(p);
free(sd->path);
free(sd->dir);
free(sd);
r->action = ACTION_NONE;
return;
}
tmp_mode = x - '0';
sd->mode += tmp_mode << 6;
x = *(p + 7);
if ((x < '0') || (x > '7'))
{
free(p);
free(sd->path);
free(sd->dir);
free(sd);
r->action = ACTION_NONE;
return;
}
tmp_mode = x - '0';
sd->mode += tmp_mode << 3;
x = *(p + 8);
if ((x < '0') || (x > '7'))
{
free(p);
free(sd->path);
free(sd->dir);
free(sd);
r->action = ACTION_NONE;
return;
}
tmp_mode = x - '0';
sd->mode += tmp_mode;
}
else if (!strncmp(p, "mode=", 5)) sd->mode = atoi(p+4);
else if (!strncmp(p, "uid=", 4)) sd->uid = atoi(p+4);
else if (!strncmp(p, "gid=", 4)) sd->gid = atoi(p+4);
free(p);
p = NULL;
}
r->data = sd;
}
else
{
sd = (struct store_data *)r->data;
}
if (r->action == ACTION_STORE_DIR)
{
val = asl_get(msg, ASL_KEY_TIME);
if (val == NULL) return;
tick = atol(val);
status = _act_store_dir_setup(sd, tick);
if (status != ASL_STATUS_OK)
{
asldebug("_act_store_dir_setup %s failed: %s\n", sd->path, asl_core_error(status));
asl_file_close(sd->store);
sd->store = NULL;
r->action = ACTION_NONE;
return;
}
}
if (sd->store == NULL)
{
s = NULL;
mask = umask(0);
status = asl_file_open_write(sd->path, (sd->mode & 0666), sd->uid, sd->gid, &s);
umask(mask);
if ((status != ASL_STATUS_OK) || (s == NULL))
{
asldebug("asl_file_open_write %s failed: %s\n", sd->path, asl_core_error(status));
asl_file_close(sd->store);
sd->store = NULL;
r->action = ACTION_NONE;
return;
}
sd->store = s;
}
if (r->action != ACTION_STORE_DIR)
{
status = _act_store_file_setup(sd);
if (status != ASL_STATUS_OK)
{
asldebug("_act_store_file_setup %s failed: %s\n", sd->path, asl_core_error(status));
asl_file_close(sd->store);
sd->store = NULL;
r->action = ACTION_NONE;
return;
}
}
mid = sd->next_id;
status = asl_file_save(sd->store, msg, &mid);
if (status != ASL_STATUS_OK)
{
asldebug("asl_file_save %s failed: %s\n", sd->path, asl_core_error(status));
asl_file_close(sd->store);
sd->store = NULL;
r->action = ACTION_NONE;
return;
}
if ((sd->flags & ACT_STORE_FLAG_STAY_OPEN) == 0)
{
asl_file_close(sd->store);
sd->store = NULL;
}
if ((sd->flags & ACT_STORE_FLAG_CONTINUE) == 0)
{
opts = (char *)asl_get(msg, ASL_KEY_OPTION);
if (opts == NULL)
{
asl_set(msg, ASL_KEY_OPTION, ASL_OPT_IGNORE);
}
else
{
str = NULL;
asprintf(&str, "%s %s", ASL_OPT_IGNORE, opts);
if (str != NULL)
{
asl_set(msg, ASL_KEY_OPTION, str);
free(str);
}
}
}
}
static void
_act_forward(action_rule_t *r, aslmsg msg)
{
}
static void
send_to_asl_store(aslmsg msg)
{
const char *vlevel, *val;
uint64_t v64;
uint32_t status, level, lmask;
int x, log_me;
action_rule_t *r;
if (filter_token == -1)
{
status = notify_register_check(NOTIFY_SYSTEM_ASL_FILTER, &filter_token);
if (status != NOTIFY_STATUS_OK)
{
filter_token = -1;
}
else
{
status = notify_check(filter_token, &x);
if (status == NOTIFY_STATUS_OK)
{
v64 = global.asl_log_filter;
status = notify_set_state(filter_token, v64);
}
if (status != NOTIFY_STATUS_OK)
{
notify_cancel(filter_token);
filter_token = -1;
}
}
}
log_me = asl_check_option(msg, ASL_OPT_STORE);
if (log_me == 1)
{
db_save_message(msg);
return;
}
log_me = 0;
if (filter_token >= 0)
{
x = 0;
status = notify_check(filter_token, &x);
if ((status == NOTIFY_STATUS_OK) && (x == 1))
{
v64 = 0;
status = notify_get_state(filter_token, &v64);
if ((status == NOTIFY_STATUS_OK) && (v64 != 0)) global.asl_log_filter = v64;
}
}
val = asl_get(msg, ASL_KEY_PID);
if ((val != NULL) && (atoi(val) <= 1)) log_me = 1;
else
{
vlevel = asl_get(msg, ASL_KEY_LEVEL);
level = 7;
if (vlevel != NULL) level = atoi(vlevel);
lmask = ASL_FILTER_MASK(level);
if ((lmask & global.asl_log_filter) != 0) log_me = 1;
}
if (log_me == 0) return;
if (asl_datastore_rule == NULL)
{
db_save_message(msg);
return;
}
for (r = asl_datastore_rule; r != NULL; r = r->next)
{
if (asl_msg_cmp(r->query, (asl_msg_t *)msg) == 1)
{
db_save_message(msg);
return;
}
}
}
int
asl_action_sendmsg(aslmsg msg, const char *outid)
{
action_rule_t *r;
if (reset != RESET_NONE) _do_reset();
if (msg == NULL) return -1;
for (r = asl_action_rule; r != NULL; r = r->next)
{
if (asl_msg_cmp(r->query, (asl_msg_t *)msg) == 1)
{
if ((r->action == ACTION_STORE) || (r->action == ACTION_STORE_DIR))
{
_act_store(r, msg);
if (asl_check_option(msg, ASL_OPT_IGNORE) != 0) return -1;
}
if (r->action == ACTION_NONE) continue;
else if (r->action == ACTION_IGNORE) return -1;
else if (r->action == ACTION_ACCESS) _act_access_control(r, msg);
else if (r->action == ACTION_NOTIFY) _act_notify(r);
else if (r->action == ACTION_BROADCAST) _act_broadcast(r, msg);
else if (r->action == ACTION_FORWARD) _act_forward(r, msg);
}
}
if (asl_check_option(msg, ASL_OPT_IGNORE) != 0) return -1;
send_to_asl_store(msg);
return 0;
}
static int
_parse_config_file(const char *name)
{
FILE *cf;
char *line;
cf = fopen(name, "r");
if (cf == NULL) return 1;
while (NULL != (line = get_line_from_file(cf)))
{
_parse_line(line);
free(line);
}
fclose(cf);
return 0;
}
int
asl_action_init(void)
{
asldebug("%s: init\n", MY_ID);
query = asl_msg_new(ASL_TYPE_QUERY);
aslevent_addmatch(query, MY_ID);
aslevent_addoutput(asl_action_sendmsg, MY_ID);
_parse_config_file(_PATH_ASL_CONF);
return 0;
}
int
asl_action_reset(void)
{
reset = global.reset;
return 0;
}
int
asl_action_close(void)
{
action_rule_t *r, *n;
struct store_data *sd;
n = NULL;
for (r = asl_action_rule; r != NULL; r = n)
{
n = r->next;
if (((r->action == ACTION_STORE) || (r->action == ACTION_STORE_DIR) || (r->action == ACTION_NONE)) && (r->data != NULL))
{
sd = (struct store_data *)r->data;
if (sd->store != NULL) asl_file_close(sd->store);
if (sd->storedata != NULL) fclose(sd->storedata);
free(sd->path);
free(sd->dir);
sd->store = NULL;
free(sd);
}
if (r->query != NULL) asl_msg_release(r->query);
free(r->options);
free(r);
}
asl_action_rule = NULL;
n = NULL;
for (r = asl_datastore_rule; r != NULL; r = n)
{
n = r->next;
if (r->query != NULL) asl_msg_release(r->query);
free(r->options);
free(r);
}
asl_datastore_rule = NULL;
return 0;
}