root/trunk/config.c

Revision 42, 13.3 kB (checked in by jesus, 9 years ago)

function updates and libevent logging

  • Property svn:eol-style set to native
  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
Line 
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 #include "sld_config.h"
12
13 #ifdef PERL
14 #include "perl.h"
15 #endif
16 #ifdef PYTHON
17 #include "python.h"
18 #endif
19 #include "skiplist.h"
20 #include "timefuncs.h"
21 #include "module.h"
22
23 extern FILE *sld_in;
24 extern int buffsize;
25
26 int sld_parse (void);
27 int line_num, semantic_errors;
28 static Skiplist logfiles;
29 static Skiplist spreaddaemons;
30 extern int verbose;
31 extern int skiplocking;
32 int logfile_compare(const void *a, const void *b) {
33   LogFile *ar = (LogFile *)a;
34   LogFile *br = (LogFile *)b;
35   return strcmp(ar->filename, br->filename);
36 }
37 int logfile_compare_key(const void *a, const void *b) {
38   LogFile *br = (LogFile *)b;
39   return strcmp(a, br->filename);
40
41 int spreadd_compare(const void *a, const void *b) {
42   SpreadConfiguration *ar = (SpreadConfiguration *)a;
43   SpreadConfiguration *br = (SpreadConfiguration *)b;
44   int temp;
45   if((temp = strcmp(ar->port, br->port))!=0)
46     return temp;
47   if((!ar->host) && (!br->host)) return 0;
48   if(!ar->host) return -1;
49   if(!br->host) return 1;
50   return strcmp(ar->host, br->host);
51 }
52 int spreadd_compare_key(const void *a, const void *b) {
53   SpreadConfiguration *br = (SpreadConfiguration *)b;
54   int temp;
55   if((temp = strcmp(a, br->port))!=0)
56     return temp;
57   if((!a) && (!br->host)) return 0;
58   if(!a) return -1;
59   if(!br->host) return 1;
60   return strcmp(a, br->host);
61
62 int facility_compare(const void *a, const void *b) {
63   LogFacility *ar = (LogFacility *)a;
64   LogFacility *br = (LogFacility *)b;
65   return strcmp(ar->groupname, br->groupname);
66 }
67 int facility_compare_key(const void *a, const void *b) {
68   LogFacility *br = (LogFacility *)b;
69   return strcmp(a, br->groupname);
70 }
71 void config_cleanup() {
72 #ifdef PERL
73   perl_shutdown();
74 #endif
75 #ifdef PYTHON
76   python_shutdown();
77 #endif
78 }
79
80 int config_init(char *filename) {
81   int ret;
82   sl_init(&logfiles);
83   sl_set_compare(&logfiles, logfile_compare, logfile_compare_key);
84   sl_init(&spreaddaemons);
85   sl_set_compare(&spreaddaemons, spreadd_compare, spreadd_compare_key);
86   /*
87     sl_init(&logfacilities);
88     sl_set_compare(&logfacilities, facility_compare, facility_compare_key);
89   */
90 #ifdef PERL
91   perl_startup();
92 #endif
93 #ifdef PYTHON
94   python_startup();
95 #endif
96   sld_in = fopen(filename, "r");
97   if (!sld_in) {
98     fprintf(stderr, "Couldn't open input file: %s\n", filename);
99     return -1;
100   }
101   ret = sld_parse();
102   fclose(sld_in);
103   if(ret) return ret;
104   ret = module_load_finalize();
105   return ret;
106
107 char *config_get_spreaddaemon(SpreadConfiguration *sc) {
108   static char buffer[1024];
109   if(sc->host) {
110     snprintf(buffer, 1024, "%s@%s", sc->port, sc->host);
111   }
112   else {
113     strncpy(buffer, sc->port, 1024);
114   }
115   return buffer;
116 }
117
118 void config_set_spread_port(SpreadConfiguration *sc, char *newport) {
119   if(sc->port) free(sc->port);
120   sc->port = newport;
121 }
122 void config_set_spread_host(SpreadConfiguration *sc, char *newhost) {
123   if(sc->host) free(sc->host);
124   sc->host = newhost;
125 }
126 void config_add_spreadconf(SpreadConfiguration *sc) {
127   sl_insert(&spreaddaemons, sc);
128 }
129 SpreadConfiguration *config_new_spread_conf(void) {
130   SpreadConfiguration *newsc;
131   newsc = (SpreadConfiguration *)calloc(1, sizeof(SpreadConfiguration));
132   newsc->port=strdup("4803");
133   newsc->logfacilities = (Skiplist *)malloc(sizeof(Skiplist));
134   sl_init(newsc->logfacilities);
135   sl_set_compare(newsc->logfacilities,
136                  facility_compare, facility_compare_key); 
137   return newsc;
138
139 LogFacility *config_new_logfacility(void) {
140   LogFacility *newlf;
141   newlf = calloc(1, sizeof(LogFacility));
142   newlf->rewritetimes=NO_REWRITE_TIMES;
143   return newlf;
144 }
145 void config_add_logfacility(SpreadConfiguration *sc, LogFacility *lf) {
146   sl_insert(sc->logfacilities, lf);
147 }
148 void config_set_logfacility_group(LogFacility *lf, char *ng) {
149   if(lf->groupname) free(lf->groupname);
150   lf->groupname = ng;
151 }
152 void config_set_logfacility_external_module(LogFacility *lf, char *sym) {
153   sld_module_list_t *newhead;
154   newhead = calloc(1, sizeof(*newhead));
155   newhead->module_name = strdup(sym);
156   newhead->next = lf->modulelog;
157   lf->modulelog = newhead;
158 }
159 void config_set_logfacility_filename(LogFacility *lf, char *nf) {
160   LogFile *logf;
161   logf = sl_find(&logfiles, nf, NULL);
162   lf->logfile = logf;
163   if(!lf->logfile) {
164     logf = (LogFile *)malloc(sizeof(LogFile));
165     logf->filename = nf;
166     logf->fd = -1;
167     sl_insert(&logfiles, logf);
168     lf->logfile = logf;
169   }
170   else {
171     free(nf);
172   }
173 }
174 #ifdef PERL
175 void config_set_logfacility_external_perl(LogFacility *lf, char *pf) {
176   if(lf->perl_log_handler) free(lf->perl_log_handler);
177   lf->perl_log_handler = strdup(pf);
178 }
179
180 void config_set_hupfacility_external_perl(LogFacility *lf, char *pf) {
181   if(lf->perl_hup_handler) free(lf->perl_hup_handler);
182   lf->perl_hup_handler = strdup(pf);
183 }
184 #endif
185
186 #ifdef PYTHON
187 void config_set_logfacility_external_python(LogFacility *lf, char *pf) {
188   if(lf->python_handler) free(lf->python_handler);
189   lf->python_handler = strdup(pf);
190 }
191 #endif
192
193 void config_set_logfacility_vhostdir(LogFacility *lf, char *vhd) {
194   int i;
195   lf->vhostdir = vhd;
196   lf->hash = (hash_element *) malloc (FHASH_SIZE * sizeof(hash_element));
197   fprintf( stderr, "\nZeroing vhost hash for usage!\n");
198   for(i=0; i< FHASH_SIZE; i++) {
199     lf->hash[i].fd = -1;
200     lf->hash[i].hostheader = NULL;
201   }
202
203 }
204 void config_set_logfaclity_rewritetimes_clf(LogFacility *lf) {
205   lf->rewritetimes = REWRITE_TIMES_IN_CLF;
206 }
207 void config_set_logfaclity_rewritetimes_user(LogFacility *lf, char *format) {
208   lf->rewritetimes = REWRITE_TIMES_FORMAT;
209   if(lf->rewritetimesformat) {
210     free(lf->rewritetimesformat);
211   }
212   lf->rewritetimesformat = format;
213 }
214 void config_add_logfacility_match(LogFacility *lf, char *nm) {
215 #ifdef RE_SYNTAX_EGREP
216   const char *ret;
217 #else 
218   int ret;
219 #endif 
220   if(lf->nmatches>=10) {
221     fprintf(stderr, "Already 10 regex's on group\n");
222     return;
223   }
224 #if defined(RE_SYNTAX_EGREP)
225   re_set_syntax(RE_SYNTAX_EGREP);
226   if((ret = re_compile_pattern(nm, strlen(nm),
227                                &lf->match_expression[lf->nmatches]))!=0) {
228 #elif defined(REG_EXTENDED)
229 if((ret = regcomp(&lf->match_expression[lf->nmatches], nm, REG_EXTENDED))!=0) {
230 #elif defined(REG_EGREP)
231 if((ret = regcomp(&lf->match_expression[lf->nmatches], nm, REG_EGREP))!=0) {
232 #endif
233 #if defined(RE_SYNTAX_EGREP) || defined(REG_EXTENDED) || defined(REG_EGREP)
234       char errbuf[120];
235       regerror(ret, &lf->match_expression[lf->nmatches], errbuf, sizeof errbuf);
236       fprintf(stderr, errbuf);
237 #endif 
238   } else {
239     lf->nmatches++;
240   }
241 }
242
243 int config_foreach_spreadconf(int (*func)(SpreadConfiguration *, void *),
244                               void *closure) {
245   int i=0;
246   struct skiplistnode *iter;
247   SpreadConfiguration *sc;
248   iter = sl_getlist(&spreaddaemons);
249   if(!iter) return i;
250   sc = iter->data;
251   do {
252     if(func(sc, closure)==0) i++;
253   } while((sc = sl_next(&iter))!=NULL);
254   return i; 
255 }
256
257 int config_foreach_logfacility(SpreadConfiguration *sc,
258                                int (*func)(LogFacility *, void *),
259                                void *closure) {
260   int i=0;
261   struct skiplistnode *iter;
262   LogFacility *lf;
263   iter = sl_getlist(sc->logfacilities);
264   if(!iter) return i;
265   lf = iter->data;
266   do {
267     if(func(lf, closure)==0) i++;
268   } while((lf = sl_next(&iter))!=NULL);
269   return i; 
270 }
271
272 char *config_process_message(SpreadConfiguration *sc, char *group,
273                              char *message, int *len) {
274   LogFacility *lf;
275   char *cp;
276   lf = sl_find(sc->logfacilities, group, NULL);
277   if(lf->rewritetimes)
278     force_local_time(message, len, buffsize,
279                      lf->rewritetimes, lf->rewritetimesformat);
280   if(lf->vhostdir) {
281     cp=message;
282     while(*cp != ' ' && *cp) {
283         cp++;
284         --*len;
285     }
286     --*len;
287     return cp+1;
288   }
289   return message;
290 }   
291
292 void config_hup(void) {
293   config_close();
294   config_start();
295 #ifdef PERL
296 #endif
297
298
299 int config_close(void) {
300   struct skiplistnode *sciter, *lfiter;
301   SpreadConfiguration *sc;
302   LogFacility *lf;
303                                 int i;
304   sciter = sl_getlist(&spreaddaemons);
305   if(!sciter) return 0;
306   sc = (SpreadConfiguration *)sciter->data;
307   /* For each spread configuration: */
308   do {
309     lfiter = sl_getlist(sc->logfacilities);
310     if(!lfiter) return 0;
311     lf = (LogFacility *)lfiter->data;
312     /* For each log facility in that spread configuration: */
313     do {
314       if(lf->vhostdir) {
315         for (i=0;i< FHASH_SIZE;i++) {
316           if(lf->hash[i].fd>0) {
317             if(!skiplocking) flock(lf->hash[i].fd, LOCK_UN);
318             close(lf->hash[i].fd);
319             lf->hash[i].fd = -1;
320           }
321         }
322       } else if(lf->logfile && lf->logfile->fd>0) {
323         if(!skiplocking) flock(lf->logfile->fd, LOCK_UN);
324         close(lf->logfile->fd);
325         lf->logfile->fd = -1;
326       }
327     } while((lf = sl_next(&lfiter))!=NULL);
328   } while((sc = sl_next(&sciter))!=NULL);
329   return 0;
330
331
332 int open_pipe_log(char *filename)
333 {
334         int pid, pfd[2];
335
336         if (pipe(pfd) < 0)
337                 return -1;
338         if ((pid = fork()) < 0)
339                 return -1;
340         else if (pid == 0) {
341                 close(pfd[1]);
342                 dup2(pfd[0], STDIN_FILENO);
343                 close(pfd[0]);
344                 signal(SIGCHLD, SIG_DFL);
345                 signal(SIGHUP, SIG_IGN);
346                 filename++; /* skip past leading '|' */
347                 execl(SHELL_PATH, SHELL_PATH, "-c", filename, (char *) 0);
348         }
349         else {
350                 close(pfd[0]);
351                 return pfd[1];
352         }
353         return -1;
354 }
355 int config_start(void) {
356   struct skiplistnode *sciter, *lfiter;
357   SpreadConfiguration *sc;
358   LogFacility *lf;
359   sciter = sl_getlist(&spreaddaemons);
360   if(!sciter) return 0;
361   sc = (SpreadConfiguration *)sciter->data;
362   /* For each spread configuration: */
363   do {
364     lfiter = sl_getlist(sc->logfacilities);
365     if(!lfiter) return 0;
366     lf = (LogFacility *)lfiter->data;
367     /* For each log facility in that spread configuration: */
368     do {
369 #ifdef PERL
370       if(lf->perl_hup_handler) perl_hup(lf->perl_hup_handler);
371 #endif
372       if(!lf->logfile || !lf->logfile->filename || lf->vhostdir) continue;
373       else if(lf->logfile->fd<0) {
374                         if(lf->logfile->filename[0] == '|') {
375                                 lf->logfile->fd = open_pipe_log(lf->logfile->filename);
376                         }
377                         else {
378                         lf->logfile->fd = open(lf->logfile->filename,
379                                O_CREAT|O_APPEND|O_WRONLY,
380                                00644);
381                         }
382                 }       
383       if(!skiplocking) {
384         if(flock(lf->logfile->fd, LOCK_NB|LOCK_EX)==-1) {
385           fprintf(stderr, "Cannot lock %s, is another spreadlogd running?\n",
386                   lf->logfile->filename);
387           exit(1);
388         }
389       }
390       if(verbose) {
391         fprintf(stderr, "LogFacility: %s\n\tFile: %s\n\tFD: %d\n\t%d regexs\n",
392                 lf->groupname, lf->logfile->filename,
393                 lf->logfile->fd, lf->nmatches);
394       }
395     } while((lf = sl_next(&lfiter))!=NULL);
396   } while((sc = sl_next(&sciter))!=NULL);
397   return 0;
398
399
400 int config_do_external_module(SpreadConfiguration *sc, char *sender, char *group, char *message) {
401   LogFacility *lf;
402   sld_module_list_t *node;
403   lf = sl_find(sc->logfacilities, group, NULL);
404   if(!lf || !lf->modulelog) return -1;
405   for(node=lf->modulelog; node; node=node->next) {
406     if(!node->module) node->module = module_get(node->module_name);
407     if(node->module) node->module->logline(sc, sender, group, message);
408   }
409   return 0;
410 }
411
412 #ifdef PERL
413 int config_do_external_perl(SpreadConfiguration *sc, char *sender, char *group, char *message) {
414   LogFacility *lf;
415   lf = sl_find(sc->logfacilities, group, NULL);
416   if(!lf || !lf->perl_log_handler) return -1;
417   if(lf->vhostdir) {
418     return perl_log(lf->perl_log_handler, sender, group, message);
419   } else {
420     return perl_log(lf->perl_log_handler, sender, group, message);
421   }
422   return -1;
423 }
424 #endif
425 #ifdef PYTHON
426 int config_do_external_python(SpreadConfiguration *sc, char *sender, char *group, char *message) {
427   LogFacility *lf;
428   lf = sl_find(sc->logfacilities, group, NULL);
429   if(!lf || !lf->python_handler) return -1;
430   if(lf->vhostdir) {
431     return python_log(lf->python_handler, sender, group, message);
432   } else {
433     return python_log(lf->python_handler, sender, group, message);
434   }
435   return -1;
436 }
437 #endif
438 int config_get_fd(SpreadConfiguration *sc, char *group, char *message) {
439   LogFacility *lf;
440   int i, slen, fd;
441   hash_element temp;
442   char *cp;
443   char fullpath[MAXPATHLEN];
444   lf = sl_find(sc->logfacilities, group, NULL);
445   if(!lf || !lf->logfile || !lf->logfile->filename) return -1;
446   if(lf->vhostdir) {
447     cp = message;
448     while(*cp != ' ' && *cp){
449       cp++;
450     }
451     *cp = '\0';
452     if((fd = gethash(message, lf->hash)) < 0) {
453       temp.hostheader = strdup(message);
454       *cp = ' ';
455       snprintf(fullpath, MAXPATHLEN, "%s/%s", lf->vhostdir,temp.hostheader);
456       temp.fd = open(fullpath,
457                      O_CREAT|O_APPEND|O_WRONLY,
458                      00644);
459       if(!skiplocking) {
460         if(flock(temp.fd, LOCK_NB|LOCK_EX)==-1) {
461           fprintf(stderr, "Cannot lock %s, is another spreadlogd running?\n",
462                   fullpath);
463           exit(1);
464         }
465       }
466       inshash(temp,lf->hash);
467       return temp.fd;
468     }                                           
469     *cp = ' ';
470     return fd;
471   }     
472   if(!lf->nmatches) return lf->logfile->fd;
473   slen = strlen(message);
474   for(i=0; i<lf->nmatches; i++) {
475 #ifdef RE_SYNTAX_EGREP
476     int ret;
477     if((ret = re_search(&lf->match_expression[i],
478                         message, slen, 0, slen, NULL)) >= 0)
479       return lf->logfile->fd;
480     else if(ret==-2 && verbose)
481       fprintf(stderr, "Internal error in re_search.\n");
482     else if(ret==-1 && verbose)
483       fprintf(stderr, "Failed match!\n");
484 #else
485   if(!regexec(&lf->match_expression[i], message, 0, NULL, 0))
486     return lf->logfile->fd;
487 #endif 
488   }
489   return -1;
490
491
Note: See TracBrowser for help on using the browser.