]>
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
);