]> git.saurik.com Git - apt.git/blobdiff - apt-pkg/contrib/configuration.cc
* Fix typos in manpages. Thanks to Daniel Leidert for the fixes
[apt.git] / apt-pkg / contrib / configuration.cc
index 2fa570c2195bf5fd15d7cb6ce9fff76b5d489b47..da57c2054cdfbbd389b8aed86a8a0e89461060cd 100644 (file)
@@ -1,6 +1,6 @@
 // -*- mode: cpp; mode: fold -*-
 // Description                                                         /*{{{*/
-// $Id: configuration.cc,v 1.22 2001/05/14 05:47:30 jgg Exp $
+// $Id: configuration.cc,v 1.28 2004/04/30 04:00:15 mdz Exp $
 /* ######################################################################
 
    Configuration Class
@@ -8,13 +8,13 @@
    This class provides a configuration file and command line parser
    for a tree-oriented configuration environment. All runtime configuration
    is stored in here.
+
+   This source is placed in the Public Domain, do with it what you will
+   It was originally written by Jason Gunthorpe <jgg@debian.org>.
    
    ##################################################################### */
                                                                        /*}}}*/
 // Include files                                                       /*{{{*/
-#ifdef __GNUG__
-#pragma implementation "apt-pkg/configuration.h"
-#endif
 #include <apt-pkg/configuration.h>
 #include <apt-pkg/error.h>
 #include <apt-pkg/strutl.h>
@@ -107,7 +107,7 @@ Configuration::Item *Configuration::Lookup(Item *Head,const char *S,
       return 0;
    
    I = new Item;
-   I->Tag = string(S,Len);
+   I->Tag.assign(S,Len);
    I->Next = *Last;
    I->Parent = Head;
    *Last = I;
@@ -158,7 +158,7 @@ string Configuration::Find(const char *Name,const char *Default) const
    if (Itm == 0 || Itm->Value.empty() == true)
    {
       if (Default == 0)
-        return string();
+        return "";
       else
         return Default;
    }
@@ -173,11 +173,16 @@ string Configuration::Find(const char *Name,const char *Default) const
  */
 string Configuration::FindFile(const char *Name,const char *Default) const
 {
+   const Item *RootItem = Lookup("RootDir");
+   std::string rootDir =  (RootItem == 0) ? "" : RootItem->Value;
+   if(rootDir.size() > 0 && rootDir[rootDir.size() - 1] != '/')
+     rootDir.push_back('/');
+
    const Item *Itm = Lookup(Name);
    if (Itm == 0 || Itm->Value.empty() == true)
    {
       if (Default == 0)
-        return string();
+        return "";
       else
         return Default;
    }
@@ -204,7 +209,7 @@ string Configuration::FindFile(const char *Name,const char *Default) const
       Itm = Itm->Parent;
    }
 
-   return val;
+   return rootDir + val;
 }
                                                                        /*}}}*/
 // Configuration::FindDir - Find a directory name                      /*{{{*/
@@ -279,7 +284,7 @@ string Configuration::FindAny(const char *Name,const char *Default) const
       case 'i': 
       {
         char buf[16];
-        snprintf(buf, sizeof(buf)-1, "%d", FindI(key, atoi(Default)));
+        snprintf(buf, sizeof(buf)-1, "%d", FindI(key, Default ? atoi(Default) : 0 ));
         return buf;
       }
    }
@@ -291,7 +296,7 @@ string Configuration::FindAny(const char *Name,const char *Default) const
 // Configuration::CndSet - Conditinal Set a value                      /*{{{*/
 // ---------------------------------------------------------------------
 /* This will not overwrite */
-void Configuration::CndSet(const char *Name,string Value)
+void Configuration::CndSet(const char *Name,const string &Value)
 {
    Item *Itm = Lookup(Name,true);
    if (Itm == 0)
@@ -303,7 +308,7 @@ void Configuration::CndSet(const char *Name,string Value)
 // Configuration::Set - Set a value                                    /*{{{*/
 // ---------------------------------------------------------------------
 /* */
-void Configuration::Set(const char *Name,string Value)
+void Configuration::Set(const char *Name,const string &Value)
 {
    Item *Itm = Lookup(Name,true);
    if (Itm == 0)
@@ -322,6 +327,47 @@ void Configuration::Set(const char *Name,int Value)
    char S[300];
    snprintf(S,sizeof(S),"%i",Value);
    Itm->Value = S;
+}
+                                                                       /*}}}*/
+// Configuration::Clear - Clear an single value from a list            /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+void Configuration::Clear(const string Name, int Value)
+{
+   char S[300];
+   snprintf(S,sizeof(S),"%i",Value);
+   Clear(Name, S);
+}
+                                                                       /*}}}*/
+// Configuration::Clear - Clear an single value from a list            /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+void Configuration::Clear(const string Name, string Value)
+{
+   Item *Top = Lookup(Name.c_str(),false);
+   if (Top == 0 || Top->Child == 0)
+      return;
+
+   Item *Tmp, *Prev, *I;
+   Prev = I = Top->Child;
+
+   while(I != NULL)
+   {
+      if(I->Value == Value)
+      {
+        Tmp = I;
+        // was first element, point parent to new first element
+        if(Top->Child == Tmp)
+           Top->Child = I->Next;
+        I = I->Next;
+        Prev->Next = I;
+        delete Tmp;
+      } else {
+        Prev = I;
+        I = I->Next;
+      }
+   }
+     
 }
                                                                        /*}}}*/
 // Configuration::Clear - Clear an entire tree                         /*{{{*/
@@ -330,10 +376,10 @@ void Configuration::Set(const char *Name,int Value)
 void Configuration::Clear(string Name)
 {
    Item *Top = Lookup(Name.c_str(),false);
-   if (Top == 0)
+   if (Top == 0) 
       return;
-   
-   Top->Value = string();
+
+   Top->Value.clear();
    Item *Stop = Top;
    Top = Top->Child;
    Stop->Child = 0;
@@ -380,28 +426,33 @@ bool Configuration::ExistsAny(const char *Name) const
 {
    string key = Name;
 
-   if (key.size() > 2 && key.end()[-2] == '/' &&
-       key.find_first_of("fdbi",key.size()-1) < key.size())
+   if (key.size() > 2 && key.end()[-2] == '/')
    {
-      key.resize(key.size() - 2);
-      if (Exists(key.c_str()))
-        return true;
+      if (key.find_first_of("fdbi",key.size()-1) < key.size())
+      {
+         key.resize(key.size() - 2);
+         if (Exists(key.c_str()))
+            return true;
+      }
+      else
+      {
+         _error->Warning(_("Unrecognized type abbreviation: '%c'"), key.end()[-3]);
+      }
    }
-
    return Exists(Name);
 }
                                                                        /*}}}*/
 // Configuration::Dump - Dump the config                               /*{{{*/
 // ---------------------------------------------------------------------
 /* Dump the entire configuration space */
-void Configuration::Dump()
+void Configuration::Dump(ostream& str)
 {
    /* Write out all of the configuration directives by walking the 
       configuration tree */
    const Configuration::Item *Top = Tree(0);
    for (; Top != 0;)
    {
-      clog << Top->FullTag() << " \"" << Top->Value << "\";" << endl;
+      str << Top->FullTag() << " \"" << Top->Value << "\";" << endl;
       
       if (Top->Child != 0)
       {
@@ -437,7 +488,7 @@ string Configuration::Item::FullTag(const Item *Stop) const
    sections like 'zone "foo.org" { .. };' This causes each section to be
    added in with a tag like "zone::foo.org" instead of being split 
    tag/value. AsSectional enables Sectional parsing.*/
-bool ReadConfigFile(Configuration &Conf,string FName,bool AsSectional,
+bool ReadConfigFile(Configuration &Conf,const string &FName,bool AsSectional,
                    unsigned Depth)
 {   
    // Open the stream for reading
@@ -445,7 +496,7 @@ bool ReadConfigFile(Configuration &Conf,string FName,bool AsSectional,
    if (!F != 0)
       return _error->Errno("ifstream::ifstream",_("Opening configuration file %s"),FName.c_str());
    
-   char Buffer[300];
+   char Buffer[1024];
    string LineBuffer;
    string Stack[100];
    unsigned int StackPos = 0;
@@ -459,6 +510,10 @@ bool ReadConfigFile(Configuration &Conf,string FName,bool AsSectional,
    {
       F.getline(Buffer,sizeof(Buffer));
       CurLine++;
+      // This should be made to work instead, but this is better than looping
+      if (F.fail() && !F.eof())
+         return _error->Error(_("Line %d too long (max %lu)"), CurLine, sizeof(Buffer));
+
       _strtabexpand(Buffer,sizeof(Buffer));
       _strstrip(Buffer);
 
@@ -572,7 +627,7 @@ bool ReadConfigFile(Configuration &Conf,string FName,bool AsSectional,
            string Tag;
            const char *Pos = LineBuffer.c_str();
            if (ParseQuoteWord(Pos,Tag) == false)
-              return _error->Error(_("Syntax error %s:%u: Malformed Tag"),FName.c_str(),CurLine);
+              return _error->Error(_("Syntax error %s:%u: Malformed tag"),FName.c_str(),CurLine);
 
            // Parse off the word
            string Word;
@@ -659,13 +714,13 @@ bool ReadConfigFile(Configuration &Conf,string FName,bool AsSectional,
            }
            
            // Empty the buffer
-           LineBuffer = string();
+           LineBuffer.clear();
            
            // Move up a tag, but only if there is no bit to parse
            if (TermChar == '}')
            {
               if (StackPos == 0)
-                 ParentTag = string();
+                 ParentTag.clear();
               else
                  ParentTag = Stack[--StackPos];
            }
@@ -690,8 +745,8 @@ bool ReadConfigFile(Configuration &Conf,string FName,bool AsSectional,
 // ReadConfigDir - Read a directory of config files                    /*{{{*/
 // ---------------------------------------------------------------------
 /* */
-bool ReadConfigDir(Configuration &Conf,string Dir,bool AsSectional,
-                   unsigned Depth)
+bool ReadConfigDir(Configuration &Conf,const string &Dir,bool AsSectional,
+                  unsigned Depth)
 {   
    DIR *D = opendir(Dir.c_str());
    if (D == 0)