root/tags/v_1_5_0/config.c

Revision 30, 12.7 kB (checked in by jesus, 11 years ago)

PERL/PYTHON ifdefs

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