]> git.ipfire.org Git - thirdparty/squid.git/blobdiff - src/cache_cf.cc
Merged from parent (trunk r10600).
[thirdparty/squid.git] / src / cache_cf.cc
index 113c5df4c2f5cc4628cbd1a4a3cc3db6635b36d1..88199d85f687342a5d45682f1ec122d33ebdd5dd 100644 (file)
@@ -70,6 +70,7 @@
 #include "StoreFileSystem.h"
 #include "SwapDir.h"
 #include "wordlist.h"
+#include "ipc/Kids.h"
 
 #if HAVE_GLOB_H
 #include <glob.h>
@@ -263,6 +264,110 @@ parseManyConfigFiles(char* files, int depth)
     return error_count;
 }
 
+static void
+ReplaceSubstr(char*& str, int& len, unsigned substrIdx, unsigned substrLen, const char* newSubstr)
+{
+    assert(str != NULL);
+    assert(newSubstr != NULL);
+
+    unsigned newSubstrLen = strlen(newSubstr);
+    if (newSubstrLen > substrLen)
+        str = (char*)realloc(str, len - substrLen + newSubstrLen + 1);
+
+    // move tail part including zero
+    memmove(str + substrIdx + newSubstrLen, str + substrIdx + substrLen, len - substrIdx - substrLen + 1);
+    // copy new substring in place
+    memcpy(str + substrIdx, newSubstr, newSubstrLen);
+
+    len = strlen(str);
+}
+
+static void
+SubstituteMacro(char*& line, int& len, const char* macroName, const char* substStr)
+{
+    assert(line != NULL);
+    assert(macroName != NULL);
+    assert(substStr != NULL);
+    unsigned macroNameLen = strlen(macroName);
+    while (const char* macroPos = strstr(line, macroName)) // we would replace all occurrences
+        ReplaceSubstr(line, len, macroPos - line, macroNameLen, substStr);
+}
+
+static void
+ProcessMacros(char*& line, int& len)
+{
+    SubstituteMacro(line, len, "${process_name}", KidName);
+    SubstituteMacro(line, len, "${process_number}", xitoa(KidIdentifier));
+}
+
+static void
+trim_trailing_ws(char* str)
+{
+    assert(str != NULL);
+    unsigned i = strlen(str);
+    while ((i > 0) && xisspace(str[i - 1]))
+        --i;
+    str[i] = '\0';
+}
+
+static const char*
+FindStatement(const char* line, const char* statement)
+{
+    assert(line != NULL);
+    assert(statement != NULL);
+
+    const char* str = skip_ws(line);
+    unsigned len = strlen(statement);
+    if (strncmp(str, statement, len) == 0) {
+        str += len;
+        if (*str == '\0')
+            return str;
+        else if (xisspace(*str))
+            return skip_ws(str);
+    }
+
+    return NULL;
+}
+
+static bool
+StrToInt(const char* str, long& number)
+{
+    assert(str != NULL);
+
+    char* end;
+    number = strtol(str, &end, 0);
+
+    return (end != str) && (*end == '\0'); // returns true if string contains nothing except number
+}
+
+static bool
+EvalBoolExpr(const char* expr)
+{
+    assert(expr != NULL);
+    if (strcmp(expr, "true") == 0) {
+        return true;
+    } else if (strcmp(expr, "false") == 0) {
+        return false;
+    } else if (const char* equation = strchr(expr, '=')) {
+        const char* rvalue = skip_ws(equation + 1);
+        char* lvalue = (char*)xmalloc(equation - expr + 1);
+        xstrncpy(lvalue, expr, equation - expr + 1);
+        trim_trailing_ws(lvalue);
+
+        long number1;
+        if (!StrToInt(lvalue, number1))
+            fatalf("String is not a integer number: '%s'\n", lvalue);
+        long number2;
+        if (!StrToInt(rvalue, number2))
+            fatalf("String is not a integer number: '%s'\n", rvalue);
+
+        xfree(lvalue);
+        return number1 == number2;
+    }
+    fatalf("Unable to evaluate expression '%s'\n", expr);
+    return false; // this place cannot be reached
+}
+
 static int
 parseOneConfigFile(const char *file_name, unsigned int depth)
 {
@@ -303,6 +408,7 @@ parseOneConfigFile(const char *file_name, unsigned int depth)
 
     config_lineno = 0;
 
+    Vector<bool> if_states;
     while (fgets(config_input_line, BUFSIZ, fp)) {
         config_lineno++;
 
@@ -362,20 +468,38 @@ parseOneConfigFile(const char *file_name, unsigned int depth)
             continue;
         }
 
+        trim_trailing_ws(tmp_line);
+        ProcessMacros(tmp_line, tmp_line_len);
         debugs(3, 5, "Processing: '" << tmp_line << "'");
 
-        /* Handle includes here */
-        if (tmp_line_len >= 9 && strncmp(tmp_line, "include", 7) == 0 && xisspace(tmp_line[7])) {
-            err_count += parseManyConfigFiles(tmp_line + 8, depth + 1);
-        } else if (!parse_line(tmp_line)) {
-            debugs(3, 0, HERE << cfg_filename << ":" << config_lineno << " unrecognized: '" << tmp_line << "'");
-            err_count++;
+        if (const char* expr = FindStatement(tmp_line, "if")) {
+            if_states.push_back(EvalBoolExpr(expr)); // store last if-statement meaning
+        } else if (FindStatement(tmp_line, "endif")) {
+            if (!if_states.empty())
+                if_states.pop_back(); // remove last if-statement meaning
+            else
+                fatalf("'endif' without 'if'\n");
+        } else if (FindStatement(tmp_line, "else")) {
+            if (!if_states.empty())
+                if_states.back() = !if_states.back();
+            else
+                fatalf("'else' without 'if'\n");
+        } else if (if_states.empty() || if_states.back()) { // test last if-statement meaning if present
+            /* Handle includes here */
+            if (tmp_line_len >= 9 && strncmp(tmp_line, "include", 7) == 0 && xisspace(tmp_line[7])) {
+                err_count += parseManyConfigFiles(tmp_line + 8, depth + 1);
+            } else if (!parse_line(tmp_line)) {
+                debugs(3, 0, HERE << cfg_filename << ":" << config_lineno << " unrecognized: '" << tmp_line << "'");
+                err_count++;
+            }
         }
 
         safe_free(tmp_line);
         tmp_line_len = 0;
 
     }
+    if (!if_states.empty())
+        fatalf("if-statement without 'endif'\n");
 
     if (is_pipe) {
         int ret = pclose(fp);