]> git.saurik.com Git - apple/syslog.git/blob - syslogd.tproj/asl_in.c
bc5b2b8f10c3b7d832e0def5fc18834b62111efe
[apple/syslog.git] / syslogd.tproj / asl_in.c
1 /*
2 * Copyright (c) 2004 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
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
11 * file.
12 *
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.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24 #include <sys/types.h>
25 #include <sys/stat.h>
26 #include <sys/fcntl.h>
27 #include <sys/socket.h>
28 #include <sys/un.h>
29 #include <sys/uio.h>
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <unistd.h>
34 #include <errno.h>
35 #include "daemon.h"
36
37 #define forever for(;;)
38
39 #define ASL_SOCKET_NAME "AppleSystemLogger"
40 #define MY_ID "asl"
41
42 static int sock = -1;
43 static asl_msg_t *query = NULL;
44
45 extern int asl_log_filter;
46
47 #define MATCH_EOF -1
48 #define MATCH_NULL 0
49 #define MATCH_TRUE 1
50 #define MATCH_FALSE 2
51
52 extern int prune;
53
54 extern void db_enqueue(asl_msg_t *m);
55
56 static int filter_token = -1;
57
58 asl_msg_t *
59 asl_in_getmsg(int fd)
60 {
61 char *out;
62 asl_msg_t *m;
63 uint32_t len, n;
64 char tmp[16];
65 int status;
66 uid_t uid;
67 gid_t gid;
68
69 n = read(fd, tmp, 11);
70 if (n < 11)
71 {
72 if (n == 0)
73 {
74 close(fd);
75 aslevent_removefd(fd);
76 return NULL;
77 }
78
79 if (n < 0)
80 {
81 asldebug("%s: read error (len=%d): %s\n", MY_ID, n, strerror(errno));
82 if (errno != EINTR)
83 {
84 close(fd);
85 aslevent_removefd(fd);
86 return NULL;
87 }
88 }
89
90 return NULL;
91 }
92
93 len = atoi(tmp);
94 if (len == 0) return NULL;
95
96 out = malloc(len);
97 if (out == NULL) return NULL;
98
99 n = read(fd, out, len);
100 if (n < len)
101 {
102 if (n <= 0)
103 {
104 asldebug("%s: read error (body): %s\n", MY_ID, strerror(errno));
105 if (errno != EINTR)
106 {
107 close(fd);
108 aslevent_removefd(fd);
109 free(out);
110 return NULL;
111 }
112 }
113 }
114
115 asldebug("asl_in_getmsg: %s\n", (out == NULL) ? "NULL" : out);
116
117 uid = -2;
118 gid = -2;
119
120 status = getpeereid(fd, &uid, &gid);
121 m = asl_msg_from_string(out);
122 if (m == NULL)
123 {
124 free(out);
125 return NULL;
126 }
127
128 snprintf(tmp, sizeof(tmp), "%d", uid);
129 asl_set(m, ASL_KEY_UID, tmp);
130
131 snprintf(tmp, sizeof(tmp), "%d", gid);
132 asl_set(m, ASL_KEY_GID, tmp);
133
134 free(out);
135 return m;
136 }
137
138 asl_msg_t *
139 asl_in_acceptmsg(int fd)
140 {
141 int clientfd;
142
143 asldebug("%s: accepting message\n", MY_ID);
144 clientfd = accept(fd, NULL, 0);
145 if (clientfd < 0)
146 {
147 asldebug("%s: error accepting socket fd %d: %s\n", MY_ID, fd, strerror(errno));
148 return NULL;
149 }
150
151 if (fcntl(clientfd, F_SETFL, O_NONBLOCK) < 0)
152 {
153 close(clientfd);
154 clientfd = -1;
155 asldebug("%s: couldn't set O_NONBLOCK for fd %d: %s\n", MY_ID, clientfd, strerror(errno));
156 return NULL;
157 }
158
159 aslevent_addfd(clientfd, ADDFD_FLAGS_LOCAL, asl_in_getmsg, NULL, NULL);
160 return NULL;
161 }
162
163 int
164 aslmod_sendmsg(asl_msg_t *msg, const char *outid)
165 {
166 const char *vlevel, *facility, *ignore;
167 uint32_t lmask;
168 uint64_t v64;
169 int status, x, level, log_me;
170
171 /* set up com.apple.syslog.asl_filter */
172 if (filter_token == -1)
173 {
174 status = notify_register_check(NOTIFY_SYSTEM_ASL_FILTER, &filter_token);
175 if (status != NOTIFY_STATUS_OK)
176 {
177 filter_token = -1;
178 }
179 else
180 {
181 status = notify_check(filter_token, &x);
182 if (status == NOTIFY_STATUS_OK)
183 {
184 v64 = asl_log_filter;
185 status = notify_set_state(filter_token, v64);
186 }
187 if (status != NOTIFY_STATUS_OK)
188 {
189 notify_cancel(filter_token);
190 filter_token = -1;
191 }
192 }
193 }
194
195 if (filter_token >= 0)
196 {
197 x = 0;
198 status = notify_check(filter_token, &x);
199 if ((status == NOTIFY_STATUS_OK) && (x == 1))
200 {
201 v64 = 0;
202 status = notify_get_state(filter_token, &v64);
203 if ((status == NOTIFY_STATUS_OK) && (v64 != 0)) asl_log_filter = v64;
204 }
205 }
206
207 log_me = 0;
208 facility = asl_get(msg, ASL_KEY_FACILITY);
209 if ((facility != NULL) && (!strcmp(facility, "kern"))) log_me = 1;
210 else
211 {
212 vlevel = asl_get(msg, ASL_KEY_LEVEL);
213 level = 7;
214 if (vlevel != NULL) level = atoi(vlevel);
215 lmask = ASL_FILTER_MASK(level);
216 if ((lmask & asl_log_filter) != 0) log_me = 1;
217 }
218
219 if (log_me == 1)
220 {
221 ignore = asl_get(msg, ASL_KEY_IGNORE);
222 if ((ignore != NULL) && (!strcasecmp(ignore, "yes"))) log_me = 0;
223 }
224
225 if (log_me == 1) db_enqueue(msg);
226
227 return 0;
228 }
229
230 int
231 asl_in_init(void)
232 {
233 int rbufsize;
234 int len;
235 launch_data_t sockets_dict, fd_array, fd_dict;
236
237 asldebug("%s: init\n", MY_ID);
238 if (sock >= 0) return sock;
239 if (launch_dict == NULL)
240 {
241 asldebug("%s: laucnchd dict is NULL\n", MY_ID);
242 return -1;
243 }
244
245 sockets_dict = launch_data_dict_lookup(launch_dict, LAUNCH_JOBKEY_SOCKETS);
246 if (sockets_dict == NULL)
247 {
248 asldebug("%s: laucnchd lookup of LAUNCH_JOBKEY_SOCKETS failed\n", MY_ID);
249 return -1;
250 }
251
252 fd_array = launch_data_dict_lookup(sockets_dict, ASL_SOCKET_NAME);
253 if (fd_array == NULL)
254 {
255 asldebug("%s: laucnchd lookup of ASL_SOCKET_NAME failed\n", MY_ID);
256 return -1;
257 }
258
259 len = launch_data_array_get_count(fd_array);
260 if (len <= 0)
261 {
262 asldebug("%s: laucnchd fd array is empty\n", MY_ID);
263 return -1;
264 }
265
266 if (len > 1)
267 {
268 asldebug("%s: warning! laucnchd fd array has %d sockets\n", MY_ID, len);
269 }
270
271 fd_dict = launch_data_array_get_index(fd_array, 0);
272 if (fd_dict == NULL)
273 {
274 asldebug("%s: laucnchd file discriptor array element 0 is NULL\n", MY_ID);
275 return -1;
276 }
277
278 sock = launch_data_get_fd(fd_dict);
279
280 rbufsize = 128 * 1024;
281 len = sizeof(rbufsize);
282
283 if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF, &rbufsize, len) < 0)
284 {
285 asldebug("%s: couldn't set receive buffer size for %s: %s\n", MY_ID, sock, _PATH_ASL_IN, strerror(errno));
286 close(sock);
287 sock = -1;
288 return -1;
289 }
290
291 if (fcntl(sock, F_SETFL, O_NONBLOCK) < 0)
292 {
293 asldebug("%s: couldn't set O_NONBLOCK for socket %d (%s): %s\n", MY_ID, sock, _PATH_ASL_IN, strerror(errno));
294 close(sock);
295 sock = -1;
296 return -1;
297 }
298
299 query = asl_new(ASL_TYPE_QUERY);
300 aslevent_addmatch(query, MY_ID);
301 aslevent_addoutput(aslmod_sendmsg, MY_ID);
302
303 return aslevent_addfd(sock, ADDFD_FLAGS_LOCAL, asl_in_acceptmsg, NULL, NULL);
304 }
305
306 int
307 asl_in_reset(void)
308 {
309 return 0;
310 }
311
312 int
313 asl_in_close(void)
314 {
315 if (sock < 0) return 1;
316
317 if (filter_token >= 0) notify_cancel(filter_token);
318 filter_token = -1;
319 asl_log_filter = 0;
320
321 asl_free(query);
322 close(sock);
323 unlink(_PATH_ASL_IN);
324
325 return 0;
326 }