#include <pthread.h>
#include <asl_ipc.h>
-#define ASL_SERVICE_NAME "com.apple.system.logger"
-
#define streq(A, B) (strcmp(A, B) == 0)
#define strcaseeq(A, B) (strcasecmp(A, B) == 0)
+#ifndef ASL_QUERY_OP_FALSE
+#define ASL_QUERY_OP_FALSE 0
+#endif
+
#define forever for(;;)
#define TOKEN_NULL 0
time_t asl_parse_time(const char *);
const char *asl_syslog_faciliy_num_to_name(int n);
__private_extern__ asl_client_t *_asl_open_default();
+__private_extern__ int _asl_send_level_message(aslclient ac, aslmsg msg, int level, const char *message);
/* notify SPI */
uint32_t notify_register_plain(const char *name, int *out_token);
/* from asl_util.c */
-int _asl_server_socket(int *sock, struct sockaddr_un *server);
int asl_is_utf8(const char *str);
uint8_t *asl_b64_encode(const uint8_t *buf, size_t len);
+/* fork handling in syslog.c */
+extern void _syslog_fork_child();
+
/* character encoding lengths */
static const uint8_t char_encode_len[128] =
{
typedef struct
{
int notify_count;
+ int rc_change_token;
int notify_token;
int master_token;
+ uint64_t proc_filter;
+ uint64_t master_filter;
+ int port_count;
+ mach_port_t server_port;
char *sender;
pthread_mutex_t lock;
+ pthread_mutex_t port_lock;
asl_client_t *asl;
} _asl_global_t;
#ifndef BUILDING_VARIANT
-__private_extern__ _asl_global_t _asl_global = {0, -1, -1, NULL, PTHREAD_MUTEX_INITIALIZER, NULL};
+__private_extern__ _asl_global_t _asl_global = {0, -1, -1, -1, 0LL, 0LL, 0, MACH_PORT_NULL, NULL, PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, NULL};
-static mach_port_t asl_server_port = MACH_PORT_NULL;
+#define ASL_SERVICE_NAME "com.apple.system.logger"
-static int
-_asl_connect(asl_client_t *asl)
+/*
+ * Called from the child process inside fork() to clean up
+ * inherited state from the parent process.
+ *
+ * NB. A lock isn't required, since we're single threaded in this call.
+ */
+__private_extern__ void
+_asl_fork_child()
{
- if (asl->sock >= 0) return 0;
+ _asl_global.notify_count = 0;
+ _asl_global.rc_change_token = -1;
+ _asl_global.master_token = -1;
+ _asl_global.notify_token = -1;
- return _asl_server_socket(&asl->sock, &asl->server);
+ _asl_global.port_count = 0;
+ _asl_global.server_port = MACH_PORT_NULL;
+
+ /* clean up in syslog.c */
+ _syslog_fork_child();
}
static int
_asl_notify_open(int do_lock)
{
char *notify_name;
- const char *prefix;
uint32_t status;
+ uint32_t euid;
if (do_lock != 0) pthread_mutex_lock(&_asl_global.lock);
return 0;
}
- notify_name = NULL;
-
- prefix = NOTIFY_PREFIX_USER;
- if (getuid() == 0) prefix = NOTIFY_PREFIX_SYSTEM;
+ if (_asl_global.rc_change_token == -1)
+ {
+ status = notify_register_check(NOTIFY_RC, &_asl_global.rc_change_token);
+ if (status != NOTIFY_STATUS_OK) _asl_global.rc_change_token = -1;
+ }
if (_asl_global.master_token == -1)
{
if (status != NOTIFY_STATUS_OK) _asl_global.master_token = -1;
}
- asprintf(¬ify_name, "%s.%d", prefix, getpid());
+ euid = geteuid();
+ notify_name = NULL;
+ if (euid == 0) asprintf(¬ify_name, "%s.%d", NOTIFY_PREFIX_SYSTEM, getpid());
+ else asprintf(¬ify_name, "user.uid.%d.syslog.%d", euid, getpid());
if (notify_name != NULL)
{
return;
}
+ if (_asl_global.rc_change_token > 0) notify_cancel(_asl_global.rc_change_token);
+ _asl_global.rc_change_token = -1;
+
if (_asl_global.master_token > 0) notify_cancel(_asl_global.master_token);
_asl_global.master_token = -1;
{
char *name, *x;
asl_client_t *asl;
+ kern_return_t kstatus;
asl = (asl_client_t *)calloc(1, sizeof(asl_client_t));
if (asl == NULL)
asl->sock = -1;
- if (asl->options & ASL_OPT_NO_DELAY)
+ pthread_mutex_lock(&(_asl_global.port_lock));
+
+ if (_asl_global.server_port == MACH_PORT_NULL)
{
- if (_asl_connect(asl) < 0)
- {
- free(asl);
- return NULL;
- }
+ _asl_global.port_count = 0;
+
+ kstatus = bootstrap_look_up(bootstrap_port, ASL_SERVICE_NAME, &_asl_global.server_port);
+ if (kstatus == KERN_SUCCESS) _asl_global.port_count = 1;
+ else _asl_global.server_port = MACH_PORT_NULL;
+ }
+ else
+ {
+ _asl_global.port_count++;
}
+ pthread_mutex_unlock(&(_asl_global.port_lock));
+
asl->pid = getpid();
asl->uid = getuid();
asl->gid = getgid();
asl->name = strdup(ident);
if (asl->name == NULL)
{
- close(asl->sock);
+ if (asl->sock >= 0) close(asl->sock);
free(asl);
return NULL;
}
asl->name = strdup(x);
if (asl->name == NULL)
{
- close(asl->sock);
+ if (asl->sock >= 0) close(asl->sock);
free(asl);
return NULL;
}
else asl->facility = strdup(asl_syslog_faciliy_num_to_name(LOG_USER));
if (asl->facility == NULL)
{
- close(asl->sock);
+ if (asl->sock >= 0) close(asl->sock);
free(asl);
return NULL;
}
if (asl == NULL) return;
if (asl->sock >= 0) close(asl->sock);
+
+ pthread_mutex_lock(&(_asl_global.port_lock));
+
+ if (_asl_global.port_count > 0) _asl_global.port_count--;
+ if (_asl_global.port_count == 0)
+ {
+ mach_port_deallocate(mach_task_self(), _asl_global.server_port);
+ _asl_global.server_port = MACH_PORT_NULL;
+ }
+
+ pthread_mutex_unlock(&(_asl_global.port_lock));
+
if (asl->name != NULL) free(asl->name);
if (asl->facility != NULL) free(asl->facility);
if (!(asl->options & ASL_OPT_NO_REMOTE)) _asl_notify_close();
__private_extern__ asl_client_t *
_asl_open_default()
{
+ if (_asl_global.asl != NULL) return _asl_global.asl;
+
pthread_mutex_lock(&_asl_global.lock);
if (_asl_global.asl != NULL)
{
}
static int
-_asl_msg_op_test(uint32_t op, char *q, char *m, uint32_t n)
+_asl_msg_basic_test(uint32_t op, char *q, char *m, uint32_t n)
{
int cmp;
uint32_t t;
t = op & ASL_QUERY_OP_TRUE;
+ /* NULL value from query or message string fails */
+ if ((q == NULL) || (m == NULL)) return (t & ASL_QUERY_OP_NOT_EQUAL);
+
if (op & ASL_QUERY_OP_REGEX)
{
+ /* greater than or less than make no sense in substring search */
+ if ((t == ASL_QUERY_OP_GREATER) || (t == ASL_QUERY_OP_LESS)) return 0;
+
memset(&rex, 0, sizeof(regex_t));
rflags = REG_EXTENDED | REG_NOSUB;
if (op & ASL_QUERY_OP_CASEFOLD) rflags |= REG_ICASE;
- if (regcomp(&rex, q, rflags) != 0) return 0;
+ /* A bad reqular expression matches nothing */
+ if (regcomp(&rex, q, rflags) != 0) return (t & ASL_QUERY_OP_NOT_EQUAL);
+
cmp = regexec(&rex, m, 0, NULL, 0);
regfree(&rex);
+
+ if (t == ASL_QUERY_OP_NOT_EQUAL) return (cmp != 0);
return (cmp == 0);
}
if (op & ASL_QUERY_OP_NUMERIC)
{
- /* We assume the query contains a numeric string */
- if (_asl_isanumber(m) == 0) return 0;
+ if (_asl_isanumber(q) == 0) return (t == ASL_QUERY_OP_NOT_EQUAL);
+ if (_asl_isanumber(m) == 0) return (t == ASL_QUERY_OP_NOT_EQUAL);
nq = atoi(q);
nm = atoi(m);
case ASL_QUERY_OP_LESS: return (nm < nq);
case ASL_QUERY_OP_LESS_EQUAL: return (nm <= nq);
case ASL_QUERY_OP_NOT_EQUAL: return (nm != nq);
- default: return 0;
+ default: return (t == ASL_QUERY_OP_NOT_EQUAL);
}
}
case ASL_QUERY_OP_LESS: return (cmp < 0);
case ASL_QUERY_OP_LESS_EQUAL: return (cmp <= 0);
case ASL_QUERY_OP_NOT_EQUAL: return (cmp != 0);
- default: return 0;
}
- return 0;
+ return (t == ASL_QUERY_OP_NOT_EQUAL);
}
static int
-_asl_msg_test_op_substr(uint32_t op, char *q, char *m)
+_asl_msg_test_substring(uint32_t op, char *q, char *m)
{
- uint32_t i, d, lm, lq;
+ uint32_t t, i, d, lm, lq, match, newop;
+
+ t = op & ASL_QUERY_OP_TRUE;
+
+ lm = 0;
+ if (m != NULL) lm = strlen(m);
- lm = strlen(m);
- lq = strlen(q);
+ lq = 0;
+ if (q != NULL) lq = strlen(q);
- if (lq > lm) return 0;
+ /* NULL is a substring of any string */
+ if (lq == 0) return (t & ASL_QUERY_OP_EQUAL);
+
+ /* A long string is defined to be not equal to a short string */
+ if (lq > lm) return (t == ASL_QUERY_OP_NOT_EQUAL);
+
+ /* greater than or less than make no sense in substring search */
+ if ((t == ASL_QUERY_OP_GREATER) || (t == ASL_QUERY_OP_LESS)) return 0;
+
+ /*
+ * We scan the string doing an equality test.
+ * If the input test is equality, we stop as soon as we hit a match.
+ * Otherwise we keep scanning the whole message string.
+ */
+ newop = op & 0xff0;
+ newop |= ASL_QUERY_OP_EQUAL;
+ match = 0;
d = lm - lq;
for (i = 0; i <= d; i++)
{
- if (_asl_msg_op_test(op, q, m + i, lq) != 0) return 1;
+ if (_asl_msg_basic_test(newop, q, m + i, lq) != 0)
+ {
+ if (t & ASL_QUERY_OP_EQUAL) return 1;
+ match++;
+ }
}
- return 0;
+ /* If the input test was for equality, no matches were found */
+ if (t & ASL_QUERY_OP_EQUAL) return 0;
+
+ /* The input test was for not equal. Return true if no matches were found */
+ return (match == 0);
}
static int
-_asl_msg_test_op_prefix(uint32_t op, char *q, char *m)
+_asl_msg_test_prefix(uint32_t op, char *q, char *m)
{
- uint32_t lm, lq;
+ uint32_t lm, lq, t;
+
+ t = op & ASL_QUERY_OP_TRUE;
+
+ lm = 0;
+ if (m != NULL) lm = strlen(m);
- lm = strlen(m);
- lq = strlen(q);
+ lq = 0;
+ if (q != NULL) lq = strlen(q);
- if (lq > lm) return 0;
+ /* NULL is a prefix of any string */
+ if (lq == 0) return (t & ASL_QUERY_OP_EQUAL);
- return _asl_msg_op_test(op, q, m, lq);
+ /* A long string is defined to be not equal to a short string */
+ if (lq > lm) return (t == ASL_QUERY_OP_NOT_EQUAL);
+
+ /* Compare two equal-length strings */
+ return _asl_msg_basic_test(op, q, m, lq);
}
static int
-_asl_msg_test_op_suffix(uint32_t op, char *q, char *m)
+_asl_msg_test_suffix(uint32_t op, char *q, char *m)
{
- uint32_t lm, lq, d;
+ uint32_t lm, lq, d, t;
+
+ t = op & ASL_QUERY_OP_TRUE;
+
+ lm = 0;
+ if (m != NULL) lm = strlen(m);
- lm = strlen(m);
- lq = strlen(q);
+ lq = 0;
+ if (q != NULL) lq = strlen(q);
- if (lq > lm) return 0;
+ /* NULL is a suffix of any string */
+ if (lq == 0) return (t & ASL_QUERY_OP_EQUAL);
+ /* A long string is defined to be not equal to a short string */
+ if (lq > lm) return (t == ASL_QUERY_OP_NOT_EQUAL);
+
+ /* Compare two equal-length strings */
d = lm - lq;
- return _asl_msg_op_test(op, q, m + d, lq);
+ return _asl_msg_basic_test(op, q, m + d, lq);
}
+/*
+ * Splits out prefix, suffix, and substring tests.
+ * Sends the rest to _asl_msg_basic_test().
+ */
static int
-_asl_msg_test_op(uint32_t op, char *q, char *m)
+_asl_msg_test_expression(uint32_t op, char *q, char *m)
{
uint32_t t;
if (op & ASL_QUERY_OP_PREFIX)
{
- if (op & ASL_QUERY_OP_SUFFIX) return _asl_msg_test_op_substr(op, q, m);
- return _asl_msg_test_op_prefix(op, q, m);
+ if (op & ASL_QUERY_OP_SUFFIX) return _asl_msg_test_substring(op, q, m);
+ return _asl_msg_test_prefix(op, q, m);
}
- if (op & ASL_QUERY_OP_SUFFIX) return _asl_msg_test_op_suffix(op, q, m);
+ if (op & ASL_QUERY_OP_SUFFIX) return _asl_msg_test_suffix(op, q, m);
- return _asl_msg_op_test(op, q, m, 0);
+ return _asl_msg_basic_test(op, q, m, 0);
}
+/*
+ * Special case for comparing time values.
+ * If both inputs are time strings, this compares the time
+ * value in seconds. Otherwise it just does normal matching.
+ */
static int
-_asl_msg_test_time_op(uint32_t op, char *q, char *m)
+_asl_msg_test_time_expression(uint32_t op, char *q, char *m)
{
time_t tq, tm;
- char *vq, *vm;
- struct tm gtime;
- uint32_t t, do_numeric;
- int cmp;
-
- do_numeric = 1;
+ uint32_t t;
- if ((op & ASL_QUERY_OP_PREFIX) || (op & ASL_QUERY_OP_SUFFIX) || (op & ASL_QUERY_OP_REGEX) || (op & ASL_QUERY_OP_CASEFOLD)) do_numeric = 0;
+ if ((op & ASL_QUERY_OP_PREFIX) || (op & ASL_QUERY_OP_SUFFIX) || (op & ASL_QUERY_OP_REGEX)) return _asl_msg_test_expression(op, q, m);
+ if ((q == NULL) || (m == NULL)) return _asl_msg_test_expression(op, q, m);
tq = asl_parse_time(q);
- if (tq < 0) return _asl_msg_test_op(op, q, m);
+ if (tq < 0) return _asl_msg_test_expression(op, q, m);
tm = asl_parse_time(m);
- if (tm < 0) return _asl_msg_test_op(op, q, m);
+ if (tm < 0) return _asl_msg_test_expression(op, q, m);
+
+ t = op & ASL_QUERY_OP_TRUE;
- if (do_numeric == 1)
+ switch (t)
{
- t = op & ASL_QUERY_OP_TRUE;
- switch (t)
+ case ASL_QUERY_OP_FALSE:
+ {
+ return 0;
+ }
+ case ASL_QUERY_OP_EQUAL:
{
- case ASL_QUERY_OP_EQUAL:
- if (tm == tq) return 1;
- return 0;
- case ASL_QUERY_OP_GREATER:
- if (tm > tq) return 1;
- return 0;
- case ASL_QUERY_OP_GREATER_EQUAL:
- if (tm >= tq) return 1;
- return 0;
- case ASL_QUERY_OP_LESS:
- if (tm < tq) return 1;
- return 0;
- case ASL_QUERY_OP_LESS_EQUAL:
- if (tm <= tq) return 1;
- return 0;
- case ASL_QUERY_OP_NOT_EQUAL:
- if (tm != tq) return 1;
- return 0;
- default:
- return 0;
+ if (tm == tq) return 1;
+ return 0;
+ }
+ case ASL_QUERY_OP_GREATER:
+ {
+ if (tm > tq) return 1;
+ return 0;
+ }
+ case ASL_QUERY_OP_GREATER_EQUAL:
+ {
+ if (tm >= tq) return 1;
+ return 0;
+ }
+ case ASL_QUERY_OP_LESS:
+ {
+ if (tm < tq) return 1;
+ return 0;
+ }
+ case ASL_QUERY_OP_LESS_EQUAL:
+ {
+ if (tm <= tq) return 1;
+ return 0;
+ }
+ case ASL_QUERY_OP_NOT_EQUAL:
+ {
+ if (tm != tq) return 1;
+ return 0;
+ }
+ case ASL_QUERY_OP_TRUE:
+ {
+ return 1;
}
-
- return 0;
}
- memset(>ime, 0, sizeof(struct tm));
- gmtime_r(&tq, >ime);
-
- /* Canonical form: YYYY.MM.DD hh:mm:ss UTC */
- vq = NULL;
- asprintf(&vq, "%d.%02d.%02d %02d:%02d:%02d UTC", gtime.tm_year + 1900, gtime.tm_mon + 1, gtime.tm_mday, gtime.tm_hour, gtime.tm_min, gtime.tm_sec);
- if (vq == NULL) return 0;
-
- memset(>ime, 0, sizeof(struct tm));
- gmtime_r(&tm, >ime);
-
- /* Canonical form: YYYY.MM.DD hh:mm:ss UTC */
- vm = NULL;
- asprintf(&vm, "%d.%02d.%02d %02d:%02d:%02d UTC", gtime.tm_year + 1900, gtime.tm_mon + 1, gtime.tm_mday, gtime.tm_hour, gtime.tm_min, gtime.tm_sec);
- if (vm == NULL) return 0;
-
- cmp = _asl_msg_test_op(op, q, m);
-
- free(vq);
- free(vm);
-
- return cmp;
+ /* NOTREACHED */
+ return 0;
}
+/* test a query against a message */
static int
_asl_msg_test(asl_msg_t *q, asl_msg_t *m)
{
- uint32_t i, j;
+ uint32_t i, j, t;
int cmp;
- char *val;
+ /*
+ * Check each simple expression (key op val) separately.
+ * The query suceeds (returns 1) if all simple expressions
+ * succeed (i.e. AND the simple expressions).
+ */
for (i = 0; i < q->count; i++)
{
+ /* Find query key[i] in the message */
j = _asl_msg_index(m, q->key[i]);
- if (j == (uint32_t)-1) return 0;
- if (q->val[i] == NULL) continue;
+ /* NULL op is meaningless, but we allow it to succeed */
if (q->op == NULL) continue;
- if ((q->op[i] & ASL_QUERY_OP_TRUE) == ASL_QUERY_OP_TRUE) continue;
+ /* ASL_QUERY_OP_TRUE tests if key[i] is present in the message */
+ t = q->op[i] & ASL_QUERY_OP_TRUE;
+ if (t == ASL_QUERY_OP_TRUE)
+ {
+ if (j == (uint32_t)-1) return 0;
+ continue;
+ }
- if (m->val[j] == NULL) return 0;
+ /* ASL_QUERY_OP_FALSE tests if the key is NOT present in the message */
+ if (t == ASL_QUERY_OP_FALSE)
+ {
+ if (j != (uint32_t)-1) return 0;
+ continue;
+ }
- val = q->val[i];
+ if (j == (uint32_t)-1)
+ {
+ /* the message does NOT have query key[i] - fail unless we are testing not equal */
+ if (t == ASL_QUERY_OP_NOT_EQUAL) continue;
+ return 0;
+ }
cmp = 1;
if (streq(q->key[i], ASL_KEY_TIME))
{
- cmp = _asl_msg_test_time_op(q->op[i], q->val[i], m->val[j]);
+ cmp = _asl_msg_test_time_expression(q->op[i], q->val[i], m->val[j]);
}
else
{
- cmp = _asl_msg_test_op(q->op[i], val, m->val[j]);
+ cmp = _asl_msg_test_expression(q->op[i], q->val[i], m->val[j]);
}
if (cmp == 0) return 0;
if (level < ASL_LEVEL_EMERG) level = ASL_LEVEL_EMERG;
if (level > ASL_LEVEL_DEBUG) level = ASL_LEVEL_DEBUG;
- str = NULL;
- asprintf(&str, "%d", level);
- if (str == NULL)
- {
- if ((msg != NULL) && (my_msg != 0)) asl_free(msg);
- return -1;
- }
-
- asl_set(msg, ASL_KEY_LEVEL, str);
- free(str);
-
/* insert strerror for %m */
len = 0;
elen = 0;
return -1;
}
- asl_set(msg, ASL_KEY_MSG, str);
+ status = _asl_send_level_message(ac, (aslmsg)msg, level, str);
free(str);
- status = asl_send(ac, (aslmsg)msg);
-
if ((msg != NULL) && (my_msg != 0)) asl_free(msg);
return status;
}
}
/*
- * asl_send: send a message
+ * asl_send (internal version): send a message
* This routine may be used instead of asl_log() or asl_vlog() if asl_set()
* has been used to set all of a message's attributes.
- * msg: an aslmsg
* returns 0 for success, non-zero for failure
*/
-int
-asl_send(aslclient ac, aslmsg msg)
+__private_extern__ int
+_asl_send_level_message(aslclient ac, aslmsg msg, int level, const char *message)
{
- char *str, *out_raw, *out;
- uint32_t i, len, level, lmask, outstatus, filter, senderx, facilityx;
+ char *str, *out_raw;
+ caddr_t out;
+ uint32_t i, len, outlen, lmask, outstatus, filter, check, senderx, facilityx;
uint64_t v64;
const char *val;
char *name, *x;
int status, rc_filter;
asl_client_t *asl;
int use_global_lock;
- asl_msg_t *mt;
+ asl_msg_t *mt, *tmp_msg;
char hname[_POSIX_HOST_NAME_MAX];
+ kern_return_t kstatus;
use_global_lock = 0;
asl = (asl_client_t *)ac;
if (msg == NULL) return 0;
- level = ASL_LEVEL_DEBUG;
-
val = asl_get(msg, ASL_KEY_LEVEL);
if (val != NULL) level = atoi(val);
lmask = ASL_FILTER_MASK(level);
- filter = asl->filter;
- rc_filter = 0;
-
if (!(asl->options & ASL_OPT_NO_REMOTE))
{
pthread_mutex_lock(&_asl_global.lock);
- if (_asl_global.notify_token >= 0)
+ if (_asl_global.rc_change_token >= 0)
{
- v64 = 0;
-
- status = notify_get_state(_asl_global.notify_token, &v64);
- if ((status == NOTIFY_STATUS_OK) && (v64 != 0))
+ /* initialize or re-check process-specific and master filters */
+ check = 0;
+ status = notify_check(_asl_global.rc_change_token, &check);
+ if ((status == NOTIFY_STATUS_OK) && (check != 0))
{
- filter = v64;
- rc_filter = 1;
- }
- }
-
- if ((rc_filter == 0) && (_asl_global.master_token >= 0))
- {
- v64 = 0;
+ if (_asl_global.master_token >= 0)
+ {
+ v64 = 0;
+ status = notify_get_state(_asl_global.master_token, &v64);
+ if (status == NOTIFY_STATUS_OK) _asl_global.master_filter = v64;
+ }
- status = notify_get_state(_asl_global.master_token, &v64);
- if ((status == NOTIFY_STATUS_OK) && (v64 != 0))
- {
- filter = v64;
+ if (_asl_global.notify_token >= 0)
+ {
+ v64 = 0;
+ status = notify_get_state(_asl_global.notify_token, &v64);
+ if (status == NOTIFY_STATUS_OK) _asl_global.proc_filter = v64;
+ }
}
}
pthread_mutex_unlock(&_asl_global.lock);
}
+ filter = asl->filter;
+ rc_filter = 0;
+
+ /* master filter overrides local filter */
+ if (_asl_global.master_filter != 0)
+ {
+ filter = _asl_global.master_filter;
+ rc_filter = 1;
+ }
+
+ /* process-specific filter overrides local and master */
+ if (_asl_global.proc_filter != 0)
+ {
+ filter = _asl_global.proc_filter;
+ rc_filter = 1;
+ }
+
+ /*
+ * Copy the message to tmp_msg to make setting values thread-safe
+ */
+ tmp_msg = calloc(1, sizeof(asl_msg_t));
+ if (tmp_msg == NULL) return -1;
+
+ tmp_msg->type = ASL_TYPE_MSG;
+
+ mt = (asl_msg_t *)msg;
+ for (i = 0; i < mt->count; i++)
+ {
+ asl_set(tmp_msg, mt->key[i], mt->val[i]);
+ }
+
+ /*
+ * Set Level and Message from parameters.
+ */
+ if (message != NULL) asl_set(tmp_msg, ASL_KEY_MSG, message);
+ asl_set(tmp_msg, ASL_KEY_LEVEL, _asl_level_string(level));
+
/*
* Time, TimeNanoSec, Host, PID, UID, and GID values get set here
*/
asprintf(&str, "%lu", tval.tv_sec);
if (str != NULL)
{
- asl_set(msg, ASL_KEY_TIME, str);
+ asl_set(tmp_msg, ASL_KEY_TIME, str);
free(str);
str = NULL;
}
asprintf(&str, "%lu", tval.tv_usec * 1000);
if (str != NULL)
{
- asl_set(msg, ASL_KEY_TIME_NSEC, str);
+ asl_set(tmp_msg, ASL_KEY_TIME_NSEC, str);
free(str);
str = NULL;
}
asprintf(&str, "%lu", tick);
if (str != NULL)
{
- asl_set(msg, ASL_KEY_TIME, str);
+ asl_set(tmp_msg, ASL_KEY_TIME, str);
free(str);
str = NULL;
}
memset(&hname, 0, _POSIX_HOST_NAME_MAX);
if (gethostname(hname, _POSIX_HOST_NAME_MAX) == 0)
{
- asl_set(msg, ASL_KEY_HOST, hname);
+ asl_set(tmp_msg, ASL_KEY_HOST, hname);
}
str = NULL;
asprintf(&str, "%u", getpid());
if (str != NULL)
{
- asl_set(msg, ASL_KEY_PID, str);
+ asl_set(tmp_msg, ASL_KEY_PID, str);
free(str);
}
asprintf(&str, "%d", getuid());
if (str != NULL)
{
- asl_set(msg, ASL_KEY_UID, str);
+ asl_set(tmp_msg, ASL_KEY_UID, str);
free(str);
}
asprintf(&str, "%u", getgid());
if (str != NULL)
{
- asl_set(msg, ASL_KEY_GID, str);
+ asl_set(tmp_msg, ASL_KEY_GID, str);
free(str);
}
senderx = (uint32_t)-1;
facilityx = (uint32_t)-1;
- mt = (asl_msg_t *)msg;
- for (i = 0; (i < mt->count) && ((senderx == (uint32_t)-1) || (facilityx == (uint32_t)-1)); i++)
+ for (i = 0; (i < tmp_msg->count) && ((senderx == (uint32_t)-1) || (facilityx == (uint32_t)-1)); i++)
{
- if (mt->key[i] == NULL) continue;
- if (streq(mt->key[i], ASL_KEY_SENDER)) senderx = i;
- else if (streq(mt->key[i], ASL_KEY_FACILITY)) facilityx = i;
+ if (tmp_msg->key[i] == NULL) continue;
+ if (streq(tmp_msg->key[i], ASL_KEY_SENDER)) senderx = i;
+ else if (streq(tmp_msg->key[i], ASL_KEY_FACILITY)) facilityx = i;
}
/*
* Set Sender if needed
*/
- if ((senderx == (uint32_t)-1) || (mt->val[senderx] == NULL))
+ if ((senderx == (uint32_t)-1) || (tmp_msg->val[senderx] == NULL))
{
if ((ac != NULL) && (ac->name != NULL))
{
/* Use the Sender name from the client handle */
- asl_set(msg, ASL_KEY_SENDER, ac->name);
+ asl_set(tmp_msg, ASL_KEY_SENDER, ac->name);
}
else
{
}
}
- if (_asl_global.sender != NULL) asl_set(msg, ASL_KEY_SENDER, _asl_global.sender);
- else asl_set(msg, ASL_KEY_SENDER, "Unknown");
+ if (_asl_global.sender != NULL) asl_set(tmp_msg, ASL_KEY_SENDER, _asl_global.sender);
+ else asl_set(tmp_msg, ASL_KEY_SENDER, "Unknown");
}
}
/*
* Set Facility
*/
- if ((facilityx == (uint32_t)-1) || (mt->val[facilityx] == NULL))
+ if ((facilityx == (uint32_t)-1) || (tmp_msg->val[facilityx] == NULL))
{
if ((ac != NULL) && (ac->facility != NULL))
{
/* Use the Facility name from the client handle */
- asl_set(msg, ASL_KEY_FACILITY, ac->facility);
+ asl_set(tmp_msg, ASL_KEY_FACILITY, ac->facility);
}
}
- outstatus = 0;
+ /* Set "ASLOption store" if remote control is active */
+ if (rc_filter != 0)
+ {
+ val = asl_get(msg, ASL_KEY_OPTION);
+ if (val == NULL)
+ {
+ asl_set(tmp_msg, ASL_KEY_OPTION, ASL_OPT_STORE);
+ }
+ else
+ {
+ str = NULL;
+ asprintf(&str, "%s %s", ASL_OPT_STORE, val);
+ if (str != NULL)
+ {
+ asl_set(tmp_msg, ASL_KEY_OPTION, str);
+ free(str);
+ str = NULL;
+ }
+ }
+ }
+
+ outstatus = -1;
if (use_global_lock != 0) pthread_mutex_lock(&_asl_global.lock);
if ((filter != 0) && ((filter & lmask) != 0))
{
len = 0;
- out_raw = asl_msg_to_string((asl_msg_t *)msg, &len);
+ out_raw = asl_msg_to_string(tmp_msg, &len);
if ((out_raw != NULL) && (len != 0))
{
- asprintf(&out, "%10u %s\n", len + 1, out_raw);
- if (out != NULL)
+ /* send a mach message to syslogd */
+ outlen = len + 11;
+ kstatus = vm_allocate(mach_task_self(), (vm_address_t *)&out, outlen + 1, TRUE);
+ if (kstatus == KERN_SUCCESS)
{
- if (asl->sock == -1) _asl_connect(asl);
+ memset(out, 0, outlen + 1);
+ snprintf((char *)out, outlen, "%10u %s", len, out_raw);
+
+ status = 0;
- if (asl->sock >= 0)
+ pthread_mutex_lock(&(_asl_global.port_lock));
+
+ if (_asl_global.server_port == MACH_PORT_NULL)
{
- status = write(asl->sock, out, len + 12);
- if (status < 0)
- {
- /* Write failed - try resetting */
- close(asl->sock);
- asl->sock = -1;
- _asl_connect(asl);
- if (asl->sock >= 0) status = write(asl->sock, out, len + 12);
- if (status < 0) outstatus = -1;
- }
+ _asl_global.port_count = 0;
+
+ kstatus = bootstrap_look_up(bootstrap_port, ASL_SERVICE_NAME, &_asl_global.server_port);
+ if (kstatus == KERN_SUCCESS) _asl_global.port_count = 1;
+ else _asl_global.server_port = MACH_PORT_NULL;
}
- else outstatus = -1;
- free(out);
+ pthread_mutex_unlock(&(_asl_global.port_lock));
+
+ if (kstatus == KERN_SUCCESS) kstatus = _asl_server_message(_asl_global.server_port, (caddr_t)out, outlen + 1);
+ else vm_deallocate(mach_task_self(), (vm_address_t)out, outlen + 1);
+
+ if (kstatus == KERN_SUCCESS) outstatus = 0;
}
free(out_raw);
}
}
+ outstatus = 0;
+
+ /* write to file descriptors */
for (i = 0; i < asl->fd_count; i++)
{
if (asl->fd_list[i] < 0) continue;
len = 0;
- out = asl_format_message(msg, asl->fd_mfmt[i], asl->fd_tfmt[i], asl->fd_encoding[i], &len);
+ out = asl_format_message(tmp_msg, asl->fd_mfmt[i], asl->fd_tfmt[i], asl->fd_encoding[i], &len);
if (out == NULL) continue;
status = write(asl->fd_list[i], out, len - 1);
free(out);
}
+ asl_free((aslmsg)tmp_msg);
+
if (use_global_lock != 0) pthread_mutex_unlock(&_asl_global.lock);
return outstatus;
}
+/*
+ * asl_send: send a message
+ * returns 0 for success, non-zero for failure
+ */
+int
+asl_send(aslclient ac, aslmsg msg)
+{
+ return _asl_send_level_message(ac, msg, ASL_LEVEL_DEBUG, NULL);
+}
+
char *
asl_msg_string(aslmsg a)
{
/*
* Called if there's a malloc error while manipulating a message in asl_set_query.
- * Cleans up the key, kap, and op fields, sets count to zero.
+ * Cleans up the key, val, and op fields, sets count to zero.
*/
static void
_asl_clear_msg(asl_msg_t *msg)
int
asl_set_query(aslmsg a, const char *key, const char *val, uint32_t op)
{
- uint32_t i;
+ uint32_t i, len;
char *dk, *dv;
asl_msg_t *msg;
msg = (asl_msg_t *)a;
if (msg == NULL) return 0;
-
if (key == NULL) return -1;
dv = NULL;
- if (streq(key, ASL_KEY_LEVEL))
+ if ((streq(key, ASL_KEY_MSG)) && (val != NULL))
+ {
+ /* strip trailing newlines */
+ dv = strdup(val);
+ if (dv == NULL) return -1;
+
+ len = strlen(dv);
+ i = len - 1;
+ while ((len > 0) && (dv[i] == '\n'))
+ {
+ dv[i] = '\0';
+ i--;
+ len--;
+ }
+ }
+ else if (streq(key, ASL_KEY_LEVEL))
{
if (val == NULL) return -1;
if (val[0] == '\0') return -1;
}
dk = strdup(key);
- if (dk == NULL) return -1;
+ if (dk == NULL)
+ {
+ if (dv != NULL) free(dv);
+ _asl_clear_msg(msg);
+ return -1;
+ }
msg->key[msg->count] = dk;
msg->val[msg->count] = dv;
asl_search(aslclient ac, aslmsg a)
{
asl_search_result_t query, *out;
- asl_msg_t *qlist[1];
- uint32_t status;
- uint64_t last_id;
+ asl_msg_t *q, *qlist[1];
+ uint32_t status, x;
+ uint64_t last_id, start_id;
asl_store_t *store;
if (a == NULL) return NULL;
+ q = (asl_msg_t *)a;
+
+ /* check for "ASLMessageId >[=] n" and set start_id */
+ start_id = 0;
+ x = _asl_msg_index(q, ASL_KEY_MSG_ID);
+ if ((x != (uint32_t)-1) && (q->val[x] != NULL) && (q->op != NULL) && (q->op[x] & ASL_QUERY_OP_GREATER))
+ {
+ if (q->op[x] & ASL_QUERY_OP_EQUAL) start_id = atoi(q->val[x]);
+ else start_id = atoi(q->val[x]) + 1;
+ }
+
store = NULL;
status = asl_store_open_read(NULL, &store);
if (status != 0) return NULL;
query.count = 1;
query.msg = qlist;
- status = asl_store_match(store, &query, &out, &last_id, 0, 0, 1);
+ status = asl_store_match(store, &query, &out, &last_id, start_id, 0, 1);
asl_store_close(store);
return out;
return -1;
}
-#ifdef ASL_SYSLOG_COMPAT
-
-__private_extern__ void
-asl_syslog_syslog(int pri, const char *fmt, ...)
-{
- va_list ap;
- asl_msg_t *m;
-
- if (fmt == NULL) return;
-
- m = asl_new(ASL_TYPE_MSG);
-
- va_start(ap, fmt);
- asl_vlog(NULL, m, pri, fmt, ap);
- va_end(ap);
-
- asl_free(m);
-}
-
-__private_extern__ void
-asl_syslog_vsyslog(int pri, const char *fmt, va_list ap)
-{
- asl_msg_t *m;
-
- m = asl_new(ASL_TYPE_MSG);
- asl_vlog(NULL, m, pri, fmt, ap);
- asl_free(m);
-}
-
-__private_extern__ void
-asl_syslog_openlog(const char *ident, int flags, int facility)
-{
- const char *fname;
- uint32_t opts;
-
- opts = 0;
-
- if (flags & LOG_NDELAY) opts |= ASL_OPT_NO_DELAY;
- if (flags & LOG_PERROR) opts |= ASL_OPT_STDERR;
-
- fname = asl_syslog_faciliy_num_to_name(facility);
- if (fname == NULL) fname = "user";
-
- asl_global_client = asl_open(ident, fname, opts);
-}
-
-__private_extern__ void
-asl_syslog_closelog()
-{
- asl_close();
-}
-
-__private_extern__ int
-asl_syslog_setlogmask(int p)
-{
- return asl_set_filter(p);
-}
-
-#endif ASL_SYSLOG_COMPAT
-
#endif /* BUILDING_VARIANT */