1 |
/* ====================================================================== |
---|
2 |
* Copyright (c) 2000 Theo Schlossnagle |
---|
3 |
* All rights reserved. |
---|
4 |
* The following code was written by Theo Schlossnagle <jesus@omniti.com> |
---|
5 |
* This code was written to facilitate clustered logging via Spread. |
---|
6 |
* More information on Spread can be found at http://www.spread.org/ |
---|
7 |
* Please refer to the LICENSE file before using this software. |
---|
8 |
* ====================================================================== |
---|
9 |
*/ |
---|
10 |
|
---|
11 |
|
---|
12 |
#include <stdio.h> |
---|
13 |
#include <string.h> |
---|
14 |
#include <sys/types.h> |
---|
15 |
#include <sys/stat.h> |
---|
16 |
#include <fcntl.h> |
---|
17 |
#include <sys/file.h> |
---|
18 |
#include <sys/param.h> |
---|
19 |
#include <unistd.h> |
---|
20 |
|
---|
21 |
#include "config.h" |
---|
22 |
#include "skiplist.h" |
---|
23 |
#include "timefuncs.h" |
---|
24 |
|
---|
25 |
extern FILE *yyin; |
---|
26 |
extern int buffsize; |
---|
27 |
extern int nr_open; |
---|
28 |
|
---|
29 |
int yyparse (void); |
---|
30 |
int line_num, semantic_errors; |
---|
31 |
static Skiplist logfiles; |
---|
32 |
static Skiplist spreaddaemons; |
---|
33 |
extern int verbose; |
---|
34 |
extern int skiplocking; |
---|
35 |
int logfile_compare(void *a, void *b) { |
---|
36 |
LogFile *ar = (LogFile *)a; |
---|
37 |
LogFile *br = (LogFile *)b; |
---|
38 |
return strcmp(ar->filename, br->filename); |
---|
39 |
} |
---|
40 |
int logfile_compare_key(void *a, void *b) { |
---|
41 |
LogFile *br = (LogFile *)b; |
---|
42 |
return strcmp(a, br->filename); |
---|
43 |
} |
---|
44 |
int spreadd_compare(void *a, void *b) { |
---|
45 |
SpreadConfiguration *ar = (SpreadConfiguration *)a; |
---|
46 |
SpreadConfiguration *br = (SpreadConfiguration *)b; |
---|
47 |
int temp; |
---|
48 |
if((temp = strcmp(ar->port, br->port))!=0) |
---|
49 |
return temp; |
---|
50 |
if((!ar->host) && (!br->host)) return 0; |
---|
51 |
if(!ar->host) return -1; |
---|
52 |
if(!br->host) return 1; |
---|
53 |
return strcmp(ar->host, br->host); |
---|
54 |
} |
---|
55 |
int spreadd_compare_key(void *a, void *b) { |
---|
56 |
SpreadConfiguration *br = (SpreadConfiguration *)b; |
---|
57 |
int temp; |
---|
58 |
if((temp = strcmp(a, br->port))!=0) |
---|
59 |
return temp; |
---|
60 |
if((!a) && (!br->host)) return 0; |
---|
61 |
if(!a) return -1; |
---|
62 |
if(!br->host) return 1; |
---|
63 |
return strcmp(a, br->host); |
---|
64 |
} |
---|
65 |
int facility_compare(void *a, void *b) { |
---|
66 |
LogFacility *ar = (LogFacility *)a; |
---|
67 |
LogFacility *br = (LogFacility *)b; |
---|
68 |
return strcmp(ar->groupname, br->groupname); |
---|
69 |
} |
---|
70 |
int facility_compare_key(void *a, void *b) { |
---|
71 |
LogFacility *br = (LogFacility *)b; |
---|
72 |
return strcmp(a, br->groupname); |
---|
73 |
} |
---|
74 |
int config_init(char *filename) { |
---|
75 |
int ret; |
---|
76 |
sl_init(&logfiles); |
---|
77 |
sl_set_compare(&logfiles, logfile_compare, logfile_compare_key); |
---|
78 |
sl_init(&spreaddaemons); |
---|
79 |
sl_set_compare(&spreaddaemons, spreadd_compare, spreadd_compare_key); |
---|
80 |
/* |
---|
81 |
sl_init(&logfacilities); |
---|
82 |
sl_set_compare(&logfacilities, facility_compare, facility_compare_key); |
---|
83 |
*/ |
---|
84 |
yyin = fopen(filename, "r"); |
---|
85 |
if (!yyin) { |
---|
86 |
fprintf(stderr, "Couldn't open input file: %s\n", filename); |
---|
87 |
return -1; |
---|
88 |
} |
---|
89 |
ret = yyparse(); |
---|
90 |
fclose(yyin); |
---|
91 |
return ret; |
---|
92 |
} |
---|
93 |
char *config_get_spreaddaemon(SpreadConfiguration *sc) { |
---|
94 |
static char buffer[1024]; |
---|
95 |
if(sc->host) { |
---|
96 |
snprintf(buffer, 1024, "%s@%s", sc->port, sc->host); |
---|
97 |
} |
---|
98 |
else { |
---|
99 |
strncpy(buffer, sc->port, 1024); |
---|
100 |
} |
---|
101 |
return buffer; |
---|
102 |
} |
---|
103 |
|
---|
104 |
void config_set_spread_port(SpreadConfiguration *sc, char *newport) { |
---|
105 |
if(sc->port) free(sc->port); |
---|
106 |
sc->port = newport; |
---|
107 |
} |
---|
108 |
void config_set_spread_host(SpreadConfiguration *sc, char *newhost) { |
---|
109 |
if(sc->host) free(sc->host); |
---|
110 |
sc->host = newhost; |
---|
111 |
} |
---|
112 |
void config_add_spreadconf(SpreadConfiguration *sc) { |
---|
113 |
sl_insert(&spreaddaemons, sc); |
---|
114 |
} |
---|
115 |
SpreadConfiguration *config_new_spread_conf(void) { |
---|
116 |
SpreadConfiguration *newsc; |
---|
117 |
newsc = (SpreadConfiguration *)malloc(sizeof(SpreadConfiguration)); |
---|
118 |
newsc->host=NULL; |
---|
119 |
newsc->port=strdup("4803"); |
---|
120 |
newsc->connected = 0; |
---|
121 |
newsc->logfacilities = (Skiplist *)malloc(sizeof(Skiplist)); |
---|
122 |
sl_init(newsc->logfacilities); |
---|
123 |
sl_set_compare(newsc->logfacilities, |
---|
124 |
facility_compare, facility_compare_key); |
---|
125 |
return newsc; |
---|
126 |
} |
---|
127 |
LogFacility *config_new_logfacility(void) { |
---|
128 |
LogFacility *newlf; |
---|
129 |
newlf = malloc(sizeof(LogFacility)); |
---|
130 |
newlf->groupname=NULL; |
---|
131 |
newlf->logfile=NULL; |
---|
132 |
newlf->nmatches=0; |
---|
133 |
newlf->rewritetimes=NO_REWRITE_TIMES; |
---|
134 |
newlf->rewritetimesformat=NULL; |
---|
135 |
return newlf; |
---|
136 |
} |
---|
137 |
void config_add_logfacility(SpreadConfiguration *sc, LogFacility *lf) { |
---|
138 |
sl_insert(sc->logfacilities, lf); |
---|
139 |
} |
---|
140 |
void config_set_logfacility_group(LogFacility *lf, char *ng) { |
---|
141 |
if(lf->groupname) free(lf->groupname); |
---|
142 |
lf->groupname = ng; |
---|
143 |
} |
---|
144 |
void config_set_logfacility_filename(LogFacility *lf, char *nf) { |
---|
145 |
LogFile *logf; |
---|
146 |
logf = sl_find(&logfiles, nf, NULL); |
---|
147 |
lf->logfile = logf; |
---|
148 |
if(!lf->logfile) { |
---|
149 |
logf = (LogFile *)malloc(sizeof(LogFile)); |
---|
150 |
logf->filename = nf; |
---|
151 |
logf->fd = -1; |
---|
152 |
sl_insert(&logfiles, logf); |
---|
153 |
lf->logfile = logf; |
---|
154 |
} |
---|
155 |
else { |
---|
156 |
free(nf); |
---|
157 |
} |
---|
158 |
} |
---|
159 |
void config_set_logfacility_vhostdir(LogFacility *lf, char *vhd) { |
---|
160 |
int i; |
---|
161 |
lf->vhostdir = vhd; |
---|
162 |
lf->hash = (hash_element *) malloc (nr_open * sizeof(hash_element)); |
---|
163 |
fprintf( stderr, "\nZeroing vhost hash for usage!\n"); |
---|
164 |
for(i=0; i< nr_open; i++) { |
---|
165 |
lf->hash[i].fd = -1; |
---|
166 |
lf->hash[i].hostheader = NULL; |
---|
167 |
} |
---|
168 |
|
---|
169 |
} |
---|
170 |
void config_set_logfaclity_rewritetimes_clf(LogFacility *lf) { |
---|
171 |
lf->rewritetimes = REWRITE_TIMES_IN_CLF; |
---|
172 |
} |
---|
173 |
void config_set_logfaclity_rewritetimes_user(LogFacility *lf, char *format) { |
---|
174 |
lf->rewritetimes = REWRITE_TIMES_FORMAT; |
---|
175 |
if(lf->rewritetimesformat) { |
---|
176 |
free(lf->rewritetimesformat); |
---|
177 |
} |
---|
178 |
lf->rewritetimesformat = format; |
---|
179 |
} |
---|
180 |
void config_add_logfacility_match(LogFacility *lf, char *nm) { |
---|
181 |
#ifdef RE_SYNTAX_EGREP |
---|
182 |
const char *ret; |
---|
183 |
#else |
---|
184 |
int ret; |
---|
185 |
#endif |
---|
186 |
if(lf->nmatches>=10) { |
---|
187 |
fprintf(stderr, "Already 10 regex's on group\n"); |
---|
188 |
return; |
---|
189 |
} |
---|
190 |
#ifdef RE_SYNTAX_EGREP |
---|
191 |
re_set_syntax(RE_SYNTAX_EGREP); |
---|
192 |
if((ret = re_compile_pattern(nm, strlen(nm), |
---|
193 |
&lf->match_expression[lf->nmatches]))!=0) { |
---|
194 |
fprintf(stderr, ret); |
---|
195 |
#else |
---|
196 |
if((ret = regcomp(&lf->match_expression[lf->nmatches], nm, REG_EGREP))!=0) { |
---|
197 |
char errbuf[120]; |
---|
198 |
regerror(ret, &lf->match_expression[lf->nmatches], errbuf, sizeof errbuf); |
---|
199 |
fprintf(stderr, errbuf); |
---|
200 |
#endif |
---|
201 |
} else { |
---|
202 |
lf->nmatches++; |
---|
203 |
} |
---|
204 |
} |
---|
205 |
|
---|
206 |
int config_foreach_spreadconf(int (*func)(SpreadConfiguration *, void *), |
---|
207 |
void *closure) { |
---|
208 |
int i=0; |
---|
209 |
struct skiplistnode *iter; |
---|
210 |
SpreadConfiguration *sc; |
---|
211 |
iter = sl_getlist(&spreaddaemons); |
---|
212 |
if(!iter) return i; |
---|
213 |
sc = iter->data; |
---|
214 |
do { |
---|
215 |
if(func(sc, closure)==0) i++; |
---|
216 |
} while((sc = sl_next(&spreaddaemons, &iter))!=NULL); |
---|
217 |
return i; |
---|
218 |
} |
---|
219 |
|
---|
220 |
int config_foreach_logfacility(SpreadConfiguration *sc, |
---|
221 |
int (*func)(LogFacility *, void *), |
---|
222 |
void *closure) { |
---|
223 |
int i=0; |
---|
224 |
struct skiplistnode *iter; |
---|
225 |
LogFacility *lf; |
---|
226 |
iter = sl_getlist(sc->logfacilities); |
---|
227 |
if(!iter) return i; |
---|
228 |
lf = iter->data; |
---|
229 |
do { |
---|
230 |
if(func(lf, closure)==0) i++; |
---|
231 |
} while((lf = sl_next(sc->logfacilities, &iter))!=NULL); |
---|
232 |
return i; |
---|
233 |
} |
---|
234 |
|
---|
235 |
char *config_process_message(SpreadConfiguration *sc, char *group, |
---|
236 |
char *message, int *len) { |
---|
237 |
LogFacility *lf; |
---|
238 |
char *cp; |
---|
239 |
lf = sl_find(sc->logfacilities, group, NULL); |
---|
240 |
if(lf->rewritetimes) |
---|
241 |
force_local_time(message, len, buffsize, |
---|
242 |
lf->rewritetimes, lf->rewritetimesformat); |
---|
243 |
if(lf->vhostdir) { |
---|
244 |
cp=message; |
---|
245 |
while(*cp != ' ') { |
---|
246 |
cp++; |
---|
247 |
--*len; |
---|
248 |
} |
---|
249 |
--*len; |
---|
250 |
return cp+1; |
---|
251 |
} |
---|
252 |
return message; |
---|
253 |
} |
---|
254 |
|
---|
255 |
void config_hup(void) { |
---|
256 |
config_close(); |
---|
257 |
config_start(); |
---|
258 |
} |
---|
259 |
|
---|
260 |
int config_close(void) { |
---|
261 |
struct skiplistnode *sciter, *lfiter; |
---|
262 |
SpreadConfiguration *sc; |
---|
263 |
LogFacility *lf; |
---|
264 |
int i; |
---|
265 |
sciter = sl_getlist(&spreaddaemons); |
---|
266 |
if(!sciter) return 0; |
---|
267 |
sc = (SpreadConfiguration *)sciter->data; |
---|
268 |
/* For each spread configuration: */ |
---|
269 |
do { |
---|
270 |
lfiter = sl_getlist(sc->logfacilities); |
---|
271 |
if(!lfiter) return 0; |
---|
272 |
lf = (LogFacility *)lfiter->data; |
---|
273 |
/* For each log facility in that spread configuration: */ |
---|
274 |
do { |
---|
275 |
if(lf->vhostdir) { |
---|
276 |
for (i=0;i< nr_open;i++) { |
---|
277 |
if(lf->hash[i].fd>0) { |
---|
278 |
if(!skiplocking) flock(lf->hash[i].fd, LOCK_UN); |
---|
279 |
close(lf->hash[i].fd); |
---|
280 |
lf->hash[i].fd = -1; |
---|
281 |
} |
---|
282 |
} |
---|
283 |
} else if(lf->logfile->fd>0) { |
---|
284 |
if(!skiplocking) flock(lf->logfile->fd, LOCK_UN); |
---|
285 |
close(lf->logfile->fd); |
---|
286 |
lf->logfile->fd = -1; |
---|
287 |
} |
---|
288 |
} while((lf = sl_next(sc->logfacilities, &lfiter))!=NULL); |
---|
289 |
} while((sc = sl_next(&spreaddaemons, &sciter))!=NULL); |
---|
290 |
return 0; |
---|
291 |
} |
---|
292 |
|
---|
293 |
int config_start(void) { |
---|
294 |
struct skiplistnode *sciter, *lfiter; |
---|
295 |
SpreadConfiguration *sc; |
---|
296 |
LogFacility *lf; |
---|
297 |
sciter = sl_getlist(&spreaddaemons); |
---|
298 |
if(!sciter) return 0; |
---|
299 |
sc = (SpreadConfiguration *)sciter->data; |
---|
300 |
/* For each spread configuration: */ |
---|
301 |
do { |
---|
302 |
lfiter = sl_getlist(sc->logfacilities); |
---|
303 |
if(!lfiter) return 0; |
---|
304 |
lf = (LogFacility *)lfiter->data; |
---|
305 |
/* For each log facility in that spread configuration: */ |
---|
306 |
do { |
---|
307 |
if(lf->vhostdir) continue; |
---|
308 |
else if(lf->logfile->fd<0) |
---|
309 |
lf->logfile->fd = open(lf->logfile->filename, |
---|
310 |
#ifdef __USE_LARGEFILE64 |
---|
311 |
O_CREAT|O_APPEND|O_WRONLY|O_LARGEFILE, |
---|
312 |
#else |
---|
313 |
O_CREAT|O_APPEND|O_WRONLY, |
---|
314 |
#endif |
---|
315 |
00644); |
---|
316 |
if(!skiplocking) { |
---|
317 |
if(flock(lf->logfile->fd, LOCK_NB|LOCK_EX)==-1) { |
---|
318 |
fprintf(stderr, "Cannot lock %s, is another spreadlogd running?\n", |
---|
319 |
lf->logfile->filename); |
---|
320 |
exit(1); |
---|
321 |
} |
---|
322 |
} |
---|
323 |
if(verbose) { |
---|
324 |
fprintf(stderr, "LogFacility: %s\n\tFile: %s\n\tFD: %d\n\t%d regexs\n", |
---|
325 |
lf->groupname, lf->logfile->filename, |
---|
326 |
lf->logfile->fd, lf->nmatches); |
---|
327 |
} |
---|
328 |
} while((lf = sl_next(sc->logfacilities, &lfiter))!=NULL); |
---|
329 |
} while((sc = sl_next(&spreaddaemons, &sciter))!=NULL); |
---|
330 |
return 0; |
---|
331 |
} |
---|
332 |
|
---|
333 |
int config_get_fd(SpreadConfiguration *sc, char *group, char *message) { |
---|
334 |
LogFacility *lf; |
---|
335 |
int i, ret, slen, fd; |
---|
336 |
hash_element temp; |
---|
337 |
char *cp; |
---|
338 |
char fullpath[MAXPATHLEN]; |
---|
339 |
lf = sl_find(sc->logfacilities, group, NULL); |
---|
340 |
if(!lf) return -1; |
---|
341 |
if(lf->vhostdir) { |
---|
342 |
cp = message; |
---|
343 |
while(*cp != ' '){ |
---|
344 |
cp++; |
---|
345 |
} |
---|
346 |
*cp = '\0'; |
---|
347 |
if((fd = gethash(message, lf->hash)) < 0) { |
---|
348 |
temp.hostheader = strdup(message); |
---|
349 |
*cp = ' '; |
---|
350 |
snprintf(fullpath, MAXPATHLEN, "%s/%s", lf->vhostdir,temp.hostheader); |
---|
351 |
temp.fd = open(fullpath, |
---|
352 |
#ifdef __USE_LARGEFILE64 |
---|
353 |
O_CREAT|O_APPEND|O_WRONLY|O_LARGEFILE, |
---|
354 |
#else |
---|
355 |
O_CREAT|O_APPEND|O_WRONLY, |
---|
356 |
#endif |
---|
357 |
00644); |
---|
358 |
if(!skiplocking) { |
---|
359 |
if(flock(temp.fd, LOCK_NB|LOCK_EX)==-1) { |
---|
360 |
fprintf(stderr, "Cannot lock %s, is another spreadlogd running?\n", |
---|
361 |
fullpath); |
---|
362 |
exit(1); |
---|
363 |
} |
---|
364 |
} |
---|
365 |
inshash(temp,lf->hash); |
---|
366 |
return temp.fd; |
---|
367 |
} |
---|
368 |
*cp = ' '; |
---|
369 |
return fd; |
---|
370 |
} |
---|
371 |
if(!lf->nmatches) return lf->logfile->fd; |
---|
372 |
slen = strlen(message); |
---|
373 |
for(i=0; i<lf->nmatches; i++) { |
---|
374 |
#ifdef RE_SYNTAX_EGREP |
---|
375 |
if((ret = re_search(&lf->match_expression[i], |
---|
376 |
message, slen, 0, slen, NULL)) >= 0) |
---|
377 |
return lf->logfile->fd; |
---|
378 |
else if(ret==-2 && verbose) |
---|
379 |
fprintf(stderr, "Internal error in re_search.\n"); |
---|
380 |
else if(ret==-1 && verbose) |
---|
381 |
fprintf(stderr, "Failed match!\n"); |
---|
382 |
#else if(!regexec(&lf->match_expression[i], message, 0, NULL, 0)) |
---|
383 |
return lf->logfile->fd; |
---|
384 |
#endif |
---|
385 |
} |
---|
386 |
return -1; |
---|
387 |
} |
---|
388 |
|
---|