/*
- * Copyright (c) 2004 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2004-2008 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
- * "Portions Copyright (c) 2004 Apple Computer, Inc. All Rights
- * Reserved. 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 1.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.apple.com/publicsource and read it before using
- * this file.
+ * 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,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
- * License for the specific language governing rights and limitations
- * under the License."
+ * 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@
*/
#define forever for(;;)
-#define MY_ID "asl"
+#define ASL_SOCKET_NAME "AppleSystemLogger"
+#define MY_ID "asl_in"
static int sock = -1;
-static FILE *aslfile = NULL;
-static asl_msg_t *query = NULL;
-
-extern int asl_log_filter;
-
-#define MATCH_EOF -1
-#define MATCH_NULL 0
-#define MATCH_TRUE 1
-#define MATCH_FALSE 2
-
-extern int prune;
-
-static int filter_token = -1;
-
-struct prune_query_entry
-{
- asl_msg_t *query;
- TAILQ_ENTRY(prune_query_entry) entries;
-};
-
-static TAILQ_HEAD(pql, prune_query_entry) pquery;
-
-static int
-_search_next(FILE *log, char **outstr)
-{
- char *str;
- aslmsg m;
- int match, i;
- struct prune_query_entry *p;
-
- *outstr = NULL;
-
- if (log == NULL) return MATCH_EOF;
-
- str = get_line_from_file(log);
- if (str == NULL) return MATCH_EOF;
-
- m = asl_msg_from_string(str);
- if (m == NULL)
- {
- free(str);
- return MATCH_NULL;
- }
-
- *outstr = str;
-
- for (i = 0, p = pquery.tqh_first; p != NULL; p = p->entries.tqe_next, i++)
- {
- match = asl_msg_cmp(p->query, m);
- if (match == 1)
- {
- asl_free(m);
- return MATCH_TRUE;
- }
- }
-
- asl_free(m);
- return MATCH_FALSE;
-}
-
-/*
- * Pruning the main output file (asl.log)
- *
- * The prune file (_PATH_ASL_PRUNE) is set up by the syslog command-line utiliy.
- * It contains a set of queries. The main output file is read, and each
- * message is matched against these queries. If any query matches, we save
- * that message. Anything that doesn't match is discarded.
- *
- */
-int
-asl_prune(asl_msg_t *inq)
-{
- char *pname, *str;
- FILE *pfile, *qfile;
- struct prune_query_entry *p, *n;
- asl_msg_t *q;
- int status, incount, outcount;
-
- asldebug("syslogd: pruning %s\n", _PATH_ASL_OUT);
-
- if (inq != NULL)
- {
- TAILQ_INIT(&pquery);
- p = (struct prune_query_entry *)calloc(1, sizeof(struct prune_query_entry));
- if (p == NULL) return -1;
-
- p->query = inq;
- TAILQ_INSERT_TAIL(&pquery, p, entries);
- }
- else
- {
- qfile = fopen(_PATH_ASL_PRUNE, "r");
- if (qfile == NULL)
- {
- asldebug("syslogd: can't read %s: %s\n", _PATH_ASL_PRUNE, strerror(errno));
- return 0;
- }
-
- TAILQ_INIT(&pquery);
-
- forever
- {
- str = get_line_from_file(qfile);
- if (str == NULL) break;
-
- q = asl_msg_from_string(str);
- asldebug("syslogd: prune line %s\n", str);
-
- free(str);
- if (q == NULL) continue;
-
- if (q->type != ASL_TYPE_QUERY)
- {
- asl_free(q);
- continue;
- }
-
- p = (struct prune_query_entry *)calloc(1, sizeof(struct prune_query_entry));
- if (p == NULL) return -1;
-
- p->query = q;
- TAILQ_INSERT_TAIL(&pquery, p, entries);
- }
- }
-
- pname = NULL;
- asprintf(&pname, "%s.%d", _PATH_ASL_OUT, getpid());
- if (pname == NULL) return -1;
-
- pfile = fopen(pname, "w");
- if (pfile == NULL)
- {
- asldebug("syslogd: can't write %s: %s\n", pname, strerror(errno));
- free(pname);
- return -1;
- }
-
- fclose(aslfile);
- aslfile = fopen(_PATH_ASL_OUT, "r");
- if (aslfile == NULL)
- {
- asldebug("syslogd: can't read %s: %s\n", _PATH_ASL_OUT, strerror(errno));
- free(pname);
- aslfile = fopen(_PATH_ASL_OUT, "a");
- return -1;
- }
-
- incount = 0;
- outcount = 0;
-
- do
- {
- str = NULL;
- incount++;
- status = _search_next(aslfile, &str);
-
- /*
- * Pruning deletes records that match the search.
- * If the match fails, we keep the record.
- */
- if (status == MATCH_FALSE)
- {
- outcount++;
- fprintf(pfile, "%s\n", str);
- }
-
- if (str != NULL) free(str);
- }
- while (status != MATCH_EOF);
-
- fclose(pfile);
- fclose(aslfile);
-
- unlink(_PATH_ASL_OUT);
- rename(pname, _PATH_ASL_OUT);
- free(pname);
- unlink(_PATH_ASL_PRUNE);
- aslfile = fopen(_PATH_ASL_OUT, "a");
-
- n = NULL;
- for (p = pquery.tqh_first; p != NULL; p = n)
- {
- n = p->entries.tqe_next;
-
- if (p->query != NULL) asl_free(p->query);
-
- TAILQ_REMOVE(&pquery, p, entries);
- free(p);
- }
-
- asldebug("syslogd: prune %d records in, %d records out\n", incount, outcount);
-
- return 0;
-}
asl_msg_t *
asl_in_getmsg(int fd)
char *out;
asl_msg_t *m;
uint32_t len, n;
- char ls[16];
+ char tmp[16];
+ int status;
+ uid_t uid;
+ gid_t gid;
- n = read(fd, ls, 11);
+ n = read(fd, tmp, 11);
if (n < 11)
{
- if (n <= 0)
+ if (n == 0)
+ {
+ asl_client_count_decrement();
+
+ close(fd);
+ aslevent_removefd(fd);
+ return NULL;
+ }
+
+ if (n < 0)
{
- asldebug("%s: read error (len): %s\n", MY_ID, strerror(errno));
+ asldebug("%s: read error (len=%d): %s\n", MY_ID, n, strerror(errno));
if (errno != EINTR)
{
+ asl_client_count_decrement();
+
close(fd);
aslevent_removefd(fd);
return NULL;
return NULL;
}
- len = atoi(ls);
- asldebug("%s: expecting message length %d bytes\n", MY_ID, len);
+ len = atoi(tmp);
+ if (len == 0) return NULL;
+
out = malloc(len);
if (out == NULL) return NULL;
asldebug("%s: read error (body): %s\n", MY_ID, strerror(errno));
if (errno != EINTR)
{
+ asl_client_count_decrement();
+
close(fd);
aslevent_removefd(fd);
free(out);
}
}
+ asldebug("asl_in_getmsg: %s\n", (out == NULL) ? "NULL" : out);
+
+ uid = -2;
+ gid = -2;
+
+ status = getpeereid(fd, &uid, &gid);
m = asl_msg_from_string(out);
+ if (m == NULL)
+ {
+ free(out);
+ return NULL;
+ }
+
+ snprintf(tmp, sizeof(tmp), "%d", uid);
+ asl_set(m, ASL_KEY_UID, tmp);
+
+ snprintf(tmp, sizeof(tmp), "%d", gid);
+ asl_set(m, ASL_KEY_GID, tmp);
+
free(out);
return m;
}
asl_msg_t *
-asl_in_acceptmsg(int fd)
+asl_in_new_connection(int fd)
{
int clientfd;
- asldebug("%s: accepting message\n", MY_ID);
+ asldebug("%s: accepting connection\n", MY_ID);
clientfd = accept(fd, NULL, 0);
if (clientfd < 0)
{
- asldebug("%s: error accepting socket fd %d: %s\n", MY_ID, fd, strerror(errno));
+ asldebug("%s: error connecting socket fd %d: %s\n", MY_ID, fd, strerror(errno));
return NULL;
}
return NULL;
}
- aslevent_addfd(clientfd, asl_in_getmsg, NULL, NULL);
+ asl_client_count_increment();
+
+ aslevent_addfd(SOURCE_ASL_SOCKET, clientfd, ADDFD_FLAGS_LOCAL, asl_in_getmsg, NULL, NULL);
return NULL;
}
int
-aslmod_sendmsg(asl_msg_t *msg, const char *outid)
+asl_in_init(void)
{
- const char *vlevel;
- char *mstr;
- uint32_t n, lmask;
- int status, x, level;
-
- if (aslfile == NULL) return -1;
+ int rbufsize;
+ int len;
+ launch_data_t sockets_dict, fd_array, fd_dict;
- /* set up com.apple.syslog.asl_filter */
- if (filter_token == -1)
+ asldebug("%s: init\n", MY_ID);
+ if (sock >= 0) return sock;
+ if (global.launch_dict == NULL)
{
- 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) status = notify_set_state(filter_token, asl_log_filter);
- if (status != NOTIFY_STATUS_OK)
- {
- notify_cancel(filter_token);
- filter_token = -1;
- }
- }
+ asldebug("%s: launchd dict is NULL\n", MY_ID);
+ return -1;
}
- if (filter_token >= 0)
+ sockets_dict = launch_data_dict_lookup(global.launch_dict, LAUNCH_JOBKEY_SOCKETS);
+ if (sockets_dict == NULL)
{
- x = 1;
- status = notify_check(filter_token, &x);
- if ((status == NOTIFY_STATUS_OK) && (x == 1))
- {
- x = asl_log_filter;
- status = notify_get_state(filter_token, &x);
- if ((status == NOTIFY_STATUS_OK) && (x != 0)) asl_log_filter = x;
- }
+ asldebug("%s: launchd lookup of LAUNCH_JOBKEY_SOCKETS failed\n", MY_ID);
+ return -1;
}
- vlevel = asl_get(msg, ASL_KEY_LEVEL);
- level = 7;
- if (vlevel != NULL) level = atoi(vlevel);
- lmask = ASL_FILTER_MASK(level);
- if ((lmask & asl_log_filter) == 0) return 0;
-
- mstr = asl_msg_to_string(msg, &n);
- if (mstr != NULL)
+ fd_array = launch_data_dict_lookup(sockets_dict, ASL_SOCKET_NAME);
+ if (fd_array == NULL)
{
- fprintf(aslfile, "%s\n", mstr);
- fflush(aslfile);
- free(mstr);
+ asldebug("%s: launchd lookup of ASL_SOCKET_NAME failed\n", MY_ID);
+ return -1;
}
- return 0;
-}
-
-int
-asl_in_init(void)
-{
- struct sockaddr_un sun;
- int rbufsize;
- int len;
-
- asldebug("%s: init\n", MY_ID);
- if (sock >= 0) return sock;
-
- unlink(_PATH_ASL_IN);
- sock = socket(AF_UNIX, SOCK_STREAM, 0);
- if (sock < 0)
+ len = launch_data_array_get_count(fd_array);
+ if (len <= 0)
{
- asldebug("%s: couldn't create socket for %s: %s\n", MY_ID, _PATH_ASL_IN, strerror(errno));
+ asldebug("%s: launchd fd array is empty\n", MY_ID);
return -1;
}
- asldebug("%s: creating %s for fd %d\n", MY_ID, _PATH_ASL_IN, sock);
-
- memset(&sun, 0, sizeof(sun));
- sun.sun_family = AF_UNIX;
- strcpy(sun.sun_path, _PATH_ASL_IN);
+ if (len > 1)
+ {
+ asldebug("%s: warning! launchd fd array has %d sockets\n", MY_ID, len);
+ }
- len = sizeof(struct sockaddr_un);
- if (bind(sock, (struct sockaddr *)&sun, len) < 0)
+ fd_dict = launch_data_array_get_index(fd_array, 0);
+ if (fd_dict == NULL)
{
- asldebug("%s: couldn't bind socket %d for %s: %s\n", MY_ID, sock, _PATH_ASL_IN, strerror(errno));
- close(sock);
- sock = -1;
+ asldebug("%s: launchd file discriptor array element 0 is NULL\n", MY_ID);
return -1;
}
+ sock = launch_data_get_fd(fd_dict);
+
rbufsize = 128 * 1024;
len = sizeof(rbufsize);
if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF, &rbufsize, len) < 0)
{
- asldebug("%s: couldn't set receive buffer size for %s: %s\n", MY_ID, sock, _PATH_ASL_IN, strerror(errno));
+ asldebug("%s: couldn't set receive buffer size for %d (%s): %s\n", MY_ID, sock, _PATH_ASL_IN, strerror(errno));
close(sock);
sock = -1;
return -1;
}
-
- if (listen(sock, SOMAXCONN) < 0)
- {
- asldebug("%s: couldn't listen on socket %d for %s: %s\n", MY_ID, sock, _PATH_ASL_IN, strerror(errno));
- close(sock);
- sock = -1;
- unlink(_PATH_ASL_IN);
- return -1;
- }
if (fcntl(sock, F_SETFL, O_NONBLOCK) < 0)
{
return -1;
}
- chmod(_PATH_ASL_IN, 0666);
-
- /* Add logger routine for main output file */
- aslfile = fopen(_PATH_ASL_OUT, "a");
- if (aslfile != NULL)
- {
- query = asl_new(ASL_TYPE_QUERY);
- aslevent_addmatch(query, MY_ID);
- aslevent_addoutput(aslmod_sendmsg, MY_ID);
- }
-
- return aslevent_addfd(sock, asl_in_acceptmsg, NULL, NULL);
+ return aslevent_addfd(SOURCE_ASL_SOCKET, sock, ADDFD_FLAGS_LOCAL, asl_in_new_connection, NULL, NULL);
}
int
{
if (sock < 0) return 1;
- if (filter_token >= 0) notify_cancel(filter_token);
- filter_token = -1;
- asl_log_filter = 0;
-
- asl_free(query);
close(sock);
- if (aslfile != NULL) fclose(aslfile);
unlink(_PATH_ASL_IN);
return 0;