]>
Commit | Line | Data |
---|---|---|
b16a592a A |
1 | /* |
2 | * Copyright (c) 2004 Apple Computer, Inc. All rights reserved. | |
3 | * | |
4 | * @APPLE_LICENSE_HEADER_START@ | |
5 | * | |
02b408bf A |
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. | |
b16a592a A |
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, | |
02b408bf A |
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. | |
b16a592a A |
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 | } |