]> git.saurik.com Git - apple/syslog.git/blobdiff - syslogd.tproj/asl_in.c
syslog-100.2.tar.gz
[apple/syslog.git] / syslogd.tproj / asl_in.c
index 7a1723e7e01855342512321e065cdf077299cc4f..1bd0883ff1c72847927a71903e4f8a8295e366f3 100644 (file)
@@ -1,23 +1,22 @@
 /*
- * 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)
@@ -241,16 +47,30 @@ 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;
@@ -260,8 +80,9 @@ asl_in_getmsg(int fd)
                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;
 
@@ -273,6 +94,8 @@ asl_in_getmsg(int fd)
                        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);
@@ -281,21 +104,39 @@ asl_in_getmsg(int fd)
                }
        }
 
+       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;
        }
 
@@ -307,121 +148,72 @@ asl_in_acceptmsg(int fd)
                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)
        {
@@ -431,18 +223,7 @@ asl_in_init(void)
                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
@@ -456,13 +237,7 @@ asl_in_close(void)
 {
        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;