]> git.saurik.com Git - apple/syslog.git/blob - syslogd.tproj/asl_action.c
syslog-13.1.tar.gz
[apple/syslog.git] / syslogd.tproj / asl_action.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/socket.h>
27 #include <sys/un.h>
28 #include <sys/uio.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <unistd.h>
33 #include <fcntl.h>
34 #include <errno.h>
35 #include <netdb.h>
36 #include <notify.h>
37 #include "daemon.h"
38
39 #define _PATH_ASL_CONF "/etc/asl.conf"
40 #define MY_ID "asl_action"
41
42 #define ASL_KEY_FACILITY "Facility"
43 #define IndexNull ((uint32_t)-1)
44 #define forever for(;;)
45
46 static asl_msg_t *query = NULL;
47 static int reset = 0;
48
49 struct action_rule
50 {
51 asl_msg_t *query;
52 char *action;
53 char *options;
54 TAILQ_ENTRY(action_rule) entries;
55 };
56
57 static TAILQ_HEAD(cr, action_rule) asl_action_rule;
58
59 int asl_action_close();
60 static int _parse_notify_file(const char *);
61
62 static void
63 _do_reset(void)
64 {
65 asl_action_close();
66 _parse_notify_file(_PATH_ASL_CONF);
67 }
68
69 /*
70 * Config File format:
71 * Q [k v] [k v] ... action args...
72 */
73
74 /* Skip over query */
75 static char *
76 _find_action(char *s)
77 {
78 char *p;
79
80 p = s;
81 if (p == NULL) return NULL;
82 if (*p != 'Q') return NULL;
83
84 p++;
85
86 forever
87 {
88 /* Find next [ */
89 while ((*p == ' ') || (*p == '\t')) p++;
90
91 if (*p == '\0') return NULL;
92 if (*p != '[') return p;
93
94 /* skip to closing ] */
95 while (*p != ']')
96 {
97 p++;
98 if (*p == '\\')
99 {
100 p++;
101 if (*p == ']') p++;
102 }
103 }
104
105 if (*p == ']') p++;
106 }
107
108 return NULL;
109 }
110
111 static int
112 _parse_line(char *s)
113 {
114 char *act, *p;
115 struct action_rule *out;
116
117 if (s == NULL) return -1;
118 while ((*s == ' ') || (*s == '\t')) s++;
119 if (*s == '#') return -1;
120
121 act = _find_action(s);
122
123 if (act == NULL) return -1;
124 out = (struct action_rule *)calloc(1, sizeof(struct action_rule));
125 if (out == NULL) return -1;
126
127 p = strchr(act, ' ');
128 if (p != NULL) *p = '\0';
129 out->action = strdup(act);
130
131 if (out->action == NULL)
132 {
133 free(out);
134 return -1;
135 }
136
137 if (p != NULL)
138 {
139 out->options = strdup(p+1);
140
141 if (out->options == NULL)
142 {
143 free(out->action);
144 free(out);
145 return -1;
146 }
147 }
148
149 p = act - 1;
150
151 *p = '\0';
152 out->query = asl_msg_from_string(s);
153
154 if (out->query == NULL)
155 {
156 free(out->action);
157 if (out->options != NULL) free(out->options);
158 free(out);
159 return -1;
160 }
161
162 TAILQ_INSERT_TAIL(&asl_action_rule, out, entries);
163
164 return 0;
165 }
166
167 static void
168 _act_notify(struct action_rule *r)
169 {
170 if (r == NULL) return;
171 if (r->options == NULL) return;
172 notify_post(r->options);
173 }
174
175 int
176 asl_action_sendmsg(asl_msg_t *msg, const char *outid)
177 {
178 struct action_rule *r;
179
180
181 if (reset != 0)
182 {
183 _do_reset();
184 reset = 0;
185 }
186
187 if (msg == NULL) return -1;
188
189 for (r = asl_action_rule.tqh_first; r != NULL; r = r->entries.tqe_next)
190 {
191 if (asl_msg_cmp(r->query, msg) == 1)
192 {
193 if (r->action == NULL) continue;
194 if (!strcmp(r->action, "notify")) _act_notify(r);
195 }
196 }
197
198 return 0;
199 }
200
201 static int
202 _parse_notify_file(const char *name)
203 {
204 FILE *cf;
205 char *line;
206
207 cf = fopen(name, "r");
208 if (cf == NULL) return 1;
209
210 while (NULL != (line = get_line_from_file(cf)))
211 {
212 _parse_line(line);
213 free(line);
214 }
215
216 fclose(cf);
217
218 return 0;
219 }
220
221 int
222 asl_action_init(void)
223 {
224 asldebug("%s: init\n", MY_ID);
225
226 TAILQ_INIT(&asl_action_rule);
227
228 query = asl_new(ASL_TYPE_QUERY);
229 aslevent_addmatch(query, MY_ID);
230 aslevent_addoutput(asl_action_sendmsg, MY_ID);
231
232 _parse_notify_file(_PATH_ASL_CONF);
233 return 0;
234 }
235
236 int
237 asl_action_reset(void)
238 {
239 reset = 1;
240 return 0;
241 }
242
243 int
244 asl_action_close(void)
245 {
246 struct action_rule *r, *n;
247
248 n = NULL;
249 for (r = asl_action_rule.tqh_first; r != NULL; r = n)
250 {
251 n = r->entries.tqe_next;
252
253 if (r->query != NULL) asl_free(r->query);
254 if (r->action != NULL) free(r->action);
255 if (r->options != NULL) free(r->options);
256
257 TAILQ_REMOVE(&asl_action_rule, r, entries);
258 free(r);
259 }
260
261 return 0;
262 }