root/trunk/config.c

Revision 14, 11.1 kB (checked in by george, 13 years ago)

Added piped log support.

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