root/trunk/config.c

Revision 24, 12.6 kB (checked in by george, 11 years ago)

added python interpreter

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