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