]>
git.saurik.com Git - apple/syslog.git/blob - syslogd.tproj/asl_in.c
   2  * Copyright (c) 2004 Apple Computer, Inc. All rights reserved. 
   4  * @APPLE_LICENSE_HEADER_START@ 
   6  * This file contains Original Code and/or Modifications of Original Code 
   7  * as defined in and that are subject to the Apple Public Source License 
   8  * Version 2.0 (the 'License'). You may not use this file except in 
   9  * compliance with the License. Please obtain a copy of the License at 
  10  * http://www.opensource.apple.com/apsl/ and read it before using this 
  13  * The Original Code and all software distributed under the License are 
  14  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 
  15  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 
  16  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 
  17  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 
  18  * Please see the License for the specific language governing rights and 
  19  * limitations under the License. 
  21  * @APPLE_LICENSE_HEADER_END@ 
  24 #include <sys/types.h> 
  26 #include <sys/fcntl.h> 
  27 #include <sys/socket.h> 
  37 #define forever for(;;) 
  42 static FILE *aslfile 
= NULL
; 
  43 static asl_msg_t 
*query 
= NULL
; 
  45 extern int asl_log_filter
; 
  54 static int filter_token 
= -1; 
  56 struct prune_query_entry
 
  59         TAILQ_ENTRY(prune_query_entry
) entries
; 
  62 static TAILQ_HEAD(pql
, prune_query_entry
) pquery
; 
  65 _search_next(FILE *log
, char **outstr
) 
  70         struct prune_query_entry 
*p
; 
  74         if (log 
== NULL
) return MATCH_EOF
; 
  76         str 
= get_line_from_file(log
); 
  77         if (str 
== NULL
) return MATCH_EOF
; 
  79         m 
= asl_msg_from_string(str
); 
  88         for (i 
= 0, p 
= pquery
.tqh_first
; p 
!= NULL
; p 
= p
->entries
.tqe_next
, i
++) 
  90                 match 
= asl_msg_cmp(p
->query
, m
); 
 103  * Pruning the main output file (asl.log) 
 105  * The prune file (_PATH_ASL_PRUNE) is set up by the syslog command-line utiliy. 
 106  * It contains a set of queries.  The main output file is read, and each 
 107  * message is matched against these queries.  If any query matches, we save 
 108  * that message.  Anything that doesn't match is discarded. 
 112 asl_prune(asl_msg_t 
*inq
) 
 116         struct prune_query_entry 
*p
, *n
; 
 118         int status
, incount
, outcount
; 
 120         asldebug("syslogd: pruning %s\n", _PATH_ASL_OUT
); 
 125                 p 
= (struct prune_query_entry 
*)calloc(1, sizeof(struct prune_query_entry
)); 
 126                 if (p 
== NULL
) return -1; 
 129                 TAILQ_INSERT_TAIL(&pquery
, p
, entries
); 
 133                 qfile 
= fopen(_PATH_ASL_PRUNE
, "r"); 
 136                         asldebug("syslogd: can't read %s: %s\n", _PATH_ASL_PRUNE
, strerror(errno
)); 
 144                         str 
= get_line_from_file(qfile
); 
 145                         if (str 
== NULL
) break; 
 147                         q 
= asl_msg_from_string(str
); 
 148                         asldebug("syslogd: prune line %s\n", str
); 
 151                         if (q 
== NULL
) continue; 
 153                         if (q
->type 
!= ASL_TYPE_QUERY
) 
 159                         p 
= (struct prune_query_entry 
*)calloc(1, sizeof(struct prune_query_entry
)); 
 160                         if (p 
== NULL
) return -1; 
 163                         TAILQ_INSERT_TAIL(&pquery
, p
, entries
); 
 168         asprintf(&pname
, "%s.%d", _PATH_ASL_OUT
, getpid()); 
 169         if (pname 
== NULL
) return -1; 
 171         pfile 
= fopen(pname
, "w"); 
 174                 asldebug("syslogd: can't write %s: %s\n", pname
, strerror(errno
)); 
 180         aslfile 
= fopen(_PATH_ASL_OUT
, "r"); 
 183                 asldebug("syslogd: can't read %s: %s\n", _PATH_ASL_OUT
, strerror(errno
)); 
 185                 aslfile 
= fopen(_PATH_ASL_OUT
, "a"); 
 196                 status 
= _search_next(aslfile
, &str
); 
 199                  * Pruning deletes records that match the search. 
 200                  * If the match fails, we keep the record. 
 202                 if (status 
== MATCH_FALSE
) 
 205                         fprintf(pfile
, "%s\n", str
); 
 208                 if (str 
!= NULL
) free(str
); 
 210         while (status 
!= MATCH_EOF
); 
 215         unlink(_PATH_ASL_OUT
); 
 216         rename(pname
, _PATH_ASL_OUT
); 
 218         unlink(_PATH_ASL_PRUNE
); 
 219         aslfile 
= fopen(_PATH_ASL_OUT
, "a"); 
 222         for (p 
= pquery
.tqh_first
; p 
!= NULL
; p 
= n
) 
 224                 n 
= p
->entries
.tqe_next
; 
 226                 if (p
->query 
!= NULL
) asl_free(p
->query
); 
 228                 TAILQ_REMOVE(&pquery
, p
, entries
); 
 232         asldebug("syslogd: prune %d records in, %d records out\n", incount
, outcount
); 
 238 asl_in_getmsg(int fd
) 
 245         n 
= read(fd
, ls
, 11); 
 250                         asldebug("%s: read error (len): %s\n", MY_ID
, strerror(errno
)); 
 254                                 aslevent_removefd(fd
); 
 263         asldebug("%s: expecting message length %d bytes\n", MY_ID
, len
); 
 265         if (out 
== NULL
) return NULL
; 
 267         n 
= read(fd
, out
, len
); 
 272                         asldebug("%s: read error (body): %s\n", MY_ID
, strerror(errno
)); 
 276                                 aslevent_removefd(fd
); 
 283         m 
= asl_msg_from_string(out
); 
 289 asl_in_acceptmsg(int fd
) 
 293         asldebug("%s: accepting message\n", MY_ID
); 
 294         clientfd 
= accept(fd
, NULL
, 0); 
 297                 asldebug("%s: error accepting socket fd %d: %s\n", MY_ID
, fd
, strerror(errno
)); 
 301         if (fcntl(clientfd
, F_SETFL
, O_NONBLOCK
) < 0) 
 305                 asldebug("%s: couldn't set O_NONBLOCK for fd %d: %s\n", MY_ID
, clientfd
, strerror(errno
)); 
 309         aslevent_addfd(clientfd
, asl_in_getmsg
, NULL
, NULL
); 
 314 aslmod_sendmsg(asl_msg_t 
*msg
, const char *outid
) 
 319         int status
, x
, level
; 
 321         if (aslfile 
== NULL
) return -1; 
 323         /* set up com.apple.syslog.asl_filter */ 
 324         if (filter_token 
== -1) 
 326                 status 
= notify_register_check(NOTIFY_SYSTEM_ASL_FILTER
, &filter_token
); 
 327                 if (status 
!= NOTIFY_STATUS_OK
) 
 333                         status 
= notify_check(filter_token
, &x
); 
 334                         if (status 
== NOTIFY_STATUS_OK
) status 
= notify_set_state(filter_token
, asl_log_filter
); 
 335                         if (status 
!= NOTIFY_STATUS_OK
) 
 337                                 notify_cancel(filter_token
); 
 343         if (filter_token 
>= 0) 
 346                 status 
= notify_check(filter_token
, &x
); 
 347                 if ((status 
== NOTIFY_STATUS_OK
) && (x 
== 1)) 
 350                         status 
= notify_get_state(filter_token
, &x
); 
 351                         if ((status 
== NOTIFY_STATUS_OK
) && (x 
!= 0)) asl_log_filter 
= x
; 
 355         vlevel 
= asl_get(msg
, ASL_KEY_LEVEL
); 
 357         if (vlevel 
!= NULL
) level 
= atoi(vlevel
); 
 358         lmask 
= ASL_FILTER_MASK(level
); 
 359         if ((lmask 
& asl_log_filter
) == 0) return 0; 
 361         mstr 
= asl_msg_to_string(msg
, &n
); 
 364                 fprintf(aslfile
, "%s\n", mstr
); 
 375         struct sockaddr_un sun
; 
 379         asldebug("%s: init\n", MY_ID
); 
 380         if (sock 
>= 0) return sock
; 
 382         unlink(_PATH_ASL_IN
); 
 383         sock 
= socket(AF_UNIX
, SOCK_STREAM
, 0); 
 386                 asldebug("%s: couldn't create socket for %s: %s\n", MY_ID
, _PATH_ASL_IN
, strerror(errno
)); 
 390         asldebug("%s: creating %s for fd %d\n", MY_ID
, _PATH_ASL_IN
, sock
); 
 392         memset(&sun
, 0, sizeof(sun
)); 
 393         sun
.sun_family 
= AF_UNIX
; 
 394         strcpy(sun
.sun_path
, _PATH_ASL_IN
); 
 396         len 
= sizeof(struct sockaddr_un
); 
 397         if (bind(sock
, (struct sockaddr 
*)&sun
, len
) < 0) 
 399                 asldebug("%s: couldn't bind socket %d for %s: %s\n", MY_ID
, sock
, _PATH_ASL_IN
, strerror(errno
)); 
 405         rbufsize 
= 128 * 1024; 
 406         len 
= sizeof(rbufsize
); 
 408         if (setsockopt(sock
, SOL_SOCKET
, SO_RCVBUF
, &rbufsize
, len
) < 0) 
 410                 asldebug("%s: couldn't set receive buffer size for %s: %s\n", MY_ID
, sock
, _PATH_ASL_IN
, strerror(errno
)); 
 416         if (listen(sock
, SOMAXCONN
) < 0) 
 418                 asldebug("%s: couldn't listen on socket %d for %s: %s\n", MY_ID
, sock
, _PATH_ASL_IN
, strerror(errno
)); 
 421                 unlink(_PATH_ASL_IN
); 
 425         if (fcntl(sock
, F_SETFL
, O_NONBLOCK
) < 0) 
 427                 asldebug("%s: couldn't set O_NONBLOCK for socket %d (%s): %s\n", MY_ID
, sock
, _PATH_ASL_IN
, strerror(errno
)); 
 433         chmod(_PATH_ASL_IN
, 0666); 
 435         /* Add logger routine for main output file */ 
 436         aslfile 
= fopen(_PATH_ASL_OUT
, "a"); 
 439                 query 
= asl_new(ASL_TYPE_QUERY
); 
 440                 aslevent_addmatch(query
, MY_ID
); 
 441                 aslevent_addoutput(aslmod_sendmsg
, MY_ID
); 
 444         return aslevent_addfd(sock
, asl_in_acceptmsg
, NULL
, NULL
); 
 456         if (sock 
< 0) return 1; 
 458         if (filter_token 
>= 0) notify_cancel(filter_token
); 
 464         if (aslfile 
!= NULL
) fclose(aslfile
); 
 465         unlink(_PATH_ASL_IN
);