diff src/wflogs-config.cpp @ 2:400b1de6e1c6

allow multiple config contexts
author Carl Byington <carl@five-ten-sg.com>
date Fri, 17 May 2013 10:32:12 -0700
parents 0aa1171aebd2
children 37eace15ef87
line wrap: on
line diff
--- a/src/wflogs-config.cpp	Wed May 15 13:31:12 2013 -0700
+++ b/src/wflogs-config.cpp	Fri May 17 10:32:12 2013 -0700
@@ -1,6 +1,6 @@
 /*
 
-Copyright (c) 2007 Carl Byington - 510 Software Group, released under
+Copyright (c) 2013 Carl Byington - 510 Software Group, released under
 the GPL version 3 or any later version at your choice available at
 http://www.gnu.org/licenses/gpl-3.0.txt
 
@@ -34,13 +34,11 @@
 
 ////////////////////////////////////////////////
 //
-CONFIG::CONFIG() {
-    reference_count    = 0;
+CONTEXT::CONTEXT(const char *nam) {
+    name               = nam;
     fd                 = -1;
     len                = 0;
     fdo                = -1;
-    generation         = 0;
-    load_time          = 0;
     period             = 120;
     versions           = 3;
     output             = NULL;
@@ -51,25 +49,25 @@
 }
 
 
-CONFIG::~CONFIG() {
+CONTEXT::~CONTEXT() {
+    free_all();
 }
 
 
-void CONFIG::sleep(int duration, time_t &previous) {
-    ::sleep(duration);
-    time_t now = time(NULL);
-    previous = now;
+void CONTEXT::dump() {
+    printf("context %s {\n", name);
+    printf("    period   %d; \n", period);
+    printf("    versions %d; \n", versions);
+    printf("    output   \"%s\";\n", output);
+    printf("    tempin   \"%s\";\n", tempin);
+    printf("    wflogs   \"%s\";\n", wflogs);
+    printf("    file     \"%s\";\n", fn);
+    printf("    pattern  \"%s\";\n", pattern);
+    printf("};\n\n");
 }
 
 
-void CONFIG::free_all() {
-    regfree(&re);
-    close();
-    closeo();
-}
-
-
-void CONFIG::openo(bool msg) {
+void CONTEXT::openo(bool msg) {
     open_time = time(NULL);
     fdo = ::creat(tempin, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
     if (fdo == -1) {
@@ -82,7 +80,7 @@
 }
 
 
-void CONFIG::open(bool msg) {
+void CONTEXT::open(bool msg) {
     fd        = ::open(fn, O_RDONLY);
     len       = 0;
     if (fd == -1) {
@@ -103,8 +101,8 @@
             snprintf(buf, sizeof(buf), "syslog file %s cannot stat after open", fn);
             tokp->token_error(buf);
         }
-        // specify that this fd gets closed on exec, so that selinux
-        // won't complain about iptables trying to read log files.
+        // specify that this fd gets closed on exec, so that wflogs
+        // won't have access to it.
         int oldflags = fcntl(fd, F_GETFD, 0);
         if (oldflags >= 0) {
             fcntl(fd, F_SETFD, oldflags | FD_CLOEXEC);
@@ -113,7 +111,7 @@
 }
 
 
-bool CONFIG::write(char *p) {
+bool CONTEXT::write(char *p) {
     // p points to \0 at end of buf, may be destroyed
     if (failedo()) {
         openo(false);
@@ -124,7 +122,7 @@
 }
 
 
-bool CONFIG::read() {
+bool CONTEXT::read() {
     if (failed()) {
         open(false);
         if (failed()) return false;
@@ -164,13 +162,13 @@
 }
 
 
-void CONFIG::closeo() {
+void CONTEXT::closeo() {
     if (fdo != -1) ::close(fdo);
     fdo = -1;
 }
 
 
-void CONFIG::close() {
+void CONTEXT::close() {
     if (debug_syslog > 1) {
         snprintf(buf, sizeof(buf), "syslog file %s closed", fn);
         my_syslog(buf);
@@ -180,7 +178,7 @@
 }
 
 
-void CONFIG::process(char *p) {
+void CONTEXT::process(char *p) {
     // p points to \0 at end of buf, may be destroyed
     if (pattern) {
         if (0 == regexec(&re, buf, 0, NULL, 0)) {
@@ -193,7 +191,7 @@
 }
 
 
-void CONFIG::check_wflog() {
+void CONTEXT::check_wflog() {
     time_t now = time(NULL);
     if ((fdo != -1) && (open_time + period < now)) {
         closeo();
@@ -216,19 +214,58 @@
 }
 
 
+void CONTEXT::free_all() {
+    regfree(&re);
+    close();
+    closeo();
+}
+
+
+////////////////////////////////////////////////
+//
+CONFIG::CONFIG() {
+    reference_count    = 0;
+    generation         = 0;
+    load_time          = 0;
+}
+
+
+CONFIG::~CONFIG() {
+    for (context_list::iterator i=contexts.begin(); i!=contexts.end(); i++) {
+        CONTEXT *c = *i;
+        delete c;
+    }
+}
+
+
 void CONFIG::dump() {
-    int level = 0;
-    char indent[maxlen];
-    int i = min(maxlen-1, level*4);
-    memset(indent, ' ', i);
-    indent[i] = '\0';
-    printf("%s period   %d; \n", indent, period);
-    printf("%s versions %d; \n", indent, versions);
-    printf("%s output   \"%s\";\n", indent, output);
-    printf("%s tempin   \"%s\";\n", indent, tempin);
-    printf("%s wflogs   \"%s\";\n", indent, wflogs);
-    printf("%s file     \"%s\";\n", indent, fn);
-    printf("%s pattern  \"%s\";\n", indent, pattern);
+    for (context_list::iterator i=contexts.begin(); i!=contexts.end(); i++) {
+        CONTEXTP c = *i;
+        c->dump();
+    }
+}
+
+
+bool CONFIG::read() {
+    bool rc = false;
+    for (context_list::iterator i=contexts.begin(); i!=contexts.end(); i++) {
+        CONTEXT *c = *i;
+        rc |= c->read();
+    }
+}
+
+void CONFIG::sleep(int duration, time_t &previous) {
+    ::sleep(duration);
+    time_t now = time(NULL);
+    previous = now;
+}
+
+
+void CONFIG::free_all() {
+    for (context_list::iterator i=contexts.begin(); i!=contexts.end(); i++) {
+        CONTEXT *c = *i;
+        c->free_all();
+    }
 }
 
 
@@ -283,67 +320,102 @@
 
 
 ////////////////////////////////////////////////
-// parse a config file
 //
-bool load_conf(CONFIG &dc, const char *fn) {
-    TOKEN tok(fn, &dc.config_files);
-    dc.set_token(tok);
+bool parse_context(TOKEN &tok, CONFIG &dc, CONTEXTP parent);
+bool parse_context(TOKEN &tok, CONFIG &dc, CONTEXTP parent) {
+    const char *name = tok.next();
+    if (!tsa(tok, token_lbrace)) return false;
+    CONTEXTP con = new CONTEXT(name);
+    con->set_token(tok);
     while (true) {
         const char *have = tok.next();
         if (!have) break;
+        if (have == token_rbrace) break;  // done
         if (have == token_period) {
             have = tok.next();
-            dc.set_period(atoi(have));
+            con->set_period(atoi(have));
             if (!tsa(tok, token_semi)) return false;
         }
         else if (have == token_versions) {
             have = tok.next();
-            dc.set_versions(atoi(have));
+            con->set_versions(atoi(have));
             if (!tsa(tok, token_semi)) return false;
         }
         else if (have == token_output) {
-            dc.set_output(tok.next());
+            con->set_output(tok.next());
             if (!tsa(tok, token_semi)) return false;
         }
         else if (have == token_tempin) {
-            dc.set_tempin(tok.next());
+            con->set_tempin(tok.next());
             if (!tsa(tok, token_semi)) return false;
         }
         else if (have == token_wflogs) {
-            dc.set_wflogs(tok.next());
+            con->set_wflogs(tok.next());
             if (!tsa(tok, token_semi)) return false;
         }
         else if (have == token_file) {
-            dc.set_file(tok.next());
+            con->set_file(tok.next());
             if (!tsa(tok, token_semi)) return false;
         }
         else if (have == token_pattern) {
-            dc.pattern = tok.next();
-            int rc = regcomp(&dc.re, dc.pattern, REG_ICASE | REG_EXTENDED);
+            con->pattern = tok.next();
+            int rc = regcomp(&con->re, con->pattern, REG_ICASE | REG_EXTENDED);
             if (rc) {
                 char bu[maxlen];
-                regerror(rc, &dc.re, bu, maxlen);
+                regerror(rc, &con->re, bu, maxlen);
                 char buf[maxlen];
-                snprintf(buf, sizeof(buf), "pattern %s not valid - %s", dc.pattern, bu);
+                snprintf(buf, sizeof(buf), "pattern %s not valid - %s", con->pattern, bu);
                 tok.token_error(buf);
-                dc.pattern = NULL;
+                con->pattern = NULL;
             }
 
             if (!tsa(tok, token_semi)) return false;
         }
         else {
-            tok.token_error("statement", have);
+            tok.token_error("period/versions/output/tempin/wflogs/file/pattern", have);
             return false;
         }
     }
+    if (!tsa(tok, token_semi)) {
+        delete con;
+        return false;
+    }
+    dc.add_context(con);
     return true;
 }
 
 
 ////////////////////////////////////////////////
+// parse a config file
+//
+bool load_conf(CONFIG &dc, const char *fn) {
+    int count = 0;
+    TOKEN tok(fn, &dc.config_files);
+    while (true) {
+        const char *have = tok.next();
+        if (!have) break;
+        if (have == token_context) {
+            if (!parse_context(tok, dc, NULL)) {
+                tok.token_error("load_conf() failed to parse context");
+                return false;
+            }
+            else count++;
+        }
+        else {
+            tok.token_error(token_context, have);
+            return false;
+        }
+    }
+    tok.token_error("load_conf() found %d contexts in %s", count, fn);
+    return (!dc.contexts.empty());
+}
+
+
+////////////////////////////////////////////////
 // init the tokens
 //
 void token_init() {
+    token_context    = register_string("context");
     token_file       = register_string("file");
     token_include    = register_string("include");
     token_lbrace     = register_string("{");