root/trunk/config.c

Revision 51, 14.0 kB (checked in by jesus, 6 years ago)

make this work on Solaris

  • 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 #ifndef LOCK_UN
305   struct flock fl;
306   fl.l_type = F_UNLCK;
307   fl.l_whence = SEEK_SET;
308   fl.l_start = 0;
309   fl.l_len = 0;
310 #endif
311
312   sciter = sl_getlist(&spreaddaemons);
313   if(!sciter) return 0;
314   sc = (SpreadConfiguration *)sciter->data;
315   /* For each spread configuration: */
316   do {
317     lfiter = sl_getlist(sc->logfacilities);
318     if(!lfiter) return 0;
319     lf = (LogFacility *)lfiter->data;
320     /* For each log facility in that spread configuration: */
321     do {
322       if(lf->vhostdir) {
323         for (i=0;i< FHASH_SIZE;i++) {
324           if(lf->hash[i].fd>0) {
325             if(!skiplocking)
326 #ifdef LOCK_UN
327               flock(lf->hash[i].fd, LOCK_UN);
328 #else
329               fcntl(lf->hash[i].fd, F_SETLKW, &fl);
330 #endif
331             close(lf->hash[i].fd);
332             lf->hash[i].fd = -1;
333           }
334         }
335       } else if(lf->logfile && lf->logfile->fd>0) {
336         if(!skiplocking)
337 #ifdef LOCK_UN
338           flock(lf->logfile->fd, LOCK_UN);
339 #else
340           fcntl(lf->logfile->fd, F_SETLKW, &fl);
341 #endif
342         close(lf->logfile->fd);
343         lf->logfile->fd = -1;
344       }
345     } while((lf = sl_next(&lfiter))!=NULL);
346   } while((sc = sl_next(&sciter))!=NULL);
347   return 0;
348
349
350 int open_pipe_log(char *filename)
351 {
352         int pid, pfd[2];
353
354         if (pipe(pfd) < 0)
355                 return -1;
356         if ((pid = fork()) < 0)
357                 return -1;
358         else if (pid == 0) {
359                 close(pfd[1]);
360                 dup2(pfd[0], STDIN_FILENO);
361                 close(pfd[0]);
362                 signal(SIGCHLD, SIG_DFL);
363                 signal(SIGHUP, SIG_IGN);
364                 filename++; /* skip past leading '|' */
365                 execl(SHELL_PATH, SHELL_PATH, "-c", filename, (char *) 0);
366         }
367         else {
368                 close(pfd[0]);
369                 return pfd[1];
370         }
371         return -1;
372 }
373 int config_start(void) {
374   struct skiplistnode *sciter, *lfiter;
375   SpreadConfiguration *sc;
376   LogFacility *lf;
377 #ifndef LOCK_UN
378   struct flock fl;
379   fl.l_type = F_WRLCK;
380   fl.l_whence = SEEK_SET;
381   fl.l_start = 0;
382   fl.l_len = 0;
383 #endif
384
385   sciter = sl_getlist(&spreaddaemons);
386   if(!sciter) return 0;
387   sc = (SpreadConfiguration *)sciter->data;
388   /* For each spread configuration: */
389   do {
390     lfiter = sl_getlist(sc->logfacilities);
391     if(!lfiter) return 0;
392     lf = (LogFacility *)lfiter->data;
393     /* For each log facility in that spread configuration: */
394     do {
395 #ifdef PERL
396       if(lf->perl_hup_handler) perl_hup(lf->perl_hup_handler);
397 #endif
398       if(!lf->logfile || !lf->logfile->filename || lf->vhostdir) continue;
399       else if(lf->logfile->fd<0) {
400                         if(lf->logfile->filename[0] == '|') {
401                                 lf->logfile->fd = open_pipe_log(lf->logfile->filename);
402                         }
403                         else {
404                         lf->logfile->fd = open(lf->logfile->filename,
405                                O_CREAT|O_APPEND|O_WRONLY,
406                                00644);
407                         }
408                 }       
409       if(!skiplocking) {
410         if(
411 #ifdef LOCK_UN
412            flock(lf->logfile->fd, LOCK_NB|LOCK_EX)
413 #else
414            fcntl(lf->logfile->fd, F_SETLK, &fl)
415 #endif
416            == -1) {
417           fprintf(stderr, "Cannot lock %s, is another spreadlogd running?\n",
418                   lf->logfile->filename);
419           exit(1);
420         }
421       }
422       if(verbose) {
423         fprintf(stderr, "LogFacility: %s\n\tFile: %s\n\tFD: %d\n\t%d regexs\n",
424                 lf->groupname, lf->logfile->filename,
425                 lf->logfile->fd, lf->nmatches);
426       }
427     } while((lf = sl_next(&lfiter))!=NULL);
428   } while((sc = sl_next(&sciter))!=NULL);
429   return 0;
430
431
432 int config_do_external_module(SpreadConfiguration *sc, char *sender, char *group, char *message) {
433   LogFacility *lf;
434   sld_module_list_t *node;
435   lf = sl_find(sc->logfacilities, group, NULL);
436   if(!lf || !lf->modulelog) return -1;
437   for(node=lf->modulelog; node; node=node->next) {
438     if(!node->module) node->module = module_get(node->module_name);
439     if(node->module) node->module->logline(sc, sender, group, message);
440   }
441   return 0;
442 }
443
444 #ifdef PERL
445 int config_do_external_perl(SpreadConfiguration *sc, char *sender, char *group, char *message) {
446   LogFacility *lf;
447   lf = sl_find(sc->logfacilities, group, NULL);
448   if(!lf || !lf->perl_log_handler) return -1;
449   if(lf->vhostdir) {
450     return perl_log(lf->perl_log_handler, sender, group, message);
451   } else {
452     return perl_log(lf->perl_log_handler, sender, group, message);
453   }
454   return -1;
455 }
456 #endif
457 #ifdef PYTHON
458 int config_do_external_python(SpreadConfiguration *sc, char *sender, char *group, char *message) {
459   LogFacility *lf;
460   lf = sl_find(sc->logfacilities, group, NULL);
461   if(!lf || !lf->python_handler) return -1;
462   if(lf->vhostdir) {
463     return python_log(lf->python_handler, sender, group, message);
464   } else {
465     return python_log(lf->python_handler, sender, group, message);
466   }
467   return -1;
468 }
469 #endif
470 int config_get_fd(SpreadConfiguration *sc, char *group, char *message) {
471   LogFacility *lf;
472   int i, slen, fd;
473   hash_element temp;
474   char *cp;
475   char fullpath[MAXPATHLEN];
476 #ifndef LOCK_UN
477   struct flock fl;
478   fl.l_type = F_WRLCK;
479   fl.l_whence = SEEK_SET;
480   fl.l_start = 0;
481   fl.l_len = 0;
482 #endif
483
484   lf = sl_find(sc->logfacilities, group, NULL);
485   if(!lf || !lf->logfile || !lf->logfile->filename) return -1;
486   if(lf->vhostdir) {
487     cp = message;
488     while(*cp != ' ' && *cp){
489       cp++;
490     }
491     *cp = '\0';
492     if((fd = gethash(message, lf->hash)) < 0) {
493       temp.hostheader = strdup(message);
494       *cp = ' ';
495       snprintf(fullpath, MAXPATHLEN, "%s/%s", lf->vhostdir,temp.hostheader);
496       temp.fd = open(fullpath,
497                      O_CREAT|O_APPEND|O_WRONLY,
498                      00644);
499       if(!skiplocking) {
500         if(
501 #ifdef LOCK_UN
502            flock(temp.fd, LOCK_NB|LOCK_EX)
503 #else
504            fcntl(temp.fd, F_SETLK, &fl)
505 #endif
506            == -1) {
507           fprintf(stderr, "Cannot lock %s, is another spreadlogd running?\n",
508                   fullpath);
509           exit(1);
510         }
511       }
512       inshash(temp,lf->hash);
513       return temp.fd;
514     }                                           
515     *cp = ' ';
516     return fd;
517   }     
518   if(!lf->nmatches) return lf->logfile->fd;
519   slen = strlen(message);
520   for(i=0; i<lf->nmatches; i++) {
521 #ifdef RE_SYNTAX_EGREP
522     int ret;
523     if((ret = re_search(&lf->match_expression[i],
524                         message, slen, 0, slen, NULL)) >= 0)
525       return lf->logfile->fd;
526     else if(ret==-2 && verbose)
527       fprintf(stderr, "Internal error in re_search.\n");
528     else if(ret==-1 && verbose)
529       fprintf(stderr, "Failed match!\n");
530 #else
531   if(!regexec(&lf->match_expression[i], message, 0, NULL, 0))
532     return lf->logfile->fd;
533 #endif 
534   }
535   return -1;
536
537
Note: See TracBrowser for help on using the browser.