+// Configuration::Exists - Returns true if the Name exists /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+bool Configuration::Exists(const char *Name)
+{
+ Item *Itm = Lookup(Name,false);
+ if (Itm == 0)
+ return false;
+ return true;
+}
+ /*}}}*/
+// Configuration::Dump - Dump the config /*{{{*/
+// ---------------------------------------------------------------------
+/* Dump the entire configuration space */
+void Configuration::Dump()
+{
+ /* Write out all of the configuration directives by walking the
+ configuration tree */
+ const Configuration::Item *Top = _config->Tree(0);
+ for (; Top != 0;)
+ {
+ clog << Top->FullTag() << " \"" << Top->Value << "\";" << endl;
+
+ if (Top->Child != 0)
+ {
+ Top = Top->Child;
+ continue;
+ }
+
+ while (Top != 0 && Top->Next == 0)
+ Top = Top->Parent;
+ if (Top != 0)
+ Top = Top->Next;
+ }
+}
+ /*}}}*/
+
+// Configuration::Item::FullTag - Return the fully scoped tag /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+string Configuration::Item::FullTag() const
+{
+ if (Parent == 0 || Parent->Parent == 0)
+ return Tag;
+ return Parent->FullTag() + "::" + Tag;
+}
+ /*}}}*/
+
+// ReadConfigFile - Read a configuration file /*{{{*/
+// ---------------------------------------------------------------------
+/* The configuration format is very much like the named.conf format
+ used in bind8, in fact this routine can parse most named.conf files. */
+bool ReadConfigFile(Configuration &Conf,string FName)
+{
+ // Open the stream for reading
+ ifstream F(FName.c_str(),ios::in | ios::nocreate);
+ if (!F != 0)
+ return _error->Errno("ifstream::ifstream","Opening configuration file %s",FName.c_str());
+
+ char Buffer[300];
+ string LineBuffer;
+
+ // Parser state
+ string ParentTag;
+
+ int CurLine = 0;
+ bool InComment = false;
+ while (F.eof() == false)
+ {
+ F.getline(Buffer,sizeof(Buffer));
+ CurLine++;
+ _strtabexpand(Buffer,sizeof(Buffer));
+ _strstrip(Buffer);
+
+ // Multi line comment
+ if (InComment == true)
+ {
+ for (const char *I = Buffer; *I != 0; I++)
+ {
+ if (*I == '*' && I[1] == '/')
+ {
+ memmove(Buffer,I+2,strlen(I+2) + 1);
+ InComment = false;
+ break;
+ }
+ }
+ if (InComment == true)
+ continue;
+ }
+
+ // Discard single line comments
+ for (char *I = Buffer; *I != 0; I++)
+ {
+ if (*I == '/' && I[1] == '/')
+ {
+ *I = 0;
+ break;
+ }
+ }
+
+ // Look for multi line comments
+ for (char *I = Buffer; *I != 0; I++)
+ {
+ if (*I == '/' && I[1] == '*')
+ {
+ InComment = true;
+ for (char *J = Buffer; *J != 0; J++)
+ {
+ if (*J == '*' && J[1] == '/')
+ {
+ memmove(I,J+2,strlen(J+2) + 1);
+ InComment = false;
+ break;
+ }
+ }
+
+ if (InComment == true)
+ {
+ *I = 0;
+ break;
+ }
+ }
+ }
+
+ // Blank
+ if (Buffer[0] == 0)
+ continue;
+
+ // We now have a valid line fragment
+ for (char *I = Buffer; *I != 0;)
+ {
+ if (*I == '{' || *I == ';' || *I == '}')
+ {
+ // Put the last fragement into the buffer
+ char *Start = Buffer;
+ char *Stop = I;
+ for (; Start != I && isspace(*Start) != 0; Start++);
+ for (; Stop != Start && isspace(Stop[-1]) != 0; Stop--);
+ if (LineBuffer.empty() == false && Stop - Start != 0)
+ LineBuffer += ' ';
+ LineBuffer += string(Start,Stop - Start);
+
+ // Remove the fragment
+ char TermChar = *I;
+ memmove(Buffer,I + 1,strlen(I + 1) + 1);
+ I = Buffer;
+
+ // Move up a tag
+ if (TermChar == '}')
+ {
+ string::size_type Pos = ParentTag.rfind("::");
+ if (Pos == string::npos)
+ ParentTag = string();
+ else
+ ParentTag = string(ParentTag,0,Pos);
+ }
+
+ // Syntax Error
+ if (TermChar == '{' && LineBuffer.empty() == true)
+ return _error->Error("Syntax error %s:%u: Block starts with no name.",FName.c_str(),CurLine);
+
+ if (LineBuffer.empty() == true)
+ continue;
+
+ // Parse off the tag
+ string::size_type Pos = LineBuffer.find(' ');
+ if (Pos == string::npos)
+ {
+ if (TermChar == '{')
+ Pos = LineBuffer.length();
+ else
+ return _error->Error("Syntax error %s:%u: Tag with no value",FName.c_str(),CurLine);
+ }
+
+ string Tag = string(LineBuffer,0,Pos);
+
+ // Go down a level
+ if (TermChar == '{')
+ {
+ if (ParentTag.empty() == true)
+ ParentTag = Tag;
+ else
+ ParentTag += string("::") + Tag;
+ Tag = string();
+ }
+
+ // We dont have a value to set
+ if (Pos == LineBuffer.length())
+ {
+ LineBuffer = string();
+ continue;
+ }
+
+ // Parse off the word
+ string Word;
+ if (ParseCWord(LineBuffer.c_str()+Pos,Word) == false)
+ return _error->Error("Syntax error %s:%u: Malformed value",FName.c_str(),CurLine);
+
+ // Generate the item name
+ string Item;
+ if (ParentTag.empty() == true)
+ Item = Tag;
+ else
+ {
+ if (Tag.empty() == true)
+ Item = ParentTag;
+ else
+ Item = ParentTag + "::" + Tag;
+ }
+
+ // Set the item in the configuration class
+ Conf.Set(Item,Word);
+
+ // Empty the buffer
+ LineBuffer = string();
+ }
+ else
+ I++;
+ }
+
+ // Store the fragment
+ const char *Stripd = _strstrip(Buffer);
+ if (*Stripd != 0 && LineBuffer.empty() == false)
+ LineBuffer += " ";
+ LineBuffer += Stripd;
+ }
+
+ return true;
+}
+ /*}}}*/